# Coverage for thb/meta/cards/equipment.py : 97%

## 499 statements 486 run 13 missing 0 excluded 5 partial

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 -*-

2 from __future__ import annotations

3

4# -- stdlib --

5 from typing import Optional

6 import random

7

8# -- third party --

9# -- own --

10 from thb import actions

11 from thb.actions import ttags

12 from thb.cards import definition, equipment

13 from thb.cards.base import Card

14 from thb.meta.common import ui_meta

15 from utils.misc import BatchList

16

17

18# -- code --

19 def equip_iav(self, cl, tl):

20 return (True, '配上好装备，不再掉节操！')

21

22

23 def suppress_launch_card_effect_string(self, act):

24 return None

25

26

27@ui_meta(equipment.WearEquipmentAction)

28 class WearEquipmentAction:

29

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 )

35

36

37@ui_meta(equipment.WeaponReforgeHandler)

38 class WeaponReforgeHandler:

39 choose_option_prompt = '你希望重铸这张牌么？'

40 choose_option_buttons = (('重铸', True), ('装备', False))

41

42

43@ui_meta(equipment.ReforgeWeapon)

44 class 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 )

50

51

52@ui_meta(definition.OpticalCloakCard)

53 class 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 )

63

64 is_action_valid = equip_iav

65 effect_string = suppress_launch_card_effect_string

66

67

68@ui_meta(equipment.OpticalCloakSkill)

69 class OpticalCloakSkill:

70 # Skill

71 name = '光学迷彩'

72

73 def sound_effect(self, act):

74 return 'thb-cv-card_opticalcloak'

75

76 def effect_string(self, act):

77 return definition.GrazeCard.ui_meta.effect_string(act)

78

79

80@ui_meta(equipment.OpticalCloakHandler)

81 class OpticalCloakHandler:

82 # choose_option

83 choose_option_buttons = (('发动', True), ('不发动', False))

84 choose_option_prompt = '你要发动【光学迷彩】吗？'

85

86

87@ui_meta(equipment.OpticalCloak)

88 class OpticalCloak:

89 fatetell_display_name = '光学迷彩'

90

91 def effect_string_before(self, act):

92 return '|G【%s】|r祭起了|G光学迷彩|r…' % (

93 act.target.ui_meta.name,

94 )

95

96 def effect_string(self, act):

97 if act.succeeded:

98 return '效果拔群！'

99 else:

100 return '但是被看穿了…'

101

102

103@ui_meta(definition.MomijiShieldCard)

104 class 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 )

114

115 is_action_valid = equip_iav

116 effect_string = suppress_launch_card_effect_string

117

118

119@ui_meta(equipment.MomijiShieldSkill)

120 class MomijiShieldSkill:

121 # Skill

122 name = '天狗盾'

123

124

125@ui_meta(equipment.MomijiShield)

126 class MomijiShield:

127 def effect_string(self, act):

128 return '被|G天狗盾|r挡下了…'

129

130 def sound_effect(self, act):

131 return 'thb-cv-card_momijishield'

132

133

134 ufo_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)

142

143

144@ui_meta(definition.GreenUFOCard)

145 class 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

151

152 is_action_valid = equip_iav

153 effect_string = suppress_launch_card_effect_string

154

155

156@ui_meta(equipment.GreenUFOSkill)

157 class GreenUFOSkill:

158 # Skill

159 name = '绿色UFO'

160 no_display = True

161

162

163@ui_meta(definition.RedUFOCard)

164 class 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

170

171 is_action_valid = equip_iav

172 effect_string = suppress_launch_card_effect_string

173

174

175@ui_meta(equipment.RedUFOSkill)

176 class RedUFOSkill:

177 # Skill

178 name = '红色UFO'

179 no_display = True

180

181

182@ui_meta(definition.RoukankenCard)

183 class 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

199

200

201@ui_meta(equipment.RoukankenSkill)

202 class RoukankenSkill:

203 # Skill

204 name = '楼观剑'

205

206

207@ui_meta(equipment.Roukanken)

208 class Roukanken:

209 def effect_string_apply(self, act):

210 return '没有什么防具是|G楼观剑|r斩不断的！'

211

212 def sound_effect(self, act):

213 return 'thb-cv-card_roukanken'

214

215

216@ui_meta(definition.ElementalReactorCard)

217 class 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 )

231

232 is_action_valid = equip_iav

233 effect_string = suppress_launch_card_effect_string

234

235

236@ui_meta(equipment.ElementalReactorSkill)

237 class ElementalReactorSkill:

238 # Skill

239 name = '八卦炉'

