v0.8.0: reworked monks and warlocks

This commit is contained in:
Evan Debenham 2019-11-23 22:51:14 -05:00
parent 9e65b4b634
commit 59824f1556
49 changed files with 352 additions and 159 deletions

View File

@ -0,0 +1,87 @@
/*
* 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.buffs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
public class Degrade extends FlavourBuff {
public static final float DURATION = 50f;
{
type = buffType.NEGATIVE;
announced = true;
}
@Override
public boolean attachTo(Char target) {
if (super.attachTo(target)){
Item.updateQuickslot();
return true;
}
return false;
}
@Override
public void detach() {
super.detach();
Item.updateQuickslot();
}
//called in Item.buffedLevel()
public static int reduceLevel( int level ){
if (level <= 0){
//zero or negative levels are unaffected
return level;
} else {
//Otherwise returns the rounded result of sqrt(2*(lvl-1)) + 1
// This means that levels 1/2/3/4/5/6/7/8/9/10/11/12/...
// Are now instead: 1/2/3/3/4/4/4/5/5/ 5/ 5/ 6/...
// Basically every level starting with 3 sticks around for 1 level longer than the last
return (int)Math.round(Math.sqrt(2*(level-1)) + 1);
}
}
@Override
public int icon() {
return BuffIndicator.DEGRADE;
}
@Override
public String toString() {
return Messages.get(this, "name");
}
@Override
public String heroMessage() {
return Messages.get(this, "heromsg");
}
@Override
public String desc() {
return Messages.get(this, "desc", dispTurns());
}
}

View File

@ -52,7 +52,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SnipersMark;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
@ -1038,7 +1037,7 @@ public class Hero extends Char {
//TODO improve this when I have proper damage source logic
if (belongings.armor != null && belongings.armor.hasGlyph(AntiMagic.class, this)
&& AntiMagic.RESISTS.contains(src.getClass())){
dmg -= AntiMagic.drRoll(belongings.armor.level());
dmg -= AntiMagic.drRoll(belongings.armor.buffedLvl());
}
super.damage( dmg, src );

View File

@ -21,19 +21,15 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gauntlet;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.MonkSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
@ -81,34 +77,50 @@ public class Monk extends Mob {
super.rollToDropLoot();
}
private int hitsToDisarm = 0;
protected float focusCooldown = 0;
@Override
public int attackProc( Char enemy, int damage ) {
damage = super.attackProc( enemy, damage );
if (enemy == Dungeon.hero) {
Hero hero = Dungeon.hero;
KindOfWeapon weapon = hero.belongings.weapon;
if (weapon != null
&& !(weapon instanceof Gloves)
&& !(weapon instanceof Gauntlet)
&& !weapon.cursed) {
if (hitsToDisarm == 0) hitsToDisarm = Random.NormalIntRange(4, 8);
if (--hitsToDisarm == 0) {
hero.belongings.weapon = null;
Dungeon.quickslot.convertToPlaceholder(weapon);
weapon.updateQuickslot();
Dungeon.level.drop(weapon, hero.pos).sprite.drop();
GLog.w(Messages.get(this, "disarm", weapon.name()));
}
}
protected boolean act() {
boolean result = super.act();
if (buff(Focus.class) == null && state == HUNTING && focusCooldown <= 0) {
Buff.affect( this, Focus.class );
}
return result;
}
return damage;
@Override
protected void spend( float time ) {
focusCooldown -= time;
super.spend( time );
}
@Override
public void move( int step ) {
// moving reduces cooldown by an additional 0.67, giving a total reduction of 1.67f.
// basically monks will become focused notably faster if you kite them.
focusCooldown -= 0.67f;
super.move( step );
}
@Override
public int defenseSkill( Char enemy ) {
if (buff(Focus.class) != null){
return 100_000_000;
}
return 0; //testing
}
@Override
public String defenseVerb() {
Focus f = buff(Focus.class);
if (f == null) {
return super.defenseVerb();
} else {
f.detach();
//TODO this might be a bit too fast
focusCooldown = Random.NormalFloat( 4, 6 );
return Messages.get(this, "parried");
}
}
{
@ -116,17 +128,40 @@ public class Monk extends Mob {
immunities.add( Terror.class );
}
private static String DISARMHITS = "hitsToDisarm";
private static String FOCUS_COOLDOWN = "focus_cooldown";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(DISARMHITS, hitsToDisarm);
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( FOCUS_COOLDOWN, focusCooldown );
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
hitsToDisarm = bundle.getInt(DISARMHITS);
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
focusCooldown = bundle.getInt( FOCUS_COOLDOWN );
}
public static class Focus extends Buff {
{
type = buffType.POSITIVE;
announced = true;
}
@Override
public int icon() {
return BuffIndicator.MIND_VISION;
}
@Override
public String toString() {
return Messages.get(this, "name");
}
@Override
public String desc() {
return Messages.get(this, "desc");
}
}
}

View File

@ -21,9 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SeniorSprite;
import com.watabou.utils.Random;
@ -31,20 +28,21 @@ public class Senior extends Monk {
{
spriteClass = SeniorSprite.class;
lootChance = 1f;
}
@Override
public void move( int step ) {
// on top of the existing move bonus, senior monks get a further 1.66 cooldown reduction
// for a total of 3.33, double the normal 1.67 for regular monks
focusCooldown -= 1.66f;
super.move( step );
}
@Override
public int damageRoll() {
return Random.NormalIntRange( 16, 24 );
}
@Override
public int attackProc( Char enemy, int damage ) {
damage = super.attackProc( enemy, damage );
if (Random.Int( 10 ) == 0) {
Buff.prolong( enemy, Paralysis.class, 1.1f );
}
return super.attackProc( enemy, damage );
return Random.NormalIntRange( 16, 25 );
}
}

View File

@ -21,10 +21,11 @@
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.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Degrade;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
@ -34,6 +35,7 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.WarlockSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
@ -58,7 +60,7 @@ public class Warlock extends Mob implements Callback {
@Override
public int damageRoll() {
return Random.NormalIntRange( 16, 22 );
return Random.NormalIntRange( 12, 18 );
}
@Override
@ -101,9 +103,12 @@ public class Warlock extends Mob implements Callback {
spend( TIME_TO_ZAP );
if (hit( this, enemy, true )) {
//TODO would be nice for this to work on ghost/statues too
if (enemy == Dungeon.hero && Random.Int( 2 ) == 0) {
//TODO new debuff
//Buff.prolong( enemy, Weakness.class, Weakness.DURATION );
if (enemy.buff( Degrade.class ) == null){
Sample.INSTANCE.play( Assets.SND_DEGRADE );
}
Buff.prolong( enemy, Degrade.class, Degrade.DURATION );
}
int dmg = Random.Int( 12, 18 );

View File

@ -190,7 +190,7 @@ public class PrismaticImage extends NPC {
//TODO improve this when I have proper damage source logic
if (hero.belongings.armor != null && hero.belongings.armor.hasGlyph(AntiMagic.class, this)
&& AntiMagic.RESISTS.contains(src.getClass())){
dmg -= AntiMagic.drRoll(hero.belongings.armor.level());
dmg -= AntiMagic.drRoll(hero.belongings.armor.buffedLvl());
}
super.damage(dmg, src);

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Degrade;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
@ -289,10 +290,21 @@ public class Item implements Bundlable {
protected void onDetach(){}
//returns the true level of the item, only affected by modifiers which are persistent (e.g. curse infusion)
public int level(){
return level;
}
//returns the level of the item, after it may have been modified by temporary boosts/reductions
//note that not all item properties should care about buffs/debuffs! (e.g. str requirement)
public int buffedLvl(){
if (Dungeon.hero.buff( Degrade.class ) != null) {
return Degrade.reduceLevel(level());
} else {
return level();
}
}
public void level( int value ){
level = value;
@ -335,6 +347,10 @@ public class Item implements Bundlable {
return levelKnown ? level() : 0;
}
public int buffedVisiblyUpgraded() {
return levelKnown ? buffedLvl() : 0;
}
public boolean visiblyCursed() {
return cursed && cursedKnown;
}

View File

@ -83,11 +83,11 @@ abstract public class KindOfWeapon extends EquipableItem {
}
public int min(){
return min(level());
return min(buffedLvl());
}
public int max(){
return max(level());
return max(buffedLvl());
}
abstract public int min(int lvl);

View File

@ -265,7 +265,7 @@ public class Armor extends EquipableItem {
}
public final int DRMax(){
return DRMax(level());
return DRMax(buffedLvl());
}
public int DRMax(int lvl){
@ -278,7 +278,7 @@ public class Armor extends EquipableItem {
}
public final int DRMin(){
return DRMin(level());
return DRMin(buffedLvl());
}
public int DRMin(int lvl){
@ -306,7 +306,7 @@ public class Armor extends EquipableItem {
}
}
return evasion + augment.evasionFactor(level());
return evasion + augment.evasionFactor(buffedLvl());
}
public float speedFactor( Char owner, float speed ){
@ -324,7 +324,7 @@ public class Armor extends EquipableItem {
break;
}
}
if (!enemyNear) speed *= (1.2f + 0.04f * level());
if (!enemyNear) speed *= (1.2f + 0.04f * buffedLvl());
} else if (hasGlyph(Flow.class, owner) && Dungeon.level.water[owner.pos]){
speed *= 2f;
}
@ -342,7 +342,7 @@ public class Armor extends EquipableItem {
public float stealthFactor( Char owner, float stealth ){
if (hasGlyph(Obfuscation.class, owner)){
stealth += 1 + level()/3f;
stealth += 1 + buffedLvl()/3f;
}
return stealth;
@ -353,6 +353,16 @@ public class Armor extends EquipableItem {
return super.level() + (curseInfusionBonus ? 1 : 0);
}
//other things can equip these, for now we assume only the hero can be affected by levelling debuffs
@Override
public int buffedLvl() {
if (isEquipped( Dungeon.hero ) || Dungeon.hero.belongings.contains( this )){
return super.buffedLvl();
} else {
return level();
}
}
@Override
public Item upgrade() {
return upgrade( false );

View File

@ -38,7 +38,7 @@ public class Affection extends Glyph {
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max(0, armor.level());
int level = Math.max(0, armor.buffedLvl());
// lvl 0 - 15%
// lvl 1 ~ 19%

View File

@ -40,7 +40,7 @@ public class Entanglement extends Glyph {
@Override
public int proc(Armor armor, Char attacker, final Char defender, final int damage ) {
final int level = Math.max( 0, armor.level() );
final int level = Math.max( 0, armor.buffedLvl() );
if (Random.Int( 4 ) == 0) {

View File

@ -37,7 +37,7 @@ public class Potential extends Glyph {
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level() );
int level = Math.max( 0, armor.buffedLvl() );
// lvl 0 - 16.7%
// lvl 1 - 28.6%

View File

@ -35,7 +35,7 @@ public class Repulsion extends Armor.Glyph {
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level() );
int level = Math.max( 0, armor.buffedLvl() );
if (Random.Int( level + 5 ) >= 4){
int oppositeHero = attacker.pos + (attacker.pos - defender.pos);

View File

@ -35,7 +35,7 @@ public class Thorns extends Armor.Glyph {
@Override
public int proc(Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max(0, armor.level());
int level = Math.max(0, armor.buffedLvl());
// lvl 0 - 16.7%
// lvl 1 - 28.6%

View File

@ -34,7 +34,6 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Viscosity extends Glyph {
@ -51,7 +50,7 @@ public class Viscosity extends Glyph {
return 0;
}
int level = Math.max( 0, armor.level() );
int level = Math.max( 0, armor.buffedLvl() );
float percent = (level+1)/(float)(level+6);
int amount = (int)Math.ceil(realDamage * percent);

View File

@ -117,6 +117,17 @@ public class Artifact extends KindofMisc {
return levelKnown ? Math.round((level()*10)/(float)levelCap): 0;
}
@Override
public int buffedVisiblyUpgraded() {
return visiblyUpgraded();
}
@Override
public int buffedLvl() {
//level isn't affected by buffs/debuffs
return level();
}
//transfers upgrades from another artifact, transfer level will equal the displayed level
public void transferUpgrade(int transferLvl) {
upgrade(Math.round((float)(transferLvl*levelCap)/10));

View File

@ -312,9 +312,9 @@ public class Ring extends KindofMisc {
public int soloBonus(){
if (cursed){
return Math.min( 0, Ring.this.level()-2 );
return Math.min( 0, Ring.this.buffedLvl()-2 );
} else {
return Ring.this.level()+1;
return Ring.this.buffedLvl()+1;
}
}

View File

@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Degrade;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
@ -48,6 +49,8 @@ public class ScrollOfUpgrade extends InventoryScroll {
upgrade( curUser );
Degrade.detach( curUser, Degrade.class );
//logic for telling the user when item properties change from upgrades
//...yes this is rather messy
if (item instanceof Weapon){

View File

@ -29,13 +29,13 @@ import com.watabou.utils.Random;
public abstract class DamageWand extends Wand{
public int min(){
return min(level());
return min(buffedLvl());
}
public abstract int min(int lvl);
public int max(){
return max(level());
return max(buffedLvl());
}
public abstract int max(int lvl);

View File

@ -161,7 +161,7 @@ public abstract class Wand extends Item {
}
protected void processSoulMark(Char target, int chargesUsed){
processSoulMark(target, level(), chargesUsed);
processSoulMark(target, buffedLvl(), chargesUsed);
}
protected static void processSoulMark(Char target, int wandLevel, int chargesUsed){

View File

@ -81,7 +81,7 @@ public class WandOfBlastWave extends DamageWand {
if (ch.isAlive()) {
Ballistica trajectory = new Ballistica(ch.pos, ch.pos + i, Ballistica.MAGIC_BOLT);
int strength = 1 + Math.round(level() / 2f);
int strength = 1 + Math.round(buffedLvl() / 2f);
throwChar(ch, trajectory, strength);
} else if (ch == Dungeon.hero){
Dungeon.fail( getClass() );
@ -98,7 +98,7 @@ public class WandOfBlastWave extends DamageWand {
if (ch.isAlive() && bolt.path.size() > bolt.dist+1) {
Ballistica trajectory = new Ballistica(ch.pos, bolt.path.get(bolt.dist + 1), Ballistica.MAGIC_BOLT);
int strength = level() + 3;
int strength = buffedLvl() + 3;
throwChar(ch, trajectory, strength);
}
}

View File

@ -52,9 +52,9 @@ public class WandOfCorrosion extends Wand {
@Override
protected void onZap(Ballistica bolt) {
CorrosiveGas gas = Blob.seed(bolt.collisionPos, 50 + 10 * level(), CorrosiveGas.class);
CorrosiveGas gas = Blob.seed(bolt.collisionPos, 50 + 10 * buffedLvl(), CorrosiveGas.class);
CellEmitter.center(bolt.collisionPos).burst( CorrosionParticle.SPLASH, 10 );
gas.setStrength(2 + level());
gas.setStrength(2 + buffedLvl());
GameScene.add(gas);
for (int i : PathFinder.NEIGHBOURS9) {
@ -85,7 +85,7 @@ public class WandOfCorrosion extends Wand {
// lvl 0 - 33%
// lvl 1 - 50%
// lvl 2 - 60%
if (Random.Int( level() + 3 ) >= 2) {
if (Random.Int( buffedLvl() + 3 ) >= 2) {
Buff.affect( defender, Ooze.class ).set( 20f );
CellEmitter.center(defender.pos).burst( CorrosionParticle.SPLASH, 5 );

View File

@ -130,7 +130,7 @@ public class WandOfCorruption extends Wand {
Mob enemy = (Mob) ch;
float corruptingPower = 3 + level()/2f;
float corruptingPower = 3 + buffedLvl()/2f;
//base enemy resistance is usually based on their exp, but in special cases it is based on other criteria
float enemyResist = 1 + enemy.EXP;
@ -202,7 +202,7 @@ public class WandOfCorruption extends Wand {
Class<?extends FlavourBuff> debuffCls = (Class<? extends FlavourBuff>) Random.chances(debuffs);
if (debuffCls != null){
Buff.append(enemy, debuffCls, 6 + level()*3);
Buff.append(enemy, debuffCls, 6 + buffedLvl()*3);
} else {
//if no debuff can be applied (all are present), then go up one tier
if (category == MINOR_DEBUFFS) debuffEnemy( enemy, MAJOR_DEBUFFS);
@ -252,8 +252,8 @@ public class WandOfCorruption extends Wand {
// lvl 0 - 25%
// lvl 1 - 40%
// lvl 2 - 50%
if (Random.Int( level() + 4 ) >= 3){
Buff.prolong( defender, Amok.class, 4+level()*2);
if (Random.Int( buffedLvl() + 4 ) >= 3){
Buff.prolong( defender, Amok.class, 4+ buffedLvl()*2);
}
}

View File

@ -59,7 +59,7 @@ public class WandOfDisintegration extends DamageWand {
boolean terrainAffected = false;
int level = level();
int level = buffedLvl();
int maxDistance = Math.min(distance(), beam.dist);

View File

@ -74,7 +74,7 @@ public class WandOfFrost extends DamageWand {
float chill = ch.buff(Chill.class).cooldown();
damage = (int)Math.round(damage * Math.pow(0.9f, chill));
} else {
ch.sprite.burst( 0xFF99CCFF, level() / 2 + 2 );
ch.sprite.burst( 0xFF99CCFF, buffedLvl() / 2 + 2 );
}
processSoulMark(ch, chargesPerCast());
@ -82,9 +82,9 @@ public class WandOfFrost extends DamageWand {
if (ch.isAlive()){
if (Dungeon.level.water[ch.pos])
Buff.prolong(ch, Chill.class, 4+level());
Buff.prolong(ch, Chill.class, 4+buffedLvl());
else
Buff.prolong(ch, Chill.class, 2+level());
Buff.prolong(ch, Chill.class, 2+buffedLvl());
}
} else {
Dungeon.level.pressCell(bolt.collisionPos);

View File

@ -85,14 +85,14 @@ public class WandOfLivingEarth extends DamageWand {
buff = Buff.affect(curUser, RockArmor.class);
}
if (buff != null) {
buff.addArmor(level(), armorToAdd);
buff.addArmor( buffedLvl(), armorToAdd);
}
}
//shooting at the guardian
if (guardian != null && guardian == ch){
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level() / 2);
guardian.setInfo(curUser, level(), armorToAdd);
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl() / 2);
guardian.setInfo(curUser, buffedLvl(), armorToAdd);
processSoulMark(guardian, chargesPerCast());
//shooting the guardian at a location
@ -100,13 +100,13 @@ public class WandOfLivingEarth extends DamageWand {
//create a new guardian
guardian = new EarthGuardian();
guardian.setInfo(curUser, level(), buff.armor);
guardian.setInfo(curUser, buffedLvl(), buff.armor);
//if the collision pos is occupied (likely will be), then spawn the guardian in the
//adjacent cell which is closes to the user of the wand.
if (ch != null){
ch.sprite.centerEmitter().burst(MagicMissile.EarthParticle.BURST, 5 + level()/2);
ch.sprite.centerEmitter().burst(MagicMissile.EarthParticle.BURST, 5 + buffedLvl()/2);
processSoulMark(ch, chargesPerCast());
ch.damage(damage, this);
@ -123,7 +123,7 @@ public class WandOfLivingEarth extends DamageWand {
}
if (closest == -1){
curUser.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level()/2);
curUser.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl()/2);
return; //do not spawn guardian or detach buff
} else {
guardian.pos = closest;
@ -141,7 +141,7 @@ public class WandOfLivingEarth extends DamageWand {
Dungeon.level.occupyCell(guardian);
}
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level()/2);
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl()/2);
buff.detach();
//shooting at a location/enemy with no guardian being shot
@ -149,16 +149,16 @@ public class WandOfLivingEarth extends DamageWand {
if (ch != null) {
ch.sprite.centerEmitter().burst(MagicMissile.EarthParticle.BURST, 5 + level() / 2);
ch.sprite.centerEmitter().burst(MagicMissile.EarthParticle.BURST, 5 + buffedLvl() / 2);
processSoulMark(ch, chargesPerCast());
ch.damage(damage, this);
if (guardian == null) {
curUser.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level() / 2);
curUser.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl() / 2);
} else {
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level() / 2);
guardian.setInfo(curUser, level(), armorToAdd);
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl() / 2);
guardian.setInfo(curUser, buffedLvl(), armorToAdd);
if (ch.alignment == Char.Alignment.ENEMY || ch.buff(Amok.class) != null) {
guardian.aggro(ch);
}
@ -194,11 +194,11 @@ public class WandOfLivingEarth extends DamageWand {
int armor = Math.round(damage*0.25f);
if (guardian != null){
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level() / 2);
guardian.setInfo(Dungeon.hero, level(), armor);
guardian.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl() / 2);
guardian.setInfo(Dungeon.hero, buffedLvl(), armor);
} else {
attacker.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + level() / 2);
Buff.affect(attacker, RockArmor.class).addArmor(level(), armor);
attacker.sprite.centerEmitter().burst(MagicMissile.EarthParticle.ATTRACT, 8 + buffedLvl() / 2);
Buff.affect(attacker, RockArmor.class).addArmor( buffedLvl(), armor);
}
}

View File

@ -54,7 +54,7 @@ public class WandOfMagicMissile extends DamageWand {
processSoulMark(ch, chargesPerCast());
ch.damage(damageRoll(), this);
ch.sprite.burst(0xFFFFFFFF, level() / 2 + 2);
ch.sprite.burst(0xFFFFFFFF, buffedLvl() / 2 + 2);
} else {
Dungeon.level.pressCell(bolt.collisionPos);
@ -63,7 +63,7 @@ public class WandOfMagicMissile extends DamageWand {
@Override
public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) {
Buff.prolong( attacker, Recharging.class, 1 + staff.level()/2f);
Buff.prolong( attacker, Recharging.class, 1 + staff.buffedLvl()/2f);
SpellSprite.show(attacker, SpellSprite.CHARGE);
}

View File

@ -70,9 +70,9 @@ public class WandOfPrismaticLight extends DamageWand {
if (Dungeon.level.viewDistance < 6 ){
if (Dungeon.isChallenged(Challenges.DARKNESS)){
Buff.prolong( curUser, Light.class, 2f + level());
Buff.prolong( curUser, Light.class, 2f + buffedLvl());
} else {
Buff.prolong( curUser, Light.class, 10f+level()*5);
Buff.prolong( curUser, Light.class, 10f+buffedLvl()*5);
}
}
@ -87,18 +87,18 @@ public class WandOfPrismaticLight extends DamageWand {
int dmg = damageRoll();
//three in (5+lvl) chance of failing
if (Random.Int(5+level()) >= 3) {
Buff.prolong(ch, Blindness.class, 2f + (level() * 0.333f));
if (Random.Int(5+buffedLvl()) >= 3) {
Buff.prolong(ch, Blindness.class, 2f + (buffedLvl() * 0.333f));
ch.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6 );
}
if (ch.properties().contains(Char.Property.DEMONIC) || ch.properties().contains(Char.Property.UNDEAD)){
ch.sprite.emitter().start( ShadowParticle.UP, 0.05f, 10+level() );
ch.sprite.emitter().start( ShadowParticle.UP, 0.05f, 10+buffedLvl() );
Sample.INSTANCE.play(Assets.SND_BURNING);
ch.damage(Math.round(dmg*1.333f), this);
} else {
ch.sprite.centerEmitter().burst( RainbowParticle.BURST, 10+level() );
ch.sprite.centerEmitter().burst( RainbowParticle.BURST, 10+buffedLvl() );
ch.damage(dmg, this);
}
@ -147,7 +147,7 @@ public class WandOfPrismaticLight extends DamageWand {
@Override
public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) {
//cripples enemy
Buff.prolong( defender, Cripple.class, 1f+staff.level());
Buff.prolong( defender, Cripple.class, 1f+staff.buffedLvl());
}
@Override

View File

@ -79,7 +79,7 @@ public class WandOfTransfusion extends Wand {
// 10% of max hp
int selfDmg = Math.round(curUser.HT*0.10f);
int healing = selfDmg + 3*level();
int healing = selfDmg + 3*buffedLvl();
int shielding = (ch.HP + healing) - ch.HT;
if (shielding > 0){
healing -= shielding;
@ -90,7 +90,7 @@ public class WandOfTransfusion extends Wand {
ch.HP += healing;
ch.sprite.emitter().burst(Speck.factory(Speck.HEALING), 2 + level() / 2);
ch.sprite.emitter().burst(Speck.factory(Speck.HEALING), 2 + buffedLvl() / 2);
ch.sprite.showStatus(CharSprite.POSITIVE, "+%dHP", healing + shielding);
if (!freeCharge) {
@ -105,17 +105,17 @@ public class WandOfTransfusion extends Wand {
//charms living enemies
if (!ch.properties().contains(Char.Property.UNDEAD)) {
Buff.affect(ch, Charm.class, 5).object = curUser.id();
ch.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 3 + level()/2 );
ch.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 3 + buffedLvl()/2 );
//harms the undead
} else {
ch.damage(Random.NormalIntRange(3 + level()/2, 6+level()), this);
ch.sprite.emitter().start(ShadowParticle.UP, 0.05f, 10 + level());
ch.damage(Random.NormalIntRange(3 + buffedLvl()/2, 6+buffedLvl()), this);
ch.sprite.emitter().start(ShadowParticle.UP, 0.05f, 10 + buffedLvl());
Sample.INSTANCE.play(Assets.SND_BURNING);
}
//and grants a self shield
Buff.affect(curUser, Barrier.class).setShield((5 + 2*level()));
Buff.affect(curUser, Barrier.class).setShield((5 + 2*buffedLvl()));
}
@ -144,7 +144,7 @@ public class WandOfTransfusion extends Wand {
// lvl 0 - 10%
// lvl 1 - 18%
// lvl 2 - 25%
if (Random.Int( level() + 10 ) >= 9){
if (Random.Int( buffedLvl() + 10 ) >= 9){
//grants a free use of the staff
freeCharge = true;
GLog.p( Messages.get(this, "charged") );
@ -173,7 +173,7 @@ public class WandOfTransfusion extends Wand {
public String statsDesc() {
int selfDMG = Math.round(Dungeon.hero.HT*0.10f);
if (levelKnown)
return Messages.get(this, "stats_desc", selfDMG, selfDMG + 3*level(), 5+2*level(), 3+level()/2, 6+level());
return Messages.get(this, "stats_desc", selfDMG, selfDMG + 3*buffedLvl(), 5+2*buffedLvl(), 3+buffedLvl()/2, 6+ buffedLvl());
else
return Messages.get(this, "stats_desc", selfDMG, selfDMG, 5, 3, 6);
}

View File

@ -84,9 +84,9 @@ public class WandOfWarding extends Wand {
} else if (ch != null){
if (ch instanceof Ward){
if (wardAvailable) {
((Ward) ch).upgrade(level());
((Ward) ch).upgrade( buffedLvl() );
} else {
((Ward) ch).wandHeal( level() );
((Ward) ch).wandHeal( buffedLvl() );
}
ch.sprite.emitter().burst(MagicMissile.WardParticle.UP, ((Ward) ch).tier);
} else {
@ -97,7 +97,7 @@ public class WandOfWarding extends Wand {
} else if (canPlaceWard(bolt.collisionPos)){
Ward ward = new Ward();
ward.pos = bolt.collisionPos;
ward.wandLevel = level();
ward.wandLevel = buffedLvl();
GameScene.add(ward, 1f);
Dungeon.level.occupyCell(ward);
ward.sprite.emitter().burst(MagicMissile.WardParticle.UP, ward.tier);
@ -125,7 +125,7 @@ public class WandOfWarding extends Wand {
@Override
public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) {
int level = Math.max( 0, staff.level() );
int level = Math.max( 0, staff.buffedLvl() );
// lvl 0 - 20%
// lvl 1 - 33%
@ -133,7 +133,7 @@ public class WandOfWarding extends Wand {
if (Random.Int( level + 5 ) >= 4) {
for (Char ch : Actor.chars()){
if (ch instanceof Ward){
((Ward) ch).wandHeal(staff.level());
((Ward) ch).wandHeal(staff.buffedLvl());
ch.sprite.emitter().burst(MagicMissile.WardParticle.UP, ((Ward) ch).tier);
}
}

View File

@ -198,6 +198,12 @@ public class SpiritBow extends Weapon {
+ (curseInfusionBonus ? 1 : 0);
}
@Override
public int buffedLvl() {
//level isn't affected by buffs/debuffs
return level();
}
//for fetching upgrades from a boomerang from pre-0.7.1
public int spentUpgrades() {
return super.level() - (curseInfusionBonus ? 1 : 0);

View File

@ -213,6 +213,16 @@ abstract public class Weapon extends KindOfWeapon {
return super.level() + (curseInfusionBonus ? 1 : 0);
}
//overrides as other things can equip these
@Override
public int buffedLvl() {
if (isEquipped( Dungeon.hero ) || Dungeon.hero.belongings.contains( this )){
return super.buffedLvl();
} else {
return level();
}
}
@Override
public Item upgrade() {
return upgrade(false);

View File

@ -40,7 +40,7 @@ public class Blazing extends Weapon.Enchantment {
// lvl 0 - 33%
// lvl 1 - 50%
// lvl 2 - 60%
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
if (Random.Int( level + 3 ) >= 2) {

View File

@ -39,7 +39,7 @@ public class Blocking extends Weapon.Enchantment {
@Override
public int proc(Weapon weapon, Char attacker, Char defender, int damage) {
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
Buff.prolong(attacker, BlockBuff.class, 2 + level/2).setBlocking(level + 1);

View File

@ -45,7 +45,7 @@ public class Blooming extends Weapon.Enchantment {
// lvl 0 - 33%
// lvl 1 - 50%
// lvl 2 - 60%
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
if (Random.Int( level + 3 ) >= 2) {

View File

@ -39,7 +39,7 @@ public class Chilling extends Weapon.Enchantment {
// lvl 0 - 33%
// lvl 1 - 50%
// lvl 2 - 60%
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
if (Random.Int( level + 3 ) >= 2) {

View File

@ -45,7 +45,7 @@ public class Corrupting extends Weapon.Enchantment {
public int proc(Weapon weapon, Char attacker, Char defender, int damage) {
if (defender.buff(Corruption.class) != null || !(defender instanceof Mob)) return damage;
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
// lvl 0 - 20%
// lvl 1 ~ 22.5%

View File

@ -37,7 +37,7 @@ public class Elastic extends Weapon.Enchantment {
// lvl 0 - 20%
// lvl 1 - 33%
// lvl 2 - 43%
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
if (Random.Int( level + 5 ) >= 4) {
//trace a ballistica to our target (which will also extend past them

View File

@ -37,7 +37,7 @@ public class Grim extends Weapon.Enchantment {
@Override
public int proc( Weapon weapon, Char attacker, Char defender, int damage ) {
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
int enemyHealth = defender.HP - damage;
if (enemyHealth <= 0) return damage; //no point in proccing if they're already dead.

View File

@ -37,7 +37,7 @@ public class Lucky extends Weapon.Enchantment {
@Override
public int proc( Weapon weapon, Char attacker, Char defender, int damage ) {
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
// lvl 0 - 10%
// lvl 1 ~ 12%

View File

@ -45,7 +45,7 @@ public class Shocking extends Weapon.Enchantment {
// lvl 0 - 33%
// lvl 1 - 50%
// lvl 2 - 60%
int level = Math.max( 0, weapon.level() );
int level = Math.max( 0, weapon.buffedLvl() );
if (Random.Int( level + 3 ) >= 2) {

View File

@ -41,12 +41,12 @@ public class Greatshield extends MeleeWeapon {
@Override
public int defenseFactor( Char owner ) {
return 10+3*level(); //10 extra defence, plus 3 per level;
return 10+3*buffedLvl(); //10 extra defence, plus 3 per level;
}
public String statsInfo(){
if (isIdentified()){
return Messages.get(this, "stats_desc", 10+3*level());
return Messages.get(this, "stats_desc", 10+3*buffedLvl());
} else {
return Messages.get(this, "typical_stats_desc", 10);
}

View File

@ -41,12 +41,12 @@ public class RoundShield extends MeleeWeapon {
@Override
public int defenseFactor( Char owner ) {
return 5+2*level(); //5 extra defence, plus 2 per level;
return 5+2*buffedLvl(); //5 extra defence, plus 2 per level;
}
public String statsInfo(){
if (isIdentified()){
return Messages.get(this, "stats_desc", 5+2*level());
return Messages.get(this, "stats_desc", 5+2*buffedLvl());
} else {
return Messages.get(this, "typical_stats_desc", 5);
}

View File

@ -69,7 +69,7 @@ abstract public class MissileWeapon extends Weapon {
@Override
public int min() {
return Math.max(0, min( level() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
return Math.max(0, min( buffedLvl() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
}
@Override
@ -80,7 +80,7 @@ abstract public class MissileWeapon extends Weapon {
@Override
public int max() {
return Math.max(0, max( level() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
return Math.max(0, max( buffedLvl() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
}
@Override

View File

@ -69,8 +69,8 @@ public class Dart extends MissileWeapon {
@Override
public int min(int lvl) {
if (bow != null){
return 4 + //4 base
bow.level() + lvl; //+1 per level or bow level
return 4 + //4 base
bow.buffedLvl() + lvl; //+1 per level or bow level
} else {
return 1 + //1 base, down from 2
lvl; //scaling unchanged
@ -80,8 +80,8 @@ public class Dart extends MissileWeapon {
@Override
public int max(int lvl) {
if (bow != null){
return 12 + //12 base
3*bow.level() + 2*lvl; //+3 per bow level, +2 per level (default scaling +2)
return 12 + //12 base
3*bow.buffedLvl() + 2*lvl; //+3 per bow level, +2 per level (default scaling +2)
} else {
return 2 + //2 base, down from 5
2*lvl; //scaling unchanged

View File

@ -99,7 +99,7 @@ public class HighGrass {
//Camouflage
//FIXME doesn't work with sad ghost
if (hero.belongings.armor != null && hero.belongings.armor.hasGlyph(Camouflage.class, hero)) {
Buff.affect(hero, Camouflage.Camo.class).set(3 + hero.belongings.armor.level());
Buff.affect(hero, Camouflage.Camo.class).set(3 + hero.belongings.armor.buffedLvl());
}
}

View File

@ -93,6 +93,7 @@ public class BuffIndicator extends Component {
public static final int WEAPON = 45;
public static final int VULNERABLE = 46;
public static final int HEX = 47;
public static final int DEGRADE = 48;
public static final int SIZE = 7;

View File

@ -47,6 +47,7 @@ public class ItemSlot extends Button {
public static final int UPGRADED = 0x44FF44;
public static final int FADED = 0x999999;
public static final int WARNING = 0xFF8800;
public static final int ENHANCED = 0x3399FF;
private static final float ENABLED = 1.0f;
private static final float DISABLED = 0.3f;
@ -233,11 +234,16 @@ public class ItemSlot extends Button {
}
int level = item.visiblyUpgraded();
int buffedLvl = item.buffedVisiblyUpgraded();
if (level != 0) {
bottomRight.text( item.levelKnown ? Messages.format( TXT_LEVEL, level ) : TXT_CURSED );
if (buffedLvl != 0) {
bottomRight.text( Messages.format( TXT_LEVEL, buffedLvl ) );
bottomRight.measure();
bottomRight.hardlight( level > 0 ? UPGRADED : DEGRADED );
if (level == buffedLvl || buffedLvl <= 0) {
bottomRight.hardlight(buffedLvl > 0 ? UPGRADED : DEGRADED);
} else {
bottomRight.hardlight(buffedLvl > level ? ENHANCED : WARNING);
}
} else if (item instanceof Scroll || item instanceof Potion) {
bottomRight.text( null );

View File

@ -126,6 +126,10 @@ actors.buffs.cripple.name=Crippled
actors.buffs.cripple.heromsg=You are crippled!
actors.buffs.cripple.desc=You're pretty sure legs aren't meant to bend that way.\n\nCrippled halves movement speed, making moving a tile usually take two turns instead of one.\n\nTurns of cripple remaining: %s.
actors.buffs.degrade.name=Degraded
actors.buffs.degrade.heromsg=Your equipment feels weaker!
actors.buffs.degrade.desc=Powerful dark magic is sapping the strength that scrolls of upgrade have applied to your equipment!\n\nWhile degraded, upgraded gear will be treated as if it is a lower level than it actually is. _Every upgrade after +3 become exponentially weaker than the last one._ The descriptions of your items will change to reflect their reduced power level.\n\nDegradation does not affect strength requirements, wand charges, durability of thrown weapons, or artifacts.\n\nTurns of degradation remaining: %s. Using a scroll of upgrade will end degradation immediately.
actors.buffs.doom.name=Doomed
actors.buffs.doom.desc=It's hard to keep going when it seems like the universe wants you dead.\n\nDoomed characters will receive double damage from all sources.\n\nDoom is permanent, its effects only end in death.
@ -495,7 +499,7 @@ 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.ghoul.name=dwarven ghoul
actors.mobs.ghoul.desc=TODO
actors.mobs.ghoul.desc=As dwarven society slowly began to collapse, and the current king of the dwarves siezed absolute power, those who were weak or who resisted him were not treated well. As the king grew more adept at weilding dark magic, he bent these dwarves to his will, and now they make up the footsoldiers of his army.\n\nGhouls are not especially strong on their own, but always travel in groups, attempting to overwhelm their opponent with greater numbers.
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.
@ -554,9 +558,11 @@ actors.mobs.mob.exp=%+dEXP
actors.mobs.mob.rankings_desc=Slain by: %s
actors.mobs.monk.name=dwarf monk
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.monk.parried=parried
actors.mobs.monk.desc=These monks are fanatics, who have devoted themselves to protecting their king through physical might. So great is their devotion that they have totally surrendered their minds to their king, and now roam the dwarvern city like mindless zombies.\n\nMonks rely solely on the art of hand-to-hand combat, and are able to use their unarmed fists both for offense and defense. When they become focused, monks will parry the next physical attack used against them, even if it was otherwise garunteed to hit. Monk build focus more quickly while on the move, and more slowly when in direcy combat.
actors.mobs.monk$focus.name=Focused
actors.mobs.monk$focus.desc=This monk is perfectly honed in on their target, and seem to be anticipating their moves before they make them.\n\nWhile focused, the next physical attack made against their character is guaranteed to miss, no matter what circumstances there are. Parrying this attack will spend the monk's focus, and they will need to build it up again to parry another attack. Monks build focus more quickly while they are moving.
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.
@ -575,6 +581,7 @@ actors.mobs.scorpio.name=scorpio
actors.mobs.scorpio.desc=These huge arachnid-like demonic creatures avoid close combat by all means, firing crippling serrated spikes from long distances.
actors.mobs.senior.name=senior monk
actors.mobs.senior.desc=These monks are fanatics, who have devoted themselves to protecting their king through physical might. So great is their devotion that they have totally surrendered their minds to their king, and now roam the dwarvern city like mindless zombies.\n\nThis monk has mastered the art of hang-to-hand combat, and is able to gain focus while moving much more quickly than regular monks. When they become focused, monks will parry the next physical attack used against them, even if it was otherwise garunteed to hit. Monk build focus more quickly while on the move, and more slowly when in direcy combat.
actors.mobs.shaman.name=gnoll shaman
actors.mobs.shaman.zap_kill=The lightning bolt killed you...
@ -647,7 +654,7 @@ actors.mobs.thief.desc=Though these inmates roam free of their cells, this place
actors.mobs.warlock.name=dwarf warlock
actors.mobs.warlock.bolt_kill=The shadow bolt killed you...
actors.mobs.warlock.desc=When dwarves' interests have shifted from engineering to arcane arts, warlocks have come to power in the city. They started with elemental magic, but soon switched to demonology and necromancy.
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.
actors.mobs.wraith.name=wraith
actors.mobs.wraith.desc=A wraith is a vengeful spirit of a sinner, whose grave or tomb was disturbed. Being an ethereal entity, it is very hard to hit with a regular weapon.