v0.6.5: overhauled glyphs and some armor interaction

- defenceproc how happens before DR reduction
- antimagic now only works on magical effects specifically
- entanglement roots are now delayed
- potential no longer does self damage, charging adjusted
- stone reworked, now exchanged evasion for defence
- viscocity is now consistent
- stone is now uncommon, viscocity is now common
This commit is contained in:
Evan Debenham 2018-04-21 19:47:27 -04:00 committed by Evan Debenham
parent 55bb6e3121
commit af7bf1e000
12 changed files with 173 additions and 82 deletions
core/src/main
java/com/shatteredpixel/shatteredpixeldungeon
resources/com/shatteredpixel/shatteredpixeldungeon/messages/items

View File

@ -45,12 +45,12 @@ public abstract class Actor implements Bundlable {
//default priority values for general actor categories
//note that some specific actors pick more specific values
//e.g. a buff acting after all normal buffs might have priority BUFF_PRIO + 1
protected final int VFX_PRIO = 100; //visual effects take priority
protected final int HERO_PRIO = 0; //positive priority is before hero, negative after
protected final int BLOB_PRIO = -10; //blobs act after hero, before mobs
protected final int MOB_PRIO = -20; //mobs act between buffs and blobd
protected final int BUFF_PRIO = -30; //buffs act last in a turn
private final int DEFAULT = -100; //if no priority is given, act after all else
protected static final int VFX_PRIO = 100; //visual effects take priority
protected static final int HERO_PRIO = 0; //positive is before hero, negative after
protected static final int BLOB_PRIO = -10; //blobs act after hero, before mobs
protected static final int MOB_PRIO = -20; //mobs act between buffs and blobd
protected static final int BUFF_PRIO = -30; //buffs act last in a turn
private static final int DEFAULT = -100; //if no priority is given, act after all else
//used to determine what order actors act in if their time is equal. Higher values act earlier.
protected int actPriority = DEFAULT;

View File

@ -180,11 +180,11 @@ public abstract class Char extends Actor {
} else {
dmg = damageRoll();
}
int effectiveDamage = Math.max( dmg - dr, 0 );
int effectiveDamage = enemy.defenseProc( this, dmg );
effectiveDamage = Math.max( effectiveDamage - dr, 0 );
effectiveDamage = attackProc( enemy, effectiveDamage );
effectiveDamage = enemy.defenseProc( this, effectiveDamage );
if (visibleFight) {
Sample.INSTANCE.play( Assets.SND_HIT, 1, 1, Random.Float( 0.8f, 1.25f ) );
}

View File

@ -234,10 +234,10 @@ public class Combo extends Buff implements ActionIndicator.Action {
dmg = Math.round(dmg*0.6f);
break;
}
dmg = enemy.defenseProc(target, dmg);
dmg -= enemy.drRoll();
dmg = target.attackProc(enemy, dmg);
dmg = enemy.defenseProc(target, dmg);
enemy.damage( dmg, this );
//special effects

View File

@ -240,6 +240,7 @@ public class Belongings implements Iterable<Item> {
for (Wand.Charger charger : owner.buffs(Wand.Charger.class)){
charger.gainCharge(charge);
count++;
}
return count;

View File

@ -61,7 +61,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap.Type;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.AntiMagic;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Stone;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CapeOfThorns;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
@ -77,7 +76,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfMight;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEvasion;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfForce;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfFuror;
@ -927,15 +925,15 @@ public class Hero extends Char {
@Override
public int defenseProc( Char enemy, int damage ) {
if (belongings.armor != null) {
damage = belongings.armor.proc( enemy, this, damage );
}
Earthroot.Armor armor = buff( Earthroot.Armor.class );
if (armor != null) {
damage = armor.absorb( damage );
}
if (belongings.armor != null) {
damage = belongings.armor.proc( enemy, this, damage );
}
return damage;
}
@ -963,7 +961,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)
&& RingOfElements.RESISTS.contains(src.getClass())){
&& AntiMagic.RESISTS.contains(src.getClass())){
dmg -= Random.NormalIntRange(belongings.armor.DRMin(), belongings.armor.DRMax())/3;
}
@ -1090,19 +1088,13 @@ public class Hero extends Char {
}
if (step != -1) {
int moveTime = 1;
if (belongings.armor != null && belongings.armor.hasGlyph(Stone.class) &&
(Dungeon.level.map[pos] == Terrain.DOOR
|| Dungeon.level.map[pos] == Terrain.OPEN_DOOR
|| Dungeon.level.map[step] == Terrain.DOOR
|| Dungeon.level.map[step] == Terrain.OPEN_DOOR )){
moveTime *= 2;
}
float speed = speed();
sprite.move(pos, step);
move(step);
spend( moveTime / speed() );
spend( 1 / speed );
search(false);

View File

@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Momentum;
@ -269,6 +270,10 @@ public class Armor extends EquipableItem {
public float evasionFactor( Char owner, float evasion ){
if (hasGlyph(Stone.class) && !((Stone)glyph).testingEvasion()){
return 0;
}
if (owner instanceof Hero){
int aEnc = STRReq() - ((Hero) owner).STR();
if (aEnc > 0) evasion /= Math.pow(1.5, aEnc);
@ -279,10 +284,6 @@ public class Armor extends EquipableItem {
}
}
if (hasGlyph(Swiftness.class)) {
evasion += 5 + level()*1.5f;
}
return evasion + augment.evasionFactor(level());
}
@ -294,9 +295,16 @@ public class Armor extends EquipableItem {
}
if (hasGlyph(Swiftness.class)) {
speed *= (1.1f + 0.01f * level());
boolean enemyNear = false;
for (Char ch : Actor.chars()){
if (Dungeon.level.adjacent(ch.pos, owner.pos) && owner.alignment != ch.alignment){
enemyNear = true;
break;
}
}
if (!enemyNear) speed *= (1.2f + 0.04f * level());
} else if (hasGlyph(Flow.class) && Dungeon.level.water[owner.pos]){
speed *= (1.5f + 0.05f * level());
speed *= (1.5f + 0.1f * level());
}
return speed;
@ -506,8 +514,8 @@ public class Armor extends EquipableItem {
public static abstract class Glyph implements Bundlable {
private static final Class<?>[] glyphs = new Class<?>[]{
Obfuscation.class, Swiftness.class, Stone.class, Potential.class,
Brimstone.class, Viscosity.class, Entanglement.class, Repulsion.class, Camouflage.class, Flow.class,
Obfuscation.class, Swiftness.class, Viscosity.class, Potential.class,
Brimstone.class, Stone.class, Entanglement.class, Repulsion.class, Camouflage.class, Flow.class,
Affection.class, AntiMagic.class, Thorns.class };
private static final float[] chances= new float[]{
10, 10, 10, 10,

View File

@ -22,13 +22,37 @@
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shaman;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Warlock;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import java.util.HashSet;
public class AntiMagic extends Armor.Glyph {
private static ItemSprite.Glowing TEAL = new ItemSprite.Glowing( 0x88EEFF );
public static final HashSet<Class> RESISTS = new HashSet<>();
static {
RESISTS.add( Charm.class );
RESISTS.add( Weakness.class );
RESISTS.add( DisintegrationTrap.class );
RESISTS.add( GrimTrap.class );
RESISTS.add( Shaman.class );
RESISTS.add( Warlock.class );
RESISTS.add( Eye.class );
RESISTS.add( Yog.BurningFist.class );
}
@Override
public int proc(Armor armor, Char attacker, Char defender, int damage) {
//no proc effect, see Hero.damage

View File

@ -21,6 +21,7 @@
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
@ -32,6 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.plants.Earthroot;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.noosa.Camera;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Entanglement extends Glyph {
@ -39,16 +41,39 @@ public class Entanglement extends Glyph {
private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing( 0x663300 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage ) {
public int proc(Armor armor, Char attacker, final Char defender, final int damage ) {
int level = Math.max( 0, armor.level() );
final int level = Math.max( 0, armor.level() );
final int pos = defender.pos;
if (Random.Int( 4 ) == 0) {
Buff.prolong( defender, Roots.class, 3 - level/5 );
Buff.affect( defender, Earthroot.Armor.class ).level( 4 + 4*level );
CellEmitter.bottom( defender.pos ).start( EarthParticle.FACTORY, 0.05f, 8 );
Camera.main.shake( 1, 0.4f );
Actor delay = new Actor() {
{
actPriority = HERO_PRIO+1;
}
@Override
protected boolean act() {
Buff.affect( defender, Earthroot.Armor.class ).level( 4 * (level + 1) );
CellEmitter.bottom( defender.pos ).start( EarthParticle.FACTORY, 0.05f, 8 );
Camera.main.shake( 1, 0.4f );
if (defender.buff(Roots.class) != null){
Buff.prolong(defender, Roots.class, 5);
} else {
DelayedRoot root = Buff.append(defender, DelayedRoot.class);
root.setup(pos);
}
Actor.remove(this);
return true;
}
};
Actor.addDelayed(delay, defender.cooldown());
}
@ -59,5 +84,42 @@ public class Entanglement extends Glyph {
public Glowing glowing() {
return BROWN;
}
public static class DelayedRoot extends Buff{
{
actPriority = HERO_PRIO-1;
}
private int pos;
@Override
public boolean act() {
if (target.pos == pos){
Buff.prolong( target, Roots.class, 5 );
}
detach();
return true;
}
private void setup( int pos ){
this.pos = pos;
}
private static final String POS = "pos";
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
pos = bundle.getInt(POS);
}
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(POS, pos);
}
}
}

View File

@ -21,15 +21,13 @@
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.EnergyParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.noosa.Camera;
import com.watabou.utils.Random;
public class Potential extends Glyph {
@ -39,21 +37,12 @@ public class Potential extends Glyph {
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level() );
if (Random.Int( level + 20 ) >= 18) {
int shockDmg = Random.NormalIntRange( 2, 6 );
defender.damage( shockDmg, this );
checkOwner( defender );
if (defender == Dungeon.hero) {
Dungeon.hero.belongings.charge(1f + level/10f);
Camera.main.shake( 2, 0.3f );
if (defender instanceof Hero) {
int wands = ((Hero) defender).belongings.charge(0.1f + level*0.05f);
if (wands > 0) {
defender.sprite.centerEmitter().burst(EnergyParticle.FACTORY, wands * (level + 2));
}
attacker.sprite.parent.add( new Lightning( attacker.pos, defender.pos, null ) );
}
return damage;

View File

@ -32,8 +32,30 @@ public class Stone extends Armor.Glyph {
@Override
public int proc(Armor armor, Char attacker, Char defender, int damage) {
//no proc effect, see armor.DrMin and the end of hero.getCloser
testing = true;
float evasion = defender.defenseSkill(attacker);
float accuracy = attacker.attackSkill(defender);
testing = false;
float hitChance;
if (evasion >= accuracy){
hitChance = 1f - (1f - (accuracy/evasion))/2f;
} else {
hitChance = 1f - (evasion/accuracy)/2f;
}
//FIXME this is probably very OP, needs balancing
damage = (int)Math.ceil(damage * hitChance);
return damage;
}
private boolean testing = false;
public boolean testingEvasion(){
return testing;
}
@Override
public ItemSprite.Glowing glowing() {

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 {
@ -49,22 +48,16 @@ public class Viscosity extends Glyph {
int level = Math.max( 0, armor.level() );
if (Random.Int( level + 6 ) >= 5) {
DeferedDamage debuff = defender.buff( DeferedDamage.class );
if (debuff == null) {
debuff = new DeferedDamage();
debuff.attachTo( defender );
}
debuff.prolong( damage );
defender.sprite.showStatus( CharSprite.WARNING, Messages.get(this, "deferred", damage) );
return 0;
} else {
return damage;
}
float percent = (level+1)/(float)(level+6);
int amount = (int)Math.ceil(damage * percent);
DeferedDamage deferred = Buff.affect( defender, DeferedDamage.class );
deferred.prolong( amount );
defender.sprite.showStatus( CharSprite.WARNING, Messages.get(this, "deferred", amount) );
return damage - amount;
}
@Override

View File

@ -32,7 +32,7 @@ items.armor.glyphs.camouflage.name=%s of camouflage
items.armor.glyphs.camouflage.desc=This glyph allows the wearer to blend into tall grass, granting them temporary invisibility.
items.armor.glyphs.entanglement.name=%s of entanglement
items.armor.glyphs.entanglement.desc=This glyph grows earthroot around the wearer to absorb damage, yet roots them in the process.
items.armor.glyphs.entanglement.desc=This glyph grows earthroot around the wearer to absorb damage, but roots them if allowed to take hold.
items.armor.glyphs.flow.name=%s of flow
items.armor.glyphs.flow.desc=This glyph manipulates the flow of water around the wearer, making them much faster when moving through it.
@ -42,16 +42,16 @@ items.armor.glyphs.obfuscation.desc=This glyph obscures the wearer, making them
items.armor.glyphs.potential.name=%s of potential
items.armor.glyphs.potential.rankings_desc=Killed by: glyph of potential
items.armor.glyphs.potential.desc=This glyph releases energy when struck. This is harmful to the wearer, but recharges wands.
items.armor.glyphs.potential.desc=This glyph builds energy when struck, giving a small amount of charge to the wearer's wands.
items.armor.glyphs.repulsion.name=%s of repulsion
items.armor.glyphs.repulsion.desc=This glyph rebounds force against attackers, sending them flying back.
items.armor.glyphs.stone.name=%s of stone
items.armor.glyphs.stone.desc=This glyph surrounds the armor with weightless magical stone that improves defense, but makes it difficult to fit through doorways.
items.armor.glyphs.stone.desc=This glyph surrounds the armor with heavy magical stone that makes dodging impossible, but blocks damage in proportion with evasion.
items.armor.glyphs.swiftness.name=%s of swiftness
items.armor.glyphs.swiftness.desc=This glyph alters the nature of armor, reducing weight and increasing evasion and speed, at the cost of defense.
items.armor.glyphs.swiftness.desc=This glyph enhances the speed of the wearer whenever they aren't next to an enemy.
items.armor.glyphs.thorns.name=%s of thorns
items.armor.glyphs.thorns.desc=This powerful glyph harms attackers, causing them to slowly bleed based on the damage they deal.