v3.0.0: implemented the Sunray spell/talent

This commit is contained in:
Evan Debenham
2024-11-01 14:26:14 -04:00
parent 52b30a820c
commit 2452a8941e
9 changed files with 146 additions and 5 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

@@ -577,6 +577,11 @@ actors.hero.spells.shieldoflight.desc=The Cleric creates a thin barrier of light
actors.hero.spells.shieldoflight$shieldoflighttracker.name=shield of light
actors.hero.spells.shieldoflight$shieldoflighttracker.desc=A thin shield of light is standing between the Cleric and an enemy. It's not strong enough to outright block attacks, but will soften them.\n\nTurns Remaining: %s
actors.hero.spells.sunray.name=sunray
actors.hero.spells.sunray.prompt=Choose a target
actors.hero.spells.sunray.short_desc=Deals ranged magic damage and blinds a target once.
actors.hero.spells.sunray.desc=The Cleric fires a ray of blinding light at a target, dealing %1$d-%2$d damage and blinding them for %3$d turns. Sunray always deals maximum damage to undead and demonic targets.\n\nAfter being struck with this spell an enemy's vision will adjust, preventing them from being blinded by it again. However, if they are struck again while blinding by this spell, then the light is overwhelming and paralyses them instead.
##main hero
actors.hero.hero.name=you
actors.hero.hero.leave=You can't leave yet, the rest of the dungeon awaits below!
@@ -1021,8 +1026,8 @@ actors.hero.talent.enlightening_meal.title=Enlightening Meal
actors.hero.talent.enlightening_meal.desc=_+1:_ Eating food takes the Cleric 1 turn and grants them _1 charge_ on their holy tome.\n\n_+2:_ Eating food takes the Cleric 1 turn and grants them _1.5 charges_ on their holy tome.
actors.hero.talent.clerict2b.title=TODO
actors.hero.talent.clerict2b.desc=TODO
actors.hero.talent.clerict2c.title=TODO
actors.hero.talent.clerict2c.desc=TODO
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 50 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 50 turns, at the cost of 2 charges.
actors.hero.talent.clerict2e.title=TODO
@@ -175,7 +175,7 @@ public enum Talent {
//Cleric T1
SATIATED_SPELLS(160), DETECT_CURSE(161), SEARING_LIGHT(162), SHIELD_OF_LIGHT(163),
//Cleric T2
ENLIGHTENING_MEAL(164), CLERICT2B(165), CLERICT2C(166), DIVINE_SENSE(167), CLERICT2E(168),
ENLIGHTENING_MEAL(164), CLERICT2B(165), SUNRAY(166), DIVINE_SENSE(167), CLERICT2E(168),
//Cleric T3
CLERICT3A(169, 3), CLERICT3B(170, 3),
@@ -915,7 +915,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, CLERICT2B, CLERICT2C, DIVINE_SENSE, CLERICT2E);
Collections.addAll(tierTalents, ENLIGHTENING_MEAL, CLERICT2B, SUNRAY, DIVINE_SENSE, CLERICT2E);
break;
}
for (Talent talent : tierTalents){
@@ -85,6 +85,10 @@ public abstract class ClericSpell {
} else if (tier == 2) {
if (cleric.hasTalent(Talent.SUNRAY)){
spells.add(Sunray.INSTANCE);
}
if (cleric.hasTalent(Talent.DIVINE_SENSE)) {
spells.add(DivineSense.INSTANCE);
}
@@ -0,0 +1,122 @@
/*
* 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.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Random;
public class Sunray extends TargetedClericSpell {
public static final Sunray INSTANCE = new Sunray();
@Override
public int icon() {
return HeroIcon.SUNRAY;
}
@Override
public String desc() {
int min = Dungeon.hero.pointsInTalent(Talent.SUNRAY) == 2 ? 3 : 2;
int max = Dungeon.hero.pointsInTalent(Talent.SUNRAY) == 2 ? 12 : 8;
int dur = Dungeon.hero.pointsInTalent(Talent.SUNRAY) == 2 ? 6 : 4;
return Messages.get(this, "desc", min, max, dur) + "\n\n" + Messages.get(this, "charge_cost", (int)chargeUse(Dungeon.hero));
}
@Override
protected void onTargetSelected(HolyTome tome, Hero hero, Integer target) {
if (target == null){
return;
}
Ballistica aim = new Ballistica(hero.pos, target, Ballistica.MAGIC_BOLT);
if (Actor.findChar( aim.collisionPos ) == hero){
GLog.i( Messages.get(Wand.class, "self_target") );
return;
}
hero.busy();
Sample.INSTANCE.play( Assets.Sounds.RAY );
hero.sprite.zap(target);
hero.sprite.parent.add(
new Beam.SunRay(hero.sprite.center(), DungeonTilemap.raisedTileCenterToWorld(aim.collisionPos)));
Char ch = Actor.findChar( aim.collisionPos );
if (ch != null) {
ch.sprite.burst(0xFFFFFF44, 5);
if (Char.hasProp(ch, Char.Property.UNDEAD) || Char.hasProp(ch, Char.Property.DEMONIC)){
if (hero.pointsInTalent(Talent.SUNRAY) == 2) {
ch.damage(12, Sunray.this);
} else {
ch.damage(8, Sunray.this);
}
} else {
if (hero.pointsInTalent(Talent.SUNRAY) == 2) {
ch.damage(Random.NormalIntRange(3, 12), Sunray.this);
} else {
ch.damage(Random.NormalIntRange(2, 8), Sunray.this);
}
}
if (ch.isAlive()) {
if (ch.buff(Blindness.class) != null && ch.buff(SunRayRecentlyBlindedTracker.class) != null) {
Buff.prolong(ch, Paralysis.class, 2f + 2f*hero.pointsInTalent(Talent.SUNRAY));
ch.buff(SunRayRecentlyBlindedTracker.class).detach();
} else if (ch.buff(SunRayUsedTracker.class) == null) {
Buff.prolong(ch, Blindness.class, 2f + 2f*hero.pointsInTalent(Talent.SUNRAY));
Buff.prolong(ch, SunRayRecentlyBlindedTracker.class, 2f + 2f*hero.pointsInTalent(Talent.SUNRAY));
Buff.affect(ch, SunRayUsedTracker.class);
}
}
}
hero.spend( 1f );
hero.next();
onSpellCast(tome, hero);
}
public static class SunRayUsedTracker extends Buff {}
public static class SunRayRecentlyBlindedTracker extends FlavourBuff {}
}
@@ -66,6 +66,13 @@ public class Beam extends Image {
}
}
public static class SunRay extends Beam{
public SunRay(PointF s, PointF e){
super(s, e, Effects.Type.LIGHT_RAY, 1f);
tint(1, 1, 0.25f, 1);
}
}
public static class HealthRay extends Beam{
public HealthRay(PointF s, PointF e){
super(s, e, Effects.Type.HEALTH_RAY, 0.75f);
@@ -33,6 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.mage.Eleme
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.mage.WarpBeacon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.GuidingLight;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.HolyWeapon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.Sunray;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalWisp;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM100;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
@@ -92,6 +93,7 @@ public class AntiMagic extends Armor.Glyph {
RESISTS.add( GuidingLight.class );
RESISTS.add( HolyWeapon.class );
RESISTS.add( Sunray.class );
RESISTS.add( ElementalBlast.class );
RESISTS.add( CursedWand.class );
@@ -73,7 +73,8 @@ public class HeroIcon extends Image {
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 DIVINE_SENSE = 45;
public static final int SUNRAY = 45;
public static final int DIVINE_SENSE = 46;
//action indicator visuals
public static final int BERSERK = 80;