From d5bb26b84064ce6c5fa1101750668f8bf9f118f0 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 4 Nov 2024 11:46:18 -0500 Subject: [PATCH] v3.0.0: implemented the recall glyph talent/spell for scrolls only --- core/src/main/assets/interfaces/buffs.png | Bin 1789 -> 1802 bytes .../src/main/assets/interfaces/hero_icons.png | Bin 2228 -> 2275 bytes .../main/assets/interfaces/large_buffs.png | Bin 3994 -> 3997 bytes .../assets/messages/actors/actors.properties | 12 +- .../actors/hero/Talent.java | 13 +- .../actors/hero/spells/ClericSpell.java | 8 + .../actors/hero/spells/RecallGlyph.java | 151 ++++++++++++++++++ .../shatteredpixeldungeon/items/Item.java | 5 + .../items/artifacts/HolyTome.java | 2 +- .../items/scrolls/Scroll.java | 2 +- .../items/spells/Alchemize.java | 2 +- .../items/spells/BeaconOfReturning.java | 2 +- .../items/spells/InventorySpell.java | 2 +- .../items/spells/MagicalInfusion.java | 2 +- .../items/spells/SummonElemental.java | 2 +- .../items/spells/TargetedSpell.java | 2 +- .../items/spells/UnstableSpell.java | 2 +- .../ui/BuffIndicator.java | 1 + .../shatteredpixeldungeon/ui/HeroIcon.java | 1 + 19 files changed, 194 insertions(+), 15 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/RecallGlyph.java diff --git a/core/src/main/assets/interfaces/buffs.png b/core/src/main/assets/interfaces/buffs.png index 02024face4e3933e6279b16ea03efe7a30f058f7..0c37331ced8a16f81f6e24dc2f512a9e5489f451 100644 GIT binary patch delta 1444 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 E0QUl@D*ylh delta 1935 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 DWxbC` delta 3684 zcmXw4c{o%J7r*z;3^QizrXk)jcA-ovsW6u*MGL7Y>qy&MMAU1adxuJCQ!0uYT2+cx zWSOfJ$(9NwjJ1U{B4)T|KJWKE-+7+%obCCYf6n=xbH(toVUZt*Si7%u*&GY*sCfle z!!+(Y4vqR<^cjutzPd4;xC2}T)0>G0K`u;ZlWayC{jt@UFXjo;)7ROX;i1fri{Ce} zKdyVcF5jpt+_{I$*u7KWwU9>KxZ^(cC0s@euZ7u-W938Ekk0YR^PpZGRYGV~Qp*(le5*cu#{0ea$$(Z=#<~Kz)ja zA`^-~Lv*M-ptO0*Atw*4%+rl;PP8GHlfmKlC_Oa$dKr2sjlXMOhw`GuM!d{()Yya- zid&yDAwNdsH&-|&7r2&?(dTa?*js+u-Rm^3mjfX)S+sN^Mpf|=LN>{McyxP7%CPX8 z>|)6 z6!@J9O&9^g{HIp$=xvxT6Ot>lT7@ zot3!2!;<`kflz&{3*h`Un`JE&rCXqB#a;AqcQjTD{s26L1EBBby7)3B#fBhW>V%<@IY0x#R_>q;dFO!w!R=pA zSh5dd0msvoAX8iJd#U0{X5Lmf`$1J_9~FE(Pzcn^9Wg`ca+^bTriCwwu|q?V+tkk6 z(PQN#ALwR*lE*gc`A1C4ohA}|CTWpZoe%o!aYe)AC(8Lp`j$Iwz3TX|T(cgG#thiX z|1-gVEzNp)aak_5hQ>}_##75mK?>A|5az4Tt1mDhn-!cY_X^5xye z>*DTOXzO1sz&Zp92nveNZ&%#yg;XMc{#|6`Wr5-m`*#$c1(cO_kRlOOg3c`291ltg z*9817sz#DvFuiH13qNkxiw~W(wVk}8 zsdMJ2U1BC6rIsO!`q#o!I_-0UppM?ZfqJ8Q#TgR$zqN!hPB$@Foo67<+mLvtt%d+f zn(V9EE@I~xqMDnFF^W7aSvm=cJ<%<1hR!lml$(R0*K1)CQ@2k`T5GPme_-s>!aWC= z`yfS_c0qtIB2nToZC!()>wi4xomu| z{Je%_hWi}Cij$2JS(&b4UvpnC^jA4P^* zq2FwAT5!g5$lHk$O0Jrx0(3nD#!LVLnJrSaDN+3JCN$I+jvN3J#OV;C;?W6^KEG*pr)ZoJf;cH7?l-4*hQ;gPO+p>rW zZ*xf{_rYnXWos)M_cm8rd>$p996l`71_~jEZ?-AqS@pY~4Cs3;f6Hqp%LX$Oyp_Sz z#9Yf!WYBHTdmos7^%4?q(jN|cqLML$N>=K1%NNln;`TWGvJqQdDW>nD#nO+_cgWqr zw57?~P?yz(+5KO4h2-iec~iWc7A{uINi`CB+n`vtX0wyp?dnd2wLz-7$fzrtw8{L$t2k{@WyDNRw|ccu@yI=qk57jl-z+KKTX(g{Q2Kb9t~5SZG;_=R zYv-qJA)<wWLh{Xjz#bV5pBzub}9*I$q>z!na68rQxKLp@E=> zwYU$dIfLM%8M5nO&_fGx42=j%CP`lSxVY_JD28`e2}!iI#Qx<5#KlCylM%Dt(4BW> ztJg!<3RMGUDWm0exRt>31C(rXX{h=SSe^ycCWT9*?GRVEG3rv#Y3@$mFxB$*PaUaQ zu9I!>b`0lK{ix>jOqxpf*5Y$e5TWj&V)Wda8vtMF%0)x)4HPw>>_oXZX)*=feZS+S zEtt+AWPSqhW0v^7n{(22=D2)>)&3>Rd=Y7OOz77r=6#tad~vS^976a^=kWvm{=3mp zVv9Qx6ZDxTyT9Oxh98!oM~0l6Q@ZC4lG&VhI_cNl&H|m&6^P)WEr!?6cJl@GSea?E zp)Ej|7O~(7d60$nXYM5x9IMLSg5jM;VwrIKD5}iiqODi<;=c+7-4GiENb^)fux?Oy3or=UNJqc!;Lk-P+n{pitbmf4DLH7zzmnVYQa;Gfz*(Z{yqBgl==#n zLxH%Y=9C5`ws=l@`$*3N7(zk;6Ed03#yImZ3RDhdAxF`eK#)n8!y|D1X@tnNxS5Vo zc1Y%8IN+FU=sufa)prbNA?Hev&@}V{ssFj{rFkeR*A`t?WEuj4`G%HdsYb{V17`3E z!KIpzBYG0Ws6!%7>K&6(IT3aTy7+F#-D@AXCvpjSW}bZh;?YC{ZHo&@XRlfx6t}8g zpR`*k{o`FmrF0DUT-$LWdh|oR7F$a_N4K2)&I6;;ZhUb;!FZ@-8fo&93~PeZXTw2B zcXy%9i}^j_J#`t{UmA2^_++46%MWAFj>V^-icM3dhp(c)j(7hvW#CQRlRXPCVO{@1 zU2|U+=O62V3LEIy3}f6&ngUjyQqhQ0W0okcK2sxMBmelpDv&t1>KDSEX@J;X-7#a+ zc57kf%S}W62;t;e8-O732k6ZVjK%}YnuIa3(E)1P6B9=~_B zNdpEy;JJg(RHj!`FaX~MuQ=|s`$owfB3s#UNCicL-2|M?*a1+299qFe37n$Jm3$%( zkQ=jRZ{{K&)tIYmT#x#g!k<3kKkSkl3XyM@z6E~9li*+gFIQT^_C;muoqxRhT?XkY z>Iq~3@rHXc(Z6ur_Mec5_$9l0+l8s7I|^s9$O4d80@6PQpsk~Fc@ZEj+)_+Cagz(tCPh0>G!hk_SL$-5V~}ku#!!3az1DE7oDpIOgz%@sL5Q6Jl z`M^3FyJt3;S4AqoTlb~MFS=wz&w|gWL|XG#E2(faIi%)0Kuf*A?e?+|y~CWjUdEhd zF+Ue+wUbMstDY*c?dq3=Yf#y7H cls ){ if (hero.hasTalent(INSCRIBED_POWER)){ // 2/3 empowered wand zaps Buff.affect(hero, ScrollEmpower.class).reset((int) (factor * (1 + hero.pointsInTalent(INSCRIBED_POWER)))); @@ -698,6 +700,11 @@ public enum Talent { Buff.affect(hero, Invisibility.class, factor * (1 + 2*hero.pointsInTalent(INSCRIBED_STEALTH))); Sample.INSTANCE.play( Assets.Sounds.MELD ); } + if (hero.heroClass == HeroClass.CLERIC + && hero.hasTalent(RECALL_GLYPH) + && Scroll.class.isAssignableFrom(cls)){ + Buff.affect(hero, RecallGlyph.UsedGlyphTracker.class, hero.pointsInTalent(RECALL_GLYPH) == 2 ? 300 : 10).item = cls; + } } public static void onUpgradeScrollUsed( Hero hero ){ @@ -915,7 +922,7 @@ public enum Talent { Collections.addAll(tierTalents, FOCUSED_MEAL, LIQUID_AGILITY, WEAPON_RECHARGING, LETHAL_HASTE, SWIFT_EQUIP); break; case CLERIC: - Collections.addAll(tierTalents, ENLIGHTENING_MEAL, CLERICT2B, SUNRAY, DIVINE_SENSE, CLERICT2E); + Collections.addAll(tierTalents, ENLIGHTENING_MEAL, RECALL_GLYPH, SUNRAY, DIVINE_SENSE, CLERICT2E); break; } for (Talent talent : tierTalents){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/ClericSpell.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/ClericSpell.java index 18e46b475..12b909286 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/ClericSpell.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/ClericSpell.java @@ -41,6 +41,10 @@ public abstract class ClericSpell { return 1; } + public boolean canCast( Hero hero ){ + return true; + } + public String name(){ return Messages.get(this, "name"); } @@ -89,6 +93,10 @@ public abstract class ClericSpell { spells.add(Sunray.INSTANCE); } + if (cleric.hasTalent(Talent.RECALL_GLYPH)){ + spells.add(RecallGlyph.INSTANCE); + } + if (cleric.hasTalent(Talent.DIVINE_SENSE)) { spells.add(DivineSense.INSTANCE); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/RecallGlyph.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/RecallGlyph.java new file mode 100644 index 000000000..1d7c57774 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/RecallGlyph.java @@ -0,0 +1,151 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2024 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.spells; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +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.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfEnchantment; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfMetamorphosis; +import com.shatteredpixel.shatteredpixeldungeon.items.stones.Runestone; +import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAugmentation; +import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; +import com.watabou.utils.Bundle; +import com.watabou.utils.Reflection; + +public class RecallGlyph extends ClericSpell { + + public static RecallGlyph INSTANCE = new RecallGlyph(); + + @Override + public int icon() { + return HeroIcon.RECALL_GLYPH; + } + + @Override + public String desc() { + return Messages.get(this, "desc", Dungeon.hero.pointsInTalent(Talent.RECALL_GLYPH) == 2 ? 300 : 10) + "\n\n" + Messages.get(this, "charge_cost", (int)chargeUse(Dungeon.hero)); + } + + @Override + public void onCast(HolyTome tome, Hero hero) { + + if (hero.buff(UsedGlyphTracker.class) == null){ + return; + } + + Item item = Reflection.newInstance(hero.buff(UsedGlyphTracker.class).item); + + item.setCurrent(hero); + + //TODO runestones + if (item instanceof Scroll){ + ((Scroll) item).anonymize(); + ((Scroll) item).doRead(); + } + + onSpellCast(tome, hero); + hero.buff(UsedGlyphTracker.class).detach(); + + } + + @Override + public float chargeUse(Hero hero) { + if (hero.buff(UsedGlyphTracker.class) != null){ + Class item = hero.buff(UsedGlyphTracker.class).item; + if (ExoticScroll.class.isAssignableFrom(item)){ + if (item == ScrollOfMetamorphosis.class || item == ScrollOfEnchantment.class){ + return 6; + } else { + return 3; + } + } else if (Scroll.class.isAssignableFrom(item)){ + if (item == ScrollOfTransmutation.class){ + return 4; + } else { + return 2; + } + } else if (Runestone.class.isAssignableFrom(item)){ + if (item == StoneOfAugmentation.class || item == StoneOfEnchantment.class){ + return 2; + } else { + return 1; + } + } + } + return 0; + } + + @Override + public boolean canCast(Hero hero) { + return hero.buff(UsedGlyphTracker.class) != null; + } + + public static class UsedGlyphTracker extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + public Class item; + + @Override + public int icon() { + return BuffIndicator.GLYPH_RECALL; + } + + @Override + public float iconFadePercent() { + float duration = Dungeon.hero.pointsInTalent(Talent.RECALL_GLYPH) == 2 ? 300 : 10; + return Math.max(0, (duration - visualcooldown()) / duration); + } + + @Override + public String desc() { + return Messages.get(this, "desc", Messages.titleCase(Reflection.newInstance(item).name()), dispTurns()); + } + + private static String ITEM = "item"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ITEM, item); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + item = bundle.getClass(ITEM); + } + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Item.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Item.java index 621a2b620..3e82f0fc8 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Item.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Item.java @@ -687,6 +687,11 @@ public class Item implements Bundlable { protected static Hero curUser = null; protected static Item curItem = null; + public void setCurrent( Hero hero ){ + curUser = hero; + curItem = this; + } + protected static CellSelector.Listener thrower = new CellSelector.Listener() { @Override public void onSelect( Integer target ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java index 7271b2f78..73a5f7048 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java @@ -87,7 +87,7 @@ public class HolyTome extends Artifact { } public boolean canCast( Hero hero, ClericSpell spell ){ - return (charge >= spell.chargeUse(hero)); + return (charge >= spell.chargeUse(hero) && spell.canCast(hero)); } public void spendCharge( float chargesSpent ){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/Scroll.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/Scroll.java index 972ddbc6b..55ff9dcf6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/Scroll.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/Scroll.java @@ -201,7 +201,7 @@ public abstract class Scroll extends Item { if (!anonymous) { Catalog.countUse(getClass()); if (Random.Float() < talentChance) { - Talent.onScrollUsed(curUser, curUser.pos, talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, talentFactor, getClass()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/Alchemize.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/Alchemize.java index 3423bb88d..318419b41 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/Alchemize.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/Alchemize.java @@ -261,7 +261,7 @@ public class Alchemize extends Spell { } Catalog.countUse(getClass()); if (curItem instanceof Alchemize && Random.Float() < ((Alchemize)curItem).talentChance){ - Talent.onScrollUsed(curUser, curUser.pos, ((Alchemize) curItem).talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, ((Alchemize) curItem).talentFactor, curItem.getClass()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/BeaconOfReturning.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/BeaconOfReturning.java index f51abece0..0f119ef86 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/BeaconOfReturning.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/BeaconOfReturning.java @@ -176,7 +176,7 @@ public class BeaconOfReturning extends Spell { detach(hero.belongings.backpack); Catalog.countUse(getClass()); if (Random.Float() < talentChance){ - Talent.onScrollUsed(curUser, curUser.pos, talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, talentFactor, getClass()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/InventorySpell.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/InventorySpell.java index 120373823..d21be8452 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/InventorySpell.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/InventorySpell.java @@ -98,7 +98,7 @@ public abstract class InventorySpell extends Spell { Catalog.countUse(curItem.getClass()); if (Random.Float() < ((Spell) curItem).talentChance) { - Talent.onScrollUsed(curUser, curUser.pos, ((Spell) curItem).talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, ((Spell) curItem).talentFactor, curItem.getClass()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/MagicalInfusion.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/MagicalInfusion.java index e2eff968f..5257496a4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/MagicalInfusion.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/MagicalInfusion.java @@ -78,7 +78,7 @@ public class MagicalInfusion extends InventorySpell { Catalog.countUse(curItem.getClass()); if (Random.Float() < ((Spell) curItem).talentChance) { - Talent.onScrollUsed(curUser, curUser.pos, ((Spell) curItem).talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, ((Spell) curItem).talentFactor, getClass()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java index 9933817c9..8c4950fcd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java @@ -123,7 +123,7 @@ public class SummonElemental extends Spell { detach(Dungeon.hero.belongings.backpack); Catalog.countUse(getClass()); if (Random.Float() < talentChance){ - Talent.onScrollUsed(curUser, curUser.pos, talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, talentFactor, getClass()); } } else { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/TargetedSpell.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/TargetedSpell.java index a3783649b..53a7a7fce 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/TargetedSpell.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/TargetedSpell.java @@ -95,7 +95,7 @@ public abstract class TargetedSpell extends Spell { curUser.spendAndNext( 1f ); Catalog.countUse(curSpell.getClass()); if (Random.Float() < curSpell.talentChance){ - Talent.onScrollUsed(curUser, curUser.pos, curSpell.talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, curSpell.talentFactor, curSpell.getClass()); } } }); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/UnstableSpell.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/UnstableSpell.java index dae483050..5b25fc174 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/UnstableSpell.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/UnstableSpell.java @@ -115,7 +115,7 @@ public class UnstableSpell extends Spell { Catalog.countUse(getClass()); if (Random.Float() < talentChance){ - Talent.onScrollUsed(curUser, curUser.pos, talentFactor); + Talent.onScrollUsed(curUser, curUser.pos, talentFactor, getClass()); } } 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 b5788f53a..5cd06f32c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java @@ -127,6 +127,7 @@ public class BuffIndicator extends Component { public static final int SPELL_FOOD = 75; public static final int LIGHT_SHIELD= 76; public static final int HOLY_SIGHT = 77; + public static final int GLYPH_RECALL= 78; 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 b4e5d7bc7..abafcddf2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/HeroIcon.java @@ -75,6 +75,7 @@ public class HeroIcon extends Image { public static final int DETECT_CURSE = 44; public static final int SUNRAY = 45; public static final int DIVINE_SENSE = 46; + public static final int RECALL_GLYPH = 47; //action indicator visuals public static final int BERSERK = 80;