From 3ba9d52d22251ec2804bde73d65463a9c0b43848 Mon Sep 17 00:00:00 2001 From: Vincent Quatrevieux Date: Tue, 6 Feb 2024 18:28:04 +0100 Subject: [PATCH] feat(fight): Handle living chest --- .../quatrevieux/araknemu/game/GameModule.java | 1 + .../handler/misc/AddDiscernmentHandler.java | 72 ++++++++ .../ending/reward/FightRewardsSheet.java | 9 + .../fight/ending/reward/RewardsGenerator.java | 11 ++ .../drop/ChallengeRewardsGenerator.java | 6 + .../ending/reward/drop/action/AddItems.java | 45 +++-- .../ending/reward/drop/action/AddKamas.java | 36 +++- .../reward/drop/pvm/PvmRewardsGenerator.java | 7 + .../drop/pvm/provider/PvmXpProvider.java | 70 ++++--- .../game/fight/fighter/AbstractFighter.java | 2 +- .../fight/fighter/DefaultFighterFactory.java | 6 +- .../araknemu/game/fight/fighter/Fighter.java | 3 + .../fight/fighter/FighterCharacteristics.java | 14 +- .../fighter/invocation/DoubleFighter.java | 3 +- .../DoubleFighterCharacteristics.java | 11 +- .../fighter/invocation/InvocationFighter.java | 3 +- .../InvocationFighterCharacteristics.java | 11 +- .../invocation/StaticInvocationFighter.java | 3 +- .../MonsterFighterCharacteristics.java | 8 +- .../player/PlayerFighterCharacteristics.java | 12 +- .../fight/module/CommonEffectsModule.java | 2 + .../game/fight/state/ActiveState.java | 1 + .../game/fight/state/FinishState.java | 20 +- .../game/fight/state/PlacementState.java | 1 + .../fight/fighter/ApplyEndFightReward.java | 47 ----- .../fight/fighter/ApplyLeaveReward.java | 48 ----- .../fight/fighter/StopFightSession.java | 40 +++- .../araknemu/game/GameBaseCase.java | 11 ++ .../araknemu/game/GameDataSet.java | 1 + .../fight/castable/effect/FunctionalTest.java | 8 + .../misc/AddDiscernmentHandlerTest.java | 172 ++++++++++++++++++ .../ending/reward/drop/AddItemsTest.java | 17 ++ .../ending/reward/drop/AddKamasTest.java | 14 ++ .../pvm/provider/PvmItemDropProviderTest.java | 38 ++++ .../pvm/provider/PvmKamasProviderTest.java | 28 +++ .../drop/pvm/provider/PvmXpProviderTest.java | 22 +++ .../ChallengeRewardsGeneratorTest.java | 27 +++ .../generator/PvmRewardsGeneratorTest.java | 100 ++++++++++ .../fighter/DefaultFighterFactoryTest.java | 7 +- .../DoubleFighterCharacteristicsTest.java | 9 + .../InvocationFighterCharacteristicsTest.java | 22 +++ .../MonsterFighterCharacteristicsTest.java | 6 + .../PlayerFighterCharacteristicsTest.java | 17 ++ .../game/fight/state/ActiveStateTest.java | 29 ++- .../game/fight/state/FinishStateTest.java | 101 ++++++++++ .../order/AlternateTeamFighterOrderTest.java | 7 +- .../fighter/ApplyEndFightRewardTest.java | 69 ------- .../fight/fighter/ApplyLeaveRewardTest.java | 64 ------- .../fight/fighter/StopFightSessionTest.java | 32 +++- 49 files changed, 965 insertions(+), 328 deletions(-) create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandler.java delete mode 100644 src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightReward.java delete mode 100644 src/main/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveReward.java create mode 100644 src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/AddDiscernmentHandlerTest.java delete mode 100644 src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyEndFightRewardTest.java delete mode 100644 src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/ApplyLeaveRewardTest.java 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