v3.0.0: improved spell icons/ordering and added the bless talent/spell

This commit is contained in:
Evan Debenham
2024-12-05 16:09:52 -05:00
parent 6c5844cc4b
commit 5b9100fed9
8 changed files with 144 additions and 33 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@@ -544,6 +544,10 @@ actors.hero.abilities.ratmogrify$transmograt.desc=This enemy has been transforme
actors.hero.abilities.ratmogrify$transmograt.rankings_desc=Slain by: ratmogrified enemy
##Cleric Spells
actors.hero.spells.blessspell.name=bless
actors.hero.spells.blessspell.short_desc=Blesses & shields Cleric, blesses & heals others.
actors.hero.spells.blessspell.desc=The Cleric places a holy blessing on themselves or another character they can see.\n\nWhen cast on themselves the effect is weaker, granting %1$d turns of bless and %2$d barrier.\n\nWhen cast on other characters the spell is more powerful, granting %3$d turns of bless and %4$d healing. Excess healing is converted into barrier.
actors.hero.spells.cleanse.name=cleanse
actors.hero.spells.cleanse.short_desc=Clears debuffs and grants shielding.
actors.hero.spells.cleanse.desc=The Cleric instantly clears all harmful effects on themselves and visible allies. After the spell ends all characters affected also gain %1$d turns of debuff immunity, and %2$d barrier.
@@ -1071,8 +1075,8 @@ actors.hero.talent.sunray.title=Sunray
actors.hero.talent.sunray.desc=_+1:_ The Cleric can cast _Sunray,_ A spell that deals _2-8 damage_ and blinds the target for _4 turns,_ at the cost of 1 charge.\n\n_+2:_ The Cleric can cast _Sunray,_ A spell that deals _3-12 damage_ and blinds the target for _6 turns,_ at the cost of 1 charge.\n\nSunray can only blind each target once, but if the target is already blinded by Sunray then it paralyses instead. Sunray always deals maximum damage to demonic and undead foes.
actors.hero.talent.divine_sense.title=Divine Sense
actors.hero.talent.divine_sense.desc=_+1:_ The Cleric can cast _Divine Sense,_ a spell that grants them _8 tiles_ of Mind Vision for 30 turns, at the cost of 2 charges.\n\n_+2:_ The Cleric can cast _Divine Sense,_ a spell that grants them _12 tiles_ of Mind Vision for 30 turns, at the cost of 2 charges.
actors.hero.talent.clerict2e.title=Unknown
actors.hero.talent.clerict2e.desc=This talent hasn't been implemented yet, it currently does nothing.
actors.hero.talent.bless.title=Bless
actors.hero.talent.bless.desc=_+1:_ The Cleric can cast _Bless,_ a spell that grants _4 turns of bless and 10 shielding_ when cast on themselves or _10 turns of bless and 15 healing_ when cast on another character, at the cost of 1 charge.\n\n_+2:_ The Cleric can cast _Bless,_ a spell that grants _6 turns of bless and 15 shielding_ when cast on themselves or _15 turns of bless and 25 healing_ when cast on another character, at the cost of 1 charge.\n\nExcess healing from this spell is converted into shielding.
actors.hero.talent.cleanse.title=Cleanse
actors.hero.talent.cleanse.desc=_+1:_ The Cleric can cast _Cleanse,_ a spell which is cast instantly, _removes negative status effects_ from the Cleric and any nearby allies, and grants them _10 shielding,_ at the cost of 2 charges.\n\n_+2:_ The Cleric can cast _Cleanse,_ a spell which is cast instantly, _grants 3 turns of negative status immunity_ to the Cleric and any nearby allies, and grants them _20 shielding,_ at the cost of 2 charges.\n\n_+3:_ The Cleric can cast _Cleanse,_ a spell which is cast instantly, _grants 5 turns of negative status immunity_ to the Cleric and any nearby allies, and grants them _30 shielding,_ at the cost of 2 charges.

