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 -- 

5# -- third party -- 

6# -- own -- 

7from game.base import ActionShootdown 

8from thb.actions import Damage, DrawCards, FinalizeStage, LaunchCard, UserAction, user_choose_cards 

9from thb.cards.base import PhysicalCard, Skill, t_None, t_OtherN 

10from thb.cards.basic import Attack 

11from thb.cards.definition import AttackCard, RejectCard 

12from thb.cards.spellcard import BaseDuel 

13from thb.characters.base import Character, register_character_to 

14from thb.mode import THBEventHandler 

15 

16 

17# -- code -- 

18class DarknessDuel(BaseDuel): 

19 pass 

20 

21 

22class DarknessAction(UserAction): 

23 card_usage = 'launch' 

24 

25 def apply_action(self): 

26 attacker, victim = self.target_list 

27 src = self.source 

28 g = self.game 

29 tags = self.source.tags 

30 tags['darkness_tag'] = tags['turn_count'] 

31 

32 cards = user_choose_cards(self, attacker, ('cards', 'showncards')) 

33 if cards: 

34 c = cards[0] 

35 g.process_action(LaunchCard(attacker, [victim], c)) 

36 else: 

37 g.process_action(Damage(src, attacker, 1)) 

38 

39 return True 

40 

41 def cond(self, cl): 

42 if len(cl) != 1: return False 

43 c = cl[0] 

44 if not c.associated_action: return False 

45 return issubclass(c.associated_action, Attack) 

46 

47 def ask_for_action_verify(self, p, cl, tl): 

48 attacker, victim = self.target_list 

49 return LaunchCard(attacker, [victim], cl[0]).can_fire() 

50 

51 def is_valid(self): 

52 tags = self.source.tags 

53 if tags['turn_count'] <= tags['darkness_tag']: 

54 return False 

55 

56 attacker, victim = self.target_list 

57 if not LaunchCard(attacker, [victim], AttackCard()).can_fire(): 

58 return False 

59 

60 return True 

61 

62 

63class Darkness(Skill): 

64 associated_action = DarknessAction 

65 skill_category = ['character', 'active'] 

66 target = t_OtherN(2) 

67 usage = 'drop' 

68 

69 def check(self): 

70 cl = self.associated_cards 

71 if not(cl and len(cl) == 1): 

72 return False 

73 

74 if cl[0].is_card(Skill): 74 ↛ 75line 74 didn't jump to line 75, because the condition on line 74 was never true

75 return False 

76 

77 return True 

78 

79 

80class DarknessKOF(Skill): 

81 associated_action = None 

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

83 target = t_None() 

84 

85 

86class DarknessKOFAction(UserAction): 

87 def apply_action(self): 

88 tgt = self.target 

89 g = self.game 

90 tgt.tags['darkness_kof_tag'] = max(g.turn_count, 1) 

91 return True 

92 

93 

94class DarknessKOFLimit(ActionShootdown): 

95 pass 

96 

97 

98class DarknessKOFHandler(THBEventHandler): 

99 interested = ['character_debut', 'action_shootdown'] 

100 

101 def handle(self, evt_type, arg): 

102 if evt_type == 'character_debut': 

103 old, new = arg 

104 if new.has_skill(DarknessKOF): 

105 g = self.game 

106 g.process_action(DarknessKOFAction(new, new)) 

107 

108 elif evt_type == 'action_shootdown' and isinstance(arg, LaunchCard): 

109 src = arg.source 

110 if not src: 110 ↛ 111line 110 didn't jump to line 111, because the condition on line 110 was never true

111 return arg 

112 

113 g = self.game 

114 opp = g.get_opponent(arg.source) 

115 if opp.tags['darkness_kof_tag'] < g.turn_count: 115 ↛ 116line 115 didn't jump to line 116, because the condition on line 115 was never true

116 return arg 

117 

118 card = arg.card 

119 if not card.is_card(PhysicalCard) and 'treat_as' not in card.category: 

120 return arg 

121 

122 if card.is_card(RejectCard): 

123 return arg 

124 

125 # XXX: DollControl's second target do not count as target 

126 # but in KOF the second target is always the launcher, 

127 # and never be the opp, so the handle can be same. 

128 if opp in arg.target_list: 

129 raise DarknessKOFLimit 

130 

131 return arg 

132 

133 

134class Cheating(Skill): 

135 associated_action = None 

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

137 target = t_None() 

138 

139 

140class CheatingDrawCards(DrawCards): 

141 pass 

142 

143 

144class CheatingHandler(THBEventHandler): 

145 interested = ('action_apply',) 

146 execute_before = ('CiguateraHandler', ) 

147 

148 def handle(self, evt_type, act): 

149 if evt_type == 'action_apply' and isinstance(act, FinalizeStage): 

150 tgt = act.target 

151 if tgt.has_skill(Cheating) and not tgt.dead: 

152 g = self.game 

153 g.process_action(CheatingDrawCards(tgt, 1)) 

154 return act 

155 

156 

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

158class Rumia(Character): 

159 skills = [Darkness, Cheating] 

160 eventhandlers = [CheatingHandler] 

161 maxlife = 3 

162 

163 

164@register_character_to('kof') 

165class RumiaKOF(Character): 

166 skills = [DarknessKOF, Cheating] 

167 eventhandlers = [DarknessKOFHandler, CheatingHandler] 

168 maxlife = 3