v2.2.0: more crystal enemy impl
This commit is contained in:
@@ -21,11 +21,17 @@
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Healing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CrystalGuardianSprite;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
@@ -33,11 +39,34 @@ import com.watabou.utils.Random;
|
||||
public class CrystalGuardian extends Mob{
|
||||
|
||||
{
|
||||
HP = HT = 1;
|
||||
spriteClass = CrystalGuardianSprite.class;
|
||||
|
||||
HP = HT = 100;
|
||||
defenseSkill = 14;
|
||||
|
||||
EXP = 10;
|
||||
maxLvl = -2;
|
||||
|
||||
SLEEPING = new Sleeping();
|
||||
state = SLEEPING;
|
||||
|
||||
properties.add(Property.INORGANIC);
|
||||
properties.add(Property.MINIBOSS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 10, 20 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drRoll() {
|
||||
return super.drRoll() + Random.NormalIntRange(0, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,6 +74,17 @@ public class CrystalGuardian extends Mob{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
if (HP <= 0){
|
||||
HP = 1;
|
||||
if (sprite != null) ((CrystalGuardianSprite)sprite).crumple();
|
||||
spend(10f-cooldown());
|
||||
Buff.affect(this, Healing.class).setHeal(100, 0, 10);
|
||||
}
|
||||
return super.isAlive();
|
||||
}
|
||||
|
||||
public CrystalGuardian(){
|
||||
super();
|
||||
switch (Random.Int(3)){
|
||||
@@ -77,24 +117,32 @@ public class CrystalGuardian extends Mob{
|
||||
@Override
|
||||
public void beckon(int cell) {
|
||||
super.beckon(cell);
|
||||
state = HUNTING;
|
||||
}
|
||||
|
||||
//If we are still penned into our starting area, break out of it
|
||||
PathFinder.buildDistanceMap(cell, Dungeon.level.passable);
|
||||
if (PathFinder.distance[pos] == Integer.MAX_VALUE){
|
||||
boolean[] passable = Dungeon.level.passable.clone();
|
||||
@Override
|
||||
public void move(int step, boolean travelling) {
|
||||
super.move(step, travelling);
|
||||
if (Dungeon.level.map[pos] == Terrain.MINE_CRYSTAL){
|
||||
Level.set(pos, Terrain.EMPTY);
|
||||
GameScene.updateMap(pos);
|
||||
if (Dungeon.level.heroFOV[pos]){
|
||||
Splash.at(pos, 0xFFFFFF, 5);
|
||||
Sample.INSTANCE.play( Assets.Sounds.SHATTER );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] modifyPassable(boolean[] passable) {
|
||||
//TODO maybe base this on passable instead of hunting?
|
||||
// want to prevent one guardian randomly waking another though
|
||||
if (state == HUNTING){
|
||||
for (int i = 0; i < Dungeon.level.length(); i++){
|
||||
passable[i] = passable[i] || Dungeon.level.map[i] == Terrain.MINE_CRYSTAL;
|
||||
}
|
||||
PathFinder.Path p = PathFinder.find(pos, cell, passable);
|
||||
if (p != null) {
|
||||
for (int i : p) {
|
||||
if (Dungeon.level.map[i] == Terrain.MINE_CRYSTAL) {
|
||||
Level.set(i, Terrain.EMPTY);
|
||||
GameScene.updateMap(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return passable;
|
||||
}
|
||||
|
||||
protected class Sleeping extends Mob.Sleeping{
|
||||
|
||||
@@ -21,17 +21,34 @@
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AscensionChallenge;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CrystalWispSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class CrystalWisp extends Mob{
|
||||
|
||||
{
|
||||
HP = HT = 1;
|
||||
spriteClass = CrystalWispSprite.class;
|
||||
|
||||
HP = HT = 35;
|
||||
defenseSkill = 16;
|
||||
|
||||
EXP = 7;
|
||||
maxLvl = -2;
|
||||
|
||||
flying = true;
|
||||
|
||||
properties.add(Property.INORGANIC);
|
||||
}
|
||||
|
||||
public CrystalWisp(){
|
||||
@@ -57,6 +74,75 @@ public class CrystalWisp extends Mob{
|
||||
return passable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 3, 10 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drRoll() {
|
||||
return super.drRoll() + Random.NormalIntRange(0, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return super.canAttack(enemy)
|
||||
|| new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos;
|
||||
}
|
||||
|
||||
protected boolean doAttack(Char enemy ) {
|
||||
|
||||
if (Dungeon.level.adjacent( pos, enemy.pos )
|
||||
|| new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos != enemy.pos) {
|
||||
|
||||
return super.doAttack( enemy );
|
||||
|
||||
} else {
|
||||
|
||||
if (sprite != null && (sprite.visible || enemy.sprite.visible)) {
|
||||
sprite.zap( enemy.pos );
|
||||
return false;
|
||||
} else {
|
||||
zap();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//used so resistances can differentiate between melee and magical attacks
|
||||
public static class CrystalBolt{}
|
||||
|
||||
private void zap() {
|
||||
spend( 1f );
|
||||
|
||||
Invisibility.dispel(this);
|
||||
Char enemy = this.enemy;
|
||||
if (hit( this, enemy, true )) {
|
||||
|
||||
int dmg = Random.NormalIntRange( 2, 8 );
|
||||
dmg = Math.round(dmg * AscensionChallenge.statModifier(this));
|
||||
enemy.damage( dmg, new CrystalBolt() );
|
||||
|
||||
if (!enemy.isAlive() && enemy == Dungeon.hero) {
|
||||
Badges.validateDeathFromEnemyMagic();
|
||||
Dungeon.fail( this );
|
||||
GLog.n( Messages.get(this, "bolt_kill") );
|
||||
}
|
||||
} else {
|
||||
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
|
||||
}
|
||||
}
|
||||
|
||||
public void onZapComplete() {
|
||||
zap();
|
||||
next();
|
||||
}
|
||||
|
||||
public static final String SPRITE = "sprite";
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,11 +22,15 @@
|
||||
package com.shatteredpixel.shatteredpixeldungeon.sprites;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Healing;
|
||||
import com.watabou.noosa.MovieClip;
|
||||
import com.watabou.noosa.TextureFilm;
|
||||
|
||||
public abstract class CrystalGuardianSprite extends MobSprite {
|
||||
|
||||
private Animation crumple;
|
||||
|
||||
public CrystalGuardianSprite() {
|
||||
super();
|
||||
|
||||
@@ -48,9 +52,23 @@ public abstract class CrystalGuardianSprite extends MobSprite {
|
||||
die = new MovieClip.Animation( 5, false );
|
||||
die.frames( frames, 11+c, 12+c, 13+c, 14+c, 15+c, 15+c );
|
||||
|
||||
crumple = die.clone();
|
||||
|
||||
play( idle );
|
||||
}
|
||||
|
||||
public void crumple(){
|
||||
play(crumple);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void link(Char ch) {
|
||||
super.link(ch);
|
||||
if (ch.buff(Healing.class) != null && ch.cooldown() > 0){
|
||||
crumple();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int texOffset();
|
||||
|
||||
public static class Blue extends CrystalGuardianSprite {
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
package com.shatteredpixel.shatteredpixeldungeon.sprites;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalWisp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||
import com.watabou.noosa.TextureFilm;
|
||||
|
||||
public abstract class CrystalWispSprite extends MobSprite {
|
||||
@@ -52,6 +55,23 @@ public abstract class CrystalWispSprite extends MobSprite {
|
||||
play( idle );
|
||||
}
|
||||
|
||||
public void zap( int cell ) {
|
||||
|
||||
super.zap( cell );
|
||||
|
||||
((CrystalWisp)ch).onZapComplete();
|
||||
parent.add( new Beam.LightRay(center(), DungeonTilemap.raisedTileCenterToWorld(cell)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete( Animation anim ) {
|
||||
if (anim == zap) {
|
||||
idle();
|
||||
}
|
||||
super.onComplete( anim );
|
||||
}
|
||||
|
||||
protected abstract int texOffset();
|
||||
|
||||
public static class Blue extends CrystalWispSprite {
|
||||
|
||||
Reference in New Issue
Block a user