Coverage for thb/meta/cards/equipment.py : 97%
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):
310 g = self.game
311 me = self.me
312 try:
313 act = g.hybrid_stack[-1]
314 if act.cond([equipment.GungnirSkill(me)]):
315 return True
317 except (IndexError, AttributeError):
318 pass
320 return False
322 def is_complete(self, skill):
323 me = self.me
324 assert skill.is_card(equipment.GungnirSkill)
325 acards = skill.associated_cards
326 if len(acards) != 2:
327 return (False, '请选择2张手牌!')
328 elif any(c.resides_in not in (me.cards, me.showncards) for c in acards):
329 return (False, '只能使用手牌发动!')
330 return (True, '反正这条也看不到,偷个懒~~~')
332 def is_action_valid(self, sk, tl):
333 assert sk.is_card(equipment.GungnirSkill)
334 rst, reason = self.is_complete(sk)
335 if not rst:
336 return (rst, reason)
337 else:
338 return definition.AttackCard().ui_meta.is_action_valid(sk, tl)
340 def effect_string(self, act):
341 # for LaunchCard.effect_string
342 source = act.source
343 target = act.target
344 s = '|G【%s】|r发动了|G冈格尼尔|r之枪,将两张牌当作|G弹幕|r对|G【%s】|r使用。' % (
345 source.ui_meta.name,
346 target.ui_meta.name,
347 )
348 return s
350 def sound_effect(self, act):
351 return definition.AttackCard.ui_meta.sound_effect(act)
354@ui_meta(definition.ScarletRhapsodyCard)
355class ScarletRhapsodyCard:
356 # action_stage meta
357 name = '绯想之剑'
358 image = 'thb-card-scarletrhapsodysword'
359 image_small = 'thb-card-small-scarletrhapsodysword'
360 description = (
361 '|R绯想之剑|r\n'
362 '\n'
363 '攻击范围4,装备后:当你使用的|G弹幕|r是你的最后一张手牌时,你可以为此|G弹幕|r指定至多三名目标。\n'
364 '\n'
365 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
366 '\n'
367 '|DB(画师:霏茶,CV:VV)|r'
368 )
370 is_action_valid = equip_iav
371 effect_string = suppress_launch_card_effect_string
374@ui_meta(equipment.ScarletRhapsodySkill)
375class ScarletRhapsodySkill:
376 # Skill
377 name = '绯想之剑'
379 def clickable(self):
380 g = self.game
381 me = self.me
382 try:
383 act = g.action_stack[-1]
384 if isinstance(act, actions.ActionStage):
385 return act.target is me
387 except IndexError:
388 pass
390 return False
392 def is_action_valid(self, sk, tl):
393 assert sk.is_card(equipment.ScarletRhapsodySkill)
394 if not sk.check():
395 return (False, '请选择你的最后一张【弹幕】!')
396 else:
397 if not tl:
398 return (False, '请选择弹幕的目标(最多可以选择3名玩家)')
400 if self.me in tl: 400 ↛ 401line 400 didn't jump to line 401, because the condition on line 400 was never true
401 return (True, '您真的要自残么?!')
402 else:
403 return (True, '全人类的绯想天!')
405 def effect_string(self, act: actions.LaunchCard) -> Optional[str]:
406 # for LaunchCard.ui_meta.effect_string
407 src = act.source
408 tl = BatchList(act.target_list)
410 return '全人类的绯想天,当然不能只打一个!于是|G【%s】|r选了|G【%s】|r一共%d个目标!' % (
411 src.ui_meta.name,
412 '】|r、|G【'.join(tl.ui_meta.name),
413 len(tl),
414 )
416 def sound_effect(self, act):
417 return 'thb-cv-card_srs'
420@ui_meta(definition.RepentanceStickCard)
421class RepentanceStickCard:
422 # action_stage meta
423 name = '悔悟棒'
424 image = 'thb-card-repentancestick'
425 image_small = 'thb-card-small-repentancestick'
426 description = (
427 '|R悔悟棒|r\n'
428 '\n'
429 '攻击范围2,装备后:当你使用|G弹幕|r造成伤害时,你可以防止此伤害,改为依次弃置目标角色区域内的两张牌。\n'
430 '|B|R>> |r 区域内的牌包括手牌,装备区的牌和判定区的牌。\n'
431 '\n'
432 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
433 '\n'
434 '|DB(画师:霏茶,CV:shourei小N)|r'
435 )
437 is_action_valid = equip_iav
438 effect_string = suppress_launch_card_effect_string
441@ui_meta(equipment.RepentanceStickSkill)
442class RepentanceStickSkill:
443 # Skill
444 name = '悔悟棒'
447@ui_meta(equipment.RepentanceStickHandler)
448class RepentanceStickHandler:
449 # choose_option
450 choose_option_buttons = (('发动', True), ('不发动', False))
451 choose_option_prompt = '你要发动【悔悟棒】吗?'
454@ui_meta(equipment.RepentanceStick)
455class RepentanceStick:
456 def effect_string_before(self, act):
457 return (
458 '|G【%s】|r用|G悔悟棒|r狠狠地敲了|G【%s】|r一通…'
459 ) % (
460 act.source.ui_meta.name,
461 act.target.ui_meta.name,
463 )
465 def effect_string(self, act: equipment.RepentanceStick) -> str:
466 cl = BatchList[Card](act.cards)
467 return '又抢过|G【%s】|r的|G%s|r扔了出去!' % (
468 act.target.ui_meta.name,
469 '|r和|G'.join(cl.ui_meta.name)
470 )
472 def sound_effect(self, act):
473 return 'thb-cv-card_repentancestick'
476@ui_meta(definition.IbukiGourdCard)
477class IbukiGourdCard:
478 # action_stage meta
479 name = '伊吹瓢'
480 image = 'thb-card-ibukigourd'
481 image_small = 'thb-card-small-ibukigourd'
482 is_action_valid = equip_iav
483 effect_string = suppress_launch_card_effect_string
485 description = (
486 '|R伊吹瓢|r\n\n'
487 '装备后:获得立即|B喝醉|r状态。并且,若你在出牌阶段没有造成过伤害,在回合结束阶段获得|B喝醉|r状态。\n\n'
488 '|DB(画师:霏茶)|r'
489 )
492@ui_meta(equipment.IbukiGourdSkill)
493class IbukiGourdSkill:
494 # Skill
495 name = '伊吹瓢'
498@ui_meta(definition.HouraiJewelCard)
499class HouraiJewelCard:
500 # action_stage meta
501 name = '蓬莱玉枝'
502 image = 'thb-card-houraijewel'
503 image_small = 'thb-card-small-houraijewel'
504 description = (
505 '|R蓬莱玉枝|r\n'
506 '\n'
507 '攻击范围1。装备后,你使用的|G弹幕|r时,可以将弹幕的效果转化成如下的符卡效果:造成1点伤害。\n'
508 '\n'
509 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
510 '\n'
511 '|DB(画师:霏茶)|r'
512 )
514 is_action_valid = equip_iav
515 effect_string = suppress_launch_card_effect_string
518@ui_meta(equipment.HouraiJewelSkill)
519class HouraiJewelSkill:
520 # Skill
521 name = '蓬莱玉枝'
524@ui_meta(equipment.HouraiJewelHandler)
525class HouraiJewelHandler:
526 # choose_option
527 choose_option_buttons = (('发动', True), ('不发动', False))
528 choose_option_prompt = '你要发动【蓬莱玉枝】吗?'
531@ui_meta(equipment.HouraiJewelAttack)
532class HouraiJewelAttack:
533 def effect_string_apply(self, act):
534 return (
535 '|G【%s】|r发动了|G蓬莱玉枝|r,包裹着魔法核心的弹幕冲向了|G【%s】|r!'
536 ) % (
537 act.source.ui_meta.name,
538 act.target.ui_meta.name,
539 )
542@ui_meta(definition.MaidenCostumeCard)
543class MaidenCostumeCard:
544 # action_stage meta
545 name = '巫女服'
546 image = 'thb-card-maidencostume'
547 image_small = 'thb-card-small-maidencostume'
548 description = (
549 '|R巫女服|r\n\n'
550 '装备后:当你成为一张符卡的目标时,你可以进行一次判定:若判定牌点数为9到K,则视为你使用了一张|G好人卡|r。\n\n'
551 '|DB(画师:霏茶,CV:VV)|r'
552 )
553 is_action_valid = equip_iav
554 effect_string = suppress_launch_card_effect_string
557@ui_meta(equipment.MaidenCostume)
558class MaidenCostume:
559 # Skill
560 name = '巫女服'
562 def sound_effect(self, act):
563 return 'thb-cv-card_maidencostume'
566@ui_meta(equipment.MaidenCostumeHandler)
567class MaidenCostumeHandler:
568 # choose_option
569 choose_option_buttons = (('发动', True), ('不发动', False))
570 choose_option_prompt = '你要发动【巫女服】吗?'
573@ui_meta(equipment.MaidenCostumeAction)
574class MaidenCostumeAction:
575 fatetell_display_name = '巫女服'
577 def effect_string_before(self, act):
578 return (
579 '|G【%s】|r穿了|G巫女服|r,春度爆表,不怕符卡!'
580 ) % (
581 act.source.ui_meta.name,
582 )
584 def effect_string(self, act):
585 if not act.succeeded:
586 return (
587 '好像|G【%s】|r的春度还是不够用…'
588 ) % (
589 act.source.ui_meta.name,
590 )
593@ui_meta(definition.HakuroukenCard)
594class HakuroukenCard:
595 # action_stage meta
596 name = '白楼剑'
597 image = 'thb-card-hakurouken'
598 image_small = 'thb-card-small-hakurouken'
599 description = (
600 '|R白楼剑|r\n\n'
601 '攻击范围2,装备后:当你使用的草花色|G弹幕|r指定一名目标角色后,你可以令其选择一项:\n'
602 '|B|R>> |r弃置一张手牌。\n'
603 '|B|R>> |r令你摸一张牌。\n'
604 '\n'
605 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
606 '\n'
607 '|DB(画师:霏茶,CV:小羽)|r'
608 )
609 is_action_valid = equip_iav
610 effect_string = suppress_launch_card_effect_string
613@ui_meta(equipment.HakuroukenSkill)
614class HakuroukenSkill:
615 # Skill
616 name = '白楼剑'
619@ui_meta(equipment.Hakurouken)
620class Hakurouken:
621 # choose_card
622 def choose_card_text(self, act, cards):
623 if act.cond(cards):
624 return (True, '弃置这张牌')
625 else:
626 return (False, '请弃掉一张牌(否则对方摸一张牌)')
628 def effect_string_before(self, act):
629 return (
630 '|G【%s】|r祭起了|G白楼剑|r,试图斩断|G【%s】|r的迷惘!'
631 ) % (
632 act.source.ui_meta.name,
633 act.target.ui_meta.name,
634 )
636 def effect_string(self, act):
637 if act.peer_action == 'drop':
638 return '|G【%s】|r弃置了一张牌。' % act.target.ui_meta.name
639 else:
640 return None # DrawCards has it's own prompt
642 def sound_effect(self, act):
643 return 'thb-cv-card_hakurouken'
646@ui_meta(equipment.HakuroukenHandler)
647class HakuroukenHandler:
648 # choose_option
649 choose_option_buttons = (('发动', True), ('不发动', False))
650 choose_option_prompt = '你要发动【白楼剑】吗?'
653@ui_meta(definition.AyaRoundfanCard)
654class AyaRoundfanCard:
655 # action_stage meta
656 name = '团扇'
657 image = 'thb-card-ayaroundfan'
658 image_small = 'thb-card-small-ayaroundfan'
659 description = (
660 '|R团扇|r\n'
661 '\n'
662 '攻击距离5,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,你可以弃置一张手牌,然后弃置其装备区里的一张牌。\n'
663 '\n'
664 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
665 '\n'
666 '|DB(画师:霏茶,CV:VV)|r'
667 )
668 is_action_valid = equip_iav
669 effect_string = suppress_launch_card_effect_string
672@ui_meta(equipment.AyaRoundfanSkill)
673class AyaRoundfanSkill:
674 # Skill
675 name = '团扇'
678@ui_meta(equipment.AyaRoundfanHandler)
679class AyaRoundfanHandler:
680 # choose_card
681 def choose_card_text(self, act, cards):
682 if act.cond(cards):
683 return (True, '这种妨碍拍摄的东西,统统脱掉!')
684 else:
685 return (False, '请弃掉一张手牌发动团扇(否则不发动)')
688@ui_meta(equipment.AyaRoundfan)
689class AyaRoundfan:
690 def effect_string_before(self, act):
691 return (
692 '|G【%s】|r觉得手中的|G团扇|r用起来好顺手,便加大力度试了试…'
693 ) % (
694 act.source.ui_meta.name,
695 )
697 def effect_string(self, act):
698 return (
699 '于是|G【%s】|r的|G%s|r就飞了出去!'
700 ) % (
701 act.target.ui_meta.name,
702 act.card.ui_meta.name,
703 )
705 def sound_effect(self, act):
706 return random.choice([
707 'thb-cv-card_roundfan1',
708 'thb-cv-card_roundfan2',
709 ])
712@ui_meta(definition.NenshaPhoneCard)
713class NenshaPhoneCard:
714 # action_stage meta
715 name = '念写机'
716 image = 'thb-card-nenshaphone'
717 image_small = 'thb-card-small-nenshaphone'
718 description = (
719 '|R念写机|r\n'
720 '\n'
721 '攻击距离4,装备后:当你使用的|G弹幕|r对目标角色造成伤害后,可以将其两张手牌置入明牌区。\n'
722 '\n'
723 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
724 '\n'
725 '|DB(画师:霏茶)|r'
727 )
728 is_action_valid = equip_iav
729 effect_string = suppress_launch_card_effect_string
732@ui_meta(equipment.NenshaPhoneSkill)
733class NenshaPhoneSkill:
734 # Skill
735 name = '念写机'
738@ui_meta(equipment.NenshaPhoneHandler)
739class NenshaPhoneHandler:
740 # choose_option
741 choose_option_buttons = (('发动', True), ('不发动', False))
742 choose_option_prompt = '你要发动【念写机】吗?'
745@ui_meta(equipment.NenshaPhone)
746class NenshaPhone:
747 def effect_string(self, act):
748 return (
749 '|G【%s】|r表示,将|G【%s】|r推倒后拍摄胖次,是记者的自我修养中不可或缺的一部分。'
750 ) % (
751 act.source.ui_meta.name,
752 act.target.ui_meta.name,
753 )
755 def sound_effect(self, act):
756 return 'thb-cv-card_nenshaphone'
759@ui_meta(definition.LaevateinCard)
760class LaevateinCard:
761 # action_stage meta
762 name = '莱瓦汀'
763 image = 'thb-card-laevatein'
764 image_small = 'thb-card-small-laevatein'
765 description = (
766 '|R莱瓦汀|r\n'
767 '\n'
768 '攻击距离3,装备后:当你使用的|G弹幕|r被目标角色使用的|G擦弹|r抵消时,你可以弃置两张牌,令此|G弹幕|r依然生效。\n'
769 '\n'
770 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
771 '\n'
772 '|DB(画师:霏茶,CV:VV)|r'
773 )
774 is_action_valid = equip_iav
775 effect_string = suppress_launch_card_effect_string
778@ui_meta(equipment.LaevateinSkill)
779class LaevateinSkill:
780 # Skill
781 name = '莱瓦汀'
784@ui_meta(equipment.LaevateinHandler)
785class LaevateinHandler:
786 # choose_card
787 def choose_card_text(self, act, cards):
788 if act.cond(cards):
789 return (True, '灭世之炎岂能轻易闪过!')
790 else:
791 return (False, '请弃掉两张牌发动莱瓦汀(否则不发动)')
794@ui_meta(equipment.Laevatein)
795class Laevatein:
796 def effect_string_before(self, act):
797 return '|G莱瓦汀|r的灭世之炎岂能轻易闪过!'
799 def sound_effect(self, act):
800 return 'thb-cv-card_laevatein'
803@ui_meta(definition.DeathSickleCard)
804class DeathSickleCard:
805 # action_stage meta
806 name = '死神之镰'
807 image = 'thb-card-deathsickle'
808 image_small = 'thb-card-small-deathsickle'
809 description = (
810 '|R死神之镰|r\n'
811 '\n'
812 '攻击范围2,装备后:当你使用的【弹幕】对目标角色造成伤害时,若其没有手牌,此伤害+1。\n'
813 '\n'
814 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
815 '\n'
816 '|DB(画师:霏茶,CV:小羽)|r'
817 )
818 is_action_valid = equip_iav
819 effect_string = suppress_launch_card_effect_string
822@ui_meta(equipment.DeathSickleSkill)
823class DeathSickleSkill:
824 # Skill
825 name = '死神之镰'
828@ui_meta(equipment.DeathSickle)
829class DeathSickle:
830 def effect_string(self, act):
831 return (
832 '|G【%s】|r看到|G【%s】|r一副丧家犬的模样,'
833 '手中的|G死神之镰|r不自觉地一狠…'
834 ) % (
835 act.source.ui_meta.name,
836 act.target.ui_meta.name,
837 )
839 def sound_effect(self, act):
840 return 'thb-cv-card_deathsickle'
843@ui_meta(definition.KeystoneCard)
844class KeystoneCard:
845 # action_stage meta
846 name = '要石'
847 image = 'thb-card-keystone'
848 image_small = 'thb-card-small-keystone'
849 description = (
850 '|R要石|r\n\n'
851 '特殊的绿色UFO装备,距离+1\n'
852 '装备后跳过【罪袋】对你的结算。\n\n'
853 '|DB(画师:霏茶,CV:shourei小N)|r'
854 )
855 is_action_valid = equip_iav
856 effect_string = suppress_launch_card_effect_string
859@ui_meta(equipment.KeystoneSkill)
860class KeystoneSkill:
861 # Skill
862 name = '要石'
865@ui_meta(equipment.Keystone)
866class Keystone:
867 def effect_string(self, act):
868 return '|G【%s】|r站在|G要石|r上,照着|G罪袋|r的脸一脚踹了下去!' % (
869 act.target.ui_meta.name
870 )
872 def sound_effect(self, act):
873 return 'thb-cv-card_keystone'
876@ui_meta(definition.WitchBroomCard)
877class WitchBroomCard:
878 # action_stage meta
879 name = '魔女扫把'
880 image = 'thb-card-witchbroom'
881 image_small = 'thb-card-small-witchbroom'
882 is_action_valid = equip_iav
883 effect_string = suppress_launch_card_effect_string
884 description = (
885 '|R魔女扫把|r\n\n'
886 '特殊的红色UFO装备,距离-2。\n\n'
887 '|DB(画师:霏茶)|r'
888 )
891@ui_meta(equipment.WitchBroomSkill)
892class WitchBroomSkill:
893 # Skill
894 no_display = True
897@ui_meta(definition.YinYangOrbCard)
898class YinYangOrbCard:
899 # action_stage meta
900 name = '阴阳玉'
901 image = 'thb-card-yinyangorb'
902 image_small = 'thb-card-small-yinyangorb'
903 description = (
904 '|R阴阳玉|r\n\n'
905 '装备后:在你的判定牌生效前,你可以用装备区内的|G阴阳玉|r替换之。\n\n'
906 '|DB(画师:霏茶)|r'
907 )
908 is_action_valid = equip_iav
909 effect_string = suppress_launch_card_effect_string
912@ui_meta(equipment.YinYangOrbSkill)
913class YinYangOrbSkill:
914 # Skill
915 name = '阴阳玉'
918@ui_meta(equipment.YinYangOrbHandler)
919class YinYangOrbHandler:
920 # choose_option
921 choose_option_buttons = (('替换', True), ('不替换', False))
922 choose_option_prompt = '你要使用【阴阳玉】替换当前的判定牌吗?'
925@ui_meta(equipment.YinYangOrb)
926class YinYangOrb:
927 def effect_string(self, act):
928 return '|G【%s】|r用|G%s|r替换了她的判定牌。' % (
929 act.target.ui_meta.name,
930 self.card_desc(act.card),
931 )
934@ui_meta(definition.SuwakoHatCard)
935class SuwakoHatCard:
936 # action_stage meta
937 name = '青蛙帽'
938 image = 'thb-card-suwakohat'
939 image_small = 'thb-card-small-suwakohat'
940 description = (
941 '|R青蛙帽|r\n\n'
942 '装备后:手牌上限+2。\n\n'
943 '|DB(画师:霏茶,CV:VV)|r'
944 )
945 is_action_valid = equip_iav
946 effect_string = suppress_launch_card_effect_string
949@ui_meta(equipment.SuwakoHatSkill)
950class SuwakoHatSkill:
951 # Skill
952 name = '青蛙帽'
955@ui_meta(equipment.SuwakoHatEffect)
956class SuwakoHatEffect:
957 def sound_effect(self, act):
958 return 'thb-cv-card_suwakohat'
961@ui_meta(definition.YoumuPhantomCard)
962class YoumuPhantomCard:
963 # action_stage meta
964 name = '半灵'
965 image = 'thb-card-phantom'
966 image_small = 'thb-card-small-phantom'
967 description = (
968 '|R半灵|r\n\n'
969 '装备后:增加1点体力上限,当失去装备区里的【半灵】时,你回复1点体力。\n\n'
970 '|DB(画师:霏茶,CV:小羽)|r'
971 )
973 is_action_valid = equip_iav
974 effect_string = suppress_launch_card_effect_string
977@ui_meta(equipment.YoumuPhantomSkill)
978class YoumuPhantomSkill:
979 # Skill
980 name = '半灵'
983@ui_meta(equipment.YoumuPhantomHeal)
984class YoumuPhantomHeal:
985 def sound_effect(self, act):
986 return 'thb-cv-card_phantom'
989@ui_meta(definition.IceWingCard)
990class IceWingCard:
991 # action_stage meta
992 name = '⑨的翅膀'
993 image = 'thb-card-icewing'
994 image_small = 'thb-card-small-icewing'
995 description = (
996 '|R⑨的翅膀|r\n\n'
997 '特殊的红色UFO装备,距离-1。\n\n'
998 '装备后:|G封魔阵|r和|G冻青蛙|r对你无效。\n\n'
999 '|DB(画师:霏茶,CV:VV)|r'
1000 )
1002 is_action_valid = equip_iav
1003 effect_string = suppress_launch_card_effect_string
1006@ui_meta(equipment.IceWingSkill)
1007class IceWingSkill:
1008 # Skill
1009 name = '⑨的翅膀'
1012@ui_meta(equipment.IceWing)
1013class IceWing:
1014 def effect_string(self, act):
1015 return '|G【%s】|r借着|G⑨的翅膀|r飞了出来,|G%s|r没起到什么作用。' % (
1016 act.target.ui_meta.name,
1017 act.action.associated_card.ui_meta.name,
1018 )
1020 def sound_effect(self, act):
1021 tgt = act.target
1022 if ttags(tgt)['__icewing_se']:
1023 return None
1025 ttags(tgt)['__icewing_se'] = True
1026 return 'thb-cv-card_icewing'
1029@ui_meta(definition.GrimoireCard)
1030class GrimoireCard:
1031 # action_stage meta
1032 name = '魔导书'
1033 image = 'thb-card-grimoire'
1034 image_small = 'thb-card-small-grimoire'
1035 description = (
1036 '|R魔导书|r\n'
1037 '\n'
1038 '攻击距离1,装备后,你可以消耗一点干劲并将一张牌按照以下规则使用:\n'
1039 '|B|R>> |r黑桃♠视为|G百鬼夜行|r。\n'
1040 '|B|R>> |r红桃♥视为|G宴会|r。\n'
1041 '|B|R>> |r梅花♣视为|G地图炮|r。\n'
1042 '|B|R>> |r方片♦视为|G五谷丰登|r。\n'
1043 '\n'
1044 '|R出牌阶段你可以消耗1点干劲重铸手牌中的武器|r\n'
1045 '\n'
1046 '|DB(画师:霏茶,CV:shourei小N)|r'
1047 )
1048 is_action_valid = equip_iav
1049 effect_string = suppress_launch_card_effect_string
1052@ui_meta(equipment.GrimoireSkill)
1053class GrimoireSkill:
1054 # Skill
1055 name = '魔导书'
1057 def clickable(self):
1058 g = self.game
1059 me = self.me
1060 t = me.tags
1061 if t['grimoire_tag'] >= t['turn_count']:
1062 return False
1064 try:
1065 act = g.action_stack[-1]
1066 if isinstance(act, actions.ActionStage):
1067 if me.tags['freeattack'] >= me.tags['turn_count']: 1067 ↛ 1068line 1067 didn't jump to line 1068, because the condition on line 1067 was never true
1068 return True
1070 if me.tags['vitality'] > 0:
1071 return True
1073 if me.has_skill(equipment.ElementalReactorSkill): 1073 ↛ 1074line 1073 didn't jump to line 1074, because the condition on line 1073 was never true
1074 return True
1076 except IndexError:
1077 pass
1079 return False
1081 def is_action_valid(self, sk, tl):
1082 assert sk.is_card(equipment.GrimoireSkill)
1083 acards = sk.associated_cards
1084 if not (len(acards)) == 1:
1085 return (False, '请选择一张牌')
1086 else:
1087 s = sk.lookup_tbl[acards[0].suit].ui_meta.name
1088 return (True, '发动【%s】' % s)
1090 def effect_string(self, act):
1091 # for LaunchCard.ui_meta.effect_string
1092 source = act.source
1093 card = act.card
1094 return (
1095 '|G【%s】|r抓起一张牌放入|G魔导书|r' +
1096 ',念动咒语,发动了|G%s|r。'
1097 ) % (
1098 source.ui_meta.name,
1099 card.lookup_tbl[card.associated_cards[0].suit].ui_meta.name
1100 )
1102 def sound_effect(self, act):
1103 return 'thb-cv-card_grimoire'
1106@ui_meta(equipment.SinsackHatAction)
1107class SinsackHatAction:
1108 fatetell_display_name = '头套'
1110 def effect_string_before(self, act):
1111 return '看着戴着|G头套|r的|G【%s】|r,真正的的罪袋们都兴奋了起来!' % (
1112 act.target.ui_meta.name,
1113 )
1116@ui_meta(equipment.SinsackHat)
1117class SinsackHat:
1118 # Skill
1119 name = '头套'
1122@ui_meta(definition.SinsackHatCard)
1123class SinsackHatCard:
1124 # action_stage meta
1125 name = '头套'
1126 image = 'thb-card-sinsackhat'
1127 image_small = 'thb-card-small-sinsackhat'
1128 description = (
1129 '|R罪袋的头套|r\n\n'
1130 '对距离2以内的一名角色使用。\n'
1131 '装备|G罪袋的头套|r的角色需在判定阶段后进行一次判定,若为黑桃1-8,则目标角色受到2点伤害,并且将|G罪袋的头套|r收入手牌。\n'
1132 '|DB(画师:霏茶,CV:大白)|r'
1133 )
1135 def is_action_valid(self, c, tl):
1136 if not tl: 1136 ↛ 1137line 1136 didn't jump to line 1137, because the condition on line 1136 was never true
1137 return (False, '请选择目标')
1138 t = tl[0]
1139 if self.me is t: 1139 ↛ 1140line 1139 didn't jump to line 1140, because the condition on line 1139 was never true
1140 return (True, '真的要自己戴上吗?')
1141 return (True, '是这样的,这个不是胖次……不不,真的没有胖次')
1143 effect_string = suppress_launch_card_effect_string