diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index d2f1143e0..b9a6c8402 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -1594,6 +1594,11 @@ actors.mobs.ghoul.desc=As dwarven society slowly began to collapse, and the curr actors.mobs.gnoll.name=gnoll scout actors.mobs.gnoll.desc=Gnolls are hyena-like humanoids. They dwell in sewers and dungeons, venturing up to raid the surface from time to time. Gnoll scouts are regular members of their pack, they are not as strong as brutes and not as intelligent as shamans. +actors.mobs.gnollexile.name=gnoll exile +actors.mobs.gnollexile.desc=Gnolls are sometimes exiled from their society for a variety of reasons. The unusual grey fur on this gnoll indicates it was probably kicked out for just not fitting in. Exiles have to be strong and smart to survive, this one looks like it knows how to use the spear its holding. +actors.mobs.gnollexile.desc_passive=_The gnoll exile isn't moving to attack._ It doesn't seem as aggressive as the other gnolls here, it probably doesn't want a fight. You could just let it pass, although it has a backpack that might be full of useful items... +actors.mobs.gnollexile.desc_aggro=_The gnoll exile looks around angrily._ It seems something has made it decide to fight after all. Watch out for that spear! + actors.mobs.gnollgeomancer.name=gnoll geomancer actors.mobs.gnollgeomancer.warning=The geomancer begins to stir. Make sure you're ready before you continue! actors.mobs.gnollgeomancer.alert=The geomancer awakens! The entire cave seems to shift as it leaps away while laughing madly! diff --git a/core/src/main/assets/sprites/gnoll.png b/core/src/main/assets/sprites/gnoll.png index 23f1d18a4..7c74c6a3b 100644 Binary files a/core/src/main/assets/sprites/gnoll.png and b/core/src/main/assets/sprites/gnoll.png differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/ChampionEnemy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/ChampionEnemy.java index d13c6ec38..9f0d1acb8 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/ChampionEnemy.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/ChampionEnemy.java @@ -23,7 +23,6 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.buffs; import com.shatteredpixel.shatteredpixeldungeon.Challenges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; -import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire; @@ -31,8 +30,8 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; -import com.watabou.utils.BArray; import com.watabou.noosa.Image; +import com.watabou.utils.BArray; import com.watabou.utils.Bundle; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; @@ -162,10 +161,9 @@ public abstract class ChampionEnemy extends Buff { return false; } else { boolean[] passable = BArray.not(Dungeon.level.solid, null); - for (Char ch : Actor.chars()) { - //our own tile is always passable - passable[ch.pos] = ch == target; - } + + //our own tile is always passable + passable[target.pos] = true; PathFinder.buildDistanceMap(enemy.pos, passable, 4); @@ -209,10 +207,9 @@ public abstract class ChampionEnemy extends Buff { return false; } else { boolean[] passable = BArray.not(Dungeon.level.solid, null); - for (Char ch : Actor.chars()) { - //our own tile is always passable - passable[ch.pos] = ch == target; - } + + //our own tile is always passable + passable[target.pos] = true; PathFinder.buildDistanceMap(enemy.pos, passable, 2); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GnollExile.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GnollExile.java new file mode 100644 index 000000000..0daeb76fe --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GnollExile.java @@ -0,0 +1,103 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2025 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 + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; + + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.items.Gold; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.GnollExileSprite; +import com.watabou.utils.BArray; +import com.watabou.utils.PathFinder; + +public class GnollExile extends Gnoll { + + { + spriteClass = GnollExileSprite.class; + + PASSIVE = new Passive(); + state = PASSIVE; + + loot = Gold.class; + lootChance = 1f; + } + + //TODO higher stats, more detailed behaviour, better loot + + //"the spear-wielding gnoll pauses and eyes you suspiciously, but doesn't move to attack" + //"After a moment the gnoll nods its head toward you and begins to move on" + + // offer 1 ration to get all of its drops + + //has 1 extra reach from their spear + @Override + protected boolean canAttack( Char enemy ) { + if (Dungeon.level.adjacent( pos, enemy.pos )){ + return true; + } + + if (Dungeon.level.distance( pos, enemy.pos ) <= 2){ + boolean[] passable = BArray.not(Dungeon.level.solid, null); + + //our own tile is always passable + passable[pos] = true; + + PathFinder.buildDistanceMap(enemy.pos, passable, 2); + + if (PathFinder.distance[pos] <= 2){ + return true; + } + } + + return super.canAttack(enemy); + } + + @Override + public String description() { + String desc = super.description(); + if (state == PASSIVE){ + desc += "\n\n" + Messages.get(this, "desc_passive"); + } else { + desc += "\n\n" + Messages.get(this, "desc_aggro"); + } + return desc; + } + + //while passive gnoll exiles wander around + private class Passive extends Mob.Wandering { + @Override + public boolean act( boolean enemyInFOV, boolean justAlerted ) { + if (enemyInFOV && justAlerted) { + + //TODO pause if hero first enters fov? + + return noticeEnemy(); + + } else { + + return continueWandering(); + + } + } + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/MobSpawner.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/MobSpawner.java index 79dfa62ff..a9253a16b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/MobSpawner.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/MobSpawner.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.RatSkull; +import com.watabou.utils.DeviceCompat; import com.watabou.utils.Random; import java.util.ArrayList; @@ -247,6 +248,8 @@ public class MobSpawner extends Actor { Class cl = rotation.get(i); if (cl == Rat.class) { cl = Albino.class; + } else if (cl == Gnoll.class && DeviceCompat.isDebug()) { + cl = GnollExile.class; } else if (cl == Slime.class) { cl = CausticSlime.class; } else if (cl == Thief.class) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollExileSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollExileSprite.java new file mode 100644 index 000000000..c6550e13c --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollExileSprite.java @@ -0,0 +1,53 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2025 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 + */ + +package com.shatteredpixel.shatteredpixeldungeon.sprites; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.watabou.noosa.TextureFilm; + +public class GnollExileSprite extends MobSprite { + + public GnollExileSprite() { + super(); + + texture( Assets.Sprites.GNOLL ); + + TextureFilm frames = new TextureFilm( texture, 12, 15 ); + + int c = 21; + + idle = new Animation( 2, true ); + idle.frames( frames, 0+c, 0+c, 0+c, 1+c, 0+c, 0+c, 1+c, 1+c ); + + run = new Animation( 12, true ); + run.frames( frames, 4+c, 5+c, 6+c, 7+c ); + + attack = new Animation( 12, false ); + attack.frames( frames, 2+c, 3+c, 0+c ); + + die = new Animation( 12, false ); + die.frames( frames, 8+c, 9+c, 10+c ); + + play( idle ); + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollTricksterSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollTricksterSprite.java index 3bccacd1e..0775a66e8 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollTricksterSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/GnollTricksterSprite.java @@ -39,19 +39,21 @@ public class GnollTricksterSprite extends MobSprite { TextureFilm frames = new TextureFilm( texture, 12, 15 ); + int c = 42; + idle = new MovieClip.Animation( 2, true ); - idle.frames( frames, 21, 21, 21, 22, 21, 21, 22, 22 ); + idle.frames( frames, 0+c, 0+c, 0+c, 1+c, 0+c, 0+c, 1+c, 1+c ); run = new MovieClip.Animation( 12, true ); - run.frames( frames, 25, 26, 27, 28 ); + run.frames( frames, 4+c, 5+c, 6+c, 7+c ); attack = new MovieClip.Animation( 12, false ); - attack.frames( frames, 23, 24, 21 ); + attack.frames( frames, 2+c, 3+c, 0+c ); cast = attack.clone(); - die = new MovieClip.Animation( 12, false ); - die.frames( frames, 29, 30, 31 ); + die = new Animation( 12, false ); + die.frames( frames, 8+c, 9+c, 10+c ); play( idle ); }