v3.0.0: implemented the Paladin's lay on hands spell

This commit is contained in:
Evan Debenham
2025-01-14 16:22:47 -05:00
parent 5570e015fd
commit 86cf0ad29b
4 changed files with 127 additions and 5 deletions

View File

@@ -647,6 +647,10 @@ actors.hero.spells.judgement.name=judgement
actors.hero.spells.judgement.short_desc=Damages all visible enemies.
actors.hero.spells.judgement.desc=The Cleric slams their fist onto the ground, causing an eruption of light that deals damage to all enemies they can see. This deals %1$d-%2$d damage at base, but also deals an additional 5-10 damage for each spell the Cleric has cast since entering ascended form (or since they last cast Judgement).\n\nCurrently Judgement will deal %3$d-%4$d damage.
actors.hero.spells.layonhands.name=lay on hands
actors.hero.spells.layonhands.short_desc=Instantly heals an adjacent character or shields the Paladin.
actors.hero.spells.layonhands.desc=The Paladin channels holy energy through their hands, healing or protecting whatever they touch.\n\nThe Paladin can cast this spell on any adjacent character to give them %1$d healing, or on themselves to gain %1$d shielding. Excess healing from this spell is converted into shielding.\n\nThis spell is cast instantaneously and can be cast repeatedly, but cannot grant more than three casts worth of shielding at a time.
actors.hero.spells.mindform.name=mind form
actors.hero.spells.mindform.short_desc=TODO
actors.hero.spells.mindform.desc=TODO
@@ -1152,8 +1156,8 @@ actors.hero.talent.hallowed_ground.desc=_+1:_ The Priest can cast _Hallowed Grou
actors.hero.talent.mnemonic_prayer.title=Mnemonic Prayer
actors.hero.talent.mnemonic_prayer.desc=_+1:_ The Priest can cast _Mnemonic Prayer,_ a spell that extends buffs/debuffs on an ally/enemy for _3 turns_ at 1 charge cost.\n\n_+2:_ The Priest can cast _Mnemonic Prayer,_ a spell that extends buffs/debuffs on an ally/enemy for _4 turns_ at 1 charge cost.\n\n_+3:_ The Priest can cast _Mnemonic Prayer,_ a spell that extends buffs/debuffs on an ally/enemy for _5 turns_ at 1 charge cost.\n\nMnemonic Prayer also re-illuminates the target if they were illuminated previously. Mnemonic Prayer can only extend a particular instance of a buff/debuff once, and cannot extend buffs from armor abilities.
actors.hero.talent.paladint3a.title=Unknown
actors.hero.talent.paladint3a.desc=This talent hasn't been implemented yet, it currently does nothing.
actors.hero.talent.lay_on_hands.title=lay on hands
actors.hero.talent.lay_on_hands.desc=_+1:_ The Paladin can cast _Lay on Hands,_ a spell that instantly heals a nearby character for _10 HP,_ or grants the Paladin _10 shielding,_ at the cost of 1 charge.\n\n_+2:_ The Paladin can cast _Lay on Hands,_ a spell that instantly heals a nearby character for _15 HP,_ or grants the Paladin _15 shielding,_ at the cost of 1 charge.\n\n_+3:_ The Paladin can cast _Lay on Hands,_ a spell that instantly heals a nearby character for _20 HP,_ or grants the Paladin _20 shielding,_ at the cost of 1 charge.\n\nExcess healing from this spell is converted into shielding. Lay on Hands can be cast repeatedly, but cannot apply more than three casts worth of shielding at once.
actors.hero.talent.paladint3b.title=Unknown
actors.hero.talent.paladint3b.desc=This talent hasn't been implemented yet, it currently does nothing.
actors.hero.talent.paladint3c.title=Unknown

View File

