diff --git a/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java b/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java
index 26434a7ce..e77a8a1d7 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java
@@ -983,6 +983,7 @@ private void configureServices(ContainerConfigurator configurator) {
simulator.register(125, new AlterCharacteristicSimulator()); // vitality
simulator.register(126, new AlterCharacteristicSimulator()); // intelligence
simulator.register(138, new AlterCharacteristicSimulator(2)); // percent damage
+ simulator.register(176, new AlterCharacteristicSimulator(20)); // discernment
simulator.register(178, new AlterCharacteristicSimulator(8)); // heal
simulator.register(182, new AddMaxSummonedCreatureSimulator(10)); // summoned creature
simulator.register(606, new AlterCharacteristicSimulator()); // Wisdom not dispellable
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandler.java
new file mode 100644
index 000000000..2155df7a9
--- /dev/null
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandler.java
@@ -0,0 +1,72 @@
+/*
+ * 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 .
+ *
+ * Copyright (c) 2017-2024 Vincent Quatrevieux
+ */
+
+package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc;
+
+import fr.quatrevieux.araknemu.game.fight.castable.BaseCastScope;
+import fr.quatrevieux.araknemu.game.fight.castable.Castable;
+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.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.map.FightCell;
+import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;
+
+/**
+ * Buff effect for adding discernment points to a target
+ * When casted on a summon creature, the created will be allowed to get drops, which will be given to the summoner
+ *
+ * @see fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics#alterDiscernment(int)
+ */
+public final class AddDiscernmentHandler implements EffectHandler, BuffHook {
+ @Override
+ public void handle(FightCastScope cast, BaseCastScope.EffectScope effect) {
+ throw new UnsupportedOperationException("Add discernment should be used as buff");
+ }
+
+ @Override
+ public void buff(FightCastScope cast, BaseCastScope.EffectScope effect) {
+ final SpellEffect spellEffect = effect.effect();
+ final Castable action = cast.action();
+ final Fighter caster = cast.caster();
+
+ EffectValue.forEachTargets(spellEffect, caster, cast.targets(), (target, effectValue) -> {
+ target.buffs().add(new Buff(
+ BuffEffect.fixed(spellEffect, effectValue.value()),
+ action,
+ caster,
+ target,
+ this
+ ));
+ });
+ }
+
+ @Override
+ public void onBuffStarted(Buff buff) {
+ buff.target().characteristics().alterDiscernment(buff.effect().min());
+ }
+
+ @Override
+ public void onBuffTerminated(Buff buff) {
+ buff.target().characteristics().alterDiscernment(-buff.effect().min());
+ }
+}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/FightRewardsSheet.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/FightRewardsSheet.java
index 061238a8e..3dcd18912 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/FightRewardsSheet.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/FightRewardsSheet.java
@@ -65,4 +65,13 @@ public Type type() {
public List rewards() {
return rewards;
}
+
+ /**
+ * Apply all rewards
+ */
+ public void apply() {
+ for (DropReward reward : rewards) {
+ reward.apply();
+ }
+ }
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/RewardsGenerator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/RewardsGenerator.java
index 7b588567f..c27209238 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/RewardsGenerator.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/RewardsGenerator.java
@@ -20,6 +20,7 @@
package fr.quatrevieux.araknemu.game.fight.ending.reward;
import fr.quatrevieux.araknemu.game.fight.ending.EndFightResults;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
/**
* Generate rewards for end fight
@@ -31,4 +32,14 @@ public interface RewardsGenerator {
* @param results The end fight results
*/
public FightRewardsSheet generate(EndFightResults results);
+
+ /**
+ * Check if the given fighter can be rewarded
+ * Generally, it will check if the fighter is not a summon creature
+ *
+ * @param fighter The fighter to check
+ *
+ * @return true if the fighter can be rewarded (so it will be in the rewards sheet), false to ignore it
+ */
+ public boolean supports(Fighter fighter);
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/ChallengeRewardsGenerator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/ChallengeRewardsGenerator.java
index 6b4fb6039..9e3736b18 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/ChallengeRewardsGenerator.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/ChallengeRewardsGenerator.java
@@ -23,6 +23,7 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.FightRewardsSheet;
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardsGenerator;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import java.util.ArrayList;
import java.util.Collections;
@@ -41,4 +42,9 @@ public FightRewardsSheet generate(EndFightResults results) {
return new FightRewardsSheet(results, FightRewardsSheet.Type.NORMAL, rewards);
}
+
+ @Override
+ public boolean supports(Fighter fighter) {
+ return !fighter.invoked();
+ }
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddItems.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddItems.java
index 2ca136710..f14fa559e 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddItems.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddItems.java
@@ -38,17 +38,40 @@ public AddItems(ItemService service) {
@Override
public void apply(DropReward reward, Fighter fighter) {
- fighter.apply(new FighterOperation() {
- @Override
- public void onPlayer(PlayerFighter fighter) {
- final PlayerInventory inventory = fighter.player().inventory();
-
- reward.items().forEach((itemId, quantity) -> {
- for (int q = 0; q < quantity; ++q) {
- inventory.add(service.create(itemId));
- }
- });
+ fighter.apply(new Operation(reward));
+ }
+
+ private class Operation implements FighterOperation {
+ private final DropReward reward;
+
+ public Operation(DropReward reward) {
+ this.reward = reward;
+ }
+
+ @Override
+ public void onPlayer(PlayerFighter fighter) {
+ final PlayerInventory inventory = fighter.player().inventory();
+
+ reward.items().forEach((itemId, quantity) -> {
+ for (int q = 0; q < quantity; ++q) {
+ inventory.add(service.create(itemId));
+ }
+ });
+ }
+
+ @Override
+ public void onGenericFighter(Fighter fighter) {
+ if (!fighter.invoked()) {
+ return;
}
- });
+
+ final Fighter invoker = fighter.invoker();
+
+ if (invoker == null) {
+ return;
+ }
+
+ invoker.apply(this);
+ }
}
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddKamas.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddKamas.java
index 78d1b8cf4..7019cde9d 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddKamas.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/action/AddKamas.java
@@ -23,6 +23,7 @@
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
+import org.checkerframework.checker.index.qual.Positive;
/**
* Add kamas to fighter
@@ -32,15 +33,36 @@ public final class AddKamas implements DropRewardAction {
public void apply(DropReward reward, Fighter fighter) {
final long kamas = reward.kamas();
- if (kamas == 0) {
- return;
+ if (kamas > 0) {
+ fighter.apply(new Operation(kamas));
+ }
+ }
+
+ private static class Operation implements FighterOperation {
+ private final @Positive long kamas;
+
+ public Operation(@Positive long kamas) {
+ this.kamas = kamas;
+ }
+
+ @Override
+ public void onPlayer(PlayerFighter fighter) {
+ fighter.player().inventory().addKamas(kamas);
}
- fighter.apply(new FighterOperation() {
- @Override
- public void onPlayer(PlayerFighter fighter) {
- fighter.player().inventory().addKamas(kamas);
+ @Override
+ public void onGenericFighter(Fighter fighter) {
+ if (!fighter.invoked()) {
+ return;
}
- });
+
+ final Fighter invoker = fighter.invoker();
+
+ if (invoker == null) {
+ return;
+ }
+
+ invoker.apply(this);
+ }
}
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/PvmRewardsGenerator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/PvmRewardsGenerator.java
index 06235fe82..b0dec8437 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/PvmRewardsGenerator.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/PvmRewardsGenerator.java
@@ -26,6 +26,7 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.action.DropRewardAction;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.pvm.provider.DropRewardProvider;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import java.util.ArrayList;
import java.util.List;
@@ -73,4 +74,10 @@ public FightRewardsSheet generate(EndFightResults results) {
return new FightRewardsSheet(results, FightRewardsSheet.Type.NORMAL, rewards);
}
+
+ @Override
+ public boolean supports(Fighter fighter) {
+ // Keep invocations (e.g. living chest)
+ return !fighter.invoked() || fighter.characteristics().discernment() > 0;
+ }
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProvider.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProvider.java
index 454fc1544..dfb59e0d1 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProvider.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProvider.java
@@ -25,12 +25,18 @@
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation;
+import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import org.checkerframework.checker.index.qual.NonNegative;
+import java.util.Collection;
+import java.util.stream.IntStream;
+
/**
* Base formula for compute the Pvm experience
*/
public final class PvmXpProvider implements DropRewardProvider {
+ private static final double[] LVL_DEV_BONUS = { 3.5, 1.0, 1.1, 1.3, 2.2, 2.5, 2.8, 3.1 };
+
private final double rate;
public PvmXpProvider() {
@@ -47,7 +53,7 @@ public DropRewardProvider.Scope initialize(EndFightResults results) {
totalXp(results),
teamsLevelsRate(results),
teamLevelDeviationBonus(results),
- results.winners().stream().mapToInt(Fighter::level).sum()
+ levels(results.winners()).sum()
);
}
@@ -56,46 +62,22 @@ private long totalXp(EndFightResults results) {
}
private double teamLevelDeviationBonus(EndFightResults results) {
- final int level = results.winners().stream().mapToInt(Fighter::level).max().orElse(0) / 3;
+ final int level = levels(results.winners()).max().orElse(0) / 3;
int number = 0;
for (Fighter winner : results.winners()) {
- if (winner.level() > level) {
+ if (!winner.invoked() && winner.level() > level) {
++number;
}
}
- switch (number) {
- case 1:
- return 1.0;
-
- case 2:
- return 1.1;
-
- case 3:
- return 1.3;
-
- case 4:
- return 2.2;
-
- case 5:
- return 2.5;
-
- case 6:
- return 2.8;
-
- case 7:
- return 3.1;
-
- default:
- return 3.5;
- }
+ return number >= LVL_DEV_BONUS.length ? LVL_DEV_BONUS[0] : LVL_DEV_BONUS[number];
}
private double teamsLevelsRate(EndFightResults results) {
- final double winnersLevel = results.winners().stream().mapToInt(Fighter::level).sum();
- final double loosersLevel = results.loosers().stream().mapToInt(Fighter::level).sum();
+ final double winnersLevel = levels(results.winners()).sum();
+ final double loosersLevel = levels(results.loosers()).sum();
return Math.min(
1.3,
@@ -103,6 +85,10 @@ private double teamsLevelsRate(EndFightResults results) {
);
}
+ private IntStream levels(Collection fighters) {
+ return fighters.stream().filter(fighter -> !fighter.invoked()).mapToInt(Fighter::level);
+ }
+
private static class Scope implements DropRewardProvider.Scope {
private final long totalXp;
private final double teamsLevelsRate;
@@ -118,15 +104,23 @@ public Scope(long totalXp, double teamsLevelsRate, double teamLevelDeviationBonu
@Override
public void provide(DropReward reward) {
- final long winXp = (long) (
- totalXp
- * teamsLevelsRate
- * teamLevelDeviationBonus
- * (1 + ((double) reward.fighter().level() / winnersLevel))
- * (1 + (double) reward.fighter().characteristics().get(Characteristic.WISDOM) / 100)
- );
+ reward.fighter().apply(new FighterOperation() {
+ @Override
+ public void onPlayer(PlayerFighter fighter) {
+ final long winXp = computeXp(fighter.level(), fighter.characteristics().get(Characteristic.WISDOM));
+
+ reward.setXp(Math.max(winXp, 0));
+ }
+ });
+ }
- reward.setXp(Math.max(winXp, 0));
+ private long computeXp(int level, int wisdom) {
+ return (long) (totalXp
+ * teamsLevelsRate
+ * teamLevelDeviationBonus
+ * (1 + ((double) level / winnersLevel))
+ * (1 + (double) wisdom / 100)
+ );
}
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java
index 0a7f96222..bfd0410d2 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java
@@ -193,7 +193,7 @@ public final void setInvoker(Fighter invoker) {
}
@Override
- public @Nullable FighterData invoker() {
+ public @Nullable Fighter invoker() {
return invoker;
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactory.java
index 894de6f6c..8de330a34 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactory.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactory.java
@@ -25,8 +25,6 @@
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.game.fight.team.FightTeam;
import fr.quatrevieux.araknemu.game.listener.fight.SendFightJoined;
-import fr.quatrevieux.araknemu.game.listener.fight.fighter.ApplyEndFightReward;
-import fr.quatrevieux.araknemu.game.listener.fight.fighter.ApplyLeaveReward;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.LeaveOnDisconnect;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.SendFightLeaved;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.SendSpellBoosted;
@@ -61,11 +59,9 @@ public PlayerFighter create(GamePlayer player) {
final PlayerFighter fighter = new PlayerFighter(player);
fighter.dispatcher().add(new SendFightJoined(fighter));
- fighter.dispatcher().add(new ApplyEndFightReward(fighter));
- fighter.dispatcher().add(new StopFightSession(fighter));
+ fighter.dispatcher().register(new StopFightSession(fighter));
fighter.dispatcher().add(new SendFightLeaved(fighter));
fighter.dispatcher().add(new LeaveOnDisconnect(fighter));
- fighter.dispatcher().add(new ApplyLeaveReward(fighter));
fighter.dispatcher().add(new SendStats(fighter));
fighter.dispatcher().add(new SendSpellBoosted(fighter));
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java
index e6726e4b2..266868525 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java
@@ -58,6 +58,9 @@ public default boolean dead() {
return life().dead();
}
+ @Override
+ public @Nullable Fighter invoker();
+
/**
* Change the fighter cell
*
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterCharacteristics.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterCharacteristics.java
index 1f42c08d3..70a9e0aea 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterCharacteristics.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterCharacteristics.java
@@ -21,6 +21,7 @@
import fr.quatrevieux.araknemu.data.constant.Characteristic;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.Characteristics;
+import org.checkerframework.checker.index.qual.NonNegative;
/**
* Characteristics for a fighter
@@ -34,7 +35,7 @@ public interface FighterCharacteristics extends Characteristics {
/**
* Get the total discernment of the fighter
*/
- public int discernment();
+ public @NonNegative int discernment();
/**
* Change a buff characteristic
@@ -49,4 +50,15 @@ public interface FighterCharacteristics extends Characteristics {
* Those characteristics ignore fight buffs, and corresponds to characteristics of the fighter before start the fight
*/
public Characteristics initial();
+
+ /**
+ * Modify the fighter discernment
+ *
+ * In case of invocation, this will allow the creature to get items on end fight
+ * The discernment cannot be negative, so if the sum of the value and the current discernment is negative,
+ * the discernment will be set to 0
+ *
+ * @param value The value to add to the discernment. If negative, remove the value.
+ */
+ public void alterDiscernment(int value);
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighter.java
index cf783d41a..590b2fd93 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighter.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighter.java
@@ -26,7 +26,6 @@
import fr.quatrevieux.araknemu.game.fight.fighter.EmptySpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics;
-import fr.quatrevieux.araknemu.game.fight.fighter.FighterData;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation;
@@ -118,7 +117,7 @@ public boolean invoked() {
}
@Override
- public @NonNull FighterData invoker() {
+ public @NonNull Fighter invoker() {
return NullnessUtil.castNonNull(super.invoker());
}
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristics.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristics.java
index 9069cb57a..6fa8ac255 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristics.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristics.java
@@ -26,6 +26,7 @@
import fr.quatrevieux.araknemu.game.world.creature.characteristics.Characteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.DefaultCharacteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.MutableCharacteristics;
+import org.checkerframework.checker.index.qual.NonNegative;
/**
* Characteristics for a double
@@ -37,6 +38,7 @@ public final class DoubleFighterCharacteristics implements FighterCharacteristic
private final Characteristics base;
private final MutableCharacteristics buffs = new DefaultCharacteristics();
+ private @NonNegative int discernmentBoost = 0;
/**
* @param fighter The double fighter
@@ -53,8 +55,13 @@ public int initiative() {
}
@Override
- public int discernment() {
- return 0; // monster do not have discernment
+ public @NonNegative int discernment() {
+ return discernmentBoost;
+ }
+
+ @Override
+ public void alterDiscernment(int value) {
+ discernmentBoost = Math.max(discernmentBoost + value, 0);
}
@Override
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java
index 988a08341..b74ed3dae 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java
@@ -26,7 +26,6 @@
import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterSpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics;
-import fr.quatrevieux.araknemu.game.fight.fighter.FighterData;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighterSprite;
@@ -119,7 +118,7 @@ public FighterLife life() {
}
@Override
- public @NonNull FighterData invoker() {
+ public @NonNull Fighter invoker() {
return NullnessUtil.castNonNull(super.invoker());
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristics.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristics.java
index 02a985e0f..5d46e4867 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristics.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristics.java
@@ -28,6 +28,7 @@
import fr.quatrevieux.araknemu.game.world.creature.characteristics.Characteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.DefaultCharacteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.MutableCharacteristics;
+import org.checkerframework.checker.index.qual.NonNegative;
/**
* Characteristics for an invocation
@@ -38,6 +39,7 @@ public final class InvocationFighterCharacteristics implements FighterCharacteri
private final Fighter fighter;
private final MutableCharacteristics boost;
private final float rate;
+ private @NonNegative int discernmentBoost = 0;
public InvocationFighterCharacteristics(Monster monster, Fighter fighter, FighterData invoker) {
this.base = monster.characteristics();
@@ -52,8 +54,13 @@ public int initiative() {
}
@Override
- public int discernment() {
- return 0;
+ public @NonNegative int discernment() {
+ return discernmentBoost;
+ }
+
+ @Override
+ public void alterDiscernment(int value) {
+ discernmentBoost = Math.max(discernmentBoost + value, 0);
}
@Override
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java
index d0c543e60..d7e1ed1a2 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java
@@ -26,7 +26,6 @@
import fr.quatrevieux.araknemu.game.fight.fighter.EmptySpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics;
-import fr.quatrevieux.araknemu.game.fight.fighter.FighterData;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighterSprite;
@@ -117,7 +116,7 @@ public FighterLife life() {
}
@Override
- public @NonNull FighterData invoker() {
+ public @NonNull Fighter invoker() {
return NullnessUtil.castNonNull(super.invoker());
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristics.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristics.java
index 7b40f8858..6e44e78fb 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristics.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristics.java
@@ -27,6 +27,7 @@
import fr.quatrevieux.araknemu.game.world.creature.characteristics.Characteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.DefaultCharacteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.MutableCharacteristics;
+import org.checkerframework.checker.index.qual.NonNegative;
/**
* Monster fighter characteristics
@@ -48,10 +49,15 @@ public int initiative() {
}
@Override
- public int discernment() {
+ public @NonNegative int discernment() {
return 0; // monster do not have discernment
}
+ @Override
+ public void alterDiscernment(int value) {
+ // No-op: monster can't have discernment
+ }
+
@Override
public int get(Characteristic characteristic) {
return monster.characteristics().get(characteristic) + buffs.get(characteristic);
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristics.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristics.java
index 05e725160..8d4287533 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristics.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristics.java
@@ -26,6 +26,7 @@
import fr.quatrevieux.araknemu.game.world.creature.characteristics.Characteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.DefaultCharacteristics;
import fr.quatrevieux.araknemu.game.world.creature.characteristics.MutableCharacteristics;
+import org.checkerframework.checker.index.qual.NonNegative;
/**
* Player fighter characteristics
@@ -35,6 +36,7 @@ public final class PlayerFighterCharacteristics implements FighterCharacteristic
private final PlayerFighter fighter;
private final MutableCharacteristics buffs = new DefaultCharacteristics();
+ private int discernmentBoost = 0;
public PlayerFighterCharacteristics(CharacterCharacteristics baseCharacteristics, PlayerFighter fighter) {
this.baseCharacteristics = baseCharacteristics;
@@ -77,9 +79,13 @@ public int boostPoints() {
}
@Override
- public int discernment() {
- // @todo Add buff discernment
- return baseCharacteristics.discernment();
+ public @NonNegative int discernment() {
+ return Math.max(baseCharacteristics.discernment() + discernmentBoost, 0);
+ }
+
+ @Override
+ public void alterDiscernment(int value) {
+ discernmentBoost += value;
}
@Override
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java
index c78fd61fd..db703947f 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java
@@ -64,6 +64,7 @@
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.heal.HealHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.heal.HealOnAttackHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.heal.HealOnDamageHandler;
+import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc.AddDiscernmentHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc.ChangeAppearanceHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc.DispelHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc.InvisibilityHandler;
@@ -254,6 +255,7 @@ public void effects(EffectsHandler handler) {
handler.register(290, new BoostSpellHandler(SpellsBoosts.Modifier.LAUNCH_PER_TURN));
handler.register(293, new BoostSpellHandler(SpellsBoosts.Modifier.BASE_DAMAGE));
+ handler.register(176, new AddDiscernmentHandler());
handler.register(788, new AddCharacteristicOnDamageHandler(fight)
.register(108, AlterVitalityHook.add(fight))
.register(118, Characteristic.STRENGTH)
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java
index 71ded08c2..09cebc097 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java
@@ -151,6 +151,7 @@ public synchronized void leave(Fighter fighter) {
)
);
+ rewardsSheet.apply();
fighter.dispatch(new FightLeaved(rewardsSheet.rewards().get(0)));
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/FinishState.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/FinishState.java
index a5830e65c..6d71734b8 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/FinishState.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/FinishState.java
@@ -22,6 +22,7 @@
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.ending.EndFightResults;
import fr.quatrevieux.araknemu.game.fight.ending.reward.FightRewardsSheet;
+import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardsGenerator;
import fr.quatrevieux.araknemu.game.fight.event.FightFinished;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.team.FightTeam;
@@ -29,6 +30,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* The fight is terminated
@@ -38,6 +40,7 @@ public final class FinishState implements FightState {
public void start(Fight fight) {
final FightRewardsSheet rewardsSheet = fight.type().rewards().generate(results(fight));
+ rewardsSheet.apply();
rewardsSheet.rewards().forEach(reward -> reward.fighter().dispatch(new FightFinished(reward)));
fight.send(new FightEnd(rewardsSheet));
@@ -54,14 +57,23 @@ public int id() {
* Compute the end fight results
*/
private EndFightResults results(Fight fight) {
+ final RewardsGenerator rewards = fight.type().rewards();
final List winners = new ArrayList<>();
final List loosers = new ArrayList<>();
+ final Optional winnerTeam = fight.teams().stream()
+ .filter(FightTeam::alive)
+ .findFirst()
+ ;
- for (FightTeam team : fight.teams()) {
- if (team.alive()) {
- winners.addAll(team.fighters());
+ for (Fighter fighter : fight.fighters()) {
+ if (!rewards.supports(fighter)) {
+ continue;
+ }
+
+ if (winnerTeam.filter(team -> team.equals(fighter.team())).isPresent()) {
+ winners.add(fighter);
} else {
- loosers.addAll(team.fighters());
+ loosers.add(fighter);
}
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java
index 40acedc76..e97b50dac 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java
@@ -283,6 +283,7 @@ private void punishDeserter(Fighter fighter) {
)
);
+ rewardsSheet.apply();
fighter.dispatch(new FightLeaved(rewardsSheet.rewards().get(0)));
}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightReward.java b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightReward.java
deleted file mode 100644
index 47e1a2e40..000000000
--- a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightReward.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (c) 2017-2019 Vincent Quatrevieux
- */
-
-package fr.quatrevieux.araknemu.game.listener.fight.fighter;
-
-import fr.quatrevieux.araknemu.core.event.Listener;
-import fr.quatrevieux.araknemu.game.fight.event.FightFinished;
-import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
-
-/**
- * Apply reward when fight is terminated
- */
-public final class ApplyEndFightReward implements Listener {
- private final PlayerFighter fighter;
-
- public ApplyEndFightReward(PlayerFighter fighter) {
- this.fighter = fighter;
- }
-
- @Override
- public void on(FightFinished event) {
- fighter.player().stop(fighter);
- event.reward().apply();
- fighter.player().save();
- }
-
- @Override
- public Class event() {
- return FightFinished.class;
- }
-}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveReward.java b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveReward.java
deleted file mode 100644
index a758520bf..000000000
--- a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveReward.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (c) 2017-2019 Vincent Quatrevieux
- */
-
-package fr.quatrevieux.araknemu.game.listener.fight.fighter;
-
-import fr.quatrevieux.araknemu.core.event.Listener;
-import fr.quatrevieux.araknemu.game.fight.event.FightLeaved;
-import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
-
-/**
- * Apply reward when fighter leave a fight
- */
-public final class ApplyLeaveReward implements Listener {
- private final PlayerFighter fighter;
-
- public ApplyLeaveReward(PlayerFighter fighter) {
- this.fighter = fighter;
- }
-
- @Override
- public void on(FightLeaved event) {
- event.reward().ifPresent(reward -> {
- reward.apply();
- fighter.player().save();
- });
- }
-
- @Override
- public Class event() {
- return FightLeaved.class;
- }
-}
diff --git a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSession.java b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSession.java
index bf00ea40c..fe4f83e82 100644
--- a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSession.java
+++ b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSession.java
@@ -19,27 +19,55 @@
package fr.quatrevieux.araknemu.game.listener.fight.fighter;
+import fr.quatrevieux.araknemu.core.event.EventsSubscriber;
import fr.quatrevieux.araknemu.core.event.Listener;
+import fr.quatrevieux.araknemu.game.fight.event.FightFinished;
import fr.quatrevieux.araknemu.game.fight.event.FightLeaved;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
/**
- * Stop the fight session on leave fight
+ * Stop the fight session on leave or fight end, and save the player
*/
-public final class StopFightSession implements Listener {
+public final class StopFightSession implements EventsSubscriber {
private final PlayerFighter fighter;
+ private final Listener[] listeners;
public StopFightSession(PlayerFighter fighter) {
this.fighter = fighter;
+ this.listeners = new Listener[] { new OnLeave(), new OnFinish() };
}
- @Override
- public void on(FightLeaved event) {
+ private void apply() {
fighter.player().stop(fighter);
+ fighter.player().save();
}
@Override
- public Class event() {
- return FightLeaved.class;
+ public Listener[] listeners() {
+ return listeners;
+ }
+
+ public final class OnLeave implements Listener {
+ @Override
+ public void on(FightLeaved event) {
+ apply();
+ }
+
+ @Override
+ public Class event() {
+ return FightLeaved.class;
+ }
+ }
+
+ public final class OnFinish implements Listener {
+ @Override
+ public void on(FightFinished event) {
+ apply();
+ }
+
+ @Override
+ public Class event() {
+ return FightFinished.class;
+ }
}
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/GameBaseCase.java b/src/test/java/fr/quatrevieux/araknemu/game/GameBaseCase.java
index 2a093c118..95c4b8da9 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/GameBaseCase.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/GameBaseCase.java
@@ -138,6 +138,7 @@
import java.time.Instant;
import java.util.Arrays;
import java.util.EnumSet;
+import java.util.regex.Pattern;
public class GameBaseCase extends DatabaseTestCase {
static public class SendingRequestStack {
@@ -155,6 +156,16 @@ public void assertLast(String packet) {
Assertions.assertEquals(packet, channel.getMessages().peek().toString());
}
+ public void assertLastMatches(String regex) {
+ final boolean matches = Pattern.matches(regex, channel.getMessages().peek().toString());
+
+ if (matches) {
+ return;
+ }
+
+ Assertions.fail("Packet '" + channel.getMessages().peek() + "' does not match regex '" + regex + "'");
+ }
+
public void assertCount(int count) {
Assertions.assertEquals(count, channel.getMessages().size());
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java b/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java
index bee73780c..9d2b7e93e 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java
@@ -567,6 +567,7 @@ public GameDataSet pushFunctionalSpells() throws SQLException, ContainerExceptio
"(391, 'Maîtrise de l Epée', 4800, '10,1,1', '165,6,10,,4,0|165,6,15,,4,0|6|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|0|false', '165,6,15,,4,0|165,6,20,,4,0|6|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|0|false', '165,6,20,,4,0|165,6,25,,4,0|5|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|0|false', '165,6,25,,4,0|165,6,30,,4,0|4|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|0|false', '165,6,30,,4,0|165,6,35,,4,0|3|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|0|false', '165,6,35,,4,0|165,6,40,,4,0|2|0|0|50|100|false|false|false|false|3|0|0|6|PaPa||8;18;19;3;1;41|100|false', '')",
"(447, 'Furie', 1054, '11,1,1', '96,6,10,,0,0,1d5+5;112,4,,,3,0,0d0+4;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,4,,,4,0,0d0+4;89,1,,,1,0,0d0+1|5|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|70|false', '96,7,11,,0,0,1d5+6;112,5,,,3,0,0d0+5;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,5,,,4,0,0d0+5;89,1,,,1,0,0d0+1|5|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|70|false', '96,8,12,,0,0,1d5+7;112,6,,,3,0,0d0+6;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,6,,,4,0,0d0+6;89,1,,,1,0,0d0+1|5|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|70|false', '96,9,13,,0,0,1d5+8;112,7,,,3,0,0d0+7;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,7,,,4,0,0d0+7;89,1,,,1,0,0d0+1|5|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|70|false', '96,9,13,,0,0,1d5+8;112,8,,,3,0,0d0+8;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,8,,,4,0,0d0+8;89,1,,,1,0,0d0+1|4|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|70|false', '96,9,13,,0,0,1d5+8;112,8,,,4,0,0d0+8;89,1,,,1,0,0d0+1|96,11,15,,0,0,1d5+10;112,8,,,4,0,0d0+8;89,1,,,1,0,0d0+1|3|1|3|50|100|false|true|false|false|0|0|0|0|XbPaPaXbPaPa||18;19;3;1;41|170|false', '0;32;32')",
"(319, 'Oniside', 0, '10,1,1', '98,21,70,,0,0,1d50+20;8,,,,0,0|98,101,150,,0,0,1d50+100;8,,,,0,0|7|1|6|20|0|false|true|false|true|0|0|0|0|PaPaPaPa||7;18;19;3;1;41|0|false', '98,26,75,,0,0,1d50+25;8,,,,0,0|98,101,150,,0,0,1d50+100;8,,,,0,0|7|1|6|20|0|false|true|false|true|0|0|0|0|PaPaPaPa||7;18;19;3;1;41|0|false', '98,31,80,,0,0,1d50+30;8,,,,0,0|98,101,150,,0,0,1d50+100;8,,,,0,0|7|1|6|20|0|false|true|false|true|0|0|0|0|PaPaPaPa||7;18;19;3;1;41|0|false', '98,41,90,,0,0,1d50+40;8,,,,0,0|98,101,150,,0,0,1d50+100;8,,,,0,0|7|1|6|20|0|false|true|false|true|0|0|0|0|PaPaPaPa||7;18;19;3;1;41|0|false', '98,51,100,,0,0,1d50+50;8,,,,0,0|98,101,150,,0,0,1d50+100;8,,,,0,0|7|1|6|20|0|false|true|false|true|0|0|0|0|PaPaPaPa||7;18;19;3;1;41|0|false', '', '')",
+ "(495, 'Prospection', 0, '0,0,1', '176,1,5,,3,0,1d5+0||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '176,6,10,,3,0,1d5+5||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '176,6,15,,3,0,1d10+5||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '176,11,20,,3,0,1d10+10||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '176,11,20,,5,0,1d10+10||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '176,31,50,,5,0,1d20+30||5|0|0|0|0|false|true|false|false|0|1|0|0|Pa||18;19;3;1;41|0|true', '')",
}, ",") + ";"
);
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java
index 2f03bdf21..a07aba1b7 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java
@@ -2049,6 +2049,14 @@ void killTargetThenSwitch() {
assertEquals(136, player.fighter().cell().id());
}
+ @Test
+ void addDiscernment() {
+ castNormal(495, fighter1.cell()); // Prospection
+
+ assertBetween(111, 120, fighter1.characteristics().discernment());
+ assertEquals(6, fighter1.buffs().stream().filter(b -> b.effect().effect() == 176).findFirst().get().remainingTurns());
+ }
+
private List configureFight(Consumer configurator) {
fight.cancel(true);
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandlerTest.java
new file mode 100644
index 000000000..c06040384
--- /dev/null
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandlerTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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 .
+ *
+ * Copyright (c) 2017-2019 Vincent Quatrevieux
+ */
+
+package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.misc;
+
+import fr.quatrevieux.araknemu.data.constant.Characteristic;
+import fr.quatrevieux.araknemu.data.value.EffectArea;
+import fr.quatrevieux.araknemu.game.fight.Fight;
+import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
+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.BuffHook;
+import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
+import fr.quatrevieux.araknemu.game.spell.Spell;
+import fr.quatrevieux.araknemu.game.spell.SpellConstraints;
+import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;
+import fr.quatrevieux.araknemu.game.spell.effect.area.CellArea;
+import fr.quatrevieux.araknemu.game.spell.effect.area.CircleArea;
+import fr.quatrevieux.araknemu.game.spell.effect.target.SpellEffectTarget;
+import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class AddDiscernmentHandlerTest extends FightBaseCase {
+ private Fight fight;
+ private PlayerFighter caster;
+ private PlayerFighter target;
+ private AddDiscernmentHandler handler;
+
+ @Override
+ @BeforeEach
+ public void setUp() throws Exception {
+ super.setUp();
+
+ fight = createFight();
+ fight.nextState();
+ fight.turnList().start();
+
+ caster = player.fighter();
+ target = other.fighter();
+
+ target.move(fight.map().get(123));
+
+ handler = new AddDiscernmentHandler();
+
+ requestStack.clear();
+ }
+
+ @Test
+ void handle() {
+ SpellEffect effect = Mockito.mock(SpellEffect.class);
+ Spell spell = Mockito.mock(Spell.class);
+ SpellConstraints constraints = Mockito.mock(SpellConstraints.class);
+
+ Mockito.when(effect.area()).thenReturn(new CellArea());
+ Mockito.when(effect.effect()).thenReturn(123);
+ Mockito.when(effect.min()).thenReturn(50);
+ Mockito.when(effect.max()).thenReturn(60);
+ Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT);
+ Mockito.when(spell.constraints()).thenReturn(constraints);
+ Mockito.when(constraints.freeCell()).thenReturn(false);
+
+ FightCastScope scope = makeCastScope(caster, spell, effect, caster.cell());
+ assertThrows(UnsupportedOperationException.class, () -> handler.handle(scope, scope.effects().get(0)));
+ }
+
+ @Test
+ void buff() {
+ SpellEffect effect = Mockito.mock(SpellEffect.class);
+ Spell spell = Mockito.mock(Spell.class);
+ SpellConstraints constraints = Mockito.mock(SpellConstraints.class);
+
+ Mockito.when(effect.effect()).thenReturn(123);
+ Mockito.when(effect.min()).thenReturn(50);
+ Mockito.when(effect.max()).thenReturn(60);
+ Mockito.when(effect.duration()).thenReturn(5);
+ Mockito.when(effect.area()).thenReturn(new CircleArea(new EffectArea(EffectArea.Type.CIRCLE, 10)));
+ Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT);
+ Mockito.when(spell.constraints()).thenReturn(constraints);
+ Mockito.when(constraints.freeCell()).thenReturn(false);
+
+ FightCastScope scope = makeCastScope(caster, spell, effect, caster.cell());
+ handler.buff(scope, scope.effects().get(0));
+
+ Optional buff1 = caster.buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst();
+ Optional buff2 = target.buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst();
+
+ assertTrue(buff1.isPresent());
+ assertTrue(buff2.isPresent());
+
+ assertBetween(50, 60, buff1.get().effect().min());
+ assertEquals(buff1.get().effect().min(), buff2.get().effect().min());
+ assertTrue(buff1.get().canBeDispelled());
+ assertTrue(buff2.get().canBeDispelled());
+ }
+
+ @Test
+ void buffWithOneTargetMaximized() {
+ target.buffs().add(new Buff(Mockito.mock(SpellEffect.class), Mockito.mock(Spell.class), target, target, new BuffHook() {
+ @Override
+ public void onEffectValueTarget(Buff buff, EffectValue value) {
+ value.maximize();
+ }
+ }));
+
+ SpellEffect effect = Mockito.mock(SpellEffect.class);
+ Spell spell = Mockito.mock(Spell.class);
+ SpellConstraints constraints = Mockito.mock(SpellConstraints.class);
+
+ Mockito.when(effect.effect()).thenReturn(123);
+ Mockito.when(effect.min()).thenReturn(0);
+ Mockito.when(effect.max()).thenReturn(10000);
+ Mockito.when(effect.duration()).thenReturn(5);
+ Mockito.when(effect.area()).thenReturn(new CircleArea(new EffectArea(EffectArea.Type.CIRCLE, 10)));
+ Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT);
+ Mockito.when(spell.constraints()).thenReturn(constraints);
+ Mockito.when(constraints.freeCell()).thenReturn(false);
+
+ FightCastScope scope = makeCastScope(target, spell, effect, caster.cell());
+ handler.buff(scope, scope.effects().get(0));
+
+ Optional buff1 = caster.buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst();
+ Optional buff2 = target.buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst();
+
+ assertTrue(buff1.isPresent());
+ assertTrue(buff2.isPresent());
+
+ assertBetween(0, 9999, buff1.get().effect().min());
+ assertEquals(10000, buff2.get().effect().min());
+ }
+
+ @Test
+ void onBuffStartedAndTerminated() {
+ SpellEffect effect = Mockito.mock(SpellEffect.class);
+
+ Mockito.when(effect.effect()).thenReturn(123);
+ Mockito.when(effect.min()).thenReturn(50);
+ Mockito.when(effect.duration()).thenReturn(5);
+
+ Buff buff = new Buff(effect, Mockito.mock(Spell.class), caster, target, handler);
+
+ handler.onBuffStarted(buff);
+ assertEquals(150, target.characteristics().discernment());
+
+ handler.onBuffTerminated(buff);
+ assertEquals(100, target.characteristics().discernment());
+ }
+}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddItemsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddItemsTest.java
index 308fb5212..a1cc8791d 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddItemsTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddItemsTest.java
@@ -23,6 +23,8 @@
import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.action.AddItems;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.game.item.ItemService;
@@ -111,4 +113,19 @@ void applyOnMonster() {
action.apply(reward, fighter);
}
+
+ @Test
+ void applyOnInvocationShouldForwardToInvoker() {
+ Fighter invoc = new DoubleFighter(-10, fighter);
+
+ DropReward reward = new DropReward(RewardType.WINNER, invoc, Collections.emptyList());
+ reward.addItem(39);
+ reward.addItem(40);
+ reward.addItem(2425);
+
+ action.apply(reward, invoc);
+ assertEquals(39, player.inventory().get(1).item().template().id());
+ assertEquals(40, player.inventory().get(2).item().template().id());
+ assertEquals(2425, player.inventory().get(3).item().template().id());
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddKamasTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddKamasTest.java
index 7413e8143..c60caa75a 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddKamasTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/AddKamasTest.java
@@ -23,6 +23,7 @@
import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.action.AddKamas;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import org.junit.jupiter.api.BeforeEach;
@@ -81,4 +82,17 @@ void applyOnMonster() {
action.apply(reward, fighter);
}
+
+ @Test
+ void applyOnInvocationShouldForwardToInvoker() {
+ DoubleFighter fighter = new DoubleFighter(-10, player.fighter());
+
+ DropReward reward = new DropReward(RewardType.WINNER, fighter, Collections.emptyList());
+ reward.setKamas(1000);
+
+ long lastKamas = player.properties().kamas();
+
+ action.apply(reward, fighter);
+ assertEquals(1000, player.properties().kamas() - lastKamas);
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmItemDropProviderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmItemDropProviderTest.java
index 4b70fd564..a3daed5e8 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmItemDropProviderTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmItemDropProviderTest.java
@@ -26,6 +26,7 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.player.characteristic.SpecialEffects;
import org.junit.jupiter.api.BeforeEach;
@@ -201,6 +202,43 @@ void withMultipleFighters() {
assertTrue(items.containsKey(14));
}
+ @Test
+ void withInvocation() {
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+ invoc.characteristics().alterDiscernment(50);
+
+ monsterFighters.get(0).reward().items().clear();
+
+ monsterFighters.get(0).reward().items().add(new MonsterRewardItem(0, 12, 2, 100, 100));
+ monsterFighters.get(0).reward().items().add(new MonsterRewardItem(0, 13, 1, 100, 100));
+ monsterFighters.get(0).reward().items().add(new MonsterRewardItem(0, 14, 4, 100, 100));
+ monsterFighters.get(0).reward().items().add(new MonsterRewardItem(0, 15, 1, 100, 100));
+
+ EndFightResults results = new EndFightResults(
+ fight,
+ Arrays.asList(player.fighter(), invoc),
+ Collections.singletonList(monsterFighters.get(0))
+ );
+
+ DropRewardProvider.Scope scope = formula.initialize(results);
+
+ DropReward reward = new DropReward(RewardType.WINNER, player.fighter(), Collections.emptyList());
+ scope.provide(reward);
+ Map items = reward.items();
+
+ assertEquals(2, items.size());
+ assertTrue(items.containsKey(12));
+ assertTrue(items.containsKey(15));
+
+ reward = new DropReward(RewardType.WINNER, invoc, Collections.emptyList());
+ scope.provide(reward);
+ items = reward.items();
+
+ assertEquals(2, items.size());
+ assertTrue(items.containsKey(12));
+ assertTrue(items.containsKey(13));
+ }
+
@Test
void withMultipleMonsters() {
monsterFighters.get(0).reward().items().clear();
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmKamasProviderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmKamasProviderTest.java
index 1f9220a6e..8c3c30cb4 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmKamasProviderTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmKamasProviderTest.java
@@ -25,10 +25,12 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -92,6 +94,32 @@ void withMultipleMonsters() {
assertNotEquals(reward.kamas(), otherReward.kamas());
}
+ @Test
+ void withInvocation() {
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+
+ EndFightResults results = new EndFightResults(
+ fight,
+ Arrays.asList(player.fighter(), invoc),
+ monsterFighters
+ );
+
+ DropReward reward = new DropReward(RewardType.WINNER, player.fighter(), Collections.emptyList());
+ formula.initialize(results).provide(reward);
+
+ assertBetween(100, 140, reward.kamas());
+
+ DropReward otherReward = new DropReward(RewardType.WINNER, player.fighter(), Collections.emptyList());
+ formula.initialize(results).provide(otherReward);
+
+ assertNotEquals(reward.kamas(), otherReward.kamas());
+
+ DropReward invocReward = new DropReward(RewardType.WINNER, invoc, Collections.emptyList());
+ formula.initialize(results).provide(invocReward);
+
+ assertBetween(100, 140, invocReward.kamas());
+ }
+
@Test
void withoutMonsters() {
EndFightResults results = new EndFightResults(
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProviderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProviderTest.java
index fe0c4120b..27e81cd3e 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProviderTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/drop/pvm/provider/PvmXpProviderTest.java
@@ -26,10 +26,12 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -67,6 +69,26 @@ void withOneMonster() {
assertEquals(25, reward.xp());
}
+ @Test
+ void shouldIgnoreInvocations() {
+ final DoubleFighter invoc = new DoubleFighter(-10, player.fighter());
+
+ EndFightResults results = new EndFightResults(
+ fight,
+ Arrays.asList(player.fighter(), invoc),
+ Arrays.asList(monsterFighters.get(0), new DoubleFighter(-11, monsterFighters.get(0)))
+ );
+
+ DropReward reward = new DropReward(RewardType.WINNER, player.fighter(), Collections.emptyList());
+ formula.initialize(results).provide(reward);
+ assertEquals(25, reward.xp());
+
+
+ DropReward invocReward = new DropReward(RewardType.WINNER, invoc, Collections.emptyList());
+ formula.initialize(results).provide(invocReward);
+ assertEquals(0, invocReward.xp());
+ }
+
@Test
void withoutMonster() {
EndFightResults results = new EndFightResults(
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/ChallengeRewardsGeneratorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/ChallengeRewardsGeneratorTest.java
index 13a07e477..f28c0cfdc 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/ChallengeRewardsGeneratorTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/ChallengeRewardsGeneratorTest.java
@@ -27,15 +27,22 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.ChallengeRewardsGenerator;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
+import fr.quatrevieux.araknemu.game.monster.MonsterService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
class ChallengeRewardsGeneratorTest extends FightBaseCase {
private Fight fight;
@@ -78,4 +85,24 @@ void generate() {
assertEquals(0, DropReward.class.cast(rewards.get(1)).mountXp());
assertEquals(0, DropReward.class.cast(rewards.get(1)).kamas());
}
+
+ @Test
+ void supports() throws SQLException {
+ dataSet
+ .pushMonsterTemplates()
+ .pushMonsterSpells()
+ ;
+
+ assertTrue(generator.supports(player.fighter()));
+ assertTrue(generator.supports(new MonsterFighter(
+ -10, container.get(MonsterService.class).load(36).get(1),
+ player.fighter().team()
+ )));
+ assertFalse(generator.supports(new DoubleFighter(-10, player.fighter())));
+
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+ invoc.characteristics().alterDiscernment(10);
+
+ assertFalse(generator.supports(invoc));
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java
index 1a68b28fb..a1d65b036 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java
@@ -29,17 +29,26 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.pvm.provider.PvmItemDropProvider;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.pvm.provider.PvmKamasProvider;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.pvm.provider.PvmXpProvider;
+import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
+import fr.quatrevieux.araknemu.game.monster.MonsterService;
import fr.quatrevieux.araknemu.game.player.characteristic.SpecialEffects;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
class PvmRewardsGeneratorTest extends FightBaseCase {
private PvmRewardsGenerator generator;
@@ -90,6 +99,53 @@ void generate() throws Exception {
assertEquals(0, sheet.rewards().get(1).items().size());
}
+ @Test
+ void generateWithInvocation() throws Exception {
+ Fight fight = createPvmFight();
+ fight.nextState();
+
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+ fight.fighters().join(invoc, fight.map().get(142));
+ invoc.characteristics().alterDiscernment(10);
+
+ EndFightResults results = new EndFightResults(
+ fight,
+ Arrays.asList(player.fighter(), invoc),
+ new ArrayList<>(fight.team(1).fighters())
+ );
+
+ FightRewardsSheet sheet = generator.generate(results);
+
+ assertSame(results, sheet.results());
+ assertCount(fight.fighters().all().size(), sheet.rewards());
+ assertEquals(FightRewardsSheet.Type.NORMAL, sheet.type());
+
+ assertEquals(RewardType.WINNER, sheet.rewards().get(0).type());
+ assertEquals(player.fighter(), sheet.rewards().get(0).fighter());
+ assertEquals(241, sheet.rewards().get(0).xp());
+ assertBetween(100, 140, sheet.rewards().get(0).kamas());
+ assertEquals(1, sheet.rewards().get(0).items().size());
+
+ assertEquals(RewardType.WINNER, sheet.rewards().get(1).type());
+ assertEquals(invoc, sheet.rewards().get(1).fighter());
+ assertEquals(0, sheet.rewards().get(1).xp());
+ assertBetween(100, 140, sheet.rewards().get(1).kamas());
+ assertEquals(1, sheet.rewards().get(1).items().size());
+
+ assertEquals(RewardType.LOOSER, sheet.rewards().get(2).type());
+ assertEquals(0, sheet.rewards().get(2).xp());
+ assertEquals(0, sheet.rewards().get(2).kamas());
+ assertEquals(0, sheet.rewards().get(2).items().size());
+
+ Map items = new HashMap<>();
+ items.putAll(sheet.rewards().get(0).items());
+ items.putAll(sheet.rewards().get(1).items());
+
+ assertEquals(2, items.size());
+ assertEquals(1, (int) items.get(8213));
+ assertEquals(1, (int) items.get(8219));
+ }
+
@Test
void generateShouldSortWinnersByDiscernment() throws Exception {
player.properties().characteristics().specials().add(SpecialEffects.Type.DISCERNMENT, 100);
@@ -154,4 +210,48 @@ void generateFunctional() throws Exception {
assertEquals(8219, player.inventory().get(2).item().template().id());
assertEquals(1, player.inventory().get(2).quantity());
}
+
+ @Test
+ void generateFunctionalWithInvocation() throws Exception {
+ long lastXp = player.properties().experience().current();
+ long lastKamas = player.inventory().kamas();
+
+ dataSet.pushItemSets();
+
+ Fight fight = createPvmFight();
+ fight.nextState();
+
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+ fight.fighters().join(invoc, fight.map().get(142));
+ invoc.characteristics().alterDiscernment(10);
+
+ fight.team(1).fighters().forEach(fighter -> fighter.life().kill(player.fighter()));
+ requestStack.clear();
+ fight.nextState();
+
+ assertBetween(200, 280, player.inventory().kamas() - lastKamas);
+ assertEquals(241, player.properties().experience().current() - lastXp);
+ assertEquals(8213, player.inventory().get(1).item().template().id());
+ assertEquals(1, player.inventory().get(1).quantity());
+ assertEquals(8219, player.inventory().get(2).item().template().id());
+ assertEquals(1, player.inventory().get(2).quantity());
+ }
+
+ @Test
+ void supports() throws Exception {
+ Fight fight = createPvmFight();
+ fight.nextState();
+
+ assertTrue(generator.supports(player.fighter()));
+ assertTrue(generator.supports(new MonsterFighter(
+ -10, container.get(MonsterService.class).load(36).get(1),
+ player.fighter().team()
+ )));
+ assertFalse(generator.supports(new DoubleFighter(-10, player.fighter())));
+
+ Fighter invoc = new DoubleFighter(-10, player.fighter());
+ invoc.characteristics().alterDiscernment(10);
+
+ assertTrue(generator.supports(invoc));
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactoryTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactoryTest.java
index 450a46ee3..ac7bd6633 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactoryTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/DefaultFighterFactoryTest.java
@@ -28,8 +28,6 @@
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.game.listener.fight.SendFightJoined;
-import fr.quatrevieux.araknemu.game.listener.fight.fighter.ApplyEndFightReward;
-import fr.quatrevieux.araknemu.game.listener.fight.fighter.ApplyLeaveReward;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.LeaveOnDisconnect;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.SendFightLeaved;
import fr.quatrevieux.araknemu.game.listener.fight.fighter.SendSpellBoosted;
@@ -76,11 +74,10 @@ void createPlayerFighter() throws SQLException, ContainerException {
assertSame(player, fighter.player());
assertTrue(fighter.dispatcher().has(SendFightJoined.class));
- assertTrue(fighter.dispatcher().has(ApplyEndFightReward.class));
- assertTrue(fighter.dispatcher().has(StopFightSession.class));
+ assertTrue(fighter.dispatcher().has(StopFightSession.OnLeave.class));
+ assertTrue(fighter.dispatcher().has(StopFightSession.OnFinish.class));
assertTrue(fighter.dispatcher().has(SendFightLeaved.class));
assertTrue(fighter.dispatcher().has(LeaveOnDisconnect.class));
- assertTrue(fighter.dispatcher().has(ApplyLeaveReward.class));
assertTrue(fighter.dispatcher().has(SendStats.class));
assertTrue(fighter.dispatcher().has(SendSpellBoosted.class));
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristicsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristicsTest.java
index 599ad4007..7c43a0783 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristicsTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/DoubleFighterCharacteristicsTest.java
@@ -56,6 +56,15 @@ void initiative() {
@Test
void discernment() {
assertEquals(0, characteristics.discernment());
+
+ characteristics.alterDiscernment(50);
+ assertEquals(50, characteristics.discernment());
+
+ characteristics.alterDiscernment(-20);
+ assertEquals(30, characteristics.discernment());
+
+ characteristics.alterDiscernment(-50);
+ assertEquals(0, characteristics.discernment());
}
@Test
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristicsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristicsTest.java
index 02f81f80b..1e69c5ff1 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristicsTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighterCharacteristicsTest.java
@@ -109,4 +109,26 @@ void alter() {
assertEquals(140, characteristics.get(Characteristic.STRENGTH));
assertEquals(70, characteristics.get(Characteristic.INTELLIGENCE));
}
+
+ @Test
+ void discernment() {
+ Fighter invoc = Mockito.mock(Fighter.class);
+
+ InvocationFighterCharacteristics characteristics = new InvocationFighterCharacteristics(
+ container.get(MonsterService.class).load(36).get(1),
+ invoc,
+ player.fighter()
+ );
+
+ assertEquals(0, characteristics.discernment());
+
+ characteristics.alterDiscernment(50);
+ assertEquals(50, characteristics.discernment());
+
+ characteristics.alterDiscernment(-20);
+ assertEquals(30, characteristics.discernment());
+
+ characteristics.alterDiscernment(-50);
+ assertEquals(0, characteristics.discernment());
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristicsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristicsTest.java
index 49f07fa7b..e74b9c474 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristicsTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighterCharacteristicsTest.java
@@ -101,6 +101,12 @@ void initiative() {
@Test
void discernment() {
assertEquals(0, characteristics.discernment());
+
+ characteristics.alterDiscernment(10);
+ assertEquals(0, characteristics.discernment());
+
+ characteristics.alterDiscernment(-10);
+ assertEquals(0, characteristics.discernment());
}
@Test
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristicsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristicsTest.java
index a308d2145..cef882715 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristicsTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighterCharacteristicsTest.java
@@ -92,6 +92,23 @@ void alter() {
assertEquals(-10, ref.get().value());
}
+ @Test
+ void discernment() {
+ assertEquals(100, fighterCharacteristics.discernment());
+
+ fighterCharacteristics.alterDiscernment(50);
+ assertEquals(150, fighterCharacteristics.discernment());
+
+ fighterCharacteristics.alterDiscernment(-50);
+ assertEquals(100, fighterCharacteristics.discernment());
+
+ fighterCharacteristics.alterDiscernment(-20);
+ assertEquals(80, fighterCharacteristics.discernment());
+
+ fighterCharacteristics.alterDiscernment(-100);
+ assertEquals(0, fighterCharacteristics.discernment());
+ }
+
@Test
void initial() {
assertSame(baseCharacteristics, fighterCharacteristics.initial());
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java
index c22fd6d16..f8fcc7936 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java
@@ -23,11 +23,13 @@
import fr.quatrevieux.araknemu.game.GameBaseCase;
import fr.quatrevieux.araknemu.game.exploration.map.ExplorationMapService;
import fr.quatrevieux.araknemu.game.fight.Fight;
+import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
import fr.quatrevieux.araknemu.game.fight.FightService;
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.event.FightLeaved;
import fr.quatrevieux.araknemu.game.fight.exception.JoinFightException;
+import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.game.fight.map.FightMap;
import fr.quatrevieux.araknemu.game.fight.team.SimpleTeam;
@@ -78,7 +80,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-class ActiveStateTest extends GameBaseCase {
+class ActiveStateTest extends FightBaseCase {
private ActiveState state;
private Fight fight;
private PlayerFighter fighter;
@@ -93,7 +95,7 @@ public void setUp() throws Exception {
dataSet.pushMaps().pushSubAreas().pushAreas();
final GamePlayer me = gamePlayer(true);
- final GamePlayer enemy = makeOtherPlayer();
+ final GamePlayer enemy = super.other;
FightMap map;
fight = new Fight(
@@ -101,7 +103,7 @@ public void setUp() throws Exception {
new ChallengeType(configuration.fight()),
map = container.get(FightService.class).map(container.get(ExplorationMapService.class).load(10340)),
Arrays.asList(
- fight -> new SimpleTeam(fight, fighter = new PlayerFighter(me), Arrays.asList(map.get(123), map.get(222)), 0),
+ fight -> new SimpleTeam(fight, fighter = container.get(FighterFactory.class).create(me), Arrays.asList(map.get(123), map.get(222)), 0),
fight -> new SimpleTeam(fight, other = new PlayerFighter(enemy), Arrays.asList(map.get(321)), 1)
),
new StatesFlow(
@@ -274,4 +276,25 @@ void leaveNotLastOfTeamWillDispatchLeavedEventWithALooserReward() throws SQLExce
assertInstanceOf(DropReward.class, ref.get().reward().get());
assertEquals(RewardType.LOOSER, ref.get().reward().get().type());
}
+
+ @Test
+ void leavePvmFightShouldApplyLooseReward() throws Exception {
+ AtomicReference ref = new AtomicReference<>();
+ PlayerFighter teammate = new PlayerFighter(makeSimpleGamePlayer(10));
+
+ fight = createPvmFight();
+ fight.state(PlacementState.class).joinTeam(
+ teammate,
+ player.fighter().team()
+ );
+ player.fighter().dispatcher().add(FightLeaved.class, ref::set);
+
+ state.start(fight);
+ state.leave(player.fighter());
+
+ assertNotNull(ref.get());
+ assertInstanceOf(DropReward.class, ref.get().reward().get());
+ assertEquals(RewardType.LOOSER, ref.get().reward().get().type());
+ assertEquals(0, gamePlayer().properties().life().current(), 2); // Add a delta to ensure that life regeneration will fail the test
+ }
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/FinishStateTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/FinishStateTest.java
index 12bbfd084..26c69fc06 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/FinishStateTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/FinishStateTest.java
@@ -19,6 +19,7 @@
package fr.quatrevieux.araknemu.game.fight.state;
+import fr.quatrevieux.araknemu.data.living.entity.player.Player;
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
import fr.quatrevieux.araknemu.game.fight.ending.EndFightResults;
@@ -26,13 +27,17 @@
import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
+import fr.quatrevieux.araknemu.game.fight.fighter.invocation.DoubleFighter;
import fr.quatrevieux.araknemu.network.game.out.fight.FightEnd;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -83,6 +88,42 @@ void start() {
);
}
+ @Test
+ void startShouldFilterInvocations() {
+ fight.fighters().join(
+ new DoubleFighter(-10, player.fighter()),
+ fight.map().get(142)
+ );
+
+ other.fighter().life().alter(player.fighter(), -1000);
+
+ Fighter winner = player.fighter();
+ Fighter looser = other.fighter();
+
+ state.start(fight);
+
+ assertFalse(player.isFighting());
+ assertFalse(other.isFighting());
+ assertCount(0, fight.teams());
+
+ requestStack.assertLast(
+ new FightEnd(
+ new FightRewardsSheet(
+ new EndFightResults(
+ fight,
+ Collections.singletonList(winner),
+ Collections.singletonList(looser)
+ ),
+ FightRewardsSheet.Type.NORMAL,
+ Arrays.asList(
+ new DropReward(RewardType.WINNER, winner, Collections.emptyList()),
+ new DropReward(RewardType.LOOSER, looser, Collections.emptyList())
+ )
+ )
+ )
+ );
+ }
+
@Test
void startOnWinningPvmFight() throws Exception {
fight = createPvmFight();
@@ -104,6 +145,66 @@ void startOnWinningPvmFight() throws Exception {
assertEquals(241, player.properties().experience().current() - lastXp);
}
+ @Test
+ void startShouldSavePlayerInDatabase() throws Exception {
+ fight = createPvmFight();
+ fight.nextState();
+
+ player.fighter().life().alter(player.fighter(), -100);
+
+ Collection monsters = fight.team(1).fighters();
+
+ long lastXp = player.properties().experience().current();
+ long lastKamas = player.inventory().kamas();
+
+ monsters.forEach(fighter -> fighter.life().kill(fighter));
+
+ state.start(fight);
+
+ assertFalse(player.isFighting());
+ assertCount(0, fight.teams());
+
+ assertBetween(100, 140, player.inventory().kamas() - lastKamas);
+ assertEquals(241, player.properties().experience().current() - lastXp);
+
+ Player entity = dataSet.refresh(new Player(player.id()));
+ assertEquals(player.inventory().kamas(), entity.kamas());
+ assertEquals(195, entity.life());
+ assertEquals(player.properties().experience().current(), entity.experience());
+ }
+
+ @Test
+ void startOnPvmFightShouldKeepInvocationWithDiscerment() throws Exception {
+ fight = createPvmFight();
+ fight.nextState();
+
+ final DoubleFighter invocation = new DoubleFighter(-10, player.fighter());
+
+ fight.fighters().join(
+ invocation,
+ fight.map().get(142)
+ );
+
+ invocation.characteristics().alterDiscernment(50);
+
+ Collection monsters = fight.team(1).fighters();
+
+ long lastXp = player.properties().experience().current();
+ long lastKamas = player.inventory().kamas();
+
+ monsters.forEach(fighter -> fighter.life().kill(fighter));
+
+ state.start(fight);
+
+ requestStack.assertLastMatches("^GE\\d+\\|1\\|0\\|2;1;Bob;50;0;5350000;5481700;5860000;\\d+;;;;\\d+\\|2;-10;Bob;50;0;0;0;0;;;;;\\d+\\|0;-1;31;4;1;0;0;0;;;;;\\|0;-2;34;9;1;0;0;0;;;;;$");
+
+ assertFalse(player.isFighting());
+ assertCount(0, fight.teams());
+
+ assertBetween(200, 280, player.inventory().kamas() - lastKamas);
+ assertEquals(241, player.properties().experience().current() - lastXp);
+ }
+
@Test
void levelUpShouldRestoreLife() throws Exception {
// Issue #192 : The life is not restored because SynchronizeLife is performed after LevelUp
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java
index f8f3a0dcd..703d35742 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java
@@ -234,6 +234,11 @@ public void alter(Characteristic characteristic, int value) {
}
+ @Override
+ public void alterDiscernment(int value) {
+
+ }
+
@Override
public Characteristics initial() {
return null;
@@ -309,7 +314,7 @@ public O apply(O operation) {
}
@Override
- public FighterData invoker() {
+ public Fighter invoker() {
return null;
}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightRewardTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightRewardTest.java
deleted file mode 100644
index dbc5636ee..000000000
--- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightRewardTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (c) 2017-2019 Vincent Quatrevieux
- */
-
-package fr.quatrevieux.araknemu.game.listener.fight.fighter;
-
-import fr.quatrevieux.araknemu.game.fight.Fight;
-import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.action.AddExperience;
-import fr.quatrevieux.araknemu.game.fight.event.FightFinished;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-
-class ApplyEndFightRewardTest extends FightBaseCase {
- private Fight fight;
- private ApplyEndFightReward listener;
-
- @Override
- @BeforeEach
- public void setUp() throws Exception {
- super.setUp();
-
- fight = createFight();
- listener = new ApplyEndFightReward(player.fighter());
- }
-
- @Test
- void onFightFinishedWithoutReward() {
- listener.on(new FightFinished(new DropReward(RewardType.WINNER, player.fighter(), Collections.emptyList())));
-
- assertFalse(player.isFighting());
- }
-
- @Test
- void onFightFinishedWithXpReward() {
- long lastXp = player.properties().experience().current();
-
- DropReward reward = new DropReward(RewardType.WINNER, player.fighter(), Arrays.asList(new AddExperience()));
- reward.setXp(1000);
-
- listener.on(new FightFinished(reward));
-
- assertFalse(player.isFighting());
- assertEquals(lastXp + 1000, player.properties().experience().current());
- }
-}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveRewardTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveRewardTest.java
deleted file mode 100644
index 8ebeb1141..000000000
--- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveRewardTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (c) 2017-2019 Vincent Quatrevieux
- */
-
-package fr.quatrevieux.araknemu.game.listener.fight.fighter;
-
-import fr.quatrevieux.araknemu.game.fight.Fight;
-import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.RewardType;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
-import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.action.AddExperience;
-import fr.quatrevieux.araknemu.game.fight.event.FightLeaved;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class ApplyLeaveRewardTest extends FightBaseCase {
- private Fight fight;
- private ApplyLeaveReward listener;
-
- @Override
- @BeforeEach
- public void setUp() throws Exception {
- super.setUp();
-
- fight = createFight();
- listener = new ApplyLeaveReward(player.fighter());
- }
-
- @Test
- void withReward() {
- long lastXp = player.properties().experience().current();
-
- DropReward reward = new DropReward(RewardType.WINNER, player.fighter(), Arrays.asList(new AddExperience()));
- reward.setXp(1000);
-
- listener.on(new FightLeaved(reward));
-
- assertEquals(lastXp + 1000, player.properties().experience().current());
- }
-
- @Test
- void withoutReward() {
- listener.on(new FightLeaved());
- }
-}
diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSessionTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSessionTest.java
index 384c8c57e..38558c59e 100644
--- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSessionTest.java
+++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/StopFightSessionTest.java
@@ -19,18 +19,25 @@
package fr.quatrevieux.araknemu.game.listener.fight.fighter;
+import fr.quatrevieux.araknemu.core.event.DefaultListenerAggregate;
+import fr.quatrevieux.araknemu.data.living.entity.player.Player;
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.FightBaseCase;
+import fr.quatrevieux.araknemu.game.fight.ending.reward.FightReward;
+import fr.quatrevieux.araknemu.game.fight.event.FightFinished;
import fr.quatrevieux.araknemu.game.fight.event.FightLeaved;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
class StopFightSessionTest extends FightBaseCase {
private Fight fight;
- private StopFightSession listener;
+ private StopFightSession subscriber;
+ private DefaultListenerAggregate listener;
private PlayerFighter fighter;
@Override
@@ -40,13 +47,30 @@ public void setUp() throws Exception {
fight = createFight();
fighter = player.fighter();
- listener = new StopFightSession(fighter);
+ subscriber = new StopFightSession(fighter);
+ listener = new DefaultListenerAggregate();
+ listener.register(subscriber);
}
@Test
- void onFighterRemoved() {
- listener.on(new FightLeaved());
+ void onFightLeaved() {
+ player.properties().life().set(50);
+ listener.dispatch(new FightLeaved());
assertFalse(player.isFighting());
+
+ Player entity = dataSet.refresh(new Player(player.id()));
+ assertEquals(50, entity.life());
+ }
+
+ @Test
+ void onFightFinished() {
+ player.properties().life().set(50);
+ listener.dispatch(new FightFinished(Mockito.mock(FightReward.class)));
+
+ assertFalse(player.isFighting());
+
+ Player entity = dataSet.refresh(new Player(player.id()));
+ assertEquals(50, entity.life());
}
}
\ No newline at end of file