240

241

242@ui_meta(definition.UmbrellaCard)

243 class 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 )

253

254 is_action_valid = equip_iav

255 effect_string = suppress_launch_card_effect_string

256

257

258@ui_meta(equipment.UmbrellaSkill)

259 class UmbrellaSkill:

260 # Skill

261 name = '紫的阳伞'

262

263

264@ui_meta(equipment.UmbrellaEffect)

265 class 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 = ''

275

276 return '|G【%s】|r受到的%s效果被|G阳伞|r挡下了…' % (

277 dmg.target.ui_meta.name, s,

278 )

279

280 def sound_effect(self, act):

281 return 'thb-cv-card_umbrella'

282

283

284@ui_meta(definition.GungnirCard)

285 class 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 )

299

300 is_action_valid = equip_iav

301 effect_string = suppress_launch_card_effect_string

302

303

304@ui_meta(equipment.GungnirSkill)

305 class GungnirSkill:

306 # Skill

307 name = '冈格尼尔'

308

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

316

317 except (IndexError, AttributeError):

318 pass

319

320 return False

321

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, '反正这条也看不到，偷个懒~~~')

331

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)

339

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

349

350 def sound_effect(self, act):

351 return definition.AttackCard.ui_meta.sound_effect(act)

352

353

354@ui_meta(definition.ScarletRhapsodyCard)

355 class 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 )

369

370 is_action_valid = equip_iav

371 effect_string = suppress_launch_card_effect_string

372

373

374@ui_meta(equipment.ScarletRhapsodySkill)

375 class ScarletRhapsodySkill:

376 # Skill

377 name = '绯想之剑'

378

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

386

387 except IndexError:

388 pass

389

390 return False

391

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名玩家）')

399

400 if self.me in tl: 400 ↛ 401 line 400 didn't jump to line 401, because the condition on line 400 was never true

401 return (True, '您真的要自残么？！')

402 else:

403 return (True, '全人类的绯想天！')

404

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)

409

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 )

415

416 def sound_effect(self, act):

417 return 'thb-cv-card_srs'

418

419

420@ui_meta(definition.RepentanceStickCard)

421 class 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 )

436

437 is_action_valid = equip_iav

438 effect_string = suppress_launch_card_effect_string

439

440

441@ui_meta(equipment.RepentanceStickSkill)

442 class RepentanceStickSkill:

443 # Skill

444 name = '悔悟棒'

445

446

447@ui_meta(equipment.RepentanceStickHandler)

448 class RepentanceStickHandler:

449 # choose_option

450 choose_option_buttons = (('发动', True), ('不发动', False))

451 choose_option_prompt = '你要发动【悔悟棒】吗？'

452

453

454@ui_meta(equipment.RepentanceStick)

455 class 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,

462

463 )

464

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 )

471

472 def sound_effect(self, act):

473 return 'thb-cv-card_repentancestick'

474

475

476@ui_meta(definition.IbukiGourdCard)

477 class 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

484

485 description = (

486 '|R伊吹瓢|r\n\n'

487 '装备后：获得立即|B喝醉|r状态。并且，若你在出牌阶段没有造成过伤害，在回合结束阶段获得|B喝醉|r状态。\n\n'

488 '|DB（画师：霏茶）|r'

489 )

490

491

492@ui_meta(equipment.IbukiGourdSkill)

493 class IbukiGourdSkill:

494 # Skill

495 name = '伊吹瓢'

496

497

498@ui_meta(definition.HouraiJewelCard)

499 class 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 )

513

514 is_action_valid = equip_iav

515 effect_string = suppress_launch_card_effect_string

516

517

518@ui_meta(equipment.HouraiJewelSkill)

519 class HouraiJewelSkill:

520 # Skill

521 name = '蓬莱玉枝'

522

523

524@ui_meta(equipment.HouraiJewelHandler)

525 class HouraiJewelHandler:

526 # choose_option

527 choose_option_buttons = (('发动', True), ('不发动', False))

528 choose_option_prompt = '你要发动【蓬莱玉枝】吗？'

529

530

531@ui_meta(equipment.HouraiJewelAttack)

532 class 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 )

540

541

542@ui_meta(definition.MaidenCostumeCard)

543 class 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

555

556

557@ui_meta(equipment.MaidenCostume)

558 class MaidenCostume:

559 # Skill

560 name = '巫女服'

561

562 def sound_effect(self, act):

563 return 'thb-cv-card_maidencostume'

564

565

566@ui_meta(equipment.MaidenCostumeHandler)

567 class MaidenCostumeHandler:

568 # choose_option