@@ -183,7 +183,7 @@ public enum Talent {
//Priest T3
HOLY_LANCE(171, 3), HALLOWED_GROUND(172, 3), MNEMONIC_PRAYER(173, 3),
//Paladin T3
PALADINT3A(174, 3), PALADINT3B(175, 3), PALADINT3C(176, 3),
LAY_ON_HANDS(174, 3), PALADINT3B(175, 3), PALADINT3C(176, 3),
//Ascended Form T4
DIVINE_INTERVENTION(177, 4), JUDGEMENT(178, 4), FLASH(179, 4),
//Trinity T4
@@ -1022,7 +1022,7 @@ public enum Talent {
Collections.addAll(tierTalents, HOLY_LANCE, HALLOWED_GROUND, MNEMONIC_PRAYER);
break;
case PALADIN:
Collections.addAll(tierTalents, PALADINT3A, PALADINT3B, PALADINT3C);
Collections.addAll(tierTalents, LAY_ON_HANDS, PALADINT3B, PALADINT3C);
break;
}
for (Talent talent : tierTalents){

View File

@@ -152,7 +152,9 @@ public abstract class ClericSpell {
spells.add(MnemonicPrayer.INSTANCE);
}
//TODO paladin spells
if (cleric.hasTalent(Talent.LAY_ON_HANDS)){
spells.add(LayOnHands.INSTANCE);
}
} else if (tier == 4){
@@ -194,6 +196,8 @@ public abstract class ClericSpell {
spells.add(BlessSpell.INSTANCE);
spells.add(Cleanse.INSTANCE);
spells.add(Radiance.INSTANCE);
spells.add(Smite.INSTANCE);
spells.add(LayOnHands.INSTANCE);
spells.add(HolyLance.INSTANCE);
spells.add(HallowedGround.INSTANCE);
spells.add(MnemonicPrayer.INSTANCE);

View File

@@ -0,0 +1,114 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2025 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.effects.FloatingText;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
public class LayOnHands extends TargetedClericSpell {
public static LayOnHands INSTANCE = new LayOnHands();
@Override
public int icon() {
return HeroIcon.LAY_ON_HANDS;
}
@Override
public String desc() {
return Messages.get(this, "desc", 5 + 5*Dungeon.hero.pointsInTalent(Talent.LAY_ON_HANDS)) + "\n\n" + Messages.get(this, "charge_cost", (int)chargeUse(Dungeon.hero));
}
@Override
public int targetingFlags(){
return -1; //auto-targeting behaviour is often wrong, so we don't use it
}
@Override
protected void onTargetSelected(HolyTome tome, Hero hero, Integer target) {
if (target == null) {
return;
}
if (Dungeon.level.distance(hero.pos, target) > 1){
GLog.w(Messages.get(this, "invalid_target"));
return;
}
Char ch = Actor.findChar(target);
if (ch == null){
GLog.w(Messages.get(this, "no_target"));
return;
}
Sample.INSTANCE.play(Assets.Sounds.TELEPORT);
Barrier barrier = Buff.affect(ch, Barrier.class);
int totalHeal = 5 + 5*hero.pointsInTalent(Talent.LAY_ON_HANDS);
int totalBarrier = 0;
if (ch == hero){
totalBarrier = totalHeal;
totalBarrier = Math.min(3*totalHeal - barrier.shielding(), totalBarrier);
totalBarrier = Math.max(0, totalBarrier);
Buff.affect(ch, Barrier.class).incShield(totalBarrier);
ch.sprite.showStatusWithIcon( CharSprite.POSITIVE, Integer.toString(totalBarrier), FloatingText.SHIELDING );
hero.sprite.operate(ch.pos);
hero.next();
} else {
if (ch.HT - ch.HP < totalHeal){
totalBarrier = totalHeal - (ch.HT - ch.HP);
totalBarrier = Math.min(3*totalHeal - barrier.shielding(), totalBarrier);
totalBarrier = Math.max(0, totalBarrier);
if (ch.HP != ch.HT) {
ch.HP = ch.HT;
ch.sprite.showStatusWithIcon(CharSprite.POSITIVE, Integer.toString(totalHeal - totalBarrier), FloatingText.HEALING);
}
if (totalBarrier >= 0) {
barrier.incShield(totalBarrier);
ch.sprite.showStatusWithIcon(CharSprite.POSITIVE, Integer.toString(totalBarrier), FloatingText.SHIELDING);
}
} else {
ch.HP = ch.HP + totalHeal;
ch.sprite.showStatusWithIcon( CharSprite.POSITIVE, Integer.toString(totalHeal), FloatingText.HEALING );
}
hero.sprite.zap(ch.pos);
hero.next();
}
onSpellCast(tome, hero);
}
}