Coverage for thb/meta/cards/equipment.py : 79%
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, cl, 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, g):
310 try:
311 act = g.hybrid_stack[-1]
312 if act.cond([equipment.GungnirSkill(g.me)]):
313 return True
315 except (IndexError, AttributeError):
316 pass
318 return False
320 def is_complete(self, skill):
321 me = self.me
322 assert skill.is_card(equipment.GungnirSkill)
323 acards = skill.associated_cards
324 if len(acards) != 2:
325 return (False, '请选择2张手牌!')
326 elif any(c.resides_in not in (me.cards, me.showncards) for c in acards):
327 return (False, '只能使用手牌发动!')
328 return (True, '反正这条也看不到,偷个懒~~~')
330 def is_action_valid(self, sk, tl):
331 assert sk.is_card(equipment.GungnirSkill)
332 rst, reason = self.is_complete(sk)
333 if not rst:
334 return (rst, reason)
335 else:
336 return definition.AttackCard().ui_meta.is_action_valid(sk, tl)
338 def effect_string(self, act):
339 # for LaunchCard.effect_string
340 source = act.source
341 target = act.target
342 s = '|G【%s】|r发动了|G冈格尼尔|r之枪,将两张牌当作|G弹幕|r对|G【%s】|r使用。' % (
343 source.ui_meta.name,
344 target.ui_meta.name,
345 )
346 return s
348 def sound_effect(self, act):
349 return definition.AttackCard.ui_meta.sound_effect(act)
352@ui_meta(definition.ScarletRhapsodyCard)
353class ScarletRhapsodyCard:
354 # action_stage meta
355 name = '绯想之剑'
356 image = 'thb-card-scarletrhapsodysword'
357 image_small = 'thb-card-small-scarletrhapsodysword'
358 description = (
359 '|R绯想之剑|r\n'
360 '\n'
361 '攻击范围4,装备后:当你使用的|G弹幕|r是你的最后一张手牌时,你可以为此|G弹幕|r指定至多三名目标。\n'
362 '\n'
363 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
364 '\n'
365 '|DB(画师:霏茶,CV:VV)|r'
366 )
368 is_action_valid = equip_iav
369 effect_string = suppress_launch_card_effect_string
372@ui_meta(equipment.ScarletRhapsodySkill)
373class ScarletRhapsodySkill:
374 # Skill
375 name = '绯想之剑'
377 def clickable(self, game):
378 me = game.me
379 try:
380 act = game.action_stack[-1]
381 if isinstance(act, actions.ActionStage):
382 return act.target is me
384 except IndexError:
385 pass
387 return False
389 def is_action_valid(self, sk, tl):
390 assert sk.is_card(equipment.ScarletRhapsodySkill)
391 if not sk.check():
392 return (False, '请选择你的最后一张【弹幕】!')
393 else:
394 if not tl:
395 return (False, '请选择弹幕的目标(最多可以选择3名玩家)')
397 if self.me in tl: 397 ↛ 398line 397 didn't jump to line 398, because the condition on line 397 was never true
398 return (True, '您真的要自残么?!')
399 else:
400 return (True, '全人类的绯想天!')
402 def effect_string(self, act: actions.LaunchCard) -> Optional[str]:
403 # for LaunchCard.ui_meta.effect_string
404 src = act.source
405 tl = BatchList(act.target_list)
407 return '全人类的绯想天,当然不能只打一个!于是|G【%s】|r选了|G【%s】|r一共%d个目标!' % (
408 src.ui_meta.name,
409 '】|r、|G【'.join(tl.ui_meta.name),
410 len(tl),
411 )
413 def sound_effect(self, act):
414 return 'thb-cv-card_srs'
417@ui_meta(definition.RepentanceStickCard)
418class RepentanceStickCard:
419 # action_stage meta
420 name = '悔悟棒'
421 image = 'thb-card-repentancestick'
422 image_small = 'thb-card-small-repentancestick'
423 description = (
424 '|R悔悟棒|r\n'
425 '\n'
426 '攻击范围2,装备后:当你使用|G弹幕|r造成伤害时,你可以防止此伤害,改为依次弃置目标角色区域内的两张牌。\n'
427 '|B|R>> |r 区域内的牌包括手牌,装备区的牌和判定区的牌。\n'
428 '\n'
429 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
430 '\n'
431 '|DB(画师:霏茶,CV:shourei小N)|r'
432 )
434 is_action_valid = equip_iav
435 effect_string = suppress_launch_card_effect_string
438@ui_meta(equipment.RepentanceStickSkill)
439class RepentanceStickSkill:
440 # Skill
441 name = '悔悟棒'
444@ui_meta(equipment.RepentanceStickHandler)
445class RepentanceStickHandler:
446 # choose_option
447 choose_option_buttons = (('发动', True), ('不发动', False))
448 choose_option_prompt = '你要发动【悔悟棒】吗?'
451@ui_meta(equipment.RepentanceStick)
452class RepentanceStick:
453 def effect_string_before(self, act):
454 return (
455 '|G【%s】|r用|G悔悟棒|r狠狠地敲了|G【%s】|r一通…'
456 ) % (
457 act.source.ui_meta.name,
458 act.target.ui_meta.name,
460 )
462 def effect_string(self, act: equipment.RepentanceStick) -> str:
463 cl = BatchList[Card](act.cards)
464 return '又抢过|G【%s】|r的|G%s|r扔了出去!' % (
465 act.target.ui_meta.name,
466 '|r和|G'.join(cl.ui_meta.name)
467 )
469 def sound_effect(self, act):
470 return 'thb-cv-card_repentancestick'
473@ui_meta(definition.IbukiGourdCard)
474class IbukiGourdCard:
475 # action_stage meta
476 name = '伊吹瓢'
477 image = 'thb-card-ibukigourd'
478 image_small = 'thb-card-small-ibukigourd'
479 is_action_valid = equip_iav
480 effect_string = suppress_launch_card_effect_string
482 description = (
483 '|R伊吹瓢|r\n\n'
484 '装备后:获得立即|B喝醉|r状态。并且,若你在出牌阶段没有造成过伤害,在回合结束阶段获得|B喝醉|r状态。\n\n'
485 '|DB(画师:霏茶)|r'
486 )
489@ui_meta(equipment.IbukiGourdSkill)
490class IbukiGourdSkill:
491 # Skill
492 name = '伊吹瓢'
495@ui_meta(definition.HouraiJewelCard)
496class HouraiJewelCard:
497 # action_stage meta
498 name = '蓬莱玉枝'
499 image = 'thb-card-houraijewel'
500 image_small = 'thb-card-small-houraijewel'
501 description = (
502 '|R蓬莱玉枝|r\n'
503 '\n'
504 '攻击范围1。装备后,你使用的|G弹幕|r时,可以将弹幕的效果转化成如下的符卡效果:造成1点伤害。\n'
505 '\n'
506 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
507 '\n'
508 '|DB(画师:霏茶)|r'
509 )
511 is_action_valid = equip_iav
512 effect_string = suppress_launch_card_effect_string
515@ui_meta(equipment.HouraiJewelSkill)
516class HouraiJewelSkill:
517 # Skill
518 name = '蓬莱玉枝'
521@ui_meta(equipment.HouraiJewelHandler)
522class HouraiJewelHandler:
523 # choose_option
524 choose_option_buttons = (('发动', True), ('不发动', False))
525 choose_option_prompt = '你要发动【蓬莱玉枝】吗?'
528@ui_meta(equipment.HouraiJewelAttack)
529class HouraiJewelAttack:
530 def effect_string_apply(self, act):
531 return (
532 '|G【%s】|r发动了|G蓬莱玉枝|r,包裹着魔法核心的弹幕冲向了|G【%s】|r!'
533 ) % (
534 act.source.ui_meta.name,
535 act.target.ui_meta.name,
536 )
539@ui_meta(definition.MaidenCostumeCard)
540class MaidenCostumeCard:
541 # action_stage meta
542 name = '巫女服'
543 image = 'thb-card-maidencostume'
544 image_small = 'thb-card-small-maidencostume'
545 description = (
546 '|R巫女服|r\n\n'
547 '装备后:当你成为一张符卡的目标时,你可以进行一次判定:若判定牌点数为9到K,则视为你使用了一张|G好人卡|r。\n\n'
548 '|DB(画师:霏茶,CV:VV)|r'
549 )
550 is_action_valid = equip_iav
551 effect_string = suppress_launch_card_effect_string
554@ui_meta(equipment.MaidenCostume)
555class MaidenCostume:
556 # Skill
557 name = '巫女服'
559 def sound_effect(self, act):
560 return 'thb-cv-card_maidencostume'
563@ui_meta(equipment.MaidenCostumeHandler)
564class MaidenCostumeHandler:
565 # choose_option
566 choose_option_buttons = (('发动', True), ('不发动', False))
567 choose_option_prompt = '你要发动【巫女服】吗?'
570@ui_meta(equipment.MaidenCostumeAction)
571class MaidenCostumeAction:
572 fatetell_display_name = '巫女服'
574 def effect_string_before(self, act):
575 return (
576 '|G【%s】|r穿了|G巫女服|r,春度爆表,不怕符卡!'
577 ) % (
578 act.source.ui_meta.name,
579 )
581 def effect_string(self, act):
582 if not act.succeeded:
583 return (
584 '好像|G【%s】|r的春度还是不够用…'
585 ) % (
586 act.source.ui_meta.name,
587 )
590@ui_meta(definition.HakuroukenCard)
591class HakuroukenCard:
592 # action_stage meta
593 name = '白楼剑'
594 image = 'thb-card-hakurouken'
595 image_small = 'thb-card-small-hakurouken'
596 description = (
597 '|R白楼剑|r\n\n'
598 '攻击范围2,装备后:当你使用的草花色|G弹幕|r指定一名目标角色后,你可以令其选择一项:\n'
599 '|B|R>> |r弃置一张手牌。\n'
600 '|B|R>> |r令你摸一张牌。\n'
601 '\n'
602 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
603 '\n'
604 '|DB(画师:霏茶,CV:小羽)|r'
605 )
606 is_action_valid = equip_iav
607 effect_string = suppress_launch_card_effect_string
610@ui_meta(equipment.HakuroukenSkill)
611class HakuroukenSkill:
612 # Skill
613 name = '白楼剑'
616@ui_meta(equipment.Hakurouken)
617class Hakurouken:
618 # choose_card
619 def choose_card_text(self, g, act, cards):
620 if act.cond(cards):
621 return (True, '弃置这张牌')
622 else:
623 return (False, '请弃掉一张牌(否则对方摸一张牌)')
625 def effect_string_before(self, act):
626 return (
627 '|G【%s】|r祭起了|G白楼剑|r,试图斩断|G【%s】|r的迷惘!'
628 ) % (
629 act.source.ui_meta.name,
630 act.target.ui_meta.name,
631 )
633 def effect_string(self, act):
634 if act.peer_action == 'drop':
635 return '|G【%s】|r弃置了一张牌。' % act.target.ui_meta.name
636 else:
637 return None # DrawCards has it's own prompt
639 def sound_effect(self, act):
640 return 'thb-cv-card_hakurouken'
643@ui_meta(equipment.HakuroukenHandler)
644class HakuroukenHandler:
645 # choose_option
646 choose_option_buttons = (('发动', True), ('不发动', False))
647 choose_option_prompt = '你要发动【白楼剑】吗?'
650@ui_meta(definition.AyaRoundfanCard)
651class AyaRoundfanCard:
652 # action_stage meta
653 name = '团扇'
654 image = 'thb-card-ayaroundfan'
655 image_small = 'thb-card-small-ayaroundfan'
656 description = (
657 '|R团扇|r\n'
658 '\n'
659 '攻击距离5,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,你可以弃置一张手牌,然后弃置其装备区里的一张牌。\n'
660 '\n'
661 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
662 '\n'
663 '|DB(画师:霏茶,CV:VV)|r'
664 )
665 is_action_valid = equip_iav
666 effect_string = suppress_launch_card_effect_string
669@ui_meta(equipment.AyaRoundfanSkill)
670class AyaRoundfanSkill:
671 # Skill
672 name = '团扇'
675@ui_meta(equipment.AyaRoundfanHandler)
676class AyaRoundfanHandler:
677 # choose_card
678 def choose_card_text(self, g, act, cards):
679 if act.cond(cards):
680 return (True, '这种妨碍拍摄的东西,统统脱掉!')
681 else:
682 return (False, '请弃掉一张手牌发动团扇(否则不发动)')
685@ui_meta(equipment.AyaRoundfan)
686class AyaRoundfan:
687 def effect_string_before(self, act):
688 return (
689 '|G【%s】|r觉得手中的|G团扇|r用起来好顺手,便加大力度试了试…'
690 ) % (
691 act.source.ui_meta.name,
692 )
694 def effect_string(self, act):
695 return (
696 '于是|G【%s】|r的|G%s|r就飞了出去!'
697 ) % (
698 act.target.ui_meta.name,
699 act.card.ui_meta.name,
700 )
702 def sound_effect(self, act):
703 return random.choice([
704 'thb-cv-card_roundfan1',
705 'thb-cv-card_roundfan2',
706 ])
709@ui_meta(definition.NenshaPhoneCard)
710class NenshaPhoneCard:
711 # action_stage meta
712 name = '念写机'
713 image = 'thb-card-nenshaphone'
714 image_small = 'thb-card-small-nenshaphone'
715 description = (
716 '|R念写机|r\n'
717 '\n'
718 '攻击距离4,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,可以将其两张手牌置入明牌区。\n'
719 '\n'
720 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
721 '\n'
722 '|DB(画师:霏茶)|r'
724 )
725 is_action_valid = equip_iav
726 effect_string = suppress_launch_card_effect_string
729@ui_meta(equipment.NenshaPhoneSkill)
730class NenshaPhoneSkill:
731 # Skill
732 name = '念写机'
735@ui_meta(equipment.NenshaPhoneHandler)
736class NenshaPhoneHandler:
737 # choose_option
738 choose_option_buttons = (('发动', True), ('不发动', False))
739 choose_option_prompt = '你要发动【念写机】吗?'
742@ui_meta(equipment.NenshaPhone)
743class NenshaPhone:
744 def effect_string(self, act):
745 return (
746 '|G【%s】|r表示,将|G【%s】|r推倒后拍摄胖次,是记者的自我修养中不可或缺的一部分。'
747 ) % (
748 act.source.ui_meta.name,
749 act.target.ui_meta.name,
750 )
752 def sound_effect(self, act):
753 return 'thb-cv-card_nenshaphone'
756@ui_meta(definition.LaevateinCard)
757class LaevateinCard:
758 # action_stage meta
759 name = '莱瓦汀'
760 image = 'thb-card-laevatein'
761 image_small = 'thb-card-small-laevatein'
762 description = (
763 '|R莱瓦汀|r\n'
764 '\n'
765 '攻击距离3,装备后:当你使用的|G弹幕|r被目标角色使用的|G擦弹|r抵消时,你可以弃置两张牌,令此|G弹幕|r依然生效。\n'
766 '\n'
767 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
768 '\n'
769 '|DB(画师:霏茶,CV:VV)|r'
770 )
771 is_action_valid = equip_iav
772 effect_string = suppress_launch_card_effect_string
775@ui_meta(equipment.LaevateinSkill)
776class LaevateinSkill:
777 # Skill
778 name = '莱瓦汀'
781@ui_meta(equipment.LaevateinHandler)
782class LaevateinHandler:
783 # choose_card
784 def choose_card_text(self, g, act, cards):
785 if act.cond(cards):
786 return (True, '灭世之炎岂能轻易闪过!')
787 else:
788 return (False, '请弃掉两张牌发动莱瓦汀(否则不发动)')
791@ui_meta(equipment.Laevatein)
792class Laevatein:
793 def effect_string_before(self, act):
794 return '|G莱瓦汀|r的灭世之炎岂能轻易闪过!'
796 def sound_effect(self, act):
797 return 'thb-cv-card_laevatein'
800@ui_meta(definition.DeathSickleCard)
801class DeathSickleCard:
802 # action_stage meta
803 name = '死神之镰'
804 image = 'thb-card-deathsickle'
805 image_small = 'thb-card-small-deathsickle'
806 description = (
807 '|R死神之镰|r\n'
808 '\n'
809 '攻击范围2,装备后:当你使用的【弹幕】对目标角色造成伤害时,若其没有手牌,此伤害+1。\n'
810 '\n'
811 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
812 '\n'
813 '|DB(画师:霏茶,CV:小羽)|r'
814 )
815 is_action_valid = equip_iav
816 effect_string = suppress_launch_card_effect_string
819@ui_meta(equipment.DeathSickleSkill)
820class DeathSickleSkill:
821 # Skill
822 name = '死神之镰'
825@ui_meta(equipment.DeathSickle)
826class DeathSickle:
827 def effect_string(self, act):
828 return (
829 '|G【%s】|r看到|G【%s】|r一副丧家犬的模样,'
830 '手中的|G死神之镰|r不自觉地一狠…'
831 ) % (
832 act.source.ui_meta.name,
833 act.target.ui_meta.name,
834 )
836 def sound_effect(self, act):
837 return 'thb-cv-card_deathsickle'
840@ui_meta(definition.KeystoneCard)
841class KeystoneCard:
842 # action_stage meta
843 name = '要石'
844 image = 'thb-card-keystone'
845 image_small = 'thb-card-small-keystone'
846 description = (
847 '|R要石|r\n\n'
848 '特殊的绿色UFO装备,距离+1\n'
849 '装备后跳过【罪袋】对你的结算。\n\n'
850 '|DB(画师:霏茶,CV:shourei小N)|r'
851 )
852 is_action_valid = equip_iav
853 effect_string = suppress_launch_card_effect_string
856@ui_meta(equipment.KeystoneSkill)
857class KeystoneSkill:
858 # Skill
859 name = '要石'
862@ui_meta(equipment.Keystone)
863class Keystone:
864 def effect_string(self, act):
865 return '|G【%s】|r站在|G要石|r上,照着|G罪袋|r的脸一脚踹了下去!' % (
866 act.target.ui_meta.name
867 )
869 def sound_effect(self, act):
870 return 'thb-cv-card_keystone'
873@ui_meta(definition.WitchBroomCard)
874class WitchBroomCard:
875 # action_stage meta
876 name = '魔女扫把'
877 image = 'thb-card-witchbroom'
878 image_small = 'thb-card-small-witchbroom'
879 is_action_valid = equip_iav
880 effect_string = suppress_launch_card_effect_string
881 description = (
882 '|R魔女扫把|r\n\n'
883 '特殊的红色UFO装备,距离-2。\n\n'
884 '|DB(画师:霏茶)|r'
885 )
888@ui_meta(equipment.WitchBroomSkill)
889class WitchBroomSkill:
890 # Skill
891 no_display = True
894@ui_meta(definition.YinYangOrbCard)
895class YinYangOrbCard:
896 # action_stage meta
897 name = '阴阳玉'
898 image = 'thb-card-yinyangorb'
899 image_small = 'thb-card-small-yinyangorb'
900 description = (
901 '|R阴阳玉|r\n\n'
902 '装备后:在你的判定牌生效前,你可以用装备区内的|G阴阳玉|r替换之。\n\n'
903 '|DB(画师:霏茶)|r'
904 )
905 is_action_valid = equip_iav
906 effect_string = suppress_launch_card_effect_string
909@ui_meta(equipment.YinYangOrbSkill)
910class YinYangOrbSkill:
911 # Skill
912 name = '阴阳玉'
915@ui_meta(equipment.YinYangOrbHandler)
916class YinYangOrbHandler:
917 # choose_option
918 choose_option_buttons = (('替换', True), ('不替换', False))
919 choose_option_prompt = '你要使用【阴阳玉】替换当前的判定牌吗?'
922@ui_meta(equipment.YinYangOrb)
923class YinYangOrb:
924 def effect_string(self, act):
925 return '|G【%s】|r用|G%s|r替换了她的判定牌。' % (
926 act.target.ui_meta.name,
927 self.card_desc(act.card),
928 )
931@ui_meta(definition.SuwakoHatCard)
932class SuwakoHatCard:
933 # action_stage meta
934 name = '青蛙帽'
935 image = 'thb-card-suwakohat'
936 image_small = 'thb-card-small-suwakohat'
937 description = (
938 '|R青蛙帽|r\n\n'
939 '装备后:手牌上限+2。\n\n'
940 '|DB(画师:霏茶,CV:VV)|r'
941 )
942 is_action_valid = equip_iav
943 effect_string = suppress_launch_card_effect_string
946@ui_meta(equipment.SuwakoHatSkill)
947class SuwakoHatSkill:
948 # Skill
949 name = '青蛙帽'
952@ui_meta(equipment.SuwakoHatEffect)
953class SuwakoHatEffect:
954 def sound_effect(self, act):
955 return 'thb-cv-card_suwakohat'
958@ui_meta(definition.YoumuPhantomCard)
959class YoumuPhantomCard:
960 # action_stage meta
961 name = '半灵'
962 image = 'thb-card-phantom'
963 image_small = 'thb-card-small-phantom'
964 description = (
965 '|R半灵|r\n\n'
966 '装备后:增加1点体力上限,当失去装备区里的【半灵】时,你回复1点体力。\n\n'
967 '|DB(画师:霏茶,CV:小羽)|r'
968 )
970 is_action_valid = equip_iav
971 effect_string = suppress_launch_card_effect_string
974@ui_meta(equipment.YoumuPhantomSkill)
975class YoumuPhantomSkill:
976 # Skill
977 name = '半灵'
980@ui_meta(equipment.YoumuPhantomHeal)
981class YoumuPhantomHeal:
982 def sound_effect(self, act):
983 return 'thb-cv-card_phantom'
986@ui_meta(definition.IceWingCard)
987class IceWingCard:
988 # action_stage meta
989 name = '⑨的翅膀'
990 image = 'thb-card-icewing'
991 image_small = 'thb-card-small-icewing'
992 description = (
993 '|R⑨的翅膀|r\n\n'
994 '特殊的红色UFO装备,距离-1。\n\n'
995 '装备后:|G封魔阵|r和|G冻青蛙|r对你无效。\n\n'
996 '|DB(画师:霏茶,CV:VV)|r'
997 )
999 is_action_valid = equip_iav
1000 effect_string = suppress_launch_card_effect_string
1003@ui_meta(equipment.IceWingSkill)
1004class IceWingSkill:
1005 # Skill
1006 name = '⑨的翅膀'
1009@ui_meta(equipment.IceWing)
1010class IceWing:
1011 def effect_string(act):
1012 return '|G【%s】|r借着|G⑨的翅膀|r飞了出来,|G%s|r没起到什么作用。' % (
1013 act.target.ui_meta.name,
1014 act.action.associated_card.ui_meta.name,
1015 )
1017 def sound_effect(self, act):
1018 tgt = act.target
1019 if ttags(tgt)['__icewing_se']:
1020 return None
1022 ttags(tgt)['__icewing_se'] = True
1023 return 'thb-cv-card_icewing'
1026@ui_meta(definition.GrimoireCard)
1027class GrimoireCard:
1028 # action_stage meta
1029 name = '魔导书'
1030 image = 'thb-card-grimoire'
1031 image_small = 'thb-card-small-grimoire'
1032 description = (
1033 '|R魔导书|r\n'
1034 '\n'
1035 '攻击距离1,装备后,你可以消耗一点干劲并将一张牌按照以下规则使用:\n'
1036 '|B|R>> |r黑桃♠视为|G百鬼夜行|r。\n'
1037 '|B|R>> |r红桃♥视为|G宴会|r。\n'
1038 '|B|R>> |r梅花♣视为|G地图炮|r。\n'
1039 '|B|R>> |r方片♦视为|G五谷丰登|r。\n'
1040 '\n'
1041 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
1042 '\n'
1043 '|DB(画师:霏茶,CV:shourei小N)|r'
1044 )
1045 is_action_valid = equip_iav
1046 effect_string = suppress_launch_card_effect_string
1049@ui_meta(equipment.GrimoireSkill)
1050class GrimoireSkill:
1051 # Skill
1052 name = '魔导书'
1054 def clickable(self, game):
1055 me = game.me
1056 t = me.tags
1057 if t['grimoire_tag'] >= t['turn_count']:
1058 return False
1060 try:
1061 act = game.action_stack[-1]
1062 if isinstance(act, actions.ActionStage):
1063 if me.tags['freeattack'] >= me.tags['turn_count']:
1064 return True
1066 if me.tags['vitality'] > 0:
1067 return True
1069 if me.has_skill(equipment.ElementalReactorSkill):
1070 return True
1072 except IndexError:
1073 pass
1075 return False
1077 def is_action_valid(self, sk, tl):
1078 assert sk.is_card(equipment.GrimoireSkill)
1079 acards = sk.associated_cards
1080 if not (len(acards)) == 1:
1081 return (False, '请选择一张牌')
1082 else:
1083 s = sk.lookup_tbl[acards[0].suit].ui_meta.name
1084 return (True, '发动【%s】' % s)
1086 def effect_string(self, act):
1087 # for LaunchCard.ui_meta.effect_string
1088 source = act.source
1089 card = act.card
1090 return (
1091 '|G【%s】|r抓起一张牌放入|G魔导书|r' +
1092 ',念动咒语,发动了|G%s|r。'
1093 ) % (
1094 source.ui_meta.name,
1095 card.lookup_tbl[card.associated_cards[0].suit].ui_meta.name
1096 )
1098 def sound_effect(self, act):
1099 return 'thb-cv-card_grimoire'
1102@ui_meta(equipment.SinsackHatAction)
1103class SinsackHatAction:
1104 fatetell_display_name = '头套'
1106 def effect_string_before(self, act):
1107 return '看着戴着|G头套|r的|G【%s】|r,真正的的罪袋们都兴奋了起来!' % (
1108 act.target.ui_meta.name,
1109 )
1112@ui_meta(equipment.SinsackHat)
1113class SinsackHat:
1114 # Skill
1115 name = '头套'
1118@ui_meta(definition.SinsackHatCard)
1119class SinsackHatCard:
1120 # action_stage meta
1121 name = '头套'
1122 image = 'thb-card-sinsackhat'
1123 image_small = 'thb-card-small-sinsackhat'
1124 description = (
1125 '|R罪袋的头套|r\n\n'
1126 '对距离2以内的一名角色使用。\n'
1127 '装备|G罪袋的头套|r的角色需在判定阶段后进行一次判定,若为黑桃1-8,则目标角色受到2点伤害,并且将|G罪袋的头套|r收入手牌。\n'
1128 '|DB(画师:霏茶,CV:大白)|r'
1129 )
1131 def is_action_valid(self, c, tl):
1132 if not tl:
1133 return (False, '请选择目标')
1134 t = tl[0]
1135 if self.me is t:
1136 return (True, '真的要自己戴上吗?')
1137 return (True, '是这样的,这个不是胖次……不不,真的没有胖次')
1139 effect_string = suppress_launch_card_effect_string