569 choose_option_buttons = (('发动', True), ('不发动', False))

570 choose_option_prompt = '你要发动【巫女服】吗？'

571

572

573@ui_meta(equipment.MaidenCostumeAction)

574 class MaidenCostumeAction:

575 fatetell_display_name = '巫女服'

576

577 def effect_string_before(self, act):

578 return (

579 '|G【%s】|r穿了|G巫女服|r，春度爆表，不怕符卡！'

580 ) % (

581 act.source.ui_meta.name,

582 )

583

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 )

591

592

593@ui_meta(definition.HakuroukenCard)

594 class 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

611

612

613@ui_meta(equipment.HakuroukenSkill)

614 class HakuroukenSkill:

615 # Skill

616 name = '白楼剑'

617

618

619@ui_meta(equipment.Hakurouken)

620 class 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, '请弃掉一张牌（否则对方摸一张牌）')

627

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 )

635

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

641

642 def sound_effect(self, act):

643 return 'thb-cv-card_hakurouken'

644

645

646@ui_meta(equipment.HakuroukenHandler)

647 class HakuroukenHandler:

648 # choose_option

649 choose_option_buttons = (('发动', True), ('不发动', False))

650 choose_option_prompt = '你要发动【白楼剑】吗？'

651

652

653@ui_meta(definition.AyaRoundfanCard)

654 class 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

670

671

672@ui_meta(equipment.AyaRoundfanSkill)

673 class AyaRoundfanSkill:

674 # Skill

675 name = '团扇'

676

677

678@ui_meta(equipment.AyaRoundfanHandler)

679 class 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, '请弃掉一张手牌发动团扇（否则不发动）')

686

687

688@ui_meta(equipment.AyaRoundfan)

689 class AyaRoundfan:

690 def effect_string_before(self, act):

691 return (

692 '|G【%s】|r觉得手中的|G团扇|r用起来好顺手，便加大力度试了试…'

693 ) % (

694 act.source.ui_meta.name,

695 )

696

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 )

704

705 def sound_effect(self, act):

706 return random.choice([

707 'thb-cv-card_roundfan1',

708 'thb-cv-card_roundfan2',

709 ])

710

711

712@ui_meta(definition.NenshaPhoneCard)

713 class 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'

726

727 )

728 is_action_valid = equip_iav

729 effect_string = suppress_launch_card_effect_string

730

731

732@ui_meta(equipment.NenshaPhoneSkill)

733 class NenshaPhoneSkill:

734 # Skill

735 name = '念写机'

736

737

738@ui_meta(equipment.NenshaPhoneHandler)

739 class NenshaPhoneHandler:

740 # choose_option

741 choose_option_buttons = (('发动', True), ('不发动', False))

742 choose_option_prompt = '你要发动【念写机】吗？'

743

744

745@ui_meta(equipment.NenshaPhone)

746 class 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 )

754

755 def sound_effect(self, act):

756 return 'thb-cv-card_nenshaphone'

757

758

759@ui_meta(definition.LaevateinCard)

760 class 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

776

777

778@ui_meta(equipment.LaevateinSkill)

779 class LaevateinSkill:

780 # Skill

781 name = '莱瓦汀'

782

783

784@ui_meta(equipment.LaevateinHandler)

785 class 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, '请弃掉两张牌发动莱瓦汀（否则不发动）')

792

793

794@ui_meta(equipment.Laevatein)

795 class Laevatein:

796 def effect_string_before(self, act):

797 return '|G莱瓦汀|r的灭世之炎岂能轻易闪过！'

798

799 def sound_effect(self, act):

800 return 'thb-cv-card_laevatein'

801

802

803@ui_meta(definition.DeathSickleCard)

804 class 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

820

821

822@ui_meta(equipment.DeathSickleSkill)

823 class DeathSickleSkill:

824 # Skill

825 name = '死神之镰'

826

827

828@ui_meta(equipment.DeathSickle)

829 class 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 )

838

839 def sound_effect(self, act):

840 return 'thb-cv-card_deathsickle'

841

842

843@ui_meta(definition.KeystoneCard)

844 class 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

857

858

859@ui_meta(equipment.KeystoneSkill)

860 class KeystoneSkill:

861 # Skill

862 name = '要石'

863

864

865@ui_meta(equipment.Keystone)

866 class Keystone:

867 def effect_string(self, act):

868 return '|G【%s】|r站在|G要石|r上，照着|G罪袋|r的脸一脚踹了下去！' % (

869 act.target.ui_meta.name

870 )

871

872 def sound_effect(self, act):

