v2.2.0: fixed a variety of small bugs:

- guardians 'dodging' instead of 'blocking'
- guardians having defenseSkill while recovering
- spire not finishing attacks if hero leaves vision range
- beacon of returning allowing return to mining level
- 'cash out' being repeatedly selectable
This commit is contained in:
Evan Debenham
2023-10-04 14:18:31 -04:00
parent 538914864a
commit 098ab9d772
5 changed files with 86 additions and 73 deletions

View File

@@ -1112,6 +1112,7 @@ actors.mobs.crab.name=sewer crab
actors.mobs.crab.desc=These huge crabs are at the top of the food chain in the sewers. They are extremely fast and their thick carapace can withstand heavy blows.
actors.mobs.crystalguardian.name=crystal guardian
actors.mobs.crystalguardian.def_verb=blocked
actors.mobs.crystalguardian.desc=These large crystalline guardians almost look like statues, if it weren't for their bright glowing eyes. The hardened crystal they're made out of causes them to be sluggish but very tough, so _it's best to leave them to sleep in their crystal nest for as long as possible._\n\nDue to their size, crystal guardians will move much more slowly in enclosed spaces. They're also so durable that they're impossible to kill outright. They can be beaten down and temporarily disabled, but they'll just get back up again after a little while.
actors.mobs.crystalmimic.name=crystal mimic

View File

@@ -89,6 +89,12 @@ public class CrystalGuardian extends Mob{
return 20;
}
@Override
public int defenseSkill(Char enemy) {
if (recovering) return 0;
return super.defenseSkill(enemy);
}
@Override
public int drRoll() {
return super.drRoll() + Random.NormalIntRange(0, 10);

View File

@@ -103,83 +103,83 @@ public class CrystalSpire extends Mob {
enemySeen = enemy.isAlive() && fieldOfView[enemy.pos];
//end of char/mob logic
if (!targetedCells.isEmpty()){
ArrayList<Integer> cellsToAttack = targetedCells.remove(0);
for (int i : cellsToAttack){
Char ch = Actor.findChar(i);
if (ch instanceof CrystalSpire){
continue; //don't spawn crystals on itself
}
Level.set(i, Terrain.MINE_CRYSTAL);
GameScene.updateMap(i);
Splash.at(i, 0xFFFFFF, 5);
}
for (int i : cellsToAttack){
Char ch = Actor.findChar(i);
if (ch != null && !(ch instanceof CrystalWisp || ch instanceof CrystalSpire)){
int dmg = Random.NormalIntRange(6, 15);
//guardians are hit harder by the attack
if (ch instanceof CrystalGuardian) {
dmg += 12; //18-27 damage
Buff.prolong(ch, Cripple.class, 30f);
}
ch.damage(dmg, CrystalSpire.this);
int movePos = i;
//crystal guardians get knocked away from the hero, others get knocked away from the spire
if (ch instanceof CrystalGuardian){
for (int j : PathFinder.NEIGHBOURS8){
if (!Dungeon.level.solid[i+j] && Actor.findChar(i+j) == null &&
Dungeon.level.trueDistance(i+j, Dungeon.hero.pos) > Dungeon.level.trueDistance(movePos, Dungeon.hero.pos)){
movePos = i+j;
}
}
} else if (!Char.hasProp(ch, Property.IMMOVABLE)) {
for (int j : PathFinder.NEIGHBOURS8){
if (!Dungeon.level.solid[i+j] && Actor.findChar(i+j) == null &&
Dungeon.level.trueDistance(i+j, pos) > Dungeon.level.trueDistance(movePos, pos)){
movePos = i+j;
}
}
}
if (ch.isAlive()){
if (movePos != i){
Actor.add(new Pushing(ch, i, movePos));
ch.pos = movePos;
Dungeon.level.occupyCell(ch);
}
} else if (ch == Dungeon.hero){
GLog.n( Messages.capitalize(Messages.get(Char.class, "kill", name())) );
Dungeon.fail(this);
}
}
}
PixelScene.shake( 1, 0.7f );
Sample.INSTANCE.play( Assets.Sounds.SHATTER );
if (!targetedCells.isEmpty()){
for (int i : targetedCells.get(0)){
sprite.parent.add(new TargetedCell(i, 0xFF0000));
}
}
}
if (hits < 3 || !enemySeen){
spend(TICK);
return true;
} else {
if (!targetedCells.isEmpty()){
ArrayList<Integer> cellsToAttack = targetedCells.remove(0);
for (int i : cellsToAttack){
Char ch = Actor.findChar(i);
if (ch instanceof CrystalSpire){
continue; //don't spawn crystals on itself
}
Level.set(i, Terrain.MINE_CRYSTAL);
GameScene.updateMap(i);
Splash.at(i, 0xFFFFFF, 5);
}
for (int i : cellsToAttack){
Char ch = Actor.findChar(i);
if (ch != null && !(ch instanceof CrystalWisp || ch instanceof CrystalSpire)){
int dmg = Random.NormalIntRange(6, 15);
//guardians are hit harder by the attack
if (ch instanceof CrystalGuardian) {
dmg += 12; //18-27 damage
Buff.prolong(ch, Cripple.class, 30f);
}
ch.damage(dmg, CrystalSpire.this);
int movePos = i;
//crystal guardians get knocked away from the hero, others get knocked away from the spire
if (ch instanceof CrystalGuardian){
for (int j : PathFinder.NEIGHBOURS8){
if (!Dungeon.level.solid[i+j] && Actor.findChar(i+j) == null &&
Dungeon.level.trueDistance(i+j, Dungeon.hero.pos) > Dungeon.level.trueDistance(movePos, Dungeon.hero.pos)){
movePos = i+j;
}
}
} else if (!Char.hasProp(ch, Property.IMMOVABLE)) {
for (int j : PathFinder.NEIGHBOURS8){
if (!Dungeon.level.solid[i+j] && Actor.findChar(i+j) == null &&
Dungeon.level.trueDistance(i+j, pos) > Dungeon.level.trueDistance(movePos, pos)){
movePos = i+j;
}
}
}
if (ch.isAlive()){
if (movePos != i){
Actor.add(new Pushing(ch, i, movePos));
ch.pos = movePos;
Dungeon.level.occupyCell(ch);
}
} else if (ch == Dungeon.hero){
GLog.n( Messages.capitalize(Messages.get(Char.class, "kill", name())) );
Dungeon.fail(this);
}
}
}
PixelScene.shake( 1, 0.7f );
Sample.INSTANCE.play( Assets.Sounds.SHATTER );
if (!targetedCells.isEmpty()){
for (int i : targetedCells.get(0)){
sprite.parent.add(new TargetedCell(i, 0xFF0000));
}
}
}
if (abilityCooldown <= 0){
if (Random.Int(2) == 0) {

View File

@@ -155,6 +155,12 @@ public class BeaconOfReturning extends Spell {
return;
}
//cannot return to mining level
if (returnDepth >= 11 && returnDepth <= 14 && returnBranch == 1){
GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") );
return;
}
Level.beforeTransition();
Invisibility.dispel();
InterlevelScene.mode = InterlevelScene.Mode.RETURN;

View File

@@ -144,7 +144,7 @@ public class WndBlacksmith extends Window {
WndBlacksmith.this.hide();
}
};
cashOut.enable(true);
cashOut.enable(Blacksmith.Quest.favor > 0);
buttons.add(cashOut);
float pos = message.bottom() + 3*GAP;