v0.9.3: implemented the redesigned smoke bomb ability

This commit is contained in:
Evan Debenham 2021-04-30 23:15:42 -04:00
parent 3cfe725609
commit 161851aa64
4 changed files with 112 additions and 16 deletions

View File

@ -595,12 +595,12 @@ actors.hero.talent.projectile_momentum.desc=_+1:_ While freerunning, the Freerun
actors.hero.talent.speedy_stealth.title=speedy stealth
actors.hero.talent.speedy_stealth.desc=_+1:_ The Freerunner gains 2 stacks of momentum per turn while he is invisible.\n\n_+2:_ In addition to the benefits of +1, freerunning no longer counts down while the Freerunner is invisible.\n\n_+3:_ In addition to the benefits of +1 and +2, the Freerunner moves at 2x speed while invisible, regardless of whether he is freerunning or not.
actors.hero.talent.smoke_bomb_1.title=TODO NAME
actors.hero.talent.smoke_bomb_1.desc=TODO DESC
actors.hero.talent.smoke_bomb_2.title=TODO NAME
actors.hero.talent.smoke_bomb_2.desc=TODO DESC
actors.hero.talent.smoke_bomb_3.title=TODO NAME
actors.hero.talent.smoke_bomb_3.desc=TODO DESC
actors.hero.talent.hasty_retreat.title=hasty retreat
actors.hero.talent.hasty_retreat.desc=_+1:_ After blinking the Rogue gains _2 turns_ of haste and invisibility.\n\n_+2:_ After blinking the Rogue gains _4 turns_ of haste and invisibility.\n\n_+3:_ After blinking the Rogue gains _6 turns_ of haste and invisibility.\n\n_+4:_ After blinking the Rogue gains _8 turns_ of haste and invisibility.
actors.hero.talent.body_replacement.title=body replacement
actors.hero.talent.body_replacement.desc=_+1:_ After blinking, the Rogue leaves a wooden decoy behind that has _30 health and 1-5 armor_.\n\n_+2:_ After blinking, the Rogue leaves a wooden decoy behind that has _60 health and 2-10 armor_.\n\n_+3:_ After blinking, the Rogue leaves a wooden decoy behind that has _90 health and 3-15 armor_.\n\n_+4:_ After blinking, the Rogue leaves a wooden decoy behind that has _120 health and 4-20 armor_.\n\nOnly one decoy can be active at a time.
actors.hero.talent.shadow_step.title=shadow step
actors.hero.talent.shadow_step.desc=_+1:_ If the rogue uses smoke bomb while invisible, it occurs instantly and has a _24% reduced_ charge cost, but it also doesn't blind enemies or trigger other talents.\n\n_+2:_ If the rogue uses smoke bomb while invisible, it occurs instantly and has a _42% reduced_ charge cost, but it also doesn't blind enemies or trigger other talents.\n\n_+3:_ If the rogue uses smoke bomb while invisible, it occurs instantly and has a _56% reduced_ charge cost, but it also doesn't blind enemies or trigger other talents.\n\n_+4:_ If the rogue uses smoke bomb while invisible, it occurs instantly and has a _67% reduced_ charge cost, but it also doesn't blind enemies or trigger other talents.
actors.hero.talent.smoke_bomb_4.title=TODO NAME
actors.hero.talent.smoke_bomb_4.desc=TODO DESC

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

View File

