Distance skill (#37)

* global distance skill

* normal distance skill

* remove addGeneral from init.lua

* fixed distance
This commit is contained in:
notify 2023-01-04 14:21:29 +08:00 committed by GitHub
parent 9de041e969
commit 509cf29175
14 changed files with 131 additions and 46 deletions

View File

@ -4,6 +4,7 @@
---@field alive_players ClientPlayer[] ---@field alive_players ClientPlayer[]
---@field current ClientPlayer ---@field current ClientPlayer
---@field discard_pile integer[] ---@field discard_pile integer[]
---@field status_skills Skill[]
Client = class('Client') Client = class('Client')
-- load client classes -- load client classes
@ -28,6 +29,10 @@ function Client:initialize()
self.players = {} -- ClientPlayer[] self.players = {} -- ClientPlayer[]
self.alive_players = {} self.alive_players = {}
self.discard_pile = {} 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 end
---@param id integer ---@param id integer

View File

@ -12,19 +12,4 @@ function ClientPlayer:initialize(cp)
self.global_known_cards = {} -- card that visible to all players self.global_known_cards = {} -- card that visible to all players
end 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 return ClientPlayer

View File

@ -4,6 +4,7 @@
---@field skills table<string, Skill> ---@field skills table<string, Skill>
---@field related_skills table<string, Skill[]> ---@field related_skills table<string, Skill[]>
---@field global_trigger TriggerSkill[] ---@field global_trigger TriggerSkill[]
---@field global_status_skill table<class, Skill[]>
---@field generals table<string, General> ---@field generals table<string, General>
---@field lords string[] ---@field lords string[]
---@field cards Card[] ---@field cards Card[]
@ -24,6 +25,7 @@ function Engine:initialize()
self.skills = {} -- name --> Skill self.skills = {} -- name --> Skill
self.related_skills = {} -- skillName --> relatedSkill[] self.related_skills = {} -- skillName --> relatedSkill[]
self.global_trigger = {} self.global_trigger = {}
self.global_status_skill = {}
self.generals = {} -- name --> General self.generals = {} -- name --> General
self.lords = {} -- lordName[] self.lords = {} -- lordName[]
self.cards = {} -- Card[] self.cards = {} -- Card[]
@ -97,6 +99,16 @@ function Engine:addSkill(skill)
error(string.format("Duplicate skill %s detected", skill.name)) error(string.format("Duplicate skill %s detected", skill.name))
end end
self.skills[skill.name] = skill 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 end
---@param skills Skill[] ---@param skills Skill[]

View File

@ -24,6 +24,8 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender)
self.skills = {} -- skills first added to this general self.skills = {} -- skills first added to this general
self.other_skills = {} -- skill belongs other general, e.g. "mashu" of pangde self.other_skills = {} -- skill belongs other general, e.g. "mashu" of pangde
package:addGeneral(self)
end end
---@param skill Skill ---@param skill Skill

View File

@ -41,7 +41,7 @@ end
---@param general General ---@param general General
function Package:addGeneral(general) function Package:addGeneral(general)
assert(general.class and general:isInstanceOf(General)) assert(general.class and general:isInstanceOf(General))
table.insert(self.generals, general) table.insertIfNeed(self.generals, general)
end end
---@param card Card ---@param card Card

View File

@ -22,6 +22,7 @@
---@field player_cards table<integer, integer[]> ---@field player_cards table<integer, integer[]>
---@field special_cards table<string, integer[]> ---@field special_cards table<string, integer[]>
---@field cardUsedHistory table<string, integer> ---@field cardUsedHistory table<string, integer>
---@field fixedDistance table<Player, integer>
local Player = class("Player") local Player = class("Player")
---@alias Phase integer ---@alias Phase integer
@ -72,6 +73,7 @@ function Player:initialize()
self.special_cards = {} self.special_cards = {}
self.cardUsedHistory = {} self.cardUsedHistory = {}
self.fixedDistance = {}
end end
---@param general General ---@param general General
@ -226,6 +228,17 @@ function Player:getAttackRange()
return math.max(baseAttackRange, 0) return math.max(baseAttackRange, 0)
end 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 ---@param other Player
function Player:distanceTo(other) function Player:distanceTo(other)
assert(other:isInstanceOf(Player)) assert(other:isInstanceOf(Player))
@ -239,7 +252,17 @@ function Player:distanceTo(other)
end end
local left = #Fk:currentRoom().alive_players - right local left = #Fk:currentRoom().alive_players - right
local ret = math.min(left, 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) return math.max(ret, 1)
end end
@ -334,12 +357,21 @@ end
function Player:addSkill(skill, source_skill) function Player:addSkill(skill, source_skill)
skill = getActualSkill(skill) skill = getActualSkill(skill)
local toget = table.clone(skill.related_skills) local toget = {table.unpack(skill.related_skills)}
table.insert(toget, skill) table.insert(toget, skill)
local room = Fk:currentRoom()
local ret = {} local ret = {}
for _, s in ipairs(toget) do for _, s in ipairs(toget) do
if not self:hasSkill(s) then if not self:hasSkill(s) then
table.insert(ret, s) 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
end end

