v0.9.3: implemented the death mark ability
This commit is contained in:
parent
ff80adeb30
commit
886bd3d0a8
|
@ -363,8 +363,11 @@ actors.hero.abilities.rogue.smokebomb.prompt=Choose a location to jump to
|
|||
actors.hero.abilities.rogue.smokebomb.short_desc=The Rogue throws down a _Smoke Bomb_ while blinking away. He becomes temporarily invisible and blinds enemies near his old location.
|
||||
actors.hero.abilities.rogue.smokebomb.desc=TODO
|
||||
actors.hero.abilities.rogue.deathmark.name=death mark
|
||||
actors.hero.abilities.rogue.deathmark.ally_target=You can only mark enemies
|
||||
actors.hero.abilities.rogue.deathmark.short_desc=The Rogue places a _Death Mark_ on a chosen enemy. Marked enemies take bonus damage, but cannot die until the mark ends.
|
||||
actors.hero.abilities.rogue.deathmark.desc=TODO
|
||||
actors.hero.abilities.rogue.deathmark$deathmarktracker.name=Marked for Death
|
||||
actors.hero.abilities.rogue.deathmark$deathmarktracker.desc=TODO\n\nTurns left: %s.
|
||||
actors.hero.abilities.rogue.shadowclone.name=shadow clone
|
||||
actors.hero.abilities.rogue.shadowclone.short_desc=The Rogue summons a _Shadow Clone_, which is frail, but can be directed and deals damage based on his weapon.
|
||||
actors.hero.abilities.rogue.shadowclone.desc=TODO
|
||||
|
@ -621,12 +624,12 @@ actors.hero.talent.body_replacement.desc=_+1:_ After blinking, the Rogue leaves
|
|||
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.rogue_2_1.title=TODO NAME
|
||||
actors.hero.talent.rogue_2_1.desc=TODO DESC
|
||||
actors.hero.talent.rogue_2_2.title=TODO NAME
|
||||
actors.hero.talent.rogue_2_2.desc=TODO DESC
|
||||
actors.hero.talent.rogue_2_3.title=TODO NAME
|
||||
actors.hero.talent.rogue_2_3.desc=TODO DESC
|
||||
actors.hero.talent.fear_the_reaper.title=fear the reaper
|
||||
actors.hero.talent.fear_the_reaper.desc=_+1:_ When a death marked enemy reaches 0 hp, they become _crippled_.\n\n_+2:_ When a death marked enemy reaches 0 hp, they become _feared and crippled_.\n\n_+3:_ When a death marked enemy reaches 0 hp, they become _feared and crippled_ and enemies within 3 tiles become _crippled_.\n\n_+4:_ When a death marked enemy reaches 0 hp, they become _feared and crippled_ and enemies within 3 tiles become _feared and crippled_.
|
||||
actors.hero.talent.deathly_durability.title=deathly durability
|
||||
actors.hero.talent.deathly_durability.desc=_+1:_ Enemies killed by death mark give the rogue shielding equal to _10%_ of their hp when they were marked.\n\n_+2:_ Enemies killed by death mark give the rogue shielding equal to _20%_ of their hp when they were marked.\n\n_+3:_ Enemies killed by death mark give the rogue shielding equal to _30%_ of their hp when they were marked.\n\n_+4:_ Enemies killed by death mark give the rogue shielding equal to _40%_ of their hp when they were marked.
|
||||
actors.hero.talent.double_mark.title=double mark
|
||||
actors.hero.talent.double_mark.desc=_+1:_ Marking a second target at the same time as the first one has a _24% reduced_ charge cost.\n\n_+2:_ Marking a second target at the same time as the first one has a _42% reduced_ charge cost.\n\n_+3:_ Marking a second target at the same time as the first one has a _56% reduced_ charge cost.\n\n_+4:_ Marking a second target at the same time as the first one has a _67% reduced_ charge cost.
|
||||
|
||||
actors.hero.talent.rogue_3_1.title=TODO NAME
|
||||
actors.hero.talent.rogue_3_1.desc=TODO DESC
|
||||
|
|
|
@ -63,6 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.rogue.DeathMark;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.AntiMagic;
|
||||
|
@ -96,6 +97,7 @@ import com.watabou.utils.Bundle;
|
|||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
@ -546,6 +548,9 @@ public abstract class Char extends Actor {
|
|||
if (this.buff(Doom.class) != null && !isImmune(Doom.class)){
|
||||
dmg *= 2;
|
||||
}
|
||||
if (alignment != Alignment.ALLY && this.buff(DeathMark.DeathMarkTracker.class) != null){
|
||||
dmg *= 1.25f;
|
||||
}
|
||||
|
||||
Class<?> srcClass = src.getClass();
|
||||
if (isImmune( srcClass )) {
|
||||
|
@ -586,6 +591,28 @@ public abstract class Char extends Actor {
|
|||
|
||||
if (!isAlive()) {
|
||||
die( src );
|
||||
} else if (HP == 0 && buff(DeathMark.DeathMarkTracker.class) != null){
|
||||
if (Dungeon.hero.hasTalent(Talent.FEAR_THE_REAPER)) {
|
||||
if (Dungeon.hero.pointsInTalent(Talent.FEAR_THE_REAPER) >= 2) {
|
||||
Buff.prolong(this, Terror.class, 5f).target = Dungeon.hero;
|
||||
}
|
||||
Buff.prolong(this, Cripple.class, 5f);
|
||||
|
||||
if (Dungeon.hero.pointsInTalent(Talent.FEAR_THE_REAPER) >= 3) {
|
||||
boolean[] passable = BArray.not(Dungeon.level.solid, null);
|
||||
PathFinder.buildDistanceMap(pos, passable, 3);
|
||||
|
||||
for (Char ch : Actor.chars()) {
|
||||
if (ch != this && ch.alignment == Alignment.ENEMY
|
||||
&& PathFinder.distance[ch.pos] != Integer.MAX_VALUE) {
|
||||
if (Dungeon.hero.pointsInTalent(Talent.FEAR_THE_REAPER) == 4) {
|
||||
Buff.prolong(ch, Terror.class, 5f).target = Dungeon.hero;
|
||||
}
|
||||
Buff.prolong(ch, Cripple.class, 5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,6 +639,9 @@ public abstract class Char extends Actor {
|
|||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
if (buff(DeathMark.DeathMarkTracker.class) != null){
|
||||
return true;
|
||||
}
|
||||
return HP > 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,8 +117,8 @@ public enum Talent {
|
|||
EVASIVE_ARMOR(78, 3), PROJECTILE_MOMENTUM(79, 3), SPEEDY_STEALTH(80, 3),
|
||||
//Smoke Bomb T4
|
||||
HASTY_RETREAT(81, 4), BODY_REPLACEMENT(82, 4), SHADOW_STEP(83, 4),
|
||||
//??? T4
|
||||
ROGUE_2_1(84, 4), ROGUE_2_2(85, 4), ROGUE_2_3(86, 4),
|
||||
//Death Mark T4
|
||||
FEAR_THE_REAPER(84, 4), DEATHLY_DURABILITY(85, 4), DOUBLE_MARK(86, 4),
|
||||
//??? T4
|
||||
ROGUE_3_1(87, 4), ROGUE_3_2(88, 4), ROGUE_3_3(89, 4),
|
||||
|
||||
|
|
|
@ -21,20 +21,141 @@
|
|||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.rogue;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||
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.items.armor.ClassArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class DeathMark extends ArmorAbility {
|
||||
|
||||
@Override
|
||||
protected void activate(ClassArmor armor, Hero hero, Integer target) {
|
||||
//TODO
|
||||
protected String targetingPrompt() {
|
||||
return Messages.get(this, "prompt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Talent[] talents() {
|
||||
return new Talent[]{Talent.ROGUE_2_1, Talent.ROGUE_2_2, Talent.ROGUE_2_3, Talent.HEROIC_ENERGY};
|
||||
public float chargeUse( Hero hero ) {
|
||||
float chargeUse = super.chargeUse(hero);
|
||||
if (hero.buff(DoubleMarkTracker.class) != null){
|
||||
//reduced charge use by 24%/42%/56%/67%
|
||||
chargeUse *= Math.pow(0.76, hero.pointsInTalent(Talent.DOUBLE_MARK));
|
||||
}
|
||||
return chargeUse;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate(ClassArmor armor, Hero hero, Integer target) {
|
||||
if (target == null){
|
||||
return;
|
||||
}
|
||||
|
||||
Char ch = Actor.findChar(target);
|
||||
|
||||
if (ch == null){
|
||||
GLog.w(Messages.get(this, "no_target"));
|
||||
} else if (ch.alignment != Char.Alignment.ENEMY){
|
||||
GLog.w(Messages.get(this, "ally_target"));
|
||||
}
|
||||
|
||||
if (ch != null){
|
||||
Buff.affect(ch, DeathMarkTracker.class, 5f);
|
||||
ch.buff(DeathMarkTracker.class).setInitialHP(ch.HP);
|
||||
}
|
||||
|
||||
armor.charge -= chargeUse( hero );
|
||||
armor.updateQuickslot();
|
||||
hero.sprite.zap(target);
|
||||
|
||||
Invisibility.dispel();
|
||||
hero.next();
|
||||
|
||||
if (hero.buff(DoubleMarkTracker.class) != null){
|
||||
hero.buff(DoubleMarkTracker.class).detach();
|
||||
} else if (hero.hasTalent(Talent.DOUBLE_MARK)) {
|
||||
Buff.affect(hero, DoubleMarkTracker.class, 0.01f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DoubleMarkTracker extends FlavourBuff{};
|
||||
|
||||
@Override
|
||||
public Talent[] talents() {
|
||||
return new Talent[]{Talent.FEAR_THE_REAPER, Talent.DEATHLY_DURABILITY, Talent.DOUBLE_MARK, Talent.HEROIC_ENERGY};
|
||||
}
|
||||
|
||||
public static class DeathMarkTracker extends FlavourBuff {
|
||||
|
||||
int initialHP = 0;
|
||||
|
||||
{
|
||||
type = buffType.NEGATIVE;
|
||||
announced = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.MARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Messages.get(this, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
//TODO show initial HP here?
|
||||
return Messages.get(this, "desc", dispTurns(visualcooldown()));
|
||||
}
|
||||
|
||||
private void setInitialHP( int hp ){
|
||||
if (initialHP < hp){
|
||||
initialHP = hp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
if (!target.isAlive()){
|
||||
target.sprite.flash();
|
||||
target.sprite.bloodBurstA(target.sprite.center(), target.HT*2);
|
||||
Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG);
|
||||
target.die(this);
|
||||
int shld = Math.round(initialHP * (0.1f*Dungeon.hero.pointsInTalent(Talent.DEATHLY_DURABILITY)));
|
||||
if (shld > 0 && target.alignment != Char.Alignment.ALLY){
|
||||
Buff.affect(Dungeon.hero, Barrier.class).setShield(shld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String INITIAL_HP = "initial_hp";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
bundle.put(INITIAL_HP, initialHP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
initialHP = bundle.getInt(INITIAL_HP);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public class Brute extends Mob {
|
|||
|
||||
@Override
|
||||
public synchronized boolean isAlive() {
|
||||
if (HP > 0){
|
||||
if (super.isAlive()){
|
||||
return true;
|
||||
} else {
|
||||
if (!hasRaged){
|
||||
|
|
|
@ -511,7 +511,7 @@ public class NewDM300 extends Mob {
|
|||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return HP > 0 || pylonsActivated < totalPylonsToActivate();
|
||||
return super.isAlive() || pylonsActivated < totalPylonsToActivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -194,7 +194,7 @@ public class Tengu extends Mob {
|
|||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return HP > 0 || Dungeon.level.mobs.contains(this); //Tengu has special death rules, see prisonbosslevel.progress()
|
||||
return super.isAlive() || Dungeon.level.mobs.contains(this); //Tengu has special death rules, see prisonbosslevel.progress()
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue
Block a user