v2.3.0: added fungal sentries, with WIP visuals and bare mechanics
This commit is contained in:
@@ -1202,6 +1202,9 @@ actors.mobs.eye.desc=Evil Eyes are floating balls of pent up demonic energy. Whi
|
||||
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. Its 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.
|
||||
|
||||
actors.mobs.fungalsentry.name=fungal sentry
|
||||
actors.mobs.fungalsentry.desc=This especially tall mushroom acts as a point of defense for the larger fungal network living in this cave.\n\nIt is immobile, but will shoot precise blasts of poison at anything that gets within its line of sight. While the impact of these blasts is fairly weak, _they can stack up deadly amounts of poison very quickly._ While it can be killed, it's probably best to avoid it.
|
||||
|
||||
actors.mobs.fungalspinner.name=fungal spinner
|
||||
actors.mobs.fungalspinner.desc=This cave spinner appears to be being controlled by a parasitic fungus. The fungus has also changed its abilities, replacing its web and venom sacks with fungal growth.\n\nThe fungal spinner will spit plant life at you instead of webs, spreading fungal vegetation and potentially rooting you. While it can't poison, the fungal spinner will gain substantial damage resistance if it is adjacent to any mushrooms.
|
||||
|
||||
|
||||
BIN
core/src/main/assets/sprites/fungal_sentry.png
Normal file
BIN
core/src/main/assets/sprites/fungal_sentry.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 199 B |
@@ -312,15 +312,16 @@ public class Assets {
|
||||
public static final String PYLON = "sprites/pylon.png";
|
||||
public static final String DM200 = "sprites/dm200.png";
|
||||
public static final String LOTUS = "sprites/lotus.png";
|
||||
public static final String NINJA_LOG= "sprites/ninja_log.png";
|
||||
public static final String SPIRIT_HAWK= "sprites/spirit_hawk.png";
|
||||
public static final String RED_SENTRY= "sprites/red_sentry.png";
|
||||
public static final String CRYSTAL_WISP= "sprites/crystal_wisp.png";
|
||||
public static final String CRYSTAL_GUARDIAN= "sprites/crystal_guardian.png";
|
||||
public static final String CRYSTAL_SPIRE= "sprites/crystal_spire.png";
|
||||
public static final String GNOLL_GUARD= "sprites/gnoll_guard.png";
|
||||
public static final String GNOLL_SAPPER= "sprites/gnoll_sapper.png";
|
||||
public static final String GNOLL_GEOMANCER = "sprites/gnoll_geomancer.png";
|
||||
public static final String FUNGAL_SPINNER = "sprites/fungal_spinner.png";
|
||||
public static final String NINJA_LOG = "sprites/ninja_log.png";
|
||||
public static final String SPIRIT_HAWK = "sprites/spirit_hawk.png";
|
||||
public static final String RED_SENTRY = "sprites/red_sentry.png";
|
||||
public static final String CRYSTAL_WISP = "sprites/crystal_wisp.png";
|
||||
public static final String CRYSTAL_GUARDIAN = "sprites/crystal_guardian.png";
|
||||
public static final String CRYSTAL_SPIRE = "sprites/crystal_spire.png";
|
||||
public static final String GNOLL_GUARD = "sprites/gnoll_guard.png";
|
||||
public static final String GNOLL_SAPPER = "sprites/gnoll_sapper.png";
|
||||
public static final String GNOLL_GEOMANCER = "sprites/gnoll_geomancer.png";
|
||||
public static final String FUNGAL_SPINNER = "sprites/fungal_spinner.png";
|
||||
public static final String FUNGAL_SENTRY = "sprites/fungal_sentry.png";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2023 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.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.FungalSentrySprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class FungalSentry extends Mob {
|
||||
|
||||
{
|
||||
spriteClass = FungalSentrySprite.class;
|
||||
|
||||
HP = HT = 200;
|
||||
defenseSkill = 12;
|
||||
|
||||
EXP = 10;
|
||||
maxLvl = -2;
|
||||
|
||||
state = WANDERING = new Waiting();
|
||||
|
||||
properties.add(Property.IMMOVABLE);
|
||||
properties.add(Property.MINIBOSS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser(int target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getFurther(int target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange(5, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
//TODO attack is a little permissive atm?
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return super.canAttack(enemy)
|
||||
|| new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos;
|
||||
}
|
||||
|
||||
//TODO if we want to allow them to be literally killed, probably should give them a heal if hero is out of FOV, or similar
|
||||
|
||||
@Override
|
||||
public int attackProc(Char enemy, int damage) {
|
||||
Buff.affect(enemy, Poison.class).extend(6);
|
||||
return super.attackProc(enemy, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
{
|
||||
immunities.add( ToxicGas.class );
|
||||
immunities.add( Poison.class );
|
||||
}
|
||||
|
||||
private class Waiting extends Mob.Wandering{
|
||||
|
||||
@Override
|
||||
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
|
||||
//always notices the hero
|
||||
if (enemyInFOV) {
|
||||
|
||||
return noticeEnemy();
|
||||
|
||||
} else {
|
||||
|
||||
return continueWandering();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean noticeEnemy() {
|
||||
spend(TICK);
|
||||
return super.noticeEnemy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.particles.CorrosionParti
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PoisonParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.RainbowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
|
||||
@@ -66,12 +67,12 @@ public class MagicMissile extends Emitter {
|
||||
public static final int RAINBOW = 8;
|
||||
public static final int EARTH = 9;
|
||||
public static final int WARD = 10;
|
||||
|
||||
public static final int SHAMAN_RED = 11;
|
||||
public static final int SHAMAN_BLUE = 12;
|
||||
public static final int SHAMAN_PURPLE = 13;
|
||||
public static final int TOXIC_VENT = 14;
|
||||
public static final int ELMO = 15;
|
||||
public static final int POISON = 16;
|
||||
|
||||
public static final int MAGIC_MISS_CONE = 100;
|
||||
public static final int FROST_CONE = 101;
|
||||
@@ -166,7 +167,6 @@ public class MagicMissile extends Emitter {
|
||||
size( 4 );
|
||||
pour( WardParticle.FACTORY, 0.01f );
|
||||
break;
|
||||
|
||||
case SHAMAN_RED:
|
||||
size( 2 );
|
||||
pour( ShamanParticle.RED, 0.01f );
|
||||
@@ -187,6 +187,10 @@ public class MagicMissile extends Emitter {
|
||||
size( 5 );
|
||||
pour( ElmoParticle.FACTORY, 0.01f );
|
||||
break;
|
||||
case POISON:
|
||||
size( 3 );
|
||||
pour( PoisonParticle.MISSILE, 0.01f );
|
||||
break;
|
||||
|
||||
case MAGIC_MISS_CONE:
|
||||
size( 10 );
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalGuardian;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.FungalSentry;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GnollGuard;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GnollSapper;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.RotLasher;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
@@ -199,11 +199,15 @@ public class MineLargeRoom extends CaveRoom {
|
||||
}
|
||||
|
||||
Point p = center();
|
||||
RotLasher m = new RotLasher(); //placeholder enemy
|
||||
FungalSentry m = new FungalSentry();
|
||||
m.pos = level.pointToCell(p);
|
||||
level.mobs.add(m);
|
||||
Painter.set(level, p, Terrain.GRASS);
|
||||
|
||||
//no high grass directly above the sentry
|
||||
p.y--;
|
||||
Painter.set(level, p, Terrain.GRASS);
|
||||
|
||||
} else {
|
||||
Painter.fillEllipse(level, this, 3, Terrain.EMPTY);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2023 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.sprites;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.watabou.noosa.TextureFilm;
|
||||
import com.watabou.utils.Callback;
|
||||
|
||||
public class FungalSentrySprite extends CharSprite {
|
||||
|
||||
private int cellToAttack;
|
||||
|
||||
public FungalSentrySprite(){
|
||||
super();
|
||||
|
||||
texture(Assets.Sprites.FUNGAL_SENTRY );
|
||||
|
||||
TextureFilm frames = new TextureFilm( texture, 18, 18 );
|
||||
|
||||
idle = new Animation( 0, true );
|
||||
idle.frames( frames, 0);
|
||||
|
||||
run = new Animation( 0, true );
|
||||
run.frames( frames, 0);
|
||||
|
||||
attack = new Animation( 24, false );
|
||||
attack.frames( frames, 0 );
|
||||
|
||||
zap = attack.clone();
|
||||
|
||||
die = new Animation( 12, false );
|
||||
die.frames( frames, 0 );
|
||||
|
||||
play( idle );
|
||||
|
||||
}
|
||||
|
||||
//TODO blood
|
||||
|
||||
@Override
|
||||
public void attack( int cell ) {
|
||||
if (!Dungeon.level.adjacent( cell, ch.pos )) {
|
||||
|
||||
cellToAttack = cell;
|
||||
zap(cell);
|
||||
|
||||
} else {
|
||||
|
||||
super.attack( cell );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete( Animation anim ) {
|
||||
if (anim == zap) {
|
||||
idle();
|
||||
|
||||
MagicMissile.boltFromChar(parent, MagicMissile.POISON, this, cellToAttack, new Callback() {
|
||||
@Override
|
||||
public void call() {
|
||||
ch.onAttackComplete();
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
super.onComplete( anim );
|
||||
}
|
||||
}
|
||||
|
||||
public class ScorpioShot extends Item {
|
||||
{
|
||||
image = ItemSpriteSheet.FISHING_SPEAR;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user