v0.4.1: reworked evil eyes
This commit is contained in:
parent
52fc2b1a7d
commit
093635c454
|
@ -31,11 +31,14 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Dewdrop;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Vampiric;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
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.EyeSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
@ -54,6 +57,8 @@ public class Eye extends Mob {
|
|||
|
||||
flying = true;
|
||||
|
||||
HUNTING = new Hunting();
|
||||
|
||||
loot = new Dewdrop();
|
||||
lootChance = 0.5f;
|
||||
|
||||
|
@ -61,18 +66,8 @@ public class Eye extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int drRoll() {
|
||||
return Random.NormalIntRange(0, 10);
|
||||
}
|
||||
|
||||
private Ballistica beam;
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
|
||||
beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN);
|
||||
|
||||
return beam.subPath(1, beam.dist).contains(enemy.pos);
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange(20, 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,44 +76,88 @@ public class Eye extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return 1.6f;
|
||||
public int drRoll() {
|
||||
return Random.NormalIntRange(0, 10);
|
||||
}
|
||||
|
||||
private Ballistica beam;
|
||||
private int beamCooldown;
|
||||
public boolean beamCharged;
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
|
||||
if (beamCooldown == 0) {
|
||||
Ballistica aim = new Ballistica(pos, enemy.pos, Ballistica.STOP_TERRAIN);
|
||||
|
||||
if (enemy.invisible == 0 && aim.subPath(1, aim.dist).contains(enemy.pos)){
|
||||
beam = aim;
|
||||
return true;
|
||||
} else
|
||||
//if the beam is charged, it has to attack, will aim at previous location of hero.
|
||||
return beamCharged;
|
||||
} else
|
||||
return super.canAttack(enemy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
if (beamCooldown > 0)
|
||||
beamCooldown--;
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
|
||||
if (beamCooldown > 0) {
|
||||
return super.doAttack(enemy);
|
||||
} else if (!beamCharged){
|
||||
((EyeSprite)sprite).charge( enemy.pos );
|
||||
spend( attackDelay()*2f );
|
||||
beamCharged = true;
|
||||
return true;
|
||||
} else {
|
||||
|
||||
spend( attackDelay() );
|
||||
|
||||
boolean rayVisible = false;
|
||||
|
||||
for (int i : beam.subPath(0, beam.dist)) {
|
||||
if (Dungeon.visible[i]) {
|
||||
rayVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rayVisible) {
|
||||
sprite.attack( beam.collisionPos );
|
||||
if (Dungeon.visible[pos]) {
|
||||
sprite.zap( beam.collisionPos );
|
||||
return false;
|
||||
} else {
|
||||
attack( enemy );
|
||||
deathGaze();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attack( Char enemy ) {
|
||||
}
|
||||
|
||||
public void deathGaze(){
|
||||
if (!beamCharged || beamCooldown > 0 || beam == null)
|
||||
return;
|
||||
|
||||
beamCharged = false;
|
||||
beamCooldown = Random.IntRange(3, 6);
|
||||
|
||||
boolean terrainAffected = false;
|
||||
|
||||
for (int pos : beam.subPath(1, beam.dist)) {
|
||||
|
||||
if (Level.flamable[pos]) {
|
||||
|
||||
Dungeon.level.destroy( pos );
|
||||
GameScene.updateMap( pos );
|
||||
terrainAffected = true;
|
||||
|
||||
}
|
||||
|
||||
Char ch = Actor.findChar( pos );
|
||||
if (ch == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hit( this, ch, true )) {
|
||||
ch.damage( Random.NormalIntRange( 14, 20 ), this );
|
||||
ch.damage( Random.NormalIntRange( 30, 40 ), this );
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
ch.sprite.flash();
|
||||
|
@ -134,7 +173,34 @@ public class Eye extends Mob {
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (terrainAffected) {
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
beam = null;
|
||||
sprite.idle();
|
||||
}
|
||||
|
||||
private static final String BEAM_TARGET = "beamTarget";
|
||||
private static final String BEAM_COOLDOWN = "beamCooldown";
|
||||
private static final String BEAM_CHARGED = "beamCharged";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
if (beam != null)
|
||||
bundle.put( BEAM_TARGET, beam.collisionPos);
|
||||
bundle.put( BEAM_COOLDOWN, beamCooldown );
|
||||
bundle.put( BEAM_CHARGED, beamCharged );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
if (bundle.contains(BEAM_TARGET))
|
||||
beam = new Ballistica(pos, bundle.getInt(BEAM_TARGET), Ballistica.STOP_TERRAIN);
|
||||
beamCooldown = bundle.getInt(BEAM_COOLDOWN);
|
||||
beamCharged = bundle.getBoolean(BEAM_CHARGED);
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<>();
|
||||
|
@ -158,4 +224,14 @@ public class Eye extends Mob {
|
|||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
|
||||
private class Hunting extends Mob.Hunting{
|
||||
@Override
|
||||
public boolean act(boolean enemyInFOV, boolean justAlerted) {
|
||||
//always attack if the beam is charged, no exceptions
|
||||
if (beamCharged)
|
||||
enemyInFOV = true;
|
||||
return super.act(enemyInFOV, justAlerted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,6 +193,17 @@ public class MagicMissile extends Emitter {
|
|||
};
|
||||
};
|
||||
|
||||
public static final Emitter.Factory ATTRACTING = new Factory() {
|
||||
@Override
|
||||
public void emit( Emitter emitter, int index, float x, float y ) {
|
||||
((MagicParticle)emitter.recycle( MagicParticle.class )).resetAttract( x, y );
|
||||
}
|
||||
@Override
|
||||
public boolean lightMode() {
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
public MagicParticle() {
|
||||
super();
|
||||
|
||||
|
@ -211,6 +222,17 @@ public class MagicMissile extends Emitter {
|
|||
left = lifespan;
|
||||
}
|
||||
|
||||
public void resetAttract( float x, float y) {
|
||||
revive();
|
||||
|
||||
//size = 8;
|
||||
left = lifespan;
|
||||
|
||||
speed.polar( Random.Float( PointF.PI2 ), Random.Float( 16, 32 ) );
|
||||
this.x = x - speed.x * lifespan;
|
||||
this.y = y - speed.y * lifespan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
|
|
@ -384,7 +384,7 @@ actors.mobs.elemental.desc=Wandering fire elementals are a byproduct of summonin
|
|||
|
||||
actors.mobs.eye.name=evil eye
|
||||
actors.mobs.eye.deathgaze_kill=The deathgaze killed you...
|
||||
actors.mobs.eye.desc=One of this demon's other names is "orb of hatred", because when it sees an enemy, it uses its deathgaze recklessly, often ignoring its allies and wounding them.
|
||||
actors.mobs.eye.desc=Evil Eyes are floating balls of pent up demonic energy. While they are capable of melee combat, their true strength comes from their magic.\n\nAfter building energy for a short time an Evil Eye will unleash a devastating beam of energy called the _deathgaze._ Anything within the Evil Eye's sights will take tremendous damage, wise adventurers will run for cover.
|
||||
|
||||
actors.mobs.fetidrat.name=fetid rat
|
||||
actors.mobs.fetidrat.desc=Something is clearly wrong with this rat. Its greasy black fur and rotting skin are very different from the healthy rats you've seen previously. It's pale green eyes make it seem especially menacing.\n\nThe rat carries a cloud of horrible stench with it, it's overpoweringly strong up close.\n\nDark ooze dribbles from the rat's mouth, it eats through the floor but seems to dissolve in water.
|
||||
|
|
|
@ -23,12 +23,19 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||
import com.watabou.noosa.TextureFilm;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
|
||||
public class EyeSprite extends MobSprite {
|
||||
|
||||
private int attackPos;
|
||||
private int zapPos;
|
||||
|
||||
private Animation charging;
|
||||
private Emitter chargeParticles;
|
||||
|
||||
public EyeSprite() {
|
||||
super();
|
||||
|
@ -40,11 +47,20 @@ public class EyeSprite extends MobSprite {
|
|||
idle = new Animation( 8, true );
|
||||
idle.frames( frames, 0, 1, 2 );
|
||||
|
||||
charging = new Animation( 12, true);
|
||||
charging.frames( frames, 3, 4 );
|
||||
|
||||
chargeParticles = centerEmitter();
|
||||
chargeParticles.autoKill = false;
|
||||
chargeParticles.pour(MagicMissile.MagicParticle.ATTRACTING, 0.05f);
|
||||
chargeParticles.on = false;
|
||||
|
||||
run = new Animation( 12, true );
|
||||
run.frames( frames, 5, 6 );
|
||||
|
||||
attack = new Animation( 8, false );
|
||||
attack.frames( frames, 4, 3 );
|
||||
zap = attack.clone();
|
||||
|
||||
die = new Animation( 8, false );
|
||||
die.frames( frames, 7, 8, 9 );
|
||||
|
@ -53,19 +69,47 @@ public class EyeSprite extends MobSprite {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void attack( int pos ) {
|
||||
attackPos = pos;
|
||||
super.attack( pos );
|
||||
public void link(Char ch) {
|
||||
super.link(ch);
|
||||
if (((Eye)ch).beamCharged) play(charging);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
chargeParticles.pos(center());
|
||||
chargeParticles.visible = visible;
|
||||
}
|
||||
|
||||
public void charge( int pos ){
|
||||
turnTo(ch.pos, pos);
|
||||
play(charging);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play(Animation anim) {
|
||||
chargeParticles.on = anim == charging;
|
||||
super.play(anim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zap( int pos ) {
|
||||
zapPos = pos;
|
||||
super.zap( pos );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete( Animation anim ) {
|
||||
super.onComplete( anim );
|
||||
|
||||
if (anim == attack) {
|
||||
if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) {
|
||||
parent.add( new Beam.DeathRay( center(), DungeonTilemap.tileCenterToWorld( attackPos ) ) );
|
||||
if (anim == zap) {
|
||||
if (Dungeon.visible[ch.pos] || Dungeon.visible[zapPos]) {
|
||||
parent.add( new Beam.DeathRay( center(), DungeonTilemap.tileCenterToWorld( zapPos ) ) );
|
||||
}
|
||||
((Eye)ch).deathGaze();
|
||||
ch.next();
|
||||
} else if (anim == die){
|
||||
chargeParticles.killAndErase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user