save/load; one bug - cant load after saving in one session form menu

after changing floor
v5stable
ondra 11 years ago
parent e2e073dae7
commit f618ab4ba6
  1. 24
      src/mightypork/gamecore/input/InputSystem.java
  2. 137
      src/mightypork/gamecore/input/KeyStroke.java
  3. 6
      src/mightypork/gamecore/input/Keys.java
  4. 1
      src/mightypork/gamecore/util/ion/Ion.java
  5. 14
      src/mightypork/rogue/App.java
  6. 18
      src/mightypork/rogue/screens/LoaderRequest.java
  7. 42
      src/mightypork/rogue/screens/LoadingOverlay.java
  8. 42
      src/mightypork/rogue/screens/game/ScreenGame.java
  9. 47
      src/mightypork/rogue/screens/select_world/WorldSlot.java
  10. 2
      src/mightypork/rogue/world/Inventory.java
  11. 10
      src/mightypork/rogue/world/World.java
  12. 27
      src/mightypork/rogue/world/WorldConsole.java
  13. 10
      src/mightypork/rogue/world/WorldProvider.java
  14. 11
      src/mightypork/rogue/world/entity/impl/BossRatAi.java
  15. 12
      src/mightypork/rogue/world/entity/impl/BrownRatAi.java
  16. 1
      src/mightypork/rogue/world/entity/impl/EntityBossRat.java
  17. 1
      src/mightypork/rogue/world/entity/impl/EntityBrownRat.java
  18. 1
      src/mightypork/rogue/world/entity/impl/EntityGrayRat.java
  19. 17
      src/mightypork/rogue/world/entity/impl/GrayRatAi.java
  20. 94
      src/mightypork/rogue/world/entity/impl/MonsterAi.java
  21. 15
      src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
  22. 12
      src/mightypork/rogue/world/level/Level.java

@ -215,4 +215,28 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
{ {
return Mouse.isButtonDown(button); return Mouse.isButtonDown(button);
} }
public static int getModifierKeys()
{
int mods = 0;
if(Keyboard.isKeyDown(Keys.L_ALT) || Keyboard.isKeyDown(Keys.R_ALT)) {
mods |= Keys.MOD_ALT;
}
if(Keyboard.isKeyDown(Keys.L_SHIFT) || Keyboard.isKeyDown(Keys.R_SHIFT)) {
mods |= Keys.MOD_SHIFT;
}
if(Keyboard.isKeyDown(Keys.L_CONTROL) || Keyboard.isKeyDown(Keys.R_CONTROL)) {
mods |= Keys.MOD_CONTROL;
}
if(Keyboard.isKeyDown(Keys.L_META) || Keyboard.isKeyDown(Keys.R_META)) {
mods |= Keys.MOD_META;
}
return mods;
}
} }

