Coverage for thb/characters/rumia.py : 39%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2from __future__ import annotations
4# -- stdlib --
5from typing import TYPE_CHECKING
7# -- third party --
8# -- own --
9from game.base import ActionShootdown
10from thb.actions import Damage, DrawCards, FinalizeStage, LaunchCard, UserAction, user_choose_cards
11from thb.cards.base import PhysicalCard, Skill, t_None, t_OtherN
12from thb.cards.basic import Attack
13from thb.cards.definition import AttackCard, RejectCard
14from thb.cards.spellcard import BaseDuel
15from thb.characters.base import Character, register_character_to
16from thb.mode import THBEventHandler
18# -- typing --
19if TYPE_CHECKING:
20 from thb.thbkof import THBattleKOF # noqa: F401
23# -- code --
24class DarknessDuel(BaseDuel):
25 pass
28class DarknessAction(UserAction):
29 card_usage = 'launch'
31 def apply_action(self):
32 attacker, victim = self.target_list
33 src = self.source
34 g = self.game
35 tags = self.source.tags
36 tags['darkness_tag'] = tags['turn_count']
38 cards = user_choose_cards(self, attacker, ('cards', 'showncards'))
39 if cards:
40 c = cards[0]
41 g.process_action(LaunchCard(attacker, [victim], c))
42 else:
43 g.process_action(Damage(src, attacker, 1))
45 return True
47 def cond(self, cl):
48 if len(cl) != 1: return False
49 c = cl[0]
50 if not c.associated_action: return False
51 return issubclass(c.associated_action, Attack)
53 def ask_for_action_verify(self, p, cl, tl):
54 attacker, victim = self.target_list
55 return LaunchCard(attacker, [victim], cl[0]).can_fire()
57 def is_valid(self):
58 tags = self.source.tags
59 if tags['turn_count'] <= tags['darkness_tag']:
60 return False
62 attacker, victim = self.target_list
63 if not LaunchCard(attacker, [victim], AttackCard()).can_fire():
64 return False
66 return True
69class Darkness(Skill):
70 associated_action = DarknessAction
71 skill_category = ['character', 'active']
72 target = t_OtherN(2)
73 usage = 'drop'
75 def check(self):
76 cl = self.associated_cards
77 if not(cl and len(cl) == 1):
78 return False
80 if cl[0].is_card(Skill):
81 return False
83 return True
86class DarknessKOF(Skill):
87 associated_action = None
88 skill_category = ['character', 'passive']
89 target = t_None()
92class DarknessKOFAction(UserAction):
93 def apply_action(self):
94 tgt = self.target
95 g = self.game
96 tgt.tags['darkness_kof_tag'] = max(g.turn_count, 1)
97 return True
100class DarknessKOFLimit(ActionShootdown):
101 pass
104class DarknessKOFHandler(THBEventHandler):
105 interested = ['character_debut', 'action_shootdown']
106 game: THBattleKOF
108 def handle(self, evt_type, arg):
109 if evt_type == 'character_debut':
110 old, new = arg
111 if new.has_skill(DarknessKOF):
112 g = self.game
113 g.process_action(DarknessKOFAction(new, new))
115 elif evt_type == 'action_shootdown' and isinstance(arg, LaunchCard):
116 src = arg.source
117 if not src:
118 return arg
120 g = self.game
121 opp = g.get_opponent(arg.source)
122 if opp.tags['darkness_kof_tag'] < g.turn_count:
123 return arg
125 card = arg.card
126 if not card.is_card(PhysicalCard) and 'treat_as' not in card.category:
127 return arg
129 if card.is_card(RejectCard):
130 return arg
132 # XXX: DollControl's second target do not count as target
133 # but in KOF the second target is always the launcher,
134 # and never be the opp, so the handle can be same.
135 if opp in arg.target_list:
136 raise DarknessKOFLimit
138 return arg
141class Cheating(Skill):
142 associated_action = None
143 skill_category = ['character', 'passive', 'compulsory']
144 target = t_None()
147class CheatingDrawCards(DrawCards):
148 pass
151class CheatingHandler(THBEventHandler):
152 interested = ['action_apply']
153 execute_before = ['CiguateraHandler']
155 def handle(self, evt_type, act):
156 if evt_type == 'action_apply' and isinstance(act, FinalizeStage):
157 tgt = act.target
158 if tgt.has_skill(Cheating) and not tgt.dead:
159 g = self.game
160 g.process_action(CheatingDrawCards(tgt, 1))
161 return act
164@register_character_to('common', '-kof')
165class Rumia(Character):
166 skills = [Darkness, Cheating]
167 eventhandlers = [CheatingHandler]
168 maxlife = 3
171@register_character_to('kof')
172class RumiaKOF(Character):
173 skills = [DarknessKOF, Cheating]
174 eventhandlers = [DarknessKOFHandler, CheatingHandler]
175 maxlife = 3