def unbindkp(self, update: Update, context: CallbackContext) -> bool: """撤销自己的KP权限。只有当前群内KP可以使用该指令。 在撤销KP之后的新KP会自动获取原KP的所有NPC的卡片""" if isprivate(update): return self.errorInfo('发群消息撤销自己的KP权限') gp = self.forcegetgroup(update) if gp.kp is None: return self.errorInfo('本群没有KP', True) if not self.checkaccess(self.forcegetplayer(update), gp) & GROUPKP: return self.errorInfo('你不是KP', True) self.changecardsplid(gp, gp.kp, self.forcegetplayer(0)) kp = gp.kp self.delkp(gp) kp.write() gp.write() self.reply('KP已撤销') if self.getOP(gp.id).find("delcard") != -1: self.popOP(gp.id) return True
def showjoblist(self, update: Update, context: CallbackContext) -> None: """显示职业列表""" if not isprivate(update): self.errorInfo("请在私聊中使用该指令") return rttext = "职业列表:" counts = 0 for job in self.joblist: jobinfo = self.joblist[job] rttext += job + f":\n信用范围 [{str(jobinfo[0])},{str(jobinfo[1])}]\n" rttext += "技能点计算方法:" calcd: Dict[str, int] = jobinfo[2] calcmeth = " 加 ".join("或".join(x.split('_')) + "乘" + str(calcd[x]) for x in calcd) rttext += calcmeth + "\n" rttext += "主要技能:" + "、".join(x for x in jobinfo[3:]) + "\n" counts += 1 if counts == 3: self.reply(rttext) rttext = "" counts = 0 time.sleep(0.2)
def startgame(self, update: Update, context: CallbackContext) -> bool: """开始一场游戏。 这一指令将拷贝本群内所有卡,之后将用拷贝的卡片副本进行游戏,修改属性将不会影响到游戏外的原卡属性。 如果要正常结束游戏,使用`/endgame`可以将游戏的角色卡数据覆写到原本的数据上。 如果要放弃这些游戏内进行的修改,使用`/abortgame`会直接删除这些副本。 `/startgame`:正常地开始游戏,对所有玩家的卡片(type为PL)进行卡片检查。 `/startgame ignore`跳过开始游戏的检查,直接开始游戏。 开始后,bot会询问是否保存聊天文本数据。此时回复cancel或者取消,即可取消开始游戏。""" if isprivate(update): return self.errorInfo("游戏需要在群里进行") gp = self.forcegetgroup(update) kp = self.forcegetplayer(update) if gp.kp != kp: return self.errorInfo("游戏只能由KP发起", True) if gp.game is not None: return self.errorInfo("游戏已经在进行中") if gp.pausedgame is not None: return self.continuegame(update, context) # 检测到游戏暂停中,直接继续 # 开始验证 if not(len(context.args) > 0 and context.args[0] == "ignore"): if not self.checkstart(gp): return False self.reply( "准备开始游戏,是否需要记录聊天文本?如果需要记录文本,请回复'记录',否则不会记录文本。\n\ 回复'cancel'或者'取消'来取消游戏。" ) self.addOP(gp.id, "startgame") return True
def showrule(self, update: Update, context: CallbackContext) -> bool: """显示当前群内的规则。 如果想了解群规则的详情,请查阅setrule指令的帮助: `/help setrule`""" if isprivate(update): return self.errorInfo("请在群内查看规则") gp = self.forcegetgroup(update) rule = gp.rule self.reply(str(rule)) return True
def transferkp(self, update: Update, context: CallbackContext) -> bool: """转移KP权限,只有群管理员可以使用这个指令。 当前群没有KP时或当前群KP为管理员时,无法使用。 `/transferkp --kpid`:将当前群KP权限转移到某个群成员。 如果指定的`kpid`不在群内则无法设定。 `/transferkp`:将当前群KP权限转移到自身。 `/trasferkp`(reply to someone):将kp权限转移给被回复者。""" if isprivate(update): return self.errorInfo("发送群消息强制转移KP权限") gp = self.getgp(update) pl = self.getplayer(update) f = self.checkaccess(pl, gp) if not f & GROUPADMIN: return self.errorInfo("没有权限", True) if gp.kp is None: return self.errorInfo("没有KP", True) if self.checkaccess(gp.kp, gp) & GROUPADMIN: return self.errorInfo("KP是管理员,无法转移") # 获取newkp newkpid: int if len(context.args) != 0: if not isint(context.args[0]): return self.errorInfo("参数需要是整数", True) newkp = self.forcegetplayer(int(context.args[0])) else: t = self.getreplyplayer(update) newkp = t if t is not None else self.forcegetplayer(update) if newkp == gp.kp: return self.errorInfo("原KP和新KP相同", True) if not self.changeKP(gp, newkp): return self.errorInfo("程序错误:不符合添加KP要求,请检查代码") # 不应触发 return True
def setname(self, update: Update, context: CallbackContext) -> bool: """设置角色卡姓名。 `/setname --name`:直接设定姓名。 `/setname`:bot将等待输入姓名。 设置的姓名可以带有空格等字符。""" card1 = self.forcegetplayer(update).controlling if card1 is None: return self.errorInfo("找不到卡。") if len(context.args) == 0: if isprivate(update): self.addOP(getchatid(update), "setname") else: self.addOP(getchatid(update), "setname " + str(card1.playerid)) self.reply("请输入姓名:") return True self.nameset(card1, ' '.join(context.args)) self.reply("角色的名字已经设置为" + card1.info.name + "。") return True
def bindkp(self, update: Update, context: CallbackContext) -> bool: """添加KP。在群里发送`/bindkp`将自己设置为KP。 如果这个群已经有一名群成员是KP,则该指令无效。 若原KP不在群里,该指令可以替换KP。 如果原KP在群里,需要先发送`/unbindkp`来撤销自己的KP,或者管理员用`/transferkp`来强制转移KP权限。""" if isprivate(update): return self.errorInfo('发送群消息添加KP') gp = self.forcegetgroup(update) kp = self.forcegetplayer(update) # 判断是否已经有KP if gp.kp is not None: # 已有KP if not self.isingroup(gp, kp): if not self.changeKP(gp, kp): # 更新NPC卡拥有者 # 不应触发 return self.errorInfo("程序错误:不符合添加KP要求,请检查代码") return True return self.errorInfo( "你已经是KP了", True ) if gp.kp == kp else self.errorInfo( '这个群已经有一位KP了,请先让TA发送 /unbindkp 撤销自己的KP。如果需要强制更换KP,请管理员用\'/transferkp kpid\'添加本群成员为KP,或者 /transferkp 将自己设为KP。' ) # 该群没有KP,可以直接添加KP self.addkp(gp, kp) # delkp指令会将KP的卡playerid全部改为0,检查如果有id为0的卡,id设为新kp的id self.changecardsplid(gp, self.forcegetplayer(0), kp) self.reply("绑定群(id): " + gp.getname() + "与KP(id): " + kp.getname()) return True
def sancheck(self, update: Update, context: CallbackContext) -> bool: """进行一次sancheck,格式如下: `/sancheck checkpass/checkfail`""" if isprivate(update): return self.errorInfo("在游戏中才能进行sancheck。") if len(context.args) == 0: return self.errorInfo("需要参数", True) checkname = context.args[0] if checkname.find("/") == -1: return self.errorInfo("将成功和失败的扣除点数用/分开。") checkpass, checkfail = checkname.split(sep='/', maxsplit=1) if not isadicename(checkpass) or not isadicename(checkfail): return self.errorInfo("无效输入") gp = self.forcegetgroup(update) if gp.game is None: return self.errorInfo("找不到游戏", True) pl = self.forcegetplayer(update) # KP 进行 if pl == gp.kp: card1 = gp.game.kpctrl if card1 is None: return self.errorInfo("请先用 /switchgamecard 切换到你的卡") else: # 玩家进行 card1 = self.findcardfromgame(gp.game, pl) if card1 is None: return self.errorInfo("找不到卡。") rttext = "理智:检定/出目 " sanity = card1.attr.SAN check = dicemdn(1, 100)[0] rttext += str(sanity) + "/" + str(check) + " " greatfailrule = gp.rule.greatfail if (sanity < 50 and check >= greatfailrule[2] and check <= greatfailrule[3]) or ( sanity >= 50 and check >= greatfailrule[0] and check <= greatfailrule[1]): # 大失败 rttext += "大失败" anstype = "大失败" elif check > sanity: # check fail rttext += "失败" anstype = "失败" else: rttext += "成功" anstype = "" rttext += "\n损失理智:" sanloss, m, n = 0, 0, 0 if anstype == "大失败": if isint(checkfail): sanloss = int(checkfail) else: t = checkfail.split("+") for tt in t: if isint(tt): sanloss += int(tt) else: ttt = tt.split('d') sanloss += int(ttt[0]) * int(ttt[1]) elif anstype == "失败": if isint(checkfail): sanloss = int(checkfail) else: m, n = checkfail.split("d", maxsplit=1) m, n = int(m), int(n) sanloss = int(sum(dicemdn(m, n))) else: if isint(checkpass): sanloss = int(checkpass) else: m, n = checkpass.split("d", maxsplit=1) m, n = int(m), int(n) sanloss = int(sum(dicemdn(m, n))) card1.attr.SAN -= sanloss rttext += str(sanloss) + "\n" if card1.attr.SAN <= 0: card1.attr.SAN = 0 card1.status = STATUS_PERMANENTINSANE rttext += "陷入永久疯狂,快乐撕卡~\n" elif sanloss > (card1.attr.SAN + sanloss) // 5: rttext += "一次损失五分之一以上理智,进入不定性疯狂状态。\n" # TODO 处理角色的疯狂状态 elif sanloss >= 5: rttext += "一次损失5点或以上理智,可能需要进行智力(灵感)检定。\n" self.reply(rttext) card1.write() return True
def roll(self, update: Update, context: CallbackContext): """基本的骰子功能。 只接受第一个空格前的参数`dicename`。 `dicename`可能是技能名、属性名(仅限游戏中),可能是`3d6`,可能是`1d4+2d10`。 骰子环境可能是游戏中,游戏外。 `/roll`:默认1d100。 `/roll --mdn`骰一个mdn的骰子。 `/roll --test`仅限游戏中可以使用。对`test`进行一次检定。 例如,`/roll 力量`会进行一次STR检定。 `/roll 射击`进行一次射击检定。 检定心理学时结果只会发送给kp。 如果要进行一个暗骰,可以输入 `/roll 暗骰`进行一次检定为50的暗骰,或者 `/roll 暗骰60`进行一次检定为60的暗骰。""" if len(context.args) == 0: self.reply(commondice("1d100")) # 骰1d100 return True dicename = context.args[0] if isprivate(update): self.reply(commondice(dicename)) return True gp = self.forcegetgroup(update) # 检查输入参数是不是一个基础骰子,如果是则直接计算骰子 if gp.game is None or dicename.find('d') >= 0 or isint(dicename): if isint(dicename) and int(dicename) > 0: dicename = "1d" + dicename rttext = commondice(dicename) if rttext == "Invalid input.": return self.errorInfo("输入无效") self.reply(rttext) return True if gp.game is None: return self.errorInfo("输入无效") # 确认不是基础骰子的计算,转到卡检定 # 获取临时检定 tpcheck, gp.game.tpcheck = gp.game.tpcheck, 0 if tpcheck != 0: gp.write() pl = self.forcegetplayer(update) # 获取卡 if pl != gp.kp: gamecard = self.findcardfromgame(gp.game, pl) else: gamecard = gp.game.kpctrl if gamecard is None: return self.errorInfo("请用 /switchgamecard 切换kp要用的卡") if not gamecard: return self.errorInfo("找不到游戏中的卡。") if gamecard.status == STATUS_DEAD: return self.errorInfo("角色已死亡") if gamecard.status == STATUS_PERMANENTINSANE: return self.errorInfo("角色已永久疯狂") if dicename.encode('utf-8').isalpha(): dicename = dicename.upper() # 找卡完成,开始检定 test = 0 if dicename == "侦察": dicename = "侦查" if dicename in gamecard.skill.allskills(): test = gamecard.skill.get(dicename) elif dicename in gamecard.interest.allskills(): test = gamecard.interest.get(dicename) elif dicename == "母语": test = gamecard.data.EDU elif dicename == "闪避": test = gamecard.data.DEX // 2 elif dicename in gamecard.data.alldatanames: test = gamecard.data.__dict__[dicename] elif dicename == "力量": dicename = "STR" test = gamecard.data.STR elif dicename == "体质": dicename = "CON" test = gamecard.data.CON elif dicename == "体型": dicename = "SIZ" test = gamecard.data.SIZ elif dicename == "敏捷": dicename = "DEX" test = gamecard.data.DEX elif dicename == "外貌": dicename = "APP" test = gamecard.data.APP elif dicename == "智力" or dicename == "灵感": dicename = "INT" test = gamecard.data.INT elif dicename == "意志": dicename = "POW" test = gamecard.data.POW elif dicename == "教育": dicename = "EDU" test = gamecard.data.EDU elif dicename == "幸运": dicename = "LUCK" test = gamecard.data.LUCK elif dicename in self.skilllist: test = self.skilllist[dicename] elif dicename[:2] == "暗骰" and (isint(dicename[2:]) or len(dicename) == 2): if len(dicename) != 2: test = int(dicename[2:]) else: test = 50 else: # HIT BAD TRAP return self.errorInfo("输入无效") # 将所有检定修正相加 test += gamecard.tempstatus.GLOBAL if gamecard.hasstatus(dicename): test += gamecard.getstatus(dicename) test += tpcheck if test < 1: test = 1 testval = dicemdn(1, 100)[0] rttext = dicename + " 检定/出目:" + str(test) + "/" + str(testval) + " " greatsuccessrule = gp.rule.greatsuccess greatfailrule = gp.rule.greatfail if (test < 50 and testval >= greatfailrule[2] and testval <= greatfailrule[3]) or ( test >= 50 and testval >= greatfailrule[0] and testval <= greatfailrule[1]): rttext += "大失败" elif (test < 50 and testval >= greatsuccessrule[2] and testval <= greatsuccessrule[3]) or ( test >= 50 and testval >= greatsuccessrule[0] and testval <= greatsuccessrule[1]): rttext += "大成功" elif testval > test: rttext += "失败" elif testval > test // 2: rttext += "普通成功" elif testval > test // 5: rttext += "困难成功" else: rttext += "极难成功" if dicename == "心理学" or dicename[:2] == "暗骰": if gp.kp is None: return self.errorInfo("本群没有KP,请先添加一个KP再试!") self.reply(dicename + " 检定/出目:" + str(test) + "/???") self.sendto(gp.kp, rttext) else: self.reply(rttext) return True
def showcard(self, update: Update, context: CallbackContext) -> bool: """显示某张卡的信息。 `/showcard --cardid (card/--attrname)`: 显示卡id为`cardid`的卡片的信息。 如果第二个参数是`card`,显示整张卡;否则,显示这一项数据。 如果第二个参数不存在,显示卡片基本信息。 群聊时使用该指令,优先查看游戏内的卡片。 显示前会检查发送者是否有权限显示这张卡。在这些情况下,无法显示卡: 群聊环境:显示非本群的卡片,或者显示本群的type不为PL的卡片; 私聊环境:显示没有查看权限的卡片。""" if len(context.args) == 0: return self.errorInfo("需要参数") if not isint(context.args[0]) or int(context.args[0]) < 0: return self.errorInfo("卡id参数无效", True) cdid = int(context.args[0]) rttext: str = "" cardi: Optional[GameCard] = None if isgroup(update): cardi = self.getgamecard(cdid) if cardi is not None: rttext = "显示游戏内的卡片\n" if cardi is None: cardi = self.getcard(cdid) if cardi is None: return self.errorInfo("找不到这张卡") if rttext == "": rttext = "显示游戏外的卡片\n" # 检查是否有权限 if isprivate(update): pl = self.forcegetplayer(update) if self.checkaccess(pl, cardi) & CANREAD == 0: return self.errorInfo("没有权限") else: if (cardi.groupid != -1 and cardi.group != self.forcegetgroup(update)) or cardi.type != PLTYPE: return self.errorInfo("没有权限", True) # 开始处理 if len(context.args) >= 2: if context.args[1] == "card": self.reply(rttext + str(cardi)) else: ans = cardi.show(context.args[1]) if ans == "找不到该属性": return self.errorInfo(ans) self.reply(rttext + ans) return True # 显示基本属性 self.reply(rttext + cardi.basicinfo()) return True
def newcard(self, update: Update, context: CallbackContext) -> bool: """随机生成一张新的角色卡。需要一个群id作为参数。 只接受私聊消息。 如果发送者不是KP,那么只能在一个群内拥有最多一张角色卡。 如果不知道群id,请先发送`/getid`到群里获取id。 `/newcard`提交创建卡请求,bot会等待你输入`groupid`。 `/newcard --groupid`新建一张卡片,绑定到`groupid`对应的群。 `/newcard --cardid`新建一张卡片,将卡片id设置为`cardid`,`cardid`必须是非负整数。 `/newcard --groupid --cardid`新建一张卡片,绑定到`groupid`对应的群的同时,将卡片id设置为`cardid`。 当指定的卡id已经被别的卡占用的时候,将自动获取未被占用的id。 当生成时有至少三项基础属性低于50时,可以使用`/discard`来放弃并删除这张角色卡。 创建新卡之后,当前控制卡片会自动切换到新卡,详情参见 `/help switch`。 角色卡说明 一张角色卡具有: `groupid`,`id`,`playerid`基本信息。 STR,CON,SIZ,DEX,APP,INT,EDU,LUCK基本属性; 职业、姓名、性别、年龄; 技能信息; 背景故事(描述,重要之人,重要之地,珍视之物,特质,受过的伤,恐惧之物,神秘学物品,第三类接触); 检定修正值; 物品,财产; 角色类型(PL,NPC); 是否可以被删除; 状态(存活,死亡,疯狂等)。""" gpid: int = None gp: Optional[Group] = None newcdid: Optional[int] = None if isgroup(update): # 先检查是否有该玩家信息 rtbutton = [[InlineKeyboardButton( text="跳转到私聊", callback_data="None", url="t.me/"+self.bot.username)]] rp_markup = InlineKeyboardMarkup(rtbutton) if self.getplayer(update) is None: self.reply("请先开启与bot的私聊", reply_markup=rp_markup) return True if len(context.args) > 0: if not isint(context.args[0]) or int(context.args[0]) < 0: return self.errorInfo("参数无效") gpid = getchatid(update) gp = self.forcegetgroup(gpid) if len(context.args) > 0: newcdid = int(context.args[0]) elif len(context.args) > 0: msg = context.args[0] if not isint(msg): return self.errorInfo("输入无效") if int(msg) >= 0: newcdid = int(msg) else: gpid = int(msg) gp = self.forcegetgroup(gpid) if len(context.args) > 1: if not isint(context.args[1]) or int(context.args[1]) < 0: return self.errorInfo("输入无效") newcdid = int(context.args[1]) if gp is None: self.reply( "准备创建新卡。\n如果你不知道群id,在群里发送 /getid 即可创建角色卡。\n你也可以选择手动输入群id,请发送群id:") if newcdid is None: self.addOP(getchatid(update), "newcard " + str(update.message.message_id)) else: self.addOP(getchatid(update), "newcard " + str(update.message.message_id)+" "+str(newcdid)) return True # 检查(pl)是否已经有卡 pl = self.forcegetplayer(update) plid = pl.id if self.hascard(plid, gpid) and pl != gp.kp: return self.errorInfo("你在这个群已经有一张卡了!") # 符合建卡条件,生成新卡 # gp is not None assert(gpid is not None) remsgid = None if isprivate(update): remsgid = update.message.message_id else: assert rp_markup self.reply("建卡信息已经私聊发送", reply_markup=rp_markup) return self.getnewcard(remsgid, gpid, plid, newcdid)
def setrule(self, update: Update, context: CallbackContext) -> bool: """设置游戏的规则。 一个群里游戏有自动生成的默认规则,使用本指令可以修改这些规则。 `/setrule --args`修改规则。`--args`格式如下: `rulename1:str --rules1:List[int] rulename2:str --rule2:List[int] ...` 一次可以修改多项规则。 有可能会出现部分规则设置成功,但部分规则设置失败的情况, 查看返回的信息可以知道哪些部分已经成功修改。 规则的详细说明: skillmax:接收长度为3的数组,记为r。`r[0]`是一般技能上限, `r[1]`是个别技能的上限,`r[2]`表示个别技能的个数。 skillmaxAged:年龄得到的技能上限增加设定。 接收长度为4的数组,记为r。`r[0]`至`r[2]`同上, 但仅仅在年龄大于`r[3]`时开启该设定。`r[3]`等于100代表不开启该设定。 skillcost:技能点数分配时的消耗。接收长度为偶数的数组,记为r。 若i为偶数(或0),`r[i]`表示技能点小于`r[i+1]`时, 需要分配`r[i]`点点数来获得1点技能点。r的最后一项必须是100。 例如:`r=[1, 80, 2, 100]`,则从10点升至90点需要花费`1*70+2*10=90`点数。 greatsuccess:大成功范围。接收长度为4的数组,记为r。 `r[0]-r[1]`为检定大于等于50时大成功范围,否则是`r[2]-r[3]`。 greatfail:大失败范围。同上。""" if isprivate(update): return self.errorInfo("请在群内用该指令设置规则") gp = self.forcegetgroup(update) if not self.isfromkp(update): return self.errorInfo("没有权限", True) if len(context.args) == 0: return self.errorInfo("需要参数", True) gprule = gp.rule ruledict: Dict[str, List[int]] = {} i = 0 while i < len(context.args): j = i+1 tplist: List[int] = [] while j < len(context.args): if isint(context.args[j]): tplist.append(int(context.args[j])) j += 1 else: break ruledict[context.args[i]] = tplist i = j del i, j msg, ok = gprule.changeRules(ruledict) if not ok: return self.errorInfo(msg) self.reply(msg) return True
def hp(self, update: Update, context: CallbackContext) -> bool: """修改HP。KP通过回复某位PL消息并在回复消息中使用本指令即可修改对方卡片的HP。 回复自己的消息,则修改kp当前选中的游戏卡。 或者,也可以使用@用户名以及用玩家id的方法选中某名PL,但请不要同时使用回复和用户名。 使用范例: `/hp +1d3`:恢复1d3点HP。 `/hp -2`:扣除2点HP。 `/hp 10`:将HP设置为10。 `/hp @username 12`:将用户名为username的玩家HP设为12。 下面的例子是无效输入: `/hp 1d3`:无法将HP设置为一个骰子的结果,恢复1d3生命请在参数前加上符号`+`,扣除同理。 在生命变动的情况下,角色状态也会同步地变动。""" if isprivate(update): return self.errorInfo("游戏中才可以修改HP。") gp = self.forcegetgroup(update) kp = self.forcegetplayer(update) if gp.kp != kp: return self.errorInfo("没有权限", True) if len(context.args) == 0: return self.errorInfo("需要指定扣除的HP", True) chp: str = context.args[0] game = gp.game if game is None: return self.errorInfo("找不到进行中的游戏", True) rppl = self.getreplyplayer(update) if update.message.reply_to_message is not None: rpmsgid = update.message.reply_to_message.message_id else: rpmsgid = update.message.message_id if rppl is None: if len(context.args) < 2: return self.errorInfo("请用回复或@用户名的方式来选择玩家改变HP") if not isint(context.args[0]) or int(context.args[0]) < 0: return self.errorInfo("参数无效") rppl = self.getplayer(int(context.args[0])) if rppl is None: return self.errorInfo("指定的用户无效") chp = context.args[1] if rppl != kp: cardi = self.findcardfromgame(game, rppl) else: cardi = game.kpctrl if cardi is None: return self.errorInfo("找不到这名玩家的卡。") if chp[0] == "+" or chp[0] == "-": if len(chp) == 1: return self.errorInfo("参数无效", True) # 由dicecalculator()处理。减法时,检查可能的括号导致的输入错误 if chp[0] == '-' and chp[1] != '(' and (chp[1:].find('+') != -1 or chp[1:].find('-') != -1): return self.errorInfo("当第一个减号的后面是可计算的骰子,且存在加减法时,请在第一个符号之后使用括号") try: diceans = dicecalculator(chp[1:]) except Exception: return self.errorInfo("参数无效", True) if diceans < 0: return self.errorInfo("骰子的结果为0,生命值不修改") chp = chp[0]+str(diceans) else: # 直接修改生命为目标值的情形。不支持dicecalculator(),仅支持整数 if not isint(chp) or int(chp) > 100 or int(chp) < 0: return self.errorInfo("参数无效", True) if cardi.status == STATUS_DEAD: return self.errorInfo("该角色已死亡") originhp = cardi.attr.HP if chp[0] == "+": cardi.attr.HP += int(chp[1:]) elif chp[0] == "-": cardi.attr.HP -= int(chp[1:]) else: cardi.attr.HP = int(chp) hpdiff = cardi.attr.HP - originhp if hpdiff == 0: return self.errorInfo("HP不变,目前HP:"+str(cardi.attr.HP)) if hpdiff < 0: # 承受伤害描述。分类为三种状态 takedmg = -hpdiff if takedmg < cardi.attr.MAXHP//2: # 轻伤,若生命不降到0,不做任何事 if takedmg >= originhp: self.reply( text="HP归0,角色昏迷", reply_to_message_id=rpmsgid) elif takedmg > cardi.attr.MAXHP: self.reply( text="致死性伤害,角色死亡", reply_to_message_id=rpmsgid) cardi.status = STATUS_DEAD else: self.reply(text="角色受到重伤,请进行体质检定以维持清醒", reply_to_message_id=rpmsgid) cardi.status = STATUS_SERIOUSLYWOUNDED if originhp <= takedmg: self.reply( text="HP归0,进入濒死状态", reply_to_message_id=rpmsgid) cardi.status = STATUS_NEARDEATH if cardi.attr.HP < 0: cardi.attr.HP = 0 else: # 恢复生命,可能脱离某种状态 if cardi.attr.HP >= cardi.attr.MAXHP: cardi.attr.HP = cardi.attr.MAXHP self.reply(text="HP达到最大值", reply_to_message_id=rpmsgid) if hpdiff > 1 and originhp <= 1 and cardi.status == STATUS_NEARDEATH: self.reply(text="脱离濒死状态", reply_to_message_id=rpmsgid) cardi.status = STATUS_SERIOUSLYWOUNDED cardi.write() self.reply(text="生命值从"+str(originhp)+"修改为" + str(cardi.attr.HP), reply_to_message_id=rpmsgid) return True