From 619d735224cb16cef23bbb7ea4d71f08d97bbf4e Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 29 Nov 2021 15:50:21 -0500 Subject: [PATCH] v1.1.0: implemented summon elemental and removed ranged atk from newborn v1.1.0: implemented summon elemental and removed ranged atk from newborn --- .../assets/messages/items/items.properties | 11 ++ .../actors/mobs/Elemental.java | 21 ++- .../items/spells/SummonElemental.java | 165 ++++++++++++++++++ 3 files changed, 195 insertions(+), 2 deletions(-) diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 14728ade1..6d6e9e8d9 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1095,6 +1095,17 @@ items.spells.recycle.inv_title=Recycle an item items.spells.recycle.recycled=Your item was recycled into: %s. items.spells.recycle.desc=This spell contains a lesser form of transmutation magic. While it won't work on equipment, this spell will transform a scroll, potion, seed, runestone, or tipped dart into a random item of the same type. +items.spells.summonelemental.name=summon elemental +items.spells.summonelemental.ac_imbue=IMBUE +items.spells.summonelemental.summon_limit=You can only have one elemental summoned at a time. +items.spells.summonelemental.imbue_prompt=Imbue an item +items.spells.summonelemental.desc=This spell channels the energy of the elemental embers used to make it, and will allow you to summon a friendly elemental to fight with you! Only one elemental can be summoned at a time. +items.spells.summonelemental.desc_newborn=The spell is currently unimbued, and will summon a weaker _newborn elemental_. You can imbue an identified potion of liquid flame, potion of frost, scroll of recharging, or scroll of transmutation to power the spell up, causing its next summon to be a full power elemental! +items.spells.summonelemental.desc_fire=The spell is currently hot to the touch, its next summon will be a _fire elemental_. You can imbue a different item, but the spell will lose its current imbue. +items.spells.summonelemental.desc_frost=The spell is currently cold to the touch, its next summon will be a _frost elemental_. You can imbue a different item, but the spell will lose its current imbue. +items.spells.summonelemental.desc_shock=The spell is currently radiating static energy, its next summon will be a _shock elemental_. You can imbue a different item, but the spell will lose its current imbue. +items.spells.summonelemental.desc_chaos=The spell is currently radiating chaotic energy, its next summon will be a _chaos elemental_. You can imbue a different item, but the spell will lose its current imbue. + items.spells.targetedspell.prompt=Choose a target items.spells.targetedspell.inv_title=Infuse an item diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Elemental.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Elemental.java index e19f4996f..2fb3793ac 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Elemental.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Elemental.java @@ -75,7 +75,7 @@ public abstract class Elemental extends Mob { return Random.NormalIntRange(0, 5); } - private int rangedCooldown = Random.NormalIntRange( 3, 5 ); + protected int rangedCooldown = Random.NormalIntRange( 3, 5 ); @Override protected boolean act() { @@ -215,12 +215,15 @@ public abstract class Elemental extends Mob { EXP = 7; properties.add(Property.MINIBOSS); + + //newborn elementals do not have ranged attacks + rangedCooldown = Integer.MAX_VALUE; } @Override public void die(Object cause) { super.die(cause); - Dungeon.level.drop( new Embers(), pos ).sprite.drop(); + if (alignment == Alignment.ENEMY) Dungeon.level.drop( new Embers(), pos ).sprite.drop(); } @Override @@ -229,6 +232,20 @@ public abstract class Elemental extends Mob { } } + + //not a miniboss, otherwise a newborn elemental + public static class AllyNewBornElemental extends NewbornFireElemental { + + { + properties.remove(Property.MINIBOSS); + } + + @Override + public boolean reset() { + return false; + } + + } public static class FrostElemental extends Elemental { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java index 55357fb08..df382a79a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/SummonElemental.java @@ -1,19 +1,184 @@ package com.shatteredpixel.shatteredpixeldungeon.items.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.AllyBuff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental; +import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.RainbowParticle; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.LiquidMetal; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfFrost; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLiquidFlame; import com.shatteredpixel.shatteredpixeldungeon.items.quest.Embers; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.utils.Reflection; + +import java.util.ArrayList; public class SummonElemental extends Spell { + public static final String AC_IMBUE = "IMBUE"; + { image = ItemSpriteSheet.SUMMON_ELE; } + private Class summonClass = Elemental.AllyNewBornElemental.class; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_IMBUE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_IMBUE)){ + GameScene.selectItem(selector); + } + } + @Override protected void onCast(Hero hero) { + for (Char ch : Actor.chars()){ + if (ch instanceof Elemental && ch.buff(InvisAlly.class) != null){ + GLog.w(Messages.get(this, "summon_limit")); + return; + } + } + + ArrayList spawnPoints = new ArrayList<>(); + + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = hero.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar( p ) == null && Dungeon.level.passable[p]) { + spawnPoints.add( p ); + } + } + + if (!spawnPoints.isEmpty()){ + + Elemental elemental = Reflection.newInstance(summonClass); + GameScene.add( elemental ); + Buff.affect(elemental, InvisAlly.class); + ScrollOfTeleportation.appear( elemental, Random.element(spawnPoints) ); + + summonClass = Elemental.AllyNewBornElemental.class; + + detach(Dungeon.hero.belongings.backpack); + + } else { + GLog.w(Messages.get(SpiritHawk.class, "no_space")); + } + + } + + @Override + public ItemSprite.Glowing glowing() { + if (summonClass == Elemental.FireElemental.class) return new ItemSprite.Glowing(0xFFBB33); + if (summonClass == Elemental.FrostElemental.class) return new ItemSprite.Glowing(0x8EE3FF); + if (summonClass == Elemental.ShockElemental.class) return new ItemSprite.Glowing(0xFFFF85); + if (summonClass == Elemental.ChaosElemental.class) return new ItemSprite.Glowing(0xE3E3E3, 0.5f); + return super.glowing(); + } + + @Override + public String desc() { + String desc = super.desc(); + + desc += "\n\n"; + + if (summonClass == Elemental.AllyNewBornElemental.class) desc += Messages.get(this, "desc_newborn"); + if (summonClass == Elemental.FireElemental.class) desc += Messages.get(this, "desc_fire"); + if (summonClass == Elemental.FrostElemental.class) desc += Messages.get(this, "desc_frost"); + if (summonClass == Elemental.ShockElemental.class) desc += Messages.get(this, "desc_shock"); + if (summonClass == Elemental.ChaosElemental.class) desc += Messages.get(this, "desc_chaos"); + + return desc; + } + + public WndBag.ItemSelector selector = new WndBag.ItemSelector() { + @Override + public String textPrompt() { + return Messages.get(SummonElemental.class, "imbue_prompt"); + } + + @Override + public boolean itemSelectable(Item item) { + return item.isIdentified() && (item instanceof PotionOfLiquidFlame + || item instanceof PotionOfFrost + || item instanceof ScrollOfRecharging + || item instanceof ScrollOfTransmutation); + } + + @Override + public void onSelect(Item item) { + + if (item == null){ + return; + } + + item.detach(Dungeon.hero.belongings.backpack); + if (item instanceof PotionOfLiquidFlame) { + Sample.INSTANCE.play(Assets.Sounds.BURNING); + curUser.sprite.emitter().burst( FlameParticle.FACTORY, 12 ); + summonClass = Elemental.FireElemental.class; + + } else if (item instanceof PotionOfFrost){ + Sample.INSTANCE.play(Assets.Sounds.SHATTER); + curUser.sprite.emitter().burst( MagicMissile.MagicParticle.FACTORY, 12 ); + summonClass = Elemental.FrostElemental.class; + + } else if (item instanceof ScrollOfRecharging){ + Sample.INSTANCE.play(Assets.Sounds.ZAP); + curUser.sprite.emitter().burst( ShaftParticle.FACTORY, 12 ); + summonClass = Elemental.ShockElemental.class; + + } else if (item instanceof ScrollOfTransmutation){ + Sample.INSTANCE.play(Assets.Sounds.READ); + curUser.sprite.emitter().burst( RainbowParticle.BURST, 12 ); + summonClass = Elemental.ChaosElemental.class; + } + + curUser.sprite.operate(curUser.pos); + + updateQuickslot(); + } + }; + + public static class InvisAlly extends AllyBuff{ + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.HEARTS); + else target.sprite.remove(CharSprite.State.HEARTS); + } + } public static class Recipe extends com.shatteredpixel.shatteredpixeldungeon.items.Recipe.SimpleRecipe {