From 4cb787a4bf1810c79a7b9834be2d85e97c3487ba Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 19 Jan 2023 14:54:10 -0500 Subject: [PATCH] v2.0.0: implement base challenge armor ability and all of its text --- core/src/main/assets/interfaces/buffs.png | Bin 1557 -> 1585 bytes .../src/main/assets/interfaces/hero_icons.png | Bin 1289 -> 1365 bytes .../main/assets/interfaces/large_buffs.png | Bin 3454 -> 3519 bytes .../main/assets/interfaces/talent_icons.png | Bin 5985 -> 6118 bytes .../assets/messages/actors/actors.properties | 26 +- .../shatteredpixeldungeon/actors/Actor.java | 9 + .../shatteredpixeldungeon/actors/Char.java | 8 +- .../actors/hero/Hero.java | 2 +- .../actors/hero/HeroClass.java | 3 +- .../actors/hero/Talent.java | 2 +- .../hero/abilities/duelist/Challenge.java | 250 ++++++++++++++++++ .../actors/mobs/DM300.java | 2 +- .../actors/mobs/DwarfKing.java | 10 +- .../actors/mobs/Ghoul.java | 11 +- .../actors/mobs/Pylon.java | 3 +- .../actors/mobs/YogDzewa.java | 12 +- .../actors/mobs/YogFist.java | 2 +- .../ui/BuffIndicator.java | 1 + .../shatteredpixeldungeon/ui/HeroIcon.java | 5 +- 19 files changed, 332 insertions(+), 14 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/duelist/Challenge.java diff --git a/core/src/main/assets/interfaces/buffs.png b/core/src/main/assets/interfaces/buffs.png index f8cb82a25a5c8e145ff221a08b07007a6d343744..8a283f13b2b5e8763ae507b386a992ef80351fac 100644 GIT binary patch delta 1071 zcmV+~1kn4H46zK5Bmo++B^3b;Edl~>cSpPT@h7L6LpdK8}Mawkqe9z$q2$%D6mRq z=hoKe*4H4ArYQtIr0E9;tcJDtj!tt>|ZCE3nUq~1D=%3|+Kv>A%fPrr=FE4L;<(CQ!D$N#Y*1&eHBe1*I zZnyV#9kCSH-{+Ny06f&N3jB@j3}KRde!0!AFi-N12A7K*9 zPyxgYg3LB7erh%y-V$;F=0ku6XyEwdm<{lg0p?#`K|uDphs;lt`GM=3>+4J)toa58 zzA;}Y7WqhjN{5Fq=rrIo2pbO5|B`9jAU5P!xxmTE?a7H}pKa9Z$gjKU?y<(uK!Xk3 z-QC|wfC=3VKma68an;|MfNAVx%1SHEykjga`oFEb*BzlH=(A0hDc^aO!Z0)c0HhJapsG{(rgU z5SR<-NSUcz=JONj&;aRgaQLr8r7!0{UfaYM3J7ClS0AyF4Mm0jm%m4ri002ovPDHLkV1g{W-U0vs delta 1042 zcmV+t1nv8=43!L!Bmoq$B^3b&Z+Ay*a$zKsM*$!KpOa_-$A4f_B#DA>#PLqv2An&b z(6Qs%!&on_E6BS4|NpU>l}&X7Td4EV9RCI|_6N1%J8}==J;k-Z#h2coPtSg#^MB ztqPoz?VW63gKTFv+vTgg#RY+|kl%!Xw~mjGTYmV}Aq)A#2)By5naBy&pb&v~;(v&adL!jG*0rDLNc8tj5C;$T; z0Y5+XvVQ>@a0Zwk8{p@s0O1Tgz?MMK049J9q{EaAFkb?(0eybIC{SYoQ2+)SLgdF8 z;1FaOLgqt&1?UJa%mB||7-yhMmNS6tFa`maz};?v1nz$ejy*(+3)gT*xJZ(uj_tyP ziw$Ao2T>6&Dxx90KtTz1MFasn`0)GL&H&rj@P9?L27xCD_|*vC-3o!H_(FV2fu;ml zCcp0S!0~53#STwD3Cx0kInWQtw*&(7#eDue2pI7l3>=PotyKM{T3SnBfC?aH5M;Jt z@t0;B;gL`XFdqUmKm*UF&)5KeL4nzemk^M>?jiHDWT*1#^{ZF8Kv+8i4E$iHRIT!r z)PJ8mfx)r?YFOBC*!YudSd-Wfj#UUur*EcH&wtfyG?3qL)7@i@p@9J#c>DI zwE+l#By^_wms9YouQuSC0Y36#19|{An=dp25Qs;B{6T2o)vMPM_|>4WIs*6gKi1(r< z^18~xMH(UTH?QW$TOfhi2MB!p_z?m#0)bEV2?F}=(HJ9ZVut_M2nBGm60meaOg|@P zcM|W-9UJ-O^5?P}*0HCC3@ZfSGzkI|Y(>*C{OZ@#?jSJJ5g>mlkdK}6A#-5I z$H+1S76Lj_UpdA<*4j6R+0CoMC+J_0-6#xJL M07*qoM6N<$f;kh>@c;k- diff --git a/core/src/main/assets/interfaces/hero_icons.png b/core/src/main/assets/interfaces/hero_icons.png index f5712a5a3389835bd85a368d6267230237e95c4a..689683d7a46060289faf073d983a295bd71ca827 100644 GIT binary patch delta 1167 zcmV;A1aSL_3e^gb)_-bAL_t(|0mPVxj@vvC2DukGy54*5y}$p%Wk0P4Ji>&awA1`H zr9W-PEOL;PtRSVif|Py~@atjd|2GZ)KPlknGnfIhFf+aX1Og26PYO)59sL3F&rbsu zI;@V(JD&PuXh6FNi)~MU{0cx%LY*>TX{l+JmQ0}5s3BRXp??~X{R)s7dIS88Ujb2o z`b$6?lMvTxK=%7}Sz=hu!j;tyV*v<|AL;=n7UQCTwY9k~L*dtrYt1X<)~(cG7b|>x z5(WfFttn_DV{XlC?aNU39Sdn5MIk33^o@umXhgUfDtn+7fL~aAcC(lV^x;)QEJ06z zyu20A#^T4=)_;}&KLKLd<)YK~pMr7;6yRpPrUBXnuvj~Wg@5K0F!OOK7oi@Yf*_s) zaSR+Es{!~4$md|W=P?uwm18LIPXjWQ0Q@lBd-1Y5_-hX$0@ibYwdh-`1>nyC%Vu0E z;O==8yFUk%R00e?0mB&(FwWO80rIDff|>vS-(=tB=6@!)-&&CUTVn;_A1?s^SONIO z2m!L=k3~=h!}kPi;qL-;$-}n$y1v6j<%zzoP+r$=TzzkLfSVFwl5dr)A zycKZZ0Dl38P7xsg(a}*3*z6$S*y#%p1jySTApOaS4`slq`AY!-0n$$)z}mKH+Lizy zApAK%+F%+Wz32+^1f1#R0T2QBDG0wcjmGK>NXt+Ukbhx81q#4_?pSRGWCjI)> zC;NT$cV7LtYlK<6os|87y!eL(m|b6AyI*9#7#M(GAm$?N0si_DnBCmm$S+F&fF-~W zlHwO3#$Vfn@c@utl>Pym5I>-oU!abmatzH*Pfz6!O8M00cPM|NCD?qkkQz+k%wt3TFR( z|Gr>0@Vp?UtAdms3h+O6=ngZK{+|=f(CwvG#0_S^445I|ry#UuMgZ!d7SNc5zZn|v z^yDuedIFv)$bKJRCX@Tu*KGIyQGg2MAAcV3_Vn&N^#xFXe-i$Qq$KEWYBr6-m%#mR z?{5UiUj&$Wz%v1b-vd5A-22+`@p0cq0si3u;;B9Zt{3J+0Df^F1+Sm}pZh%^3c^1i z0Dmn&w^M&aD4_5Y;BJ2rpaS`SFTi)|10kQiu4hndCd(#2Px#00>D%PDHLkV1hk(7&ZU^ delta 1090 zcmV-I1iky!3W*Ak)_)#JL_t(|0mYbya-}#F1$CWpPLp%a!QuZuZja~{$0}rsabeT@ zo?z2-TLGpfrKm`0qavlvit&Fx@9(#^%HMBSlz(sV8oUq@`rZKtL^1Dd0|8ynQ~>^6 z0%ETxZedp_b#rb&w?EJ|1MDXNeJjD#0S5D)8DPHxDXFKRN zBQpsz0#IuTIx;p+B2I1$m0tu>j~UB>0Cu0y^z#+C%Rqo>2iPxypFM(kD0;lPfhCv- zkk?-YbSyq&*MC?7`w3w2CC~KwiBm9M0*PhrKLoG|V83w;YyapJl$qyJFTyPWQUlKc zj)BnF46vU7pM%4R#}EyzV<-kc0j3dPKd|@s#I4|OKZpo8b$}m*T{HslR{{LwTw36s zcofU;fST3}*e_x}vjWz69TR{*omGtg{+_Y#{QTVB2Y)QE|IvB@_}2`;zhVG>u}VM| z<9~EcjfaN`cvSp-K)!f*kO2Ev3Bdda{~Ak>&5zbR1=()@3IVb+3u^@kW?{_$>}v$9 z`#Ofbij*E#q|{ZU^rRxCM-}5A;AzG9Hz;<4-C#G^4R%N7k=&-Az_T6#ot5WT1b@5~b%6Y@UcGX_c~1#=EhYnm1D;O?pnvm5Lmluo^zjThKzbMgx^8Q$>l^?C z41Nbl3;zd5-_sX(0^aFE01$xR1^6`s8k;kK)0{Hp-#=RS(3Uq%$%_A&}#|3ANs)_)zRuN5hMs~G?J z{`ZQMepIA?2Jg?Fe23T6{+(^S#_l^7*iQl4h;RUEXb1fIrH_UM1AdnR`!)XA-v0jg zukHF90xo`CieF0xlmh(HHzJ+i$#_IH5Cf5p8z2<=)PWn zy9FS3fRG(O0rqnYi~fEBL}b1E1mJgoK<@y}KLv}N0=7Zc6JWms@H;?u0v6bW6g%7u zzz_J5FBZ_d9YBEt@I&KKd~tE11CWP{ diff --git a/core/src/main/assets/interfaces/large_buffs.png b/core/src/main/assets/interfaces/large_buffs.png index ace48dab306bc47f6581bba0e0d224a7754be4e4..bdfd5ebf9292a6a50ba392a3624e8d66ed4e8e11 100644 GIT binary patch delta 3251 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 diff --git a/core/src/main/assets/interfaces/talent_icons.png b/core/src/main/assets/interfaces/talent_icons.png index f5cc67c3ddc7fd780ba502b3f95573723d8988c7..e6fc86a7b26f7db7ec7f9e3b1008391c00805895 100644 GIT binary patch delta 5814 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 delta 5680 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 properties = new HashSet<>(); @@ -1004,6 +1009,7 @@ public abstract class Char extends Actor { new HashSet( Arrays.asList(AllyBuff.class, Dread.class) )), MINIBOSS ( new HashSet(), new HashSet( Arrays.asList(AllyBuff.class, Dread.class) )), + BOSS_MINION, UNDEAD, DEMONIC, INORGANIC ( new HashSet(), diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 42037aeb9..aef987ce0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -2052,7 +2052,7 @@ public class Hero extends Char { @Override public boolean isInvulnerable(Class effect) { - return buff(AnkhInvulnerability.class) != null; + return super.isInvulnerable(effect) || buff(AnkhInvulnerability.class) != null; } public boolean search( boolean intentional ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java index ffcdd4694..66f7e1a8c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java @@ -29,6 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.QuickSlot; import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.duelist.Challenge; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.NaturesPower; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpectralBlades; @@ -254,7 +255,7 @@ public enum HeroClass { case HUNTRESS: return new ArmorAbility[]{new SpectralBlades(), new NaturesPower(), new SpiritHawk()}; case DUELIST: - return new ArmorAbility[]{}; + return new ArmorAbility[]{new Challenge()}; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java index f6c5a8669..27bc7bac3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java @@ -158,7 +158,7 @@ public enum Talent { //Duelist S2 T3 DUELIST_S2_1(142, 3), DUELIST_S2_2(143, 3), DUELIST_S2_3(144, 3), //Duelist A1 T4 - DUELIST_A1_1(145, 4), DUELIST_A1_2(146, 4), DUELIST_A1_3(147, 4), + CLOSE_THE_GAP(145, 4), INVIGORATING_VICTORY(146, 4), ELIMINATION_MATCH(147, 4), //Duelist A2 T4 DUELIST_A2_1(148, 4), DUELIST_A2_2(149, 4), DUELIST_A2_3(150, 4), //Duelist A3 T4 diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/duelist/Challenge.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/duelist/Challenge.java new file mode 100644 index 000000000..0d6c02899 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/duelist/Challenge.java @@ -0,0 +1,250 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.duelist; + +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.BlobImmunity; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Doom; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff; +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.items.armor.ClassArmor; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; + +public class Challenge extends ArmorAbility { + + { + baseChargeUse = 35; + } + + @Override + public int icon() { + return HeroIcon.CHALLENGE; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + public int targetedPos(Char user, int dst) { + return dst; + } + + @Override + protected void activate(ClassArmor armor, Hero hero, Integer target) { + if (target == null || !Dungeon.level.heroFOV[target]){ + return; + } + + Char targetCh = Actor.findChar(target); + + if (hero.buff(DuelParticipant.class) != null){ + GLog.w(Messages.get(this, "already_dueling")); + return; + } + + if (targetCh != null){ + + if (targetCh.alignment == hero.alignment){ + GLog.w(Messages.get(this, "ally_target")); + return; + } + + boolean[] passable = Dungeon.level.passable.clone(); + for (Char c : Actor.chars()) { + if (c != hero) passable[c.pos] = false; + } + + PathFinder.buildDistanceMap(targetCh.pos, passable); + if (PathFinder.distance[hero.pos] == Integer.MAX_VALUE){ + GLog.w(Messages.get(this, "unreachable_target")); + return; + } + + if (Dungeon.level.distance(hero.pos, targetCh.pos) >= 5){ + GLog.w(Messages.get(this, "distant_target")); + return; + } + + boolean bossTarget = Char.hasProp(targetCh, Char.Property.BOSS); + for (Char toFreeze : Actor.chars()){ + if (toFreeze != targetCh && toFreeze.alignment != hero.alignment + && (!bossTarget || !(Char.hasProp(targetCh, Char.Property.BOSS) || Char.hasProp(targetCh, Char.Property.BOSS_MINION)))) { + Actor.delayChar(toFreeze, DuelParticipant.DURATION); + Buff.affect(toFreeze, SpectatorFreeze.class, DuelParticipant.DURATION); + } + } + + Buff.affect(targetCh, DuelParticipant.class); + Buff.affect(hero, DuelParticipant.class); + if (targetCh instanceof Mob){ + ((Mob) targetCh).aggro(hero); + } + + GameScene.flash(0x80FFFFFF); + Sample.INSTANCE.play(Assets.Sounds.DESCEND); + + armor.charge -= chargeUse( hero ); + armor.updateQuickslot(); + hero.sprite.zap(target); + + hero.next(); + } + } + + @Override + public Talent[] talents() { + return new Talent[]{Talent.CLOSE_THE_GAP, Talent.INVIGORATING_VICTORY, Talent.ELIMINATION_MATCH, Talent.HEROIC_ENERGY}; + } + + public static class DuelParticipant extends Buff { + + public static float DURATION = 10f; + + private int left = (int)DURATION; + + @Override + public int icon() { + return BuffIndicator.CHALLENGE; + } + + @Override + public float iconFadePercent() { + return Math.max(0, (DURATION - left) / DURATION); + } + + @Override + public String iconTextDisplay() { + return Integer.toString(left); + } + + @Override + public boolean act() { + + left--; + if (left == 0) { + detach(); + } else { + Char other = null; + for (Char ch : Actor.chars()){ + if (ch != target && ch.buff(DuelParticipant.class) != null){ + other = ch; + } + } + + if (other == null){ + detach(); + } else if (Dungeon.level.distance(target.pos, other.pos) > 5){ + detach(); + } + } + + spend(TICK); + return true; + } + + @Override + public void detach() { + super.detach(); + if (!target.isAlive()) { + if (target.alignment != Dungeon.hero.alignment){ + Sample.INSTANCE.play(Assets.Sounds.BOSS); + GameScene.flash(0x80FFFFFF); + } + + for (Char ch : Actor.chars()) { + if (ch.buff(SpectatorFreeze.class) != null) { + ch.buff(SpectatorFreeze.class).detach(); + } + if (ch.buff(DuelParticipant.class) != null && ch != target) { + ch.buff(DuelParticipant.class).detach(); + } + } + } else if (target == Dungeon.hero){ + GameScene.flash(0x80FFFFFF); + } + } + + @Override + public String desc() { + return Messages.get(this, "desc", left); + } + + private static final String LEFT = "left"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + left = bundle.getInt(LEFT); + } + } + + public static class SpectatorFreeze extends FlavourBuff { + + @Override + public void fx(boolean on) { + if (on) { + target.sprite.add(CharSprite.State.DARKENED); + target.sprite.add(CharSprite.State.PARALYSED); + } else { + //allies can't be spectator frozen, so just check doom + if (target.buff(Doom.class) == null) target.sprite.remove(CharSprite.State.DARKENED); + if (target.paralysed == 0) target.sprite.remove(CharSprite.State.PARALYSED); + } + } + + @Override + public void detach(){ + super.detach(); + if (cooldown() > 0) { + Actor.delayChar(target, -cooldown()); + } + } + + { + immunities.addAll(new BlobImmunity().immunities()); + } + + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DM300.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DM300.java index 618a0afe6..4daa113a4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DM300.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DM300.java @@ -503,7 +503,7 @@ public class DM300 extends Mob { invulnWarned = true; GLog.w(Messages.get(this, "charging_hint")); } - return supercharged; + return supercharged || super.isInvulnerable(effect); } public void supercharge(){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java index 25473d62a..906d1b9d9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java @@ -438,7 +438,11 @@ public class DwarfKing extends Mob { @Override public boolean isInvulnerable(Class effect) { - return phase == 2 && effect != KingDamager.class; + if (effect == KingDamager.class){ + return false; + } else { + return phase == 2 || super.isInvulnerable(effect); + } } @Override @@ -562,6 +566,7 @@ public class DwarfKing extends Mob { public static class DKGhoul extends Ghoul { { + properties.add(Property.BOSS_MINION); state = HUNTING; } @@ -574,12 +579,14 @@ public class DwarfKing extends Mob { public static class DKMonk extends Monk { { + properties.add(Property.BOSS_MINION); state = HUNTING; } } public static class DKWarlock extends Warlock { { + properties.add(Property.BOSS_MINION); state = HUNTING; } @@ -594,6 +601,7 @@ public class DwarfKing extends Mob { public static class DKGolem extends Golem { { + properties.add(Property.BOSS_MINION); state = HUNTING; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Ghoul.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Ghoul.java index b510b9e37..8888f5b8b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Ghoul.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Ghoul.java @@ -28,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.SacrificialFire; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.duelist.Challenge; import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; @@ -261,7 +262,10 @@ public class Ghoul extends Mob { return true; } - turnsToRevive--; + //have to delay this manually here are a downed ghouls can't be directly frozen otherwise + if (target.buff(Challenge.DuelParticipant.class) == null) { + turnsToRevive--; + } if (turnsToRevive <= 0){ if (Actor.findChar( ghoul.pos ) != null) { ArrayList candidates = new ArrayList<>(); @@ -345,7 +349,10 @@ public class Ghoul extends Mob { public static Ghoul searchForHost(Ghoul dieing){ for (Char ch : Actor.chars()){ - if (ch != dieing && ch instanceof Ghoul && ch.alignment == dieing.alignment){ + //don't count hero ally ghouls or duel frozen ghouls + if (ch != dieing && ch instanceof Ghoul + && ch.alignment == dieing.alignment + && ch.buff(Challenge.SpectatorFreeze.class) == null){ if (ch.fieldOfView == null){ ch.fieldOfView = new boolean[Dungeon.level.length()]; Dungeon.level.updateFieldOfView( ch, ch.fieldOfView ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Pylon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Pylon.java index 3b1600112..4b5f5f75b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Pylon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Pylon.java @@ -63,6 +63,7 @@ public class Pylon extends Mob { maxLvl = -2; properties.add(Property.MINIBOSS); + properties.add(Property.BOSS_MINION); properties.add(Property.INORGANIC); properties.add(Property.ELECTRIC); properties.add(Property.IMMOVABLE); @@ -178,7 +179,7 @@ public class Pylon extends Mob { @Override public boolean isInvulnerable(Class effect) { //immune to damage when inactive - return (alignment == Alignment.NEUTRAL); + return alignment == Alignment.NEUTRAL || super.isInvulnerable(effect); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java index db9fc681e..5272da8dc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java @@ -368,7 +368,7 @@ public class YogDzewa extends Mob { @Override public boolean isInvulnerable(Class effect) { - return phase == 0 || findFist() != null; + return phase == 0 || findFist() != null || super.isInvulnerable(effect); } @Override @@ -629,6 +629,7 @@ public class YogDzewa extends Mob { maxLvl = -2; properties.add(Property.DEMONIC); + properties.add(Property.BOSS_MINION); } @Override @@ -649,15 +650,22 @@ public class YogDzewa extends Mob { } //used so death to yog's ripper demons have their own rankings description - public static class YogRipper extends RipperDemon {} + public static class YogRipper extends RipperDemon { + { + maxLvl = -2; + properties.add(Property.BOSS_MINION); + } + } public static class YogEye extends Eye { { maxLvl = -2; + properties.add(Property.BOSS_MINION); } } public static class YogScorpio extends Scorpio { { maxLvl = -2; + properties.add(Property.BOSS_MINION); } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogFist.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogFist.java index 47c4dbe53..569cd20e2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogFist.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogFist.java @@ -116,7 +116,7 @@ public abstract class YogFist extends Mob { invulnWarned = true; GLog.w(Messages.get(this, "invuln_warn")); } - return isNearYog(); + return isNearYog() || super.isInvulnerable(effect); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java index d6f83ceef..2b20c139a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java @@ -118,6 +118,7 @@ public class BuffIndicator extends Component { public static final int DUEL_DANCE = 64; public static final int DUEL_BRAWL = 65; public static final int DUEL_XBOW = 66; + public static final int CHALLENGE = 67; public static final int SIZE_SMALL = 7; public static final int SIZE_LARGE = 16; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java index 0a5677149..70274adcb 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java @@ -61,7 +61,10 @@ public class HeroIcon extends Image { public static final int SPECTRAL_BLADES = 25; public static final int NATURES_POWER = 26; public static final int SPIRIT_HAWK = 27; - public static final int RATMOGRIFY = 28; + public static final int CHALLENGE = 28; + public static final int DUELIST_2 = 29; + public static final int DUELIST_3 = 30; + public static final int RATMOGRIFY = 33; public HeroIcon(HeroSubClass subCls){ super( Assets.Interfaces.HERO_ICONS );