@ -113,7 +113,7 @@ public enum Talent {
//Freerunner T3
EVASIVE_ARMOR(78, 3), PROJECTILE_MOMENTUM(79, 3), SPEEDY_STEALTH(80, 3),
//Smoke Bomb T4
SMOKE_BOMB_1(81, 4), SMOKE_BOMB_2(82, 4), SMOKE_BOMB_3(83, 4), SMOKE_BOMB_4(84, 4),
HASTY_RETREAT(81, 4), BODY_REPLACEMENT(82, 4), SHADOW_STEP(83, 4), SMOKE_BOMB_4(84, 4),
//??? T4
ROGUE_2_1(85, 4), ROGUE_2_2(86, 4), ROGUE_2_3(87, 4), ROGUE_2_4(88, 4),
//??? T4

View File

@ -27,11 +27,13 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Haste;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
@ -39,10 +41,13 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.MobSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class SmokeBomb extends ArmorAbility {
@ -51,6 +56,16 @@ public class SmokeBomb extends ArmorAbility {
return Messages.get(this, "prompt");
}
@Override
public float chargeUse(Hero hero) {
if (!hero.hasTalent(Talent.SHADOW_STEP) || hero.invisible <= 0){
return super.chargeUse(hero);
} else {
//reduced charge cost by 24%/42%/56%/67%
return (float)(35f * Math.pow(0.76, hero.pointsInTalent(Talent.SHADOW_STEP)));
}
}
@Override
protected void activate(ClassArmor armor, Hero hero, Integer target) {
if (target != null) {
@ -65,17 +80,38 @@ public class SmokeBomb extends ArmorAbility {
return;
}
armor.charge -= 35;
armor.charge -= chargeUse(hero);
Item.updateQuickslot();
for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
if (Dungeon.level.adjacent(mob.pos, hero.pos) && mob.alignment != Char.Alignment.ALLY) {
Buff.prolong( mob, Blindness.class, Blindness.DURATION/2f );
if (mob.state == mob.HUNTING) mob.state = mob.WANDERING;
mob.sprite.emitter().burst( Speck.factory( Speck.LIGHT ), 4 );
boolean shadowStepping = hero.invisible > 0 && hero.hasTalent(Talent.SHADOW_STEP);
if (!shadowStepping) {
for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
if (Dungeon.level.adjacent(mob.pos, hero.pos) && mob.alignment != Char.Alignment.ALLY) {
Buff.prolong(mob, Blindness.class, Blindness.DURATION / 2f);
if (mob.state == mob.HUNTING) mob.state = mob.WANDERING;
mob.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 4);
}
}
if (hero.hasTalent(Talent.BODY_REPLACEMENT)) {
for (Char ch : Actor.chars()){
if (ch instanceof NinjaLog){
ch.die(null);
}
}
NinjaLog n = new NinjaLog();
n.pos = hero.pos;
GameScene.add(n);
}
if (hero.hasTalent(Talent.HASTY_RETREAT)){
int duration = 2*hero.pointsInTalent(Talent.HASTY_RETREAT);
Buff.affect(hero, Haste.class, duration);
Buff.affect(hero, Invisibility.class, duration);
}
}
Buff.affect(hero, Invisibility.class, Invisibility.DURATION/2f);
CellEmitter.get( hero.pos ).burst( Speck.factory( Speck.WOOL ), 10 );
ScrollOfTeleportation.appear( hero, target );
@ -84,12 +120,72 @@ public class SmokeBomb extends ArmorAbility {
Dungeon.observe();
GameScene.updateFog();
hero.spendAndNext( Actor.TICK );
if (!shadowStepping) {
hero.spendAndNext(Actor.TICK);
} else {
hero.next();
}
}
}
@Override
public Talent[] talents() {
return new Talent[]{Talent.SMOKE_BOMB_1, Talent.SMOKE_BOMB_2, Talent.SMOKE_BOMB_3, Talent.SMOKE_BOMB_4};
return new Talent[]{Talent.HASTY_RETREAT, Talent.BODY_REPLACEMENT, Talent.SHADOW_STEP, Talent.SMOKE_BOMB_4};
}
public static class NinjaLog extends NPC {
{
spriteClass = NinjaLogSprite.class;
defenseSkill = 0;
properties.add(Property.INORGANIC); //wood is organic, but this is accurate for game logic
alignment = Alignment.ALLY;
HP = HT = 30*Dungeon.hero.pointsInTalent(Talent.BODY_REPLACEMENT);
}
@Override
public int drRoll() {
return Random.NormalIntRange(Dungeon.hero.pointsInTalent(Talent.BODY_REPLACEMENT),
5*Dungeon.hero.pointsInTalent(Talent.BODY_REPLACEMENT));
}
}
public static class NinjaLogSprite extends MobSprite {
public NinjaLogSprite(){
super();
texture("sprites/ninja_log.png");
TextureFilm frames = new TextureFilm( texture, 11, 12 );
idle = new Animation( 0, true );
idle.frames( frames, 0 );
run = idle.clone();
attack = idle.clone();
zap = attack.clone();
die = new Animation( 12, false );
die.frames( frames, 1, 2, 3, 4 );
play( idle );
}
@Override
public void showAlert() {
//do nothing
}
@Override
public int blood() {
return 0xFF966400;
}
}
}