From 0bd8395d046977d108c11413ee15377db5d80f6b Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Wed, 5 Feb 2025 14:13:45 -0500 Subject: [PATCH] v3.0.0: Implemented Trinity mind form for wands --- .../assets/messages/actors/actors.properties | 1 + .../actors/hero/abilities/cleric/Trinity.java | 40 ++++++- .../actors/hero/spells/MindForm.java | 106 ++++++++++++++++++ .../items/wands/Wand.java | 2 +- 4 files changed, 144 insertions(+), 5 deletions(-) diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index c3acd81f1..45f945f63 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -552,6 +552,7 @@ actors.hero.abilities.cleric.trinity.no_duplicate=Trinity cannot duplicate an ef 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.wand_multi_use=Trinity will zap this _multi-charge_ 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._ 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 dfa7183a9..1c2a7067e 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 @@ -24,6 +24,7 @@ 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.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; @@ -42,6 +43,8 @@ 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.wands.WandOfFireblast; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.WornShortsword; @@ -52,6 +55,7 @@ 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.QuickSlotButton; import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; @@ -84,6 +88,14 @@ public class Trinity extends ArmorAbility { } + @Override + public int targetedPos(Char user, int dst) { + if (mindForm != null){ + return ((Item)mindForm).targetingPos((Hero)user, dst); + } + return super.targetedPos(user, dst); + } + public class WndUseTrinity extends WndTitledMessage { public WndUseTrinity(ClassArmor armor) { @@ -107,7 +119,7 @@ public class Trinity extends ArmorAbility { GLog.w(Messages.get(Trinity.class, "no_duplicate")); hide(); } else { - Buff.affect(Dungeon.hero, BodyForm.BodyFormBuff.class, BodyForm.duration()).setEffect(bodyForm); + Buff.prolong(Dungeon.hero, BodyForm.BodyFormBuff.class, BodyForm.duration()).setEffect(bodyForm); Sample.INSTANCE.play(Assets.Sounds.TELEPORT); Weapon w = new WornShortsword(); if (Dungeon.hero.belongings.weapon() != null) { @@ -140,7 +152,7 @@ public class Trinity extends ArmorAbility { GLog.w(Messages.get(Trinity.class, "no_duplicate")); hide(); } else { - Buff.affect(Dungeon.hero, BodyForm.BodyFormBuff.class, BodyForm.duration()).setEffect(bodyForm); + Buff.prolong(Dungeon.hero, BodyForm.BodyFormBuff.class, BodyForm.duration()).setEffect(bodyForm); Sample.INSTANCE.play(Assets.Sounds.TELEPORT); Armor a = new ClothArmor(); if (Dungeon.hero.belongings.armor() != null) { @@ -178,7 +190,17 @@ public class Trinity extends ArmorAbility { + " " + trinityItemUseText(mindForm.getClass()), 6){ @Override protected void onClick() { - //TODO + hide(); + MindForm.targetSelector mindEffect = new MindForm.targetSelector(); + mindEffect.setEffect(mindForm); + GameScene.selectCell(mindEffect); + Sample.INSTANCE.play(Assets.Sounds.TELEPORT); + Enchanting.show(Dungeon.hero, (Item)mindForm); + Dungeon.hero.sprite.operate(Dungeon.hero.pos); + + if (((Item) mindForm).usesTargeting && Dungeon.quickslot.contains(armor)){ + QuickSlotButton.useTargeting(Dungeon.quickslot.getSlot(armor)); + } } }; btnMind.icon(new ItemSprite((Item)mindForm)); @@ -187,6 +209,8 @@ public class Trinity extends ArmorAbility { btnMind.setRect(0, top + 2, width, btnMind.reqHeight()); add(btnMind); top = (int)btnMind.bottom(); + + btnMind.enable(armor.charge >= trinityChargeUsePerEffect(mindForm.getClass())); } if (spiritForm != null){ @@ -202,7 +226,7 @@ public class Trinity extends ArmorAbility { hide(); return; } - Buff.affect(Dungeon.hero, SpiritForm.SpiritFormBuff.class, SpiritForm.SpiritFormBuff.DURATION).setEffect(spiritForm); + Buff.prolong(Dungeon.hero, SpiritForm.SpiritFormBuff.class, SpiritForm.SpiritFormBuff.DURATION).setEffect(spiritForm); Sample.INSTANCE.play(Assets.Sounds.TELEPORT); Enchanting.show(Dungeon.hero, (Item)spiritForm); Dungeon.hero.sprite.operate(Dungeon.hero.pos); @@ -221,6 +245,8 @@ public class Trinity extends ArmorAbility { btnSpirit.setRect(0, top + 2, width, btnSpirit.reqHeight()); add(btnSpirit); top = (int)btnSpirit.bottom(); + + btnSpirit.enable(armor.charge >= trinityChargeUsePerEffect(spiritForm.getClass())); } resize(width, top); @@ -440,6 +466,9 @@ public class Trinity extends ArmorAbility { return Messages.get(Trinity.class, "thrown_use", MindForm.itemLevel(), Messages.decimalFormat("#.##", chargeUse)); } if (Wand.class.isAssignableFrom(cls)){ + if (cls.equals(WandOfFireblast.class) || cls.equals(WandOfRegrowth.class)){ + return Messages.get(Trinity.class, "wand_multi_use", MindForm.itemLevel(), Messages.decimalFormat("#.##", chargeUse)); + } return Messages.get(Trinity.class, "wand_use", MindForm.itemLevel(), Messages.decimalFormat("#.##", chargeUse)); } if (Ring.class.isAssignableFrom(cls)){ @@ -466,6 +495,9 @@ public class Trinity extends ArmorAbility { } } } + if (cls.equals(WandOfFireblast.class) || cls.equals(WandOfRegrowth.class)){ + return 2*chargeUse; + } if (Artifact.class.isAssignableFrom(cls)){ return chargeUse; //TODO } 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 168132b10..826c0ac6e 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 @@ -22,12 +22,27 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; 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.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.WondrousResin; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.CursedWand; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; +import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; +import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; public class MindForm extends ClericSpell { @@ -48,6 +63,10 @@ public class MindForm extends ClericSpell { return super.canCast(hero) && hero.hasTalent(Talent.MIND_FORM); } + public static int effectLevel(){ + return 2 + Dungeon.hero.pointsInTalent(Talent.MIND_FORM); + } + @Override public void onCast(HolyTome tome, Hero hero) { @@ -59,4 +78,91 @@ public class MindForm extends ClericSpell { return 2 + Dungeon.hero.pointsInTalent(Talent.MIND_FORM); } + //TODO selecting + public static class targetSelector extends CellSelector.Listener { + + private Bundlable effect; + + public void setEffect(Bundlable effect){ + this.effect = effect; + } + + private Wand wand(){ + if (effect instanceof Wand){ + ((Wand) effect).level(effectLevel()); + ((Wand) effect).curCharges = ((Wand) effect).maxCharges; + ((Wand) effect).identify(false); + return (Wand)effect; + } + return null; + } + + private MissileWeapon thrown(){ + if (effect instanceof MissileWeapon){ + ((MissileWeapon) effect).level(effectLevel()); + ((MissileWeapon) effect).identify(false); + return (MissileWeapon) effect; + } + return null; + } + + @Override + public void onSelect(Integer target) { + if (target == null){ + return; + } + if (wand() != null){ + Wand wand = wand(); + if (wand.tryToZap(Dungeon.hero, target)) { + + final Ballistica shot = new Ballistica( Dungeon.hero.pos, target, wand.collisionProperties(target)); + int cell = shot.collisionPos; + + if (target == Dungeon.hero.pos || cell == Dungeon.hero.pos) { + GLog.i( Messages.get(Wand.class, "self_target") ); + return; + } + + Dungeon.hero.sprite.zap(cell); + + //attempts to target the cell aimed at if something is there, otherwise targets the collision pos. + if (Actor.findChar(target) != null) + QuickSlotButton.target(Actor.findChar(target)); + else + QuickSlotButton.target(Actor.findChar(cell)); + + wand.fx(shot, new Callback() { + public void call() { + wand.onZap(shot); + if (Random.Float() < WondrousResin.extraCurseEffectChance()){ + WondrousResin.forcePositive = true; + CursedWand.cursedZap(wand, + Dungeon.hero, + new Ballistica(Dungeon.hero.pos, cell, Ballistica.MAGIC_BOLT), new Callback() { + @Override + public void call() { + WondrousResin.forcePositive = false; + } + }); + } + ((ClassArmor)Dungeon.hero.belongings.armor()).charge -= Trinity.trinityChargeUsePerEffect(wand.getClass()); + wand.wandUsed(); + } + }); + } + } else if (thrown() != null){ + //TODO + } + } + + @Override + public String prompt() { + if (wand() != null){ + return Messages.get(Wand.class, "prompt"); + } else { + return Messages.get(Item.class, "prompt"); + } + } + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java index b3cd2df35..fea268115 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java @@ -433,7 +433,7 @@ public abstract class Wand extends Item { particle.radiateXY(0.5f); } - protected void wandUsed() { + public void wandUsed() { if (!isIdentified()) { float uses = Math.min( availableUsesToID, Talent.itemIDSpeedFactor(Dungeon.hero, this) ); availableUsesToID -= uses;