From 5d4c85ede284ebd3d6db0e96a3f0de5a3ead6151 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 22 Aug 2022 14:30:08 -0400 Subject: [PATCH] v1.4.0: reworked the footwear of nature --- .../assets/messages/items/items.properties | 8 +- .../items/artifacts/SandalsOfNature.java | 188 +++++++++++++----- .../levels/features/HighGrass.java | 8 +- .../plants/Rotberry.java | 7 +- 4 files changed, 153 insertions(+), 58 deletions(-) diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 1055c27e8..88d41a943 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -376,18 +376,20 @@ items.artifacts.sandalsofnature.name_2=boots of nature items.artifacts.sandalsofnature.name_3=greaves of nature items.artifacts.sandalsofnature.ac_feed=FEED items.artifacts.sandalsofnature.ac_root=ROOT -items.artifacts.sandalsofnature.no_charge=They have no energy right now. items.artifacts.sandalsofnature.prompt=Select a seed -items.artifacts.sandalsofnature.already_fed=Your footwear have already recently gained nutrients from that seed. items.artifacts.sandalsofnature.levelup=Your footwear surges in size! items.artifacts.sandalsofnature.absorb_seed=The footwear absorbs the seed, they seem healthier. +items.artifacts.sandalsofnature.no_effect=You must feed a seed to your footwear first. +items.artifacts.sandalsofnature.low_charge=Your footwear don't have enough energy for that. +items.artifacts.sandalsofnature.prompt_target=Select a location +items.artifacts.sandalsofnature.out_of_range=That location is out of range. items.artifacts.sandalsofnature.desc_1=What initially seem like sandals made of twine are actually two plants! They seem very weak and pale, perhaps they need to be given nutrients? items.artifacts.sandalsofnature.desc_2=The footwear has grown and now more closely resemble two tailored shoes. Some colour has returned to them, perhaps they can still grow further? items.artifacts.sandalsofnature.desc_3=The plants have grown again and now resembles a pair of solid boots made from bark. The plants seem to have regained their strength, but perhaps they can still grow further? items.artifacts.sandalsofnature.desc_4=The plants seem to have reached their maximum size, they resemble a pair of armored greaves. The greaves are a deep brown and resemble a very sturdy tree. items.artifacts.sandalsofnature.desc_hint=You feel more attuned with nature while wearing this artifact. items.artifacts.sandalsofnature.desc_cursed=The cursed sandals are blocking any attunement with nature. -items.artifacts.sandalsofnature.desc_ability=The footwear has gained the ability to form up into a sort of immobile natural armour, but will need to charge up for it. +items.artifacts.sandalsofnature.desc_ability=The footwear ripples with the color of the last seed you fed them. They can briefly root into the ground and product that plant's effect anywhere in a 3 tile radius. Charge needed: _%d%%._ items.artifacts.sandalsofnature.desc_seeds=You have fed the footwear %d seeds. items.artifacts.talismanofforesight.name=talisman of foresight diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/SandalsOfNature.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/SandalsOfNature.java index cea870d98..58240e7c6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/SandalsOfNature.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/SandalsOfNature.java @@ -23,30 +23,46 @@ package com.shatteredpixel.shatteredpixeldungeon.items.artifacts; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; -import com.shatteredpixel.shatteredpixeldungeon.effects.particles.EarthParticle; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; import com.shatteredpixel.shatteredpixeldungeon.items.bags.VelvetPouch; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.plants.Blindweed; import com.shatteredpixel.shatteredpixeldungeon.plants.Earthroot; +import com.shatteredpixel.shatteredpixeldungeon.plants.Fadeleaf; +import com.shatteredpixel.shatteredpixeldungeon.plants.Firebloom; +import com.shatteredpixel.shatteredpixeldungeon.plants.Icecap; +import com.shatteredpixel.shatteredpixeldungeon.plants.Mageroyal; import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; +import com.shatteredpixel.shatteredpixeldungeon.plants.Rotberry; +import com.shatteredpixel.shatteredpixeldungeon.plants.Sorrowmoss; +import com.shatteredpixel.shatteredpixeldungeon.plants.Starflower; +import com.shatteredpixel.shatteredpixeldungeon.plants.Stormvine; +import com.shatteredpixel.shatteredpixeldungeon.plants.Sungrass; +import com.shatteredpixel.shatteredpixeldungeon.plants.Swiftthistle; +import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.utils.BArray; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; -import com.watabou.noosa.Camera; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.utils.Reflection; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; public class SandalsOfNature extends Artifact { @@ -56,6 +72,7 @@ public class SandalsOfNature extends Artifact { levelCap = 3; charge = 0; + chargeCap = 100; defaultAction = AC_ROOT; } @@ -64,6 +81,39 @@ public class SandalsOfNature extends Artifact { public static final String AC_ROOT = "ROOT"; public ArrayList seeds = new ArrayList<>(); + public Class curSeedEffect = null; + + private static final HashMap, Integer> seedColors = new HashMap<>(); + static { + seedColors.put(Rotberry.Seed.class, 0xCC0022); + seedColors.put(Firebloom.Seed.class, 0xFF7F00); + seedColors.put(Swiftthistle.Seed.class, 0xCCBB00); + seedColors.put(Sungrass.Seed.class, 0x2EE62E); + seedColors.put(Icecap.Seed.class, 0x66B3FF); + seedColors.put(Stormvine.Seed.class, 0x195D80); + seedColors.put(Sorrowmoss.Seed.class, 0xA15CE5); + seedColors.put(Mageroyal.Seed.class, 0xFF4CD2); + seedColors.put(Earthroot.Seed.class, 0x67583D); + seedColors.put(Starflower.Seed.class, 0x404040); + seedColors.put(Fadeleaf.Seed.class, 0x919999); + seedColors.put(Blindweed.Seed.class, 0XD9D9D9); + } + + private static final HashMap, Integer> seedChargeReqs = new HashMap<>(); + static { + seedChargeReqs.put(Rotberry.Seed.class, 10); + seedChargeReqs.put(Firebloom.Seed.class, 25); + seedChargeReqs.put(Swiftthistle.Seed.class, 25); + seedChargeReqs.put(Sungrass.Seed.class, 100); + seedChargeReqs.put(Icecap.Seed.class, 25); + seedChargeReqs.put(Stormvine.Seed.class, 25); + seedChargeReqs.put(Sorrowmoss.Seed.class, 25); + seedChargeReqs.put(Mageroyal.Seed.class, 15); + seedChargeReqs.put(Earthroot.Seed.class, 50); + seedChargeReqs.put(Starflower.Seed.class, 50); + seedChargeReqs.put(Fadeleaf.Seed.class, 15); + seedChargeReqs.put(Blindweed.Seed.class, 15); + } @Override public ArrayList actions( Hero hero ) { @@ -71,10 +121,13 @@ public class SandalsOfNature extends Artifact { if (hero.buff(MagicImmune.class) != null){ return actions; } - if (isEquipped( hero ) && level() < 3 && !cursed) { + if (isEquipped( hero ) && !cursed) { actions.add(AC_FEED); } - if (isEquipped( hero ) && charge > 0) { + if (isEquipped( hero ) + && !cursed + && curSeedEffect != null + && charge >= seedChargeReqs.get(curSeedEffect)) { actions.add(AC_ROOT); } return actions; @@ -90,18 +143,13 @@ public class SandalsOfNature extends Artifact { GameScene.selectItem(itemSelector); - } else if (action.equals(AC_ROOT) && level() > 0){ + } else if (action.equals(AC_ROOT) && !cursed){ - if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); - else if (charge == 0) GLog.i( Messages.get(this, "no_charge") ); + if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (curSeedEffect == null) GLog.i( Messages.get(this, "no_effect") ); + else if (charge < seedChargeReqs.get(curSeedEffect)) GLog.i( Messages.get(this, "low_charge") ); else { - Buff.prolong(hero, Roots.class, Roots.DURATION); - Buff.affect(hero, Earthroot.Armor.class).level(charge); - CellEmitter.bottom(hero.pos).start(EarthParticle.FACTORY, 0.05f, 8); - Camera.main.shake(1, 0.4f); - charge = 0; - Talent.onArtifactUsed(Dungeon.hero); - updateQuickslot(); + GameScene.selectCell(cellSelector); } } } @@ -116,6 +164,14 @@ public class SandalsOfNature extends Artifact { target.buff(Naturalism.class).charge(amount); } + @Override + public ItemSprite.Glowing glowing() { + if (curSeedEffect != null){ + return new ItemSprite.Glowing(seedColors.get(curSeedEffect)); + } + return null; + } + @Override public String name() { if (level() == 0) return super.name(); @@ -126,16 +182,19 @@ public class SandalsOfNature extends Artifact { public String desc() { String desc = Messages.get(this, "desc_" + (level()+1)); - if ( isEquipped ( Dungeon.hero ) ){ + if ( isEquipped ( Dungeon.hero ) ) { desc += "\n\n"; - if (!cursed) + if (!cursed) { desc += Messages.get(this, "desc_hint"); - else + } else { desc += Messages.get(this, "desc_cursed"); + } - if (level() > 0) - desc += "\n\n" + Messages.get(this, "desc_ability"); + } + + if (curSeedEffect != null){ + desc += "\n\n" + Messages.get(this, "desc_ability", seedChargeReqs.get(curSeedEffect)); } if (!seeds.isEmpty()){ @@ -155,23 +214,29 @@ public class SandalsOfNature extends Artifact { } public boolean canUseSeed(Item item){ - return item instanceof Plant.Seed && !seeds.contains(item.getClass()); + return item instanceof Plant.Seed + && !seeds.contains(item.getClass()) + && (level() < 3 || curSeedEffect != item.getClass()); } - private static final String SEEDS = "seeds"; + private static final String CUR_SEED_EFFECT = "cur_seed_effect"; @Override public void storeInBundle( Bundle bundle ) { super.storeInBundle(bundle); bundle.put(SEEDS, seeds.toArray(new Class[seeds.size()])); + bundle.put(CUR_SEED_EFFECT, curSeedEffect); } @Override public void restoreFromBundle( Bundle bundle ) { super.restoreFromBundle(bundle); - if (bundle.contains(SEEDS)) - Collections.addAll(seeds , bundle.getClassArray(SEEDS)); + if (bundle.contains(SEEDS)) { + Collections.addAll(seeds, bundle.getClassArray(SEEDS)); + } + curSeedEffect = bundle.getClass(CUR_SEED_EFFECT); + if (level() == 1) image = ItemSpriteSheet.ARTIFACT_SHOES; else if (level() == 2) image = ItemSpriteSheet.ARTIFACT_BOOTS; else if (level() >= 3) image = ItemSpriteSheet.ARTIFACT_GREAVES; @@ -180,16 +245,17 @@ public class SandalsOfNature extends Artifact { public class Naturalism extends ArtifactBuff{ public void charge(float amount) { if (cursed || target.buff(MagicImmune.class) != null) return; - if (level() > 0 && charge < target.HT){ - //gain 1+(1*level)% of the difference between current charge and max HP. - float chargeGain = (target.HT-charge) * (.01f+ level()*0.01f); + if (charge < chargeCap){ + //0.5 charge per grass at +0, up to 1 at +10 + float chargeGain = (3f + level())/6f; chargeGain *= amount; chargeGain *= RingOfEnergy.artifactChargeMultiplier(target); partialCharge += Math.max(0, chargeGain); - while (partialCharge > 1){ + while (partialCharge >= 1){ charge++; partialCharge--; } + charge = Math.min(charge, chargeCap); updateQuickslot(); } } @@ -215,30 +281,58 @@ public class SandalsOfNature extends Artifact { @Override public void onSelect( Item item ) { if (item != null && item instanceof Plant.Seed) { - if (seeds.contains(item.getClass())){ - GLog.w( Messages.get(SandalsOfNature.class, "already_fed") ); - } else { - seeds.add(item.getClass()); + if (level() < 3) seeds.add(0, item.getClass()); + curSeedEffect = item.getClass(); - Hero hero = Dungeon.hero; - hero.sprite.operate( hero.pos ); - Sample.INSTANCE.play( Assets.Sounds.PLANT ); - hero.busy(); - hero.spend( 2f ); - if (seeds.size() >= 3+(level()*3)){ - seeds.clear(); - upgrade(); - if (level() >= 1 && level() <= 3) { - GLog.p( Messages.get(SandalsOfNature.class, "levelup") ); - } + Hero hero = Dungeon.hero; + hero.sprite.operate( hero.pos ); + Sample.INSTANCE.play( Assets.Sounds.PLANT ); + hero.busy(); + hero.spend( Actor.TICK ); + if (seeds.size() >= 4+(level()*3)){ + seeds.clear(); + upgrade(); - } else { - GLog.i( Messages.get(SandalsOfNature.class, "absorb_seed") ); + if (level() >= 1 && level() <= 3) { + GLog.p( Messages.get(SandalsOfNature.class, "levelup") ); } - item.detach(hero.belongings.backpack); + + } else { + GLog.i( Messages.get(SandalsOfNature.class, "absorb_seed") ); } + item.detach(hero.belongings.backpack); } } }; + protected CellSelector.Listener cellSelector = new CellSelector.Listener(){ + + @Override + public void onSelect(Integer cell) { + if (cell != null){ + PathFinder.buildDistanceMap(curUser.pos, BArray.not(Dungeon.level.solid,null), 3); + + if (PathFinder.distance[cell] == Integer.MAX_VALUE){ + GLog.w(Messages.get(SandalsOfNature.class, "out_of_range")); + } else { + CellEmitter.get( cell ).burst( LeafParticle.GENERAL, 6 ); + + Plant plant = ((Plant.Seed) Reflection.newInstance(curSeedEffect)).couch(cell, null); + plant.activate(Actor.findChar(cell)); + Sample.INSTANCE.play(Assets.Sounds.TRAMPLE, 1, Random.Float( 0.96f, 1.05f ) ); + + charge -= seedChargeReqs.get(curSeedEffect); + Talent.onArtifactUsed(Dungeon.hero); + updateQuickslot(); + curUser.spendAndNext(1f); + } + } + } + + @Override + public String prompt() { + return Messages.get(SandalsOfNature.class, "prompt_target"); + } + }; + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java index 38ffdfb11..2403c07d4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java @@ -122,13 +122,13 @@ public class HighGrass { } if (naturalismLevel >= 0) { - // Seed, scales from 1/25 to 1/5 - if (Random.Int(25 - (naturalismLevel * 5)) == 0) { + // Seed, scales from 1/25 to 1/9 + if (Random.Int(25 - (naturalismLevel * 4)) == 0) { level.drop(Generator.random(Generator.Category.SEED), pos).sprite.drop(); } - // Dew, scales from 1/6 to 1/3 - if (Random.Int(24 - naturalismLevel*3) <= 3) { + // Dew, scales from 1/6 to 1/4 + if (Random.Int(6 - naturalismLevel/2) == 0) { level.drop(new Dewdrop(), pos).sprite.drop(); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Rotberry.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Rotberry.java index 6e16af1a0..6c6b16a80 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Rotberry.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Rotberry.java @@ -48,8 +48,6 @@ public class Rotberry extends Plant { } else { GameScene.add( Blob.seed( pos, 100, ToxicGas.class ) ); } - - Dungeon.level.drop( new Seed(), pos ).sprite.drop(); } @Override @@ -59,8 +57,9 @@ public class Rotberry extends Plant { if (Dungeon.level.heroFOV[pos]) { CellEmitter.get( pos ).burst( LeafParticle.GENERAL, 6 ); } - - //no warden benefit + + //seed always drops, no lotus benefit + Dungeon.level.drop( new Seed(), pos ).sprite.drop(); } public static class Seed extends Plant.Seed {