diff --git a/core/src/main/assets/buffs.png b/core/src/main/assets/buffs.png
index 6bf21aa6f..e984af86c 100644
Binary files a/core/src/main/assets/buffs.png and b/core/src/main/assets/buffs.png differ
diff --git a/core/src/main/assets/large_buffs.png b/core/src/main/assets/large_buffs.png
index d45054de5..58e082d6b 100644
Binary files a/core/src/main/assets/large_buffs.png and b/core/src/main/assets/large_buffs.png differ
diff --git a/core/src/main/assets/shaman.png b/core/src/main/assets/shaman.png
index 1714e82d8..318c19d9f 100644
Binary files a/core/src/main/assets/shaman.png and b/core/src/main/assets/shaman.png differ
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java
index ea8e4d200..1f79eec04 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java
@@ -43,6 +43,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FireImbue;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FrostImbue;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Haste;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSleep;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
@@ -53,8 +54,10 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ShieldBuff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Slow;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Speed;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Stamina;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vulnerable;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.items.BrokenSeal;
@@ -243,6 +246,11 @@ public abstract class Char extends Actor {
int effectiveDamage = enemy.defenseProc( this, dmg );
effectiveDamage = Math.max( effectiveDamage - dr, 0 );
+
+ if ( enemy.buff( Vulnerable.class ) != null){
+ effectiveDamage *= 1.33f;
+ }
+
effectiveDamage = attackProc( enemy, effectiveDamage );
if (visibleFight) {
@@ -308,9 +316,13 @@ public abstract class Char extends Actor {
public static boolean hit( Char attacker, Char defender, boolean magic ) {
float acuRoll = Random.Float( attacker.attackSkill( defender ) );
+ if (attacker.buff(Bless.class) != null) acuRoll *= 1.25f;
+ if (attacker.buff( Hex.class) != null) acuRoll *= 0.8f;
+
float defRoll = Random.Float( defender.defenseSkill( attacker ) );
- if (attacker.buff(Bless.class) != null) acuRoll *= 1.20f;
- if (defender.buff(Bless.class) != null) defRoll *= 1.20f;
+ if (defender.buff(Bless.class) != null) defRoll *= 1.25f;
+ if (defender.buff( Hex.class) != null) defRoll *= 0.8f;
+
return (magic ? acuRoll * 2 : acuRoll) >= defRoll;
}
@@ -334,7 +346,13 @@ public abstract class Char extends Actor {
return 1;
}
+ //TODO it would be nice to have a pre-armor and post-armor proc.
+ // atm attack is always post-armor and defence is already pre-armor
+
public int attackProc( Char enemy, int damage ) {
+ if ( buff(Weakness.class) != null ){
+ damage *= 0.67f;
+ }
return damage;
}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java
index 1cdd939cd..f1558d5e4 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java
@@ -235,6 +235,11 @@ public class Combo extends Buff implements ActionIndicator.Action {
dmg = enemy.defenseProc(target, dmg);
dmg -= enemy.drRoll();
+
+ if ( enemy.buff( Vulnerable.class ) != null){
+ dmg *= 1.33f;
+ }
+
dmg = target.attackProc(enemy, dmg);
enemy.damage( dmg, this );
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hex.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hex.java
new file mode 100644
index 000000000..4bba96015
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hex.java
@@ -0,0 +1,56 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
+
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
+
+public class Hex extends FlavourBuff {
+
+ public static final float DURATION = 30f;
+
+ {
+ type = buffType.NEGATIVE;
+ announced = true;
+ }
+
+ @Override
+ public int icon() {
+ return BuffIndicator.HEX;
+ }
+
+ @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());
+ }
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Vulnerable.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Vulnerable.java
new file mode 100644
index 000000000..7ff65eaba
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Vulnerable.java
@@ -0,0 +1,55 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
+
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
+
+public class Vulnerable extends FlavourBuff {
+
+ public static final float DURATION = 30f;
+
+ {
+ type = buffType.NEGATIVE;
+ announced = true;
+ }
+
+ @Override
+ public int icon() {
+ return BuffIndicator.VULNERABLE;
+ }
+
+ @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());
+ }
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Weakness.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Weakness.java
index 8cfc5855d..88a23eae8 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Weakness.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Weakness.java
@@ -24,9 +24,11 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
+//TODO need to re-evaluate various cases cases where this was used
+// now that warlocks give a different debuff and shamen have 3 different ones
public class Weakness extends FlavourBuff {
- public static final float DURATION = 40f;
+ public static final float DURATION = 30f;
{
type = buffType.NEGATIVE;
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
index 0a200f10b..73ea47bdc 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
@@ -222,7 +222,7 @@ public class Hero extends Char {
STR += buff.boost();
}
- return (buff(Weakness.class) != null) ? STR - 2 : STR;
+ return STR;
}
private static final String ATTACK = "attackSkill";
@@ -956,6 +956,8 @@ public class Hero extends Char {
@Override
public int attackProc( final Char enemy, int damage ) {
+ damage = super.attackProc( enemy, damage );
+
KindOfWeapon wep = belongings.weapon;
if (wep != null) damage = wep.proc( this, enemy, damage );
@@ -982,7 +984,6 @@ public class Hero extends Char {
break;
default:
}
-
return damage;
}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java
index ec85f8dde..468e12e4b 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java
@@ -109,14 +109,14 @@ public class Bestiary {
return new ArrayList<>(Arrays.asList(
Bat.class,
Brute.class, Brute.class, Brute.class,
- //DM100.class,
+ Shaman.random(),
Spinner.class));
case 14: case 15:
//1x bat, 3x brute, 1x shaman, 4x spinner
return new ArrayList<>(Arrays.asList(
Bat.class,
Brute.class, Brute.class, Brute.class,
- //DM100.class,
+ Shaman.random(),
Spinner.class, Spinner.class, Spinner.class, Spinner.class));
// City
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
index 010ea4d0c..e7ce48b57 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
@@ -480,15 +480,6 @@ public abstract class Mob extends Char {
super.onAttackComplete();
}
- @Override
- public int attackProc(Char enemy, int damage) {
- damage = super.attackProc(enemy, damage);
- if (buff(Weakness.class) != null){
- damage *= 0.67f;
- }
- return damage;
- }
-
@Override
public int defenseSkill( Char enemy ) {
boolean seen = (enemySeen && enemy.invisible == 0);
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shaman.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shaman.java
new file mode 100644
index 000000000..690aa61ee
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shaman.java
@@ -0,0 +1,171 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
+
+import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vulnerable;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
+import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
+import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.ShamanSprite;
+import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
+import com.watabou.utils.Random;
+
+//TODO decide on stats
+public abstract class Shaman extends Mob {
+
+ {
+ HP = HT = 18;
+ defenseSkill = 8;
+
+ EXP = 6;
+ maxLvl = 14;
+
+ loot = Generator.Category.SCROLL;
+ lootChance = 0.33f;
+ }
+
+ @Override
+ public int damageRoll() {
+ return Random.NormalIntRange( 2, 8 );
+ }
+
+ @Override
+ public int attackSkill( Char target ) {
+ return 11;
+ }
+
+ @Override
+ public int drRoll() {
+ return Random.NormalIntRange(0, 4);
+ }
+
+ @Override
+ protected boolean canAttack( Char enemy ) {
+ return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos;
+ }
+
+ protected boolean doAttack( Char enemy ) {
+
+ if (Dungeon.level.adjacent( pos, enemy.pos )) {
+
+ return super.doAttack( enemy );
+
+ } else {
+
+ if (sprite != null && sprite.visible) {
+ sprite.zap( enemy.pos );
+ return false;
+ } else {
+ zap();
+ return true;
+ }
+ }
+ }
+
+ //used so resistances can differentiate between melee and magical attacks
+ public static class EarthenBolt{}
+
+ private void zap() {
+ spend( 1f );
+
+ if (hit( this, enemy, true )) {
+
+ if (enemy == Dungeon.hero && Random.Int( 2 ) == 0) {
+ debuff( enemy );
+ }
+
+ int dmg = Random.Int( 0, 0 );
+ enemy.damage( dmg, new EarthenBolt() );
+
+ if (!enemy.isAlive() && enemy == Dungeon.hero) {
+ Dungeon.fail( getClass() );
+ GLog.n( Messages.get(this, "bolt_kill") );
+ }
+ } else {
+ enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
+ }
+ }
+
+ protected abstract void debuff( Char enemy );
+
+ public void onZapComplete() {
+ zap();
+ next();
+ }
+
+ @Override
+ public String description() {
+ return super.description() + "\n\n" + Messages.get(this, "spell_desc");
+ }
+
+ public static class RedShaman extends Shaman {
+ {
+ spriteClass = ShamanSprite.Red.class;
+ }
+
+ @Override
+ protected void debuff( Char enemy ) {
+ Buff.prolong( enemy, Weakness.class, Weakness.DURATION );
+ }
+ }
+
+ public static class BlueShaman extends Shaman {
+ {
+ spriteClass = ShamanSprite.Blue.class;
+ }
+
+ @Override
+ protected void debuff( Char enemy ) {
+ Buff.prolong( enemy, Vulnerable.class, Vulnerable.DURATION );
+ }
+ }
+
+ public static class PurpleShaman extends Shaman {
+ {
+ spriteClass = ShamanSprite.Purple.class;
+ }
+
+ @Override
+ protected void debuff( Char enemy ) {
+ Buff.prolong( enemy, Hex.class, Hex.DURATION );
+ }
+ }
+
+ //TODO a rare variant that helps brutes?
+
+ public static Class extends Shaman> random(){
+ float roll = Random.Float();
+ if (roll < 0.4f){
+ return RedShaman.class;
+ } else if (roll < 0.8f){
+ return BlueShaman.class;
+ } else {
+ return PurpleShaman.class;
+ }
+ }
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Warlock.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Warlock.java
index 1c3f08984..26ed674b5 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Warlock.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Warlock.java
@@ -102,7 +102,8 @@ public class Warlock extends Mob implements Callback {
if (hit( this, enemy, true )) {
if (enemy == Dungeon.hero && Random.Int( 2 ) == 0) {
- Buff.prolong( enemy, Weakness.class, Weakness.DURATION );
+ //TODO new debuff
+ //Buff.prolong( enemy, Weakness.class, Weakness.DURATION );
}
int dmg = Random.Int( 12, 18 );
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java
index 6b354db4d..9f55a65d2 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java
@@ -62,6 +62,10 @@ 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 FIRE_CONE = 100;
public static final int FOLIAGE_CONE = 101;
@@ -147,6 +151,19 @@ public class MagicMissile extends Emitter {
size( 4 );
pour( WardParticle.FACTORY, 0.01f );
break;
+
+ case SHAMAN_RED:
+ size( 2 );
+ pour( ShamanParticle.RED, 0.01f );
+ break;
+ case SHAMAN_BLUE:
+ size( 2 );
+ pour( ShamanParticle.BLUE, 0.01f );
+ break;
+ case SHAMAN_PURPLE:
+ size( 2 );
+ pour( ShamanParticle.PURPLE, 0.01f );
+ break;
case FIRE_CONE:
size( 10 );
@@ -300,7 +317,7 @@ public class MagicMissile extends Emitter {
size = 4;
if (Random.Int(10) == 0){
- color(ColorMath.random(0xFFF568, 0x80791A));
+ color(ColorMath.random(0xFFF266, 0x80771A));
} else {
color(ColorMath.random(0x805500, 0x332500));
}
@@ -326,6 +343,60 @@ public class MagicMissile extends Emitter {
}
}
+ public static class ShamanParticle extends EarthParticle{
+
+ public static final Emitter.Factory RED = new Factory() {
+ @Override
+ public void emit( Emitter emitter, int index, float x, float y ) {
+ ((ShamanParticle)emitter.recycle( ShamanParticle.class ))
+ .reset( x, y, ColorMath.random(0xFF4D4D, 0x801A1A) );
+ }
+ };
+
+ public static final Emitter.Factory BLUE = new Factory() {
+ @Override
+ public void emit( Emitter emitter, int index, float x, float y ) {
+ ((ShamanParticle)emitter.recycle( ShamanParticle.class ))
+ .reset( x, y, ColorMath.random(0x6699FF, 0x1A3C80) );
+ }
+ };
+
+ public static final Emitter.Factory PURPLE = new Factory() {
+ @Override
+ public void emit( Emitter emitter, int index, float x, float y ) {
+ ((ShamanParticle)emitter.recycle( ShamanParticle.class ))
+ .reset( x, y, ColorMath.random(0xBB33FF, 0x5E1A80) );
+ }
+ };
+
+ int startColor;
+ int endColor;
+
+ public ShamanParticle() {
+ super();
+
+ lifespan = 0.6f;
+ acc.set( 0, 0 );
+ }
+
+ public void reset( float x, float y, int endColor ){
+ super.reset( x, y );
+
+ size( 1 );
+
+ this.endColor = endColor;
+ startColor = ColorMath.random(0x805500, 0x332500);
+
+ speed.set( Random.Float( -10, +10 ), Random.Float( -10, +10 ) );
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ color( ColorMath.interpolate( endColor, startColor, (left / lifespan) ));
+ }
+ }
+
public static class WhiteParticle extends PixelParticle {
public static final Emitter.Factory FACTORY = new Factory() {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ShamanSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ShamanSprite.java
new file mode 100644
index 000000000..a48c089ab
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ShamanSprite.java
@@ -0,0 +1,113 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.sprites;
+
+import com.shatteredpixel.shatteredpixeldungeon.Assets;
+import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shaman;
+import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
+import com.watabou.noosa.TextureFilm;
+import com.watabou.noosa.audio.Sample;
+import com.watabou.utils.Callback;
+
+public abstract class ShamanSprite extends MobSprite {
+
+ protected int boltType;
+
+ protected abstract int texOffset();
+
+ public ShamanSprite() {
+ super();
+
+ int c = texOffset();
+
+ texture( Assets.SHAMAN );
+
+ TextureFilm frames = new TextureFilm( texture, 12, 15 );
+
+ idle = new Animation( 2, true );
+ idle.frames( frames, c+0, c+0, c+0, c+1, c+0, c+0, c+1, c+1 );
+
+ run = new Animation( 12, true );
+ run.frames( frames, c+4, c+5, c+6, c+7 );
+
+ attack = new Animation( 12, false );
+ attack.frames( frames, c+2, c+3, c+0 );
+
+ zap = attack.clone();
+
+ die = new Animation( 12, false );
+ die.frames( frames, c+8, c+9, c+10 );
+
+ play( idle );
+ }
+
+ public void zap( int cell ) {
+
+ turnTo( ch.pos , cell );
+ play( zap );
+
+ MagicMissile.boltFromChar( parent,
+ boltType,
+ this,
+ cell,
+ new Callback() {
+ @Override
+ public void call() {
+ ((Shaman)ch).onZapComplete();
+ }
+ } );
+ Sample.INSTANCE.play( Assets.SND_ZAP );
+ }
+
+ public static class Red extends ShamanSprite {
+ {
+ boltType = MagicMissile.SHAMAN_RED;
+ }
+
+ @Override
+ protected int texOffset() {
+ return 0;
+ }
+ }
+
+ public static class Blue extends ShamanSprite {
+ {
+ boltType = MagicMissile.SHAMAN_BLUE;
+ }
+
+ @Override
+ protected int texOffset() {
+ return 21;
+ }
+ }
+
+ public static class Purple extends ShamanSprite {
+ {
+ boltType = MagicMissile.SHAMAN_PURPLE;
+ }
+
+ @Override
+ protected int texOffset() {
+ return 42;
+ }
+ }
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java
index c55e2f599..47c1dc627 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java
@@ -91,6 +91,8 @@ public class BuffIndicator extends Component {
public static final int WELL_FED = 43;
public static final int HEALING = 44;
public static final int WEAPON = 45;
+ public static final int VULNERABLE = 46;
+ public static final int HEX = 47;
public static final int SIZE = 7;
diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties
index a91c2fa4e..76dcfb5fc 100644
--- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties
+++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties
@@ -83,7 +83,7 @@ actors.buffs.bleeding.rankings_desc=Bled to Death
actors.buffs.bleeding.desc=That wound is leaking a worrisome amount of blood.\n\nBleeding causes damage every turn. Each turn the damage decreases by a random amount, until the bleeding eventually stops.\n\nCurrent bleed damage: %d.
actors.buffs.bless.name=Blessed
-actors.buffs.bless.desc=A great burst of focus, some say it is inspired by the gods.\n\nBlessing significantly increases accuracy and evasion, making the blessed much more effective in combat.\n\nTurns of bless remaining: %s.
+actors.buffs.bless.desc=A great burst of focus, some say it is inspired by the gods.\n\nBlessing increases accuracy and evasion by 25%%, making the blessed much more effective in combat.\n\nTurns of bless remaining: %s.
actors.buffs.blindness.name=Blinded
actors.buffs.blindness.heromsg=You are blinded!
@@ -161,6 +161,10 @@ actors.buffs.haste.desc=Energy courses through your muscles, allowing you to run
actors.buffs.healing.name=Healing
actors.buffs.healing.desc=A magical remedy is causing wounds to close and flesh to knit.\n\nEvery turn health will steadily regenerate until the healing effect expires. The amount of healing may fade over time.\n\nNext heal: %d.\n\nHealing remaining: %d.
+actors.buffs.hex.name=Hexed
+actors.buffs.hex.heromsg=You have been hexed!
+actors.buffs.hex.desc=Dark magic which saps focus, making the target slightly disoriented.\n\nHexing reduces accuracy and evasion by 20%%, making the target less effective in combat.\n\nTurns of hex remaining: %s.
+
actors.buffs.hunger.hungry=Hungry
actors.buffs.hunger.starving=Starving
actors.buffs.hunger.onhungry=You are hungry.
@@ -257,6 +261,10 @@ actors.buffs.soulmark.desc=The warlock has tapped into the soul of this creature
actors.buffs.stamina.name=Stamina
actors.buffs.stamina.desc=You have unending stamina, allowing for faster movement!\n\nWhile under the effects of stamina you will run at +50%% speed, but will perform all other actions at normal speed.\n\nTurns of stamina remaining: %s.
+actors.buffs.vulnerable.name=Vulnerable
+actors.buffs.vulnerable.heromsg=You feel fragile!
+actors.buffs.vulnerable.desc=Vulnerability magic increases all physical damage that a character takes by 33%%, after that damage has been reduced by armor.\n\nTurns of vulnerable remaining: %s.
+
actors.buffs.terror.name=Terrified
actors.buffs.terror.desc=Terror is manipulative magic which forces its target into an uncontrollable panic.\n\nTerrified characters are forced to run away from their opponent, trying to put as many doors and walls between them as possible. The shock of pain will lessen the duration of terror, however.\n\nTurns of terror remaining: %s.
@@ -274,7 +282,7 @@ actors.buffs.vertigo.desc=Walking in a straight line can be difficult when the w
actors.buffs.weakness.name=Weakened
actors.buffs.weakness.heromsg=You feel weakened!
-actors.buffs.weakness.desc=Everything suddenly seems much heavier.\n\nWeakening magic reduces a character's physical strength. The hero will lose 2 points of effective strength, while enemies will deal reduced damage.\n\nTurns of weakness remaining: %s.
+actors.buffs.weakness.desc=Everything suddenly seems much heavier.\n\nWeakening magic reduces a character's physical strength, causing them to deal 33%% reduced damage.\n\nTurns of weakness remaining: %s.
actors.buffs.wellfed.name=Well Fed
actors.buffs.wellfed.desc=You feel quite satisfied and full.\n\nWhile well fed, your hunger will not increase, and you will heal an additional amount of health over time.\n\nTurns remaining: %d.
@@ -562,7 +570,10 @@ actors.mobs.senior.name=senior monk
actors.mobs.shaman.name=gnoll shaman
actors.mobs.shaman.zap_kill=The lightning bolt killed you...
-actors.mobs.shaman.desc=The most intelligent gnolls can master shamanistic magic. Gnoll shamans prefer battle spells to compensate for lack of might, not hesitating to use them on those who question their status in a tribe.
+actors.mobs.shaman.desc=Gnoll shamans are intelligent gnolls who use battle spells to compensate for their lack of might. They have a very respected position in gnoll society, despite their weaker strength.
+actors.mobs.shaman$redshaman.spell_desc=This shaman is wearing a red mask, and will use magic that temporarily _weakens your attacking power._
+actors.mobs.shaman$blueshaman.spell_desc=This shaman is wearing a blue mask, and will use magic that temporarily _increases the damage you take._
+actors.mobs.shaman$purpleshaman.spell_desc=This shaman is wearing a purple mask, and will use magic that temporarily _reduces your accuracy and evasion._
actors.mobs.armoredbrute.name=armored brute
actors.mobs.armoredbrute.desc=The most senior gnoll brutes often wear powerful armor to show their status. The armor makes these brutes much more resilient to physical damage, and their greater discipline means they can rage for much longer before succumbing to their wounds.