View File

@ -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

View File

@ -10,7 +10,7 @@ function fk.qlist(list)
end end
function table:contains(element) 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 for _, e in ipairs(self) do
if e == element then return true end if e == element then return true end
end end

View File

@ -4,6 +4,10 @@ dofile "lua/server/event.lua"
dofile "lua/server/system_enum.lua" dofile "lua/server/system_enum.lua"
TriggerSkill = require "core.skill_type.trigger" TriggerSkill = require "core.skill_type.trigger"
ActiveSkill = require "core.skill_type.active_skill" ActiveSkill = require "core.skill_type.active_skill"
DistanceSkill = require "core.skill_type.distance"
StatusSkills = {
DistanceSkill,
}
BasicCard = require "core.card_type.basic" BasicCard = require "core.card_type.basic"
local Trick = require "core.card_type.trick" local Trick = require "core.card_type.trick"
@ -107,6 +111,25 @@ function fk.CreateActiveSkill(spec)
return skill return skill
end 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 ---@class CardSpec: Card
---@field skill Skill ---@field skill Skill

View File

@ -135,7 +135,7 @@ function GameLogic:prepareForStart()
end end
for _, p in ipairs(room.alive_players) do for _, p in ipairs(room.alive_players) do
room:handleAddLoseSkills(p, "zhiheng", nil, false) room:handleAddLoseSkills(p, "zhiheng|mashu", nil, false)
end end
self:addTriggerSkill(GameRule) self:addTriggerSkill(GameRule)

View File

@ -12,6 +12,7 @@
---@field void integer[] ---@field void integer[]
---@field card_place table<integer, CardArea> ---@field card_place table<integer, CardArea>
---@field owner_map table<integer, integer> ---@field owner_map table<integer, integer>
---@field status_skills Skill[]
local Room = class("Room") local Room = class("Room")
-- load classes used by the game -- load classes used by the game
@ -71,6 +72,10 @@ function Room:initialize(_room)
self.void = {} self.void = {}
self.card_place = {} self.card_place = {}
self.owner_map = {} 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 end
-- When this function returns, the Room(C++) thread stopped. -- When this function returns, the Room(C++) thread stopped.

View File

