Hide keyboard shortcuts

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 

3 

4# -- stdlib -- 

5import itertools 

6import random 

7 

8# -- third party -- 

9# -- own -- 

10from thb.cards import definition, spellcard 

11from thb.meta.common import ui_meta 

12 

13 

14# -- code -- 

15@ui_meta(definition.DemolitionCard) 

16class DemolitionCard: 

17 # action_stage meta 

18 image = 'thb-card-demolition' 

19 name = '城管执法' 

20 description = ( 

21 '|R城管执法|r\n\n' 

22 '非延时符卡。\n' 

23 '出牌阶段,对一名其他角色使用,弃置其区域内的一张牌。\n\n' 

24 '|DB(画师:霏茶,CV:shourei小N)|r' 

25 ) 

26 

27 def is_action_valid(self, c, tl): 

28 if not tl: 

29 return (False, '请选择拆除目标') 

30 

31 tgt = tl[0] 

32 if not sum([len(l) for l in [tgt.cards, tgt.showncards, tgt.equips, tgt.fatetell]]): 

33 return (False, '这货已经没有牌了') 

34 else: 

35 return (True, '嗯,你的牌太多了') 

36 

37 def sound_effect(self, act): 

38 return 'thb-cv-card_demolition' 

39 

40 

41@ui_meta(spellcard.Demolition) 

42class Demolition: 

43 def effect_string(self, act): 

44 if not act.succeeded: return None 44 ↛ exitline 44 didn't return from function 'effect_string', because the return on line 44 wasn't executed

45 return '|G【%s】|r卸掉了|G【%s】|r的%s。' % ( 

46 act.source.ui_meta.name, 

47 act.target.ui_meta.name, 

48 self.card_desc(act.card), 

49 ) 

50 

51 

52@ui_meta(definition.RejectCard) 

53class RejectCard: 

54 # action_stage meta 

55 name = '好人卡' 

56 image = 'thb-card-reject' 

57 description = ( 

58 '|R好人卡|r\n\n' 

59 '非延时符卡。\n' 

60 '一张符卡对一名目标角色生效前,你可以使用此牌来抵消该符卡对其目标角色产生的效果。\n\n' 

61 '|DB(画师:霏茶,CV:VV)' 

62 ) 

63 

64 def is_action_valid(self, c, tl): 

65 return (False, '你不能主动出好人卡') 

66 

67 def effect_string(self, act): 

68 return '|G【%s】|r为|G【%s】|r受到的|G%s|r使用了|G%s|r。' % ( 

69 act.source.ui_meta.name, 

70 act.target.ui_meta.name, 

71 act.force_action.target_act.associated_card.ui_meta.name, 

72 act.card.ui_meta.name, 

73 ) 

74 

75 def sound_effect(self, act): 

76 return 'thb-cv-card_reject' 

77 

78 def has_reject_card(self, p): 

79 from thb.cards.definition import RejectCard as RC 

80 if any([c.is_card(RC) for c in itertools.chain(p.cards, p.showncards)]): 

81 return True 

82 

83 from thb.characters import reimu 

84 if p.has_skill(reimu.SpiritualAttack) and not p.dead: 

85 return True 

86 

87 return False 

88 

89 

90@ui_meta(spellcard.RejectHandler) 

91class RejectHandler: 

92 # choose_card meta 

93 def choose_card_text(self, act, cards): 

94 c = act.target_act.associated_card 

95 name = c.ui_meta.name 

96 

97 s = '【%s】受到的【%s】' % ( 

98 act.target_act.target.ui_meta.name, 

99 name, 

100 ) 

101 

102 if act.cond(cards): 

103 return (True, '对不起,你是一个好人(%s)' % s) 

104 else: 

105 return (False, '请选择一张好人卡(%s)' % s) 

106 

107 

108@ui_meta(definition.SealingArrayCard) 

109class SealingArrayCard: 

110 # action_stage meta 

111 name = '封魔阵' 

112 image = 'thb-card-sealarray' 

113 tag_anim = lambda c: 'thb-tag-sealarray' 113 ↛ exitline 113 didn't run the lambda on line 113

114 description = ( 

115 '|R封魔阵|r\n\n' 

116 '延时类符卡。\n' 

117 '出牌阶段,对一名其他角色使用,将此牌横置于该角色的判定区内。该角色的判定阶段,需进行一次判定然后弃置此牌。若判定结果不为红桃,跳过其出牌阶段。\n' 

118 '|B|R>> |r判定开始前,你可以使用【好人卡】抵消该符卡的效果(抵消后弃掉【封魔阵】)。\n\n' 

119 '|DB(画师:霏茶,CV:shourei小N)|r' 

120 ) 

121 

122 def is_action_valid(self, c, tl): 

123 if len(tl) != 1: 

