Hide keyboard shortcuts

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 

3 

4# -- stdlib -- 

5from typing import TYPE_CHECKING, cast 

6 

7# -- third party -- 

8# -- own -- 

9from thb.actions import Damage, DropCards, FatetellAction, LaunchCard, random_choose_card 

10from thb.cards.base import Card, Skill, VirtualCard 

11from thb.cards.classes import AttackCard, BaseAttack, InevitableAttack, RedUFOSkill, TreatAs, t_None 

12from thb.characters.base import Character, register_character_to 

13from thb.inputlets import ChooseOptionInputlet, ChoosePeerCardInputlet 

14from thb.mode import THBEventHandler, THBAction 

15from utils.misc import classmix 

16 

17# -- typing -- 

18if TYPE_CHECKING: 

19 from thb.thbkof import THBattleKOF # noqa: F401 

20 

21 

22# -- code -- 

23class Assault(RedUFOSkill): 

24 skill_category = ['character', 'passive', 'compulsory'] 

25 increment = 1 

26 

27 

28class AssaultKOF(Skill): 

29 associated_action = None 

30 skill_category = ['character', 'passive'] 

31 target = t_None() 

32 

33 

34class AssaultAttack(TreatAs, VirtualCard): 

35 treat_as = AttackCard 

36 

37 

38class AssaultKOFHandler(THBEventHandler): 

39 interested = ['character_debut'] 

40 game: THBattleKOF 

41 

42 def handle(self, evt_type, arg): 

43 if evt_type == 'character_debut': 

44 old, new = arg 

45 if not new.has_skill(AssaultKOF): 

46 return arg 

47 

48 g = self.game 

49 op = g.get_opponent(new) 

50 lc = LaunchCard(new, [op], AssaultAttack(new)) 

51 if not lc.can_fire(): 

52 return arg 

53 

54 if g.user_input([new], ChooseOptionInputlet(self, (False, True))): 

55 g.process_action(lc) 

56 

57 return arg 

58 

59 

60class FreakingPower(Skill): 

61 associated_action = None 

62 skill_category = ['character', 'passive'] 

63 target = t_None() 

64 

65 

66class FreakingPowerAction(FatetellAction): 

67 def __init__(self, atkact): 

68 self.atkact = atkact 

69 self.source = atkact.source 

70 self.target = atkact.target 

71 self.fatetell_target = atkact.source 

72 

73 def fatetell_action(self, ft): 

74 act = self.atkact 

75 if ft.succeeded: 

76 act.__class__ = classmix(InevitableAttack, act.__class__) 

77 else: 

78 act._['freaking_power'] = True 

79 

80 return True 

81 

82 @staticmethod 

83 def fatetell_cond(c): 

84 return c.color == Card.RED 

85 

86 

87class FreakingPowerHandler(THBEventHandler): 

88 interested = ['action_after', 'action_before'] 

89 execute_before = ['AyaRoundfanHandler'] 

90 

91 def handle(self, evt_type, act): 

92 if evt_type == 'action_before' and isinstance(act, BaseAttack) and not act._['freaking_power']: 

93 src = act.source 

94 g = self.game 

95 if not src.has_skill(FreakingPower): return act 

96 if not g.user_input([src], ChooseOptionInputlet(self, (False, True))): 

97 return act 

98 tgt = act.target 

99 g.process_action(FreakingPowerAction(act)) 

100 

101 elif evt_type == 'action_after' and isinstance(act, Damage): 

102 g = self.game 

103 

104 if act.cancelled: return act 

105 

106 pact = cast(THBAction, g.action_stack[-1]) 

107 if not pact._['freaking_power']: 

108 return act 

109 

110 src, tgt = pact.source, act.target 

111 if tgt.dead: return act 

112 

113 if not (tgt.cards or tgt.showncards or tgt.equips): 

114 return act 

115 

116 catnames = ('cards', 'showncards', 'equips') 

117 card = g.user_input([src], ChoosePeerCardInputlet(self, tgt, catnames)) 

118 card = card or random_choose_card(g, [tgt.cards, tgt.showncards, tgt.equips]) 

119 if card: 

120 g.players.exclude(tgt).reveal(card) 

121 g.process_action(DropCards(src, tgt, [card])) 

122 

123 return act 

124 

125 

126@register_character_to('common', '-kof') 

127class Yugi(Character): 

128 skills = [Assault, FreakingPower] 

129 eventhandlers = [FreakingPowerHandler] 

130 maxlife = 4 

131 

132 

133@register_character_to('kof') 

134class YugiKOF(Character): 

135 skills = [AssaultKOF, FreakingPower] 

136 eventhandlers = [AssaultKOFHandler, FreakingPowerHandler] 

137 maxlife = 4