Skip to content

Commit

Permalink
Merge pull request Arakne#290 from vincent4vx/feature-fight-handle-ph…
Browse files Browse the repository at this point in the history
…ysical-magical-damage-effects

handle physical magical damage effects
  • Loading branch information
vincent4vx authored Jun 3, 2023
2 parents 64eb742 + 7bbc3a4 commit 65c0089
Show file tree
Hide file tree
Showing 9 changed files with 415 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ public Characteristic percentResistance() {
return percentResistance;
}

/**
* Check if this element is physical (neutral or earth)
*/
public boolean physical() {
return this == NEUTRAL || this == EARTH;
}

/**
* Extract set of elements from a bit set
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* This file is part of Araknemu.
*
* Araknemu is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Araknemu 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Araknemu. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (c) 2017-2023 Vincent Quatrevieux
*/

package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor;

import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buff;
import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffEffect;
import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffHook;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.EffectHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.Damage;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;

/**
* Buff effect for increasing or decrease magical or physical resistance
*
* Like {@link fr.quatrevieux.araknemu.game.fight.castable.effect.handler.characteristic.AddCharacteristicHandler},
* the effect value will be computed before the buff is applied, so the resistance is fixed
*
* Unlike {@link ReduceDamageHandler}, this effect reduce all damage, not only direct damage
*/
public final class AlterResistanceHandler implements EffectHandler, BuffHook {
private final boolean physical;
private final int multiplier;

/**
* @param physical Does this effect alter physical resistance ? If false, it alters magical resistance
* @param multiplier The multiplier to apply to the resistance. 1 for adding resistance, -1 for reducing resistance
*/
public AlterResistanceHandler(boolean physical, int multiplier) {
this.physical = physical;
this.multiplier = multiplier;
}

@Override
public void handle(FightCastScope cast, FightCastScope.EffectScope effect) {
throw new UnsupportedOperationException("AlterResistanceHandler can only be used as buff");
}

@Override
public void buff(FightCastScope cast, FightCastScope.EffectScope effect) {
final SpellEffect spellEffect = effect.effect();
final Fighter caster = cast.caster();

EffectValue.forEachTargets(
spellEffect,
caster,
effect.targets(),
(target, effectValue) -> target.buffs().add(new Buff(
BuffEffect.fixed(spellEffect, effectValue.value()),
cast.action(),
caster,
target,
this
))
);
}

@Override
public void onDamage(Buff buff, Damage value) {
if (value.element().physical() != physical) {
return;
}

value.fixed(buff.effect().min() * multiplier);
}

/**
* Create effect handler for adding physical resistance
* So, it will reduce all suffered damage with element neutral or earth
*/
public static AlterResistanceHandler increasePhysical() {
return new AlterResistanceHandler(true, 1);
}

/**
* Create effect handler for adding magical resistance
* So, it will reduce all suffered damage with element air, fire or water
*/
public static AlterResistanceHandler increaseMagical() {
return new AlterResistanceHandler(false, 1);
}

/**
* Create effect handler for reducing magical resistance
* So, it will increase all suffered damage with element air, fire or water
*/
public static AlterResistanceHandler reduceMagical() {
return new AlterResistanceHandler(false, -1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ private Damage computeDamage(Fighter caster, SpellEffect effect, Fighter target)
.fixed(caster.characteristics().get(Characteristic.FIXED_DAMAGE))
;

if (element.physical()) {
value.fixed(caster.characteristics().get(Characteristic.PHYSICAL_DAMAGE));
}

if (effect.trap()) {
value
.fixed(caster.characteristics().get(Characteristic.TRAP_BOOST))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectsHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.Element;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.HealOrMultiplyDamageHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.AlterResistanceHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.ReduceDamageHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.ReflectDamageHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.SpellReturnHandler;
Expand Down Expand Up @@ -154,6 +155,9 @@ public void effects(EffectsHandler handler) {
handler.register(105, new ReduceDamageHandler());
handler.register(106, new SpellReturnHandler(fight));
handler.register(107, new ReflectDamageHandler());
handler.register(172, AlterResistanceHandler.reduceMagical());
handler.register(183, AlterResistanceHandler.increaseMagical());
handler.register(184, AlterResistanceHandler.increasePhysical());
handler.register(265, new ReduceDamageHandler());

handler.register(114, new MultiplyDamageHandler());
Expand Down Expand Up @@ -185,6 +189,7 @@ public void effects(EffectsHandler handler) {
handler.register(125, new AddVitalityHandler(fight));
handler.register(126, new AddCharacteristicHandler(fight, Characteristic.INTELLIGENCE));
handler.register(138, new AddCharacteristicHandler(fight, Characteristic.PERCENT_DAMAGE));
handler.register(142, new AddCharacteristicHandler(fight, Characteristic.PHYSICAL_DAMAGE));
handler.register(178, new AddCharacteristicHandler(fight, Characteristic.HEALTH_BOOST));
handler.register(182, new AddCharacteristicHandler(fight, Characteristic.MAX_SUMMONED_CREATURES));
handler.register(220, new AddCharacteristicHandler(fight, Characteristic.COUNTER_DAMAGE));
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ public GameDataSet pushFunctionalSpells() throws SQLException, ContainerExceptio
"(1688, 'Répulsion', -1, '0,0,0', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '5,2,,,0,0||5|0|0|0|0|true|false|false|false|0|0|0|0|Xb||18;19;3;1;41|0|false', '')",
"(79, 'Piège de Masse', 410, '0,1,1', '400,1493,1,8,0,0||5|1|3|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|21|false', '400,1493,2,8,0,0||5|1|3|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|21|false', '400,1493,3,8,0,0||5|1|4|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|21|false', '400,1493,4,8,0,0||5|1|4|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|21|false', '400,1493,5,8,0,0||5|1|5|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|21|false', '400,1493,6,8,0,0||4|1|5|0|100|true|false|true|true|0|1|0|0|Cc||18;19;3;1;41|121|false', '')",
"(1493, 'Explosion de masse', -1, '0,0,0', '97,2,10,,0,0,2d5+0||2|1|1|0|100|true|true|false|false|0|0|3|0|Cc||18;19;3;1;41|0|false', '97,4,12,,0,0,2d5+2||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,6,14,,0,0,2d5+4||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,7,15,,0,0,2d5+5||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,9,17,,0,0,2d5+7||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,13,21,,0,0,2d5+11||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '')",
"(16, 'Science du bâton', 101, '10,1,1', '142,5,,,5,0,0d0+5|142,7,,,5,0,0d0+7|3|0|1|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,6,,,5,0,0d0+6|142,8,,,5,0,0d0+8|3|0|2|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,8,,,5,0,0d0+8|142,11,,,5,0,0d0+11|3|0|3|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,10,,,5,0,0d0+10|142,15,,,5,0,0d0+15|3|0|4|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,15,,,5,0,0d0+15|142,20,,,5,0,0d0+20|3|0|5|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,25,,,5,0,0d0+25|142,30,,,5,0,0d0+30|2|0|6|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|142|false', '')",
"(197, 'Puissance Sylvestre', 0, '10,1,1', '149,,,8005,2,0;169,100,,,2,0,0d0+100;183,1000,,,2,0,0d0+1000;184,1000,,,2,0,0d0+1000;168,100,,,2,0,0d0+100;108,10,,,2,0,0d0+10||6|0|1|0|100|true|false|false|true|0|0|0|15|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,2,0;169,100,,,2,0,0d0+100;183,1000,,,2,0,0d0+1000;184,1000,,,2,0,0d0+1000;168,100,,,2,0,0d0+100;108,11,,,2,0,0d0+11||5|0|2|0|100|true|false|false|true|0|0|0|14|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,3,0;169,100,,,3,0,0d0+100;183,1000,,,3,0,0d0+1000;184,1000,,,3,0,0d0+1000;168,100,,,3,0,0d0+100;108,12,,,3,0,0d0+12||5|0|3|0|100|true|false|false|true|0|0|0|13|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,3,0;169,100,,,3,0,0d0+100;183,1000,,,3,0,0d0+1000;184,1000,,,3,0,0d0+1000;168,100,,,3,0,0d0+100;108,13,,,3,0,0d0+13||4|0|4|0|100|true|false|false|true|0|0|0|12|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,4,0;169,100,,,4,0,0d0+100;183,1000,,,4,0,0d0+1000;184,1000,,,4,0,0d0+1000;168,100,,,4,0,0d0+100;108,14,,,4,0,0d0+14||3|0|5|0|100|true|false|false|true|0|0|0|11|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,4,0;169,100,,,4,0,0d0+100;183,1000,,,4,0,0d0+1000;184,1000,,,4,0,0d0+1000;168,100,,,4,0,0d0+100;108,16,,,4,0,0d0+16||2|0|6|0|100|true|false|false|true|0|0|0|10|PaPaPaPaPaPa||8;18;19;3;1;41|117|false', '4;4;4;4;4;4;5;5;5;5;5;5')",
}, ",") + ";"
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,13 @@ void fromBitSet() {
assertEquals(EnumSet.of(Element.AIR, Element.NEUTRAL), Element.fromBitSet(9));
assertSame(Element.fromBitSet(9), Element.fromBitSet(9));
}

@Test
void physical() {
assertTrue(Element.NEUTRAL.physical());
assertTrue(Element.EARTH.physical());
assertFalse(Element.WATER.physical());
assertFalse(Element.AIR.physical());
assertFalse(Element.FIRE.physical());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,37 @@ void areaTrapShouldApplyEffectToAllFightersInArea() {
requestStack.assertOne(ActionEffect.trapTriggered(fighter1, fighter2, fight.map().get(197), service.get(79).level(5)));
}

@Test
void addPhysicalDamage() {
fighter1.turn().points().addActionPoints(10);

castNormal(16, fighter1.cell()); // Science du bâton
castNormal(183, fighter2.cell()); // Ronce

int damage = fighter2.life().max() - fighter2.life().current();
assertBetween(30, 40, damage); // +15 damage

fighter2.life().alter(fighter2, 100);

castNormal(3, fighter2.cell()); // Attaque naturelle

damage = fighter2.life().max() - fighter2.life().current();
assertBetween(17, 27, damage); // Boost not applied
}

@Test
void increaseResistance() {
castNormal(197, fighter1.cell()); // Puissance Sylvestre
fighter1.turn().stop();

fighter2.turn().points().addActionPoints(10);

castNormal(183, fighter1.cell()); // Ronce
castNormal(3, fighter1.cell()); // Attaque naturelle

assertTrue(fighter1.life().isFull());
}

private List<Fighter> configureFight(Consumer<FightBuilder> configurator) {
fight.cancel(true);

Expand Down
Loading

0 comments on commit 65c0089

Please sign in to comment.