def test_buff_cancelling_when_other_buff_triggering(self): buffable = Buffable() buff_id_1 = 1 buff_id_2 = 2 buff_1 = BuffBuilder(buff_id_1).modify("+", 50, Attributes.ATK).whenever(DamageEvent)\ .just_if("not has_buff 2").build() buff_2 = BuffBuilder(buff_id_2).modify( "+", 75, Attributes.ATK).whenever(DamageEvent).build() # A condition that can be triggered by a MockEvent @buffspecs.AddConditionFor([BuffEvent]) def has_buff(event, buff_id): return buff_id in event.buffable.active_buffs add_buff(buffable, buff_1, CompleteBuildingEvent()) call_event(DamageEvent(buffable)) # Player does not have buff 2 so he should be getting buff 1 assert buffable.attributes[Attributes.ATK] == 50 assert buff_id_1 in buffable.active_buffs add_buff(buffable, buff_2, CompleteBuildingEvent()) call_event(DamageEvent(buffable)) # Now that he got buff 2 applied, buff 1 should be removed and only buff 2 is applied assert buffable.attributes[Attributes.ATK] == 75 assert buff_id_1 not in buffable.active_buffs assert buff_id_2 in buffable.active_buffs
def test_buff_stack_with_expiry_all_at_once(self): buffable = Buffable() buff = BuffSpec() buff.activation_triggers = [] # no triggers buff.conditions = [] # no conditions buff.max_stack = 3 # 3 stacks max# buff.duration_seconds = 10 buff.modifiers = [Modifier("+", 10, Attributes.DEF)] with FixedTime(get_timestamp()): expiry_time = get_timestamp() + buff.duration_seconds # Add the buff for full 3 stacks add_buff(buffable, buff, CompleteBuildingEvent()) add_buff(buffable, buff, CompleteBuildingEvent()) add_buff(buffable, buff, CompleteBuildingEvent()) assert buffable.attributes[Attributes.DEF] == 30 assert buffable.active_buffs[buff.buff_id].stack == 3 assert len(buffable.expiry_times) == 3 with FixedTime(expiry_time): assert buffable.attributes[Attributes.DEF] == 0 assert len(buffable.expiry_times) == 0 assert buff.buff_id not in buffable.active_buffs
def test_basic_buff_dependency(self): buffable = Buffable() buff_id_1 = 1 buff_id_2 = 2 buff_1 = BuffBuilder().modify( "+", 50, Attributes.ATK).just_if("has_buff 2").build() buff_2 = BuffBuilder().modify("+", 50, Attributes.ATK).build() # A condition that can be triggered by a MockEvent @buffspecs.AddConditionFor([BuffEvent]) def has_buff(event, buff_id): return buff_id in event.buffable.active_buffs add_buff(buffable, buff_1, CompleteBuildingEvent()) # Player should not be modified because he did not have buff 2 assert buffable.attributes[Attributes.ATK] == 0 # Adding the second buff should trigger the first one because his condidion matched add_buff(buffable, buff_2, CompleteBuildingEvent()) # Both buffs should be applied now assert buffable.attributes[Attributes.ATK] == 100 assert buff_id_1 in buffable.active_buffs assert buff_id_2 in buffable.active_buffs
def test_changing_source_attribute_affects_derivated_attribute(self): buffable = Buffable() buffable.attributes[Attributes.ATK] = 100 # Simple buff that 50% of your attack goes to your def buff = BuffBuilder().modify("%", 0.5, Attributes.ATK).to_attribute( Attributes.DEF).build() add_buff(buffable, buff, CompleteBuildingEvent()) # Player should have got 50% of his atk (50) to def assert buffable.attributes[Attributes.DEF] == 50 assert buffable.attributes[Attributes.ATK] == 100 # Now we add +100 attack to the player, his 50% buff instead of giving 50 def should give 100 def buff_2 = BuffBuilder().modify("+", 100, Attributes.ATK).build() add_buff(buffable, buff_2, CompleteBuildingEvent()) # Player defense should be updated as his attack increased assert buffable.attributes[Attributes.DEF] == 100 assert buffable.attributes[Attributes.ATK] == 200 # Now removing the buff should re-calculate the derivation as well remove_buff(buffable, buff_2.buff_id) # Player should have got 50% of his atk (50) to def as it should be derivating from 100 atk again assert buffable.attributes[Attributes.DEF] == 50 assert buffable.attributes[Attributes.ATK] == 100
def test_next_to_expire(self): buffable = Buffable() buff = BuffSpec() buff.activation_triggers = [] # no triggers buff.conditions = [] # no conditions buff.duration_seconds = 10 # Only lasts for 10 seconds buff.max_stack = 3 buff.modifiers = [Modifier("+", 50, Attributes.DEF)] with FixedTime(get_timestamp()): expiry_time = get_timestamp() + buff.duration_seconds # Add the buff 3 stacks add_buff(buffable, buff, CompleteBuildingEvent()) add_buff(buffable, buff, CompleteBuildingEvent()) add_buff(buffable, buff, CompleteBuildingEvent()) with FixedTime(expiry_time): expired_buffs = list(get_expired_buffs(buffable)) assert len(expired_buffs) == 3 # Calling expired buffs should have removed them from expiry list assert len(buffable.expiry_times) == 0
def test_derivation_debug_history(self): buffable = Buffable() buffable.attributes[Attributes.ATK] = 100 buff = BuffBuilder().modify("%", 0.5, Attributes.ATK).to_attribute( Attributes.DEF).build() add_buff(buffable, buff, CompleteBuildingEvent()) atk_modification_history = list( buffable.attributes.get_data(Attributes.DEF).history.values()) last_modification = atk_modification_history[0] # The original modifier should be in history as well assert last_modification.modifier.value == 0.5 assert last_modification.modifier.attribute_id == Attributes.ATK assert last_modification.modifier.operator == "%" # It should have created an modifier of 50% of user atk, since atk was 100, thats +50 DEF assert last_modification.derivated_modifier.value == 50 assert last_modification.derivated_modifier.attribute_id == Attributes.DEF assert last_modification.derivated_modifier.operator == "+" assert last_modification.buff_id == buff.buff_id event_chain = last_modification.source_event.get_event_chain() assert isinstance(event_chain[0], AddBuffEvent) assert isinstance(event_chain[1], CompleteBuildingEvent)
def test_propagating_a_derivation_buff(self): # Simple derivation buff buffable = Buffable() buffable.attributes[Attributes.ATK] = 100 buff = BuffBuilder().modify("%", 0.5, Attributes.ATK).to_attribute( Attributes.DEF).build() # We want to track the performance of this with TrackStack() as track: add_buff(buffable, buff, CompleteBuildingEvent())
def test_simple_derivation(self): buffable = Buffable() buffable.attributes[Attributes.ATK] = 100 # Simple buff that 50% of your attack goes to your def buff = BuffBuilder().modify("%", 0.5, Attributes.ATK).to_attribute( Attributes.DEF).build() add_buff(buffable, buff, CompleteBuildingEvent()) # Player should have got 50% of his atk (50) to def assert buffable.attributes[Attributes.DEF] == 50 assert buffable.attributes[Attributes.ATK] == 100 assert buff.buff_id in buffable.active_buffs # Checking the derivation has been registered assert list( buffable.attributes.get_data( Attributes.ATK).derivations.keys())[0] == Attributes.DEF
def test_removing_derivation_buff_updates_derivated_attributes(self): buffable = Buffable() buffable.attributes[Attributes.ATK] = 100 buffable.attributes[Attributes.DEF] = 100 # Simple buff that 50% of your attack goes to your def buff = BuffBuilder().modify("%", 0.5, Attributes.ATK).to_attribute( Attributes.DEF).build() add_buff(buffable, buff, CompleteBuildingEvent()) # 50% of your def, goes to your HP buff_2 = BuffBuilder().modify("%", 0.5, Attributes.DEF).to_attribute( Attributes.HP).build() add_buff(buffable, buff_2, CompleteBuildingEvent()) # Player defense should be updated as his attack increased assert buffable.attributes[Attributes.DEF] == 150 assert buffable.attributes[Attributes.HP] == 75 remove_buff(buffable, buff.buff_id) assert buffable.attributes[Attributes.DEF] == 100 assert buffable.attributes[Attributes.HP] == 50
def test_adding_buff(self): buffable = Buffable() buff = BuffSpec(1) buff.activation_triggers = [] # no triggers buff.conditions = [] # no conditions buff.max_stack = 3 # 3 stacks max buff.modifiers = [Modifier("+", 10, Attributes.DEF)] # Add the buff add_buff(buffable, buff, CompleteBuildingEvent()) # Since it has no triggers or conditions, it was added automatically assert buffable.attributes[Attributes.DEF] == 10 assert buff.buff_id in buffable.active_buffs assert buffable.active_buffs[buff.buff_id].stack == 1 # Add the buff again, should be in 2 stacks now add_buff(buffable, buff, CompleteBuildingEvent()) assert buffable.attributes[Attributes.DEF] == 20 assert buffable.active_buffs[buff.buff_id].stack == 2 # Add the buff again, should be in 2 stacks now add_buff(buffable, buff, CompleteBuildingEvent()) assert buffable.attributes[Attributes.DEF] == 30 assert buffable.active_buffs[buff.buff_id].stack == 3 # Now we reached our max stack, it should always be 3 stacks. add_buff(buffable, buff, CompleteBuildingEvent()) assert buffable.attributes[Attributes.DEF] == 30 assert buffable.active_buffs[buff.buff_id].stack == 3 # If we remove the buff, all stacks should be removed remove_buff(buffable, 1) assert buffable.attributes[Attributes.DEF] == 0 assert buff.buff_id not in buffable.active_buffs