From c174e998bc1b9d5ae67fe6dc9f22f73fd0154b0e Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 7 Jul 2019 16:35:50 -0400 Subject: [PATCH] v0.7.4: various polish for both new wands --- core/src/main/assets/guardian.png | Bin 0 -> 1030 bytes .../shatteredpixeldungeon/Assets.java | 1 + .../items/wands/Wand.java | 8 +++- .../items/wands/WandOfLivingEarth.java | 39 ++++++++++------ .../items/wands/WandOfWarding.java | 44 ++++++++++++++++-- .../sprites/EarthGuardianSprite.java | 35 ++++++++++++++ .../messages/items/items.properties | 41 ++++++++++++---- 7 files changed, 137 insertions(+), 31 deletions(-) create mode 100644 core/src/main/assets/guardian.png create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/EarthGuardianSprite.java diff --git a/core/src/main/assets/guardian.png b/core/src/main/assets/guardian.png new file mode 100644 index 0000000000000000000000000000000000000000..589f6b52ef8e1e7f3ff35f729e382d123d0e2b4b GIT binary patch literal 1030 zcmV+h1o``kP)*FdzU!EdXUi05c*0Lo5JgLjX1;075JPIVJ!>D*$9e02vVgRXG436#!T} z045p$TRi|S9{^oG0D4gXmSg~SP5_Ku0C7tIf>r=-NdRm}0A4--cu)XLGXP;h0IQ$? z|Mh4`F92de08TUjRX6}YDgcvW06r-IT08)ORsd5t06;1LhFJhtIsh^u0Dn~gTs;6@ zKL9!>02&eiQ#Sx1764B*04N#&OELg!M*uG$07x(ZX+{7vBLFxh0H*B6BLDyZ0d!JM zQvg8b*k%9#0_#acK~#7Fw3P1-nlKc_{Zo`eiv#CMDXUWTs<`d_A8%#c(5y2}qwIY8 zos$dno{%m^Etd#UjEbMZIBZrc7q8cj30eGakz}(;NHpWQqh~Mz- zX1pjkTTDWpRl6^nK_rU3bBAZVIAF?((v;He5bwWInp2t$eE4SfFN$gFzj(d^L~TW4 z8P6R%hJYm16+~*Bxgewi@_@0(J?WBh3DyF*9Ba zHK6exD9h9pu+Loq2hO$TEQ;S0h}ues=RYha?rWF3bNe$B_x&_8#V{5yI5gH-hT+*C zviaFGQV#q}*&DD`>S4Ll_SQRT9mnsf7sC8m`{}cp7=E``zpD+xP!z!X7BYhCCe*gO zX*E`Ro2E_wy#GV(d)de_$t~^aDQjBKvLsMFm)41o zo%grSPx9QzhvM54Bh29^a$q2~hWTfIq)dR5`$zm(SuFY?{nrjl`;=}Q9||6)dRC+l zmejHFfa$4mCijooTH7y(bFN51`9sUhA83L(f|Me07*qoM6N<$g1mpU A0{{R3 literal 0 HcmV?d00001 diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index e468fe9a0..9d73f2a74 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -98,6 +98,7 @@ public class Assets { public static final String ROT_HEART= "rot_heart.png"; public static final String GUARD = "guard.png"; public static final String WARDS = "wards.png"; + public static final String GUARDIAN = "guardian.png"; public static final String ITEMS = "items.png"; public static final String TERRAIN_FEATURES = "terrain_features.png"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java index 5d18ee1cc..ddd7de65c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java @@ -161,11 +161,15 @@ public abstract class Wand extends Item { } protected void processSoulMark(Char target, int chargesUsed){ + processSoulMark(target, level(), chargesUsed); + } + + protected static void processSoulMark(Char target, int wandLevel, int chargesUsed){ if (target != Dungeon.hero && Dungeon.hero.subClass == HeroSubClass.WARLOCK && //standard 1 - 0.92^x chance, plus 7%. Starts at 15% - Random.Float() > (Math.pow(0.92f, (level()*chargesUsed)+1) - 0.07f)){ - SoulMark.prolong(target, SoulMark.class, SoulMark.DURATION + level()); + Random.Float() > (Math.pow(0.92f, (wandLevel*chargesUsed)+1) - 0.07f)){ + SoulMark.prolong(target, SoulMark.class, SoulMark.DURATION + wandLevel); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLivingEarth.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLivingEarth.java index 36ee7f676..60c5bf407 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLivingEarth.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfLivingEarth.java @@ -34,8 +34,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.EarthGuardianSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; -import com.shatteredpixel.shatteredpixeldungeon.sprites.StatueSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; @@ -56,13 +56,14 @@ public class WandOfLivingEarth extends DamageWand { @Override public int max(int lvl) { - return 6 + 3*lvl; + return 4 + 2*lvl; } @Override protected void onZap(Ballistica bolt) { Char ch = Actor.findChar(bolt.collisionPos); int damage = damageRoll(); + int armorToAdd = Math.round(damage*1.33f); EarthGuardian guardian = null; for (Mob m : Dungeon.level.mobs){ @@ -77,13 +78,13 @@ public class WandOfLivingEarth extends DamageWand { buff = Buff.affect(curUser, RockArmor.class); } if (buff != null){ - buff.addArmor(level(), damage); + buff.addArmor(level(), armorToAdd); } //shooting at the guardian if (guardian != null && guardian == ch){ guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 5 + level() / 2); - guardian.setInfo(curUser, level(), damage); + guardian.setInfo(curUser, level(), armorToAdd); processSoulMark(guardian, chargesPerCast()); //shooting the guardian at a location @@ -149,7 +150,7 @@ public class WandOfLivingEarth extends DamageWand { curUser.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 5 + level() / 2); } else { guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 5 + level() / 2); - guardian.setInfo(curUser, level(), damage); + guardian.setInfo(curUser, level(), armorToAdd); if (ch != null) guardian.aggro( ch ); } } @@ -253,8 +254,7 @@ public class WandOfLivingEarth extends DamageWand { public static class EarthGuardian extends NPC { { - //TODO visuals - spriteClass = StatueSprite.class; + spriteClass = EarthGuardianSprite.class; alignment = Alignment.ALLY; state = HUNTING; @@ -275,19 +275,25 @@ public class WandOfLivingEarth extends DamageWand { HT = 20 + 10 * wandLevel; } HP = Math.min(HT, HP + healthToAdd); - //same as the hero - defenseSkill = hero.lvl + 4; + //half of hero's evasion + defenseSkill = (hero.lvl + 4)/2; } @Override public int attackSkill(Char target) { //same as the hero - return defenseSkill + 5; + return 2*defenseSkill + 5; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (enemy instanceof Mob) ((Mob)enemy).aggro(this); + return super.attackProc(enemy, damage); } @Override public int damageRoll() { - return Random.NormalIntRange(wandLevel, 6 + 3*wandLevel); + return Random.NormalIntRange(2+wandLevel, 6 + 3*wandLevel); } @Override @@ -295,20 +301,25 @@ public class WandOfLivingEarth extends DamageWand { return Random.NormalIntRange(wandLevel, 4 + 4*wandLevel); } - private static final String DEFENCE = "defence"; + @Override + public String description() { + return Messages.get(this, "desc", wandLevel, 4 + 4*wandLevel); + } + + private static final String DEFENSE = "defense"; private static final String WAND_LEVEL = "wand_level"; @Override public void storeInBundle(Bundle bundle) { super.storeInBundle(bundle); - bundle.put(DEFENCE, defenseSkill); + bundle.put(DEFENSE, defenseSkill); bundle.put(WAND_LEVEL, wandLevel); } @Override public void restoreFromBundle(Bundle bundle) { super.restoreFromBundle(bundle); - defenseSkill = bundle.getInt(DEFENCE); + defenseSkill = bundle.getInt(DEFENSE); wandLevel = bundle.getInt(WAND_LEVEL); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java index 0034ec26e..074b01f1b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java @@ -9,6 +9,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC; import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -48,27 +49,28 @@ public class WandOfWarding extends Wand { ((Ward) ch).upgrade(level()); } else { if (((Ward) ch).tier <= 3){ - GLog.w("Your wand can't sustain any more wards."); + GLog.w( Messages.get(this, "no_more_wards")); } else { ((Ward) ch).wandHeal( level() ); } } ch.sprite.emitter().burst(MagicMissile.WardParticle.UP, ((Ward) ch).tier); } else { - GLog.w("There isn't room to place a ward here"); + GLog.w( Messages.get(this, "bad_location")); } } else if (canPlaceWard(bolt.collisionPos)){ if (canPlaceMore) { Ward ward = new Ward(); ward.pos = bolt.collisionPos; + ward.wandLevel = level(); GameScene.add(ward, 1f); ward.sprite.emitter().burst(MagicMissile.WardParticle.UP, ward.tier); QuickSlotButton.target(ward); } else { - GLog.w("Your wand can't sustain any more wards."); + GLog.w( Messages.get(this, "no_more_wards")); } } else { - GLog.w("There isn't room to place a ward here"); + GLog.w( Messages.get(this, "bad_location")); } } @@ -144,6 +146,8 @@ public class WandOfWarding extends Wand { viewDistance = 3; state = WANDERING; + + name = Messages.get(this, "name_" + tier ); } public void upgrade( int wandLevel ){ @@ -172,6 +176,7 @@ public class WandOfWarding extends Wand { if (tier < 6){ tier++; viewDistance++; + name = Messages.get(this, "name_" + tier ); updateSpriteState(); } } @@ -196,6 +201,23 @@ public class WandOfWarding extends Wand { } } + @Override + public int defenseSkill(Char enemy) { + if (tier > 3){ + defenseSkill = 4 + Dungeon.depth; + } + return super.defenseSkill(enemy); + } + + @Override + public int drRoll() { + if (tier > 3){ + return Math.round(Random.NormalIntRange(0, 3 + Dungeon.depth/2) / (7f - tier)); + } else { + return 0; + } + } + @Override protected float attackDelay() { switch (tier){ @@ -231,6 +253,9 @@ public class WandOfWarding extends Wand { //always hits int dmg = Random.Int( 2 + wandLevel, 8 + 4*wandLevel ); enemy.damage( dmg, WandOfWarding.class ); + if (enemy.isAlive()){ + Wand.processSoulMark(enemy, wandLevel, 1); + } if (!enemy.isAlive() && enemy == Dungeon.hero) { Dungeon.fail( getClass() ); @@ -295,7 +320,10 @@ public class WandOfWarding extends Wand { @Override public boolean interact() { - GameScene.show(new WndOptions("test", "dismiss this ward?", "yes", "no"){ + GameScene.show(new WndOptions( Messages.get(this, "dismiss_title"), + Messages.get(this, "dismiss_body"), + Messages.get(this, "dismiss_confirm"), + Messages.get(this, "dismiss_cancel") ){ @Override protected void onSelect(int index) { if (index == 0){ @@ -306,6 +334,11 @@ public class WandOfWarding extends Wand { return true; } + @Override + public String description() { + return Messages.get(this, "desc_" + tier, 2+wandLevel, 8 + 4*wandLevel ); + } + private static final String TIER = "tier"; private static final String WAND_LEVEL = "wand_level"; private static final String TOTAL_ZAPS = "total_zaps"; @@ -322,6 +355,7 @@ public class WandOfWarding extends Wand { public void restoreFromBundle(Bundle bundle) { super.restoreFromBundle(bundle); tier = bundle.getInt(TIER); + name = Messages.get(this, "name_" + tier ); wandLevel = bundle.getInt(WAND_LEVEL); totalZaps = bundle.getInt(TOTAL_ZAPS); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/EarthGuardianSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/EarthGuardianSprite.java new file mode 100644 index 000000000..32d5d4893 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/EarthGuardianSprite.java @@ -0,0 +1,35 @@ +package com.shatteredpixel.shatteredpixeldungeon.sprites; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.watabou.noosa.TextureFilm; + +public class EarthGuardianSprite extends MobSprite { + + public EarthGuardianSprite() { + super(); + + texture( Assets.GUARDIAN ); + + TextureFilm frames = new TextureFilm( texture, 12, 15 ); + + idle = new Animation( 2, true ); + idle.frames( frames, 0, 0, 0, 0, 0, 1, 1 ); + + run = new Animation( 15, true ); + run.frames( frames, 2, 3, 4, 5, 6, 7 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 8, 9, 10 ); + + die = new Animation( 5, false ); + die.frames( frames, 11, 12, 13, 14, 15, 15 ); + + play( idle ); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } + +} diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties index f23cfcd00..671034021 100644 --- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties +++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties @@ -1148,6 +1148,11 @@ items.wands.wandofblastwave.ondeath=You killed yourself with your own Wand of Bl items.wands.wandofblastwave.desc=This wand is made of a sort of marbled stone, with gold trim and a round black gem at the tip. It feels very weighty in your hand. items.wands.wandofblastwave.stats_desc=This wand shoots a bolt which violently detonates at a target location. The force of this blast deals _%1$d-%2$d damage_ and is strong enough to send most enemies flying. +items.wands.wandofcorrosion.name=wand of corrosion +items.wands.wandofcorrosion.staff_name=staff of corrosion +items.wands.wandofcorrosion.desc=This wand has an ashen body which opens to a brilliant orange gem. +items.wands.wandofcorrosion.stats_desc=This wand shoots a bolt which explodes into a cloud of highly corrosive gas at a targeted location. Anything caught inside this cloud will take continual damage, increasing with time. + items.wands.wandofcorruption.name=wand of corruption items.wands.wandofcorruption.staff_name=staff of corruption items.wands.wandofcorruption.already_corrupted=That character cannot be influenced further. @@ -1177,12 +1182,12 @@ items.wands.wandoflightning.stats_desc=This wand sends powerful lightning arcing items.wands.wandoflivingearth.name=wand of living earth items.wands.wandoflivingearth.staff_name=staff of living earth -items.wands.wandoflivingearth.desc=TODO -items.wands.wandoflivingearth.stats_desc=TODO\n\ndeals _%1$d-%2$d damage._ +items.wands.wandoflivingearth.desc=This wand is made from a curious rock, with bands of glowing yellow energy. The rocks seem to shift slightly as you grip the wand, as if they can feel your hand. +items.wands.wandoflivingearth.stats_desc=This wand sends bolts of magical rock at enemies, dealing _%1$d-%2$d damage._ The rocks will then re-form around the user, granting them armor in proportion to the damage dealt. If enough armor is built, it will form into a rock guardian when the wand is next zapped. items.wands.wandoflivingearth$rockarmor.name=Rock Armor -items.wands.wandoflivingearth$rockarmor.desc=TODO\n\nArmor: %1$d\n\nNeeded for Guardian: %2$d +items.wands.wandoflivingearth$rockarmor.desc=Magical rocks are surrounding your body, when you are attacked they will attempt to block for you, and will reduce the damage you take by 50%%. Each damage blocked scrapes away some of the rock however.\n\nRemaining Armor: %1$d.\n\nIf enough rock is built around you, the next zap from your wand of living earth with cause the rocks to form up into a guardian which will fight with you.\n\nArmor needed for Guardian: %2$d. items.wands.wandoflivingearth$earthguardian.name=earthen guardian -items.wands.wandoflivingearth$earthguardian.desc=TODO (probably want to give some basic stats) +items.wands.wandoflivingearth$earthguardian.desc=The rocks from your wand of living earth have formed into a protective earthen guardian! This rocky protector will attack nearby enemies, which will force them to focus the guardian instead of you. When all nearby threats are gone, the guardian will re-form around you, and will return when you next use your wand.\n\nThe guardian's defensive power is tied to the level of your wand. It currently blocks _%1$d-%2$d damage._ items.wands.wandofmagicmissile.name=wand of magic missile items.wands.wandofmagicmissile.staff_name=staff of magic missile @@ -1210,12 +1215,28 @@ items.wands.wandoftransfusion.charged=Your staff is charged with the life energy items.wands.wandoftransfusion.desc=A fairly plainly shaped wand, it stands out due to its magenta hue and pitch black gem at the tip. items.wands.wandoftransfusion.stats_desc=When used on allies, this wand saps some of your own health to heal or shield them. When used on enemies, the wand briefly charms them while pulling a bit of energy back to you. Hostile undead will be damaged instead of charmed. -items.wands.wandofcorrosion.name=wand of corrosion -items.wands.wandofcorrosion.staff_name=staff of corrosion -items.wands.wandofcorrosion.desc=This wand has an ashen body which opens to a brilliant orange gem. -items.wands.wandofcorrosion.stats_desc=This wand shoots a bolt which explodes into a cloud of highly corrosive gas at a targeted location. Anything caught inside this cloud will take continual damage, increasing with time. - - +items.wands.wandofwarding.name=wand of warding +items.wands.wandofwarding.staff_name=staff of warding +items.wands.wandofwarding.no_more_wards=Your wand can't sustain any more wards. +items.wands.wandofwarding.bad_location=There isn't enough room to place a ward here. +items.wands.wandofwarding.desc=This short metal wand has a bright purple gem floating above its tip. +items.wands.wandofwarding.stats_desc=Rather than directly damaging an enemy, this wand will summon stationary wards and sentries. Note that wards require some empty space around where they are summoned, and the wand can only sustain so many wards or sentries at one time. +items.wands.wandofwarding$ward.name_1=lesser ward +items.wands.wandofwarding$ward.desc_1=This basic ward will automatically zap any enemy which comes into its range of vision, dealing _%1$d-%2$d damage._\n\nZapping this ward with your wand of warding will upgrade it.\n\nThis ward will only zap a single time before dissipating. +items.wands.wandofwarding$ward.name_2=ward +items.wands.wandofwarding$ward.desc_2=This upgraded ward has a more intricate pattern, and can attack multiple times. Each zap from this ward will deal _%1$d-%2$d damage._\n\nZapping this ward with your wand of warding will upgrade it.\n\nThis ward will zap two times before dissipating. +items.wands.wandofwarding$ward.name_3=greater ward +items.wands.wandofwarding$ward.desc_3=This fully upgraded ward is able to attack more times, and more quickly, than its predecessors. Each zap from this ward will deal _%1$d-%2$d damage._\n\nZapping this ward with your wand of warding will upgrade it.\n\nThis ward will zap four times before dissipating. +items.wands.wandofwarding$ward.name_4=lesser sentry +items.wands.wandofwarding$ward.desc_4=This smaller sentry has the same attack power as a greater ward, but isn't nearly as fragile. It resembles the gem at the tip of your wand of warding. Each zap from this sentry will deal _%1$d-%2$d damage._\n\nZapping this sentry with your wand of warding will upgrade and heal it.\n\nThis sentry will spend some health each time it zaps an enemy, but can be healed by using your wand of warding on it. +items.wands.wandofwarding$ward.name_5=sentry +items.wands.wandofwarding$ward.desc_5=This upgraded sentry is larger and able to attack more quickly than a lesser sentry. Each zap from this sentry will deal _%1$d-%2$d damage._\n\nZapping this sentry with your wand of warding will upgrade and heal it.\n\nThis sentry will spend some health each time it zaps an enemy, but can be healed by using your wand of warding on it. +items.wands.wandofwarding$ward.name_6=greater sentry +items.wands.wandofwarding$ward.desc_6=This fully upgraded sentry is significantly more durable than its predecessors. Each zap from this sentry will deal _%1$d-%2$d damage._\n\nZapping this sentry with your wand of warding will heal it.\n\nThis sentry will spend some health each time it zaps an enemy, but can be healed by using your wand of warding on it. +items.wands.wandofwarding$ward.dismiss_title=Dismiss this ward? +items.wands.wandofwarding$ward.dismiss_body=You can dispel this ward if you no longer want your wand to maintain it. Doing so immediately doing so immediately destroys the ward.\n\nDismiss this ward? +items.wands.wandofwarding$ward.dismiss_confirm=yes +items.wands.wandofwarding$ward.dismiss_cancel=no ###weapon curses items.weapon.curses.annoying.name=annoying %s