diff --git a/server/status/charactor_status/base.py b/server/status/charactor_status/base.py index 423af4f7..7885cee0 100644 --- a/server/status/charactor_status/base.py +++ b/server/status/charactor_status/base.py @@ -1,4 +1,6 @@ from typing import Any, Literal, List + +from ...modifiable_values import DamageDecreaseValue from ...consts import ObjectType from ..base import StatusBase from ...action import RemoveObjectAction, Actions @@ -10,6 +12,11 @@ class CharactorStatusBase(StatusBase): Base class of charactor status. """ type: Literal[ObjectType.CHARACTOR_STATUS] = ObjectType.CHARACTOR_STATUS + name: str + desc: str + version: str + usage: int + max_usage: int class UsageCharactorStatus(CharactorStatusBase): @@ -26,7 +33,11 @@ class UsageCharactorStatus(CharactorStatusBase): If it is not a damage related status, check_remove_triggered should be called manually. """ - name: Literal['UsageCharactorStatus'] = 'UsageCharactorStatus' + name: str + desc: str + version: str + usage: int + max_usage: int def check_should_remove(self) -> List[Actions]: """ @@ -55,8 +66,11 @@ class RoundCharactorStatus(CharactorStatusBase): event trigger on ROUND_PREPARE to check if run out of usages; when run out of usages, it will remove itself. """ - name: Literal['RoundCharactorStatus'] = 'RoundCharactorStatus' + name: str + desc: str + version: str usage: int + max_usage: int def check_should_remove(self) -> List[RemoveObjectAction]: """ @@ -79,3 +93,55 @@ def event_handler_ROUND_PREPARE( """ self.usage -= 1 return list(self.check_should_remove()) + + +class DefendCharactorStatus(UsageCharactorStatus): + """ + Base class of defend status (purple shield), decrease damage with its rule + when receive damage, and decrease usage by 1. + """ + name: str + desc: str + version: str + usage: int + max_usage: int + min_damage_to_trigger: int + max_in_one_time: int + decrease_usage_by_damage: bool = False + + def value_modifier_DAMAGE_DECREASE( + self, value: DamageDecreaseValue, match: Any, + mode: Literal['TEST', 'REAL']) -> DamageDecreaseValue: + """ + Decrease damage with its rule, and decrease 1 usage. + """ + if not value.is_corresponding_charactor_receive_damage( + self.position, match, + ): + # not this charactor receive damage, not modify + return value + assert self.usage > 0 + new_usage = value.apply_shield( + self.usage, self.min_damage_to_trigger, + self.max_in_one_time, self.decrease_usage_by_damage, + ) + assert mode == 'REAL' + self.usage = new_usage + return value + + +class ShieldCharactorStatus(DefendCharactorStatus): + """ + Base class of shield status (yellow shield), decrease damage by its usage + and decrease corresponding usage. + """ + name: str + desc: str + version: str + usage: int + max_usage: int + + # papams passing to apply_shield is fixed + min_damage_to_trigger: int = 0 + max_in_one_time: int = 0 + decrease_usage_by_damage: bool = True diff --git a/server/status/charactor_status/foods.py b/server/status/charactor_status/foods.py index c28b5fe7..54195b55 100644 --- a/server/status/charactor_status/foods.py +++ b/server/status/charactor_status/foods.py @@ -2,12 +2,12 @@ from ...consts import SkillType -from ...modifiable_values import DamageDecreaseValue, DamageIncreaseValue +from ...modifiable_values import DamageIncreaseValue from ...action import RemoveObjectAction from ...event import MakeDamageEventArguments -from .base import RoundCharactorStatus +from .base import DefendCharactorStatus, RoundCharactorStatus class Satiated(RoundCharactorStatus): @@ -59,7 +59,7 @@ def event_handler_MAKE_DAMAGE( return self.check_should_remove() -class LotusFlowerCrisp(RoundCharactorStatus): +class LotusFlowerCrisp(RoundCharactorStatus, DefendCharactorStatus): name: Literal['Lotus Flower Crisp'] desc: str = ( "During this Round, the target character takes -3 DMG the next time." @@ -67,30 +67,8 @@ class LotusFlowerCrisp(RoundCharactorStatus): version: Literal['3.3'] = '3.3' usage: int = 1 max_usage: int = 1 - - def value_modifier_DAMAGE_DECREASE( - self, value: DamageDecreaseValue, match: Any, - mode: Literal['TEST', 'REAL']) -> DamageDecreaseValue: - assert mode == 'REAL' - if not value.is_corresponding_charactor_receive_damage( - self.position, match - ): - # not this charactor receive damage, not modify - return value - if value.damage == 0: - # no damage, not modify - return value - assert self.usage > 0 - decrease = min(3, value.damage) - value.damage -= decrease - assert mode == 'REAL' - self.usage -= 1 - return value - - def event_handler_MAKE_DAMAGE( - self, event: MakeDamageEventArguments, match: Any - ) -> List[RemoveObjectAction]: - return self.check_should_remove() + min_damage_to_trigger: int = 1 + max_in_one_time: int = 3 class TandooriRoastChicken(RoundCharactorStatus):