v0.8.0: reworked elementals

This commit is contained in:
Evan Debenham 2019-11-12 09:50:00 -05:00
parent 309ef7806e
commit baea1ecf03
9 changed files with 496 additions and 101 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -118,6 +118,12 @@ public class ShatteredPixelDungeon extends Game {
com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM100.class,
"com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shaman");
com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental.Fire.class,
"com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental");
com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental.NewbornFire.class,
"com.shatteredpixel.shatteredpixeldungeon.actors.mobs.NewbornElemental");
}

View File

@ -60,6 +60,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental;
import com.shatteredpixel.shatteredpixeldungeon.items.BrokenSeal;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.AntiMagic;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Brimstone;
@ -69,6 +70,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetributio
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression;
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.weapon.enchantments.Blazing;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
@ -669,11 +671,13 @@ public abstract class Char extends Actor {
new HashSet<Class>( Arrays.asList(Bleeding.class, ToxicGas.class, Poison.class) )),
BLOB_IMMUNE ( new HashSet<Class>(),
new HashSet<Class>( Arrays.asList(Blob.class) )),
FIERY ( new HashSet<Class>( Arrays.asList(WandOfFireblast.class)),
FIERY ( new HashSet<Class>( Arrays.asList(WandOfFireblast.class, Elemental.Fire.class)),
new HashSet<Class>( Arrays.asList(Burning.class, Blazing.class))),
ICY ( new HashSet<Class>( Arrays.asList(WandOfFrost.class, Elemental.Frost.class)),
new HashSet<Class>( Arrays.asList(Frost.class, Chill.class))),
ACIDIC ( new HashSet<Class>( Arrays.asList(Corrosion.class)),
new HashSet<Class>( Arrays.asList(Ooze.class))),
ELECTRIC ( new HashSet<Class>( Arrays.asList(WandOfLightning.class, Shocking.class, Potential.class, Electricity.class, ShockingDart.class)),
ELECTRIC ( new HashSet<Class>( Arrays.asList(WandOfLightning.class, Shocking.class, Potential.class, Electricity.class, ShockingDart.class, Elemental.Shock.class )),
new HashSet<Class>()),
IMMOVABLE;

View File

@ -123,26 +123,26 @@ public class Bestiary {
case 16:
//5x elemental, 5x warlock, 1x monk
return new ArrayList<>(Arrays.asList(
Elemental.class, Elemental.class, Elemental.class, Elemental.class, Elemental.class,
Elemental.random(), Elemental.random(), Elemental.random(), Elemental.random(), Elemental.random(),
Warlock.class, Warlock.class, Warlock.class, Warlock.class, Warlock.class,
Monk.class));
case 17:
//2x elemental, 2x warlock, 2x monk
return new ArrayList<>(Arrays.asList(
Elemental.class, Elemental.class,
Elemental.random(), Elemental.random(),
Warlock.class, Warlock.class,
Monk.class, Monk.class));
case 18:
//1x elemental, 1x warlock, 2x monk, 1x golem
return new ArrayList<>(Arrays.asList(
Elemental.class,
Elemental.random(),
Warlock.class,
Monk.class, Monk.class,
Golem.class));
case 19: case 20:
//1x elemental, 1x warlock, 2x monk, 3x golem
return new ArrayList<>(Arrays.asList(
Elemental.class,
Elemental.random(),
Warlock.class,
Monk.class, Monk.class,
Golem.class, Golem.class, Golem.class));

View File

@ -21,33 +21,44 @@
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.blobs.Freezing;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning;
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfFrost;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLiquidFlame;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Embers;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.CursedWand;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Shocking;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ElementalSprite;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
public class Elemental extends Mob {
import java.util.ArrayList;
public abstract class Elemental extends Mob {
{
spriteClass = ElementalSprite.class;
HP = HT = 65;
HP = HT = 60;
defenseSkill = 20;
EXP = 10;
maxLvl = 20;
flying = true;
loot = new PotionOfLiquidFlame();
lootChance = 0.1f;
properties.add(Property.FIERY);
}
@Override
@ -65,26 +76,258 @@ public class Elemental extends Mob {
return Random.NormalIntRange(0, 5);
}
private int rangedCooldown = Random.NormalIntRange( 3, 5 );
@Override
protected boolean act() {
if (state == HUNTING){
rangedCooldown--;
}
return super.act();
}
@Override
protected boolean canAttack( Char enemy ) {
if (rangedCooldown <= 0) {
return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT ).collisionPos == enemy.pos;
} else {
return super.canAttack( enemy );
}
}
protected boolean doAttack( Char enemy ) {
if (Dungeon.level.adjacent( pos, 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;
}
}
}
@Override
public int attackProc( Char enemy, int damage ) {
damage = super.attackProc( enemy, damage );
if (Random.Int( 2 ) == 0) {
Buff.affect( enemy, Burning.class ).reignite( enemy );
}
meleeProc( enemy, damage );
return damage;
}
private void zap() {
spend( 1f );
if (hit( this, enemy, true )) {
rangedProc( enemy );
rangedCooldown = Random.NormalIntRange( 3, 5 );
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
}
public void onZapComplete() {
zap();
next();
}
@Override
public void add( Buff buff ) {
if (buff instanceof Frost || buff instanceof Chill) {
if (Dungeon.level.water[this.pos])
damage( Random.NormalIntRange( HT / 2, HT ), buff );
else
damage( Random.NormalIntRange( 1, HT * 2 / 3 ), buff );
if (harmfulBuffs.contains( buff.getClass() )) {
damage( Random.NormalIntRange( HT/2, HT * 3/5 ), buff );
} else {
super.add( buff );
}
}
protected abstract void meleeProc( Char enemy, int damage );
protected abstract void rangedProc( Char enemy );
protected ArrayList<Class<? extends Buff>> harmfulBuffs = new ArrayList<>();
private static final String COOLDOWN = "cooldown";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( COOLDOWN, rangedCooldown );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
if (bundle.contains( COOLDOWN )){
rangedCooldown = bundle.getInt( COOLDOWN );
}
}
public static class Fire extends Elemental {
{
spriteClass = ElementalSprite.Fire.class;
loot = new PotionOfLiquidFlame();
lootChance = 1/8f;
properties.add( Property.FIERY );
harmfulBuffs.add( com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost.class );
harmfulBuffs.add( Chill.class );
}
@Override
protected void meleeProc( Char enemy, int damage ) {
if (Random.Int( 2 ) == 0 && !Dungeon.level.water[enemy.pos]) {
Buff.affect( enemy, Burning.class ).reignite( enemy );
Splash.at( enemy.sprite.center(), sprite.blood(), 5);
}
}
@Override
protected void rangedProc( Char enemy ) {
if (!Dungeon.level.water[enemy.pos]) {
Buff.affect( enemy, Burning.class ).reignite( enemy, 4f );
}
Splash.at( enemy.sprite.center(), sprite.blood(), 5);
}
}
//used in wandmaker quest
public static class NewbornFire extends Fire {
{
spriteClass = ElementalSprite.NewbornFire.class;
HT = 60;
HP = HT/2; //32
defenseSkill = 12;
EXP = 7;
loot = new Embers();
lootChance = 1f;
properties.add(Property.MINIBOSS);
}
}
public static class Frost extends Elemental {
{
spriteClass = ElementalSprite.Frost.class;
loot = new PotionOfFrost();
lootChance = 1/8f;
properties.add( Property.ICY );
harmfulBuffs.add( Burning.class );
}
@Override
protected void meleeProc( Char enemy, int damage ) {
if (Random.Int( 3 ) == 0 || Dungeon.level.water[enemy.pos]) {
Freezing.freeze( enemy.pos );
Splash.at( enemy.sprite.center(), sprite.blood(), 5);
}
}
@Override
protected void rangedProc( Char enemy ) {
Freezing.freeze( enemy.pos );
Splash.at( enemy.sprite.center(), sprite.blood(), 5);
}
}
public static class Shock extends Elemental {
{
spriteClass = ElementalSprite.Shock.class;
loot = new ScrollOfRecharging();
lootChance = 1/4f;
properties.add( Property.ELECTRIC );
}
@Override
protected void meleeProc( Char enemy, int damage ) {
ArrayList<Char> affected = new ArrayList<>();
ArrayList<Lightning.Arc> arcs = new ArrayList<>();
Shocking.arc( this, enemy, 2, affected, arcs );
if (!Dungeon.level.water[enemy.pos]) {
affected.remove( enemy );
}
for (Char ch : affected) {
ch.damage( Math.round( damage * 0.4f ), this );
}
sprite.parent.addToFront( new Lightning( arcs, null ) );
Sample.INSTANCE.play( Assets.SND_LIGHTNING );
}
@Override
protected void rangedProc( Char enemy ) {
Buff.affect( enemy, Blindness.class, 5f );
GameScene.flash( 0xFFFFFF );
}
}
public static class Chaos extends Elemental {
{
spriteClass = ElementalSprite.Chaos.class;
loot = new ScrollOfTransmutation();
lootChance = 1f;
}
@Override
protected void meleeProc( Char enemy, int damage ) {
CursedWand.cursedZap( null, this, new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT ), new Callback() {
@Override
public void call() {
next();
}
} );
}
@Override
protected void rangedProc( Char enemy ) {
CursedWand.cursedZap( null, this, new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT ), new Callback() {
@Override
public void call() {
next();
}
} );
}
}
public static Class<? extends Elemental> random(){
if (Random.Int( 50 ) == 0){
return Chaos.class;
}
float roll = Random.Float();
if (roll < 0.4f){
return Fire.class;
} else if (roll < 0.8f){
return Frost.class;
} else {
return Shock.class;
}
}
}

View File

@ -1,60 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2019 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Embers;
import com.shatteredpixel.shatteredpixeldungeon.sprites.NewbornElementalSprite;
public class NewbornElemental extends Elemental {
{
spriteClass = NewbornElementalSprite.class;
HT = 65;
HP = HT/2; //32
defenseSkill = 12;
EXP = 7;
properties.add(Property.MINIBOSS);
}
@Override
public void add(Buff buff) {
if (buff instanceof Frost || buff instanceof Chill) {
die(buff);
} else {
super.add(buff);
}
}
@Override
public void die(Object cause) {
super.die(cause);
Dungeon.level.drop( new Embers(), pos ).sprite.drop();
}
}

View File

@ -26,7 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.NewbornElemental;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
@ -97,7 +97,7 @@ public class CeremonialCandle extends Item {
heapBottom.pickUp();
heapLeft.pickUp();
NewbornElemental elemental = new NewbornElemental();
Elemental.NewbornFire elemental = new Elemental.NewbornFire();
Char ch = Actor.findChar( ritualPos );
if (ch != null) {
ArrayList<Integer> candidates = new ArrayList<>();

View File

@ -23,28 +23,50 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.RainbowParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SparkParticle;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.Callback;
public class ElementalSprite extends MobSprite {
public abstract class ElementalSprite extends MobSprite {
protected int boltType;
protected abstract int texOffset();
private Emitter particles;
protected abstract Emitter createEmitter();
public ElementalSprite() {
super();
int c = texOffset();
texture( Assets.ELEMENTAL );
TextureFilm frames = new TextureFilm( texture, 12, 14 );
idle = new Animation( 10, true );
idle.frames( frames, 0, 1, 2 );
idle.frames( frames, c+0, c+1, c+2 );
run = new Animation( 12, true );
run.frames( frames, 0, 1, 3 );
run.frames( frames, c+0, c+1, c+3 );
attack = new Animation( 15, false );
attack.frames( frames, 4, 5, 6 );
attack.frames( frames, c+4, c+5, c+6 );
zap = attack.clone();
die = new Animation( 15, false );
die.frames( frames, 7, 8, 9, 10, 11, 12, 13, 12 );
die.frames( frames, c+7, c+8, c+9, c+10, c+11, c+12, c+13, c+12 );
play( idle );
}
@ -52,17 +74,192 @@ public class ElementalSprite extends MobSprite {
@Override
public void link( Char ch ) {
super.link( ch );
add( State.BURNING );
if (particles == null) {
particles = createEmitter();
}
}
@Override
public void update() {
super.update();
if (particles != null){
particles.visible = visible;
}
}
@Override
public void die() {
super.die();
remove( State.BURNING );
if (particles != null){
particles.on = false;
}
}
@Override
public void kill() {
super.kill();
if (particles != null){
particles.killAndErase();
}
}
public void zap( int cell ) {
turnTo( ch.pos , cell );
play( zap );
MagicMissile.boltFromChar( parent,
boltType,
this,
cell,
new Callback() {
@Override
public void call() {
((Elemental)ch).onZapComplete();
}
} );
Sample.INSTANCE.play( Assets.SND_ZAP );
}
@Override
public void onComplete( Animation anim ) {
if (anim == zap) {
idle();
}
super.onComplete( anim );
}
public static class Fire extends ElementalSprite {
{
boltType = MagicMissile.FIRE;
}
@Override
protected int texOffset() {
return 0;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( FlameParticle.FACTORY, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFFFF7D13;
return 0xFFFFBB33;
}
}
public static class NewbornFire extends ElementalSprite {
{
boltType = MagicMissile.FIRE;
}
@Override
protected int texOffset() {
return 14;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( ElmoParticle.FACTORY, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFF85FFC8;
}
}
public static class Frost extends ElementalSprite {
{
boltType = MagicMissile.FROST;
}
@Override
protected int texOffset() {
return 28;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( MagicMissile.MagicParticle.FACTORY, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFF8EE3FF;
}
}
public static class Shock extends ElementalSprite {
//different bolt, so overrides zap
@Override
public void zap( int cell ) {
turnTo( ch.pos , cell );
play( zap );
((Elemental)ch).onZapComplete();
parent.add( new Beam.LightRay(center(), DungeonTilemap.raisedTileCenterToWorld(cell)));
}
@Override
protected int texOffset() {
return 42;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( SparkParticle.STATIC, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFFFFFF85;
}
}
public static class Chaos extends ElementalSprite {
//no bolt, overrides zap instead
@Override
public void zap( int cell ) {
turnTo( ch.pos , cell );
play( zap );
((Elemental)ch).onZapComplete();
Sample.INSTANCE.play( Assets.SND_ZAP );
}
@Override
protected int texOffset() {
return 56;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( RainbowParticle.BURST, 0.025f );
return emitter;
}
@Override
public int blood() {
return 0xFFE3E3E3;
}
}
}

View File

@ -476,8 +476,16 @@ actors.mobs.dm300.def_verb=blocked
actors.mobs.dm300.rankings_desc=Crushed by the DM-300
actors.mobs.dm300.desc=This machine was created by the Dwarves several centuries ago. Later, Dwarves started to replace machines with golems, elementals and even demons. Eventually it led their civilization to the decline. The DM-300 and similar machines were typically used for construction and mining, and in some cases, for city defense.
actors.mobs.elemental.name=fire elemental
actors.mobs.elemental.desc=Wandering fire elementals are a byproduct of summoning greater entities. They are too chaotic in their nature to be controlled by even the most powerful demonologist.
actors.mobs.elemental$fire.name=fire elemental
actors.mobs.elemental$fire.desc=Elementals are chaotic creatures that are often created when powerful occult magic isn't properly controlled. Elementals have minimal intelligence, and are usually associated with a particular type of magic.\n\nFire elementals are a common type of elemental which deals damage with fiery magic. They will set their target ablaze with melee attacks, and can occasionally shoot bolts of fire as well.
actors.mobs.elemental$newbornfire.name=newborn fire elemental
actors.mobs.elemental$newbornfire.desc=Elementals are chaotic creatures that are often created when powerful occult magic isn't properly controlled. Elementals have minimal intelligence, and are usually associated with a particular type of magic.\n\nFire elementals are a common type of elemental which deals damage with fiery magic. They will set their target ablaze with melee attacks, and can occasionally shoot bolts of fire as well.\n\nThis fire elemental is freshy summoned, and is weakened as a result. In this state it is especially vulnerable to the cold. Its offensive capabilities are still great though, caution is advised.
actors.mobs.elemental$frost.name=frost elemental
actors.mobs.elemental$frost.desc=Elementals are chaotic creatures that are often created when powerful occult magic isn't properly controlled. Elementals have minimal intelligence, and are usually associated with a particular type of magic.\n\nFrost elementals are a common type of elemental which weakens enemies with chilling magic. They will chill their target with melee and occasional ranged attacks. Their magic is much more effective in water.
actors.mobs.elemental$shock.name=shock elemental
actors.mobs.elemental$shock.desc=Elementals are chaotic creatures that are often created when powerful occult magic isn't properly controlled. Elementals have minimal intelligence, and are usually associated with a particular type of magic.\n\nShock elementals are a less common type of elemental which disrupts its enemies with electricity and flashes of light. In melee they will arc electricity to nearby enemies, and deal bonus damage to their primary target if they are in water. They will also occasionally focus a ranged blast of light at their target, temporarily blinding them.
actors.mobs.elemental$chaos.name=chaos elemental
actors.mobs.elemental$chaos.desc=Elementals are chaotic creatures that are often created when powerful occult magic isn't properly controlled. Elementals have minimal intelligence, and are usually associated with a particular type of magic.\n\nChaos elementals are rare and dangerous elementals which haven't stabilized to a particular element. They will unleash wild unpredictable magic when they attack.
actors.mobs.eye.name=evil eye
actors.mobs.eye.deathgaze_kill=The deathgaze killed you...
@ -547,9 +555,6 @@ actors.mobs.monk.disarm=The monk knocks the %s from your hands!
actors.mobs.monk.def_verb=blocked
actors.mobs.monk.desc=These monks are fanatics, who devoted themselves to protecting their city's secrets from all aliens. They don't use any armor or weapons, relying solely on the art of hand-to-hand combat.
actors.mobs.newbornelemental.name=newborn fire elemental
actors.mobs.newbornelemental.desc=Fire elementals are a byproduct of summoning greater entities. They are too chaotic in their nature to be controlled by even the most powerful demonologist.\n\nThis fire elemental is freshy summoned, and is weakened as a result. In this state it is especially vulnerable to the cold. Its offensive capabilities are still great though, caution is advised.
actors.mobs.piranha.name=giant piranha
actors.mobs.piranha.desc=These carnivorous fish are not natural inhabitants of underground pools. They were bred specifically to protect flooded treasure vaults.