From 9f9c3a2bdca4fb74b6f202dec0bdb27e7130101d Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 2 Feb 2025 15:58:39 -0500 Subject: [PATCH] v3.0.0: implemented effect selection for Trinity --- .../assets/messages/actors/actors.properties | 32 +- .../actors/hero/abilities/cleric/Trinity.java | 342 ++++++++++++++++-- .../actors/hero/spells/BodyForm.java | 5 + .../actors/hero/spells/MindForm.java | 12 +- .../actors/hero/spells/SpiritForm.java | 16 +- .../items/armor/ClassArmor.java | 6 +- .../windows/WndChooseAbility.java | 4 +- 7 files changed, 377 insertions(+), 40 deletions(-) diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index 34e3c8d34..1ae4e201d 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -547,8 +547,24 @@ actors.hero.abilities.cleric.ascendedform.desc=The Cleric projects holy energy f actors.hero.abilities.cleric.ascendedform$ascendbuff.name=ascended form actors.hero.abilities.cleric.ascendedform$ascendbuff.desc=Radiant energy is emanating from the Cleric's body. While in this form the Cleric gains 2 attack range (from the holy energy projecting from them), and 10 shielding whenever they spend a holy tome charge. They are also able to cast the spells which are unlocked via ascended form's talents.\n\nThe shield granted by ascended form and its spells will not decay normally, but will instantly fade when ascended form ends.\n\nCurrent shielding: %1$d.\nTurns remaining: %2$d. actors.hero.abilities.cleric.trinity.name=trinity -actors.hero.abilities.cleric.trinity.short_desc=_(UNFINISHED)_ The Cleric gains a _Trinity_ of abilities, which emulate equipment they have seen and can be swapped between by using new spells. -actors.hero.abilities.cleric.trinity.desc=_Trinity has not been implemented yet, and so is currently unselectable._\n\nThe Cleric gains a _Trinity_ of armor abilities, which can be swapped between by using three new spells. Each of these spells focuses on emulating the effects of equipment that the Cleric has identified during this run: Body (weapons and armor), Mind (wands and thrown weapons), and Spirit (rings and artifacts).\n\nOnly one of these effects can be active at a time, changing Trinity's form will end all active Trinity effects. +actors.hero.abilities.cleric.trinity.no_imbue=Trinity has no effect set for any of its forms currently, use one of its spells! +actors.hero.abilities.cleric.trinity.short_desc=The Cleric gains a _Trinity_ of abilities, which emulate equipment they have seen and can be assigned by using new spells. +actors.hero.abilities.cleric.trinity.desc=The Cleric gains a _Trinity_ of armor abilities, which can be assigned to various item effects by using three new spells. Each of these spells focuses on emulating the effects of different kinds of equipment that the Cleric has identified during this run: body form (weapons and armor), mind form (wands and thrown weapons), and spirit form (rings and artifacts).\n\nEach Trinity form can be imbued with one effect at a time, and the Cleric chooses which one to activate when using Trinity. Trinity will not duplicate the effect of something you already have equipped. +actors.hero.abilities.cleric.trinity$wndusetrinity.text=Select which form of Trinity to use. The effects of different forms can be active simultaneously. +actors.hero.abilities.cleric.trinity$wndusetrinity.body=_Body Form: %s._ +actors.hero.abilities.cleric.trinity$wndusetrinity.mind=_Mind Form: %s._ +actors.hero.abilities.cleric.trinity$wndusetrinity.spirit=_Spirit Form: %s._ +actors.hero.abilities.cleric.trinity$wnditemtypeselect.text=Select an effect to be imbued into Trinity. Additional info will be shown before confirmation. +actors.hero.abilities.cleric.trinity$wnditemconfirm.body=Assign to body form +actors.hero.abilities.cleric.trinity$wnditemconfirm.mind=Assign to mind form +actors.hero.abilities.cleric.trinity$wnditemconfirm.spirit=Assign to spirit form +actors.hero.abilities.cleric.trinity.ench_glyph_use=Trinity will apply this effect for _%1$d turns_ at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.rare_ench_glyph_use=Trinity will apply this _powerful_ effect for _%1$d turns_ at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.wand_use=Trinity will zap this wand at _+%1$d_ at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.thrown_use=Trinity will throw this weapon at _+%1$d_ at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.ring_use=Trinity will apply this ring's effect at _+%1$d_ for 20 turns, at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.artifact_use=Trinity will apply this artifact's effect at _+%1$d_, at the cost of _%2$s charge._ +actors.hero.abilities.cleric.trinity.cost=The charge cost of this ability varies, but is most often _%d._ actors.hero.abilities.cleric.powerofmany.name=power of many actors.hero.abilities.cleric.powerofmany.short_desc=_(UNFINISHED)_ The Cleric channels the _Power of Many_, empowering an existing ally or creating a new one. actors.hero.abilities.cleric.powerofmany.desc=_Power of Many has not been implemented yet, and so is currently unselectable._ @@ -576,7 +592,7 @@ actors.hero.spells.blessspell.desc=The Cleric places a holy blessing on themselv actors.hero.spells.bodyform.name=body form actors.hero.spells.bodyform.short_desc=Assigns Trinity to an enchant or glyph. -actors.hero.spells.bodyform.desc=The Cleric chooses an enchantment or glyph that they have identified this run and imbues Trinity with its effect.\n\nWhen Trinity is used, The Cleric gains the effect of the chosen enchantment or glyph for %d turns. This temporary enchant or glyph will work with any effect that a regular enchantment or glyph would.\n\nThis spell replaces any other effect that Trinity is currently imbued with. +actors.hero.spells.bodyform.desc=The Cleric chooses an enchantment or glyph that they have identified this run and imbues Trinity with its effect.\n\nWhen Trinity is used, The Cleric gains the effect of the chosen enchantment or glyph for %d turns. This temporary enchant or glyph will work with any effect that a regular enchantment or glyph would.\n\nThis spell replaces any other body effect that Trinity is currently imbued with. actors.hero.spells.cleanse.name=cleanse actors.hero.spells.cleanse.short_desc=Clears debuffs and grants shielding. @@ -662,7 +678,7 @@ actors.hero.spells.layonhands.desc=The Paladin channels holy energy through thei actors.hero.spells.mindform.name=mind form actors.hero.spells.mindform.short_desc=Assigns Trinity to a wand or thrown weapon. -actors.hero.spells.mindform.desc=The Cleric chooses a wand or thrown weapons that they have identified this run and imbues Trinity with its effect.\n\nWhen Trinity is used, The Cleric can make a single attack as if they were using the chosen item at +%d. This will trigger all effects that using that type of item would normally trigger.\n\nThis spell replaces any other effect that Trinity is currently imbued with. +actors.hero.spells.mindform.desc=The Cleric chooses a wand or thrown weapons that they have identified this run and imbues Trinity with its effect.\n\nWhen Trinity is used, The Cleric can make a single attack as if they were using the chosen item at +%d. This will trigger all effects that using that type of item would normally trigger.\n\nThis spell replaces any other mind effect that Trinity is currently imbued with. actors.hero.spells.mnemonicprayer.name=mnemonic prayer actors.hero.spells.mnemonicprayer.short_desc=Extends buffs/debuffs on an ally/enemy, & re-applies illuminated. @@ -686,7 +702,7 @@ actors.hero.spells.shieldoflight$shieldoflighttracker.desc=A thin shield of ligh actors.hero.spells.spiritform.name=spirit form actors.hero.spells.spiritform.short_desc=Assigns Trinity to a ring or artifact. -actors.hero.spells.spiritform.desc=The Cleric chooses a ring or artifact that they have identified this run (except the holy tome) and imbues Trinity with its effect.\n\nIf a ring is chosen, then Trinity grants that ring's effect at +%1$d for 20 turns.\n\nIf an artifact is chosen, then Trinity replicates that Artifact's effect at +%2$d. Each artifact has different specific behaviors and armor charge costs when used with Trinity.\n\nThis spell replaces any other effect that Trinity is currently imbued with. +actors.hero.spells.spiritform.desc=The Cleric chooses a ring or artifact that they have identified this run (except the holy tome) and imbues Trinity with its effect.\n\nIf a ring is chosen, then Trinity grants that ring's effect at +%1$d for 20 turns.\n\nIf an artifact is chosen, then Trinity replicates that Artifact's effect at +%2$d. Each artifact has different specific behaviors and armor charge costs when used with Trinity.\n\nThis spell replaces any other spirit effect that Trinity is currently imbued with. actors.hero.spells.smite.name=smite actors.hero.spells.smite.short_desc=Guarantees a hit with bonus damage and enchant power. @@ -1186,11 +1202,11 @@ actors.hero.talent.flash.title=flash actors.hero.talent.flash.desc=_+1:_ While in Ascended Form, the Cleric can cast _Flash_ to teleport up to _3 tiles_ away.\n\n_+2:_ While in Ascended Form, the Cleric can cast _Flash_ to teleport up to _4 tiles_ away.\n\n_+3:_ While in Ascended Form, the Cleric can cast _Flash_ to teleport up to _5 tiles_ away.\n\n_+4:_ While in Ascended Form, the Cleric can cast _Flash_ to teleport up to _6 tiles_ away.\n\nFlash costs 1 tome charge initially, and 1 more charge for each use in the same ascended form. actors.hero.talent.body_form.title=body form -actors.hero.talent.body_form.desc=The Cleric can cast _Body Form_, which causes Trinity to assume the power of an enchantment or glyph that the Cleric has identified this run, at the cost of 2 charges.\n\n_+1:_ When Trinity is used, the Cleric gains the chosen effect for _20 turns._\n\n_+2:_ When Trinity is used, the Cleric gains the chosen effect for _27 turns._\n\n_+3:_ When Trinity is used, the Cleric gains the chosen effect for _33 turns._\n\n_+4:_ When Trinity is used, the Cleric gains the chosen effect for _40 turns._\n\nTrinity's armor charge cost is higher if the chosen glyph is rare and powerful. +actors.hero.talent.body_form.desc=The Cleric can cast _Body Form_, which imbues Trinity with the power of an enchantment or glyph that the Cleric has identified this run, at the cost of 2 charges.\n\n_+1:_ When Trinity is used, the Cleric gains the chosen effect for _20 turns._\n\n_+2:_ When Trinity is used, the Cleric gains the chosen effect for _27 turns._\n\n_+3:_ When Trinity is used, the Cleric gains the chosen effect for _33 turns._\n\n_+4:_ When Trinity is used, the Cleric gains the chosen effect for _40 turns._\n\nTrinity can only be imbued with one body effect at a time. Trinity's armor charge cost is higher if the chosen glyph is rare and powerful. actors.hero.talent.mind_form.title=mind form -actors.hero.talent.mind_form.desc=The Cleric can cast _Mind Form_, which causes Trinity to assume the power of a wand or thrown weapon that the Cleric has used this run, at the cost of 3 charges.\n\n_+1:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+3._\n\n_+2:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+4._\n\n_+3:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+5._\n\n_+4:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+6._ +actors.hero.talent.mind_form.desc=The Cleric can cast _Mind Form_, which imbues Trinity with the power of a wand or thrown weapon that the Cleric has used this run, at the cost of 3 charges.\n\n_+1:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+3._\n\n_+2:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+4._\n\n_+3:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+5._\n\n_+4:_ When Trinity is used, the Cleric uses the zap or throw effect of the chosen item, as if it were _+6._\n\nTrinity can only be imbued with one mind effect at a time. actors.hero.talent.spirit_form.title=spirit form -actors.hero.talent.spirit_form.desc=The Cleric can cast _Spirit Form_, which causes Trinity to assume the power of a ring or artifact that the Cleric has identified this run (except the holy tome), at the cost of 4 charges.\n\n_+1:_ When Trinity is used, the Cleric will gain a ring's effect at _+1_ for 20 turns, or will trigger an artifact's effect at _+4._\n\n_+2:_ When Trinity is used, the Cleric will gain a ring's effect at _+2_ for 20 turns, or will trigger an artifact's effect at _+6._\n\n_+3:_ When Trinity is used, the Cleric will gain a ring's effect at _+3_ for 20 turns, or will trigger an artifact's effect at _+8._\n\n_+4:_ When Trinity is used, the Cleric will gain a ring's effect at _+4_ for 20 turns, or will trigger an artifact's effect at _+10._\n\nSome artifacts have different effects or armor charge costs when triggered by Trinity. +actors.hero.talent.spirit_form.desc=The Cleric can cast _Spirit Form_, which imbues Trinity with the power of a ring or artifact that the Cleric has identified this run (except the holy tome), at the cost of 4 charges.\n\n_+1:_ When Trinity is used, the Cleric will gain a ring's effect at _+1_ for 20 turns, or will trigger an artifact's effect at _+4._\n\n_+2:_ When Trinity is used, the Cleric will gain a ring's effect at _+2_ for 20 turns, or will trigger an artifact's effect at _+6._\n\n_+3:_ When Trinity is used, the Cleric will gain a ring's effect at _+3_ for 20 turns, or will trigger an artifact's effect at _+8._\n\n_+4:_ When Trinity is used, the Cleric will gain a ring's effect at _+4_ for 20 turns, or will trigger an artifact's effect at _+10._\n\nTrinity can only be imbued with one spirit effect at a time. Artifacts have varied effects and armor charge costs when triggered by Trinity. actors.hero.talent.cleric_a3_1.title=Unknown actors.hero.talent.cleric_a3_1.desc=This talent hasn't been implemented yet, it currently does nothing. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/cleric/Trinity.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/cleric/Trinity.java index 5341411d3..e32dd2e8f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/cleric/Trinity.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/abilities/cleric/Trinity.java @@ -21,13 +21,45 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.cleric; +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.Statistics; 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.hero.spells.BodyForm; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.ClericSpell; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.MindForm; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.SpiritForm; +import com.shatteredpixel.shatteredpixeldungeon.effects.Enchanting; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome; +import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.WornShortsword; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; +import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; +import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; +import com.watabou.utils.Reflection; + +import java.util.ArrayList; public class Trinity extends ArmorAbility { @@ -35,40 +67,119 @@ public class Trinity extends ArmorAbility { baseChargeUse = 25; } - private Class form = null; - - @Override - public String targetingPrompt() { - //TODO varies based on form? Or just directly jump into item logic? - return super.targetingPrompt(); - } + private Bundlable bodyForm = null; + private Bundlable mindForm = null; + private Bundlable spiritForm = null; @Override protected void activate(ClassArmor armor, Hero hero, Integer target) { - //always happens atm - if (form == null){ - GLog.w("Trinity has no form currently, use one of its spells!"); + if (bodyForm == null && mindForm == null && spiritForm == null){ + GLog.w(Messages.get(this, "no_imbue")); + } else { + GameScene.show(new WndUseTrinity()); } } - private static final String FORM = "form"; + public class WndUseTrinity extends WndTitledMessage { + + public WndUseTrinity() { + super(new HeroIcon(Trinity.this), + Messages.titleCase(Trinity.this.name()), + Messages.get(WndUseTrinity.class, "text")); + + int top = height; + + if (bodyForm != null){ + RedButton btnBody = null; + if (bodyForm instanceof Weapon.Enchantment){ + + btnBody = new RedButton(Messages.get(WndUseTrinity.class, "body", + Messages.titleCase(((Weapon.Enchantment)bodyForm).name())) + + " " + trinityItemUseText(bodyForm.getClass()), 6){ + @Override + protected void onClick() { + //TODO + } + }; + btnBody.icon(new ItemSprite(ItemSpriteSheet.WORN_SHORTSWORD, ((Weapon.Enchantment) bodyForm).glowing())); + } else if (bodyForm instanceof Armor.Glyph){ + btnBody = new RedButton(Messages.get(WndUseTrinity.class, "body", + Messages.titleCase(((Armor.Glyph)bodyForm).name())) + + " " + trinityItemUseText(bodyForm.getClass()), 6){ + @Override + protected void onClick() { + //TODO + } + }; + btnBody.icon(new ItemSprite(ItemSpriteSheet.ARMOR_CLOTH, ((Armor.Glyph) bodyForm).glowing())); + } + btnBody.multiline = true; + btnBody.setSize(width, 100); //for text layout + btnBody.setRect(0, top + 2, width, btnBody.reqHeight()); + add(btnBody); + top = (int)btnBody.bottom(); + } + + if (mindForm != null){ + RedButton btnMind = new RedButton(Messages.get(WndUseTrinity.class, "mind", + Messages.titleCase(((Item)mindForm).name())) + + " " + trinityItemUseText(mindForm.getClass()), 6){ + @Override + protected void onClick() { + //TODO + } + }; + btnMind.icon(new ItemSprite((Item)mindForm)); + btnMind.multiline = true; + btnMind.setSize(width, 100); //for text layout + btnMind.setRect(0, top + 2, width, btnMind.reqHeight()); + add(btnMind); + top = (int)btnMind.bottom(); + } + + if (spiritForm != null){ + RedButton btnSpirit = new RedButton(Messages.get(WndUseTrinity.class, "spirit", + Messages.titleCase(((Item)spiritForm).name())) + + " " + trinityItemUseText(spiritForm.getClass()), 6){ + @Override + protected void onClick() { + //TODO + } + }; + btnSpirit.icon(new ItemSprite((Item)spiritForm)); + btnSpirit.multiline = true; + btnSpirit.setSize(width, 100); //for text layout + btnSpirit.setRect(0, top + 2, width, btnSpirit.reqHeight()); + add(btnSpirit); + top = (int)btnSpirit.bottom(); + } + + resize(width, top); - @Override - public void restoreFromBundle(Bundle bundle) { - super.restoreFromBundle(bundle); - if (form != null){ - bundle.put(FORM, form); } + } + private static final String BODY = "body_form"; + private static final String MIND = "mind_form"; + private static final String SPIRIT = "spirit_form"; + @Override public void storeInBundle(Bundle bundle) { super.storeInBundle(bundle); - if (bundle.contains(FORM)){ - form = bundle.getClass(FORM); - } + if (bodyForm != null) bundle.put(BODY, bodyForm); + if (mindForm != null) bundle.put(MIND, mindForm); + if (spiritForm != null) bundle.put(SPIRIT, spiritForm); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(BODY)) bodyForm = bundle.get(BODY); + if (bundle.contains(MIND)) mindForm = bundle.get(MIND); + if (bundle.contains(SPIRIT))spiritForm = bundle.get(SPIRIT); } @Override @@ -76,15 +187,196 @@ public class Trinity extends ArmorAbility { return HeroIcon.TRINITY; } - @Override - public String desc() { - //TODO a lot of variance here based on form probably. - return super.desc(); - } - @Override public Talent[] talents() { return new Talent[]{Talent.BODY_FORM, Talent.MIND_FORM, Talent.SPIRIT_FORM, Talent.HEROIC_ENERGY}; } + public static class WndItemtypeSelect extends WndTitledMessage { + + //probably want a callback here? + public WndItemtypeSelect(HolyTome tome, ClericSpell spell) { + super(new HeroIcon(spell), Messages.titleCase(spell.name()), Messages.get(WndItemtypeSelect.class, "text")); + + //start by filtering and sorting + ArrayList> discoveredClasses = new ArrayList<>(); + if (spell == BodyForm.INSTANCE) { + for (Class cls : Catalog.ENCHANTMENTS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + } + for (Class cls : Catalog.GLYPHS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + } + } else if (spell == MindForm.INSTANCE){ + for (Class cls : Catalog.WANDS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + } + for (Class cls : Catalog.THROWN_WEAPONS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + } + } else if (spell == SpiritForm.INSTANCE){ + for (Class cls : Catalog.RINGS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + } + for (Class cls : Catalog.ARTIFACTS.items()) { + if (Statistics.itemTypesDiscovered.contains(cls)) { + discoveredClasses.add(cls); + } + //no tome specifically + discoveredClasses.remove(HolyTome.class); + } + } + + ArrayList options = new ArrayList<>(); + for (Class cls : discoveredClasses){ + if (Weapon.Enchantment.class.isAssignableFrom(cls)){ + MeleeWeapon w = new WornShortsword(); + w.enchant((Weapon.Enchantment) Reflection.newInstance(cls)); + options.add(w); + } else if (Armor.Glyph.class.isAssignableFrom(cls)) { + Armor a = new ClothArmor(); + a.inscribe((Armor.Glyph) Reflection.newInstance(cls)); + options.add(a); + } else { + options.add((Item) Reflection.newInstance(cls)); + } + } + + int top = height + 2; + int left = 0; + + for (Item item : options){ + RedButton btn = new RedButton(""){ + @Override + protected void onClick() { + GameScene.show(new WndItemConfirm(WndItemtypeSelect.this, item, tome, spell)); + } + }; + btn.icon(new ItemSprite(item)); + btn.setRect(left, top, 19, 19); + add(btn); + + left += 20; + if (left >= width - 19){ + top += 20; + left = 0; + } + } + + if (left > 0){ + top += 20; + left = 0; + } + + resize(width, top); + + } + + } + + public static class WndItemConfirm extends WndTitledMessage { + + public WndItemConfirm(Window parentWnd, Item item, HolyTome tome, ClericSpell spell){ + super(new ItemSprite(item), Messages.titleCase(getName(item)), getText(item)); + + String text; + if (spell == BodyForm.INSTANCE){ + text = Messages.get(this, "body"); + } else if (spell == MindForm.INSTANCE){ + text = Messages.get(this, "mind"); + } else { + text = Messages.get(this, "spirit"); + } + + RedButton btnConfirm = new RedButton(text){ + @Override + protected void onClick() { + parentWnd.hide(); + WndItemConfirm.this.hide(); + + if (item instanceof MeleeWeapon) { + ((Trinity)Dungeon.hero.armorAbility).bodyForm = ((MeleeWeapon) item).enchantment; + } else if (item instanceof Armor) { + ((Trinity)Dungeon.hero.armorAbility).bodyForm = ((Armor) item).glyph; + } else if (item instanceof Wand || item instanceof MissileWeapon){ + ((Trinity)Dungeon.hero.armorAbility).mindForm = item; + } else { + ((Trinity)Dungeon.hero.armorAbility).spiritForm = item; + } + spell.onSpellCast(tome, Dungeon.hero); + + Dungeon.hero.sprite.operate(Dungeon.hero.pos); + Enchanting.show(Dungeon.hero, item); + Sample.INSTANCE.play(Assets.Sounds.TELEPORT); + } + }; + btnConfirm.setRect(0, height+2, width, 16); + add(btnConfirm); + + resize(width, (int)btnConfirm.bottom()); + + } + + private static String getName(Item item){ + if (item instanceof MeleeWeapon){ + return ((MeleeWeapon) item).enchantment.name(); + } else if (item instanceof Armor){ + return (((Armor) item).glyph.name()); + } + return item.name(); + } + + private static String getText(Item item){ + if (item instanceof MeleeWeapon){ + return ((MeleeWeapon) item).enchantment.desc() + "\n\n" + trinityItemUseText(((MeleeWeapon) item).enchantment.getClass()); + } else if (item instanceof Armor){ + return ((Armor) item).glyph.desc() + "\n\n" + trinityItemUseText(((Armor) item).glyph.getClass()); + } else { + return item.desc() + "\n\n" + trinityItemUseText(item.getClass()); + } + } + + } + + public static String trinityItemUseText(Class cls ){ + float chargeUse = Dungeon.hero.armorAbility.chargeUse(Dungeon.hero); + if (Weapon.Enchantment.class.isAssignableFrom(cls) || Armor.Glyph.class.isAssignableFrom(cls)) { + for (Class ench : Weapon.Enchantment.rare) { + if (ench.equals(cls)) { + return Messages.get(Trinity.class, "rare_ench_glyph_use", BodyForm.duration(), Messages.decimalFormat("#.##", 2*chargeUse)); + } + } + for (Class glyph : Armor.Glyph.rare){ + if (glyph.equals(cls)){ + return Messages.get(Trinity.class, "rare_ench_glyph_use", BodyForm.duration(), Messages.decimalFormat("#.##", 2*chargeUse)); + } + } + return Messages.get(Trinity.class, "ench_glyph_use", BodyForm.duration(), Messages.decimalFormat("#.##", chargeUse)); + } + if (MissileWeapon.class.isAssignableFrom(cls)){ + return Messages.get(Trinity.class, "thrown_use", MindForm.itemLevel(), Messages.decimalFormat("#.##", chargeUse)); + } + if (Wand.class.isAssignableFrom(cls)){ + return Messages.get(Trinity.class, "wand_use", MindForm.itemLevel(), Messages.decimalFormat("#.##", chargeUse)); + } + if (Ring.class.isAssignableFrom(cls)){ + return Messages.get(Trinity.class, "ring_use", SpiritForm.ringLevel(), Messages.decimalFormat("#.##", chargeUse)); + } + if (Artifact.class.isAssignableFrom(cls)){ + return Messages.get(Trinity.class, "artifact_use", SpiritForm.artifactLevel(), Messages.decimalFormat("#.##", chargeUse)); + } + return "error!"; + + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/BodyForm.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/BodyForm.java index 8ea6432e9..e051cf329 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/BodyForm.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/BodyForm.java @@ -21,6 +21,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.cleric.Trinity; @@ -54,4 +55,8 @@ public class BodyForm extends ClericSpell { } + public static int duration(){ + return Math.round(13.33f + 6.67f* Dungeon.hero.pointsInTalent(Talent.BODY_FORM)); + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/MindForm.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/MindForm.java index e16b02f3e..168132b10 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/MindForm.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/MindForm.java @@ -21,11 +21,13 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.cleric.Trinity; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; -import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; public class MindForm extends ClericSpell { @@ -48,7 +50,13 @@ public class MindForm extends ClericSpell { @Override public void onCast(HolyTome tome, Hero hero) { - GLog.w("not implemented yet!"); + + GameScene.show(new Trinity.WndItemtypeSelect(tome, this)); + + } + + public static int itemLevel(){ + return 2 + Dungeon.hero.pointsInTalent(Talent.MIND_FORM); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/SpiritForm.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/SpiritForm.java index 59aac29a2..26ceee5e7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/SpiritForm.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/spells/SpiritForm.java @@ -21,11 +21,13 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.cleric.Trinity; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; -import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; public class SpiritForm extends ClericSpell { @@ -48,7 +50,17 @@ public class SpiritForm extends ClericSpell { @Override public void onCast(HolyTome tome, Hero hero) { - GLog.w("not implemented yet!"); + + GameScene.show(new Trinity.WndItemtypeSelect(tome, this)); + + } + + public static int ringLevel(){ + return Dungeon.hero.pointsInTalent(Talent.MIND_FORM); + } + + public static int artifactLevel(){ + return 2 + 2*Dungeon.hero.pointsInTalent(Talent.MIND_FORM); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java index f15adcbff..871bcaa23 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java @@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.cleric.Trinity; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy; @@ -300,7 +301,10 @@ abstract public class ClassArmor extends Armor { if (ability != null) { desc += "\n\n" + ability.shortDesc(); float chargeUse = ability.chargeUse(Dungeon.hero); - desc += " " + Messages.get(this, "charge_use", Messages.decimalFormat("#.##", chargeUse)); + //trinity has variable charge cost + if (!(ability instanceof Trinity)) { + desc += " " + Messages.get(this, "charge_use", Messages.decimalFormat("#.##", chargeUse)); + } } else { desc += "\n\n" + "_" + Messages.get(this, "no_ability") + "_"; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndChooseAbility.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndChooseAbility.java index 3381dfa62..a95094941 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndChooseAbility.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndChooseAbility.java @@ -104,8 +104,8 @@ public class WndChooseAbility extends Window { abilityButton.setRect(0, pos, WIDTH-20, abilityButton.reqHeight()+2); add(abilityButton); - //TODO CLERIC these abilities aren't playable atm - if (!DeviceCompat.isDebug() && (ability instanceof Trinity || ability instanceof PowerOfMany)){ + //TODO CLERIC power of many isn't playable atm + if (!DeviceCompat.isDebug() && ability instanceof PowerOfMany){ abilityButton.enable(false); }