2023-04-09 13:35:35 +08:00
|
|
|
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
2023-03-26 17:32:45 +08:00
|
|
|
|
--- 玩家分为客户端要处理的玩家,以及服务端处理的玩家两种。
|
|
|
|
|
---
|
|
|
|
|
--- 客户端能知道的玩家的信息十分有限,而服务端知道一名玩家的所有细节。
|
|
|
|
|
---
|
|
|
|
|
--- Player类就是这两种玩家的基类,包含它们共用的部分。
|
|
|
|
|
---
|
2022-03-30 16:33:56 +08:00
|
|
|
|
---@class Player : Object
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public id integer @ 玩家的id,每名玩家的id是唯一的。机器人的id是负数。
|
|
|
|
|
---@field public hp integer @ 体力值
|
|
|
|
|
---@field public maxHp integer @ 体力上限
|
2023-04-13 20:17:39 +08:00
|
|
|
|
---@field public shield integer @ 护甲数
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public kingdom string @ 势力
|
|
|
|
|
---@field public role string @ 身份
|
|
|
|
|
---@field public general string @ 武将
|
2023-04-19 14:07:16 +08:00
|
|
|
|
---@field public deputyGeneral string @ 副将
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public gender integer @ 性别
|
|
|
|
|
---@field public seat integer @ 座位号
|
|
|
|
|
---@field public next Player @ 下家
|
|
|
|
|
---@field public phase Phase @ 当前阶段
|
|
|
|
|
---@field public faceup boolean @ 是否正面朝上
|
|
|
|
|
---@field public chained boolean @ 是否被横直
|
|
|
|
|
---@field public dying boolean @ 是否处于濒死
|
|
|
|
|
---@field public dead boolean @ 是否死亡
|
|
|
|
|
---@field public player_skills Skill[] @ 当前拥有的所有技能
|
|
|
|
|
---@field public derivative_skills table<Skill, Skill[]> @ 当前拥有的派生技能
|
|
|
|
|
---@field public flag string[] @ 当前拥有的flag,不过好像没用过
|
|
|
|
|
---@field public tag table<string, any> @ 当前拥有的所有tag,好像也没用过
|
|
|
|
|
---@field public mark table<string, integer> @ 当前拥有的所有标记,用烂了
|
|
|
|
|
---@field public player_cards table<integer, integer[]> @ 当前拥有的所有牌,键是区域,值是id列表
|
|
|
|
|
---@field public virtual_equips Card[] @ 当前的虚拟装备牌,其实也包含着虚拟延时锦囊这种
|
|
|
|
|
---@field public special_cards table<string, integer[]> @ 类似“屯田”这种的私人牌堆
|
|
|
|
|
---@field public cardUsedHistory table<string, integer[]> @ 用牌次数历史记录
|
|
|
|
|
---@field public skillUsedHistory table<string, integer[]> @ 发动技能次数的历史记录
|
|
|
|
|
---@field public fixedDistance table<Player, integer> @ 与其他玩家的固定距离列表
|
2023-08-12 00:50:17 +08:00
|
|
|
|
---@field public buddy_list integer[] @ 队友列表,或者说自己可以观看别人手牌的那些玩家的列表
|
2022-03-27 14:49:41 +08:00
|
|
|
|
local Player = class("Player")
|
2022-03-25 12:28:07 +08:00
|
|
|
|
|
2022-04-01 20:51:01 +08:00
|
|
|
|
---@alias Phase integer
|
|
|
|
|
|
|
|
|
|
Player.RoundStart = 1
|
|
|
|
|
Player.Start = 2
|
|
|
|
|
Player.Judge = 3
|
|
|
|
|
Player.Draw = 4
|
|
|
|
|
Player.Play = 5
|
|
|
|
|
Player.Discard = 6
|
|
|
|
|
Player.Finish = 7
|
|
|
|
|
Player.NotActive = 8
|
|
|
|
|
Player.PhaseNone = 9
|
|
|
|
|
|
2022-04-08 18:39:58 +08:00
|
|
|
|
---@alias PlayerCardArea integer
|
|
|
|
|
|
|
|
|
|
Player.Hand = 1
|
|
|
|
|
Player.Equip = 2
|
|
|
|
|
Player.Judge = 3
|
|
|
|
|
Player.Special = 4
|
|
|
|
|
|
2023-01-29 18:11:41 +08:00
|
|
|
|
Player.HistoryPhase = 1
|
|
|
|
|
Player.HistoryTurn = 2
|
|
|
|
|
Player.HistoryRound = 3
|
|
|
|
|
Player.HistoryGame = 4
|
|
|
|
|
|
2023-08-13 02:25:04 +08:00
|
|
|
|
Player.WeaponSlot = 'WeaponSlot'
|
|
|
|
|
Player.ArmorSlot = 'ArmorSlot'
|
|
|
|
|
Player.OffensiveRideSlot = 'OffensiveRideSlot'
|
|
|
|
|
Player.DefensiveRideSlot = 'DefensiveRideSlot'
|
|
|
|
|
Player.TreasureSlot = 'TreasureSlot'
|
|
|
|
|
Player.JudgeSlot = 'JudgeSlot'
|
|
|
|
|
|
2023-03-26 17:32:45 +08:00
|
|
|
|
--- 构造函数。总之这不是随便调用的函数
|
2022-03-25 12:28:07 +08:00
|
|
|
|
function Player:initialize()
|
2023-08-12 00:50:17 +08:00
|
|
|
|
self.id = 0
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.hp = 0
|
|
|
|
|
self.maxHp = 0
|
|
|
|
|
self.kingdom = "qun"
|
|
|
|
|
self.role = ""
|
|
|
|
|
self.general = ""
|
2023-04-19 14:07:16 +08:00
|
|
|
|
self.deputyGeneral = ""
|
2023-01-29 18:11:41 +08:00
|
|
|
|
self.gender = General.Male
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.seat = 0
|
2022-12-20 12:51:54 +08:00
|
|
|
|
self.next = nil
|
2023-03-07 10:21:56 +08:00
|
|
|
|
self.phase = Player.NotActive
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.faceup = true
|
|
|
|
|
self.chained = false
|
|
|
|
|
self.dying = false
|
|
|
|
|
self.dead = false
|
2023-03-14 20:48:08 +08:00
|
|
|
|
self.drank = 0
|
2023-12-10 18:55:16 +08:00
|
|
|
|
self.rest = 0
|
2022-04-30 15:27:56 +08:00
|
|
|
|
|
|
|
|
|
self.player_skills = {}
|
2022-09-14 13:01:10 +08:00
|
|
|
|
self.derivative_skills = {}
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.flag = {}
|
|
|
|
|
self.tag = {}
|
|
|
|
|
self.mark = {}
|
|
|
|
|
self.player_cards = {
|
|
|
|
|
[Player.Hand] = {},
|
|
|
|
|
[Player.Equip] = {},
|
|
|
|
|
[Player.Judge] = {},
|
|
|
|
|
}
|
2023-01-29 18:11:41 +08:00
|
|
|
|
self.virtual_equips = {}
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.special_cards = {}
|
|
|
|
|
|
2023-08-13 02:25:04 +08:00
|
|
|
|
self.equipSlots = {
|
|
|
|
|
Player.WeaponSlot,
|
|
|
|
|
Player.ArmorSlot,
|
|
|
|
|
Player.OffensiveRideSlot,
|
|
|
|
|
Player.DefensiveRideSlot,
|
|
|
|
|
Player.TreasureSlot,
|
|
|
|
|
}
|
|
|
|
|
self.sealedSlots = {}
|
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.cardUsedHistory = {}
|
2023-01-29 18:11:41 +08:00
|
|
|
|
self.skillUsedHistory = {}
|
2023-01-04 14:21:29 +08:00
|
|
|
|
self.fixedDistance = {}
|
2023-08-12 00:50:17 +08:00
|
|
|
|
self.buddy_list = {}
|
2022-03-25 12:28:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-09 11:44:19 +08:00
|
|
|
|
function Player:__tostring()
|
2023-04-21 04:29:52 +08:00
|
|
|
|
return string.format("<%s %d>", self.id < 0 and "Bot" or "Player", math.abs(self.id))
|
2023-04-09 11:44:19 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 设置角色、体力、技能。
|
|
|
|
|
---@param general General @ 角色类型
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param setHp? boolean @ 是否设置体力
|
|
|
|
|
---@param addSkills? boolean @ 是否增加技能
|
2022-03-25 12:28:07 +08:00
|
|
|
|
function Player:setGeneral(general, setHp, addSkills)
|
2023-07-14 23:12:46 +08:00
|
|
|
|
self.general = general.name
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if setHp then
|
|
|
|
|
self.maxHp = general.maxHp
|
|
|
|
|
self.hp = general.hp
|
|
|
|
|
end
|
2022-03-25 12:28:07 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if addSkills then
|
|
|
|
|
table.insertTable(self.player_skills, general.skills)
|
|
|
|
|
end
|
2022-03-25 12:28:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-23 21:10:07 +08:00
|
|
|
|
function Player:getGeneralMaxHp()
|
2023-05-13 14:20:34 +08:00
|
|
|
|
local general = Fk.generals[type(self:getMark("__heg_general")) == "string" and self:getMark("__heg_general") or self.general]
|
2023-08-27 20:21:37 +08:00
|
|
|
|
local deputy = Fk.generals[type(self:getMark("__heg_deputy")) == "string" and self:getMark("__heg_deputy") or self.deputyGeneral]
|
2023-04-23 21:10:07 +08:00
|
|
|
|
|
|
|
|
|
if not deputy then
|
2023-08-24 21:37:06 +08:00
|
|
|
|
return general.maxHp + general.mainMaxHpAdjustedValue
|
2023-04-23 21:10:07 +08:00
|
|
|
|
else
|
2023-08-24 21:37:06 +08:00
|
|
|
|
return (general.maxHp + general.mainMaxHpAdjustedValue + deputy.maxHp + deputy.deputyMaxHpAdjustedValue) // 2
|
2023-04-23 21:10:07 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 查询角色是否存在flag。
|
|
|
|
|
---@param flag string @ 一种标记
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:hasFlag(flag)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
return table.contains(self.flag, flag)
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为角色赋予flag。
|
|
|
|
|
---@param flag string @ 一种标记
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:setFlag(flag)
|
2023-02-26 16:51:29 +08:00
|
|
|
|
if flag == "." then
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self:clearFlags()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
if flag:sub(1, 1) == "-" then
|
|
|
|
|
flag = flag:sub(2, #flag)
|
|
|
|
|
table.removeOne(self.flag, flag)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
if not self:hasFlag(flag) then
|
|
|
|
|
table.insert(self.flag, flag)
|
|
|
|
|
end
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 清除角色flag。
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:clearFlags()
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.flag = {}
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为角色赋予Mark。
|
|
|
|
|
---@param mark string @ 标记
|
|
|
|
|
---@param count integer @ 为标记赋予的数量
|
2023-02-15 19:54:35 +08:00
|
|
|
|
-- mark name and UI:
|
|
|
|
|
-- 'xxx': invisible mark
|
|
|
|
|
-- '@mark': mark with extra data (maybe string or number)
|
|
|
|
|
-- '@@mark': mark without data
|
2023-08-12 00:50:17 +08:00
|
|
|
|
-- '@$mark': mark with card_name[] data
|
|
|
|
|
-- '@&mark': mark with general_name[] data
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:addMark(mark, count)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
count = count or 1
|
|
|
|
|
local num = self.mark[mark]
|
|
|
|
|
num = num or 0
|
|
|
|
|
self:setMark(mark, math.max(num + count, 0))
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为角色移除Mark。
|
|
|
|
|
---@param mark string @ 标记
|
|
|
|
|
---@param count integer @ 为标记删除的数量
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:removeMark(mark, count)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
count = count or 1
|
|
|
|
|
local num = self.mark[mark]
|
|
|
|
|
num = num or 0
|
|
|
|
|
self:setMark(mark, math.max(num - count, 0))
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为角色设置Mark至指定数量。
|
|
|
|
|
---@param mark string @ 标记
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param count? integer @ 为标记删除的数量
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:setMark(mark, count)
|
2023-06-11 16:22:11 +08:00
|
|
|
|
if count == 0 then count = nil end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if self.mark[mark] ~= count then
|
|
|
|
|
self.mark[mark] = count
|
|
|
|
|
end
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取角色对应Mark的数量。
|
|
|
|
|
---@param mark string @ 标记
|
2023-07-14 23:12:46 +08:00
|
|
|
|
---@return any
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:getMark(mark)
|
2024-01-25 03:13:57 +08:00
|
|
|
|
local mark = self.mark[mark]
|
|
|
|
|
if not mark then return 0 end
|
|
|
|
|
if type(mark) == "table" then return table.simpleClone(mark) end
|
|
|
|
|
return mark
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取角色有哪些Mark。
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function Player:getMarkNames()
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local ret = {}
|
|
|
|
|
for k, _ in pairs(self.mark) do
|
|
|
|
|
table.insert(ret, k)
|
|
|
|
|
end
|
|
|
|
|
return ret
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 将指定数量的牌加入玩家的对应区域。
|
|
|
|
|
---@param playerArea PlayerCardArea @ 玩家牌所在的区域
|
|
|
|
|
---@param cardIds integer[] @ 牌的ID,返回唯一牌
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param specialName? string @ 私人牌堆名
|
2022-04-08 18:39:58 +08:00
|
|
|
|
function Player:addCards(playerArea, cardIds, specialName)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
assert(table.contains({ Player.Hand, Player.Equip, Player.Judge, Player.Special }, playerArea))
|
|
|
|
|
assert(playerArea ~= Player.Special or type(specialName) == "string")
|
|
|
|
|
|
|
|
|
|
if playerArea == Player.Special then
|
|
|
|
|
self.special_cards[specialName] = self.special_cards[specialName] or {}
|
|
|
|
|
table.insertTable(self.special_cards[specialName], cardIds)
|
|
|
|
|
else
|
|
|
|
|
table.insertTable(self.player_cards[playerArea], cardIds)
|
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 将指定数量的牌移除出玩家的对应区域。
|
|
|
|
|
---@param playerArea PlayerCardArea @ 玩家牌所在的区域
|
|
|
|
|
---@param cardIds integer[] @ 牌的ID,返回唯一牌
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param specialName? string @ 私人牌堆名
|
2022-04-08 18:39:58 +08:00
|
|
|
|
function Player:removeCards(playerArea, cardIds, specialName)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
assert(table.contains({ Player.Hand, Player.Equip, Player.Judge, Player.Special }, playerArea))
|
|
|
|
|
assert(playerArea ~= Player.Special or type(specialName) == "string")
|
|
|
|
|
|
|
|
|
|
local fromAreaIds = playerArea == Player.Special and self.special_cards[specialName] or self.player_cards[playerArea]
|
|
|
|
|
if fromAreaIds then
|
|
|
|
|
for _, id in ipairs(cardIds) do
|
|
|
|
|
if #fromAreaIds == 0 then
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-10 02:18:51 +08:00
|
|
|
|
if table.contains(fromAreaIds, id) then
|
|
|
|
|
table.removeOne(fromAreaIds, id)
|
|
|
|
|
-- FIXME: 为客户端移动id为-1的牌考虑,但总感觉有地方需要商讨啊!
|
|
|
|
|
elseif table.every(fromAreaIds, function(e) return e == -1 end) then
|
|
|
|
|
table.remove(fromAreaIds, 1)
|
|
|
|
|
elseif id == -1 then
|
|
|
|
|
table.remove(fromAreaIds, 1)
|
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-01-29 18:11:41 +08:00
|
|
|
|
-- virtual delayed trick can use these functions too
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为玩家提供虚拟装备。
|
|
|
|
|
---@param card Card @ 卡牌
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:addVirtualEquip(card)
|
|
|
|
|
assert(card and card:isInstanceOf(Card) and card:isVirtual())
|
|
|
|
|
table.insertIfNeed(self.virtual_equips, card)
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为玩家移除虚拟装备。
|
|
|
|
|
---@param cid integer @ 卡牌ID,用来定位装备
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:removeVirtualEquip(cid)
|
|
|
|
|
for _, c in ipairs(self.virtual_equips) do
|
|
|
|
|
for _, id in ipairs(c.subcards) do
|
|
|
|
|
if id == cid then
|
|
|
|
|
table.removeOne(self.virtual_equips, c)
|
|
|
|
|
return c
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 确认玩家是否存在虚拟装备。
|
|
|
|
|
---@param cid integer @ 卡牌ID,用来定位装备
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:getVirualEquip(cid)
|
|
|
|
|
for _, c in ipairs(self.virtual_equips) do
|
|
|
|
|
for _, id in ipairs(c.subcards) do
|
|
|
|
|
if id == cid then
|
|
|
|
|
return c
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 确认玩家判定区是否存在延迟锦囊牌。
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:hasDelayedTrick(card_name)
|
|
|
|
|
for _, id in ipairs(self:getCardIds(Player.Judge)) do
|
|
|
|
|
local c = self:getVirualEquip(id)
|
|
|
|
|
if not c then c = Fk:getCardById(id) end
|
|
|
|
|
if c.name == card_name then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家特定区域所有牌的ID。
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param playerAreas? PlayerCardArea|PlayerCardArea[]|string @ 玩家牌所在的区域
|
|
|
|
|
---@param specialName? string @私人牌堆名
|
2023-04-01 23:06:55 +08:00
|
|
|
|
---@return integer[] @ 返回对应区域的所有牌对应的ID
|
2022-04-08 18:39:58 +08:00
|
|
|
|
function Player:getCardIds(playerAreas, specialName)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local rightAreas = { Player.Hand, Player.Equip, Player.Judge }
|
|
|
|
|
playerAreas = playerAreas or rightAreas
|
2023-10-07 03:22:57 +08:00
|
|
|
|
local cardIds = {}
|
2023-07-14 23:12:46 +08:00
|
|
|
|
if type(playerAreas) == "string" then
|
|
|
|
|
local str = playerAreas
|
|
|
|
|
playerAreas = {}
|
|
|
|
|
if str:find("h") then
|
|
|
|
|
table.insert(playerAreas, Player.Hand)
|
|
|
|
|
end
|
2023-10-07 03:22:57 +08:00
|
|
|
|
if str:find("&") then--增加特殊区域
|
|
|
|
|
for k, v in pairs(self.special_cards) do
|
|
|
|
|
if k:endsWith("&") then table.insertTable(cardIds, v) end
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-07-14 23:12:46 +08:00
|
|
|
|
if str:find("e") then
|
|
|
|
|
table.insert(playerAreas, Player.Equip)
|
|
|
|
|
end
|
|
|
|
|
if str:find("j") then
|
|
|
|
|
table.insert(playerAreas, Player.Judge)
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
assert(type(playerAreas) == "number" or type(playerAreas) == "table")
|
|
|
|
|
local areas = type(playerAreas) == "table" and playerAreas or { playerAreas }
|
|
|
|
|
|
2023-10-07 03:22:57 +08:00
|
|
|
|
rightAreas = { Player.Hand, Player.Equip, Player.Judge, Player.Special }
|
2022-04-30 15:27:56 +08:00
|
|
|
|
for _, area in ipairs(areas) do
|
|
|
|
|
assert(table.contains(rightAreas, area))
|
|
|
|
|
assert(area ~= Player.Special or type(specialName) == "string")
|
|
|
|
|
local currentCardIds = area == Player.Special and self.special_cards[specialName] or self.player_cards[area]
|
|
|
|
|
table.insertTable(cardIds, currentCardIds)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return cardIds
|
|
|
|
|
end
|
|
|
|
|
|
2024-01-25 03:13:57 +08:00
|
|
|
|
--- 通过名字检索获取玩家对应的私人牌堆。
|
2023-04-01 23:06:55 +08:00
|
|
|
|
---@param name string @ 私人牌堆名
|
2023-02-21 13:44:24 +08:00
|
|
|
|
function Player:getPile(name)
|
2024-01-25 03:13:57 +08:00
|
|
|
|
return table.simpleClone(self.special_cards[name] or {})
|
2023-02-21 13:44:24 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-01-25 03:13:57 +08:00
|
|
|
|
--- 通过ID检索获取玩家对应的私人牌堆。
|
2023-04-01 23:06:55 +08:00
|
|
|
|
---@param id integer @ 私人牌堆ID
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@return string?
|
2023-02-21 13:44:24 +08:00
|
|
|
|
function Player:getPileNameOfId(id)
|
|
|
|
|
for k, v in pairs(self.special_cards) do
|
|
|
|
|
if table.contains(v, id) then return k end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-16 15:32:16 +08:00
|
|
|
|
--- 返回所有“如手牌般使用或打出”的牌。
|
|
|
|
|
--- 或者说,返回所有名字以“&”结尾的pile的牌。
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param include_hand? boolean @ 是否包含真正的手牌
|
2023-07-16 15:32:16 +08:00
|
|
|
|
---@return integer[]
|
|
|
|
|
function Player:getHandlyIds(include_hand)
|
2023-12-03 18:45:25 +08:00
|
|
|
|
include_hand = include_hand or include_hand == nil
|
2023-07-16 15:32:16 +08:00
|
|
|
|
local ret = include_hand and self:getCardIds("h") or {}
|
|
|
|
|
for k, v in pairs(self.special_cards) do
|
|
|
|
|
if k:endsWith("&") then table.insertTable(ret, v) end
|
|
|
|
|
end
|
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-02-15 19:54:35 +08:00
|
|
|
|
-- for fkp only
|
|
|
|
|
function Player:getHandcardNum()
|
|
|
|
|
return #self:getCardIds(Player.Hand)
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-23 22:18:11 +08:00
|
|
|
|
function Player:filterHandcards()
|
|
|
|
|
for _, id in ipairs(self:getCardIds(Player.Hand)) do
|
|
|
|
|
Fk:filterCard(id, self)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 检索玩家装备区是否存在对应类型的装备。
|
|
|
|
|
---@param cardSubtype CardSubtype @ 卡牌子类
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@return integer? @ 返回卡牌ID或nil
|
2022-04-30 15:27:56 +08:00
|
|
|
|
function Player:getEquipment(cardSubtype)
|
|
|
|
|
for _, cardId in ipairs(self.player_cards[Player.Equip]) do
|
|
|
|
|
if Fk:getCardById(cardId).sub_type == cardSubtype then
|
|
|
|
|
return cardId
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
return nil
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-08-13 02:25:04 +08:00
|
|
|
|
--- 检索玩家装备区是否存在对应类型的装备列表。
|
|
|
|
|
---@param cardSubtype CardSubtype @ 卡牌子类
|
|
|
|
|
---@return integer[] @ 返回卡牌ID或空表
|
|
|
|
|
function Player:getEquipments(cardSubtype)
|
|
|
|
|
local cardIds = {}
|
|
|
|
|
for _, cardId in ipairs(self.player_cards[Player.Equip]) do
|
|
|
|
|
if Fk:getCardById(cardId).sub_type == cardSubtype then
|
|
|
|
|
table.insert(cardIds, cardId)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return cardIds
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家手牌上限。
|
2022-04-08 18:39:58 +08:00
|
|
|
|
function Player:getMaxCards()
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local baseValue = math.max(self.hp, 0)
|
2022-04-08 18:39:58 +08:00
|
|
|
|
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[MaxCardsSkill] or Util.DummyTable
|
2023-01-22 00:49:11 +08:00
|
|
|
|
local max_fixed = nil
|
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
local f = skill:getFixed(self)
|
|
|
|
|
if f ~= nil then
|
|
|
|
|
max_fixed = max_fixed and math.max(max_fixed, f) or f
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if max_fixed then baseValue = math.max(max_fixed, 0) end
|
2023-02-26 16:51:29 +08:00
|
|
|
|
|
2023-01-22 00:49:11 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
local c = skill:getCorrect(self)
|
2023-03-18 23:37:21 +08:00
|
|
|
|
baseValue = baseValue + (c or 0)
|
2023-01-22 00:49:11 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return math.max(baseValue, 0)
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
--- 获取玩家攻击范围。
|
2022-04-08 18:39:58 +08:00
|
|
|
|
function Player:getAttackRange()
|
2024-01-29 10:19:10 +08:00
|
|
|
|
local baseValue = 1
|
|
|
|
|
local weapons = self:getEquipments(Card.SubtypeWeapon)
|
|
|
|
|
if #weapons > 0 then
|
|
|
|
|
baseValue = 0
|
|
|
|
|
for _, id in ipairs(weapons) do
|
|
|
|
|
local weapon = Fk:getCardById(id)
|
|
|
|
|
baseValue = math.max(baseValue, weapon.attack_range or 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable
|
2024-01-29 10:19:10 +08:00
|
|
|
|
local max_fixed, correct = nil, 0
|
2023-04-10 21:34:23 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
2024-01-29 10:19:10 +08:00
|
|
|
|
local f = skill:getFixed(self)
|
|
|
|
|
if f ~= nil then
|
|
|
|
|
max_fixed = max_fixed and math.max(max_fixed, f) or f
|
|
|
|
|
end
|
|
|
|
|
local c = skill:getCorrect(self)
|
|
|
|
|
correct = correct + (c or 0)
|
2023-04-10 21:34:23 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-01-29 10:19:10 +08:00
|
|
|
|
return math.max(math.max(baseValue, (max_fixed or 0)) + correct, 0)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:06 +08:00
|
|
|
|
--- 获取角色是否被移除。
|
|
|
|
|
function Player:isRemoved()
|
|
|
|
|
return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s)
|
|
|
|
|
return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 修改玩家与其他角色的固定距离。
|
|
|
|
|
---@param other Player @ 其他玩家
|
|
|
|
|
---@param num integer @ 距离数
|
2023-01-04 14:21:29 +08:00
|
|
|
|
function Player:setFixedDistance(other, num)
|
2023-07-14 23:12:46 +08:00
|
|
|
|
--print(self.name .. ": fixedDistance is deprecated. Use fixed_func instead.")
|
2023-01-04 14:21:29 +08:00
|
|
|
|
self.fixedDistance[other] = num
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 移除玩家与其他角色的固定距离。
|
|
|
|
|
---@param other Player @ 其他玩家
|
2023-01-04 14:21:29 +08:00
|
|
|
|
function Player:removeFixedDistance(other)
|
2023-07-14 23:12:46 +08:00
|
|
|
|
--print(self.name .. ": fixedDistance is deprecated. Use fixed_func instead.")
|
2023-01-04 14:21:29 +08:00
|
|
|
|
self.fixedDistance[other] = nil
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家与其他角色的实际距离。
|
|
|
|
|
---
|
|
|
|
|
--- 通过 二者位次+距离技能之和 与 两者间固定距离 进行对比,更大的为实际距离。
|
|
|
|
|
---@param other Player @ 其他玩家
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param mode? string @ 计算模式(left/right/both)
|
|
|
|
|
---@param ignore_dead? boolean @ 是否忽略尸体
|
2023-07-08 01:05:54 +08:00
|
|
|
|
function Player:distanceTo(other, mode, ignore_dead)
|
2023-07-01 04:12:19 +08:00
|
|
|
|
assert(other:isInstanceOf(Player))
|
2023-07-08 01:05:54 +08:00
|
|
|
|
mode = mode or "both"
|
2023-06-09 01:16:23 +08:00
|
|
|
|
if other == self then return 0 end
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if not ignore_dead and other.dead then
|
2023-07-08 01:05:54 +08:00
|
|
|
|
return -1
|
|
|
|
|
end
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if self:isRemoved() or other:isRemoved() then
|
|
|
|
|
return -1
|
|
|
|
|
end
|
2022-12-20 12:51:54 +08:00
|
|
|
|
local right = 0
|
|
|
|
|
local temp = self
|
2023-07-08 01:05:54 +08:00
|
|
|
|
local try_time = 10
|
|
|
|
|
for _ = 0, try_time do
|
|
|
|
|
if temp == other then break end
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if (ignore_dead or not temp.dead) and not temp:isRemoved() then
|
2022-12-20 12:51:54 +08:00
|
|
|
|
right = right + 1
|
|
|
|
|
end
|
|
|
|
|
temp = temp.next
|
|
|
|
|
end
|
2023-07-08 01:05:54 +08:00
|
|
|
|
if temp ~= other then
|
2023-09-27 21:02:22 +08:00
|
|
|
|
print("Distance malfunction: start and end does not match.")
|
2023-07-08 01:05:54 +08:00
|
|
|
|
end
|
2023-08-24 21:37:06 +08:00
|
|
|
|
local left = #(ignore_dead and Fk:currentRoom().players or Fk:currentRoom().alive_players) - right - #table.filter(Fk:currentRoom().alive_players, function(p) return p:isRemoved() end)
|
2023-07-08 01:05:54 +08:00
|
|
|
|
local ret = 0
|
|
|
|
|
if mode == "left" then
|
|
|
|
|
ret = left
|
|
|
|
|
elseif mode == "right" then
|
|
|
|
|
ret = right
|
|
|
|
|
else
|
|
|
|
|
ret = math.min(left, right)
|
|
|
|
|
end
|
2023-01-04 14:21:29 +08:00
|
|
|
|
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[DistanceSkill] or Util.DummyTable
|
2023-01-04 14:21:29 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
2023-07-08 01:05:54 +08:00
|
|
|
|
local fixed = skill:getFixed(self, other)
|
2023-01-04 14:21:29 +08:00
|
|
|
|
local correct = skill:getCorrect(self, other)
|
2023-07-08 01:05:54 +08:00
|
|
|
|
if fixed ~= nil then
|
|
|
|
|
ret = fixed
|
|
|
|
|
break
|
|
|
|
|
end
|
2023-07-11 23:16:46 +08:00
|
|
|
|
ret = ret + (correct or 0)
|
2023-01-04 14:21:29 +08:00
|
|
|
|
end
|
2023-02-26 16:51:29 +08:00
|
|
|
|
|
2023-01-04 14:21:29 +08:00
|
|
|
|
if self.fixedDistance[other] then
|
|
|
|
|
ret = self.fixedDistance[other]
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
|
return math.max(ret, 1)
|
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
--- 获取其他玩家是否在玩家的攻击范围内。
|
2023-04-01 23:06:55 +08:00
|
|
|
|
---@param other Player @ 其他玩家
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param fixLimit? integer @ 卡牌距离限制增加专用
|
2023-05-28 18:58:58 +08:00
|
|
|
|
function Player:inMyAttackRange(other, fixLimit)
|
2023-07-08 01:05:54 +08:00
|
|
|
|
assert(other:isInstanceOf(Player))
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if self == other or (other and (other.dead or other:isRemoved())) or self:isRemoved() then
|
2023-01-22 00:49:11 +08:00
|
|
|
|
return false
|
|
|
|
|
end
|
2023-05-28 18:45:54 +08:00
|
|
|
|
|
2023-05-28 18:58:58 +08:00
|
|
|
|
fixLimit = fixLimit or 0
|
|
|
|
|
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable
|
2023-05-28 18:45:54 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:withinAttackRange(self, other) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-01-22 00:49:11 +08:00
|
|
|
|
local baseAttackRange = self:getAttackRange()
|
2023-05-28 18:58:58 +08:00
|
|
|
|
return self:distanceTo(other) <= (baseAttackRange + fixLimit)
|
2022-09-14 13:01:10 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:06 +08:00
|
|
|
|
--- 获取下家。
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param ignoreRemoved? boolean @ 忽略被移除
|
|
|
|
|
---@param num? integer @ 第几个,默认1
|
2023-08-24 21:37:06 +08:00
|
|
|
|
---@return ServerPlayer
|
2023-12-10 18:55:16 +08:00
|
|
|
|
function Player:getNextAlive(ignoreRemoved, num, ignoreRest)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if #Fk:currentRoom().alive_players == 0 then
|
2023-12-10 18:55:16 +08:00
|
|
|
|
return self.rest > 0 and self.next.rest > 0 and self.next or self
|
2023-08-24 21:37:06 +08:00
|
|
|
|
end
|
|
|
|
|
local doNotIgnore = not ignoreRemoved
|
|
|
|
|
if doNotIgnore and table.every(Fk:currentRoom().alive_players, function(p) return p:isRemoved() end) then
|
2023-06-09 01:10:16 +08:00
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
|
2023-09-30 11:51:17 +08:00
|
|
|
|
local ret = self
|
|
|
|
|
num = num or 1
|
|
|
|
|
for _ = 1, num do
|
2023-06-09 01:10:16 +08:00
|
|
|
|
ret = ret.next
|
2023-12-10 18:55:16 +08:00
|
|
|
|
while (ret.dead and not ignoreRest) or (doNotIgnore and ret:isRemoved()) do
|
2023-09-30 11:51:17 +08:00
|
|
|
|
ret = ret.next
|
|
|
|
|
end
|
2023-06-09 01:10:16 +08:00
|
|
|
|
end
|
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-09-30 11:51:17 +08:00
|
|
|
|
--- 获取上家。
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param ignoreRemoved boolean @ 忽略被移除
|
|
|
|
|
---@param num? integer @ 第几个,默认1
|
2023-09-30 11:51:17 +08:00
|
|
|
|
---@return ServerPlayer
|
|
|
|
|
function Player:getLastAlive(ignoreRemoved, num)
|
|
|
|
|
num = num or 1
|
2023-12-09 21:57:47 +08:00
|
|
|
|
local index = (ignoreRemoved and #Fk:currentRoom().alive_players or #table.filter(Fk:currentRoom().alive_players, function(p) return not p:isRemoved() end)) - num
|
2023-09-30 11:51:17 +08:00
|
|
|
|
return self:getNextAlive(ignoreRemoved, index)
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 增加玩家使用特定牌的历史次数。
|
|
|
|
|
---@param cardName string @ 牌名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param num? integer @ 次数
|
2022-04-30 15:27:56 +08:00
|
|
|
|
function Player:addCardUseHistory(cardName, num)
|
2023-01-29 18:11:41 +08:00
|
|
|
|
num = num or 1
|
2022-04-30 15:27:56 +08:00
|
|
|
|
assert(type(num) == "number" and num ~= 0)
|
|
|
|
|
|
2023-01-29 18:11:41 +08:00
|
|
|
|
self.cardUsedHistory[cardName] = self.cardUsedHistory[cardName] or {0, 0, 0, 0}
|
|
|
|
|
local t = self.cardUsedHistory[cardName]
|
|
|
|
|
for i, _ in ipairs(t) do
|
|
|
|
|
t[i] = t[i] + num
|
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 设定玩家使用特定牌的历史次数。
|
|
|
|
|
---@param cardName string @ 牌名
|
|
|
|
|
---@param num integer @ 次数
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param scope? integer @ 历史范围 全为nil意为清空
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:setCardUseHistory(cardName, num, scope)
|
|
|
|
|
if cardName == "" and num == nil and scope == nil then
|
2022-12-20 12:51:54 +08:00
|
|
|
|
self.cardUsedHistory = {}
|
2023-01-29 18:11:41 +08:00
|
|
|
|
return
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
2023-01-29 18:11:41 +08:00
|
|
|
|
|
|
|
|
|
num = num or 0
|
|
|
|
|
if cardName == "" then
|
|
|
|
|
for _, v in pairs(self.cardUsedHistory) do
|
|
|
|
|
v[scope] = num
|
|
|
|
|
end
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if self.cardUsedHistory[cardName] then
|
2023-01-29 18:11:41 +08:00
|
|
|
|
self.cardUsedHistory[cardName][scope] = num
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 增加玩家使用特定技能的历史次数。
|
|
|
|
|
---@param skill_name string @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param num? integer @ 次数 默认1
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:addSkillUseHistory(skill_name, num)
|
|
|
|
|
num = num or 1
|
|
|
|
|
assert(type(num) == "number" and num ~= 0)
|
|
|
|
|
|
|
|
|
|
self.skillUsedHistory[skill_name] = self.skillUsedHistory[skill_name] or {0, 0, 0, 0}
|
|
|
|
|
local t = self.skillUsedHistory[skill_name]
|
|
|
|
|
for i, _ in ipairs(t) do
|
|
|
|
|
t[i] = t[i] + num
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-08 18:39:58 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 设定玩家使用特定技能的历史次数。
|
|
|
|
|
---@param skill_name string @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param num? integer @ 次数 默认0
|
|
|
|
|
---@param scope? integer @ 查询历史范围
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:setSkillUseHistory(skill_name, num, scope)
|
|
|
|
|
if skill_name == "" and num == nil and scope == nil then
|
|
|
|
|
self.skillUsedHistory = {}
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
num = num or 0
|
|
|
|
|
if skill_name == "" then
|
|
|
|
|
for _, v in pairs(self.skillUsedHistory) do
|
|
|
|
|
v[scope] = num
|
|
|
|
|
end
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-16 13:26:02 +08:00
|
|
|
|
self.skillUsedHistory[skill_name] = self.skillUsedHistory[skill_name] or {0, 0, 0, 0}
|
|
|
|
|
self.skillUsedHistory[skill_name][scope] = num
|
2023-01-29 18:11:41 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家使用特定牌的历史次数。
|
|
|
|
|
---@param cardName string @ 牌名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param scope? integer @ 查询历史范围,默认Turn
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function Player:usedCardTimes(cardName, scope)
|
|
|
|
|
if not self.cardUsedHistory[cardName] then
|
|
|
|
|
return 0
|
|
|
|
|
end
|
|
|
|
|
scope = scope or Player.HistoryTurn
|
|
|
|
|
return self.cardUsedHistory[cardName][scope]
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家使用特定技能的历史次数。
|
|
|
|
|
---@param skill_name string @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param scope? integer @ 查询历史范围,默认Turn
|
2023-07-08 01:05:54 +08:00
|
|
|
|
function Player:usedSkillTimes(skill_name, scope)
|
|
|
|
|
if not self.skillUsedHistory[skill_name] then
|
2023-01-29 18:11:41 +08:00
|
|
|
|
return 0
|
|
|
|
|
end
|
|
|
|
|
scope = scope or Player.HistoryTurn
|
2023-07-08 01:05:54 +08:00
|
|
|
|
return self.skillUsedHistory[skill_name][scope]
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家是否无手牌。
|
2022-09-14 13:01:10 +08:00
|
|
|
|
function Player:isKongcheng()
|
|
|
|
|
return #self:getCardIds(Player.Hand) == 0
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家是否无手牌及装备牌。
|
2022-09-14 13:01:10 +08:00
|
|
|
|
function Player:isNude()
|
|
|
|
|
return #self:getCardIds{Player.Hand, Player.Equip} == 0
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家所有区域是否无牌。
|
2022-09-14 13:01:10 +08:00
|
|
|
|
function Player:isAllNude()
|
|
|
|
|
return #self:getCardIds() == 0
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家是否受伤。
|
2022-12-20 12:51:54 +08:00
|
|
|
|
function Player:isWounded()
|
|
|
|
|
return self.hp < self.maxHp
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取玩家已失去体力。
|
2023-03-09 12:19:16 +08:00
|
|
|
|
function Player:getLostHp()
|
|
|
|
|
return math.min(self.maxHp - self.hp, self.maxHp)
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
|
---@param skill string | Skill
|
|
|
|
|
---@return Skill
|
|
|
|
|
local function getActualSkill(skill)
|
|
|
|
|
if type(skill) == "string" then
|
|
|
|
|
skill = Fk.skills[skill]
|
|
|
|
|
end
|
|
|
|
|
assert(skill:isInstanceOf(Skill))
|
|
|
|
|
return skill
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 检索玩家是否有对应技能。
|
|
|
|
|
---@param skill string | Skill @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param ignoreNullified? boolean @ 忽略技能是否被无效
|
|
|
|
|
---@param ignoreAlive? boolean @ 忽略角色在场与否
|
2023-03-20 20:49:23 +08:00
|
|
|
|
function Player:hasSkill(skill, ignoreNullified, ignoreAlive)
|
|
|
|
|
if not ignoreAlive and self.dead then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
|
skill = getActualSkill(skill)
|
|
|
|
|
|
2023-03-20 20:49:23 +08:00
|
|
|
|
if not (ignoreNullified or skill:isEffectable(self)) then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
|
if table.contains(self.player_skills, skill) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-09 22:25:15 +08:00
|
|
|
|
if self:isInstanceOf(ServerPlayer) and -- isInstanceOf(nil) will return false
|
|
|
|
|
table.contains(self._fake_skills, skill) and
|
|
|
|
|
table.contains(self.prelighted_skills, skill) then
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
|
for _, v in pairs(self.derivative_skills) do
|
|
|
|
|
if table.contains(v, skill) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为玩家增加对应技能。
|
|
|
|
|
---@param skill string | Skill @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param source_skill? string | Skill @ 本有技能(和衍生技能相对)
|
2022-09-14 13:01:10 +08:00
|
|
|
|
---@return Skill[] @ got skills that Player didn't have at start
|
|
|
|
|
function Player:addSkill(skill, source_skill)
|
|
|
|
|
skill = getActualSkill(skill)
|
|
|
|
|
|
2023-01-04 14:21:29 +08:00
|
|
|
|
local toget = {table.unpack(skill.related_skills)}
|
2022-09-14 13:01:10 +08:00
|
|
|
|
table.insert(toget, skill)
|
2023-01-04 14:21:29 +08:00
|
|
|
|
|
|
|
|
|
local room = Fk:currentRoom()
|
2022-09-14 13:01:10 +08:00
|
|
|
|
local ret = {}
|
|
|
|
|
for _, s in ipairs(toget) do
|
2023-03-20 20:49:23 +08:00
|
|
|
|
if not self:hasSkill(s, true, true) then
|
2022-09-14 13:01:10 +08:00
|
|
|
|
table.insert(ret, s)
|
2023-01-29 18:11:41 +08:00
|
|
|
|
if s:isInstanceOf(TriggerSkill) and RoomInstance then
|
|
|
|
|
room.logic:addTriggerSkill(s)
|
2023-01-04 14:21:29 +08:00
|
|
|
|
end
|
2023-01-29 18:11:41 +08:00
|
|
|
|
if s:isInstanceOf(StatusSkill) then
|
2023-03-18 15:34:42 +08:00
|
|
|
|
room.status_skills[s.class] = room.status_skills[s.class] or {}
|
|
|
|
|
table.insertIfNeed(room.status_skills[s.class], s)
|
2023-01-04 14:21:29 +08:00
|
|
|
|
end
|
2022-09-14 13:01:10 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if source_skill then
|
|
|
|
|
source_skill = getActualSkill(source_skill)
|
|
|
|
|
if not self.derivative_skills[source_skill] then
|
|
|
|
|
self.derivative_skills[source_skill] = {}
|
|
|
|
|
end
|
|
|
|
|
table.insertIfNeed(self.derivative_skills[source_skill], skill)
|
|
|
|
|
else
|
|
|
|
|
table.insertIfNeed(self.player_skills, skill)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- add related skills
|
|
|
|
|
if not self.derivative_skills[skill] then
|
|
|
|
|
self.derivative_skills[skill] = {}
|
|
|
|
|
end
|
|
|
|
|
for _, s in ipairs(skill.related_skills) do
|
|
|
|
|
table.insertIfNeed(self.derivative_skills[skill], s)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 为玩家删除对应技能。
|
|
|
|
|
---@param skill string | Skill @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param source_skill? string | Skill @ 本有技能(和衍生技能相对)
|
2022-09-14 13:01:10 +08:00
|
|
|
|
---@return Skill[] @ lost skills that the Player doesn't have anymore
|
|
|
|
|
function Player:loseSkill(skill, source_skill)
|
|
|
|
|
skill = getActualSkill(skill)
|
|
|
|
|
|
|
|
|
|
if source_skill then
|
|
|
|
|
source_skill = getActualSkill(source_skill)
|
|
|
|
|
if not self.derivative_skills[source_skill] then
|
|
|
|
|
self.derivative_skills[source_skill] = {}
|
|
|
|
|
end
|
|
|
|
|
table.removeOne(self.derivative_skills[source_skill], skill)
|
|
|
|
|
else
|
|
|
|
|
table.removeOne(self.player_skills, skill)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- clear derivative skills of this skill as well
|
2023-07-14 22:17:54 +08:00
|
|
|
|
local tolose = self.derivative_skills[skill] or {}
|
2022-09-14 13:01:10 +08:00
|
|
|
|
table.insert(tolose, skill)
|
|
|
|
|
self.derivative_skills[skill] = nil
|
|
|
|
|
|
|
|
|
|
local ret = {} ---@type Skill[]
|
|
|
|
|
for _, s in ipairs(tolose) do
|
2023-03-20 20:49:23 +08:00
|
|
|
|
if not self:hasSkill(s, true, true) then
|
2022-09-14 13:01:10 +08:00
|
|
|
|
table.insert(ret, s)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-01 23:06:55 +08:00
|
|
|
|
--- 获取对应玩家所有技能。
|
2023-02-15 19:54:35 +08:00
|
|
|
|
-- return all skills that xxx:hasSkill() == true
|
|
|
|
|
function Player:getAllSkills()
|
|
|
|
|
local ret = {table.unpack(self.player_skills)}
|
|
|
|
|
for _, t in pairs(self.derivative_skills) do
|
|
|
|
|
for _, s in ipairs(t) do
|
|
|
|
|
table.insertIfNeed(ret, s)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-30 00:48:37 +08:00
|
|
|
|
--- 确认玩家是否可以使用特定牌。
|
|
|
|
|
---@param card Card @ 特定牌
|
2024-02-04 15:55:44 +08:00
|
|
|
|
---@param extra_data? UseExtraData @ 额外数据
|
|
|
|
|
function Player:canUse(card, extra_data)
|
|
|
|
|
return card.skill:canUse(self, card, extra_data)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 确认玩家是否可以对特定玩家使用特定牌。
|
|
|
|
|
---@param card Card @ 特定牌
|
|
|
|
|
---@param to Player @ 特定玩家
|
|
|
|
|
---@param extra_data? UseExtraData @ 额外数据
|
|
|
|
|
function Player:canUseTo(card, to, extra_data)
|
|
|
|
|
if self:prohibitUse(card) or self:isProhibited(to, card) then return false end
|
|
|
|
|
local distance_limited = not (extra_data and extra_data.bypass_distances)
|
|
|
|
|
local can_use = self:canUse(card, extra_data)
|
|
|
|
|
return can_use and card.skill:modTargetFilter(to.id, {}, self.id, card, distance_limited)
|
2023-06-30 00:48:37 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 确认玩家是否被禁止对特定玩家使用特定牌。
|
2023-06-03 23:59:04 +08:00
|
|
|
|
---@param to Player @ 特定玩家
|
|
|
|
|
---@param card Card @ 特定牌
|
2023-04-13 20:17:39 +08:00
|
|
|
|
function Player:isProhibited(to, card)
|
|
|
|
|
local r = Fk:currentRoom()
|
2023-08-13 02:25:04 +08:00
|
|
|
|
|
|
|
|
|
if card.type == Card.TypeEquip and #to:getAvailableEquipSlots(card.sub_type) == 0 then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-13 12:34:36 +08:00
|
|
|
|
if card.sub_type == Card.SubtypeDelayedTrick and
|
|
|
|
|
(table.contains(to.sealedSlots, Player.JudgeSlot) or to:hasDelayedTrick(card.name)) then
|
2023-08-13 02:25:04 +08:00
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = r.status_skills[ProhibitSkill] or Util.DummyTable
|
2023-04-13 20:17:39 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:isProhibited(self, to, card) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-30 00:48:37 +08:00
|
|
|
|
--- 确认玩家是否被禁止使用特定牌。
|
2023-06-03 23:59:04 +08:00
|
|
|
|
---@param card Card @ 特定的牌
|
2023-04-13 20:17:39 +08:00
|
|
|
|
function Player:prohibitUse(card)
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable
|
2023-04-13 20:17:39 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:prohibitUse(self, card) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-30 00:48:37 +08:00
|
|
|
|
--- 确认玩家是否被禁止打出特定牌。
|
2023-06-03 23:59:04 +08:00
|
|
|
|
---@param card Card @ 特定的牌
|
2023-04-13 20:17:39 +08:00
|
|
|
|
function Player:prohibitResponse(card)
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable
|
2023-04-13 20:17:39 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:prohibitResponse(self, card) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-30 00:48:37 +08:00
|
|
|
|
--- 确认玩家是否被禁止弃置特定牌。
|
2023-06-03 23:59:04 +08:00
|
|
|
|
---@param card Card @ 特定的牌
|
2023-04-13 20:17:39 +08:00
|
|
|
|
function Player:prohibitDiscard(card)
|
2023-06-11 16:22:11 +08:00
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable
|
2023-04-13 20:17:39 +08:00
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:prohibitDiscard(self, card) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:06 +08:00
|
|
|
|
--- 确认角色是否被禁止亮将。
|
|
|
|
|
function Player:prohibitReveal(isDeputy)
|
|
|
|
|
local place = isDeputy and "d" or "m"
|
|
|
|
|
if type(self:getMark(MarkEnum.RevealProhibited)) == "table" and table.contains(self:getMark(MarkEnum.RevealProhibited), place) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
|
|
|
|
return self:getMark(MarkEnum.RevealProhibited .. s)
|
|
|
|
|
end)) do
|
|
|
|
|
if type(m) == "table" and table.contains(m, place) then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-12-12 21:34:51 +08:00
|
|
|
|
---@param to Player
|
|
|
|
|
---@param ignoreFromKong? boolean
|
|
|
|
|
---@param ignoreToKong? boolean
|
|
|
|
|
function Player:canPindian(to, ignoreFromKong, ignoreToKong)
|
2023-12-28 12:11:24 +08:00
|
|
|
|
if self == to then return false end
|
|
|
|
|
|
2023-12-12 21:34:51 +08:00
|
|
|
|
if self:isKongcheng() and not ignoreFromKong then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
if to:isKongcheng() and not ignoreToKong then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable
|
|
|
|
|
for _, skill in ipairs(status_skills) do
|
|
|
|
|
if skill:prohibitPindian(self, to) then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-14 23:12:46 +08:00
|
|
|
|
--转换技状态阳
|
2023-05-13 14:20:34 +08:00
|
|
|
|
fk.SwitchYang = 0
|
2023-07-14 23:12:46 +08:00
|
|
|
|
--转换技状态阴
|
2023-05-13 14:20:34 +08:00
|
|
|
|
fk.SwitchYin = 1
|
|
|
|
|
|
2023-06-03 23:59:04 +08:00
|
|
|
|
--- 获取转换技状态
|
|
|
|
|
---@param skillName string @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param afterUse? boolean @ 是否提前计算转换后状态
|
|
|
|
|
---@param inWord? boolean @ 是否返回文字
|
2023-07-14 23:12:46 +08:00
|
|
|
|
---@return number|string @ 转换技状态
|
2023-06-30 00:48:37 +08:00
|
|
|
|
function Player:getSwitchSkillState(skillName, afterUse, inWord)
|
2023-05-13 14:20:34 +08:00
|
|
|
|
if afterUse then
|
2023-06-30 00:48:37 +08:00
|
|
|
|
return self:getMark(MarkEnum.SwithSkillPreName .. skillName) < 1 and (inWord and "yin" or fk.SwitchYin) or (inWord and "yang" or fk.SwitchYang)
|
2023-05-13 14:20:34 +08:00
|
|
|
|
else
|
2023-06-30 00:48:37 +08:00
|
|
|
|
return self:getMark(MarkEnum.SwithSkillPreName .. skillName) < 1 and (inWord and "yang" or fk.SwitchYang) or (inWord and "yin" or fk.SwitchYin)
|
2023-05-13 14:20:34 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-05-20 16:00:03 +08:00
|
|
|
|
function Player:canMoveCardInBoardTo(to, id)
|
2023-05-28 18:45:54 +08:00
|
|
|
|
if self == to then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-16 19:18:43 +08:00
|
|
|
|
local card = self:getVirualEquip(id) or Fk:getCardById(id)
|
2023-05-20 16:00:03 +08:00
|
|
|
|
assert(card.type == Card.TypeEquip or card.sub_type == Card.SubtypeDelayedTrick)
|
|
|
|
|
|
|
|
|
|
if card.type == Card.TypeEquip then
|
2023-08-13 02:25:04 +08:00
|
|
|
|
return to:hasEmptyEquipSlot(card.sub_type)
|
2023-05-20 16:00:03 +08:00
|
|
|
|
else
|
2023-08-13 02:25:04 +08:00
|
|
|
|
return
|
|
|
|
|
not (
|
|
|
|
|
table.find(to:getCardIds(Player.Judge), function(cardId)
|
2024-02-04 15:29:39 +08:00
|
|
|
|
return (to:getVirualEquip(cardId) or Fk:getCardById(cardId)).name == card.name
|
2023-08-13 02:25:04 +08:00
|
|
|
|
end) or
|
|
|
|
|
table.contains(to.sealedSlots, Player.JudgeSlot)
|
|
|
|
|
)
|
2023-05-20 16:00:03 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-16 19:18:43 +08:00
|
|
|
|
function Player:canMoveCardsInBoardTo(to, flag, excludeIds)
|
2023-05-28 18:45:54 +08:00
|
|
|
|
if self == to then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
assert(flag == nil or flag == "e" or flag == "j")
|
2023-07-16 19:18:43 +08:00
|
|
|
|
excludeIds = type(excludeIds) == "table" and excludeIds or {}
|
2023-05-28 18:45:54 +08:00
|
|
|
|
|
|
|
|
|
local areas = {}
|
|
|
|
|
if flag == "e" then
|
|
|
|
|
table.insert(areas, Player.Equip)
|
|
|
|
|
elseif flag == "j" then
|
|
|
|
|
table.insert(areas, Player.Judge)
|
|
|
|
|
else
|
|
|
|
|
areas = { Player.Equip, Player.Judge }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for _, cardId in ipairs(self:getCardIds(areas)) do
|
2023-07-16 19:18:43 +08:00
|
|
|
|
if not table.contains(excludeIds, cardId) and self:canMoveCardInBoardTo(to, cardId) then
|
2023-05-28 18:45:54 +08:00
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Player:getQuestSkillState(skillName)
|
|
|
|
|
local questSkillState = self:getMark(MarkEnum.QuestSkillPreName .. skillName)
|
|
|
|
|
return type(questSkillState) == "string" and questSkillState or nil
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-13 02:25:04 +08:00
|
|
|
|
function Player:getAvailableEquipSlots(subtype)
|
|
|
|
|
local tempSlots = table.simpleClone(self.equipSlots)
|
|
|
|
|
local tempSealedSlots = table.simpleClone(self.sealedSlots)
|
|
|
|
|
|
|
|
|
|
if subtype then
|
|
|
|
|
local singleSlot = table.filter(tempSlots, function(slot)
|
2023-08-25 08:11:25 +08:00
|
|
|
|
return slot == Util.convertSubtypeAndEquipSlot(subtype)
|
2023-08-13 02:25:04 +08:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
for _, sealedSlot in ipairs(tempSealedSlots) do
|
|
|
|
|
table.removeOne(singleSlot, sealedSlot)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return singleSlot
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for _, sealedSlot in ipairs(tempSealedSlots) do
|
|
|
|
|
table.removeOne(tempSlots, sealedSlot)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return tempSlots
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Player:hasEmptyEquipSlot(subtype)
|
|
|
|
|
return #self:getAvailableEquipSlots(subtype) - #self:getEquipments(subtype) > 0
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-12 00:50:17 +08:00
|
|
|
|
function Player:addBuddy(other)
|
|
|
|
|
table.insert(self.buddy_list, other.id)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Player:removeBuddy(other)
|
|
|
|
|
table.removeOne(self.buddy_list, other.id)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Player:isBuddy(other)
|
|
|
|
|
local id = type(other) == "number" and other or other.id
|
|
|
|
|
return self.id == id or table.contains(self.buddy_list, id)
|
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
--- 比较两名角色的性别是否相同。
|
|
|
|
|
---@param other Player @ 另一名角色
|
|
|
|
|
---@param diff? bool @ 比较二者不同
|
|
|
|
|
---@return boolean @ 返回比较结果
|
|
|
|
|
function Player:compareGenderWith(other, diff)
|
|
|
|
|
if self == other then return not diff end
|
|
|
|
|
if self.gender == General.Agender or other.gender == General.Agender then return false end
|
|
|
|
|
if self.gender == General.Bigender or other.gender == General.Bigender then return true end
|
|
|
|
|
if diff then
|
|
|
|
|
return self.gender ~= other.gender
|
|
|
|
|
else
|
|
|
|
|
return self.gender == other.gender
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-03-27 14:49:41 +08:00
|
|
|
|
return Player
|