Coverage for thb/meta/common.py : 67%
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 Any, Dict, Optional, TYPE_CHECKING, Type, Union
7# -- third party --
8# -- own --
9from game.base import GameViralContext
11# -- typing --
12if TYPE_CHECKING:
13 from thb.mode import THBattle
14 from thb.characters.base import Character # noqa: F401
17# -- code --
18UI_META: Dict[type, Any] = {}
21class UIMetaAccessor(object):
22 def __init__(self, cls):
23 self.for_cls = cls
24 self.mro = cls.mro()
26 def __getattr__(self, name):
27 for cls in self.mro:
28 if cls not in UI_META:
29 continue
31 try:
32 val = getattr(UI_META[cls](), name)
33 return val
34 except AttributeError:
35 pass
37 raise AttributeError(f'{self.for_cls.__name__}.{name}')
40def ui_meta(for_cls: type):
41 def decorate(cls: type):
42 name = cls.__name__
43 if name in UI_META: 43 ↛ 44line 43 didn't jump to line 44, because the condition on line 43 was never true
44 raise Exception(f'{name} ui_meta redefinition!')
46 cls = type(name, (cls, UIMetaBase), {})
48 # Type info is handled by plugin
49 for_cls.ui_meta = UIMetaAccessor(for_cls) # type: ignore
50 UI_META[for_cls] = cls
51 return cls
52 return decorate
55# -----BEGIN COMMON FUNCTIONS-----
56class UIMetaBase(GameViralContext):
57 game: THBattle
59 def __init__(self):
60 g = self.game
61 me = g.runner.core.game.theone_of(g)
62 try:
63 self.me = g.find_character(me)
64 except IndexError:
65 self.me = me
67 def my_turn(self):
68 g = self.game
69 me = self.me
70 try:
71 act = g.action_stack[-1]
72 except IndexError:
73 return False
75 from thb import actions
76 if not isinstance(act, actions.ActionStage):
77 return False
79 if act.target is not me: return False 79 ↛ exitline 79 didn't return from function 'my_turn', because the return on line 79 wasn't executed
81 if not act.in_user_input: return False 81 ↛ exitline 81 didn't return from function 'my_turn', because the return on line 81 wasn't executed
83 return True
85 def limit1_skill_used(self, tag):
86 me = self.me
87 t = me.tags
88 return t[tag] >= t['turn_count']
90 def clickable(self):
91 return False
93 def is_action_valid(self, c, tl):
94 return (False, 'BUG!')
96 def card_desc(self, c):
97 if isinstance(c, (list, tuple)):
98 return '、'.join([self.card_desc(i) for i in c])
100 from thb.cards.base import Card, HiddenCard
101 if c.is_card(HiddenCard): return '一张牌' 101 ↛ exitline 101 didn't return from function 'card_desc', because the return on line 101 wasn't executed
103 if c.suit == Card.SPADE:
104 suit = '|r♠'
105 elif c.suit == Card.HEART:
106 suit = '|r|cb03a11ff♥'
107 elif c.suit == Card.CLUB:
108 suit = '|r♣'
109 elif c.suit == Card.DIAMOND: 109 ↛ 111line 109 didn't jump to line 111, because the condition on line 109 was never false
110 suit = '|r|cb03a11ff♦'
111 elif c.suit == Card.NOTSET:
112 suit = '|r '
113 else:
114 suit = '|r错误'
116 num = ' A23456789_JQK'[c.number]
117 if num == '_': num = '10'
118 return suit + num + ' |G%s|r' % c.ui_meta.name
120 def build_handcard(self, cardcls, p=None):
121 me = self.me
122 from thb.cards.base import CardList
123 cl = CardList(p or me, 'cards')
124 c = cardcls()
125 c.move_to(cl)
126 return c
128 def char_desc(self, ch: Union[Character, Type[Character]]):
129 m = ch.ui_meta
131 cls: Type[Character]
132 obj: Optional[Character]
134 if isinstance(ch, Character):
135 cls, obj = ch.__class__, ch
136 else:
137 cls, obj = ch, None
139 rst = []
140 rst.append('|DB%s %s 体力:%s|r' % (m.title, m.name, cls.maxlife))
141 skills = list(cls.skills)
142 if hasattr(cls, 'boss_skills'):
143 skills.extend(cls.boss_skills)
145 if obj:
146 skills.extend([
147 c for c in obj.skills
148 if 'character' in c.skill_category and c not in skills
149 ])
151 for s in skills:
152 sm = s.ui_meta
153 rst.append('|G%s|r:%s' % (sm.name, sm.description))
155 notes = getattr(m, 'notes', '')
156 if notes:
157 rst.append(notes)
159 tail = ['%s:%s' % i for i in [
160 ('画师', m.illustrator),
161 ('CV', m.cv),
162 ('人物设计', m.designer),
163 ] if i[1]]
165 if tail:
166 rst.append('|DB(%s)|r' % ','.join(tail))
168 return '\n\n'.join(rst)