124 return (False, '请选择封魔阵的目标') 

125 t = tl[0] 

126 if self.me is t: 

127 return (False, '你不能跟自己过不去啊!') 

128 

129 return (True, '画个圈圈诅咒你!') 

130 

131 def sound_effect(self, act): 

132 return 'thb-cv-card_sealarray' 

133 

134 

135@ui_meta(spellcard.SealingArray) 

136class SealingArray: 

137 def effect_string(self, act): 

138 tgt = act.target 

139 if act.succeeded: 

140 return '|G【%s】|r被困在了封魔阵中。' % tgt.ui_meta.name 

141 else: 

142 return '封魔阵没有布置完善,|G【%s】|r侥幸逃了出来!' % tgt.ui_meta.name 

143 

144 

145@ui_meta(definition.FrozenFrogCard) 

146class FrozenFrogCard: 

147 # action_stage meta 

148 name = '冻青蛙' 

149 image = 'thb-card-frozenfrog' 

150 tag_anim = lambda c: 'thb-tag-frozenfrog' 150 ↛ exitline 150 didn't run the lambda on line 150

151 description = ( 

152 '|R冻青蛙|r\n\n' 

153 '延时类符卡。\n' 

154 '出牌阶段,对一名其他角色使用,将此牌横置于该角色的判定区内。该角色的判定阶段,需进行一次判定然后弃置此牌。若判定结果不为黑桃,跳过其摸牌阶段。\n' 

155 '|B|R>> |r判定开始前,你可以使用【好人卡】抵消该符卡的效果(抵消后弃掉【冻青蛙】)。\n\n' 

156 '|DB(画师:霏茶,CV:shourei小N)|r' 

157 ) 

158 

159 def is_action_valid(self, c, tl): 

160 if len(tl) != 1: 

161 return (False, '请选择冻青蛙的目标') 

162 t = tl[0] 

163 if self.me is t: 

164 return (False, '你不能跟自己过不去啊!') 

165 

166 return (True, '伸手党什么的,冻住就好了!') 

167 

168 def sound_effect(self, act): 

169 return 'thb-cv-card_frozenfrog' 

170 

171 

172@ui_meta(spellcard.FrozenFrog) 

173class FrozenFrog: 

174 def effect_string(self, act): 

175 tgt = act.target 

176 if act.succeeded: 

177 return '|G【%s】|r被冻住了……' % tgt.ui_meta.name 

178 else: 

179 return '幻想乡今天大晴,|G【%s】|r没有被冻住~' % tgt.ui_meta.name 

180 

181 

182@ui_meta(definition.NazrinRodCard) 

183class NazrinRodCard: 

184 # action_stage meta 

185 name = '寻龙尺' 

186 image = 'thb-card-nazrinrod' 

187 description = ( 

188 '|R寻龙尺|r\n\n' 

189 '非延时符卡。\n' 

190 '出牌阶段使用,从牌堆摸两张牌。\n\n' 

191 '|DB(画师:霏茶,CV:VV)|r' 

192 ) 

193 

194 def is_action_valid(self, c, tl): 

195 return (True, '看看能找到什么好东西~') 

196 

197 def sound_effect(self, act): 

198 return 'thb-cv-card_nazrinrod' 

199 

200 

201@ui_meta(definition.SinsackCard) 

202class SinsackCard: 

203 # action_stage meta 

204 name = '罪袋' 

205 image = 'thb-card-sinsack' 

206 tag_anim = lambda c: 'thb-tag-sinsack' 206 ↛ exitline 206 didn't run the lambda on line 206

207 description = ( 

208 '|R罪袋|r\n\n' 

209 '延时类符卡。\n' 

210 '出牌阶段,对你使用,将此牌横置于你的判定区内。判定区内有此牌的角色的判定阶段,需进行一次判定:\n' 

211 '|B|R>> |r若判定结果为黑桃1-8,则目标角色受到3点无来源伤害,然后将其置入弃牌堆。\n' 

212 '|B|R>> |r若判定结果不在此范围,则将其移动到下家的判定区内。\n' 

213 '|B|R>> |r判定开始前,你可以使用|B好人卡|r抵消该符卡的效果,并将该|G罪袋|r直接传递给下家。\n\n' 

214 '|DB(画师:霏茶,CV:VV/大白)|r' 

215 ) 

216 

217 def is_action_valid(self, c, tl): 

218 return (True, '别来找我!') 

219 

220 def sound_effect(self, act): 

221 return 'thb-cv-card_sinsack' 

222 

223 

224@ui_meta(spellcard.Sinsack) 

225class Sinsack: 

226 def effect_string(self, act): 

227 tgt = act.target 

228 if act.succeeded: 

229 return '罪袋终于找到了机会,将|G【%s】|r推倒了…' % tgt.ui_meta.name 

