v2.3.0: lots more rough implementation work on gnoll geomancer
This commit is contained in:
+130
-11
@@ -49,6 +49,7 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GnollGeomancerSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.GnollGeomancerSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
@@ -88,8 +89,22 @@ public class GnollGeomancer extends Mob {
|
|||||||
private int throwingRockFromPos = -1;
|
private int throwingRockFromPos = -1;
|
||||||
private int throwingRockToPos = -1;
|
private int throwingRockToPos = -1;
|
||||||
|
|
||||||
|
int[] sapperSpawns = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean act() {
|
protected boolean act() {
|
||||||
|
if (sapperSpawns == null){
|
||||||
|
sapperSpawns = new int[3];
|
||||||
|
int i = 0;
|
||||||
|
for (Mob m : Dungeon.level.mobs){
|
||||||
|
if (m instanceof GnollSapper){
|
||||||
|
sapperSpawns[i] = ((GnollSapper) m).spawnPos;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == 3) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (throwingRockFromPos != -1){
|
if (throwingRockFromPos != -1){
|
||||||
GnollGeomancer.doRockThrowAttack(this, throwingRockFromPos, throwingRockToPos);
|
GnollGeomancer.doRockThrowAttack(this, throwingRockFromPos, throwingRockToPos);
|
||||||
|
|
||||||
@@ -170,10 +185,11 @@ public class GnollGeomancer extends Mob {
|
|||||||
do {
|
do {
|
||||||
target = Random.Int(Dungeon.level.length());
|
target = Random.Int(Dungeon.level.length());
|
||||||
} while (!Dungeon.level.insideMap(target) || Dungeon.level.distance(pos, target) != 10);
|
} while (!Dungeon.level.insideMap(target) || Dungeon.level.distance(pos, target) != 10);
|
||||||
carveRock(target);
|
carveRock(getDashPos());
|
||||||
|
|
||||||
state = HUNTING;
|
state = HUNTING;
|
||||||
enemy = Dungeon.hero;
|
enemy = Dungeon.hero;
|
||||||
|
BossHealthBar.assignBoss(GnollGeomancer.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasSleeping) {
|
if (wasSleeping) {
|
||||||
@@ -199,26 +215,108 @@ public class GnollGeomancer extends Mob {
|
|||||||
public void damage(int dmg, Object src) {
|
public void damage(int dmg, Object src) {
|
||||||
int hpBracket = HT / 3;
|
int hpBracket = HT / 3;
|
||||||
|
|
||||||
int beforeHitHP = HP;
|
int curbracket = HP / hpBracket;
|
||||||
|
if (curbracket == 3) curbracket--; //full HP isn't its own bracket
|
||||||
|
|
||||||
|
inFinalBracket = curbracket == 0;
|
||||||
|
|
||||||
super.damage(dmg, src);
|
super.damage(dmg, src);
|
||||||
|
|
||||||
//geomancer cannot be hit through multiple brackets at a time
|
int newBracket = HP / hpBracket;
|
||||||
if ((beforeHitHP/hpBracket - HP/hpBracket) >= 2){
|
if (newBracket == 3) newBracket--; //full HP isn't its own bracket
|
||||||
HP = hpBracket * ((beforeHitHP/hpBracket)-1) + 1;
|
|
||||||
}
|
if (newBracket != curbracket) {
|
||||||
|
//cannot be hit through multiple brackets at a time
|
||||||
|
if (HP <= (curbracket-1)*hpBracket){
|
||||||
|
HP = (curbracket-1)*hpBracket + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BossHealthBar.bleed(newBracket <= 0);
|
||||||
|
|
||||||
//taking damage from full HP does not trigger a jump
|
|
||||||
if (beforeHitHP != HT && beforeHitHP / hpBracket != HP / hpBracket) {
|
|
||||||
//this is a start, but need a lot more fight logic
|
//this is a start, but need a lot more fight logic
|
||||||
int target;
|
int target;
|
||||||
do {
|
do {
|
||||||
target = Random.Int(Dungeon.level.length());
|
target = Random.Int(Dungeon.level.length());
|
||||||
} while (!Dungeon.level.insideMap(target) || Dungeon.level.distance(pos, target) != 10);
|
} while (!Dungeon.level.insideMap(target) || Dungeon.level.distance(pos, target) != 10);
|
||||||
carveRock(target);
|
carveRock(getDashPos());
|
||||||
Buff.affect(this, RockArmor.class).setShield(30);
|
Buff.affect(this, RockArmor.class).setShield(30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean inFinalBracket = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAlive() {
|
||||||
|
//cannot die until final HP bracket, regardless of incoming dmg
|
||||||
|
return super.isAlive() || !inFinalBracket;
|
||||||
|
}
|
||||||
|
|
||||||
|
//we pick location to jump to based on sapper positions:
|
||||||
|
//first aim for closest living sapper, moving 8-12 tiles, preferring to go 10
|
||||||
|
//otherwise aim to closest dead sapper pos
|
||||||
|
//if we arrive at (or are near enough to) a sapper pos, we claim that sapper
|
||||||
|
//
|
||||||
|
private int getDashPos(){
|
||||||
|
|
||||||
|
int closestSapperPos = -1;
|
||||||
|
boolean closestisAlive = false;
|
||||||
|
for (int i = 0; i < sapperSpawns.length; i++){
|
||||||
|
if (sapperSpawns[i] == -1){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestSapperPos == -1) {
|
||||||
|
closestSapperPos = sapperSpawns[i];
|
||||||
|
for (Mob m : Dungeon.level.mobs){
|
||||||
|
if (m instanceof GnollSapper && ((GnollSapper) m).spawnPos == closestSapperPos){
|
||||||
|
closestisAlive = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean sapperAlive = false;
|
||||||
|
for (Mob m : Dungeon.level.mobs){
|
||||||
|
if (m instanceof GnollSapper && ((GnollSapper) m).spawnPos == sapperSpawns[i]){
|
||||||
|
sapperAlive = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Dungeon.level.distance(pos, sapperSpawns[i]) <= 16) {
|
||||||
|
if (sapperAlive && !closestisAlive
|
||||||
|
|| Dungeon.level.distance(pos, sapperSpawns[i]) < Dungeon.level.distance(pos, closestSapperPos)) {
|
||||||
|
closestSapperPos = sapperSpawns[i];
|
||||||
|
closestisAlive = sapperAlive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO get blink position
|
||||||
|
int dashPos = closestSapperPos;
|
||||||
|
|
||||||
|
//if spawn pos is more than 12 tiles away, get as close as possible
|
||||||
|
Ballistica path = new Ballistica(pos, dashPos, Ballistica.STOP_TARGET);
|
||||||
|
|
||||||
|
if (path.dist > 12){
|
||||||
|
dashPos = path.path.get(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO move to adjacent cell if pos is occupied
|
||||||
|
|
||||||
|
for (int i = 0; i < sapperSpawns.length; i++){
|
||||||
|
if (sapperSpawns[i] == closestSapperPos){
|
||||||
|
sapperSpawns[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO if geomancer alive, steal guard and set properties
|
||||||
|
|
||||||
|
return dashPos;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void carveRock(int target){
|
private void carveRock(int target){
|
||||||
Ballistica path = new Ballistica(pos, target, Ballistica.STOP_TARGET);
|
Ballistica path = new Ballistica(pos, target, Ballistica.STOP_TARGET);
|
||||||
|
|
||||||
@@ -234,8 +332,13 @@ public class GnollGeomancer extends Mob {
|
|||||||
Dungeon.level.drop(new DarkGold(), i).sprite.drop();
|
Dungeon.level.drop(new DarkGold(), i).sprite.drop();
|
||||||
}
|
}
|
||||||
if (Dungeon.level.solid[i]){
|
if (Dungeon.level.solid[i]){
|
||||||
//TODO boulders?
|
if (Random.Int(3) == 0){
|
||||||
Dungeon.level.map[i] = Terrain.EMPTY_DECO;
|
Dungeon.level.map[i] = Terrain.MINE_BOULDER;
|
||||||
|
} else {
|
||||||
|
Dungeon.level.map[i] = Terrain.EMPTY_DECO;
|
||||||
|
}
|
||||||
|
} else if (Dungeon.level.map[i] == Terrain.HIGH_GRASS || Dungeon.level.map[i] == Terrain.FURROWED_GRASS){
|
||||||
|
Dungeon.level.map[i] = Terrain.GRASS;
|
||||||
}
|
}
|
||||||
CellEmitter.get( i - Dungeon.level.width() ).start(Speck.factory(Speck.ROCK), 0.07f, 10);
|
CellEmitter.get( i - Dungeon.level.width() ).start(Speck.factory(Speck.ROCK), 0.07f, 10);
|
||||||
}
|
}
|
||||||
@@ -392,6 +495,7 @@ public class GnollGeomancer extends Mob {
|
|||||||
source.sprite.attack(from, new Callback() {
|
source.sprite.attack(from, new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void call() {
|
public void call() {
|
||||||
|
source.sprite.idle();
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -498,6 +602,7 @@ public class GnollGeomancer extends Mob {
|
|||||||
@Override
|
@Override
|
||||||
public void call() {
|
public void call() {
|
||||||
//do nothing
|
//do nothing
|
||||||
|
source.sprite.idle();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -529,6 +634,8 @@ public class GnollGeomancer extends Mob {
|
|||||||
private static final String ROCK_FROM_POS = "rock_from_pos";
|
private static final String ROCK_FROM_POS = "rock_from_pos";
|
||||||
private static final String ROCK_TO_POS = "rock_to_pos";
|
private static final String ROCK_TO_POS = "rock_to_pos";
|
||||||
|
|
||||||
|
private static final String SAPPER_SPAWNS = "sapper_spawns";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeInBundle(Bundle bundle) {
|
public void storeInBundle(Bundle bundle) {
|
||||||
super.storeInBundle(bundle);
|
super.storeInBundle(bundle);
|
||||||
@@ -536,6 +643,10 @@ public class GnollGeomancer extends Mob {
|
|||||||
bundle.put(ABILITY_COOLDOWN, abilityCooldown);
|
bundle.put(ABILITY_COOLDOWN, abilityCooldown);
|
||||||
bundle.put(ROCK_FROM_POS, throwingRockFromPos);
|
bundle.put(ROCK_FROM_POS, throwingRockFromPos);
|
||||||
bundle.put(ROCK_TO_POS, throwingRockToPos);
|
bundle.put(ROCK_TO_POS, throwingRockToPos);
|
||||||
|
|
||||||
|
if (sapperSpawns != null){
|
||||||
|
bundle.put(SAPPER_SPAWNS, sapperSpawns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -545,5 +656,13 @@ public class GnollGeomancer extends Mob {
|
|||||||
abilityCooldown = bundle.getInt(ABILITY_COOLDOWN);
|
abilityCooldown = bundle.getInt(ABILITY_COOLDOWN);
|
||||||
throwingRockFromPos = bundle.getInt(ROCK_FROM_POS);
|
throwingRockFromPos = bundle.getInt(ROCK_FROM_POS);
|
||||||
throwingRockToPos = bundle.getInt(ROCK_TO_POS);
|
throwingRockToPos = bundle.getInt(ROCK_TO_POS);
|
||||||
|
|
||||||
|
if (bundle.contains(SAPPER_SPAWNS)) {
|
||||||
|
sapperSpawns = bundle.getIntArray(SAPPER_SPAWNS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hits >= 3){
|
||||||
|
BossHealthBar.assignBoss(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -59,6 +59,14 @@ public class GnollGeomancerSprite extends MobSprite {
|
|||||||
scale.set(1.25f);
|
scale.set(1.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete( Animation anim ) {
|
||||||
|
if (anim == zap) {
|
||||||
|
idle();
|
||||||
|
}
|
||||||
|
super.onComplete( anim );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void idle() {
|
public void idle() {
|
||||||
super.idle();
|
super.idle();
|
||||||
|
|||||||
+7
@@ -50,5 +50,12 @@ public class GnollSapperSprite extends MobSprite {
|
|||||||
play( idle );
|
play( idle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete( Animation anim ) {
|
||||||
|
if (anim == zap) {
|
||||||
|
idle();
|
||||||
|
}
|
||||||
|
super.onComplete( anim );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user