v2.1.0: added a new exotic enemy: tormented spirits
This commit is contained in:
@@ -1289,6 +1289,10 @@ actors.mobs.thief.carries=\n\nThe thief is carrying a _%s._ Stolen obviously.
|
||||
actors.mobs.thief.escapes=The thief gets away with your %s!
|
||||
actors.mobs.thief.desc=Though these inmates roam free of their cells, this place is still their prison. Over time, this place has taken their minds as well as their freedom. Long ago, these crazy thieves and bandits have forgotten who they are and why they steal.\n\nThese enemies are more likely to steal and run than they are to fight. Make sure to keep them in sight, or you might never see your stolen item again.
|
||||
|
||||
actors.mobs.tormentedspirit.name=tormented spirit
|
||||
actors.mobs.tormentedspirit.desc=Tormented spirits are otherwise good-natured spirits that has been afflicted by a curse. So long as they are cursed they will attack just like a wraith, and are more powerful as well!\n\nIt may be possible to cleanse the curse by using the right item while next to the spirit. If the curse is lifted the spirit will surely be grateful...
|
||||
actors.mobs.tormentedspirit.thank_you=Thank you...
|
||||
|
||||
actors.mobs.warlock.name=dwarf warlock
|
||||
actors.mobs.warlock.bolt_kill=The shadow bolt killed you...
|
||||
actors.mobs.warlock.desc=As the dwarves' interests shifted from engineering to arcane arts, warlocks came to power in the city. They started with elemental magic, but soon switched to demonology and necromancy. The strongest of these warlocks seized the throne of the dwarven city, and his cohorts were allowed to continue practising their dark magic, so long as they surrendered their free will to him.\n\nThese warlocks possess powerful disruptive magic, and are able to temporarily hinder the upgrade magic applied to your equipment. The more upgraded an item is, the more strongly it will be affected.
|
||||
|
||||
@@ -996,6 +996,7 @@ items.scrolls.scrollofremovecurse.name=scroll of remove curse
|
||||
items.scrolls.scrollofremovecurse.inv_title=Cleanse an item
|
||||
items.scrolls.scrollofremovecurse.cleansed=Your item glows with a cleansing light, and a malevolent energy disperses!
|
||||
items.scrolls.scrollofremovecurse.not_cleansed=Your item glows with a cleansing light, but nothing happens.
|
||||
items.scrolls.scrollofremovecurse.spirit=Your scroll frees the tormented spirit!
|
||||
items.scrolls.scrollofremovecurse.desc=The incantation on this scroll will instantly strip any curses from a single weapon, ring, wand, armor, or artifact.
|
||||
|
||||
items.scrolls.scrollofteleportation.name=scroll of teleportation
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 296 B After Width: | Height: | Size: 491 B |
@@ -811,7 +811,7 @@ public abstract class Mob extends Char {
|
||||
if (!(this instanceof Wraith)
|
||||
&& soulMarked
|
||||
&& Random.Float() < (0.4f*Dungeon.hero.pointsInTalent(Talent.NECROMANCERS_MINIONS)/3f)){
|
||||
Wraith w = Wraith.spawnAt(pos);
|
||||
Wraith w = Wraith.spawnAt(pos, false);
|
||||
if (w != null) {
|
||||
Buff.affect(w, Corruption.class);
|
||||
if (Dungeon.level.heroFOV[pos]) {
|
||||
|
||||
@@ -148,7 +148,7 @@ public class SpectralNecromancer extends Necromancer {
|
||||
|
||||
summoning = firstSummon = false;
|
||||
|
||||
Wraith wraith = Wraith.spawnAt(summoningPos);
|
||||
Wraith wraith = Wraith.spawnAt(summoningPos, false);
|
||||
wraith.adjustStats(0);
|
||||
Dungeon.level.occupyCell( wraith );
|
||||
((SpectralNecromancerSprite)sprite).finishSummoning();
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.TormentedSpiritSprite;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class TormentedSpirit extends Wraith {
|
||||
|
||||
{
|
||||
spriteClass = TormentedSpiritSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustStats(int level) {
|
||||
super.adjustStats(Math.round(level*1.5f));
|
||||
}
|
||||
|
||||
public void cleanse(){
|
||||
Sample.INSTANCE.play( Assets.Sounds.GHOST );
|
||||
yell(Messages.get(this, "thank_you"));
|
||||
|
||||
//50/50 between weapon or armor, always uncursed
|
||||
Item prize;
|
||||
if (Random.Int(2) == 0){
|
||||
prize = Generator.randomWeapon();
|
||||
if (((MeleeWeapon)prize).hasCurseEnchant()){
|
||||
((MeleeWeapon) prize).enchantment = null;
|
||||
}
|
||||
} else {
|
||||
prize = Generator.randomArmor();
|
||||
if (((Armor) prize).hasCurseGlyph()){
|
||||
((Armor) prize).glyph = null;
|
||||
}
|
||||
}
|
||||
prize.cursed = false;
|
||||
prize.cursedKnown = true;
|
||||
|
||||
Dungeon.level.drop(prize, pos).sprite.drop();
|
||||
|
||||
destroy();
|
||||
sprite.die();
|
||||
sprite.tint(1, 1, 1, 1);
|
||||
sprite.emitter().start( ShaftParticle.FACTORY, 0.3f, 4 );
|
||||
sprite.emitter().start( Speck.factory( Speck.LIGHT ), 0.2f, 3 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ChallengeParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.WraithSprite;
|
||||
@@ -93,16 +94,21 @@ public class Wraith extends Mob {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void spawnAround( int pos ) {
|
||||
public static void spawnAround( int pos, boolean allowExotic ) {
|
||||
for (int n : PathFinder.NEIGHBOURS4) {
|
||||
spawnAt( pos + n );
|
||||
spawnAt( pos + n, allowExotic );
|
||||
}
|
||||
}
|
||||
|
||||
public static Wraith spawnAt( int pos ) {
|
||||
public static Wraith spawnAt( int pos, boolean allowExotic ) {
|
||||
if ((!Dungeon.level.solid[pos] || Dungeon.level.passable[pos]) && Actor.findChar( pos ) == null) {
|
||||
|
||||
Wraith w = new Wraith();
|
||||
|
||||
Wraith w;
|
||||
if (allowExotic && Random.Int(1) == 0){
|
||||
w = new TormentedSpirit();
|
||||
} else {
|
||||
w = new Wraith();
|
||||
}
|
||||
w.adjustStats( Dungeon.scalingDepth() );
|
||||
w.pos = pos;
|
||||
w.state = w.HUNTING;
|
||||
@@ -111,8 +117,12 @@ public class Wraith extends Mob {
|
||||
|
||||
w.sprite.alpha( 0 );
|
||||
w.sprite.parent.add( new AlphaTweener( w.sprite, 1, 0.5f ) );
|
||||
|
||||
w.sprite.emitter().burst( ShadowParticle.CURSE, 5 );
|
||||
|
||||
if (w instanceof TormentedSpirit){
|
||||
w.sprite.emitter().burst(ChallengeParticle.FACTORY, 10);
|
||||
} else {
|
||||
w.sprite.emitter().burst(ShadowParticle.CURSE, 5);
|
||||
}
|
||||
|
||||
return w;
|
||||
} else {
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Heap implements Bundlable {
|
||||
public void open( Hero hero ) {
|
||||
switch (type) {
|
||||
case TOMB:
|
||||
Wraith.spawnAround( hero.pos );
|
||||
Wraith.spawnAround( hero.pos, true );
|
||||
break;
|
||||
case REMAINS:
|
||||
case SKELETON:
|
||||
@@ -93,7 +93,7 @@ public class Heap implements Bundlable {
|
||||
}
|
||||
|
||||
if (haunted){
|
||||
if (Wraith.spawnAt( pos ) == null) {
|
||||
if (Wraith.spawnAt( pos, true ) == null) {
|
||||
hero.sprite.emitter().burst( ShadowParticle.CURSE, 6 );
|
||||
hero.damage( hero.HP / 2, this );
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ public class DriedRose extends Artifact {
|
||||
}
|
||||
|
||||
if (spawnPoints.size() > 0) {
|
||||
Wraith.spawnAt(Random.element(spawnPoints));
|
||||
Wraith.spawnAt(Random.element(spawnPoints), false);
|
||||
Sample.INSTANCE.play(Assets.Sounds.CURSED);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public class CorpseDust extends Item {
|
||||
tries --;
|
||||
} while (tries > 0 && (!Dungeon.level.heroFOV[pos] || Dungeon.level.solid[pos] || Actor.findChar( pos ) != null));
|
||||
if (tries > 0) {
|
||||
Wraith.spawnAt(pos);
|
||||
Wraith.spawnAt(pos, false);
|
||||
Sample.INSTANCE.play(Assets.Sounds.CURSED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Degrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.TormentedSpirit;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
||||
@@ -35,6 +38,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.PathFinder;
|
||||
|
||||
public class ScrollOfRemoveCurse extends InventoryScroll {
|
||||
|
||||
@@ -43,6 +48,32 @@ public class ScrollOfRemoveCurse extends InventoryScroll {
|
||||
preferredBag = Belongings.Backpack.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRead() {
|
||||
TormentedSpirit spirit = null;
|
||||
for (int i : PathFinder.NEIGHBOURS8){
|
||||
if (Actor.findChar(curUser.pos+i) instanceof TormentedSpirit){
|
||||
spirit = (TormentedSpirit) Actor.findChar(curUser.pos+i);
|
||||
}
|
||||
}
|
||||
if (spirit != null){
|
||||
identify();
|
||||
Sample.INSTANCE.play( Assets.Sounds.READ );
|
||||
readAnimation();
|
||||
|
||||
new Flare( 6, 32 ).show( curUser.sprite, 2f );
|
||||
|
||||
if (curUser.buff(Degrade.class) != null) {
|
||||
Degrade.detach(curUser, Degrade.class);
|
||||
}
|
||||
|
||||
GLog.p(Messages.get(this, "spirit"));
|
||||
spirit.cleanse();
|
||||
} else {
|
||||
super.doRead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean usableOnItem(Item item) {
|
||||
return uncursable(item);
|
||||
|
||||
@@ -116,7 +116,7 @@ public class DistortionTrap extends Trap{
|
||||
case 2:
|
||||
switch (Random.Int(4)){
|
||||
case 0: default:
|
||||
Wraith.spawnAt(point);
|
||||
Wraith.spawnAt(point, true);
|
||||
continue; //wraiths spawn themselves, no need to do more
|
||||
case 1:
|
||||
//yes it's intended that these are likely to die right away
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.watabou.noosa.TextureFilm;
|
||||
|
||||
public class TormentedSpiritSprite extends MobSprite {
|
||||
|
||||
public TormentedSpiritSprite() {
|
||||
super();
|
||||
|
||||
texture( Assets.Sprites.WRAITH );
|
||||
|
||||
TextureFilm frames = new TextureFilm( texture, 14, 15 );
|
||||
|
||||
int c = 9;
|
||||
|
||||
idle = new Animation( 5, true );
|
||||
idle.frames( frames, c+0, c+1 );
|
||||
|
||||
run = new Animation( 10, true );
|
||||
run.frames( frames, c+0, c+1 );
|
||||
|
||||
attack = new Animation( 10, false );
|
||||
attack.frames( frames, c+0, c+2, c+3 );
|
||||
|
||||
die = new Animation( 8, false );
|
||||
die.frames( frames, c+0, c+4, c+5, c+6, c+7 );
|
||||
|
||||
play( idle );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int blood() {
|
||||
return 0x88BB0000;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user