diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java index 0f128c0aa..8b309b401 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java @@ -84,6 +84,7 @@ private void removeStackableActorCondition(Actor actor, ActorConditionType type, } private void removeNonStackableActorCondition(Player player, ActorConditionType type, int magnitude, int duration) { + int highestMagnitude = 0; for (Inventory.WearSlot slot : Inventory.WearSlot.values()) { ItemType t = player.inventory.getItemTypeInWearSlot(slot); if (t == null) continue; @@ -94,11 +95,14 @@ private void removeNonStackableActorCondition(Player player, ActorConditionType for (ActorConditionEffect e : equipEffects.addedConditions) { if (!e.conditionType.conditionTypeID.equals(type.conditionTypeID)) continue; if (e.duration != duration) continue; - // The player is wearing some other item that gives this condition. It will not be removed now. - return; + if (e.magnitude > highestMagnitude) + highestMagnitude = e.magnitude; } } - removeStackableActorCondition(player, type, magnitude, duration); + + if (highestMagnitude < magnitude) { + removeStackableActorCondition(player, type, magnitude-highestMagnitude, duration); + } } @@ -192,24 +196,53 @@ private void addStackableActorCondition(Actor actor, ActorConditionEffect e, int actor.conditions.add(c); actorConditionListeners.onActorConditionAdded(actor, c); } - private void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { - final ActorConditionType type = e.conditionType; - for(int i = actor.conditions.size() - 1; i >= 0; --i) { - ActorCondition c = actor.conditions.get(i); - if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue; - if (c.magnitude > e.magnitude) return; - if (c.magnitude == e.magnitude) { - if (c.duration >= duration) return; - } - // If the actor already has this condition, but of a lower magnitude, we remove the old one and add this higher magnitude. - actor.conditions.remove(i); - actorConditionListeners.onActorConditionRemoved(actor, c); - } - - ActorCondition c = e.createCondition(duration); - actor.conditions.add(c); - actorConditionListeners.onActorConditionAdded(actor, c); + private void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { + ActorCondition conditionWithSameDuration = null; + int effectiveMagnitude = e.magnitude; + final ActorConditionType type = e.conditionType; + + // Search for conditions with the same or higher duration + for(int i = actor.conditions.size() - 1; i >= 0; --i) { + ActorCondition c = actor.conditions.get(i); + if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue; + if(c.duration >= duration) { + if (c.duration == duration) + conditionWithSameDuration = c; + + effectiveMagnitude -= c.magnitude; + if(effectiveMagnitude <1) + return; + } + } + + // reduce the magnitude of shorter running conditions + for(int i=actor.conditions.size() -1; i >= 0; --i) { + ActorCondition c = actor.conditions.get(i); + if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue; + if (c.duration < duration) { + c.magnitude -= effectiveMagnitude; + if(c.magnitude <1) + { + actor.conditions.remove(i); + actorConditionListeners.onActorConditionRemoved(actor, c); + } + else + actorConditionListeners.onActorConditionMagnitudeChanged(actor, c); + } + } + + // if there is an existing condition with the same duration, we use it + if (conditionWithSameDuration != null) { + conditionWithSameDuration.magnitude += effectiveMagnitude; + actorConditionListeners.onActorConditionMagnitudeChanged(actor, conditionWithSameDuration); + } + else { + ActorCondition c = e.createCondition(duration); + c.magnitude = effectiveMagnitude; + actor.conditions.add(c); + actorConditionListeners.onActorConditionAdded(actor, c); + } } private void addActorConditionImmunity(Actor actor, ActorConditionEffect e, int duration) { diff --git a/AndorsTrail/test/controller/ActorStatsControllerTest.java b/AndorsTrail/test/controller/ActorStatsControllerTest.java new file mode 100644 index 000000000..fa8ff46d7 --- /dev/null +++ b/AndorsTrail/test/controller/ActorStatsControllerTest.java @@ -0,0 +1,94 @@ +package com.gpl.rpg.AndorsTrail.controller; + +import com.gpl.rpg.AndorsTrail.model.actor.Actor; +import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition; +import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect; +import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType; + +import java.lang.reflect.Method; +import java.util.concurrent.locks.Condition; + +import static org.junit.Assert.*; + +public class ActorStatsControllerTest { + @org.junit.Test + public void addNonStackableActorCondition() throws Exception { + Method m = Class.forName("com.gpl.rpg.AndorsTrail.controller.ActorStatsController").getDeclaredMethod("addNonStackableActorCondition", Actor.class, ActorConditionEffect.class, int.class); + m.setAccessible(true); + + ActorStatsController ctrl = new ActorStatsController(null,null); + ActorConditionType t = new ActorConditionType("typeDummy", "Dummy", 1, null, false, false, null, null, null); + Actor a = new Actor(null, true, false); + + // add a permanent conditon + m.invoke(ctrl, a, new ActorConditionEffect(t, 1, 999, null), 999); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 1); + + // adding the same permanent conditon with the same magnitude has no effect + m.invoke(ctrl, a, new ActorConditionEffect(t, 1, 999, null), 999); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 1); + + // add a permanent conditon of another type + ActorConditionType t2 = new ActorConditionType("typeDummy2", "Dummy2", 1, null, false, false, null, null, null); + m.invoke(ctrl, a, new ActorConditionEffect(t2, 1, 999, null), 999); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 1 && a.conditions.get(1).magnitude == 1); + a.conditions.remove(1); + + // adding a permanent condition with a higher magnitude than an existing one of the same type, replaces it + m.invoke(ctrl, a, new ActorConditionEffect(t, 2, 999, null), 999); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 2); + + // adding a short running condition with lower magnitude has no effect + m.invoke(ctrl, a, new ActorConditionEffect(t, 1, 10, null), 10); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 2); + + // adding a short running condition with the same magnitude has no effect + m.invoke(ctrl, a, new ActorConditionEffect(t, 2, 10, null), 10); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 2); + + // adding a short running condition with a higher magnitude gets added but reduced + // by the magnitude of the long running one + m.invoke(ctrl, a, new ActorConditionEffect(t, 3, 10, null), 10); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 2 && a.conditions.get(1).magnitude == 1); + m.invoke(ctrl, a, new ActorConditionEffect(t, 4, 10, null), 10); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 2 && a.conditions.get(1).magnitude == 2); + + // adding a short running condition with a lower magnitude than an existing one with the same or shorter duration has no effect + m.invoke(ctrl, a, new ActorConditionEffect(t, 3, 10, null), 10); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 2 && a.conditions.get(1).magnitude == 2); + m.invoke(ctrl, a, new ActorConditionEffect(t, 3, 7, null), 7); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 2 && a.conditions.get(1).magnitude == 2); + + // adding a longer runnig condition with a higher magnitude than a existing long running condition reduces the magnitude of shorter running conditions + m.invoke(ctrl, a, new ActorConditionEffect(t, 3, 999, null), 999); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 3 && a.conditions.get(1).magnitude == 1); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 3, 999, null), 999); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 3 && a.conditions.get(1).magnitude == 1); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 4, 999, null), 999); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 4); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 4, 1000, null), 1000); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 4 && a.conditions.get(0).duration == 1000); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 5, 1001, null), 1001); + assertTrue(a.conditions.size() == 1 && a.conditions.get(0).magnitude == 5 && a.conditions.get(0).duration == 1001); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 6, 10, null), 10); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 5 && a.conditions.get(1).magnitude == 1); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 6, 100, null), 100); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 5 && a.conditions.get(1).magnitude == 1 && a.conditions.get(1).duration == 100); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 7, 100, null), 100); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 5 && a.conditions.get(1).magnitude == 2 && a.conditions.get(1).duration == 100); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 6, 200, null), 200); + assertTrue(a.conditions.size() == 3 && a.conditions.get(0).magnitude == 5 && a.conditions.get(1).magnitude == 1 && a.conditions.get(2).magnitude == 1); + + m.invoke(ctrl, a, new ActorConditionEffect(t, 7, 300, null), 300); + assertTrue(a.conditions.size() == 2 && a.conditions.get(0).magnitude == 5 && a.conditions.get(1).magnitude == 2); + + } +} \ No newline at end of file