230 

231 

232@ui_meta(spellcard.SinsackDamage) 

233class SinsackDamage: 

234 def sound_effect(self, act): 

235 return 'thb-cv-card_sinsack_effect' 

236 

237 

238@ui_meta(definition.YukariDimensionCard) 

239class YukariDimensionCard: 

240 # action_stage meta 

241 image = 'thb-card-yukaridimension' 

242 name = '隙间' 

243 

244 description = ( 

245 '|R隙间|r\n\n' 

246 '非延时符卡。\n' 

247 '出牌阶段,对距离为1的一名其他角色使用,获得其区域内的一张牌。\n\n' 

248 '|DB(画师:霏茶,CV:VV)|r' 

249 ) 

250 

251 def is_action_valid(self, c, tl): 

252 if not tl: 

253 return (False, '请选择目标') 

254 

255 target = tl[0] 

256 if not (target.cards or target.showncards or target.equips or target.fatetell): 

257 return (False, '这货已经没有牌了') 

258 else: 

259 return (True, '请把胖次给我!') 

260 

261 def sound_effect(self, act): 

262 return 'thb-cv-card_dimension' 

263 

264 

265@ui_meta(spellcard.YukariDimension) 

266class YukariDimension: 

267 def effect_string(self, act): 

268 src, tgt = act.source, act.target 

269 if act.succeeded: 269 ↛ exitline 269 didn't return from function 'effect_string', because the condition on line 269 was never false

270 return '|G【%s】|r透过隙间拿走了|G【%s】|r的1张牌。' % ( 

271 src.ui_meta.name, 

272 tgt.ui_meta.name 

273 ) 

274 

275 

276@ui_meta(definition.DuelCard) 

277class DuelCard: 

278 # action_stage meta 

279 image = 'thb-card-duel' 

280 name = '弹幕战' 

281 description = ( 

282 '|R弹幕战|r\n\n' 

283 '非延时符卡。\n' 

284 '出牌阶段,对一名其他角色使用,由目标角色开始,轮流打出一张【弹幕】。首先不打出【弹幕】的一方受到另一方造成的1点伤害。\n\n' 

285 '|DB(画师:霏茶,CV:小羽)|r' 

286 ) 

287 

288 def is_action_valid(self, c, tl): 

289 if not tl: 

290 return (False, '请选择弹幕战的目标') 

291 

292 return (True, '来,战个痛快!') 

293 

294 def sound_effect(self, act): 

295 return 'thb-cv-card_duel' 

296 

297 

298@ui_meta(definition.MapCannonCard) 

299class MapCannonCard: 

300 image = 'thb-card-mapcannon' 

301 name = '地图炮' 

302 description = ( 

303 '|R地图炮|r\n\n' 

304 '群体符卡。非延时符卡。\n' 

305 '出牌阶段,对除你以外的所有其他角色使用,目标角色需依次打出一张【擦弹】,否则该角色受到1点伤害。\n\n' 

306 '|DB(画师:霏茶,CV:VV)|r' 

307 ) 

308 

309 def is_action_valid(self, c, tl): 

310 return (True, '一个都不能跑!') 

311 

312 def sound_effect(self, act): 

313 return 'thb-cv-card_mapcannon' 

314 

315 

316@ui_meta(definition.DemonParadeCard) 

317class DemonParadeCard: 

318 image = 'thb-card-demonparade' 

319 name = '百鬼夜行' 

320 description = ( 

321 '|R百鬼夜行|r\n\n' 

322 '群体符卡。非延时符卡。\n' 

323 '出牌阶段,对除你以外的所有其他角色使用,目标角色需依次打出一张|G弹幕|r,否则该角色受到1点伤害。\n\n' 

324 '|DB(画师:霏茶,CV:小羽)|r' 

325 ) 

326 

327 def is_action_valid(self, c, tl): 

328 return (True, '一只鬼,两只鬼,三只鬼……') 

329 

330 def sound_effect(self, act): 

331 return 'thb-cv-card_demonparade' 

332 

333 

334@ui_meta(definition.FeastCard) 

335class FeastCard: 

336 # action_stage meta 

337 image = 'thb-card-feast' 

338 name = '宴会' 

339 description = ( 

340 '|R宴会|r\n\n' 

341 '群体符卡。非延时符卡。\n' 

342 '出牌阶段,对所有角色使用。已受伤的角色回复一点体力,未受伤的角色获得|B喝醉|r状态。\n\n' 

343 '|DB(画师:霏茶,CV:VV)|r' 

344 ) 

345 

346 def is_action_valid(self, c, tl): 

347 return (True, '开宴啦~~') 

348 

349 def sound_effect(self, act): 

350 return random.choice([ 

351 'thb-cv-card_feast1', 

352 'thb-cv-card_feast2', 

353 'thb-cv-card_feast3', 

354 ]) 