873 return 'thb-cv-card_keystone'

874

875

876@ui_meta(definition.WitchBroomCard)

877 class 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 )

889

890

891@ui_meta(equipment.WitchBroomSkill)

892 class WitchBroomSkill:

893 # Skill

894 no_display = True

895

896

897@ui_meta(definition.YinYangOrbCard)

898 class 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

910

911

912@ui_meta(equipment.YinYangOrbSkill)

913 class YinYangOrbSkill:

914 # Skill

915 name = '阴阳玉'

916

917

918@ui_meta(equipment.YinYangOrbHandler)

919 class YinYangOrbHandler:

920 # choose_option

921 choose_option_buttons = (('替换', True), ('不替换', False))

922 choose_option_prompt = '你要使用【阴阳玉】替换当前的判定牌吗？'

923

924

925@ui_meta(equipment.YinYangOrb)

926 class 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 )

932

933

934@ui_meta(definition.SuwakoHatCard)

935 class 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

947

948

949@ui_meta(equipment.SuwakoHatSkill)

950 class SuwakoHatSkill:

951 # Skill

952 name = '青蛙帽'

953

954

955@ui_meta(equipment.SuwakoHatEffect)

956 class SuwakoHatEffect:

957 def sound_effect(self, act):

958 return 'thb-cv-card_suwakohat'

959

960

961@ui_meta(definition.YoumuPhantomCard)

962 class 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 )

972

973 is_action_valid = equip_iav

974 effect_string = suppress_launch_card_effect_string

975

976

977@ui_meta(equipment.YoumuPhantomSkill)

978 class YoumuPhantomSkill:

979 # Skill

980 name = '半灵'

981

982

983@ui_meta(equipment.YoumuPhantomHeal)

984 class YoumuPhantomHeal:

985 def sound_effect(self, act):

986 return 'thb-cv-card_phantom'

987

988

989@ui_meta(definition.IceWingCard)

990 class 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 )

1001

1002 is_action_valid = equip_iav

1003 effect_string = suppress_launch_card_effect_string

1004

1005

1006@ui_meta(equipment.IceWingSkill)

1007 class IceWingSkill:

1008 # Skill

1009 name = '⑨的翅膀'

1010

1011

1012@ui_meta(equipment.IceWing)

1013 class 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 )

1019

1020 def sound_effect(self, act):

1021 tgt = act.target

1022 if ttags(tgt)['__icewing_se']:

1023 return None

1024

1025 ttags(tgt)['__icewing_se'] = True

1026 return 'thb-cv-card_icewing'

1027

1028

1029@ui_meta(definition.GrimoireCard)

1030 class 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

1050

1051

1052@ui_meta(equipment.GrimoireSkill)

1053 class GrimoireSkill:

1054 # Skill

1055 name = '魔导书'

1056

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

1063

1064 try:

1065 act = g.action_stack[-1]

1066 if isinstance(act, actions.ActionStage):

1067 if me.tags['freeattack'] >= me.tags['turn_count']: 1067 ↛ 1068 line 1067 didn't jump to line 1068, because the condition on line 1067 was never true

1068 return True

1069

1070 if me.tags['vitality'] > 0:

1071 return True

1072

1073 if me.has_skill(equipment.ElementalReactorSkill): 1073 ↛ 1074 line 1073 didn't jump to line 1074, because the condition on line 1073 was never true

1074 return True

1075

1076 except IndexError:

1077 pass

1078

1079 return False

1080

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)

1089

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 )

1101

1102 def sound_effect(self, act):

1103 return 'thb-cv-card_grimoire'

1104

1105

1106@ui_meta(equipment.SinsackHatAction)

1107 class SinsackHatAction:

1108 fatetell_display_name = '头套'

1109

1110 def effect_string_before(self, act):

1111 return '看着戴着|G头套|r的|G【%s】|r，真正的的罪袋们都兴奋了起来！' % (

1112 act.target.ui_meta.name,

1113 )

1114

1115

1116@ui_meta(equipment.SinsackHat)

1117 class SinsackHat:

1118 # Skill

1119 name = '头套'

1120

1121

1122@ui_meta(definition.SinsackHatCard)

1123 class 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 )

1134

1135 def is_action_valid(self, c, tl):

1136 if not tl: 1136 ↛ 1137 line 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 ↛ 1140 line 1139 didn't jump to line 1140, because the condition on line 1139 was never true

1140 return (True, '真的要自己戴上吗？')

1141 return (True, '是这样的，这个不是胖次……不不，真的没有胖次')

1142

1143 effect_string = suppress_launch_card_effect_string