Coverage for thb/meta/cards/equipment.py : 73%
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 Optional
6import random
8# -- third party --
9# -- own --
10from thb import actions
11from thb.actions import ttags
12from thb.cards import definition, equipment
13from thb.cards.base import Card
14from thb.meta.common import ui_meta
15from utils.misc import BatchList
18# -- code --
19def equip_iav(self, c, tl):
20 return (True, '配上好装备,不再掉节操!')
23def suppress_launch_card_effect_string(self, act):
24 return None
27@ui_meta(equipment.WearEquipmentAction)
28class WearEquipmentAction:
30 def effect_string(self, act):
31 return '|G【%s】|r装备了%s。' % (
32 act.target.ui_meta.name,
33 self.card_desc(act.associated_card),
34 )
37@ui_meta(equipment.WeaponReforgeHandler)
38class WeaponReforgeHandler:
39 choose_option_prompt = '你希望重铸这张牌么?'
40 choose_option_buttons = (('重铸', True), ('装备', False))
43@ui_meta(equipment.ReforgeWeapon)
44class ReforgeWeapon:
45 def effect_string(self, act):
46 return '|G【%s】|r重铸了%s。' % (
47 act.target.ui_meta.name,
48 self.card_desc(act.card),
49 )
52@ui_meta(definition.OpticalCloakCard)
53class OpticalCloakCard:
54 # action_stage meta
55 name = '光学迷彩'
56 image = 'thb-card-opticalcloak'
57 image_small = 'thb-card-small-opticalcloak'
58 description = (
59 '|R光学迷彩|r\n\n'
60 '装备后:当你需要使用或打出|G擦弹|r时,可以进行一次判定,若结果为红,视为你使用或打出了一张|G擦弹|r。\n\n'
61 '|DB(画师:霏茶,CV:shourei小N)|r'
62 )
64 is_action_valid = equip_iav
65 effect_string = suppress_launch_card_effect_string
68@ui_meta(equipment.OpticalCloakSkill)
69class OpticalCloakSkill:
70 # Skill
71 name = '光学迷彩'
73 def sound_effect(self, act):
74 return 'thb-cv-card_opticalcloak'
76 def effect_string(self, act):
77 return definition.GrazeCard.ui_meta.effect_string(act)
80@ui_meta(equipment.OpticalCloakHandler)
81class OpticalCloakHandler:
82 # choose_option
83 choose_option_buttons = (('发动', True), ('不发动', False))
84 choose_option_prompt = '你要发动【光学迷彩】吗?'
87@ui_meta(equipment.OpticalCloak)
88class OpticalCloak:
89 fatetell_display_name = '光学迷彩'
91 def effect_string_before(self, act):
92 return '|G【%s】|r祭起了|G光学迷彩|r…' % (
93 act.target.ui_meta.name,
94 )
96 def effect_string(self, act):
97 if act.succeeded:
98 return '效果拔群!'
99 else:
100 return '但是被看穿了…'
103@ui_meta(definition.MomijiShieldCard)
104class MomijiShieldCard:
105 # action_stage meta
106 name = '天狗盾'
107 image = 'thb-card-momijishield'
108 image_small = 'thb-card-small-momijishield'
109 description = (
110 '|R天狗盾|r\n\n'
111 '装备后:黑色|G弹幕|r对你无效。\n\n'
112 '|DB(画师:霏茶)|r'
113 )
115 is_action_valid = equip_iav
116 effect_string = suppress_launch_card_effect_string
119@ui_meta(equipment.MomijiShieldSkill)
120class MomijiShieldSkill:
121 # Skill
122 name = '天狗盾'
125@ui_meta(equipment.MomijiShield)
126class MomijiShield:
127 def effect_string(self, act):
128 return '被|G天狗盾|r挡下了…'
130 def sound_effect(self, act):
131 return 'thb-cv-card_momijishield'
134ufo_desc = (
135 '|R%s|r\n\n'
136 'UFO用来改变自己与其他角色之间的距离。\n'
137 '|B|R>> |r红色UFO为进攻用,当你计算和其他角色的距离时,在原有的基础上减少相应距离。两名角色之间的距离至少为1。\n'
138 '|B|R>> |r绿色UFO为防守用,当其他角色计算和你的距离时,在原有的基础上增加相应距离。\n'
139 '|B|R>> |r你可以同时装备两种UFO。\n\n'
140 '|DB(画师:霏茶)|r'
141)
144@ui_meta(definition.GreenUFOCard)
145class GreenUFOCard:
146 # action_stage meta
147 name = '绿色UFO'
148 image = 'thb-card-greenufo'
149 image_small = 'thb-card-small-greenufo'
150 description = ufo_desc % name
152 is_action_valid = equip_iav
153 effect_string = suppress_launch_card_effect_string
156@ui_meta(equipment.GreenUFOSkill)
157class GreenUFOSkill:
158 # Skill
159 name = '绿色UFO'
160 no_display = True
163@ui_meta(definition.RedUFOCard)
164class RedUFOCard:
165 # action_stage meta
166 name = '红色UFO'
167 image = 'thb-card-redufo'
168 image_small = 'thb-card-small-redufo'
169 description = ufo_desc % name
171 is_action_valid = equip_iav
172 effect_string = suppress_launch_card_effect_string
175@ui_meta(equipment.RedUFOSkill)
176class RedUFOSkill:
177 # Skill
178 name = '红色UFO'
179 no_display = True
182@ui_meta(definition.RoukankenCard)
183class RoukankenCard:
184 # action_stage meta
185 name = '楼观剑'
186 image = 'thb-card-roukanken'
187 image_small = 'thb-card-small-roukanken'
188 description = (
189 '|R楼观剑|r\n'
190 '\n'
191 '攻击范围3,装备后:你使用的|G弹幕|r无视防具。\n'
192 '\n'
193 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
194 '\n'
195 '|DB(画师:霏茶)|r'
196 )
197 is_action_valid = equip_iav
198 effect_string = suppress_launch_card_effect_string
201@ui_meta(equipment.RoukankenSkill)
202class RoukankenSkill:
203 # Skill
204 name = '楼观剑'
207@ui_meta(equipment.Roukanken)
208class Roukanken:
209 def effect_string_apply(self, act):
210 return '没有什么防具是|G楼观剑|r斩不断的!'
212 def sound_effect(self, act):
213 return 'thb-cv-card_roukanken'
216@ui_meta(definition.ElementalReactorCard)
217class ElementalReactorCard:
218 # action_stage meta
219 name = '八卦炉'
220 image = 'thb-card-reactor'
221 image_small = 'thb-card-small-reactor'
222 description = (
223 '|R八卦炉|r\n'
224 '\n'
225 '攻击范围1,装备后:出牌阶段你使用|G弹幕|r时不消耗干劲。\n'
226 '\n'
227 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
228 '\n'
229 '|DB(画师:霏茶)|r'
230 )
232 is_action_valid = equip_iav
233 effect_string = suppress_launch_card_effect_string
236@ui_meta(equipment.ElementalReactorSkill)
237class ElementalReactorSkill:
238 # Skill
239 name = '八卦炉'
242@ui_meta(definition.UmbrellaCard)
243class UmbrellaCard:
244 # action_stage meta
245 name = '阳伞'
246 image = 'thb-card-umbrella'
247 image_small = 'thb-card-small-umbrella'
248 description = (
249 '|R阳伞|r\n\n'
250 '装备后:符卡效果造成的伤害对你无效。\n\n'
251 '|DB(画师:霏茶)|r'
252 )
254 is_action_valid = equip_iav
255 effect_string = suppress_launch_card_effect_string
258@ui_meta(equipment.UmbrellaSkill)
259class UmbrellaSkill:
260 # Skill
261 name = '紫的阳伞'
264@ui_meta(equipment.UmbrellaEffect)
265class UmbrellaEffect:
266 def effect_string_before(self, act):
267 a = act.action
268 dmg = act.damage_act
269 card = getattr(a, 'associated_card', None)
270 if card and card.associated_action and isinstance(a, card.associated_action):
271 # Some skills changes action
272 s = '|G%s|r' % card.ui_meta.name
273 else:
274 s = ''
276 return '|G【%s】|r受到的%s效果被|G阳伞|r挡下了…' % (
277 dmg.target.ui_meta.name, s,
278 )
280 def sound_effect(self, act):
281 return 'thb-cv-card_umbrella'
284@ui_meta(definition.GungnirCard)
285class GungnirCard:
286 # action_stage meta
287 name = '冈格尼尔'
288 image = 'thb-card-gungnir'
289 image_small = 'thb-card-small-gungnir'
290 description = (
291 '|R冈格尼尔|r\n'
292 '\n'
293 '攻击范围3,装备后:你可以将两张手牌当|G弹幕|r使用或打出。\n'
294 '\n'
295 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
296 '\n'
297 '|DB(画师:霏茶)|r'
298 )
300 is_action_valid = equip_iav
301 effect_string = suppress_launch_card_effect_string
304@ui_meta(equipment.GungnirSkill)
305class GungnirSkill:
306 # Skill
307 name = '冈格尼尔'
309 def clickable(self):
310 me = self.me
311 return self.accept_cards([equipment.GungnirSkill(me)])
313 def is_complete(self, skill):
314 me = self.me
315 assert skill.is_card(equipment.GungnirSkill)
316 acards = skill.associated_cards
317 if len(acards) != 2:
318 return (False, '请选择2张手牌!')
319 elif any(c.resides_in not in (me.cards, me.showncards) for c in acards):
320 return (False, '只能使用手牌发动!')
321 return (True, '反正这条也看不到,偷个懒~~~')
323 def is_action_valid(self, sk, tl):
324 assert sk.is_card(equipment.GungnirSkill)
325 rst, reason = self.is_complete(sk)
326 if not rst:
327 return (rst, reason)
328 else:
329 return definition.AttackCard().ui_meta.is_action_valid(sk, tl)
331 def effect_string(self, act):
332 # for LaunchCard.effect_string
333 source = act.source
334 target = act.target
335 s = '|G【%s】|r发动了|G冈格尼尔|r之枪,将两张牌当作|G弹幕|r对|G【%s】|r使用。' % (
336 source.ui_meta.name,
337 target.ui_meta.name,
338 )
339 return s
341 def sound_effect(self, act):
342 return definition.AttackCard.ui_meta.sound_effect(act)
345@ui_meta(definition.ScarletRhapsodyCard)
346class ScarletRhapsodyCard:
347 # action_stage meta
348 name = '绯想之剑'
349 image = 'thb-card-scarletrhapsodysword'
350 image_small = 'thb-card-small-scarletrhapsodysword'
351 description = (
352 '|R绯想之剑|r\n'
353 '\n'
354 '攻击范围4,装备后:当你使用的|G弹幕|r是你的最后一张手牌时,你可以为此|G弹幕|r指定至多三名目标。\n'
355 '\n'
356 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
357 '\n'
358 '|DB(画师:霏茶,CV:VV)|r'
359 )
361 is_action_valid = equip_iav
362 effect_string = suppress_launch_card_effect_string
365@ui_meta(equipment.ScarletRhapsodySkill)
366class ScarletRhapsodySkill:
367 # Skill
368 name = '绯想之剑'
370 def clickable(self):
371 g = self.game
372 me = self.me
373 try:
374 act = g.action_stack[-1]
375 if isinstance(act, actions.ActionStage):
376 return act.target is me
378 except IndexError:
379 pass
381 return False
383 def is_action_valid(self, sk, tl):
384 assert sk.is_card(equipment.ScarletRhapsodySkill)
385 if not sk.check():
386 return (False, '请选择你的最后一张【弹幕】!')
387 else:
388 if not tl:
389 return (False, '请选择弹幕的目标(最多可以选择3名玩家)')
391 if self.me in tl:
392 return (True, '您真的要自残么?!')
393 else:
394 return (True, '全人类的绯想天!')
396 def effect_string(self, act: actions.LaunchCard) -> Optional[str]:
397 # for LaunchCard.ui_meta.effect_string
398 src = act.source
399 tl = BatchList(act.target_list)
401 return '全人类的绯想天,当然不能只打一个!于是|G【%s】|r选了|G【%s】|r一共%d个目标!' % (
402 src.ui_meta.name,
403 '】|r、|G【'.join(tl.ui_meta.name),
404 len(tl),
405 )
407 def sound_effect(self, act):
408 return 'thb-cv-card_srs'
411@ui_meta(definition.RepentanceStickCard)
412class RepentanceStickCard:
413 # action_stage meta
414 name = '悔悟棒'
415 image = 'thb-card-repentancestick'
416 image_small = 'thb-card-small-repentancestick'
417 description = (
418 '|R悔悟棒|r\n'
419 '\n'
420 '攻击范围2,装备后:当你使用|G弹幕|r造成伤害时,你可以防止此伤害,改为依次弃置目标角色区域内的两张牌。\n'
421 '|B|R>> |r 区域内的牌包括手牌,装备区的牌和判定区的牌。\n'
422 '\n'
423 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
424 '\n'
425 '|DB(画师:霏茶,CV:shourei小N)|r'
426 )
428 is_action_valid = equip_iav
429 effect_string = suppress_launch_card_effect_string
432@ui_meta(equipment.RepentanceStickSkill)
433class RepentanceStickSkill:
434 # Skill
435 name = '悔悟棒'
438@ui_meta(equipment.RepentanceStickHandler)
439class RepentanceStickHandler:
440 # choose_option
441 choose_option_buttons = (('发动', True), ('不发动', False))
442 choose_option_prompt = '你要发动【悔悟棒】吗?'
445@ui_meta(equipment.RepentanceStick)
446class RepentanceStick:
447 def effect_string_before(self, act):
448 return (
449 '|G【%s】|r用|G悔悟棒|r狠狠地敲了|G【%s】|r一通…'
450 ) % (
451 act.source.ui_meta.name,
452 act.target.ui_meta.name,
454 )
456 def effect_string(self, act: equipment.RepentanceStick) -> str:
457 cl = BatchList[Card](act.cards)
458 return '又抢过|G【%s】|r的|G%s|r扔了出去!' % (
459 act.target.ui_meta.name,
460 '|r和|G'.join(cl.ui_meta.name)
461 )
463 def sound_effect(self, act):
464 return 'thb-cv-card_repentancestick'
467@ui_meta(definition.IbukiGourdCard)
468class IbukiGourdCard:
469 # action_stage meta
470 name = '伊吹瓢'
471 image = 'thb-card-ibukigourd'
472 image_small = 'thb-card-small-ibukigourd'
473 is_action_valid = equip_iav
474 effect_string = suppress_launch_card_effect_string
476 description = (
477 '|R伊吹瓢|r\n\n'
478 '装备后:获得立即|B喝醉|r状态。并且,若你在出牌阶段没有造成过伤害,在回合结束阶段获得|B喝醉|r状态。\n\n'
479 '|DB(画师:霏茶)|r'
480 )
483@ui_meta(equipment.IbukiGourdSkill)
484class IbukiGourdSkill:
485 # Skill
486 name = '伊吹瓢'
489@ui_meta(definition.HouraiJewelCard)
490class HouraiJewelCard:
491 # action_stage meta
492 name = '蓬莱玉枝'
493 image = 'thb-card-houraijewel'
494 image_small = 'thb-card-small-houraijewel'
495 description = (
496 '|R蓬莱玉枝|r\n'
497 '\n'
498 '攻击范围1。装备后,你使用的|G弹幕|r时,可以将弹幕的效果转化成如下的符卡效果:造成1点伤害。\n'
499 '\n'
500 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
501 '\n'
502 '|DB(画师:霏茶)|r'
503 )
505 is_action_valid = equip_iav
506 effect_string = suppress_launch_card_effect_string
509@ui_meta(equipment.HouraiJewelSkill)
510class HouraiJewelSkill:
511 # Skill
512 name = '蓬莱玉枝'
515@ui_meta(equipment.HouraiJewelHandler)
516class HouraiJewelHandler:
517 # choose_option
518 choose_option_buttons = (('发动', True), ('不发动', False))
519 choose_option_prompt = '你要发动【蓬莱玉枝】吗?'
522@ui_meta(equipment.HouraiJewelAttack)
523class HouraiJewelAttack:
524 def effect_string_apply(self, act):
525 return (
526 '|G【%s】|r发动了|G蓬莱玉枝|r,包裹着魔法核心的弹幕冲向了|G【%s】|r!'
527 ) % (
528 act.source.ui_meta.name,
529 act.target.ui_meta.name,
530 )
533@ui_meta(definition.MaidenCostumeCard)
534class MaidenCostumeCard:
535 # action_stage meta
536 name = '巫女服'
537 image = 'thb-card-maidencostume'
538 image_small = 'thb-card-small-maidencostume'
539 description = (
540 '|R巫女服|r\n\n'
541 '装备后:当你成为一张符卡的目标时,你可以进行一次判定:若判定牌点数为9到K,则视为你使用了一张|G好人卡|r。\n\n'
542 '|DB(画师:霏茶,CV:VV)|r'
543 )
544 is_action_valid = equip_iav
545 effect_string = suppress_launch_card_effect_string
548@ui_meta(equipment.MaidenCostume)
549class MaidenCostume:
550 # Skill
551 name = '巫女服'
553 def sound_effect(self, act):
554 return 'thb-cv-card_maidencostume'
557@ui_meta(equipment.MaidenCostumeHandler)
558class MaidenCostumeHandler:
559 # choose_option
560 choose_option_buttons = (('发动', True), ('不发动', False))
561 choose_option_prompt = '你要发动【巫女服】吗?'
564@ui_meta(equipment.MaidenCostumeAction)
565class MaidenCostumeAction:
566 fatetell_display_name = '巫女服'
568 def effect_string_before(self, act):
569 return (
570 '|G【%s】|r穿了|G巫女服|r,春度爆表,不怕符卡!'
571 ) % (
572 act.source.ui_meta.name,
573 )
575 def effect_string(self, act):
576 if not act.succeeded:
577 return (
578 '好像|G【%s】|r的春度还是不够用…'
579 ) % (
580 act.source.ui_meta.name,
581 )
584@ui_meta(definition.HakuroukenCard)
585class HakuroukenCard:
586 # action_stage meta
587 name = '白楼剑'
588 image = 'thb-card-hakurouken'
589 image_small = 'thb-card-small-hakurouken'
590 description = (
591 '|R白楼剑|r\n\n'
592 '攻击范围2,装备后:当你使用的草花色|G弹幕|r指定一名目标角色后,你可以令其选择一项:\n'
593 '|B|R>> |r弃置一张手牌。\n'
594 '|B|R>> |r令你摸一张牌。\n'
595 '\n'
596 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
597 '\n'
598 '|DB(画师:霏茶,CV:小羽)|r'
599 )
600 is_action_valid = equip_iav
601 effect_string = suppress_launch_card_effect_string
604@ui_meta(equipment.HakuroukenSkill)
605class HakuroukenSkill:
606 # Skill
607 name = '白楼剑'
610@ui_meta(equipment.Hakurouken)
611class Hakurouken:
612 # choose_card
613 def choose_card_text(self, act, cards):
614 if act.cond(cards):
615 return (True, '弃置这张牌')
616 else:
617 return (False, '请弃掉一张牌(否则对方摸一张牌)')
619 def effect_string_before(self, act):
620 return (
621 '|G【%s】|r祭起了|G白楼剑|r,试图斩断|G【%s】|r的迷惘!'
622 ) % (
623 act.source.ui_meta.name,
624 act.target.ui_meta.name,
625 )
627 def effect_string(self, act):
628 if act.peer_action == 'drop':
629 return '|G【%s】|r弃置了一张牌。' % act.target.ui_meta.name
630 else:
631 return None # DrawCards has it's own prompt
633 def sound_effect(self, act):
634 return 'thb-cv-card_hakurouken'
637@ui_meta(equipment.HakuroukenHandler)
638class HakuroukenHandler:
639 # choose_option
640 choose_option_buttons = (('发动', True), ('不发动', False))
641 choose_option_prompt = '你要发动【白楼剑】吗?'
644@ui_meta(definition.AyaRoundfanCard)
645class AyaRoundfanCard:
646 # action_stage meta
647 name = '团扇'
648 image = 'thb-card-ayaroundfan'
649 image_small = 'thb-card-small-ayaroundfan'
650 description = (
651 '|R团扇|r\n'
652 '\n'
653 '攻击距离5,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,你可以弃置一张手牌,然后弃置其装备区里的一张牌。\n'
654 '\n'
655 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
656 '\n'
657 '|DB(画师:霏茶,CV:VV)|r'
658 )
659 is_action_valid = equip_iav
660 effect_string = suppress_launch_card_effect_string
663@ui_meta(equipment.AyaRoundfanSkill)
664class AyaRoundfanSkill:
665 # Skill
666 name = '团扇'
669@ui_meta(equipment.AyaRoundfanHandler)
670class AyaRoundfanHandler:
671 # choose_card
672 def choose_card_text(self, act, cards):
673 if act.cond(cards):
674 return (True, '这种妨碍拍摄的东西,统统脱掉!')
675 else:
676 return (False, '请弃掉一张手牌发动团扇(否则不发动)')
679@ui_meta(equipment.AyaRoundfan)
680class AyaRoundfan:
681 def effect_string_before(self, act):
682 return (
683 '|G【%s】|r觉得手中的|G团扇|r用起来好顺手,便加大力度试了试…'
684 ) % (
685 act.source.ui_meta.name,
686 )
688 def effect_string(self, act):
689 return (
690 '于是|G【%s】|r的|G%s|r就飞了出去!'
691 ) % (
692 act.target.ui_meta.name,
693 act.card.ui_meta.name,
694 )
696 def sound_effect(self, act):
697 return random.choice([
698 'thb-cv-card_roundfan1',
699 'thb-cv-card_roundfan2',
700 ])
703@ui_meta(definition.NenshaPhoneCard)
704class NenshaPhoneCard:
705 # action_stage meta
706 name = '念写机'
707 image = 'thb-card-nenshaphone'
708 image_small = 'thb-card-small-nenshaphone'
709 description = (
710 '|R念写机|r\n'
711 '\n'
712 '攻击距离4,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,可以将其两张手牌置入明牌区。\n'
713 '\n'
714 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
715 '\n'
716 '|DB(画师:霏茶)|r'
718 )
719 is_action_valid = equip_iav
720 effect_string = suppress_launch_card_effect_string
723@ui_meta(equipment.NenshaPhoneSkill)
724class NenshaPhoneSkill:
725 # Skill
726 name = '念写机'
729@ui_meta(equipment.NenshaPhoneHandler)
730class NenshaPhoneHandler:
731 # choose_option
732 choose_option_buttons = (('发动', True), ('不发动', False))
733 choose_option_prompt = '你要发动【念写机】吗?'
736@ui_meta(equipment.NenshaPhone)
737class NenshaPhone:
738 def effect_string(self, act):
739 return (
740 '|G【%s】|r表示,将|G【%s】|r推倒后拍摄胖次,是记者的自我修养中不可或缺的一部分。'
741 ) % (
742 act.source.ui_meta.name,
743 act.target.ui_meta.name,
744 )
746 def sound_effect(self, act):
747 return 'thb-cv-card_nenshaphone'
750@ui_meta(definition.LaevateinCard)
751class LaevateinCard:
752 # action_stage meta
753 name = '莱瓦汀'
754 image = 'thb-card-laevatein'
755 image_small = 'thb-card-small-laevatein'
756 description = (
757 '|R莱瓦汀|r\n'
758 '\n'
759 '攻击距离3,装备后:当你使用的|G弹幕|r被目标角色使用的|G擦弹|r抵消时,你可以弃置两张牌,令此|G弹幕|r依然生效。\n'
760 '\n'
761 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
762 '\n'
763 '|DB(画师:霏茶,CV:VV)|r'
764 )
765 is_action_valid = equip_iav
766 effect_string = suppress_launch_card_effect_string
769@ui_meta(equipment.LaevateinSkill)
770class LaevateinSkill:
771 # Skill
772 name = '莱瓦汀'
775@ui_meta(equipment.LaevateinHandler)
776class LaevateinHandler:
777 # choose_card
778 def choose_card_text(self, act, cards):
779 if act.cond(cards):
780 return (True, '灭世之炎岂能轻易闪过!')
781 else:
782 return (False, '请弃掉两张牌发动莱瓦汀(否则不发动)')
785@ui_meta(equipment.Laevatein)
786class Laevatein:
787 def effect_string_before(self, act):
788 return '|G莱瓦汀|r的灭世之炎岂能轻易闪过!'
790 def sound_effect(self, act):
791 return 'thb-cv-card_laevatein'
794@ui_meta(definition.DeathSickleCard)
795class DeathSickleCard:
796 # action_stage meta
797 name = '死神之镰'
798 image = 'thb-card-deathsickle'
799 image_small = 'thb-card-small-deathsickle'
800 description = (
801 '|R死神之镰|r\n'
802 '\n'
803 '攻击范围2,装备后:当你使用的【弹幕】对目标角色造成伤害时,若其没有手牌,此伤害+1。\n'
804 '\n'
805 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
806 '\n'
807 '|DB(画师:霏茶,CV:小羽)|r'
808 )
809 is_action_valid = equip_iav
810 effect_string = suppress_launch_card_effect_string
813@ui_meta(equipment.DeathSickleSkill)
814class DeathSickleSkill:
815 # Skill
816 name = '死神之镰'
819@ui_meta(equipment.DeathSickle)
820class DeathSickle:
821 def effect_string(self, act):
822 return (
823 '|G【%s】|r看到|G【%s】|r一副丧家犬的模样,'
824 '手中的|G死神之镰|r不自觉地一狠…'
825 ) % (
826 act.source.ui_meta.name,
827 act.target.ui_meta.name,
828 )
830 def sound_effect(self, act):
831 return 'thb-cv-card_deathsickle'
834@ui_meta(definition.KeystoneCard)
835class KeystoneCard:
836 # action_stage meta
837 name = '要石'
838 image = 'thb-card-keystone'
839 image_small = 'thb-card-small-keystone'
840 description = (
841 '|R要石|r\n\n'
842 '特殊的绿色UFO装备,距离+1\n'
843 '装备后跳过【罪袋】对你的结算。\n\n'
844 '|DB(画师:霏茶,CV:shourei小N)|r'
845 )
846 is_action_valid = equip_iav
847 effect_string = suppress_launch_card_effect_string
850@ui_meta(equipment.KeystoneSkill)
851class KeystoneSkill:
852 # Skill
853 name = '要石'
856@ui_meta(equipment.Keystone)
857class Keystone:
858 def effect_string(self, act):
859 return '|G【%s】|r站在|G要石|r上,照着|G罪袋|r的脸一脚踹了下去!' % (
860 act.target.ui_meta.name
861 )
863 def sound_effect(self, act):
864 return 'thb-cv-card_keystone'
867@ui_meta(definition.WitchBroomCard)
868class WitchBroomCard:
869 # action_stage meta
870 name = '魔女扫把'
871 image = 'thb-card-witchbroom'
872 image_small = 'thb-card-small-witchbroom'
873 is_action_valid = equip_iav
874 effect_string = suppress_launch_card_effect_string
875 description = (
876 '|R魔女扫把|r\n\n'
877 '特殊的红色UFO装备,距离-2。\n\n'
878 '|DB(画师:霏茶)|r'
879 )
882@ui_meta(equipment.WitchBroomSkill)
883class WitchBroomSkill:
884 # Skill
885 no_display = True
888@ui_meta(definition.YinYangOrbCard)
889class YinYangOrbCard:
890 # action_stage meta
891 name = '阴阳玉'
892 image = 'thb-card-yinyangorb'
893 image_small = 'thb-card-small-yinyangorb'
894 description = (
895 '|R阴阳玉|r\n\n'
896 '装备后:在你的判定牌生效前,你可以用装备区内的|G阴阳玉|r替换之。\n\n'
897 '|DB(画师:霏茶)|r'
898 )
899 is_action_valid = equip_iav
900 effect_string = suppress_launch_card_effect_string
903@ui_meta(equipment.YinYangOrbSkill)
904class YinYangOrbSkill:
905 # Skill
906 name = '阴阳玉'
909@ui_meta(equipment.YinYangOrbHandler)
910class YinYangOrbHandler:
911 # choose_option
912 choose_option_buttons = (('替换', True), ('不替换', False))
913 choose_option_prompt = '你要使用【阴阳玉】替换当前的判定牌吗?'
916@ui_meta(equipment.YinYangOrb)
917class YinYangOrb:
918 def effect_string(self, act):
919 return '|G【%s】|r用|G%s|r替换了她的判定牌。' % (
920 act.target.ui_meta.name,
921 self.card_desc(act.card),
922 )
925@ui_meta(definition.SuwakoHatCard)
926class SuwakoHatCard:
927 # action_stage meta
928 name = '青蛙帽'
929 image = 'thb-card-suwakohat'
930 image_small = 'thb-card-small-suwakohat'
931 description = (
932 '|R青蛙帽|r\n\n'
933 '装备后:手牌上限+2。\n\n'
934 '|DB(画师:霏茶,CV:VV)|r'
935 )
936 is_action_valid = equip_iav
937 effect_string = suppress_launch_card_effect_string
940@ui_meta(equipment.SuwakoHatSkill)
941class SuwakoHatSkill:
942 # Skill
943 name = '青蛙帽'
946@ui_meta(equipment.SuwakoHatEffect)
947class SuwakoHatEffect:
948 def sound_effect(self, act):
949 return 'thb-cv-card_suwakohat'
952@ui_meta(definition.YoumuPhantomCard)
953class YoumuPhantomCard:
954 # action_stage meta
955 name = '半灵'
956 image = 'thb-card-phantom'
957 image_small = 'thb-card-small-phantom'
958 description = (
959 '|R半灵|r\n\n'
960 '装备后:增加1点体力上限,当失去装备区里的【半灵】时,你回复1点体力。\n\n'
961 '|DB(画师:霏茶,CV:小羽)|r'
962 )
964 is_action_valid = equip_iav
965 effect_string = suppress_launch_card_effect_string
968@ui_meta(equipment.YoumuPhantomSkill)
969class YoumuPhantomSkill:
970 # Skill
971 name = '半灵'
974@ui_meta(equipment.YoumuPhantomHeal)
975class YoumuPhantomHeal:
976 def sound_effect(self, act):
977 return 'thb-cv-card_phantom'
980@ui_meta(definition.IceWingCard)
981class IceWingCard:
982 # action_stage meta
983 name = '⑨的翅膀'
984 image = 'thb-card-icewing'
985 image_small = 'thb-card-small-icewing'
986 description = (
987 '|R⑨的翅膀|r\n\n'
988 '特殊的红色UFO装备,距离-1。\n\n'
989 '装备后:|G封魔阵|r和|G冻青蛙|r对你无效。\n\n'
990 '|DB(画师:霏茶,CV:VV)|r'
991 )
993 is_action_valid = equip_iav
994 effect_string = suppress_launch_card_effect_string
997@ui_meta(equipment.IceWingSkill)
998class IceWingSkill:
999 # Skill
1000 name = '⑨的翅膀'
1003@ui_meta(equipment.IceWing)
1004class IceWing:
1005 def effect_string(self, act):
1006 return '|G【%s】|r借着|G⑨的翅膀|r飞了出来,|G%s|r没起到什么作用。' % (
1007 act.target.ui_meta.name,
1008 act.action.associated_card.ui_meta.name,
1009 )
1011 def sound_effect(self, act):
1012 tgt = act.target
1013 if ttags(tgt)['__icewing_se']:
1014 return None
1016 ttags(tgt)['__icewing_se'] = True
1017 return 'thb-cv-card_icewing'
1020@ui_meta(definition.GrimoireCard)
1021class GrimoireCard:
1022 # action_stage meta
1023 name = '魔导书'
1024 image = 'thb-card-grimoire'
1025 image_small = 'thb-card-small-grimoire'
1026 description = (
1027 '|R魔导书|r\n'
1028 '\n'
1029 '攻击距离1,装备后,你可以消耗一点干劲并将一张牌按照以下规则使用:\n'
1030 '|B|R>> |r黑桃♠视为|G百鬼夜行|r。\n'
1031 '|B|R>> |r红桃♥视为|G宴会|r。\n'
1032 '|B|R>> |r梅花♣视为|G地图炮|r。\n'
1033 '|B|R>> |r方片♦视为|G五谷丰登|r。\n'
1034 '\n'
1035 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
1036 '\n'
1037 '|DB(画师:霏茶,CV:shourei小N)|r'
1038 )
1039 is_action_valid = equip_iav
1040 effect_string = suppress_launch_card_effect_string
1043@ui_meta(equipment.GrimoireSkill)
1044class GrimoireSkill:
1045 # Skill
1046 name = '魔导书'
1048 def clickable(self):
1049 g = self.game
1050 me = self.me
1051 t = me.tags
1052 if t['grimoire_tag'] >= t['turn_count']:
1053 return False
1055 try:
1056 act = g.action_stack[-1]
1057 if isinstance(act, actions.ActionStage):
1058 if me.tags['freeattack'] >= me.tags['turn_count']:
1059 return True
1061 if me.tags['vitality'] > 0:
1062 return True
1064 if me.has_skill(equipment.ElementalReactorSkill):
1065 return True
1067 except IndexError:
1068 pass
1070 return False
1072 def is_action_valid(self, sk, tl):
1073 assert sk.is_card(equipment.GrimoireSkill)
1074 acards = sk.associated_cards
1075 if not (len(acards)) == 1:
1076 return (False, '请选择一张牌')
1077 else:
1078 s = sk.lookup_tbl[acards[0].suit].ui_meta.name
1079 return (True, '发动【%s】' % s)
1081 def effect_string(self, act):
1082 # for LaunchCard.ui_meta.effect_string
1083 source = act.source
1084 card = act.card
1085 return (
1086 '|G【%s】|r抓起一张牌放入|G魔导书|r' +
1087 ',念动咒语,发动了|G%s|r。'
1088 ) % (
1089 source.ui_meta.name,
1090 card.lookup_tbl[card.associated_cards[0].suit].ui_meta.name
1091 )
1093 def sound_effect(self, act):
1094 return 'thb-cv-card_grimoire'
1097@ui_meta(equipment.SinsackHatAction)
1098class SinsackHatAction:
1099 fatetell_display_name = '头套'
1101 def effect_string_before(self, act):
1102 return '看着戴着|G头套|r的|G【%s】|r,真正的的罪袋们都兴奋了起来!' % (
1103 act.target.ui_meta.name,
1104 )
1107@ui_meta(equipment.SinsackHat)
1108class SinsackHat:
1109 # Skill
1110 name = '头套'
1113@ui_meta(definition.SinsackHatCard)
1114class SinsackHatCard:
1115 # action_stage meta
1116 name = '头套'
1117 image = 'thb-card-sinsackhat'
1118 image_small = 'thb-card-small-sinsackhat'
1119 description = (
1120 '|R罪袋的头套|r\n\n'
1121 '对距离2以内的一名角色使用。\n'
1122 '装备|G罪袋的头套|r的角色需在判定阶段后进行一次判定,若为黑桃1-8,则目标角色受到2点伤害,并且将|G罪袋的头套|r收入手牌。\n'
1123 '|DB(画师:霏茶,CV:大白)|r'
1124 )
1126 def is_action_valid(self, c, tl):
1127 if not tl:
1128 return (False, '请选择目标')
1129 t = tl[0]
1130 if self.me is t:
1131 return (True, '真的要自己戴上吗?')
1132 return (True, '是这样的,这个不是胖次……不不,真的没有胖次')
1134 effect_string = suppress_launch_card_effect_string