diff --git a/lua/client/client.lua b/lua/client/client.lua index ec28608a..04bc50a3 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -4,6 +4,7 @@ ---@field alive_players ClientPlayer[] ---@field current ClientPlayer ---@field discard_pile integer[] +---@field status_skills Skill[] Client = class('Client') -- load client classes @@ -28,6 +29,10 @@ function Client:initialize() self.players = {} -- ClientPlayer[] self.alive_players = {} self.discard_pile = {} + self.status_skills = {} + for class, skills in pairs(Fk.global_status_skill) do + self.status_skills[class] = {table.unpack(skills)} + end end ---@param id integer diff --git a/lua/client/clientplayer.lua b/lua/client/clientplayer.lua index 9372187b..b39d23a9 100644 --- a/lua/client/clientplayer.lua +++ b/lua/client/clientplayer.lua @@ -12,19 +12,4 @@ function ClientPlayer:initialize(cp) self.global_known_cards = {} -- card that visible to all players end ----@param skill Skill -function ClientPlayer:hasSkill(skill) - return table.contains(self.player_skills, skill) -end - ----@param skill Skill -function ClientPlayer:addSkill(skill) - table.insert(self.player_skills, skill) -end - ----@param skill Skill -function ClientPlayer:loseSkill(skill) - table.removeOne(self.player_skills, skill) -end - return ClientPlayer diff --git a/lua/core/engine.lua b/lua/core/engine.lua index ae828b9b..6164939a 100644 --- a/lua/core/engine.lua +++ b/lua/core/engine.lua @@ -4,6 +4,7 @@ ---@field skills table ---@field related_skills table ---@field global_trigger TriggerSkill[] +---@field global_status_skill table ---@field generals table ---@field lords string[] ---@field cards Card[] @@ -24,6 +25,7 @@ function Engine:initialize() self.skills = {} -- name --> Skill self.related_skills = {} -- skillName --> relatedSkill[] self.global_trigger = {} + self.global_status_skill = {} self.generals = {} -- name --> General self.lords = {} -- lordName[] self.cards = {} -- Card[] @@ -97,6 +99,16 @@ function Engine:addSkill(skill) error(string.format("Duplicate skill %s detected", skill.name)) end self.skills[skill.name] = skill + + if skill.global then + if skill:isInstanceOf(TriggerSkill) then + table.insert(self.global_trigger, skill) + else + local t = self.global_status_skill + t[skill.class] = t[skill.class] or {} + table.insert(t[skill.class], skill) + end + end end ---@param skills Skill[] diff --git a/lua/core/general.lua b/lua/core/general.lua index dd06d163..3d5db293 100644 --- a/lua/core/general.lua +++ b/lua/core/general.lua @@ -24,6 +24,8 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender) self.skills = {} -- skills first added to this general self.other_skills = {} -- skill belongs other general, e.g. "mashu" of pangde + + package:addGeneral(self) end ---@param skill Skill diff --git a/lua/core/package.lua b/lua/core/package.lua index b5180a0a..b9a54dd8 100644 --- a/lua/core/package.lua +++ b/lua/core/package.lua @@ -41,7 +41,7 @@ end ---@param general General function Package:addGeneral(general) assert(general.class and general:isInstanceOf(General)) - table.insert(self.generals, general) + table.insertIfNeed(self.generals, general) end ---@param card Card diff --git a/lua/core/player.lua b/lua/core/player.lua index e6366a3c..f4162c3b 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -22,6 +22,7 @@ ---@field player_cards table ---@field special_cards table ---@field cardUsedHistory table +---@field fixedDistance table local Player = class("Player") ---@alias Phase integer @@ -72,6 +73,7 @@ function Player:initialize() self.special_cards = {} self.cardUsedHistory = {} + self.fixedDistance = {} end ---@param general General @@ -226,6 +228,17 @@ function Player:getAttackRange() return math.max(baseAttackRange, 0) end +---@param other Player +---@param num integer +function Player:setFixedDistance(other, num) + self.fixedDistance[other] = num +end + +---@param other Player +function Player:removeFixedDistance(other) + self.fixedDistance[other] = nil +end + ---@param other Player function Player:distanceTo(other) assert(other:isInstanceOf(Player)) @@ -239,7 +252,17 @@ function Player:distanceTo(other) end local left = #Fk:currentRoom().alive_players - right local ret = math.min(left, right) - -- TODO: corrent distance here using skills + + local status_skills = Fk:currentRoom().status_skills[DistanceSkill] or {} + for _, skill in ipairs(status_skills) do + local correct = skill:getCorrect(self, other) + ret = ret + correct + end + + if self.fixedDistance[other] then + ret = self.fixedDistance[other] + end + return math.max(ret, 1) end @@ -334,12 +357,21 @@ end function Player:addSkill(skill, source_skill) skill = getActualSkill(skill) - local toget = table.clone(skill.related_skills) + local toget = {table.unpack(skill.related_skills)} table.insert(toget, skill) + + local room = Fk:currentRoom() local ret = {} for _, s in ipairs(toget) do if not self:hasSkill(s) then table.insert(ret, s) + if skill:isInstanceOf(TriggerSkill) and RoomInstance then + room.logic:addTriggerSkill(skill) + end + if table.contains(StatusSkills, skill.class) then + room.status_skills[skill.class] = room.status_skills[skill.class] or {} + table.insertIfNeed(room.status_skills[skill.class], skill) + end end end diff --git a/lua/core/skill_type/distance.lua b/lua/core/skill_type/distance.lua index e69de29b..b6b82a3e 100644 --- a/lua/core/skill_type/distance.lua +++ b/lua/core/skill_type/distance.lua @@ -0,0 +1,18 @@ +---@class DistanceSkill : Skill +---@field global boolean +local DistanceSkill = Skill:subclass("DistanceSkill") + +function DistanceSkill:initialize(name) + Skill.initialize(self, name, Skill.NotFrequent) + + self.global = false +end + +---@param from Player +---@param to Player +---@return integer +function DistanceSkill:getCorrect(from, to) + return 0 +end + +return DistanceSkill diff --git a/lua/core/util.lua b/lua/core/util.lua index 16049c85..b28c23d4 100644 --- a/lua/core/util.lua +++ b/lua/core/util.lua @@ -10,7 +10,7 @@ function fk.qlist(list) end function table:contains(element) - if #self == 0 or type(self[1]) ~= type(element) then return false end + if #self == 0 then return false end for _, e in ipairs(self) do if e == element then return true end end diff --git a/lua/fk_ex.lua b/lua/fk_ex.lua index 27c4e669..9a736110 100644 --- a/lua/fk_ex.lua +++ b/lua/fk_ex.lua @@ -4,6 +4,10 @@ dofile "lua/server/event.lua" dofile "lua/server/system_enum.lua" TriggerSkill = require "core.skill_type.trigger" ActiveSkill = require "core.skill_type.active_skill" +DistanceSkill = require "core.skill_type.distance" +StatusSkills = { + DistanceSkill, +} BasicCard = require "core.card_type.basic" local Trick = require "core.card_type.trick" @@ -107,6 +111,25 @@ function fk.CreateActiveSkill(spec) return skill end +---@class DistanceSpec: SkillSpec +---@field correct_func fun(self: DistanceSkill, from: Player, to: Player) +---@field global boolean + +---@param spec DistanceSpec +---@return DistanceSkill +function fk.CreateDistanceSkill(spec) + assert(type(spec.name) == "string") + assert(type(spec.correct_func) == "function") + + local skill = DistanceSkill:new(spec.name) + skill.getCorrect = spec.correct_func + if spec.global then + skill.global = spec.global + end + + return skill +end + ---@class CardSpec: Card ---@field skill Skill diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index 76baab26..8f58b48e 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -135,7 +135,7 @@ function GameLogic:prepareForStart() end for _, p in ipairs(room.alive_players) do - room:handleAddLoseSkills(p, "zhiheng", nil, false) + room:handleAddLoseSkills(p, "zhiheng|mashu", nil, false) end self:addTriggerSkill(GameRule) diff --git a/lua/server/room.lua b/lua/server/room.lua index 7efec8ad..57a1f103 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -12,6 +12,7 @@ ---@field void integer[] ---@field card_place table ---@field owner_map table +---@field status_skills Skill[] local Room = class("Room") -- load classes used by the game @@ -71,6 +72,10 @@ function Room:initialize(_room) self.void = {} self.card_place = {} self.owner_map = {} + self.status_skills = {} + for class, skills in pairs(Fk.global_status_skill) do + self.status_skills[class] = {table.unpack(skills)} + end end -- When this function returns, the Room(C++) thread stopped. diff --git a/packages/standard/init.lua b/packages/standard/init.lua index 1d14b2b6..660aba96 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -12,85 +12,81 @@ Fk:loadTranslationTable{ } local caocao = General:new(extension, "caocao", "wei", 4) -extension:addGeneral(caocao) Fk:loadTranslationTable{ ["caocao"] = "曹操", } local simayi = General:new(extension, "simayi", "wei", 3) -extension:addGeneral(simayi) Fk:loadTranslationTable{ ["simayi"] = "司马懿", } local xiahoudun = General:new(extension, "xiahoudun", "wei", 4) -extension:addGeneral(xiahoudun) Fk:loadTranslationTable{ ["xiahoudun"] = "夏侯惇", } local zhangliao = General:new(extension, "zhangliao", "wei", 4) -extension:addGeneral(zhangliao) Fk:loadTranslationTable{ ["zhangliao"] = "张辽", } local xuchu = General:new(extension, "xuchu", "wei", 4) -extension:addGeneral(xuchu) Fk:loadTranslationTable{ ["xuchu"] = "许褚", } local guojia = General:new(extension, "guojia", "wei", 3) -extension:addGeneral(guojia) Fk:loadTranslationTable{ ["guojia"] = "郭嘉", } local zhenji = General:new(extension, "zhenji", "wei", 3) -extension:addGeneral(zhenji) Fk:loadTranslationTable{ ["zhenji"] = "甄姬", } local liubei = General:new(extension, "liubei", "shu", 4) -extension:addGeneral(liubei) Fk:loadTranslationTable{ ["liubei"] = "刘备", } local guanyu = General:new(extension, "guanyu", "shu", 4) -extension:addGeneral(guanyu) Fk:loadTranslationTable{ ["guanyu"] = "关羽", } local zhangfei = General:new(extension, "zhangfei", "shu", 4) -extension:addGeneral(zhangfei) Fk:loadTranslationTable{ ["zhangfei"] = "张飞", } local zhugeliang = General:new(extension, "zhugeliang", "shu", 3) -extension:addGeneral(zhugeliang) Fk:loadTranslationTable{ ["zhugeliang"] = "诸葛亮", } local zhaoyun = General:new(extension, "zhaoyun", "shu", 4) -extension:addGeneral(zhaoyun) Fk:loadTranslationTable{ ["zhaoyun"] = "赵云", } +local mashu = fk.CreateDistanceSkill{ + name = "mashu", + correct_func = function(self, from, to) + if from:hasSkill(self.name) then + return -1 + end + end, +} local machao = General:new(extension, "machao", "shu", 4) -extension:addGeneral(machao) +machao:addSkill(mashu) Fk:loadTranslationTable{ ["machao"] = "马超", + ["mashu"] = "马术", } local huangyueying = General:new(extension, "huangyueying", "shu", 3) -extension:addGeneral(huangyueying) Fk:loadTranslationTable{ ["huangyueying"] = "黄月英", } @@ -108,68 +104,57 @@ local zhiheng = fk.CreateActiveSkill{ } local sunquan = General:new(extension, "sunquan", "wu", 4) sunquan:addSkill(zhiheng) -extension:addGeneral(sunquan) Fk:loadTranslationTable{ ["sunquan"] = "孙权", ["zhiheng"] = "制衡", } local ganning = General:new(extension, "ganning", "wu", 4) -extension:addGeneral(ganning) Fk:loadTranslationTable{ ["ganning"] = "甘宁", } local lvmeng = General:new(extension, "lvmeng", "wu", 4) -extension:addGeneral(lvmeng) Fk:loadTranslationTable{ ["lvmeng"] = "吕蒙", } local huanggai = General:new(extension, "huanggai", "wu", 4) -extension:addGeneral(huanggai) Fk:loadTranslationTable{ ["huanggai"] = "黄盖", } local zhouyu = General:new(extension, "zhouyu", "wu", 3) -extension:addGeneral(zhouyu) Fk:loadTranslationTable{ ["zhouyu"] = "周瑜", } local daqiao = General:new(extension, "daqiao", "wu", 3) -extension:addGeneral(daqiao) Fk:loadTranslationTable{ ["daqiao"] = "大乔", } local luxun = General:new(extension, "luxun", "wu", 3) -extension:addGeneral(luxun) Fk:loadTranslationTable{ ["luxun"] = "陆逊", } local sunshangxiang = General:new(extension, "sunshangxiang", "wu", 3) -extension:addGeneral(sunshangxiang) Fk:loadTranslationTable{ ["sunshangxiang"] = "孙尚香", } local huatuo = General:new(extension, "huatuo", "qun", 3) -extension:addGeneral(huatuo) Fk:loadTranslationTable{ ["huatuo"] = "华佗", } local lvbu = General:new(extension, "lvbu", "qun", 4) -extension:addGeneral(lvbu) Fk:loadTranslationTable{ ["lvbu"] = "吕布", } local diaochan = General:new(extension, "diaochan", "qun", 3) -extension:addGeneral(diaochan) Fk:loadTranslationTable{ ["diaochan"] = "貂蝉", } diff --git a/packages/standard_cards/init.lua b/packages/standard_cards/init.lua index cdc11179..341ebf9d 100644 --- a/packages/standard_cards/init.lua +++ b/packages/standard_cards/init.lua @@ -862,6 +862,24 @@ extension:addCards({ niohShield, }) +local horseSkill = fk.CreateDistanceSkill{ + name = "horse_skill", + global = true, + correct_func = function(self, from, to) + local ret = 0 + if from:getEquipment(Card.SubtypeOffensiveRide) then + ret = ret - 1 + end + if to:getEquipment(Card.SubtypeDefensiveRide) then + ret = ret + 1 + end + return ret + end, +} +if not Fk.skills["horse_skill"] then + Fk:addSkill(horseSkill) +end + local diLu = fk.CreateDefensiveRide{ name = "dilu", suit = Card.Club, diff --git a/qml/Pages/RoomElement/SkillArea.qml b/qml/Pages/RoomElement/SkillArea.qml index 8f4a2eb6..21efb4e0 100644 --- a/qml/Pages/RoomElement/SkillArea.qml +++ b/qml/Pages/RoomElement/SkillArea.qml @@ -71,7 +71,7 @@ Flickable { "GetSkillData", [skill_name] )); - if (data.freq = "active") { + if (data.freq === "active") { active_skills.append(data); } else { not_active_skills.append(data);