diff --git a/server/action.py b/server/action.py index c58be8bb..39fefc7e 100644 --- a/server/action.py +++ b/server/action.py @@ -24,6 +24,8 @@ class ActionTypes(str, Enum): COMBAT_ACTION = 'COMBAT_ACTION' SWITCH_CHARACTOR = 'SWITCH_CHARACTOR' CHARGE = 'CHARGE' + USE_SKILL = 'USE_SKILL' + USE_CARD = 'USE_CARD' SKILL_END = 'SKILL_END' CHARACTOR_DEFEATED = 'CHARACTOR_DEFEATED' CREATE_OBJECT = 'CREATE_OBJECT' @@ -242,6 +244,22 @@ class ChargeAction(ActionBase): charge: int +class UseSkillAction(ActionBase): + """ + Action for using skill. + """ + type: Literal[ActionTypes.USE_SKILL] = ActionTypes.USE_SKILL + skill_position: ObjectPosition + + +class UseCardAction(ActionBase): + """ + Action for using card. + """ + type: Literal[ActionTypes.USE_CARD] = ActionTypes.USE_CARD + card_position: ObjectPosition + + class SkillEndAction(ActionBase): """ Action for ending skill. diff --git a/server/charactor/charactor_base.py b/server/charactor/charactor_base.py index 552878e9..1fbc8e37 100644 --- a/server/charactor/charactor_base.py +++ b/server/charactor/charactor_base.py @@ -7,6 +7,8 @@ from typing import List, Literal, Any + +from ..event import UseSkillEventArguments from ..consts import ( ELEMENT_TO_DIE_COLOR, DamageElementalType, DamageType, ObjectType, SkillType, WeaponType, ElementType, FactionType, @@ -22,7 +24,7 @@ from ..card.equipment.weapon import Weapons from ..action import ( ChargeAction, CombatActionAction, MakeDamageAction, MoveObjectAction, - RemoveObjectAction, Actions, SkillEndAction + RemoveObjectAction, Actions, SkillEndAction, UseSkillAction ) @@ -63,7 +65,6 @@ def get_actions(self, match: Any) -> List[Actions]: 1. MakeDamageAction to attack the enemy active charactor with damage `self.damage` and damage type `self.damage_type`. 2. ChargeAction to charge the active charactor by 1. - 3. SkillEndAction to declare skill end, and trigger the event. """ target_table = match.player_tables[1 - self.position.player_idx] target_charactor_idx = target_table.active_charactor_idx @@ -91,6 +92,17 @@ def get_actions(self, match: Any) -> List[Actions]: ), ] + def event_handler_USE_SKILL( + self, event: UseSkillEventArguments, match: Any + ): + """ + When use skill event triggered, check if this skill is used. + If so, return self.get_actions() + """ + if event.action.skill_position == self.position: + return self.get_actions(match) + return [] + class PhysicalNormalAttackBase(SkillBase): """ @@ -304,7 +316,9 @@ def get_actions( break else: raise AssertionError('Skill not found') - ret += self.skill.get_actions(match) + ret.append(UseSkillAction( + skill_position = self.skill.position + )) # skill used, add SkillEndAction ret.append(SkillEndAction( position = self.skill.position, diff --git a/server/charactor/dendro/collei.py b/server/charactor/dendro/collei.py index f575cd99..795b62fb 100644 --- a/server/charactor/dendro/collei.py +++ b/server/charactor/dendro/collei.py @@ -146,22 +146,6 @@ class FloralSidewinder(SkillTalent): ) skill: FloralBrush = FloralBrush() - def get_actions( - self, target: ObjectPosition | None, match: Any - ) -> List[Actions]: - # When equip this card, as skill must be used, but currently talent - # is on hand, add one more action to create status. - ret = super().get_actions(target, match) - # create status before using skill - ret = [CreateObjectAction( - object_name = 'Floral Sidewinder', - object_position = self.position.set_area( - ObjectPositionType.TEAM_STATUS - ), - object_arguments = {} - )] + ret - return ret - # charactor base diff --git a/server/event.py b/server/event.py index f28879a4..8aef8a2e 100644 --- a/server/event.py +++ b/server/event.py @@ -24,6 +24,7 @@ ChangeObjectUsageAction, MoveObjectAction, ConsumeArcaneLegendAction, + UseSkillAction, ) from .modifiable_values import DamageValue, FinalDamageValue @@ -213,6 +214,14 @@ class ChargeEventArguments(EventArgumentsBase): charge_after: int +class UseSkillEventArguments(EventArgumentsBase): + """ + Event arguments for use skill. + """ + type: Literal[ActionTypes.USE_SKILL] = ActionTypes.USE_SKILL + action: UseSkillAction + + class SkillEndEventArguments(EventArgumentsBase): """ Event arguments for skill end event. diff --git a/server/match.py b/server/match.py index 5c16a5dc..9aeb395f 100644 --- a/server/match.py +++ b/server/match.py @@ -21,6 +21,8 @@ SwitchCharactorAction, MakeDamageAction, ChargeAction, + UseSkillAction, + # UseCardAction, SkillEndAction, CreateObjectAction, RemoveObjectAction, @@ -74,6 +76,7 @@ RemoveObjectEventArguments, ChangeObjectUsageEventArguments, MoveObjectEventArguments, + UseSkillEventArguments, ) from .object_base import ObjectBase from .modifiable_values import ( @@ -1276,19 +1279,23 @@ def _respond_use_skill(self, response: UseSkillResponse): value = cost_value, mode = 'REAL' ) - actions: List[Actions] = [RemoveDiceAction( - player_idx = response.player_idx, - dice_idxs = response.dice_idxs, - )] - actions += skill.get_actions(self) - actions.append(SkillEndAction( - position = skill.position, - skill_type = skill.skill_type, - )) - actions.append(CombatActionAction( - action_type = 'SKILL', - position = skill.position, - )) + actions: List[Actions] = [ + RemoveDiceAction( + player_idx = response.player_idx, + dice_idxs = response.dice_idxs, + ), + UseSkillAction( + skill_position = skill.position, + ), + SkillEndAction( + position = skill.position, + skill_type = skill.skill_type + ), + CombatActionAction( + action_type = 'SKILL', + position = skill.position, + ) + ] event_frame = EventFrame( events = [], triggered_actions = actions @@ -1315,6 +1322,9 @@ def _respond_use_card(self, response: UseCardResponse): player_idx = response.player_idx, dice_idxs = response.dice_idxs, ), + # UseCardAction( + # card_position = card.position, + # ) ] if card.type in [ObjectType.CARD, ObjectType.ARCANE]: # only card and arcane type will be removed from hand. @@ -1379,6 +1389,10 @@ def _act(self, action: ActionBase) -> List[EventArguments]: return list(self._action_make_damage(action)) elif isinstance(action, ChargeAction): return list(self._action_charge(action)) + elif isinstance(action, UseSkillAction): + return list(self._action_use_skill(action)) + # elif isinstance(action, UseCardAction): + # return list(self._action_use_card(action)) elif isinstance(action, SkillEndAction): return list(self._action_skill_end(action)) elif isinstance(action, CharactorDefeatedAction): @@ -2293,6 +2307,22 @@ def _action_consume_arcane_legend( Action funtions that only used to trigger specific event """ + def _action_use_skill(self, action: UseSkillAction) \ + -> List[UseSkillEventArguments]: + player_idx = action.skill_position.player_idx + table = self.player_tables[player_idx] + charactor = table.charactors[table.active_charactor_idx] + skill = charactor.get_object(action.skill_position) + assert skill is not None and skill.type == ObjectType.SKILL + logging.info( + f'player {player_idx} ' + f'charactor {charactor.name}:{table.active_charactor_idx} ' + f'use skill {skill.name}.' # type: ignore + ) + return [UseSkillEventArguments( + action = action, + )] + def _action_skill_end(self, action: SkillEndAction) \ -> List[SkillEndEventArguments]: player_idx = action.position.player_idx