View File

@@ -178,7 +178,7 @@ public enum Talent {
//Cleric T1
SATIATED_SPELLS(160), DETECT_CURSE(161), SEARING_LIGHT(162), SHIELD_OF_LIGHT(163),
//Cleric T2
ENLIGHTENING_MEAL(164), RECALL_GLYPH(165), SUNRAY(166), DIVINE_SENSE(167), CLERICT2E(168),
ENLIGHTENING_MEAL(164), RECALL_GLYPH(165), SUNRAY(166), DIVINE_SENSE(167), BLESS(168),
//Cleric T3
CLEANSE(169, 3), LIGHT_READING(170, 3),
//Priest T3
@@ -937,7 +937,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, RECALL_GLYPH, SUNRAY, DIVINE_SENSE, CLERICT2E);
Collections.addAll(tierTalents, ENLIGHTENING_MEAL, RECALL_GLYPH, SUNRAY, DIVINE_SENSE, BLESS);
break;
}
for (Talent talent : tierTalents){

View File

@@ -0,0 +1,102 @@
/*
* 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 <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.Bless;
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.Flare;
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 BlessSpell extends TargetedClericSpell {
public static final BlessSpell INSTANCE = new BlessSpell();
@Override
public int icon() {
return HeroIcon.BLESS;
}
@Override
protected void onTargetSelected(HolyTome tome, Hero hero, Integer target) {
if (target == null){
return;
}
Char ch = Actor.findChar(target);
if (ch == null || !Dungeon.level.heroFOV[target]){
GLog.w(Messages.get(this, "no_target"));
return;
}
Sample.INSTANCE.play(Assets.Sounds.TELEPORT);
new Flare(6, 32).color(0xFFFF00, true).show(ch.sprite, 2f);
if (ch == hero){
Buff.prolong(ch, Bless.class, 2f + 2*hero.pointsInTalent(Talent.BLESS));
Buff.affect(ch, Barrier.class).setShield(5 + 5*hero.pointsInTalent(Talent.BLESS));
ch.sprite.showStatusWithIcon( CharSprite.POSITIVE, Integer.toString(5 + 5*hero.pointsInTalent(Talent.BLESS)), FloatingText.SHIELDING );
hero.sprite.operate(ch.pos);
} else {
Buff.prolong(ch, Bless.class, 5f + 5*hero.pointsInTalent(Talent.BLESS));
int totalHeal = 5 + 10*hero.pointsInTalent(Talent.BLESS);
if (ch.HT - ch.HP < totalHeal){
int barrier = totalHeal - (ch.HT - ch.HP);
if (ch.HP != ch.HT) {
ch.HP = ch.HT;
ch.sprite.showStatusWithIcon(CharSprite.POSITIVE, Integer.toString(totalHeal - barrier), FloatingText.HEALING);
}
Buff.affect(ch, Barrier.class).setShield(barrier);
ch.sprite.showStatusWithIcon( CharSprite.POSITIVE, Integer.toString(barrier), FloatingText.SHIELDING );
} else {
ch.HP = ch.HP + totalHeal;
ch.sprite.showStatusWithIcon( CharSprite.POSITIVE, Integer.toString(totalHeal), FloatingText.HEALING );
}
hero.sprite.zap(ch.pos);
}
hero.busy();
hero.sprite.operate(hero.pos);
onSpellCast(tome, hero);
}
public String desc(){
int talentLvl = Dungeon.hero.pointsInTalent(Talent.BLESS);
return Messages.get(this, "desc", 2+2*talentLvl, 5+5*talentLvl, 5+5*talentLvl, 5+10*talentLvl) + "\n\n" + Messages.get(this, "charge_cost", (int)chargeUse(Dungeon.hero));
}
}

View File

@@ -80,44 +80,48 @@ public abstract class ClericSpell {
spells.add(HolyWeapon.INSTANCE);
spells.add(HolyWard.INSTANCE);
if (cleric.hasTalent(Talent.SHIELD_OF_LIGHT)) {
spells.add(ShieldOfLight.INSTANCE);
}
if (cleric.hasTalent(Talent.DETECT_CURSE)) {
spells.add(DetectCurse.INSTANCE);
}
} else if (tier == 2) {
if (cleric.hasTalent(Talent.SUNRAY)){
spells.add(Sunray.INSTANCE);
if (cleric.hasTalent(Talent.SHIELD_OF_LIGHT)) {
spells.add(ShieldOfLight.INSTANCE);
}
} else if (tier == 2) {
if (cleric.hasTalent(Talent.RECALL_GLYPH)){
spells.add(RecallGlyph.INSTANCE);
}
if (cleric.hasTalent(Talent.SUNRAY)){
spells.add(Sunray.INSTANCE);
}
if (cleric.hasTalent(Talent.DIVINE_SENSE)) {
spells.add(DivineSense.INSTANCE);
}
if (cleric.hasTalent(Talent.BLESS)){
spells.add(BlessSpell.INSTANCE);
}
} else if (tier == 3){
if (cleric.subClass == HeroSubClass.PRIEST) {
spells.add(Radiance.INSTANCE);
} else if (cleric.subClass == HeroSubClass.PALADIN){
//TODO innate smite spell
}
if (cleric.hasTalent(Talent.CLEANSE)){
spells.add(Cleanse.INSTANCE);
}
if (cleric.subClass == HeroSubClass.PRIEST) {
spells.add(Radiance.INSTANCE);
if (cleric.hasTalent(Talent.HOLY_LANCE)){
spells.add(HolyLance.INSTANCE);
}
} else if (cleric.subClass == HeroSubClass.PALADIN){
//TODO innate smite spell
if (cleric.hasTalent(Talent.HOLY_LANCE)){
spells.add(HolyLance.INSTANCE);
}
}
@@ -130,10 +134,10 @@ public abstract class ClericSpell {
spells.add(GuidingLight.INSTANCE);
spells.add(HolyWeapon.INSTANCE);
spells.add(HolyWard.INSTANCE);
spells.add(ShieldOfLight.INSTANCE);
spells.add(DetectCurse.INSTANCE);
spells.add(Sunray.INSTANCE);
spells.add(ShieldOfLight.INSTANCE);
spells.add(RecallGlyph.INSTANCE);
spells.add(Sunray.INSTANCE);
spells.add(DivineSense.INSTANCE);
spells.add(Cleanse.INSTANCE);
spells.add(Radiance.INSTANCE);

View File

@@ -55,7 +55,7 @@ public class ShieldOfLight extends TargetedClericSpell {
}
Char ch = Actor.findChar(target);
if (ch == null || ch.alignment == Char.Alignment.ALLY){
if (ch == null || ch.alignment == Char.Alignment.ALLY || !Dungeon.level.heroFOV[target]){
GLog.w(Messages.get(this, "no_target"));
return;
}

View File

@@ -76,14 +76,15 @@ public class HeroIcon extends Image {
public static final int GUIDING_LIGHT = 40;
public static final int HOLY_WEAPON = 41;
public static final int HOLY_WARD = 42;
public static final int SHIELD_OF_LIGHT = 43;
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;
public static final int HOLY_LANCE = 48;
public static final int RADIANCE = 49;
public static final int CLEANSE = 50;
public static final int DETECT_CURSE = 43;
public static final int SHIELD_OF_LIGHT = 44;
public static final int RECALL_GLYPH = 45;
public static final int SUNRAY = 46;
public static final int DIVINE_SENSE = 47;
public static final int BLESS = 48;
public static final int CLEANSE = 49;
public static final int RADIANCE = 50;
public static final int HOLY_LANCE = 51;
//all cleric spells have a separate icon with no background for the action indicator
public static final int SPELL_ACTION_OFFSET = 32;