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 Any, Dict, Optional, TYPE_CHECKING, Type, Union 

6 

7# -- third party -- 

8# -- own -- 

9from game.base import GameViralContext 

10 

11# -- typing -- 

12if TYPE_CHECKING: 

13 from thb.mode import THBattle 

14 from thb.characters.base import Character # noqa: F401 

15 

16 

17# -- code -- 

18UI_META: Dict[type, Any] = {} 

19 

20 

21class UIMetaAccessor(object): 

22 def __init__(self, cls): 

23 self.for_cls = cls 

24 self.mro = cls.mro() 

25 

26 def __getattr__(self, name): 

27 for cls in self.mro: 27 ↛ 34line 27 didn't jump to line 34, because the loop on line 27 didn't complete

28 try: 

29 val = getattr(UI_META[cls](), name) 

30 return val 

31 except AttributeError: 

32 pass 

33 

34 raise AttributeError(f'{self.cls.__name__}.{name}') 

35 

36 

37def ui_meta(for_cls: type): 

38 def decorate(cls: type): 

39 name = cls.__name__ 

40 if name in UI_META: 40 ↛ 41line 40 didn't jump to line 41, because the condition on line 40 was never true

41 raise Exception(f'{name} ui_meta redefinition!') 

42 

43 cls = type(name, (cls, UIMetaBase), {}) 

44 

45 # Type info is handled by plugin 

46 for_cls.ui_meta = UIMetaAccessor(for_cls) # type: ignore 

47 UI_META[for_cls] = cls 

48 return cls 

49 return decorate 

50 

51 

52# -----BEGIN COMMON FUNCTIONS----- 

53class UIMetaBase(GameViralContext): 

54 game: THBattle 

55 

56 def __init__(self): 

57 g = self.game 

58 me = g.runner.core.game.theone_of(g) 

59 try: 

60 self.me = g.find_character(me) 

61 except IndexError: 

62 self.me = me 

63 

64 def my_turn(self): 

65 g = self.game 

66 try: 

67 act = g.action_stack[-1] 

68 except IndexError: 

69 return False 

70 

71 from thb import actions 

72 if not isinstance(act, actions.ActionStage): 

73 return False 

74 

75 if act.target is not g.me: return False 

76 

77 if not act.in_user_input: return False 

78 

79 return True 

80 

81 def limit1_skill_used(self, tag): 

82 g = self.game 

83 t = g.me.tags 

84 return t[tag] >= t['turn_count'] 

85 

86 def clickable(self): 

87 return False 

88 

89 def is_action_valid(self, c, tl): 

90 return (False, 'BUG!') 

91 

92 def card_desc(self, c): 

93 if isinstance(c, (list, tuple)): 

94 return '、'.join([self.card_desc(i) for i in c]) 

95 

96 from thb.cards.base import Card, HiddenCard 

97 if c.is_card(HiddenCard): return '一张牌' 

98 

99 if c.suit == Card.SPADE: 

100 suit = '|r♠' 

101 elif c.suit == Card.HEART: 

102 suit = '|r|cb03a11ff♥' 

103 elif c.suit == Card.CLUB: 

104 suit = '|r♣' 

105 elif c.suit == Card.DIAMOND: 

106 suit = '|r|cb03a11ff♦' 

107 elif c.suit == Card.NOTSET: 

108 suit = '|r ' 

109 else: 

110 suit = '|r错误' 

111 

112 num = ' A23456789_JQK'[c.number] 

113 if num == '_': num = '10' 

114 return suit + num + ' |G%s|r' % c.ui_meta.name 

115 

116 def build_handcard(self, cardcls, p=None): 

117 g = self.game 

118 from thb.cards.base import CardList 

119 cl = CardList(p or g.me, 'cards') 

120 c = cardcls() 

121 c.move_to(cl) 

122 return c 

123 

124 def char_desc(self, ch: Union[Character, Type[Character]]): 

125 m = ch.ui_meta 

126 

127 cls: Type[Character] 

128 obj: Optional[Character] 

129 

130 if isinstance(ch, Character): 

131 cls, obj = ch.__class__, ch 

132 else: 

133 cls, obj = ch, None 

134 

135 rst = [] 

136 rst.append('|DB%s %s 体力:%s|r' % (m.title, m.name, cls.maxlife)) 

137 skills = list(cls.skills) 

138 if hasattr(cls, 'boss_skills'): 

139 skills.extend(cls.boss_skills) 

140 

141 if obj: 

142 skills.extend([ 

143 c for c in obj.skills 

144 if 'character' in c.skill_category and c not in skills 

145 ]) 

146 

147 for s in skills: 

148 sm = s.ui_meta 

149 rst.append('|G%s|r:%s' % (sm.name, sm.description)) 

150 

151 notes = getattr(m, 'notes', '') 

152 if notes: 

153 rst.append(notes) 

154 

155 tail = ['%s:%s' % i for i in [ 

156 ('画师', m.illustrator), 

157 ('CV', m.cv), 

158 ('人物设计', m.designer), 

159 ] if i[1]] 

160 

161 if tail: 

162 rst.append('|DB(%s)|r' % ','.join(tail)) 

163 

164 return '\n\n'.join(rst)