v0.7.5: fully implemented Tengu abilities and balanced the boss fight
This commit is contained in:
parent
b9282c42c1
commit
c2accf8ae6
|
@ -29,7 +29,9 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Electricity;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Electricity;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||||
|
@ -56,6 +58,7 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.TenguSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.TenguSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
|
||||||
|
@ -63,13 +66,13 @@ import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
|
||||||
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;
|
||||||
|
import com.watabou.utils.Callback;
|
||||||
import com.watabou.utils.PathFinder;
|
import com.watabou.utils.PathFinder;
|
||||||
import com.watabou.utils.PointF;
|
import com.watabou.utils.PointF;
|
||||||
import com.watabou.utils.Random;
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
//TODO currently has attack/defence stats for testing, need to add those
|
|
||||||
public class NewTengu extends Mob {
|
public class NewTengu extends Mob {
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -77,7 +80,7 @@ public class NewTengu extends Mob {
|
||||||
|
|
||||||
HP = HT = 160;
|
HP = HT = 160;
|
||||||
EXP = 20;
|
EXP = 20;
|
||||||
defenseSkill = 0;
|
defenseSkill = 15;
|
||||||
|
|
||||||
HUNTING = new Hunting();
|
HUNTING = new Hunting();
|
||||||
|
|
||||||
|
@ -95,17 +98,21 @@ public class NewTengu extends Mob {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int damageRoll() {
|
public int damageRoll() {
|
||||||
return Random.NormalIntRange( 0, 0 );
|
return Random.NormalIntRange( 6, 12 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int attackSkill( Char target ) {
|
public int attackSkill( Char target ) {
|
||||||
|
if (target.invisible > 0){
|
||||||
|
return 12;
|
||||||
|
} else {
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int drRoll() {
|
public int drRoll() {
|
||||||
return Random.NormalIntRange(0, 0);
|
return Random.NormalIntRange(0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -238,20 +245,24 @@ public class NewTengu extends Mob {
|
||||||
|
|
||||||
//otherwise, jump in a larger possible area, as the room is bigger
|
//otherwise, jump in a larger possible area, as the room is bigger
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
newPos = Random.Int(level.length());
|
newPos = Random.Int(level.length());
|
||||||
} while (
|
} while (
|
||||||
level.solid[newPos] ||
|
level.solid[newPos] ||
|
||||||
level.distance(newPos, enemy.pos) < 5 ||
|
level.distance(newPos, enemy.pos) < 6 ||
|
||||||
level.distance(newPos, enemy.pos) > 7 ||
|
level.distance(newPos, enemy.pos) > 8 ||
|
||||||
level.distance(newPos, pos) < 6 ||
|
level.distance(newPos, pos) < 6 ||
|
||||||
Actor.findChar(newPos) != null);
|
Actor.findChar(newPos) != null ||
|
||||||
|
Dungeon.level.heaps.get(newPos) != null);
|
||||||
|
|
||||||
if (level.heroFOV[pos]) CellEmitter.get( pos ).burst( Speck.factory( Speck.WOOL ), 6 );
|
if (level.heroFOV[pos]) CellEmitter.get( pos ).burst( Speck.factory( Speck.WOOL ), 6 );
|
||||||
|
|
||||||
sprite.move( pos, newPos );
|
sprite.move( pos, newPos );
|
||||||
move( newPos );
|
move( newPos );
|
||||||
|
|
||||||
|
if (arenaJumps < 4) arenaJumps++;
|
||||||
|
|
||||||
if (level.heroFOV[newPos]) CellEmitter.get( newPos ).burst( Speck.factory( Speck.WOOL ), 6 );
|
if (level.heroFOV[newPos]) CellEmitter.get( newPos ).burst( Speck.factory( Speck.WOOL ), 6 );
|
||||||
Sample.INSTANCE.play( Assets.SND_PUFF );
|
Sample.INSTANCE.play( Assets.SND_PUFF );
|
||||||
|
|
||||||
|
@ -284,7 +295,7 @@ public class NewTengu extends Mob {
|
||||||
BossHealthBar.assignBoss(this);
|
BossHealthBar.assignBoss(this);
|
||||||
if (HP <= HT/2) BossHealthBar.bleed(true);
|
if (HP <= HT/2) BossHealthBar.bleed(true);
|
||||||
if (HP == HT) {
|
if (HP == HT) {
|
||||||
yell(Messages.get(this, "notice_mine", Dungeon.hero.givenName()));
|
yell(Messages.get(this, "notice_gotcha", Dungeon.hero.givenName()));
|
||||||
for (Char ch : Actor.chars()){
|
for (Char ch : Actor.chars()){
|
||||||
if (ch instanceof DriedRose.GhostHero){
|
if (ch instanceof DriedRose.GhostHero){
|
||||||
GLog.n("\n");
|
GLog.n("\n");
|
||||||
|
@ -292,26 +303,65 @@ public class NewTengu extends Mob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yell(Messages.get(this, "notice_face", Dungeon.hero.givenName()));
|
yell(Messages.get(this, "notice_have", Dungeon.hero.givenName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
immunities.add( Blindness.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String LAST_ABILITY = "last_ability";
|
||||||
|
private static final String ABILITIES_USED = "abilities_used";
|
||||||
|
private static final String ARENA_JUMPS = "arena_jumps";
|
||||||
|
private static final String ABILITY_COOLDOWN = "ability_cooldown";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put( LAST_ABILITY, lastAbility );
|
||||||
|
bundle.put( ABILITIES_USED, abilitiesUsed );
|
||||||
|
bundle.put( ARENA_JUMPS, arenaJumps );
|
||||||
|
bundle.put( ABILITY_COOLDOWN, abilityCooldown );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromBundle(Bundle bundle) {
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
super.restoreFromBundle(bundle);
|
super.restoreFromBundle(bundle);
|
||||||
|
lastAbility = bundle.getInt( LAST_ABILITY );
|
||||||
|
abilitiesUsed = bundle.getInt( ABILITIES_USED );
|
||||||
|
arenaJumps = bundle.getInt( ARENA_JUMPS );
|
||||||
|
abilityCooldown = bundle.getInt( ABILITY_COOLDOWN );
|
||||||
|
|
||||||
BossHealthBar.assignBoss(this);
|
BossHealthBar.assignBoss(this);
|
||||||
if (HP <= HT/2) BossHealthBar.bleed(true);
|
if (HP <= HT/2) BossHealthBar.bleed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//don't bother bundling this, as its purely cosmetic
|
||||||
|
private boolean yelledCoward = false;
|
||||||
|
|
||||||
//tengu is always hunting
|
//tengu is always hunting
|
||||||
private class Hunting extends Mob.Hunting{
|
private class Hunting extends Mob.Hunting{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean act(boolean enemyInFOV, boolean justAlerted) {
|
public boolean act(boolean enemyInFOV, boolean justAlerted) {
|
||||||
|
|
||||||
|
if (!enemyInFOV && fieldOfView[enemy.pos]){
|
||||||
|
if (!yelledCoward) {
|
||||||
|
yell(Messages.get(NewTengu.class, "coward"));
|
||||||
|
yelledCoward = true;
|
||||||
|
}
|
||||||
|
enemyInFOV = true;
|
||||||
|
}
|
||||||
|
|
||||||
enemySeen = enemyInFOV;
|
enemySeen = enemyInFOV;
|
||||||
if (enemyInFOV && !isCharmedBy( enemy ) && canAttack( enemy )) {
|
if (enemyInFOV && !isCharmedBy( enemy ) && canAttack( enemy )) {
|
||||||
|
|
||||||
|
if (canUseAbility()){
|
||||||
|
return useAbility();
|
||||||
|
}
|
||||||
|
|
||||||
return doAttack( enemy );
|
return doAttack( enemy );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -336,10 +386,137 @@ public class NewTengu extends Mob {
|
||||||
//***** Tengu abilities. These are expressed in game logic as buffs, blobs, and items *****
|
//***** Tengu abilities. These are expressed in game logic as buffs, blobs, and items *****
|
||||||
//*****************************************************************************************
|
//*****************************************************************************************
|
||||||
|
|
||||||
|
//so that mobs can also use this
|
||||||
|
private static Char throwingChar;
|
||||||
|
|
||||||
|
private int lastAbility = -1;
|
||||||
|
private int abilitiesUsed = 0;
|
||||||
|
private int arenaJumps = 0;
|
||||||
|
|
||||||
|
//starts at 2, so one turn and then first ability
|
||||||
|
private int abilityCooldown = 2;
|
||||||
|
|
||||||
|
private static final int BOMB_ABILITY = 0;
|
||||||
|
private static final int FIRE_ABILITY = 1;
|
||||||
|
private static final int SHOCKER_ABILITY = 2;
|
||||||
|
|
||||||
|
//expects to be called once per turn;
|
||||||
|
public boolean canUseAbility(){
|
||||||
|
|
||||||
|
if (HP > HT/2) return false;
|
||||||
|
|
||||||
|
//1 base ability use, plus 2 uses per jump
|
||||||
|
int targetAbilityUses = 1 + 2*arenaJumps;
|
||||||
|
|
||||||
|
//and ane extra 2 use for jumps 3 and 4
|
||||||
|
targetAbilityUses += Math.max(0, arenaJumps-2);
|
||||||
|
|
||||||
|
if (abilitiesUsed >= targetAbilityUses){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
abilityCooldown--;
|
||||||
|
|
||||||
|
if (targetAbilityUses - abilitiesUsed >= 5){
|
||||||
|
//Very behind in ability uses, use one right away!
|
||||||
|
abilityCooldown = 0;
|
||||||
|
} else if (targetAbilityUses - abilitiesUsed >= 3){
|
||||||
|
//moderately behind in uses, use one every other action.
|
||||||
|
if (abilityCooldown == -1 || abilityCooldown > 1) abilityCooldown = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//standard delay before ability use, 1-4 turns
|
||||||
|
if (abilityCooldown == -1) abilityCooldown = Random.IntRange(1, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abilityCooldown == 0){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean useAbility(){
|
||||||
|
boolean abilityUsed = false;
|
||||||
|
int abilityToUse = -1;
|
||||||
|
|
||||||
|
while (!abilityUsed){
|
||||||
|
|
||||||
|
if (abilitiesUsed == 0){
|
||||||
|
abilityToUse = BOMB_ABILITY;
|
||||||
|
} else if (abilitiesUsed == 1){
|
||||||
|
abilityToUse = SHOCKER_ABILITY;
|
||||||
|
} else {
|
||||||
|
abilityToUse = Random.Int(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we roll the same ability as last time, 9/10 chance to reroll
|
||||||
|
if (abilityToUse != lastAbility || Random.Int(10) == 0){
|
||||||
|
switch (abilityToUse){
|
||||||
|
case BOMB_ABILITY : default:
|
||||||
|
abilityUsed = throwBomb(NewTengu.this, enemy);
|
||||||
|
break;
|
||||||
|
case FIRE_ABILITY:
|
||||||
|
abilityUsed = throwFire(NewTengu.this, enemy);
|
||||||
|
break;
|
||||||
|
case SHOCKER_ABILITY:
|
||||||
|
abilityUsed = throwShocker(NewTengu.this, enemy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lastAbility = abilityToUse;
|
||||||
|
abilitiesUsed++;
|
||||||
|
|
||||||
|
spend(2 * TICK);
|
||||||
|
return lastAbility == FIRE_ABILITY;
|
||||||
|
}
|
||||||
|
|
||||||
//******************
|
//******************
|
||||||
//***Bomb Ability***
|
//***Bomb Ability***
|
||||||
//******************
|
//******************
|
||||||
|
|
||||||
|
//returns true if bomb was thrown
|
||||||
|
public static boolean throwBomb(final Char thrower, final Char target){
|
||||||
|
|
||||||
|
int targetCell = -1;
|
||||||
|
|
||||||
|
//Targets closest cell which is adjacent to target, and at least 3 tiles away
|
||||||
|
for (int i : PathFinder.NEIGHBOURS8){
|
||||||
|
int cell = target.pos + i;
|
||||||
|
if (Dungeon.level.distance(cell, thrower.pos) >= 3){
|
||||||
|
if (targetCell == -1 ||
|
||||||
|
Dungeon.level.trueDistance(cell, thrower.pos) < Dungeon.level.trueDistance(targetCell, thrower.pos)){
|
||||||
|
targetCell = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetCell == -1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int finalTargetCell = targetCell;
|
||||||
|
throwingChar = thrower;
|
||||||
|
final BombAbility.BombItem item = new BombAbility.BombItem();
|
||||||
|
thrower.sprite.zap(finalTargetCell);
|
||||||
|
((MissileSprite) thrower.sprite.parent.recycle(MissileSprite.class)).
|
||||||
|
reset(thrower.sprite,
|
||||||
|
finalTargetCell,
|
||||||
|
item,
|
||||||
|
new Callback() {
|
||||||
|
@Override
|
||||||
|
public void call() {
|
||||||
|
item.onThrow(finalTargetCell);
|
||||||
|
thrower.next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static class BombAbility extends Buff {
|
public static class BombAbility extends Buff {
|
||||||
|
|
||||||
public int bombPos;
|
public int bombPos;
|
||||||
|
@ -419,7 +596,7 @@ public class NewTengu extends Mob {
|
||||||
if (cur[cell] > 0 && off[cell] == 0){
|
if (cur[cell] > 0 && off[cell] == 0){
|
||||||
|
|
||||||
Char ch = Actor.findChar(cell);
|
Char ch = Actor.findChar(cell);
|
||||||
if (ch != null){
|
if (ch != null && !(ch instanceof NewTengu)){
|
||||||
int dmg = Random.NormalIntRange(5 + Dungeon.depth, 10 + Dungeon.depth*2);
|
int dmg = Random.NormalIntRange(5 + Dungeon.depth, 10 + Dungeon.depth*2);
|
||||||
dmg -= ch.drRoll();
|
dmg -= ch.drRoll();
|
||||||
|
|
||||||
|
@ -473,12 +650,16 @@ public class NewTengu extends Mob {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO change for when tengu throws this
|
|
||||||
@Override
|
@Override
|
||||||
protected void onThrow(int cell) {
|
protected void onThrow(int cell) {
|
||||||
super.onThrow(cell);
|
super.onThrow(cell);
|
||||||
|
if (throwingChar != null){
|
||||||
|
Buff.append(throwingChar, BombAbility.class).bombPos = cell;
|
||||||
|
throwingChar = null;
|
||||||
|
} else {
|
||||||
Buff.append(curUser, BombAbility.class).bombPos = cell;
|
Buff.append(curUser, BombAbility.class).bombPos = cell;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemSprite.Glowing glowing() {
|
public ItemSprite.Glowing glowing() {
|
||||||
|
@ -491,6 +672,23 @@ public class NewTengu extends Mob {
|
||||||
//***Fire Ability***
|
//***Fire Ability***
|
||||||
//******************
|
//******************
|
||||||
|
|
||||||
|
public static boolean throwFire(final Char thrower, final Char target){
|
||||||
|
|
||||||
|
Ballistica aim = new Ballistica(thrower.pos, target.pos, Ballistica.WONT_STOP);
|
||||||
|
|
||||||
|
for (int i = 0; i < PathFinder.CIRCLE8.length; i++){
|
||||||
|
if (aim.sourcePos+PathFinder.CIRCLE8[i] == aim.path.get(1)){
|
||||||
|
thrower.sprite.zap(target.pos);
|
||||||
|
Buff.append(thrower, NewTengu.FireAbility.class).direction = i;
|
||||||
|
|
||||||
|
thrower.sprite.emitter().start(Speck.factory(Speck.STEAM), .03f, 10);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static class FireAbility extends Buff {
|
public static class FireAbility extends Buff {
|
||||||
|
|
||||||
public int direction;
|
public int direction;
|
||||||
|
@ -593,7 +791,11 @@ public class NewTengu extends Mob {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur[cell] > 0 && off[cell] == 0){
|
if (cur[cell] > 0 && off[cell] == 0){
|
||||||
Fire.burn( cell );
|
|
||||||
|
Char ch = Actor.findChar( cell );
|
||||||
|
if (ch != null && !ch.isImmune(Fire.class) && !(ch instanceof NewTengu)) {
|
||||||
|
Buff.affect( ch, Burning.class ).reignite( ch );
|
||||||
|
}
|
||||||
|
|
||||||
if (Dungeon.level.flamable[cell]){
|
if (Dungeon.level.flamable[cell]){
|
||||||
Dungeon.level.destroy( cell );
|
Dungeon.level.destroy( cell );
|
||||||
|
@ -637,6 +839,50 @@ public class NewTengu extends Mob {
|
||||||
//***Shocker Ability***
|
//***Shocker Ability***
|
||||||
//*********************
|
//*********************
|
||||||
|
|
||||||
|
//returns true if shocker was thrown
|
||||||
|
public static boolean throwShocker(final Char thrower, final Char target){
|
||||||
|
|
||||||
|
int targetCell = -1;
|
||||||
|
|
||||||
|
//Targets closest cell which is adjacent to target, and not adjacent to thrower or another shocker
|
||||||
|
for (int i : PathFinder.NEIGHBOURS8){
|
||||||
|
int cell = target.pos + i;
|
||||||
|
if (Dungeon.level.distance(cell, thrower.pos) >= 2){
|
||||||
|
boolean validTarget = true;
|
||||||
|
for (ShockerAbility s : thrower.buffs(ShockerAbility.class)){
|
||||||
|
if (Dungeon.level.distance(cell, s.shockerPos) < 2){
|
||||||
|
validTarget = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (validTarget && Dungeon.level.trueDistance(cell, thrower.pos) < Dungeon.level.trueDistance(targetCell, thrower.pos)){
|
||||||
|
targetCell = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetCell == -1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int finalTargetCell = targetCell;
|
||||||
|
throwingChar = thrower;
|
||||||
|
final ShockerAbility.ShockerItem item = new ShockerAbility.ShockerItem();
|
||||||
|
thrower.sprite.zap(finalTargetCell);
|
||||||
|
((MissileSprite) thrower.sprite.parent.recycle(MissileSprite.class)).
|
||||||
|
reset(thrower.sprite,
|
||||||
|
finalTargetCell,
|
||||||
|
item,
|
||||||
|
new Callback() {
|
||||||
|
@Override
|
||||||
|
public void call() {
|
||||||
|
item.onThrow(finalTargetCell);
|
||||||
|
thrower.next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ShockerAbility extends Buff {
|
public static class ShockerAbility extends Buff {
|
||||||
|
|
||||||
public int shockerPos;
|
public int shockerPos;
|
||||||
|
@ -725,7 +971,7 @@ public class NewTengu extends Mob {
|
||||||
if (cur[cell] > 0 && off[cell] == 0){
|
if (cur[cell] > 0 && off[cell] == 0){
|
||||||
|
|
||||||
Char ch = Actor.findChar(cell);
|
Char ch = Actor.findChar(cell);
|
||||||
if (ch != null){
|
if (ch != null && !(ch instanceof NewTengu)){
|
||||||
ch.damage(2 + Dungeon.depth, Electricity.class);
|
ch.damage(2 + Dungeon.depth, Electricity.class);
|
||||||
|
|
||||||
if (ch == Dungeon.hero && !ch.isAlive()) {
|
if (ch == Dungeon.hero && !ch.isAlive()) {
|
||||||
|
@ -766,12 +1012,16 @@ public class NewTengu extends Mob {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO change for when tengu throws this
|
|
||||||
@Override
|
@Override
|
||||||
protected void onThrow(int cell) {
|
protected void onThrow(int cell) {
|
||||||
super.onThrow(cell);
|
super.onThrow(cell);
|
||||||
|
if (throwingChar != null){
|
||||||
|
Buff.append(throwingChar, ShockerAbility.class).shockerPos = cell;
|
||||||
|
throwingChar = null;
|
||||||
|
} else {
|
||||||
Buff.append(curUser, ShockerAbility.class).shockerPos = cell;
|
Buff.append(curUser, ShockerAbility.class).shockerPos = cell;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemSprite.Glowing glowing() {
|
public ItemSprite.Glowing glowing() {
|
||||||
|
|
|
@ -487,8 +487,11 @@ public class NewPrisonBossLevel extends Level {
|
||||||
clearEntities(tenguCell);
|
clearEntities(tenguCell);
|
||||||
|
|
||||||
for (Item item : storedItems) {
|
for (Item item : storedItems) {
|
||||||
|
if (!(item instanceof NewTengu.BombAbility.BombItem)
|
||||||
|
&& !(item instanceof NewTengu.ShockerAbility.ShockerItem)) {
|
||||||
drop(item, randomTenguCellPos());
|
drop(item, randomTenguCellPos());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameScene.flash(0xFFFFFF);
|
GameScene.flash(0xFFFFFF);
|
||||||
Sample.INSTANCE.play(Assets.SND_BLAST);
|
Sample.INSTANCE.play(Assets.SND_BLAST);
|
||||||
|
@ -535,7 +538,7 @@ public class NewPrisonBossLevel extends Level {
|
||||||
FadingTraps f = new FadingTraps();
|
FadingTraps f = new FadingTraps();
|
||||||
f.setCoveringArea(mazeCells[i]);
|
f.setCoveringArea(mazeCells[i]);
|
||||||
GameScene.add(f, false);
|
GameScene.add(f, false);
|
||||||
f.startFade(2.5f);
|
f.startFade( 3f );
|
||||||
|
|
||||||
Sample.INSTANCE.play(Assets.SND_TELEPORT);
|
Sample.INSTANCE.play(Assets.SND_TELEPORT);
|
||||||
int roomCenter = (mazeCells[i].left + mazeCells[i].right)/2 +
|
int roomCenter = (mazeCells[i].left + mazeCells[i].right)/2 +
|
||||||
|
@ -629,7 +632,7 @@ public class NewPrisonBossLevel extends Level {
|
||||||
FadingTraps t = new FadingTraps();
|
FadingTraps t = new FadingTraps();
|
||||||
t.setCoveringArea(tenguCell);
|
t.setCoveringArea(tenguCell);
|
||||||
GameScene.add(t, false);
|
GameScene.add(t, false);
|
||||||
t.startFade( 2.5f );
|
t.startFade( 3f );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class TenguDartTrap extends PoisonDartTrap {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int poisonAmount() {
|
protected int poisonAmount() {
|
||||||
return 9; //21 damage total
|
return 8; //17 damage total
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,8 +30,6 @@ import com.watabou.utils.Callback;
|
||||||
|
|
||||||
public class TenguSprite extends MobSprite {
|
public class TenguSprite extends MobSprite {
|
||||||
|
|
||||||
private Animation cast;
|
|
||||||
|
|
||||||
public TenguSprite() {
|
public TenguSprite() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -48,7 +46,7 @@ public class TenguSprite extends MobSprite {
|
||||||
attack = new Animation( 15, false );
|
attack = new Animation( 15, false );
|
||||||
attack.frames( frames, 6, 7, 7, 0 );
|
attack.frames( frames, 6, 7, 7, 0 );
|
||||||
|
|
||||||
cast = attack.clone();
|
zap = attack.clone();
|
||||||
|
|
||||||
die = new Animation( 8, false );
|
die = new Animation( 8, false );
|
||||||
die.frames( frames, 8, 9, 10, 10, 10, 10, 10, 10 );
|
die.frames( frames, 8, 9, 10, 10, 10, 10, 10, 10 );
|
||||||
|
@ -90,7 +88,7 @@ public class TenguSprite extends MobSprite {
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
play( cast );
|
play( zap );
|
||||||
turnTo( ch.pos , cell );
|
turnTo( ch.pos , cell );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -585,9 +585,10 @@ actors.mobs.swarm.def_verb=evaded
|
||||||
actors.mobs.swarm.desc=The deadly swarm of flies buzzes angrily. Every non-magical attack will split it into two smaller but equally dangerous swarms.
|
actors.mobs.swarm.desc=The deadly swarm of flies buzzes angrily. Every non-magical attack will split it into two smaller but equally dangerous swarms.
|
||||||
|
|
||||||
actors.mobs.newtengu.name=Tengu
|
actors.mobs.newtengu.name=Tengu
|
||||||
actors.mobs.newtengu.notice_mine=You're mine, %s!
|
actors.mobs.newtengu.notice_gotcha=Gotcha, %s!
|
||||||
actors.mobs.newtengu.notice_face=Face me, %s!
|
|
||||||
actors.mobs.newtengu.interesting=Let's make this interesting...
|
actors.mobs.newtengu.interesting=Let's make this interesting...
|
||||||
|
actors.mobs.newtengu.notice_have=I have you now, %s!
|
||||||
|
actors.mobs.newtengu.coward=I can still hear you, Coward!
|
||||||
actors.mobs.newtengu.defeated=Free at last...
|
actors.mobs.newtengu.defeated=Free at last...
|
||||||
actors.mobs.newtengu.rankings_desc=Assassinated by the Tengu
|
actors.mobs.newtengu.rankings_desc=Assassinated by the Tengu
|
||||||
actors.mobs.newtengu.desc=A famous and enigmatic assassin, named for the mask grafted to his face.\n\nTengu is held down with large clasps on his wrists and knees, though he seems to have gotten rid of his chains long ago.\n\nHe will try to use traps, deceptive magic, and precise attacks to eliminate the only thing stopping his escape: you.
|
actors.mobs.newtengu.desc=A famous and enigmatic assassin, named for the mask grafted to his face.\n\nTengu is held down with large clasps on his wrists and knees, though he seems to have gotten rid of his chains long ago.\n\nHe will try to use traps, deceptive magic, and precise attacks to eliminate the only thing stopping his escape: you.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user