@ -12,85 +12,81 @@ Fk:loadTranslationTable{
} }
local caocao = General:new(extension, "caocao", "wei", 4) local caocao = General:new(extension, "caocao", "wei", 4)
extension:addGeneral(caocao)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["caocao"] = "曹操", ["caocao"] = "曹操",
} }
local simayi = General:new(extension, "simayi", "wei", 3) local simayi = General:new(extension, "simayi", "wei", 3)
extension:addGeneral(simayi)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["simayi"] = "司马懿", ["simayi"] = "司马懿",
} }
local xiahoudun = General:new(extension, "xiahoudun", "wei", 4) local xiahoudun = General:new(extension, "xiahoudun", "wei", 4)
extension:addGeneral(xiahoudun)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["xiahoudun"] = "夏侯惇", ["xiahoudun"] = "夏侯惇",
} }
local zhangliao = General:new(extension, "zhangliao", "wei", 4) local zhangliao = General:new(extension, "zhangliao", "wei", 4)
extension:addGeneral(zhangliao)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhangliao"] = "张辽", ["zhangliao"] = "张辽",
} }
local xuchu = General:new(extension, "xuchu", "wei", 4) local xuchu = General:new(extension, "xuchu", "wei", 4)
extension:addGeneral(xuchu)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["xuchu"] = "许褚", ["xuchu"] = "许褚",
} }
local guojia = General:new(extension, "guojia", "wei", 3) local guojia = General:new(extension, "guojia", "wei", 3)
extension:addGeneral(guojia)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["guojia"] = "郭嘉", ["guojia"] = "郭嘉",
} }
local zhenji = General:new(extension, "zhenji", "wei", 3) local zhenji = General:new(extension, "zhenji", "wei", 3)
extension:addGeneral(zhenji)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhenji"] = "甄姬", ["zhenji"] = "甄姬",
} }
local liubei = General:new(extension, "liubei", "shu", 4) local liubei = General:new(extension, "liubei", "shu", 4)
extension:addGeneral(liubei)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["liubei"] = "刘备", ["liubei"] = "刘备",
} }
local guanyu = General:new(extension, "guanyu", "shu", 4) local guanyu = General:new(extension, "guanyu", "shu", 4)
extension:addGeneral(guanyu)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["guanyu"] = "关羽", ["guanyu"] = "关羽",
} }
local zhangfei = General:new(extension, "zhangfei", "shu", 4) local zhangfei = General:new(extension, "zhangfei", "shu", 4)
extension:addGeneral(zhangfei)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhangfei"] = "张飞", ["zhangfei"] = "张飞",
} }
local zhugeliang = General:new(extension, "zhugeliang", "shu", 3) local zhugeliang = General:new(extension, "zhugeliang", "shu", 3)
extension:addGeneral(zhugeliang)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhugeliang"] = "诸葛亮", ["zhugeliang"] = "诸葛亮",
} }
local zhaoyun = General:new(extension, "zhaoyun", "shu", 4) local zhaoyun = General:new(extension, "zhaoyun", "shu", 4)
extension:addGeneral(zhaoyun)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhaoyun"] = "赵云", ["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) local machao = General:new(extension, "machao", "shu", 4)
extension:addGeneral(machao) machao:addSkill(mashu)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["machao"] = "马超", ["machao"] = "马超",
["mashu"] = "马术",
} }
local huangyueying = General:new(extension, "huangyueying", "shu", 3) local huangyueying = General:new(extension, "huangyueying", "shu", 3)
extension:addGeneral(huangyueying)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["huangyueying"] = "黄月英", ["huangyueying"] = "黄月英",
} }
@ -108,68 +104,57 @@ local zhiheng = fk.CreateActiveSkill{
} }
local sunquan = General:new(extension, "sunquan", "wu", 4) local sunquan = General:new(extension, "sunquan", "wu", 4)
sunquan:addSkill(zhiheng) sunquan:addSkill(zhiheng)
extension:addGeneral(sunquan)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["sunquan"] = "孙权", ["sunquan"] = "孙权",
["zhiheng"] = "制衡", ["zhiheng"] = "制衡",
} }
local ganning = General:new(extension, "ganning", "wu", 4) local ganning = General:new(extension, "ganning", "wu", 4)
extension:addGeneral(ganning)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["ganning"] = "甘宁", ["ganning"] = "甘宁",
} }
local lvmeng = General:new(extension, "lvmeng", "wu", 4) local lvmeng = General:new(extension, "lvmeng", "wu", 4)
extension:addGeneral(lvmeng)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["lvmeng"] = "吕蒙", ["lvmeng"] = "吕蒙",
} }
local huanggai = General:new(extension, "huanggai", "wu", 4) local huanggai = General:new(extension, "huanggai", "wu", 4)
extension:addGeneral(huanggai)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["huanggai"] = "黄盖", ["huanggai"] = "黄盖",
} }
local zhouyu = General:new(extension, "zhouyu", "wu", 3) local zhouyu = General:new(extension, "zhouyu", "wu", 3)
extension:addGeneral(zhouyu)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["zhouyu"] = "周瑜", ["zhouyu"] = "周瑜",
} }
local daqiao = General:new(extension, "daqiao", "wu", 3) local daqiao = General:new(extension, "daqiao", "wu", 3)
extension:addGeneral(daqiao)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["daqiao"] = "大乔", ["daqiao"] = "大乔",
} }
local luxun = General:new(extension, "luxun", "wu", 3) local luxun = General:new(extension, "luxun", "wu", 3)
extension:addGeneral(luxun)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["luxun"] = "陆逊", ["luxun"] = "陆逊",
} }
local sunshangxiang = General:new(extension, "sunshangxiang", "wu", 3) local sunshangxiang = General:new(extension, "sunshangxiang", "wu", 3)
extension:addGeneral(sunshangxiang)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["sunshangxiang"] = "孙尚香", ["sunshangxiang"] = "孙尚香",
} }
local huatuo = General:new(extension, "huatuo", "qun", 3) local huatuo = General:new(extension, "huatuo", "qun", 3)
extension:addGeneral(huatuo)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["huatuo"] = "华佗", ["huatuo"] = "华佗",
} }
local lvbu = General:new(extension, "lvbu", "qun", 4) local lvbu = General:new(extension, "lvbu", "qun", 4)
extension:addGeneral(lvbu)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["lvbu"] = "吕布", ["lvbu"] = "吕布",
} }
local diaochan = General:new(extension, "diaochan", "qun", 3) local diaochan = General:new(extension, "diaochan", "qun", 3)
extension:addGeneral(diaochan)
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["diaochan"] = "貂蝉", ["diaochan"] = "貂蝉",
} }

View File

@ -862,6 +862,24 @@ extension:addCards({
niohShield, 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{ local diLu = fk.CreateDefensiveRide{
name = "dilu", name = "dilu",
suit = Card.Club, suit = Card.Club,

View File

@ -71,7 +71,7 @@ Flickable {
"GetSkillData", "GetSkillData",
[skill_name] [skill_name]
)); ));
if (data.freq = "active") { if (data.freq === "active") {
active_skills.append(data); active_skills.append(data);
} else { } else {
not_active_skills.append(data); not_active_skills.append(data);