/* * Pixel Dungeon * Copyright (C) 2012-2015 Oleg Dolya * * Yet Another Pixel Dungeon * Copyright (C) 2015-2016 Considered Hamster * * 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.consideredhamster.yetanotherpixeldungeon; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Crippled; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.BuffActive; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Shocked; import com.consideredhamster.yetanotherpixeldungeon.actors.Char; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Burning; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Corrosion; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Vertigo; import com.consideredhamster.yetanotherpixeldungeon.actors.buffs.debuffs.Withered; import com.consideredhamster.yetanotherpixeldungeon.levels.Level; import com.consideredhamster.yetanotherpixeldungeon.misc.utils.GLog; import com.consideredhamster.yetanotherpixeldungeon.visuals.effects.particles.FlameParticle; import com.consideredhamster.yetanotherpixeldungeon.visuals.effects.particles.SparkParticle; import com.watabou.utils.Random; import java.util.Map; public abstract class Element { public abstract int proc( Char target, int damage ); public static final Physical PHYSICAL = new Physical(); public static final Physical.Falling FALLING = new Physical.Falling(); public static final Knockback KNOCKBACK = new Knockback(); public static final Ensnaring ENSNARING = new Ensnaring(); public static final Flame FLAME = new Flame(); public static final Flame.Periodic FLAME_PERIODIC = new Flame.Periodic(); public static final Acid ACID = new Acid(); public static final Acid.Periodic ACID_PERIODIC = new Acid.Periodic(); public static final Shock SHOCK = new Shock(); public static final Shock.Periodic SHOCK_PERIODIC = new Shock.Periodic(); public static final Mind MIND = new Mind(); public static final Body BODY = new Body(); public static final Dispel DISPEL = new Dispel(); public static final Frost FROST = new Frost(); public static final Energy ENERGY = new Energy(); public static final Unholy UNHOLY = new Unholy(); public static final Doom DOOM = new Doom(); public static class Flame extends Element { @Override public int proc( Char target, int damage ) { if (target.sprite.visible) { target.sprite.emitter().burst(FlameParticle.FACTORY, (int) Math.sqrt( damage / 2 ) + 1); } if( Random.Float() < 0.5f ){ BuffActive.addFromDamage( target, Burning.class, damage * 2 ); } return damage; } public static class Periodic extends Flame { @Override public int proc( Char target, int damage ) { return damage; } } } public static class Shock extends Element { @Override public int proc( Char target, int damage ) { if( !target.flying && Level.water[ target.pos ] ){ damage += ( damage / 2 + Random.Int( damage % 2 + 1 ) ); } // Shocked buff = target.buff( Shocked.class ); // // if( buff != null ){ // // buff.discharge(); // // } else { // // if( Random.Float() < 0.25f ){ // BuffActive.addFromDamage( target, Shocked.class, damage * 2 ); // } // //// if (target.sprite.visible) { //// target.sprite.centerEmitter().burst( SparkParticle.FACTORY, (int)Math.sqrt( damage ) + 1 ); //// } // // } return damage; } public static class Periodic extends Shock { @Override public int proc( Char target, int damage ) { return damage; } } } public static class Acid extends Element { @Override public int proc( Char target, int damage ) { if (target.sprite.visible) { target.sprite.burst(0x006600, (int) Math.sqrt(damage / 2) + 1); } if( Random.Float() < 0.75f ){ BuffActive.addFromDamage( target, Corrosion.class, damage * 2 ); } return damage; } public static class Periodic extends Acid { @Override public int proc( Char target, int damage ) { return damage; } } } public static class Frost extends Element { @Override public int proc( Char target, int damage ) { // if (target.sprite.visible) { // CellEmitter.get(target.pos).start(SnowParticle.FACTORY, 0.2f, 6); // } // // if ( damage < target.HP && Random.Int( target.HT * 2 ) < damage * damage / 2 ) { // Buff.affect(target, Frozen.class, (Level.water[target.pos] && !target.flying // ? Random.Float(2.0f, 3.0f) : Random.Float(1.0f, 1.5f))); // } return damage; } } public static class Energy extends Element { @Override public int proc( Char target, int damage ) { return damage; } } public static class Body extends Element { @Override public int proc( Char target, int damage ) { return damage; } } public static class Mind extends Element { @Override public int proc( Char target, int damage ) { return damage; } } public static class Unholy extends Element { @Override public int proc( Char target, int damage ) { // if ( Random.Int( target.HT ) < damage * damage / 2 ) { BuffActive.addFromDamage(target, Withered.class, damage * 2 ); // if( damage < target.HP && buff != null ) { // // damage *= buff.modify(); // // } // } return damage; } } public static class Dispel extends Element { @Override public int proc( Char target, int damage ) { return damage; } } public static class Doom extends Element { @Override public int proc( Char target, int damage ) { return damage; } } public static class Physical extends Element { @Override public int proc( Char target, int damage ){ return damage; } public static class Falling extends Physical { @Override public int proc( Char target, int damage ){ BuffActive.addFromDamage( target, Crippled.class, damage ); return damage; } } } public static class Knockback extends Element { @Override public int proc( Char target, int damage ){ // not actually needed, because knockback deals physical damage // maybe make some separate class from Element for such effects? return damage; } } public static class Ensnaring extends Element { @Override public int proc( Char target, int damage ){ // yeah, I guess I really should add a separate class for cases like these return damage; } } public static class Resist { public static final float VULNERABLE = -1.0f; public static final float DEFAULT = 0.0f; public static final float PARTIAL = 0.5f; public static final float IMMUNE = 1.0f; public static int modifyValue( int value, Char target, Element type ) { float resist = Element.Resist.getResistance( target, type ); if( !Element.Resist.checkIfDefault( resist ) ) { if ( Element.Resist.checkIfNegated( resist ) ) { value = 0; } else if ( Element.Resist.checkIfPartial( resist ) ) { value = value / 2 + Random.Int( value % 2 + 1 ); } else if ( Element.Resist.checkIfAmplified( resist ) ) { value = value * 3 / 2 + Random.Int( value % 2 + 1 ); } } return value; } public static float getResistance( Char target, Element type ) { Float resistance = DEFAULT; for( Map.Entry<Class<? extends Element>, Float> entry : target.resistances().entrySet() ) { if( entry.getKey().isInstance( type ) ) { resistance = entry.getValue(); break; } } return resistance; } public static boolean checkIfDefault( float resistance ) { return resistance == DEFAULT; } public static boolean checkIfNegated( float resistance ) { return resistance > IMMUNE || resistance > Random.Float( PARTIAL, IMMUNE ); } public static boolean checkIfPartial( float resistance ) { return resistance > PARTIAL || resistance > Random.Float( DEFAULT, PARTIAL ); } public static boolean checkIfAmplified( float resistance ) { return resistance < VULNERABLE || resistance < Random.Float( VULNERABLE, DEFAULT ); } } }