Skip to content

Commit

Permalink
Merge pull request #224 from vincent4vx/spell-effect-modify-effect-value
Browse files Browse the repository at this point in the history
[fight] #27 fight effects: Add maximize, minimize effects and multipl…
  • Loading branch information
vincent4vx authored Feb 8, 2022
2 parents a70d9bc + 1681ba9 commit ab603d9
Show file tree
Hide file tree
Showing 37 changed files with 1,157 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.Element;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.Damage;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.PassiveFighter;

/**
Expand All @@ -42,15 +43,19 @@ public DamageSimulator(Element element) {

@Override
public void simulate(CastSimulation simulation, CastScope.EffectScope effect) {
// @todo apply caster and target buff
final Interval value = new EffectValue(effect.effect())
.percent(simulation.caster().characteristics().get(element.boost()))
.percent(simulation.caster().characteristics().get(Characteristic.PERCENT_DAMAGE))
.fixed(simulation.caster().characteristics().get(Characteristic.FIXED_DAMAGE))
.interval()
;
final ActiveFighter caster = simulation.caster();
final int boost = caster.characteristics().get(element.boost());
final int percent = caster.characteristics().get(Characteristic.PERCENT_DAMAGE);
final int fixed = caster.characteristics().get(Characteristic.FIXED_DAMAGE);

for (PassiveFighter target : effect.targets()) {
final Interval value = EffectValue.create(effect.effect(), simulation.caster(), target)
.percent(boost)
.percent(percent)
.fixed(fixed)
.interval()
;

final Interval damage = value.map(base -> computeDamage(base, target));

if (effect.effect().duration() < 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@

import fr.arakne.utils.value.Interval;
import fr.arakne.utils.value.helper.RandomUtil;
import fr.quatrevieux.araknemu.game.fight.fighter.PassiveFighter;
import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;

import java.util.function.BiConsumer;

/**
* Handle effect jet value
*
* Computed value is :
* ( [jet + boost] * percent / 100 + fixed + effectBonus ) * multiply
*/
public final class EffectValue {
public final class EffectValue implements Cloneable {
enum State {
MINIMIZED,
RANDOMIZED,
MAXIMIZED,
FIXED,
}

/**
Expand All @@ -48,8 +52,9 @@ enum State {
private int percent = 100;
private int fixed = 0;
private int multiply = 1;
private int value = 0;

public EffectValue(SpellEffect effect) {
EffectValue(SpellEffect effect) {
this.effect = effect;
}

Expand Down Expand Up @@ -80,6 +85,16 @@ public EffectValue randomize() {
return this;
}

/**
* Roll the dice to fix the effect value
*/
public EffectValue roll() {
value = jet();
state = State.FIXED;

return this;
}

/**
* Boost the dice value
* The boost will be added at dice value
Expand Down Expand Up @@ -141,6 +156,9 @@ public int value() {
*/
public Interval interval() {
switch (state) {
case FIXED:
return Interval.of(value);

case MINIMIZED:
return Interval.of(applyBoost(effect.min()));

Expand All @@ -153,8 +171,75 @@ public Interval interval() {
}
}

@Override
protected EffectValue clone() {
try {
return (EffectValue) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(); // Should not occur
}
}

/**
* Create and configure an effect value for a given caster and target
*
* @param effect The spell effect
* @param caster The spell caster on which {@link fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs#onEffectValueCast(EffectValue)} will be called
* @param target The target on which {@link fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs#onEffectValueTarget(EffectValue, PassiveFighter)} will be called
*
* @return The configured effect
*/
public static EffectValue create(SpellEffect effect, PassiveFighter caster, PassiveFighter target) {
final EffectValue value = new EffectValue(effect);

caster.buffs().onEffectValueCast(value);
target.buffs().onEffectValueTarget(value, caster);

return value;
}

/**
* Create and configure multiple effect values for multiple targets
*
* Only one "dice" will be used for all targets, but each target will receive their own EffectValue,
* configured using {@link fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs#onEffectValueTarget(EffectValue, PassiveFighter)}.
*
* So {@link EffectValue#minimize()} and {@link EffectValue#maximize()} are effective, without change the effects value of others targets
*
* Usage:
* <pre>{@code
* public void handle(CastScope cast, CastScope.EffectScope effect) {
* EffectValue.forEachTargets(effect.effect(), cast.caster(), effect.targets(), (target, effectValue) -> {
* // Apply the effect (effectValue) on target
* target.life().alter(cast.caster(), effectValue.value());
* });
* }
* }</pre>
*
* @param effect The spell effect
* @param caster The spell caster on which {@link fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs#onEffectValueCast(EffectValue)} will be called
* @param targets Targets used to configure the effect value using {@link fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs#onEffectValueTarget(EffectValue, PassiveFighter)}
* @param action Action to perform on each target, with their related effect value
*/
public static void forEachTargets(SpellEffect effect, PassiveFighter caster, Iterable<PassiveFighter> targets, BiConsumer<PassiveFighter, EffectValue> action) {
final EffectValue value = new EffectValue(effect);

caster.buffs().onEffectValueCast(value);
value.roll();

for (PassiveFighter target : targets) {
final EffectValue targetValue = value.clone();
target.buffs().onEffectValueTarget(targetValue, caster);

action.accept(target, targetValue);
}
}

private int jet() {
switch (state) {
case FIXED:
return value;

case MINIMIZED:
return effect.min();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package fr.quatrevieux.araknemu.game.fight.castable.effect.buff;

import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.Damage;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.ReflectedDamage;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
Expand Down Expand Up @@ -154,4 +155,37 @@ public default void onLifeAltered(Buff buff, int value) {}
* @param damage The reflected damage
*/
public default void onReflectedDamage(Buff buff, ReflectedDamage damage) {}

/**
* A damage will be applied on target
* Use this hook to configure damage before apply it
*
* Unlike {@link BuffHook#onDamage(Buff, Damage)} this hook is called on the caster instead of the target
*
* @param buff The active buff
* @param damage Damage to configure
* @param target The effect target
*/
public default void onCastDamage(Buff buff, Damage damage, PassiveFighter target) {}

/**
* A new effect value is generated by the current fighter
*
* Note: {@link BuffHook#onEffectValueTarget(Buff, EffectValue, PassiveFighter)} is always called on the target after
*
* @param buff The active buff
* @param value The new effect value which will be applied
*/
public default void onEffectValueCast(Buff buff, EffectValue value) {}

/**
* An effect value will be applied on the current fighter
*
* Note: {@link BuffHook#onEffectValueCast(Buff, EffectValue)} is always called on the caster before
*
* @param buff The active buff
* @param value The effect value which will be applied
* @param caster The effect caster
*/
public default void onEffectValueTarget(Buff buff, EffectValue value, PassiveFighter caster) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package fr.quatrevieux.araknemu.game.fight.castable.effect.buff;

import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.Damage;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.ReflectedDamage;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
Expand Down Expand Up @@ -131,6 +132,27 @@ public void onReflectedDamage(ReflectedDamage damage) {
}
}

@Override
public void onCastDamage(Damage damage, PassiveFighter target) {
for (Buff buff : buffs) {
buff.hook().onCastDamage(buff, damage, target);
}
}

@Override
public void onEffectValueCast(EffectValue value) {
for (Buff buff : buffs) {
buff.hook().onEffectValueCast(buff, value);
}
}

@Override
public void onEffectValueTarget(EffectValue value, PassiveFighter caster) {
for (Buff buff : buffs) {
buff.hook().onEffectValueTarget(buff, value, caster);
}
}

@Override
public void refresh() {
removeIf(buff -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package fr.quatrevieux.araknemu.game.fight.castable.effect.buff;

import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.Damage;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.damage.ReflectedDamage;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
Expand Down Expand Up @@ -76,6 +77,21 @@ public interface Buffs extends Iterable<Buff> {
*/
public void onEndTurn();

/**
* @see BuffHook#onCastDamage(Buff, Damage, PassiveFighter)
*/
public void onCastDamage(Damage damage, PassiveFighter target);

/**
* @see BuffHook#onEffectValueCast(Buff, EffectValue)
*/
public void onEffectValueCast(EffectValue value);

/**
* @see BuffHook#onEffectValueTarget(Buff, EffectValue, PassiveFighter)
*/
public void onEffectValueTarget(EffectValue value, PassiveFighter caster);

/**
* Refresh the buff list after turn end
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void onDirectDamage(Buff buff, ActiveFighter caster, Damage value) {
// Ignore self damage
if (!caster.equals(buff.target())) {
value.reflect(
new EffectValue(buff.effect())
EffectValue.create(buff.effect(), buff.target(), caster)
.percent(buff.target().characteristics().get(Characteristic.WISDOM))
.value()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
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.fighter.PassiveFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;

/**
Expand All @@ -45,11 +45,21 @@ public void handle(CastScope cast, CastScope.EffectScope effect) {

@Override
public void buff(CastScope cast, CastScope.EffectScope effect) {
final SpellEffect buffEffect = computeBuffEffect(cast, effect.effect());
final SpellEffect spellEffect = effect.effect();
final ActiveFighter caster = cast.caster();

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

@Override
Expand All @@ -61,13 +71,4 @@ public void onBuffStarted(Buff buff) {
public void onBuffTerminated(Buff buff) {
hook.onBuffTerminated(buff);
}

/**
* Compute the buff value
*/
private SpellEffect computeBuffEffect(CastScope cast, SpellEffect effect) {
final EffectValue value = new EffectValue(effect);

return BuffEffect.fixed(effect, value.value());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.characteristic.point.AlterPointHook;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect;

/**
Expand All @@ -41,11 +42,12 @@ public AddActionPointsHandler(Fight fight) {
@Override
public void handle(CastScope cast, CastScope.EffectScope effect) {
fight.turnList().current().ifPresent(turn -> {
final EffectValue value = new EffectValue(effect.effect());
final ActiveFighter fighter = turn.fighter();
final EffectValue value = EffectValue.create(effect.effect(), fighter, fighter);
final int ap = value.value();

turn.points().addActionPoints(ap);
fight.send(ActionEffect.addActionPoints(turn.fighter(), ap));
fight.send(ActionEffect.addActionPoints(fighter, ap));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.characteristic.point.AlterPointHook;
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect;

/**
Expand All @@ -41,11 +42,12 @@ public AddMovementPointsHandler(Fight fight) {
@Override
public void handle(CastScope cast, CastScope.EffectScope effect) {
fight.turnList().current().ifPresent(turn -> {
final EffectValue value = new EffectValue(effect.effect());
final ActiveFighter fighter = turn.fighter();
final EffectValue value = EffectValue.create(effect.effect(), fighter, fighter);
final int mp = value.value();

turn.points().addMovementPoints(mp);
fight.send(ActionEffect.addMovementPoints(turn.fighter(), mp));
fight.send(ActionEffect.addMovementPoints(fighter, mp));
});
}
}
Loading

0 comments on commit ab603d9

Please sign in to comment.