v0.8.0: various tweaks and adjustments, mainly for demon halls:

- added missing properties to rippers and spawners
- fixed rippers having long visibility range, increased their damage by 11%
- reduced the bleed damage from new ripper leap
- rippers now interrupt the hero when leaping
- adjusted candle positions in Yog's boss level
- added more text (including warnings) for demon spawners
- adjusted the positioning of Yog's sprite
- fixed cases where angled visuals would be incorrectly not visible
- removed redundant declarations from Ring of Elements, it now copies from AntiMagic
This commit is contained in:
Evan Debenham 2020-03-19 04:05:56 -04:00
parent ab5a37d3d5
commit 099073dd89
11 changed files with 54 additions and 65 deletions

View File

@ -272,6 +272,9 @@ public class Visual extends Gizmo {
if (c == null || !visible) return false;
//FIXME, the below calculations ignore angle, so assume visible if angle != 0
if (angle != 0) return true;
//x coord
if (x > c.scroll.x + c.width)
return false;

View File

@ -47,7 +47,7 @@ public abstract class Actor implements Bundlable {
protected static final int VFX_PRIO = 100; //visual effects take priority
protected static final int HERO_PRIO = 0; //positive is before hero, negative after
protected static final int BLOB_PRIO = -10; //blobs act after hero, before mobs
protected static final int MOB_PRIO = -20; //mobs act between buffs and blobd
protected static final int MOB_PRIO = -20; //mobs act between buffs and blobs
protected static final int BUFF_PRIO = -30; //buffs act last in a turn
private static final int DEFAULT = -100; //if no priority is given, act after all else

View File

@ -31,8 +31,10 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SpawnerSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
@ -57,6 +59,7 @@ public class DemonSpawner extends Mob {
properties.add(Property.IMMOVABLE);
properties.add(Property.MINIBOSS);
properties.add(Property.DEMONIC);
}
@Override
@ -76,7 +79,7 @@ public class DemonSpawner extends Mob {
private float spawnCooldown = 0;
private boolean spawnRecorded = false;
public boolean spawnRecorded = false;
@Override
protected boolean act() {
@ -133,6 +136,7 @@ public class DemonSpawner extends Mob {
if (spawnRecorded){
Statistics.spawnersAlive--;
}
GLog.h(Messages.get(this, "on_death"));
super.die(cause);
}

View File

@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
@ -46,6 +47,7 @@ public class RipperDemon extends Mob {
HP = HT = 60;
defenseSkill = 22;
viewDistance = Light.DISTANCE;
EXP = 9; //for corrupting
maxLvl = -2;
@ -53,6 +55,9 @@ public class RipperDemon extends Mob {
HUNTING = new Hunting();
baseSpeed = 1f;
properties.add(Property.DEMONIC);
properties.add(Property.UNDEAD);
}
@Override
@ -62,7 +67,7 @@ public class RipperDemon extends Mob {
@Override
public int damageRoll() {
return Random.NormalIntRange( 12, 24 );
return Random.NormalIntRange( 15, 25 );
}
@Override
@ -136,7 +141,7 @@ public class RipperDemon extends Mob {
Char ch = Actor.findChar(leapPos);
if (ch != null){
if (alignment != ch.alignment){
Buff.affect(ch, Bleeding.class).set(Math.max(damageRoll(), damageRoll()));
Buff.affect(ch, Bleeding.class).set(0.75f*Math.max(damageRoll(), damageRoll()));
ch.sprite.flash();
Sample.INSTANCE.play(Assets.SND_HIT);
}
@ -201,11 +206,10 @@ public class RipperDemon extends Mob {
//get ready to leap
leapPos = targetPos;
spend(TICK);
if (Dungeon.level.heroFOV[leapPos]) {
sprite.parent.addToBack(new TargetedCell(leapPos, 0xFF0000));
}
if (Dungeon.level.heroFOV[pos]){
GLog.w(Messages.get(RipperDemon.this, "leap"));
sprite.parent.addToBack(new TargetedCell(leapPos, 0xFF0000));
Dungeon.hero.interrupt();
}
return true;
}

View File

@ -34,25 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vulnerable;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM100;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shaman;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Warlock;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLivingEarth;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfPrismaticLight;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTransfusion;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.AntiMagic;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import java.text.DecimalFormat;
@ -83,34 +65,10 @@ public class RingOfElements extends Ring {
RESISTS.add( Poison.class );
RESISTS.add( Corrosion.class );
RESISTS.add( Charm.class );
RESISTS.add( Weakness.class );
RESISTS.add( Vulnerable.class );
RESISTS.add( Hex.class );
RESISTS.add( Degrade.class );
RESISTS.add( DisintegrationTrap.class );
RESISTS.add( GrimTrap.class );
RESISTS.add( WandOfBlastWave.class );
RESISTS.add( WandOfDisintegration.class );
RESISTS.add( WandOfFireblast.class );
RESISTS.add( WandOfFrost.class );
RESISTS.add( WandOfLightning.class );
RESISTS.add( WandOfLivingEarth.class );
RESISTS.add( WandOfMagicMissile.class );
RESISTS.add( WandOfPrismaticLight.class );
RESISTS.add( WandOfTransfusion.class );
RESISTS.add( WandOfWarding.Ward.class );
RESISTS.add( ToxicGas.class );
RESISTS.add( Electricity.class );
RESISTS.add( DM100.LightningBolt.class );
RESISTS.add( Shaman.EarthenBolt.class );
RESISTS.add( Warlock.DarkBolt.class );
RESISTS.add( Eye.DeathGaze.class );
RESISTS.add( Yog.BurningFist.DarkBolt.class );
RESISTS.addAll( AntiMagic.RESISTS );
}
public static float resist( Char target, Class effect ){

View File

@ -307,10 +307,10 @@ public class LastLevel extends Level {
private static final int[] map = new int[]{
-1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1,
0, 0, 0, 0, 8, 9, 10, 11, 19, 11, 12, 13, 14, 0, 0, 0,
0, 0, 0, 0, 16, 17, 18, 19, 19, 19, 20, 21, 22, 0, 0, 0,
0, 0, 0, 0, 24, 25, 26, 31, 19, 31, 28, 29, 30, 0, 0, 0,
0, 0, 0, 0, 16, 17, 18, 31, 19, 31, 20, 21, 22, 0, 0, 0,
0, 0, 0, 0, 24, 25, 26, 19, 19, 19, 28, 29, 30, 0, 0, 0,
0, 0, 0, 0, 24, 25, 26, 19, 19, 19, 28, 29, 30, 0, 0, 0,
0, 0, 0, 0, 24, 25, 26, 19, 19, 19, 28, 29, 30, 0, 0, 0,
0, 0, 0, 0, 24, 25, 26, 31, 19, 31, 28, 29, 30, 0, 0, 0,
0, 0, 0, 0, 24, 25, 34, 35, 35, 35, 34, 29, 30, 0, 0, 0,
0, 0, 0, 0, 40, 41, 36, 36, 36, 36, 36, 40, 41, 0, 0, 0,
0, 0, 0, 0, 48, 49, 36, 36, 36, 36, 36, 48, 49, 0, 0, 0,

View File

@ -127,10 +127,9 @@ public class NewHallsBossLevel extends Level {
Painter.fill(this, ROOM_LEFT, ROOM_BOTTOM-1, 2, 2, Terrain.WALL_DECO );
Painter.fill(this, ROOM_RIGHT-1, ROOM_BOTTOM-1, 2, 2, Terrain.WALL_DECO );
Painter.fill(this, ROOM_LEFT+3, ROOM_TOP+3, 3, 3, Terrain.EMPTY );
Painter.fill(this, ROOM_LEFT+3, ROOM_TOP+2, 3, 4, Terrain.EMPTY );
exit = width/2 + ((ROOM_TOP+1) * width);
//map[exit] = Terrain.EXIT;
CustomTilemap vis = new CenterPieceVisuals();
vis.pos(ROOM_LEFT, ROOM_TOP+1);
@ -186,14 +185,14 @@ public class NewHallsBossLevel extends Level {
super.occupyCell( ch );
if (map[entrance] == Terrain.ENTRANCE && map[exit] != Terrain.EXIT
&& ch == Dungeon.hero && ch.pos != entrance) {
&& ch == Dungeon.hero && Dungeon.level.distance(ch.pos, entrance) >= 2) {
seal();
}
}
@Override
public void seal() {
super.seal();
set( entrance, Terrain.EMPTY_SP );
GameScene.updateMap( entrance );
CellEmitter.get( entrance ).start( FlameParticle.FACTORY, 0.1f, 10 );
@ -280,10 +279,10 @@ public class NewHallsBossLevel extends Level {
private static final int[] map = new int[]{
8, 9, 10, 11, 11, 11, 12, 13, 14,
16, 17, 18, 19, 19, 19, 20, 21, 22,
24, 25, 26, 27, 19, 27, 28, 29, 30,
16, 17, 18, 27, 19, 27, 20, 21, 22,
24, 25, 26, 19, 19, 19, 28, 29, 30,
24, 25, 26, 19, 19, 19, 28, 29, 30,
24, 25, 26, 19, 19, 19, 28, 29, 30,
24, 25, 26, 27, 19, 27, 28, 29, 30,
24, 25, 34, 35, 35, 35, -1, 29, 30,
40, 41, 36, 36, 36, 36, 36, 40, 41,
48, 49, 36, 36, 36, 36, 36, 48, 49
@ -301,7 +300,7 @@ public class NewHallsBossLevel extends Level {
int[] data = map.clone();
if (Dungeon.level.map[Dungeon.level.exit] == Terrain.EXIT) {
data[4] = 19;
data[21] = data[23] = data[39] = data[41] = 31;
data[12] = data[14] = 31;
}
vis.map(data, tileW);
}

View File

@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
@ -441,6 +442,23 @@ public class GameScene extends PixelScene {
((DriedRose.GhostHero) ch).sayAppeared();
}
}
int spawnersAbove = Statistics.spawnersAlive;
if (spawnersAbove > 0) {
for (Mob m : Dungeon.level.mobs) {
if (m instanceof DemonSpawner && ((DemonSpawner) m).spawnRecorded) {
spawnersAbove--;
}
}
if (spawnersAbove > 0) {
if (Dungeon.bossLevel()) {
GLog.n(Messages.get(this, "spawner_warn_final"));
} else {
GLog.n(Messages.get(this, "spawner_warn"));
}
}
}
} else if (InterlevelScene.mode == InterlevelScene.Mode.RESET) {
GLog.h(Messages.get(this, "warp"));

View File

@ -31,7 +31,7 @@ public class YogSprite extends MobSprite {
public YogSprite() {
super();
perspectiveRaise = 0.2f;
perspectiveRaise = 5 / 16f;
texture( Assets.YOG );

View File

@ -482,7 +482,8 @@ actors.mobs.crystalmimic.escaped=The crystal mimic has escaped!
actors.mobs.crystalmimic.desc=Mimics are magical creatures which can take any shape they wish. In dungeons they almost always choose a shape of a treasure chest, in order to lure in unsuspecting adventurers.\n\nCrystal mimics are trickier than their regular cousins, and prefer to avoid conflict while stealing loot. They will attempt to sprint away once discovered, and have the ability to reposition enemies when they attack.
actors.mobs.demonspawner.name=demon spawner
actors.mobs.demonspawner.desc=This twisting amalgam of dwarven flesh is responsible for creating ripper demons from dwarven body parts. Clearly the demons see no issue with using every resource they can against their enemies.\n\nWhile visually terrifying, demon spawners have no means of moving or directly defending themselves. Their considerable mass makes them hard to kill quickly however, and they will spawn ripper demons more quickly when they are under threat.
actors.mobs.demonspawner.on_death=The demonic energy here seems to lessen as the spawner dies.
actors.mobs.demonspawner.desc=This twisting amalgam of dwarven flesh is responsible for creating ripper demons from the dwarves that have died in this region. Clearly the demons see no issue with using every resource they can against their enemies.\n\nWhile visually terrifying, demon spawners have no means of moving or directly defending themselves. Their considerable mass makes them hard to kill quickly however, and they will spawn ripper demons more quickly when they are under threat.\n\n_Demon spawners seem to be connected to some central source of demonic power. Killing them may weaken it._
actors.mobs.dm100.name=DM-100
actors.mobs.dm100.zap_kill=The lightning bolt killed you...

View File

@ -22,6 +22,8 @@ scenes.changesscene.misc=Miscellaneous Changes
scenes.changesscene.language=Language Improvements
scenes.gamescene.descend=You descend to floor %d of the dungeon.
scenes.gamescene.spawner_warn=You feel that there's a source of demonic energy above you...
scenes.gamescene.spawner_warn_final=You can feel demonic energy radiating here from the previous floors!
scenes.gamescene.warp=The walls warp and shift around you!
scenes.gamescene.return=You return to floor %d of the dungeon.
scenes.gamescene.chasm=Your steps echo across the dungeon.