v0.8.0: finished up mimic implementation, reduced their accuracy a bit
This commit is contained in:
parent
faaa8530a3
commit
4e7aca628e
|
@ -24,22 +24,37 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Haste;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Honeypot;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CrystalMimic extends Mimic {
|
||||
|
||||
{
|
||||
spriteClass = MimicSprite.Crystal.class;
|
||||
|
||||
FLEEING = new Fleeing();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,7 +69,6 @@ public class CrystalMimic extends Mimic {
|
|||
@Override
|
||||
public String description() {
|
||||
if (alignment == Alignment.NEUTRAL){
|
||||
//TODO variable based on contents
|
||||
for (Item i : items){
|
||||
if (i instanceof Artifact){
|
||||
return Messages.get(Heap.class, "crystal_chest_desc", Messages.get(Heap.class, "artifact"));
|
||||
|
@ -70,8 +84,27 @@ public class CrystalMimic extends Mimic {
|
|||
}
|
||||
}
|
||||
|
||||
//does not deal bonus damage, steals instead. See attackProc
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
if (alignment == Alignment.NEUTRAL) {
|
||||
alignment = Alignment.ENEMY;
|
||||
int dmg = super.damageRoll();
|
||||
alignment = Alignment.NEUTRAL;
|
||||
return dmg;
|
||||
} else {
|
||||
return super.damageRoll();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopHiding(){
|
||||
state = HUNTING;
|
||||
state = FLEEING;
|
||||
//haste for 2 turns if attacking
|
||||
if (alignment == Alignment.NEUTRAL){
|
||||
Buff.affect(this, Haste.class, 2f);
|
||||
} else {
|
||||
Buff.affect(this, Haste.class, 1f);
|
||||
}
|
||||
if (Dungeon.level.heroFOV[pos] && Actor.chars().contains(this)) {
|
||||
enemy = Dungeon.hero;
|
||||
target = Dungeon.hero.pos;
|
||||
|
@ -82,6 +115,82 @@ public class CrystalMimic extends Mimic {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO different AI
|
||||
@Override
|
||||
public int attackProc(Char enemy, int damage) {
|
||||
if (alignment == Alignment.NEUTRAL && enemy == Dungeon.hero){
|
||||
steal( Dungeon.hero );
|
||||
|
||||
} else {
|
||||
ArrayList<Integer> candidates = new ArrayList<>();
|
||||
for (int i : PathFinder.NEIGHBOURS8){
|
||||
if (Dungeon.level.passable[pos+i] && Actor.findChar(pos+i) == null){
|
||||
candidates.add(pos + i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!candidates.isEmpty()){
|
||||
ScrollOfTeleportation.appear(enemy, Random.element(candidates));
|
||||
}
|
||||
|
||||
if (alignment == Alignment.ENEMY) state = FLEEING;
|
||||
}
|
||||
return super.attackProc(enemy, damage);
|
||||
}
|
||||
|
||||
protected void steal( Hero hero ) {
|
||||
|
||||
int tries = 10;
|
||||
Item item;
|
||||
do {
|
||||
item = hero.belongings.randomUnequipped();
|
||||
} while (tries-- > 0 && (item == null || item.unique || item.level() > 0));
|
||||
|
||||
if (item != null && !item.unique && item.level() < 1 ) {
|
||||
|
||||
GLog.w( Messages.get(this, "ate", item.name()) );
|
||||
if (!item.stackable) {
|
||||
Dungeon.quickslot.convertToPlaceholder(item);
|
||||
}
|
||||
item.updateQuickslot();
|
||||
|
||||
if (item instanceof Honeypot){
|
||||
items.add(((Honeypot)item).shatter(this, this.pos));
|
||||
item.detach( hero.belongings.backpack );
|
||||
} else {
|
||||
items.add(item.detach( hero.belongings.backpack ));
|
||||
if ( item instanceof Honeypot.ShatteredPot)
|
||||
((Honeypot.ShatteredPot)item).pickupPot(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generatePrize() {
|
||||
//Crystal mimic already contains a prize item. Just guarantee it isn't cursed.
|
||||
for (Item i : items){
|
||||
i.cursed = false;
|
||||
i.cursedKnown = true;
|
||||
}
|
||||
}
|
||||
|
||||
private class Fleeing extends Mob.Fleeing{
|
||||
@Override
|
||||
protected void nowhereToRun() {
|
||||
if (buff( Terror.class ) == null && buff( Corruption.class ) == null) {
|
||||
if (enemySeen) {
|
||||
sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Mob.class, "rage"));
|
||||
state = HUNTING;
|
||||
} else {
|
||||
GLog.n( Messages.get(CrystalMimic.class, "escaped"));
|
||||
if (Dungeon.level.heroFOV[pos]) CellEmitter.get(pos).burst(Speck.factory(Speck.WOOL), 6);
|
||||
destroy();
|
||||
sprite.killAndErase();
|
||||
}
|
||||
} else {
|
||||
super.nowhereToRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,13 +26,17 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
|
||||
//TODO should enhance the reward from these a bit, as they are much harder
|
||||
public class GoldenMimic extends Mimic {
|
||||
|
||||
{
|
||||
|
@ -71,6 +75,24 @@ public class GoldenMimic extends Mimic {
|
|||
|
||||
@Override
|
||||
public void adjustStats(int level) {
|
||||
super.adjustStats((int)Math.ceil(level*1.5f));
|
||||
super.adjustStats(Math.round(level*1.33f));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generatePrize() {
|
||||
super.generatePrize();
|
||||
//all existing prize items are guaranteed uncursed
|
||||
for (Item i : items){
|
||||
if (i instanceof EquipableItem || i instanceof Wand){
|
||||
i.cursed = false;
|
||||
i.cursedKnown = true;
|
||||
if (i instanceof Weapon && ((Weapon) i).hasCurseEnchant()){
|
||||
((Weapon) i).enchant(null);
|
||||
}
|
||||
if (i instanceof Armor && ((Armor) i).hasCurseGlyph()){
|
||||
((Armor) i).inscribe(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ public class Mimic extends Mob {
|
|||
@Override
|
||||
public int damageRoll() {
|
||||
if (alignment == Alignment.NEUTRAL){
|
||||
return Random.NormalIntRange( 2*level, 2 + 3*level);
|
||||
return Random.NormalIntRange( 2 + 2*level, 3 + 3*level);
|
||||
} else {
|
||||
return Random.NormalIntRange( 1 + level, 2 + 2*level);
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ public class Mimic extends Mob {
|
|||
if (target != null && alignment == Alignment.NEUTRAL){
|
||||
return INFINITE_ACCURACY;
|
||||
} else {
|
||||
return 9 + level;
|
||||
return 6 + level;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,6 +246,12 @@ public class Mimic extends Mob {
|
|||
m.pos = pos;
|
||||
|
||||
//generate an extra reward for killing the mimic
|
||||
m.generatePrize();
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
protected void generatePrize(){
|
||||
Item reward = null;
|
||||
do {
|
||||
switch (Random.Int(5)) {
|
||||
|
@ -266,9 +272,7 @@ public class Mimic extends Mob {
|
|||
break;
|
||||
}
|
||||
} while (reward == null || Challenges.isItemBlocked(reward));
|
||||
m.items.add(reward);
|
||||
|
||||
return m;
|
||||
items.add(reward);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -300,7 +300,7 @@ public abstract class RegularLevel extends Level {
|
|||
case 4:
|
||||
type = Heap.Type.CHEST;
|
||||
break;
|
||||
case 5:
|
||||
case 5: default:
|
||||
if (Dungeon.depth > 1 && findMob(cell) == null){
|
||||
mobs.add(Mimic.spawnAt(cell, toDrop));
|
||||
continue;
|
||||
|
@ -312,7 +312,7 @@ public abstract class RegularLevel extends Level {
|
|||
if ((toDrop instanceof Artifact && Random.Int(2) == 0) ||
|
||||
(toDrop.isUpgradable() && Random.Int(4 - toDrop.level()) == 0)){
|
||||
|
||||
if (Random.Int(5) == 0 && findMob(cell) == null){
|
||||
if (Dungeon.depth > 1 && Random.Int(10) == 0 && findMob(cell) == null){
|
||||
mobs.add(Mimic.spawnAt(cell, toDrop, GoldenMimic.class));
|
||||
} else {
|
||||
Heap dropped = drop(toDrop, cell);
|
||||
|
|
|
@ -41,6 +41,11 @@ import java.util.Arrays;
|
|||
|
||||
public class VaultRoom extends SpecialRoom {
|
||||
|
||||
//size is reduced slightly to remove rare AI issues with crystal mimics
|
||||
@Override
|
||||
public int maxHeight() { return 8; }
|
||||
public int maxWidth() { return 8; }
|
||||
|
||||
public void paint( Level level ) {
|
||||
|
||||
Painter.fill( level, this, Terrain.WALL );
|
||||
|
|
|
@ -43,7 +43,7 @@ public class MimicSprite extends MobSprite {
|
|||
TextureFilm frames = new TextureFilm( texture, 16, 16 );
|
||||
|
||||
hiding = new Animation( 1, true );
|
||||
hiding.frames( frames, 0+c, 0+c, 0+c, 0+c, 0+c, 0+c, 1+c);
|
||||
hiding.frames( frames, 0+c, 0+c, 0+c, 0+c, 0+c, 1+c);
|
||||
|
||||
idle = new Animation( 5, true );
|
||||
idle.frames( frames, 2+c, 2+c, 2+c, 3+c, 3+c );
|
||||
|
|
|
@ -473,6 +473,11 @@ actors.mobs.causticslime.desc=This slime seems to have been tainted by the dark
|
|||
actors.mobs.crab.name=sewer crab
|
||||
actors.mobs.crab.desc=These huge crabs are at the top of the food chain in the sewers. They are extremely fast and their thick carapace can withstand heavy blows.
|
||||
|
||||
actors.mobs.crystalmimic.name=crystal mimic
|
||||
actors.mobs.crystalmimic.ate=The mimic ate your %s!
|
||||
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.
|
||||
|
||||
|
@ -515,6 +520,9 @@ actors.mobs.gnoll.desc=Gnolls are hyena-like humanoids. They dwell in sewers and
|
|||
actors.mobs.gnolltrickster.name=gnoll trickster
|
||||
actors.mobs.gnolltrickster.desc=A strange looking creature, even by gnoll standards. It hunches forward with a wicked grin, almost cradling the satchel hanging over its shoulder. Its eyes are wide with a strange mix of fear and excitement.\n\nThere is a large collection of poorly made darts in its satchel, they all seem to be tipped with various harmful substances.
|
||||
|
||||
actors.mobs.goldenmimic.name=golden mimic
|
||||
actors.mobs.goldenmimic.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\nGolden mimics are tougher mimics which try to attract the strongest adventurers. They have the best loot, but are also much stronger than regular mimics.
|
||||
|
||||
actors.mobs.golem.name=golem
|
||||
actors.mobs.golem.def_verb=blocked
|
||||
actors.mobs.golem.desc=The Dwarves tried to combine their knowledge of mechanisms with their newfound power of elemental binding. They used spirits of earth as the "soul" for the mechanical bodies of golems, which were believed to be most controllable of all. Despite this, the tiniest mistake in the ritual could cause an outbreak.
|
||||
|
@ -554,7 +562,7 @@ actors.mobs.king$undead.desc=These undead dwarves, risen by the will of the King
|
|||
|
||||
actors.mobs.mimic.name=mimic
|
||||
actors.mobs.mimic.reveal=That chest is a mimic!
|
||||
actors.mobs.mimic.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. Mimics have a nasty bite, but often hold more treasure than a regular chest.
|
||||
actors.mobs.mimic.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\nMimics have a nasty bite, but often hold more treasure than a regular chest.
|
||||
|
||||
actors.mobs.necromancer.name=necromancer
|
||||
actors.mobs.necromancer.desc=These apprentice dark mages have flocked to the prison, as it is the perfect place to practise their evil craft.\n\nNecromancers will summon and empower skeletons to fight for them. Killing the necromancer will also kill the skeleton it summons.
|
||||
|
|
Loading…
Reference in New Issue
Block a user