355 

356 

357@ui_meta(definition.HarvestCard) 

358class HarvestCard: 

359 # action_stage meta 

360 image = 'thb-card-harvest' 

361 name = '五谷丰登' 

362 description = ( 

363 '|R五谷丰登|r\n\n' 

364 '群体符卡。非延时符卡。\n' 

365 '出牌阶段,对所有角色使用,你从牌堆顶亮出等同于现存角色数量的牌,目标角色依次选择并获得这些牌中的一张。\n\n' 

366 '|DB(画师:霏茶,CV:VV)|r' 

367 ) 

368 

369 def is_action_valid(self, c, tl): 

370 return (True, '麻薯会有的,节操是没有的!') 

371 

372 def sound_effect(self, act): 

373 return 'thb-cv-card_harvest' 

374 

375 

376@ui_meta(spellcard.HarvestEffect) 

377class HarvestEffect: 

378 def effect_string(self, act): 

379 if not act.succeeded: return None 379 ↛ exitline 379 didn't return from function 'effect_string', because the return on line 379 wasn't executed

380 tgt = act.target 

381 c = act.card 

382 return '|G【%s】|r获得了|G%s|r。' % ( 

383 tgt.ui_meta.name, 

384 self.card_desc(c), 

385 ) 

386 

387 

388@ui_meta(definition.DollControlCard) 

389class DollControlCard: 

390 # action_stage meta 

391 name = '人形操控' 

392 image = 'thb-card-dollcontrol' 

393 description = ( 

394 '|R人形操控|r\n\n' 

395 '非延时符卡。\n' 

396 '出牌阶段,对装备区内有武器牌的一名其他角色使用,令其选择一项:对其攻击范围内一名由你指定的角色使用一张【弹幕】,或将武器交给你。\n\n' 

397 '|DB(画师:霏茶,CV:小羽)|r' 

398 ) 

399 custom_ray = True 

400 

401 def is_action_valid(self, c, tl): 

402 n = len(tl) 

403 if n == 0: 

404 return (False, '请选择被控者') 

405 

406 if tl[0] is self.me: 

407 return (False, '你不可以控制你自己') 

408 

409 if all(e.equipment_category != 'weapon' for e in tl[0].equips): 

410 return (False, '被控者没有武器!') 

411 

412 if n == 1: 

413 return (False, '请选择被控者的攻击目标') 

414 elif n == 2: 414 ↛ exitline 414 didn't return from function 'is_action_valid', because the condition on line 414 was never false

415 from thb.actions import LaunchCard 

416 from thb.cards.definition import AttackCard 

417 c = AttackCard() 

418 lc = LaunchCard(tl[0], [tl[1]], c) 

419 if not lc.can_fire(): 

420 return (False, '被控者无法向目标出【弹幕】!') 

421 return (True, '乖,听话!') 

422 

423 def sound_effect(self, act): 

424 return 'thb-cv-card_dollcontrol' 

425 

426 

427@ui_meta(spellcard.DollControl) 

428class DollControl: 

429 # choose card meta 

430 def choose_card_text(self, act, cards): 

431 if act.cond(cards): 

432 return (True, '那好吧…') 

433 else: 

434 return (False, '请出【弹幕】(否则你的武器会被拿走)') 

435 

436 def ray(self, act): 

437 src = act.source 

438 tl = act.tl 

439 return [(src, tl[0]), (tl[0], tl[1])] 

440 

441 

442@ui_meta(definition.DonationBoxCard) 

443class DonationBoxCard: 

444 # action_stage meta 

445 name = '赛钱箱' 

446 image = 'thb-card-donationbox' 

447 description = ( 

448 '|R赛钱箱|r\n\n' 

449 '非延时符卡。\n' 

450 '出牌阶段,对至多两名其他角色使用,目标角色需将自己的一张牌置入你的明牌区。\n\n' 

451 '|DB(画师:霏茶,CV:shourei小N)|r' 

452 ) 

453 

454 def is_action_valid(self, c, tl): 

455 n = len(tl) 

456 if not n: 

457 return (False, '请选择1-2名玩家') 

458 

459 for t in tl: 

460 if not (t.cards or t.showncards or t.equips): 

461 return (False, '目标没有可以给你的牌') 

462 

463 return (True, '纳奉!纳奉!') 

464 

465 def sound_effect(self, act): 

466 return 'thb-cv-card_donationbox' 

467 

468 

469@ui_meta(spellcard.DonationBoxEffect) 

470class DonationBoxEffect: 

471 # choose card meta 

472 def choose_card_text(self, act, cards): 

473 if act.cond(cards): 

474 return (True, '这是抢劫啊!') 

475 else: 

476 return (False, '请选择一张牌(否则会随机选择一张)')