From 6cda24e6ed9d5609f8d9f9d4d05bdbff5a1a2e7c Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 10 Sep 2017 02:32:39 -0400 Subject: [PATCH] v0.6.2: reworked the freerunner subclass --- core/src/main/assets/buffs.png | Bin 1107 -> 1136 bytes core/src/main/assets/large_buffs.png | Bin 2175 -> 2260 bytes .../actors/buffs/Momentum.java | 106 ++++++++++++++++++ .../actors/hero/Hero.java | 47 ++++---- .../sprites/HeroSprite.java | 5 +- .../ui/BuffIndicator.java | 2 + .../messages/actors/actors.properties | 5 +- 7 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Momentum.java diff --git a/core/src/main/assets/buffs.png b/core/src/main/assets/buffs.png index e3b509ff1f6ed967999846b3d225890607edc3e4..d512b6f71ad82ce680f71c08ec7af99ea72fa5c2 100644 GIT binary patch delta 843 zcmV-R1GN0p2=EB7GXZ}nNkl2(T;*1J-pF!1e*y8E`P*ysm%i{02y~APurK3=vWO zKoJuFxWs@lbZkSD8|&n89{f#5Kc6;CBLjH-0c;xyWIh27Su~&b7a$8{hp2$KC`gci zE&xNvww!hHFaUZ1ywOgU%W(ri5Uz?YG#iG$f`C+I_VF2xIq&~I`TABXGuu6y#N6Mu zdd)~6Nz9V!6>NV2u%%bsmB7v|3A|(FZ~8~} zWdue5C?pU7I6k_Rz?BZ{Du6119RuO^4wys&silT827oO_03QXghyNY`^1rDAS8hQR zMJnMA^PpQGe*iS+Zo!|sZ-II3dmVTkdeyyZUZ1=gUQK^5Gi$MJuZ~yOtLIhnJ7h=B zyv_j9L`pF~7Ql&gaCq83?4JTK7z_Xy4hBO2PBzo{APHc^nvGjy04Cg@Nd+*K1TYi8 zTzYe4vUiJ(0D!^+Y+7^~pf4TP2Mf0t)N6y9o=*oF05*gF2m%`)9UYCW{i+Q?d%2R9 zT{P_mfcbxXygBY^-A62KpVR_lmql>nb% zT?J4CX$1g*FCqR_2ULOqC6qq^3c$aDD;>}~SXO@>m`R}n*sBJi0{}ey76{<+x8TSe zGOsJwu=Fyoq9}6q;t!kGx91fAS(X7Xs4rOCilS%>fS(1*oRrD@1p%By0t4z+--?nq zNwif!Km>p}0ObvW=~L&PA7C@}1%+SKqa@K&JI$+cRqYfB#001XN VZVgI+OsW6?002ovPDHLkV1i!zTlxS1 delta 814 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 delta 1928 zcmV;32Y2|?5&sa7DFcOG3Xv@5e~b$iJOBUy0d!JMQvg8b*k%9#2SZ6jK~#7FY{P{K z!~hfpu+&}lU-lGxp9Vq`XailK4-A1ZFa_qo5?BLkU<>SlBX9<;KvT3u_jCV$^u}i-kg>NmfbKA1jC%jpPAwQM~vHLxhH-T+J0Waa+Rf#f8d^U(WsJ7 z`##doX0soK%;(hr*o!tn09lq&mV#cvZUOvT7QoyB*6a0Vy|w`6y?{uT3fS&;yX}}? zNd>@9EMT7qn56>1CqV%Cg%!{=&D)g)d?6?>KL+3zFb3dfuCe(s5Yc-9yDt8oLpih# z)Kvk;E>XbH_Wb+liBaT7f53TO15HV*$!Y00U~E4M0!(2LbR$0ZJ7hc03g2A^b;41(<({0QeOI@b0_k zmI_!aEwLg2ah?ePf7=2m0b>L3=K?^d6aPqn0(~MN*#gT#d=FUtDnPm2=+iC0iuV@q zJS&1=D;@z~1sqrb2Lym$6#$+Iz`&1SAlU+05sdu9F<1(FAUOqG1Yah=)C>~?Vn1*Z zg5L(HfqxY6!~EkSm>z@Xw}2u64FWg^I0MpS5MUpJo@d7(f6zqZXI})j(5C{_^aGcG z;S@+$0Ql)KIKBuijqfes6+rFd`RzprU|)oo=NF+k9d3e}L<4%d!0sm81Sx_T_-+BB zw}R{AU-S+fC5&)-kwC)$&lZZ z6VQvue+n3TRKVHU8G}Inb3rCA;DTik3K**Zm;dt8rFWwW*xgkFkT5 zF1XN6M)N~XK%YgxTq5ACMFpH!!nqef^5ewNN}Ad4$Yt21ceLDFR%eX+XzttvoZk~(0L034wru`2#l4Fo#K#(yffanYe z5XhfB23Y_XfdDlSbb>tpyny^Ms1xho<4=Ju|GOHYUPo2{1_WARHIQwDRDjY6I1B}7 z1tbDW8=*G8kmP??E8OoI!K?s5^B1(jfAj#UfWsvM)WADiVJ(6DCipp*Ap*SbGL#BP zNE@N|UxxCV;Cft#5wMc$@cb7TmE%sok52`7LD#|pL22Oh*Y6|de*N3gXW(9WaxW*KW)U#2kpT99 zI~UtOe3|DrK}1P{8fThc4Uqp;e@7J{WuPm7iep-Z0Mc9Q9T3PPAF~3uDXV}kfD=Hm zR2B1-=l>`Rfi>Xc3r|`CRt4H>9Rx)A3k2}&n^#>b;GtnX_kd>AQv!l55#Xq6=AsgK z3I)^@KV!Xm0c4K_DCgNmD0+ZJo1lb$d-FBWEFGmwZhbZo&xC#TD<@=S5PG2 z9hade@~{3fl)nyJ%hO+U9lrMbFRsJ?v O0000 + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.buffs; + +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.watabou.noosa.Image; +import com.watabou.utils.Bundle; + +public class Momentum extends Buff { + + private int stacks = 0; + private int turnsSinceMove = 0; + + @Override + public boolean act() { + turnsSinceMove++; + if (turnsSinceMove > 0){ + stacks = Math.max(0, stacks - turnsSinceMove); + BuffIndicator.refreshHero(); + if (stacks == 0) detach(); + } + spend(TICK); + return true; + } + + public void gainStack(){ + stacks = Math.min(stacks+1, 10); + turnsSinceMove = -1; + BuffIndicator.refreshHero(); + } + + public int stacks(){ + return stacks; + } + + public float speedMultiplier(){ + //1.33x speed at max stacks + return 1f + (stacks/30f); + } + + public int evasionBonus( int excessArmorStr ){ + //10 evasion, +2.5 evasion per excess str, at max stacks + return Math.round((1f + 0.25f*excessArmorStr) * stacks); + } + + @Override + public int icon() { + return BuffIndicator.MOMENTUM; + } + + @Override + public void tintIcon(Image icon) { + if (stacks <= 5) { + icon.hardlight(0.2f * (stacks - 1), 1f, 0f); + } else { + icon.hardlight(1f, 1f - 0.2f*(stacks - 6), 0f); + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", stacks*10); + } + + private static final String STACKS = "stacks"; + private static final String TURNS_SINCE = "turnsSinceMove"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STACKS, stacks); + bundle.put(TURNS_SINCE, turnsSinceMove); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stacks = bundle.getInt(STACKS); + turnsSinceMove = bundle.getInt(TURNS_SINCE); + } +} 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 0b2443bcb..36f6a8d9c 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 @@ -40,6 +40,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Fury; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Momentum; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SnipersMark; @@ -314,16 +315,19 @@ public class Hero extends Char { int aEnc = belongings.armor != null ? belongings.armor.STRReq() - STR() : 10 - STR(); if (aEnc > 0) { - return (int)(defenseSkill * evasion / Math.pow( 1.5, aEnc )); - } else { - - int bonus = 0; - - if (belongings.armor != null && belongings.armor.hasGlyph(Swiftness.class)) - bonus += 5 + belongings.armor.level()*1.5f; - - return Math.round((defenseSkill + bonus) * evasion); + evasion /= Math.pow( 1.5, aEnc ); } + int bonus = 0; + + if (belongings.armor != null && belongings.armor.hasGlyph(Swiftness.class)) + bonus += 5 + belongings.armor.level()*1.5f; + + Momentum momentum = buff(Momentum.class); + if (momentum != null){ + bonus += momentum.evasionBonus(Math.max(0, -aEnc)); + } + + return Math.round((defenseSkill + bonus) * evasion); } @Override @@ -381,19 +385,16 @@ public class Hero extends Char { } int aEnc = armor != null ? armor.STRReq() - STR() : 0; - if (aEnc > 0) { - - return (float)(speed / Math.pow( 1.2, aEnc )); - - } else { - - return ((HeroSprite)sprite).sprint( subClass == HeroSubClass.FREERUNNER && !isStarving() ) ? - invisible > 0 ? - 2f * speed : - 1.5f * speed : - speed; - + if (aEnc > 0) speed /= Math.pow( 1.2, aEnc ); + + Momentum momentum = buff(Momentum.class); + if (momentum != null){ + ((HeroSprite)sprite).sprint( 1f + 0.05f*momentum.stacks()); + speed *= momentum.speedMultiplier(); } + + return speed; + } public boolean canSurpriseAttack(){ @@ -1100,6 +1101,10 @@ public class Hero extends Char { spend( moveTime / speed() ); search(false); + + if (subClass == HeroSubClass.FREERUNNER){ + Buff.affect(this, Momentum.class).gainStack(); + } //FIXME this is a fairly sloppy fix for a crash involving pitfall traps. //really there should be a way for traps to specify whether action should continue or diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/HeroSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/HeroSprite.java index ceaf8f49e..1130c2cae 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/HeroSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/HeroSprite.java @@ -142,9 +142,8 @@ public class HeroSprite extends CharSprite { super.update(); } - public boolean sprint( boolean on ) { - run.delay = on ? 0.667f / RUN_FRAMERATE : 1f / RUN_FRAMERATE; - return on; + public void sprint( float speed ) { + run.delay = 1f / speed / RUN_FRAMERATE; } public static TextureFilm tiers() { 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 1695d41f7..96fc398bc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java @@ -84,6 +84,8 @@ public class BuffIndicator extends Component { public static final int RAGE = 38; public static final int SACRIFICE = 39; public static final int BERSERK = 40; + public static final int MOMENTUM = 41; + public static final int PREPARATION = 42; public static final int SIZE = 7; diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties index ee46c124c..15fce39df 100644 --- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties +++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties @@ -153,6 +153,9 @@ actors.buffs.magicalsleep.desc=This character has fallen into a deep magical sle actors.buffs.mindvision.name=Mind vision actors.buffs.mindvision.desc=Somehow you are able to see all creatures on this floor through your mind. It's a weird feeling.\n\nAll characters on this floor are visible to you as long as you have mind vision. Seeing a creature through mind vision counts as it being seen or nearby for the purposes of many magical effects.\n\nTurns of mind vision remaining: %s. +actors.buffs.momentum.name=Momentum +actors.buffs.momentum.desc=As he moves, the freerunner builds momentum, increasing his speed and ability to dodge.\n\nThe speed bonus is based purely on momentum, however the bonus to dodge is also affected by armor.\n\nThe freerunner will gain additional dodge from momentum for each excess point of strength he has over the requirements of his armor.\n\nCurrent momentum power: %d%%. + actors.buffs.ooze.name=Caustic ooze actors.buffs.ooze.heromsg=Caustic ooze eats your flesh. Wash it away! actors.buffs.ooze.ondeath=You melt away... @@ -261,7 +264,7 @@ actors.hero.herosubclass.battlemage_desc=When fighting with his staff, the _Batt actors.hero.herosubclass.assassin=assassin actors.hero.herosubclass.assassin_desc=When performing a surprise attack, the _Assassin_ inflicts additional damage to his target. actors.hero.herosubclass.freerunner=freerunner -actors.hero.herosubclass.freerunner_desc=The _Freerunner_ moves faster when he unencumbered and not starving, if he is invisible, this speed boost is increased. +actors.hero.herosubclass.freerunner_desc=The _Freerunner_ builds momentum as he runs. Momentum increases his movement speed and evasion, but it quickly fades when he isn't moving. actors.hero.herosubclass.sniper=sniper actors.hero.herosubclass.sniper_desc=The _Sniper_ is able to detect weak points in an enemy's armor, effectively ignoring it when using a missile weapon. actors.hero.herosubclass.warden=warden