v3.0.0: Implemented Trinity mind form for wands

This commit is contained in:
Evan Debenham
2025-02-05 14:13:45 -05:00
parent bad258d2b4
commit 0bd8395d04
4 changed files with 144 additions and 5 deletions

View File

@@ -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._

View File

@@ -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
}

View File

@@ -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");
}
}
}
}

View File

@@ -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;