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

## 121 statements 118 run 3 missing 0 excluded 3 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# -- third party --

6# -- own --

7 from thb import actions

8 from thb.actions import PlayerTurn, ttags

9 from thb.cards import basic, base, definition

10 from thb.meta.common import ui_meta

11

12

13# -- code --

14@ui_meta(base.DummyCard)

15 class DummyCard:

16 pass

17

18

19@ui_meta(definition.AttackCard)

20 class AttackCard:

21 # action_stage meta

22 image = 'thb-card-attack'

23 name = '弹幕'

24 description = (

25 '|R弹幕|r\n\n'

26 '出牌阶段，消耗1点干劲，对你攻击范围内的一名其他角色使用，对该角色造成1点伤害。\n'

27 '|B|R>> |r默认情况下，你的攻击范围是1。\n'

28 '|B|R>> |r干劲在出牌阶段开始时恢复成1点。\n'

29 '\n'

30 '|DB（画师：霏茶，CV：VV）|r'

31 )

32

33 def is_action_valid(self, c, tl):

34 if not tl:

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

36

37 return (True, '来一发！')

38

39 def sound_effect(self, act):

40 if not isinstance(act, actions.ActionStageLaunchCard):

41 return 'thb-cv-card_attack1'

42

43 g = self.game

44 current = PlayerTurn.get_current(g).target

45

46 if act.source is not current: 46 ↛ 47 line 46 didn't jump to line 47, because the condition on line 46 was never true

47 return 'thb-cv-card_attack1'

48

49 ttags(current)['__attack_graze_count'] += 1

50

51 return [

52 'thb-cv-card_attack1',

53 'thb-cv-card_attack2',

54 'thb-cv-card_attack3',

55 'thb-cv-card_attack4',

56 ][ttags(current)['__attack_graze_count'] % 4 - 1]

57

58

59@ui_meta(definition.GrazeCard)

60 class GrazeCard:

61 # action_stage meta

62 name = '擦弹'

63 image = 'thb-card-graze'

64 description = (

65 '|R擦弹|r\n\n'

66 '当你受到|G弹幕|r的攻击时，你可以使用一张|G擦弹|r来抵消|G弹幕|r的效果。\n'

67 '|B|R>> |r默认情况下，|G擦弹|r只能在回合外使用或打出。\n\n'

68 '|DB（画师：霏茶，CV：小羽）|r'

69 )

70

71 def is_action_valid(self, c, tl):

72 return (False, '你不能主动使用擦弹')

73

74 def effect_string(self, act):

75 return '|G【%s】|r使用了|G%s|r。' % (

76 act.source.ui_meta.name,

77 act.card.ui_meta.name

78 )

79

80 def sound_effect(self, act):

81 if not isinstance(act, actions.LaunchCard): 81 ↛ 82 line 81 didn't jump to line 82, because the condition on line 81 was never true

82 return 'thb-cv-card_graze1'

83

84 g = self.game

85 try:

86 current = PlayerTurn.get_current(g).target

87 except IndexError:

88 return 'thb-cv-card_graze1'

89

90 if act.source is not current:

91 return 'thb-cv-card_graze1'

92

93 cnt = ttags(current)['__attack_graze_count']

94 if not cnt:

95 return 'thb-cv-card_graze1'

96

97 return [

98 'thb-cv-card_graze1',

99 'thb-cv-card_graze2',

100 'thb-cv-card_graze3',

101 'thb-cv-card_graze4',

102 ][cnt % 4 - 1]

103

104

105@ui_meta(definition.WineCard)

106 class WineCard:

107 # action_stage meta

108 name = '酒'

109 image = 'thb-card-wine'

110 description = (

111 '|R酒|r\n\n'

112 '出牌阶段，对自己使用。使用后获得|B喝醉|r状态。\n'

113 '|B喝醉|r状态下，使用【弹幕】造成的伤害+1，受到致命伤害时伤害-1。\n'

114 '|B|R>> |r 效果触发或者到了自己的准备阶段开始时须弃掉|B喝醉|r状态。\n'

115 '|B|R>> |r 你可以于喝醉状态下继续使用酒，但效果不叠加。\n\n'

116 '|DB（画师：霏茶，CV：shourei小N）|r'

117 )

118

119 def is_action_valid(self, c, tl):

120 me = self.me

121 if me.tags.get('wine', False):

122 return (True, '你已经醉了，还要再喝吗？')

123 return (True, '青岛啤酒，神主也爱喝！')

124

125 def sound_effect(self, act):

126 return 'thb-cv-card_wine'

127

128

129@ui_meta(basic.Wine)

130 class Wine:

131 def effect_string(self, act):

