v0.6.3: further overhauled the resistance system, and reworked ring of elements

This commit is contained in:
Evan Debenham 2018-01-28 16:37:30 -05:00 committed by Evan Debenham
parent 5529239973
commit b33824f0e9
32 changed files with 89 additions and 106 deletions

View File

@ -498,43 +498,38 @@ public abstract class Char extends Actor {
protected final HashSet<Class> resistances = new HashSet<>();
public HashSet<Class> resistances() {
HashSet<Class> result = new HashSet<>(resistances);
//returns percent effectiveness after resistances
//TODO currently resistances reduce effectiveness by a static 50%, and do not stack.
public float resist( Class effect ){
HashSet<Class> resists = new HashSet<>(resistances);
for (Property p : properties()){
result.addAll(p.resistances());
resists.addAll(p.resistances());
}
for (Buff b : buffs()){
result.addAll(b.resistances());
resists.addAll(b.resistances());
}
result.addAll(RingOfElements.resistances( this ));
return result;
}
public float resist( Class effect ){
float result = 1f;
for (Class c : resistances()){
for (Class c : resists){
if (c.isAssignableFrom(effect)){
result *= Random.Float();
result *= 0.5f;
}
}
return result;
return result * RingOfElements.resist(this, effect);
}
protected final HashSet<Class> immunities = new HashSet<>();
public HashSet<Class> immunities() {
HashSet<Class> result = new HashSet<>(immunities);
public boolean isImmune(Class effect ){
HashSet<Class> immunes = new HashSet<>(immunities);
for (Property p : properties()){
result.addAll(p.immunities());
immunes.addAll(p.immunities());
}
for (Buff b : buffs()){
result.addAll(b.immunities());
immunes.addAll(b.immunities());
}
return result;
}
public boolean isImmune(Class effect ){
for (Class c : immunities()){
for (Class c : immunes){
if (c.isAssignableFrom(effect)){
return true;
}

View File

@ -44,7 +44,7 @@ public class ParalyticGas extends Blob {
cell = i + j * Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar(cell)) != null) {
if (!ch.isImmune(this.getClass()))
Buff.prolong(ch, Paralysis.class, Paralysis.duration(ch));
Buff.prolong(ch, Paralysis.class, Paralysis.DURATION);
}
}
}

View File

@ -44,7 +44,7 @@ public class StenchGas extends Blob {
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
if (!ch.isImmune(this.getClass()))
Buff.prolong( ch, Paralysis.class, Paralysis.duration( ch )/5 );
Buff.prolong( ch, Paralysis.class, Paralysis.DURATION/5 );
}
}
}

View File

@ -121,7 +121,7 @@ public class Buff extends Actor {
public static<T extends FlavourBuff> T append( Char target, Class<T> buffClass, float duration ) {
T buff = append( target, buffClass );
buff.spend( duration );
buff.spend( duration * target.resist(buffClass) );
return buff;
}
@ -137,14 +137,14 @@ public class Buff extends Actor {
public static<T extends FlavourBuff> T affect( Char target, Class<T> buffClass, float duration ) {
T buff = affect( target, buffClass );
buff.spend( duration );
buff.spend( duration * target.resist(buffClass) );
return buff;
}
//postpones an already active buff, or creates & attaches a new buff and delays that.
public static<T extends FlavourBuff> T prolong( Char target, Class<T> buffClass, float duration ) {
T buff = affect( target, buffClass );
buff.postpone( duration );
buff.postpone( duration * target.resist(buffClass) );
return buff;
}

View File

@ -82,10 +82,8 @@ public class Burning extends Buff implements Hero.Doom {
public boolean act() {
if (target.isAlive()) {
//maximum damage scales from 6 to 2 depending on remaining hp.
int maxDmg = 3 + Math.round( 4 * target.HP / (float)target.HT );
int damage = Random.Int( 1, maxDmg );
int damage = Random.NormalIntRange( 1, 3 + target.HT/20 );
Buff.detach( target, Chill.class);
if (target instanceof Hero) {
@ -172,7 +170,7 @@ public class Burning extends Buff implements Hero.Doom {
}
public void reignite( Char ch ) {
left = duration( ch );
left = DURATION;
}
@Override
@ -196,10 +194,6 @@ public class Burning extends Buff implements Hero.Doom {
return Messages.get(this, "name");
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
}
@Override
public String desc() {
return Messages.get(this, "desc", dispTurns(left));

View File

@ -58,10 +58,6 @@ public class Charm extends FlavourBuff {
public String toString() {
return Messages.get(this, "name");
}
public static float durationFactor( Char ch ) {
return RingOfElements.durationFactor( ch );
}
@Override
public String heroMessage() {

View File

@ -131,6 +131,6 @@ public class Frost extends FlavourBuff {
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
return DURATION;
}
}

View File

@ -29,7 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
public class Paralysis extends FlavourBuff {
private static final float DURATION = 10f;
public static final float DURATION = 10f;
{
type = buffType.NEGATIVE;
@ -79,6 +79,6 @@ public class Paralysis extends FlavourBuff {
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
return DURATION;
}
}

View File

@ -113,10 +113,6 @@ public class Poison extends Buff implements Hero.Doom {
return true;
}
public static float durationFactor( Char ch ) {
return RingOfElements.durationFactor( ch );
}
@Override
public void onDeath() {
Badges.validateDeathFromPoison();

View File

@ -32,7 +32,7 @@ public class Slow extends FlavourBuff {
type = buffType.NEGATIVE;
}
private static final float DURATION = 10f;
public static final float DURATION = 10f;
@Override
public int icon() {
@ -48,8 +48,5 @@ public class Slow extends FlavourBuff {
public String desc() {
return Messages.get(this, "desc", dispTurns());
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
}
}

View File

@ -48,8 +48,5 @@ public class Vertigo extends FlavourBuff {
public String desc() {
return Messages.get(this, "desc", dispTurns());
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
}
}

View File

@ -21,14 +21,12 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
public class Weakness extends FlavourBuff {
private static final float DURATION = 40f;
public static final float DURATION = 40f;
{
type = buffType.NEGATIVE;
@ -43,10 +41,6 @@ public class Weakness extends FlavourBuff {
public String toString() {
return Messages.get(this, "name");
}
public static float duration( Char ch ) {
return DURATION * RingOfElements.durationFactor( ch );
}
@Override
public String heroMessage() {

View File

@ -981,7 +981,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.FULL.contains(src.getClass())){
&& RingOfElements.RESISTS.contains(src.getClass())){
dmg -= Random.NormalIntRange(belongings.armor.DRMin(), belongings.armor.DRMax())/3;
}

View File

@ -48,7 +48,7 @@ public class Bandit extends Thief {
if (super.steal( hero )) {
Buff.prolong( hero, Blindness.class, Random.Int( 2, 5 ) );
Buff.affect( hero, Poison.class ).set(Random.Int(5, 7) * Poison.durationFactor(enemy));
Buff.affect( hero, Poison.class ).set(Random.Int(5, 7) );
Buff.prolong( hero, Cripple.class, Random.Int( 3, 8 ) );
Dungeon.observe();

View File

@ -86,7 +86,7 @@ public class GnollTrickster extends Gnoll {
Buff.affect(enemy, Burning.class).reignite( enemy );
} else
Buff.affect( enemy, Poison.class).set((effect-2) * Poison.durationFactor(enemy));
Buff.affect( enemy, Poison.class).set((effect-2) );
}
return damage;

View File

@ -80,7 +80,7 @@ public class Spinner extends Mob {
public int attackProc(Char enemy, int damage) {
damage = super.attackProc( enemy, damage );
if (Random.Int(2) == 0) {
Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy));
Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) );
state = FLEEING;
}

View File

@ -73,7 +73,7 @@ public class Succubus extends Mob {
damage = super.attackProc( enemy, damage );
if (Random.Int( 3 ) == 0) {
Buff.affect( enemy, Charm.class, Charm.durationFactor( enemy ) * Random.IntRange( 3, 7 ) ).object = id();
Buff.affect( enemy, Charm.class, Random.IntRange( 3, 7 ) ).object = id();
enemy.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
Sample.INSTANCE.play( Assets.SND_CHARMS );
}

View File

@ -100,7 +100,7 @@ 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( enemy ) );
Buff.prolong( enemy, Weakness.class, Weakness.DURATION );
}
int dmg = Random.Int( 12, 18 );

View File

@ -44,7 +44,7 @@ public class Affection extends Glyph {
int duration = Random.IntRange( 2, 5 );
Buff.affect( attacker, Charm.class, Charm.durationFactor( attacker ) * duration ).object = defender.id();
Buff.affect( attacker, Charm.class, duration ).object = defender.id();
attacker.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
}

View File

@ -540,7 +540,7 @@ public class DriedRose extends Artifact {
public void damage(int dmg, Object src) {
//TODO improve this when I have proper damage source logic
if (rose != null && rose.armor != null && rose.armor.hasGlyph(AntiMagic.class)
&& RingOfElements.FULL.contains(src.getClass())){
&& RingOfElements.RESISTS.contains(src.getClass())){
dmg -= Random.NormalIntRange(rose.armor.DRMin(), rose.armor.DRMax())/3;
}

View File

@ -63,15 +63,15 @@ public class MysteryMeat extends Food {
break;
case 1:
GLog.w( Messages.get(MysteryMeat.class, "legs") );
Buff.prolong( hero, Roots.class, Paralysis.duration( hero ) );
Buff.prolong( hero, Roots.class, Paralysis.DURATION );
break;
case 2:
GLog.w( Messages.get(MysteryMeat.class, "not_well") );
Buff.affect( hero, Poison.class ).set( Poison.durationFactor( hero ) * hero.HT / 5 );
Buff.affect( hero, Poison.class ).set( hero.HT / 5 );
break;
case 3:
GLog.w( Messages.get(MysteryMeat.class, "stuffed") );
Buff.prolong( hero, Slow.class, Slow.duration( hero ) );
Buff.prolong( hero, Slow.class, Slow.DURATION );
break;
}
}

View File

@ -22,10 +22,17 @@
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Electricity;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Venom;
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;
@ -40,31 +47,38 @@ public class RingOfElements extends Ring {
protected RingBuff buff( ) {
return new Resistance();
}
private static final HashSet<Class> EMPTY = new HashSet<>();
public static final HashSet<Class> FULL = new HashSet<>();
public static final HashSet<Class> RESISTS = new HashSet<>();
static {
FULL.add( Burning.class );
FULL.add( ToxicGas.class );
FULL.add( Poison.class );
FULL.add( Venom.class );
FULL.add( Shaman.class );
FULL.add( Warlock.class );
FULL.add( Eye.class );
FULL.add( Yog.BurningFist.class );
RESISTS.add( Burning.class );
RESISTS.add( Charm.class );
RESISTS.add( Chill.class );
RESISTS.add( Frost.class );
RESISTS.add( Ooze.class );
RESISTS.add( Paralysis.class );
RESISTS.add( Poison.class );
RESISTS.add( Venom.class );
RESISTS.add( Weakness.class );
RESISTS.add( ToxicGas.class );
RESISTS.add( Electricity.class );
RESISTS.add( Shaman.class );
RESISTS.add( Warlock.class );
RESISTS.add( Eye.class );
RESISTS.add( Yog.BurningFist.class );
}
public static HashSet<Class> resistances( Char target ){
if (Random.Int( getBonus(target, Resistance.class) + 2 ) >= 2) {
return FULL;
} else {
return EMPTY;
public static float resist( Char target, Class effect ){
if (getBonus(target, Resistance.class) == 0) return 1f;
for (Class c : RESISTS){
if (c.isAssignableFrom(effect)){
return (float)Math.pow(0.875, getBonus(target, Resistance.class));
}
}
}
public static float durationFactor( Char target ){
int level = getBonus( target, Resistance.class);
return level <= 0 ? 1 : (1 + 0.5f * level) / (1 + level);
return 1f;
}
public class Resistance extends RingBuff {

View File

@ -52,7 +52,7 @@ public class ScrollOfPsionicBlast extends Scroll {
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Dungeon.level.heroFOV[mob.pos]) {
mob.damage(mob.HT, this );
mob.damage(mob.HP, this);
}
}

View File

@ -105,10 +105,10 @@ public class WandOfTransfusion extends Wand {
} else {
float duration = 5+level();
Buff.affect(ch, Charm.class, Charm.durationFactor(ch) * duration).object = curUser.id();
Buff.affect(ch, Charm.class, duration).object = curUser.id();
duration *= Random.Float(0.75f, 1f);
Buff.affect(curUser, Charm.class, Charm.durationFactor(ch) * duration).object = ch.id();
Buff.affect(curUser, Charm.class, duration).object = ch.id();
ch.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
curUser.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );

View File

@ -45,7 +45,7 @@ public class Eldritch extends Weapon.Enchantment {
if (Random.Int( level + 5 ) >= 4) {
if (defender == Dungeon.hero) {
Buff.affect( defender, Vertigo.class, Vertigo.duration(defender) );
Buff.affect( defender, Vertigo.class, Vertigo.DURATION );
} else {
Buff.affect( defender, Terror.class, Terror.DURATION ).object = attacker.id();
}

View File

@ -44,7 +44,7 @@ public class Venomous extends Weapon.Enchantment {
if (Random.Int( level + 3 ) >= 2) {
Buff.affect( defender, Poison.class ).extend( Poison.durationFactor( defender ) * ((level/2) + 1) );
Buff.affect( defender, Poison.class ).extend( ((level/2) + 1) );
CellEmitter.center(defender.pos).burst( PoisonParticle.SPLASH, 5 );
}

View File

@ -86,7 +86,7 @@ public class PoisonDartTrap extends Trap {
Dungeon.fail( trap.getClass() );
}
Buff.affect( finalTarget, Poison.class )
.set( Poison.durationFactor( finalTarget ) * (4 + Dungeon.depth) );
.set( 4 + Dungeon.depth );
Sample.INSTANCE.play(Assets.SND_HIT, 1, 1, Random.Float(0.8f, 1.25f));
finalTarget.sprite.bloodBurstA(finalTarget.sprite.center(), dmg);
finalTarget.sprite.flash();
@ -100,7 +100,7 @@ public class PoisonDartTrap extends Trap {
} else {
finalTarget.damage(Random.NormalIntRange(1, 4) - finalTarget.drRoll(), trap);
Buff.affect( finalTarget, Poison.class )
.set( Poison.durationFactor( finalTarget ) * (4 + Dungeon.depth) );
.set( 4 + Dungeon.depth );
}
}
}

View File

@ -95,7 +95,7 @@ public class RockfallTrap extends Trap {
damage -= ch.drRoll();
ch.damage( Math.max(damage, 0) , this);
Buff.prolong( ch, Paralysis.class, Paralysis.duration(ch)/2);
Buff.prolong( ch, Paralysis.class, Paralysis.DURATION );
if (!ch.isAlive() && ch == Dungeon.hero){
Dungeon.fail( getClass() );

View File

@ -44,7 +44,7 @@ public class WeakeningTrap extends Trap{
Char ch = Actor.findChar( pos );
if (ch == Dungeon.hero){
Buff.prolong( ch, Weakness.class, Weakness.duration(ch)*2f);
Buff.prolong( ch, Weakness.class, Weakness.DURATION*2f );
}
}
}

View File

@ -42,7 +42,7 @@ public class Sorrowmoss extends Plant {
Char ch = Actor.findChar(pos);
if (ch != null) {
Buff.affect( ch, Poison.class ).set( Poison.durationFactor( ch ) * (4 + Dungeon.depth / 2) );
Buff.affect( ch, Poison.class ).set( 4 + Dungeon.depth / 2 );
}
if (Dungeon.level.heroFOV[pos]) {

View File

@ -39,7 +39,7 @@ public class Stormvine extends Plant {
Char ch = Actor.findChar(pos);
if (ch != null) {
Buff.affect(ch, Vertigo.class, Vertigo.duration( ch ) );
Buff.affect(ch, Vertigo.class, Vertigo.DURATION );
}
}

View File

@ -538,7 +538,7 @@ items.rings.ringofaccuracy.name=ring of accuracy
items.rings.ringofaccuracy.desc=This ring increases your focus, reducing your enemy's ability to dodge your attacks. A cursed ring will instead make it easier for enemies to evade your attacks.
items.rings.ringofelements.name=ring of elements
items.rings.ringofelements.desc=This ring provides resistance to different elements, such as fire, electricity, gases etc. Also it decreases duration of negative effects.
items.rings.ringofelements.desc=This ring provides resistance to most elemental and magical effects, decreasing damage and debuff duration. Naturally a cursed ring will instead worsen these effects.
items.rings.ringofevasion.name=ring of evasion
items.rings.ringofevasion.desc=This ring quickens the wearer's reactions, making it harder to land blows on them. A cursed ring will instead make the user easier to strike.