Coverage for thb/meta/common.py : 19%
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, Sequence
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
15 from thb.cards.base import Card # noqa: F401
18# -- code --
19UI_META: Dict[type, Any] = {}
22class UIMetaAccessor(object):
23 def __init__(self, cls):
24 self.for_cls = cls
25 self.mro = cls.mro()
27 def __getattr__(self, name):
28 for cls in self.mro:
29 if cls not in UI_META:
30 continue
32 try:
33 val = getattr(UI_META[cls](), name)
34 return val
35 except AttributeError:
36 pass
38 raise AttributeError(f'{self.for_cls.__name__}.{name}')
41def ui_meta(for_cls: type):
42 def decorate(cls: type):
43 name = cls.__name__
44 if name in UI_META: 44 ↛ 45line 44 didn't jump to line 45, because the condition on line 44 was never true
45 raise Exception(f'{name} ui_meta redefinition!')
47 cls = type(name, (cls, UIMetaBase), {})
49 # Type info is handled by plugin
50 for_cls.ui_meta = UIMetaAccessor(for_cls) # type: ignore
51 UI_META[for_cls] = cls
52 return cls
53 return decorate
56# -----BEGIN COMMON FUNCTIONS-----
57class UIMetaBase(GameViralContext):
58 game: THBattle
60 def __init__(self):
61 g = self.game
62 me = g.runner.core.game.theone_of(g)
63 try:
64 self.me = g.find_character(me)
65 except IndexError:
66 self.me = me
68 def my_turn(self):
69 g = self.game
70 me = self.me
71 try:
72 act = g.action_stack[-1]
73 except IndexError:
74 return False
76 from thb import actions
77 if not isinstance(act, actions.ActionStage):
78 return False
80 if act.target is not me: return False
82 if not act.in_user_input: return False
84 return True
86 def limit1_skill_used(self, tag):
87 me = self.me
88 t = me.tags
89 return t[tag] >= t['turn_count']
91 def clickable(self):
92 return False
94 def is_action_valid(self, c, tl):
95 return (False, 'BUG!')
97 def card_desc(self, c):
98 if isinstance(c, (list, tuple)):
99 return '、'.join([self.card_desc(i) for i in c])
101 from thb.cards.base import Card, HiddenCard
102 if c.is_card(HiddenCard): return '一张牌'
104 if c.suit == Card.SPADE:
105 suit = '|r♠'
106 elif c.suit == Card.HEART:
107 suit = '|r|cb03a11ff♥'
108 elif c.suit == Card.CLUB:
109 suit = '|r♣'
110 elif c.suit == Card.DIAMOND:
111 suit = '|r|cb03a11ff♦'
112 elif c.suit == Card.NOTSET:
113 suit = '|r '
114 else:
115 suit = '|r错误'
117 num = ' A23456789_JQK'[c.number]
118 if num == '_': num = '10'
119 return suit + num + ' |G%s|r' % c.ui_meta.name
121 def build_handcard(self, cardcls, p=None):
122 me = self.me
123 from thb.cards.base import CardList
124 cl = CardList(p or me, 'cards')
125 c = cardcls()
126 c.move_to(cl)
127 return c
129 def accept_cards(self, cl: Sequence[Card]):
130 g = self.game
131 try:
132 act = g.hybrid_stack[-1]
133 if act.cond(cl): # type: ignore
134 return True
136 except (IndexError, AttributeError):
137 pass
139 return False
141 def char_desc(self, ch: Union[Character, Type[Character]]):
142 m = ch.ui_meta
144 cls: Type[Character]
145 obj: Optional[Character]
147 if isinstance(ch, Character):
148 cls, obj = ch.__class__, ch
149 else:
150 cls, obj = ch, None
152 rst = []
153 rst.append('|DB%s %s 体力:%s|r' % (m.title, m.name, cls.maxlife))
154 skills = list(cls.skills)
155 if hasattr(cls, 'boss_skills'):
156 skills.extend(cls.boss_skills)
158 if obj:
159 skills.extend([
160 c for c in obj.skills
161 if 'character' in c.skill_category and c not in skills
162 ])
164 for s in skills:
165 sm = s.ui_meta
166 rst.append('|G%s|r:%s' % (sm.name, sm.description))
168 notes = getattr(m, 'notes', '')
169 if notes:
170 rst.append(notes)
172 tail = ['%s:%s' % i for i in [
173 ('画师', m.illustrator),
174 ('CV', m.cv),
175 ('人物设计', m.designer),
176 ] if i[1]]
178 if tail:
179 rst.append('|DB(%s)|r' % ','.join(tail))
181 return '\n\n'.join(rst)