132 return '|G【%s】|r喝醉了…' % act.target.ui_meta.name

133

134

135@ui_meta(basic.WineRevive)

136 class WineRevive:

137 def effect_string(self, act):

138 return '|G【%s】|r醒酒了。' % act.target.ui_meta.name

139

140

141@ui_meta(definition.ExinwanCard)

142 class ExinwanCard:

143 # action_stage meta

144 name = '恶心丸'

145 image = 'thb-card-exinwan'

146 description = (

147 '|R恶心丸|r\n'

148 '\n'

149 '出牌阶段，对自己使用。使用时没有额外效果。当此牌以任意的方式进入弃牌堆时，引发弃牌动作的角色需选择其中一项执行：\n'

150 '|B|R>> |r受到1点无来源伤害。\n'

151 '|B|R>> |r弃置两张牌。\n'

152 '\n'

153 '|B|R! |r 当你因为其他角色装备效果(如他人发动白楼剑特效）或技能效果（如正邪挑拨，秦心暗黑能乐）而将恶心丸主动置入弃牌堆时，恶心丸的弃置者视为该角色。\n'

154 '\n'

155 '|DB（画师：霏茶，CV：shourei小N）|r'

156 )

157

158 def is_action_valid(self, c, tl):

159 return (True, '哼，哼，哼哼……')

160

161

162@ui_meta(basic.ExinwanEffect)

163 class ExinwanEffect:

164 # choose_card meta

165 def choose_card_text(self, act, cards):

166 if act.cond(cards):

167 return (True, '节操给你，离我远点！')

168 else:

169 return (False, '请选择两张牌（不选则受到一点无源伤害）')

170

171 def effect_string_before(self, act):

172 return '|G【%s】|r被恶心到了！' % act.target.ui_meta.name

173

174 def sound_effect(self, act):

175 return 'thb-cv-card_exinwan'

176

177

178@ui_meta(basic.UseGraze)

179 class UseGraze:

180 # choose_card meta

181

182 def choose_card_text(self, act, cards):

183 if act.cond(cards):

184 return (True, '我闪！')

185 else:

186 return (False, '请打出一张【擦弹】…')

187

188 def effect_string(self, act):

189 if not act.succeeded: return None

190 t = act.target

191 return '|G【%s】|r打出了|G%s|r。' % (

192 t.ui_meta.name,

193 act.card.ui_meta.name,

194 )

195

196

197@ui_meta(basic.LaunchGraze)

198 class LaunchGraze:

199 # choose_card meta

200

201 def choose_card_text(self, act, cards):

202 if act.cond(cards):

203 return (True, '我闪！')

204 else:

205 return (False, '请使用一张【擦弹】抵消【弹幕】效果…')

206

207

208@ui_meta(basic.UseAttack)

209 class UseAttack:

210 # choose_card meta

211 def choose_card_text(self, act, cards):

212 if act.cond(cards):

213 return (True, '打架？来吧！')

214 else:

215 return (False, '请打出一张弹幕…')

216

217 def effect_string(self, act):

218 if not act.succeeded: return None

219 t = act.target

220 return '|G【%s】|r打出了|G%s|r。' % (

221 t.ui_meta.name,

222 act.card.ui_meta.name,

223 )

224

225

226@ui_meta(definition.HealCard)

227 class HealCard:

228 # action_stage meta

229 image = 'thb-card-heal'

230 name = '麻薯'

231 description = (

232 '|R麻薯|r\n'

233 '\n'

234 '你可以在如下状况中使用，回复1点体力：\n'

235 '|B|R>> |r在你的出牌阶段且你的当前体力小于最大体力。\n'

236 '|B|R>> |r当有角色处于濒死状态时。\n'

237 '\n'

238 '|DB（画师：霏茶，CV：VV）|r'

239 )

240

241 def is_action_valid(self, c, tl):

242 target = tl[0]

243

244 if target.life >= target.maxlife:

245 return (False, '您已经吃饱了')

246 else:

247 return (True, '来一口，精神焕发！')

248

249 def sound_effect(self, act):

250 return 'thb-cv-card_heal'

251

252

253@ui_meta(basic.AskForHeal)

254 class AskForHeal:

255 # choose_card meta

256 def choose_card_text(self, act, cards):

257 if act.cond(cards):

258 return (True, '神说，你不能在这里被击坠(对%s使用)' % act.source.ui_meta.name)

259 else:

260 return (False, '请选择一张【麻薯】(对%s使用)…' % act.source.ui_meta.name)

261

262

263@ui_meta(basic.Heal)

264 class Heal:

265 def effect_string(self, act):

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

267 return '|G【%s】|r回复了%d点体力。' % (

268 act.target.ui_meta.name, act.amount

269 )