@ -15,58 +15,42 @@ import org.lwjgl.input.Keyboard;
*/ */
public class KeyStroke { public class KeyStroke {
private final List<Integer> keys = new ArrayList<>(2); private final int mod;
private final int key;
private final boolean fallingEdge; private final boolean fallingEdge;
private final List<Integer> badModifs = new ArrayList<>(8);
// {
// badModifs.add(Keys.L_ALT);
// badModifs.add(Keys.L_CONTROL);
// badModifs.add(Keys.L_SHIFT);
// badModifs.add(Keys.L_META);
// badModifs.add(Keys.R_ALT);
// badModifs.add(Keys.R_CONTROL);
// badModifs.add(Keys.R_SHIFT);
// badModifs.add(Keys.R_META);
// }
/** /**
* KeyStroke * KeyStroke
* *
* @param fallingEdge true for falling edge, up for rising edge * @param fallingEdge true for falling edge, up for rising edge
* @param keys keys that must be pressed * @param mod_mask mods mask
* @param key key code
*/ */
public KeyStroke(boolean fallingEdge, int... keys) public KeyStroke(boolean fallingEdge, int key, int mod_mask) {
{
badModifs.add(Keys.L_ALT);
badModifs.add(Keys.L_CONTROL);
badModifs.add(Keys.L_SHIFT);
badModifs.add(Keys.L_META);
badModifs.add(Keys.R_ALT);
badModifs.add(Keys.R_CONTROL);
badModifs.add(Keys.R_SHIFT);
badModifs.add(Keys.R_META);
this.fallingEdge = fallingEdge; this.fallingEdge = fallingEdge;
for (final int k : keys) { this.key = key;
this.keys.add(k); this.mod = mod_mask;
}
badModifs.remove((Integer) k);
} /**
* Rising edge keystroke
* @param mod_mask mods mask
* @param key key code
*/
public KeyStroke(int key, int mod_mask) {
this(false, key, mod_mask);
} }
/** /**
* Rising edge keystroke * Rising edge keystroke
* *
* @param keys * @param key key code
*/ */
public KeyStroke(int... keys) public KeyStroke(int key) {
{ this(false, key, Keys.MOD_NONE);
this(false, keys);
} }
@ -75,20 +59,41 @@ public class KeyStroke {
*/ */
public boolean isActive() public boolean isActive()
{ {
boolean st = true; boolean st = Keyboard.isKeyDown(key);
st &= (InputSystem.getModifierKeys() == mod);
return fallingEdge ? st : !st;
}
@Override
public String toString()
{
String s = "(";
for (final int k : keys) { if ((mod & Keys.MOD_CONTROL) != 0) {
st &= Keyboard.isKeyDown(k); s += "CTRL+";
} }
for (final int i : badModifs) { if ((mod & Keys.MOD_ALT) != 0) {
if (Keyboard.isKeyDown(i)) { s += "ALT+";
st = false;
break;
}
} }
return fallingEdge ? st : !st; if ((mod & Keys.MOD_SHIFT) != 0) {
s += "SHIFT+";
}
if ((mod & Keys.MOD_META) != 0) {
s += "META+";
}
s += Keyboard.getKeyName(key);
s += fallingEdge ? ",DOWN" : ",UP";
s += ")";
return s;
} }
@ -97,7 +102,9 @@ public class KeyStroke {
{ {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((keys == null) ? 0 : keys.hashCode()); result = prime * result + (fallingEdge ? 1231 : 1237);
result = prime * result + key;
result = prime * result + mod;
return result; return result;
} }
@ -107,43 +114,11 @@ public class KeyStroke {
{ {
if (this == obj) return true; if (this == obj) return true;
if (obj == null) return false; if (obj == null) return false;
if (!(obj instanceof KeyStroke)) return false; if (getClass() != obj.getClass()) return false;
final KeyStroke other = (KeyStroke) obj; KeyStroke other = (KeyStroke) obj;
if (keys == null) {
if (other.keys != null) return false;
} else if (!keys.equals(other.keys)) {
return false;
}
if (fallingEdge != other.fallingEdge) return false; if (fallingEdge != other.fallingEdge) return false;
if (key != other.key) return false;
if (mod != other.mod) return false;
return true; return true;
} }
@Override
public String toString()
{
String s = "(";
int cnt = 0;
final Iterator<Integer> i = keys.iterator();
for (; i.hasNext(); cnt++) {
if (cnt > 0) s += "+";
s += Keyboard.getKeyName(i.next());
}
s += fallingEdge ? ",DOWN" : ",UP";
s += ")";
return s;
}
public List<Integer> getKeys()
{
return keys;
}
} }

@ -133,5 +133,11 @@ public interface Keys {
public static final int INSERT = 0xD2; /* Insert on arrow keypad */ public static final int INSERT = 0xD2; /* Insert on arrow keypad */
public static final int DELETE = 0xD3; /* Delete on arrow keypad */ public static final int DELETE = 0xD3; /* Delete on arrow keypad */
public static final byte MOD_NONE = 0;
public static final byte MOD_ALT = 1;
public static final byte MOD_CONTROL = 2;
public static final byte MOD_SHIFT = 4;
public static final byte MOD_META = 8;
//@formatter:on //@formatter:on
} }

@ -182,6 +182,7 @@ public class Ion {
*/ */
public static void toFile(File file, IonObjBinary obj) throws IOException public static void toFile(File file, IonObjBinary obj) throws IOException
{ {
file.getParentFile().mkdirs();
try(OutputStream out = new FileOutputStream(file)) { try(OutputStream out = new FileOutputStream(file)) {
toStream(out, obj); toStream(out, obj);

@ -26,6 +26,7 @@ import mightypork.rogue.screens.LoadingOverlay;
import mightypork.rogue.screens.game.ScreenGame; import mightypork.rogue.screens.game.ScreenGame;
import mightypork.rogue.screens.menu.ScreenMainMenu; import mightypork.rogue.screens.menu.ScreenMainMenu;
import mightypork.rogue.screens.select_world.ScreenSelectWorld; import mightypork.rogue.screens.select_world.ScreenSelectWorld;
import mightypork.rogue.world.Inventory;
import mightypork.rogue.world.WorldProvider; import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.Level;
@ -78,6 +79,7 @@ public final class App extends BaseApp {
super.registerIonizables(); super.registerIonizables();
Ion.registerType(Level.ION_MARK, Level.class); Ion.registerType(Level.ION_MARK, Level.class);
Ion.registerType(Inventory.ION_MARK, Inventory.class);
} }
@ -132,14 +134,18 @@ public final class App extends BaseApp {
bindEventToKey(new ActionRequest(RequestType.FULLSCREEN), Keys.F11); bindEventToKey(new ActionRequest(RequestType.FULLSCREEN), Keys.F11);
bindEventToKey(new ActionRequest(RequestType.SCREENSHOT), Keys.F2); bindEventToKey(new ActionRequest(RequestType.SCREENSHOT), Keys.F2);
bindEventToKey(new GameStateRequest(GameState.EXIT), Keys.L_CONTROL, Keys.Q); bindEventToKey(new GameStateRequest(GameState.EXIT), Keys.Q, Keys.MOD_CONTROL);
bindEventToKey(new GameStateRequest(GameState.MAIN_MENU), Keys.L_CONTROL, Keys.M); bindEventToKey(new GameStateRequest(GameState.MAIN_MENU), Keys.M, Keys.MOD_CONTROL);
} }
private void bindEventToKey(final BusEvent<?> event, int key)
{
bindEventToKey(event, key, Keys.MOD_NONE);
}
private void bindEventToKey(final BusEvent<?> event, int... keys) private void bindEventToKey(final BusEvent<?> event, int key, byte mod)
{ {
getInput().bindKey(new KeyStroke(keys), new Runnable() { getInput().bindKey(new KeyStroke(key, mod), new Runnable() {
@Override @Override
public void run() public void run()

@ -5,28 +5,18 @@ import mightypork.gamecore.eventbus.BusEvent;
public class LoaderRequest extends BusEvent<LoadingOverlay> { public class LoaderRequest extends BusEvent<LoadingOverlay> {
private final boolean show;
private final String msg; private final String msg;
private Runnable task;
public LoaderRequest(boolean show, String msg) { public LoaderRequest(String msg, Runnable task) {
this.show = show; this.task = task;
this.msg = msg; this.msg = msg;
} }
public LoaderRequest(boolean show) {
this.show = show;
this.msg = null;
}
@Override @Override
protected void handleBy(LoadingOverlay handler) protected void handleBy(LoadingOverlay handler)
{ {
if(show) { handler.show(msg, task);
handler.show(msg);
}else {
handler.hide();
}
} }
} }

@ -7,6 +7,7 @@ import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter; import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.events.ScreenRequest; import mightypork.gamecore.gui.events.ScreenRequest;
import mightypork.gamecore.gui.screens.Overlay; import mightypork.gamecore.gui.screens.Overlay;
import mightypork.gamecore.util.Utils;
import mightypork.gamecore.util.math.Easing; import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.color.Color; import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.color.pal.PAL16; import mightypork.gamecore.util.math.color.pal.PAL16;
@ -36,7 +37,29 @@ public class LoadingOverlay extends Overlay {
return msg == null ? "" : msg; return msg == null ? "" : msg;
} }
}; };
private boolean busy;
private String msg; private String msg;
private Runnable task;
private TimedTask tt = new TimedTask() {
@Override
public void run()
{
Utils.runAsThread(new Runnable() {
@Override
public void run()
{
task.run();
alpha.setEasing(Easing.SINE_OUT);
alpha.fadeOut(T_OUT);
busy = false;
}
});
}
};
public LoadingOverlay(AppAccess app) { public LoadingOverlay(AppAccess app) {
@ -47,6 +70,7 @@ public class LoadingOverlay extends Overlay {
root.add(qp); root.add(qp);
updated.add(alpha); updated.add(alpha);
updated.add(tt);
Rect textRect = root.shrink(Num.ZERO, root.height().perc(48)); Rect textRect = root.shrink(Num.ZERO, root.height().perc(48));
textRect = textRect.moveY(root.height().perc(-10)); textRect = textRect.moveY(root.height().perc(-10));
@ -54,7 +78,7 @@ public class LoadingOverlay extends Overlay {
final TextPainter tp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.WHITE, msgStrProv); final TextPainter tp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.WHITE, msgStrProv);
tp.setRect(textRect); tp.setRect(textRect);
tp.setShadow(RGB.BLACK_60, tp.height().mul(1/8D).toVectXY()); tp.setShadow(RGB.BLACK_60, tp.height().mul(1 / 8D).toVectXY());
root.add(tp); root.add(tp);
} }
@ -66,21 +90,21 @@ public class LoadingOverlay extends Overlay {
} }
public void show(String message) public void show(String message, Runnable task)
{ {
if(busy) throw new IllegalStateException("Loader is busy with another task.");
this.msg = message; this.msg = message;
this.task = task;
this.busy = true;
alpha.setEasing(Easing.SINE_IN); alpha.setEasing(Easing.SINE_IN);
alpha.fadeIn(T_IN); alpha.fadeIn(T_IN);
}
public void hide() tt.start(T_IN);
{
alpha.setEasing(Easing.SINE_OUT);
alpha.fadeOut(T_OUT);
} }
@Override @Override
public void render() public void render()
{ {

@ -1,6 +1,8 @@
package mightypork.rogue.screens.game; package mightypork.rogue.screens.game;
import java.io.File;
import java.io.IOException;
import java.util.Random; import java.util.Random;
import mightypork.gamecore.app.AppAccess; import mightypork.gamecore.app.AppAccess;
@ -9,6 +11,7 @@ import mightypork.gamecore.gui.ActionGroup;
import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.Keys;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.math.Calc; import mightypork.gamecore.util.math.Calc;
import mightypork.rogue.Config; import mightypork.rogue.Config;
import mightypork.rogue.world.PlayerFacade; import mightypork.rogue.world.PlayerFacade;
@ -85,6 +88,37 @@ public class ScreenGame extends LayeredScreen {
} }
}; };
public Action actionSave = new Action() {
@Override
public void execute()
{
try {
WorldProvider.get().saveWorld();
WorldProvider.get().getWorld().getConsole().msgWorldSaved();
} catch (Exception e) {
Log.e("Could not save the world.", e);
WorldProvider.get().getWorld().getConsole().msgWorldSaveError();
}
}
};
public Action actionRestore = new Action() {
@Override
public void execute()
{
try {
File f = WorldProvider.get().getWorld().getSaveFile();
WorldProvider.get().loadWorld(f);
WorldProvider.get().getWorld().getConsole().msgReloaded();
} catch (Exception e) {
Log.e("Could not load the world.", e);
WorldProvider.get().getWorld().getConsole().msgLoadFailed();
}
}
};
/** /**
* Set gui state (overlay) * Set gui state (overlay)
@ -142,7 +176,7 @@ public class ScreenGame extends LayeredScreen {
worldLayer.setVisible(true); worldLayer.setVisible(true);
// TODO temporary here ↓ // TODO temporary here ↓
bindKey(new KeyStroke(Keys.L_CONTROL, Keys.N), new Runnable() { bindKey(new KeyStroke(Keys.N, Keys.MOD_CONTROL), new Runnable() {
@Override @Override
public void run() public void run()
@ -161,6 +195,9 @@ public class ScreenGame extends LayeredScreen {
bindKey(new KeyStroke(Keys.M), actionToggleMinimap); bindKey(new KeyStroke(Keys.M), actionToggleMinimap);
bindKey(new KeyStroke(Keys.Z), actionToggleZoom); bindKey(new KeyStroke(Keys.Z), actionToggleZoom);
bindKey(new KeyStroke(Keys.R, Keys.MOD_CONTROL), actionRestore);
bindKey(new KeyStroke(Keys.S, Keys.MOD_CONTROL), actionSave);
// add as actions - enableables. // add as actions - enableables.
worldActions.add(worldLayer); worldActions.add(worldLayer);
worldActions.add(hudLayer); worldActions.add(hudLayer);
@ -170,6 +207,9 @@ public class ScreenGame extends LayeredScreen {
worldActions.add(actionTogglePause); worldActions.add(actionTogglePause);
worldActions.add(actionToggleZoom); worldActions.add(actionToggleZoom);
worldActions.add(actionSave);
worldActions.add(actionRestore);
worldActions.enable(true); worldActions.enable(true);
// TMP TODO remove // TMP TODO remove

@ -14,6 +14,7 @@ import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter; import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.events.CrossfadeRequest; import mightypork.gamecore.gui.events.CrossfadeRequest;
import mightypork.gamecore.gui.events.ScreenRequest; import mightypork.gamecore.gui.events.ScreenRequest;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.resources.fonts.GLFont; import mightypork.gamecore.resources.fonts.GLFont;
import mightypork.gamecore.util.Utils; import mightypork.gamecore.util.Utils;
import mightypork.gamecore.util.ion.Ion; import mightypork.gamecore.util.ion.Ion;
@ -91,28 +92,44 @@ public class WorldSlot extends ConstraintLayout {
msg = "Creating world..."; msg = "Creating world...";
} }
getEventBus().send(new LoaderRequest(true, msg)); getEventBus().send(new LoaderRequest(msg, new Runnable() {
Utils.runAsThread(new Runnable() {
@Override @Override
public void run() public void run()
{ {
try { World w;
final World w = new World();
w.setSaveFile(file); if (worldBundle == null) {
w.load(worldBundle);
WorldProvider.get().setWorld(w); try {
} catch (final Exception e) { w = WorldProvider.get().createWorld(Double.doubleToLongBits(Math.random()));
WorldProvider.get().createWorld(Double.doubleToLongBits(Math.random())); w.setSaveFile(file);
}
WorldProvider.get().saveWorld();
getEventBus().send(new ScreenRequest("game"));
getEventBus().send(new LoaderRequest(false)); } catch (Exception e) {
//getEventBus().send(new GameStateRequest(GameState.PLAY_WORLD)); Log.e("Could not create & save the world.", e);
}
} else {
try {
w = new World();
w.setSaveFile(file);
w.load(worldBundle);
WorldProvider.get().setWorld(w);
getEventBus().send(new ScreenRequest("game"));
} catch (IOException e) {
Log.e("Could not load the world.", e);
}
}
getEventBus().send(new ScreenRequest("game"));
} }
}); }));
} }
}); });

@ -12,7 +12,7 @@ import mightypork.rogue.world.item.Items;
public class Inventory implements IonObjBinary { public class Inventory implements IonObjBinary {
private static final short ION_MARK = 0; public static final short ION_MARK = 54;
private Item[] items; private Item[] items;

@ -11,6 +11,7 @@ import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus; import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.clients.DelegatingClient; import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled; import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.algo.Coord; import mightypork.gamecore.util.math.algo.Coord;
@ -79,9 +80,12 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
in.loadBundled("player", playerData); in.loadBundled("player", playerData);
playerEntity = levels.get(playerData.getLevelNumber()).getEntity(playerData.getEID()); int eid = playerData.getEID();
int lvl = playerData.getLevelNumber();
playerEntity = levels.get(lvl).getEntity(eid);
if (playerEntity == null) { if (playerEntity == null) {
throw new RuntimeException("Player entity not found in the world."); throw new RuntimeException("Player entity not found in the world: " + eid + " on floor " + lvl);
} }
} }
@ -212,6 +216,8 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
// update console timing - not as child client // update console timing - not as child client
console.update(delta); console.update(delta);
if (saveFile == null) Log.w("World has no save file.");
} }

@ -34,8 +34,7 @@ public class WorldConsole implements Updateable {
private double elapsed = 0; private double elapsed = 0;
private Entry(String text) private Entry(String text) {
{
this.text = text; this.text = text;
this.fadeout = new NumAnimated(1, Easing.LINEAR); this.fadeout = new NumAnimated(1, Easing.LINEAR);
this.fadeout.setDefaultDuration(0.5); this.fadeout.setDefaultDuration(0.5);
@ -196,4 +195,28 @@ public class WorldConsole implements Updateable {
{ {
addMessage("Your " + item.getVisualName() + " has broken!"); addMessage("Your " + item.getVisualName() + " has broken!");
} }
public void msgWorldSaved()
{
addMessage("Game saved to file.");
}
public void msgWorldSaveError()
{
addMessage("Error while saving; See the log for details.");
}
public void msgReloaded()
{
addMessage("World loaded from file.");
}
public void msgLoadFailed()
{
addMessage("Error while loading; See the log for details.");
}
} }

@ -21,8 +21,7 @@ public class WorldProvider extends RootBusNode {
} }
public WorldProvider(BusAccess busAccess) public WorldProvider(BusAccess busAccess) {
{
super(busAccess); super(busAccess);
setListening(false); setListening(false);
} }
@ -50,9 +49,11 @@ public class WorldProvider extends RootBusNode {
}; };
public void createWorld(long seed) public World createWorld(long seed)
{ {
setWorld(WorldCreator.createWorld(seed)); World w = WorldCreator.createWorld(seed);
setWorld(w);
return w;
} }
@ -83,6 +84,7 @@ public class WorldProvider extends RootBusNode {
public void loadWorld(File file) throws IOException public void loadWorld(File file) throws IOException
{ {
setWorld(Ion.fromFile(file, World.class)); setWorld(Ion.fromFile(file, World.class));
world.setSaveFile(file);
} }

@ -29,14 +29,14 @@ public class BossRatAi extends GrayRatAi {
@Override @Override
protected int getAttackStrength() protected int getAttackStrength()
{ {
return Calc.randInt(5, 11); return Calc.randInt(3, 11);
} }
@Override @Override
protected int getPreyAbandonDistance() protected int getPreyAbandonDistance()
{ {
return Calc.randInt(15, 18); return Calc.randInt(12, 18);
} }
@ -44,6 +44,13 @@ public class BossRatAi extends GrayRatAi {
public void update(double delta) public void update(double delta)
{ {
super.update(delta); super.update(delta);
healTimer.update(delta); healTimer.update(delta);
} }
@Override
protected double getStepTime()
{
return isIdle() ? 0.6 : 0.4;
}
} }

@ -19,20 +19,26 @@ public class BrownRatAi extends GrayRatAi {
@Override @Override
protected double getScanRadius() protected double getScanRadius()
{ {
return isSleeping() ? Calc.randInt(3, 5) : Calc.randInt(5, 8); return isIdle() ? Calc.randInt(2, 4) : Calc.randInt(5, 8);
} }
@Override @Override
protected int getAttackStrength() protected int getAttackStrength()
{ {
return Calc.randInt(2, 5); return Calc.randInt(1, 4);
} }
@Override @Override
protected int getPreyAbandonDistance() protected int getPreyAbandonDistance()
{ {
return Calc.randInt(11, 14); return Calc.randInt(7, 12);
}
@Override
protected double getStepTime()
{
return isIdle() ? 0.5 : 0.38;
} }
} }

@ -27,7 +27,6 @@ public class EntityBossRat extends Entity {
addModule("ai", ai); addModule("ai", ai);
pos.addMoveListener(ai); pos.addMoveListener(ai);
pos.setStepTime(0.4);
setDespawnDelay(1); setDespawnDelay(1);
health.setHealthMax(80); health.setHealthMax(80);

@ -28,7 +28,6 @@ public class EntityBrownRat extends Entity {
addModule("ai", ai); addModule("ai", ai);
pos.addMoveListener(ai); pos.addMoveListener(ai);
pos.setStepTime(0.38); // faster than gray rat
setDespawnDelay(1); setDespawnDelay(1);
health.setHealthMax(20); health.setHealthMax(20);

@ -28,7 +28,6 @@ public class EntityGrayRat extends Entity {
addModule("ai", ai); addModule("ai", ai);
pos.addMoveListener(ai); pos.addMoveListener(ai);
pos.setStepTime(0.5);
setDespawnDelay(1); setDespawnDelay(1);
health.setHealthMax(6); health.setHealthMax(6);

@ -19,7 +19,7 @@ public class GrayRatAi extends MonsterAi {
@Override @Override
protected double getScanRadius() protected double getScanRadius()
{ {
return isSleeping() ? Calc.randInt(2, 4) : Calc.randInt(4, 6); return isIdle() ? Calc.randInt(2, 3) : Calc.randInt(4, 6);
} }
@ -33,27 +33,20 @@ public class GrayRatAi extends MonsterAi {
@Override @Override
protected int getAttackStrength() protected int getAttackStrength()
{ {
return 1 + (Calc.rand.nextInt(5) == 0 ? 1 : 0); return Calc.randInt(1, 2);
} }
@Override @Override
protected int getPreyAbandonDistance() protected int getPreyAbandonDistance()
{ {
return Calc.randInt(8, 11); return Calc.randInt(7, 11);
} }
@Override @Override
protected boolean shouldSkipScan() protected double getStepTime()
{ {
return false; return isIdle() ? 0.7 : 0.5;
}
@Override
protected boolean shouldRandomlyAbandonPrey()
{
return false;
} }
} }

@ -22,7 +22,6 @@ import mightypork.rogue.world.tile.Tile;
public class MonsterAi extends EntityModule implements EntityMoveListener { public class MonsterAi extends EntityModule implements EntityMoveListener {
private boolean sleeping = true;
private boolean chasing = false; private boolean chasing = false;
private final AiTimer timerFindPrey = new AiTimer(3) { private final AiTimer timerFindPrey = new AiTimer(3) {
@ -30,17 +29,17 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
@Override @Override
public void run() public void run()
{ {
if (chasing) return; if (!isIdle()) return;
lookForTarget(); lookForTarget();
} }
}; };
private final AiTimer timerAttack = new AiTimer(3) { private final AiTimer timerAttack = new AiTimer(1) {
@Override @Override
public void run() public void run()
{ {
if (!chasing) return; if (!isChasing()) return;
final Entity prey = getPreyEntity(); final Entity prey = getPreyEntity();
@ -50,6 +49,21 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
} }
}; };
private final AiTimer timerRandomWalk = new AiTimer(0.2) {
@Override
public void run()
{
if (!isIdle()) return;
if(entity.pos.isMoving()) return;
if(Calc.rand.nextInt(10) == 0) {
entity.pos.addStep(Sides.randomCardinal());
}
}
};
private PathFinder noDoorPf; private PathFinder noDoorPf;
/** Prey id */ /** Prey id */
@ -84,18 +98,13 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
{ {
if (entity.isDead()) return; if (entity.isDead()) return;
if (chasing) { if (isChasing()) {
final Entity prey = getPreyEntity(); final Entity prey = getPreyEntity();
if (!isPreyValid(prey)) { if (!isPreyValid(prey)) {
stopChasing(); stopChasing();
return; return;
} }
if (shouldRandomlyAbandonPrey()) {
stopChasing();
return;
}
if (!isPreyInAttackRange(prey)) { if (!isPreyInAttackRange(prey)) {
stepTowardsPrey(prey); stepTowardsPrey(prey);
} }
@ -122,7 +131,6 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
bundle.putBundled("tattack", timerAttack); bundle.putBundled("tattack", timerAttack);
bundle.put("chasing", chasing); bundle.put("chasing", chasing);
bundle.put("sleeping", sleeping);
bundle.put("prey", preyId); bundle.put("prey", preyId);
} }
@ -135,7 +143,6 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
bundle.loadBundled("tattack", timerAttack); bundle.loadBundled("tattack", timerAttack);
chasing = bundle.get("chasing", chasing); chasing = bundle.get("chasing", chasing);
sleeping = bundle.get("sleeping", sleeping);
preyId = bundle.get("prey", preyId); preyId = bundle.get("prey", preyId);
} }
@ -155,47 +162,40 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
timerFindPrey.update(delta); timerFindPrey.update(delta);
timerAttack.update(delta); timerAttack.update(delta);
timerRandomWalk.update(delta);
if (chasing && !entity.pos.isMoving()) { // go after the prey
if (isChasing() && !entity.pos.isMoving()) {
final Entity prey = getPreyEntity(); final Entity prey = getPreyEntity();
if (prey == null) { if (prey == null) {
// prey killed and cleaned from level // prey killed and cleaned from level
stopChasing(); stopChasing();
return;
} }
if (!isPreyInAttackRange(prey)) { if (!isPreyInAttackRange(prey)) {
stepTowardsPrey(prey); stepTowardsPrey(prey);
return;
} }
} }
if (sleeping && shouldRandomlyWake()) { }
sleeping = false;
}
if (!chasing && shouldRandomlyFallAsleep()) {
sleeping = true;
}
if (!chasing && !sleeping && !entity.pos.isMoving() && Calc.rand.nextInt(10) == 0) { public boolean isIdle()
entity.pos.addStep(Sides.randomCardinal()); {
} return !chasing;
} }
public boolean isSleeping()
public boolean isChasing()
{ {
return sleeping; return chasing;
} }
private void lookForTarget() private void lookForTarget()
{ {
if (entity.isDead()) return; if (entity.isDead()) return;
if (shouldSkipScan()) return; // not hungry right now
final Entity prey = entity.getLevel().getClosestEntity(entity.pos.getVisualPos(), EntityType.PLAYER, getScanRadius()); final Entity prey = entity.getLevel().getClosestEntity(entity.pos.getVisualPos(), EntityType.PLAYER, getScanRadius());
if (prey != null) { if (prey != null) {
@ -233,7 +233,8 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
preyId = prey.getEntityId(); preyId = prey.getEntityId();
chasing = true; chasing = true;
sleeping = false;
entity.pos.setStepTime(getStepTime());
// follow this one prey // follow this one prey
timerFindPrey.pause(); timerFindPrey.pause();
@ -245,6 +246,9 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
private void stopChasing() private void stopChasing()
{ {
chasing = false; chasing = false;
entity.pos.setStepTime(getStepTime());
preyId = -1; preyId = -1;
timerFindPrey.restart(); timerFindPrey.restart();
} }
@ -266,7 +270,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
// if close enough // if close enough
if (isPreyInAttackRange(prey)) { if (isPreyInAttackRange(prey)) {
attackPrey(prey); // attack using the timed loop
return; return;
} }
@ -307,7 +311,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
@DefaultImpl @DefaultImpl
protected double getScanRadius() protected double getScanRadius()
{ {
return sleeping ? Calc.randInt(1, 3) : Calc.randInt(4, 8); // For override return isIdle() ? Calc.randInt(1, 3) : Calc.randInt(4, 8); // For override
} }
@ -331,31 +335,9 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
return 1; // For override return 1; // For override
} }
@DefaultImpl
protected boolean shouldSkipScan()
{
return false;
}
@DefaultImpl
protected boolean shouldRandomlyAbandonPrey()
{
return false;
}
@DefaultImpl
protected boolean shouldRandomlyWake()
{
return Calc.rand.nextInt(10) == 0;
}
@DefaultImpl @DefaultImpl
protected boolean shouldRandomlyFallAsleep() protected double getStepTime()
{ {
return Calc.rand.nextInt(8) == 0; return isIdle() ? 0.7 : 0.4;
} }
} }

@ -17,7 +17,6 @@ import mightypork.rogue.world.gui.MapView;
public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndListener, KeyListener, Updateable { public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndListener, KeyListener, Updateable {
private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN }; private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN };
private static final int[] keys2 = { Keys.A, Keys.D, Keys.W, Keys.S };
private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S }; private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S };
@ -44,12 +43,16 @@ public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndLi
@Override @Override
public void receive(KeyEvent evt) public void receive(KeyEvent evt)
{ {
if (isImmobile()) return; if (isImmobile()) {
return;
}
if (evt.isDown() || mapView.plc.getPlayer().isMoving()) return; // not interested if (evt.isDown() || mapView.plc.getPlayer().isMoving()) return; // not interested
if(InputSystem.getModifierKeys() != Keys.MOD_NONE) return;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (evt.getKey() == keys[i] || evt.getKey() == keys2[i]) { if (evt.getKey() == keys[i]) {
mapView.plc.clickTile(sides[i]); mapView.plc.clickTile(sides[i]);
} }
} }
@ -62,8 +65,12 @@ public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndLi
if (mapView.plc.getPlayer().getMoveProgress() < 0.8) return false; if (mapView.plc.getPlayer().getMoveProgress() < 0.8) return false;
if(InputSystem.getModifierKeys() != Keys.MOD_NONE) return false;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (InputSystem.isKeyDown(keys[i]) || InputSystem.isKeyDown(keys2[i])) { if (InputSystem.isKeyDown(keys[i])) {
final Step side = sides[i]; final Step side = sides[i];
if (mapView.plc.canGo(side)) { if (mapView.plc.canGo(side)) {

@ -24,6 +24,7 @@ import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.World; import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.Entities; import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityPathFinder;
import mightypork.rogue.world.entity.EntityType; import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.entity.impl.PlayerEntity; import mightypork.rogue.world.entity.impl.PlayerEntity;
import mightypork.rogue.world.item.Item; import mightypork.rogue.world.item.Item;
@ -123,13 +124,11 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl
private double timeSinceLastEntitySort; private double timeSinceLastEntitySort;
public Level() public Level() {
{
} }
public Level(int width, int height) public Level(int width, int height) {
{
size.setTo(width, height); size.setTo(width, height);
buildArray(); buildArray();
} }
@ -257,6 +256,9 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl
ent.setLevel(this); ent.setLevel(this);
occupyTile(ent.getCoord()); occupyTile(ent.getCoord());
entityMap.put(ent.getEntityId(), ent); entityMap.put(ent.getEntityId(), ent);
if (ent instanceof PlayerEntity) {
playerCount++;
}
} }
} }
@ -366,7 +368,7 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl
// further // further
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
final Coord c = pos.add(Calc.randInt(-2, 2),Calc.randInt(-2, 2)); final Coord c = pos.add(Calc.randInt(-2, 2), Calc.randInt(-2, 2));
if (addEntity(entity, c)) return true; if (addEntity(entity, c)) return true;
} }

Loading…
Cancel
Save