Gamecore 2 (#16)
* upgrade gamecore * [Funtion] Room:moveCards() completed * add some functions in Room * fixup * delete wrong files
This commit is contained in:
parent
8b212c2a7a
commit
09e34cfef6
|
@ -6,6 +6,8 @@
|
||||||
---@field color Color
|
---@field color Color
|
||||||
---@field id integer
|
---@field id integer
|
||||||
---@field type CardType
|
---@field type CardType
|
||||||
|
---@field sub_type CardSubtype
|
||||||
|
---@field area CardArea
|
||||||
local Card = class("Card")
|
local Card = class("Card")
|
||||||
|
|
||||||
---@alias Suit integer
|
---@alias Suit integer
|
||||||
|
@ -29,6 +31,28 @@ Card.TypeBasic = 2
|
||||||
Card.TypeTrick = 3
|
Card.TypeTrick = 3
|
||||||
Card.TypeEquip = 4
|
Card.TypeEquip = 4
|
||||||
|
|
||||||
|
---@alias CardSubtype integer
|
||||||
|
|
||||||
|
Card.SubtypeNone = 1
|
||||||
|
Card.SubtypeDelayedTrick = 2
|
||||||
|
Card.SubtypeWeapon = 3
|
||||||
|
Card.SubtypeArmor = 4
|
||||||
|
Card.SubtypeDefensiveRide = 5
|
||||||
|
Card.SubtypeOffensiveRide = 6
|
||||||
|
Card.SubtypeTreasure = 7
|
||||||
|
|
||||||
|
---@alias CardArea integer
|
||||||
|
|
||||||
|
Card.Unknown = 0
|
||||||
|
Card.PlayerHand = 1
|
||||||
|
Card.PlayerEquip = 2
|
||||||
|
Card.PlayerJudge = 3
|
||||||
|
Card.PlayerSpecial = 4
|
||||||
|
Card.Processing = 5
|
||||||
|
Card.DrawPile = 6
|
||||||
|
Card.DiscardPile = 7
|
||||||
|
Card.Void = 8
|
||||||
|
|
||||||
function Card:initialize(name, suit, number, color)
|
function Card:initialize(name, suit, number, color)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.suit = suit or Card.NoSuit
|
self.suit = suit or Card.NoSuit
|
||||||
|
@ -47,6 +71,7 @@ function Card:initialize(name, suit, number, color)
|
||||||
self.package = nil
|
self.package = nil
|
||||||
self.id = 0
|
self.id = 0
|
||||||
self.type = 0
|
self.type = 0
|
||||||
|
self.sub_type = Card.SubTypeNone
|
||||||
end
|
end
|
||||||
|
|
||||||
return Card
|
return Card
|
||||||
|
|
|
@ -6,4 +6,12 @@ function BasicCard:initialize(name, suit, number)
|
||||||
self.type = Card.TypeBasic
|
self.type = Card.TypeBasic
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return BasicCard
|
||||||
|
function BasicCard:clone(suit, number)
|
||||||
|
local newCard = BasicCard:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
return BasicCard
|
return BasicCard
|
||||||
|
|
|
@ -6,4 +6,85 @@ function EquipCard:initialize(name, suit, number)
|
||||||
self.type = Card.TypeEquip
|
self.type = Card.TypeEquip
|
||||||
end
|
end
|
||||||
|
|
||||||
return EquipCard
|
---@class Weapon : EquipCard
|
||||||
|
local Weapon = EquipCard:subclass("Weapon")
|
||||||
|
|
||||||
|
function Weapon:initialize(name, suit, number, attackRange)
|
||||||
|
EquipCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeWeapon
|
||||||
|
self.attack_range = attackRange or 1
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return Weapon
|
||||||
|
function Weapon:clone(suit, number)
|
||||||
|
local newCard = Weapon:new(self.name, suit, number, self.attack_range)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class Armor : EquipCard
|
||||||
|
local Armor = EquipCard:subclass("armor")
|
||||||
|
|
||||||
|
function Armor:initialize(name, suit, number)
|
||||||
|
EquipCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeArmor
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return Armor
|
||||||
|
function Armor:clone(suit, number)
|
||||||
|
local newCard = Armor:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class DefensiveRide : EquipCard
|
||||||
|
local DefensiveRide = EquipCard:subclass("DefensiveRide")
|
||||||
|
|
||||||
|
function DefensiveRide:initialize(name, suit, number)
|
||||||
|
EquipCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeDefensiveRide
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return DefensiveRide
|
||||||
|
function DefensiveRide:clone(suit, number)
|
||||||
|
local newCard = DefensiveRide:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class OffensiveRide : EquipCard
|
||||||
|
local OffensiveRide = EquipCard:subclass("OffensiveRide")
|
||||||
|
|
||||||
|
function OffensiveRide:initialize(name, suit, number)
|
||||||
|
EquipCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeOffensiveRide
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return OffensiveRide
|
||||||
|
function OffensiveRide:clone(suit, number)
|
||||||
|
local newCard = OffensiveRide:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class Treasure : EquipCard
|
||||||
|
local Treasure = EquipCard:subclass("Treasure")
|
||||||
|
|
||||||
|
function Treasure:initialize(name, suit, number)
|
||||||
|
EquipCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeTreasure
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return Treasure
|
||||||
|
function Treasure:clone(suit, number)
|
||||||
|
local newCard = Treasure:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
return { EquipCard, Weapon, Armor, DefensiveRide, OffensiveRide, Treasure }
|
||||||
|
|
|
@ -6,4 +6,28 @@ function TrickCard:initialize(name, suit, number)
|
||||||
self.type = Card.TypeTrick
|
self.type = Card.TypeTrick
|
||||||
end
|
end
|
||||||
|
|
||||||
return TrickCard
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return TrickCard
|
||||||
|
function TrickCard:clone(suit, number)
|
||||||
|
local newCard = TrickCard:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class DelayedTrickCard : TrickCard
|
||||||
|
local DelayedTrickCard = TrickCard:subclass("DelayedTrickCard")
|
||||||
|
|
||||||
|
function DelayedTrickCard:initialize(name, suit, number)
|
||||||
|
TrickCard.initialize(self, name, suit, number)
|
||||||
|
self.sub_type = Card.SubtypeDelayedTrick
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param suit Suit
|
||||||
|
---@param number integer
|
||||||
|
---@return DelayedTrickCard
|
||||||
|
function DelayedTrickCard:clone(suit, number)
|
||||||
|
local newCard = DelayedTrickCard:new(self.name, suit, number)
|
||||||
|
return newCard
|
||||||
|
end
|
||||||
|
|
||||||
|
return { TrickCard, DelayedTrickCard }
|
||||||
|
|
|
@ -164,4 +164,23 @@ function Engine:getAllGenerals(except)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param except integer[]
|
||||||
|
---@return integer[]
|
||||||
|
function Engine:getAllCardIds(except)
|
||||||
|
local result = {}
|
||||||
|
for _, card in ipairs(self.cards) do
|
||||||
|
if not (except and table.contains(except, card.id)) then
|
||||||
|
table.insert(result, card.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param id integer
|
||||||
|
---@return Card
|
||||||
|
function Engine:getCardById(id)
|
||||||
|
return self.cards[id]
|
||||||
|
end
|
||||||
|
|
||||||
return Engine
|
return Engine
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
---@field flag string[]
|
---@field flag string[]
|
||||||
---@field tag table<string, any>
|
---@field tag table<string, any>
|
||||||
---@field mark table<string, integer>
|
---@field mark table<string, integer>
|
||||||
|
---@field player_cards table<integer, integer[]>
|
||||||
|
---@field special_cards table<string, integer[]>
|
||||||
local Player = class("Player")
|
local Player = class("Player")
|
||||||
|
|
||||||
---@alias Phase integer
|
---@alias Phase integer
|
||||||
|
@ -31,6 +33,13 @@ Player.Finish = 7
|
||||||
Player.NotActive = 8
|
Player.NotActive = 8
|
||||||
Player.PhaseNone = 9
|
Player.PhaseNone = 9
|
||||||
|
|
||||||
|
---@alias PlayerCardArea integer
|
||||||
|
|
||||||
|
Player.Hand = 1
|
||||||
|
Player.Equip = 2
|
||||||
|
Player.Judge = 3
|
||||||
|
Player.Special = 4
|
||||||
|
|
||||||
function Player:initialize()
|
function Player:initialize()
|
||||||
self.id = 114514
|
self.id = 114514
|
||||||
self.hp = 0
|
self.hp = 0
|
||||||
|
@ -38,7 +47,6 @@ function Player:initialize()
|
||||||
self.kingdom = "qun"
|
self.kingdom = "qun"
|
||||||
self.role = ""
|
self.role = ""
|
||||||
self.general = ""
|
self.general = ""
|
||||||
self.handcard_num = 0
|
|
||||||
self.seat = 0
|
self.seat = 0
|
||||||
self.phase = Player.PhaseNone
|
self.phase = Player.PhaseNone
|
||||||
self.faceup = true
|
self.faceup = true
|
||||||
|
@ -51,6 +59,12 @@ function Player:initialize()
|
||||||
self.flag = {}
|
self.flag = {}
|
||||||
self.tag = {}
|
self.tag = {}
|
||||||
self.mark = {}
|
self.mark = {}
|
||||||
|
self.player_cards = {
|
||||||
|
[Player.Hand] = {},
|
||||||
|
[Player.Equip] = {},
|
||||||
|
[Player.Judge] = {},
|
||||||
|
}
|
||||||
|
self.special_cards = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param general General
|
---@param general General
|
||||||
|
@ -125,4 +139,86 @@ function Player:getMarkNames()
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param playerArea PlayerCardArea
|
||||||
|
---@param cardIds integer[]
|
||||||
|
---@param specialName string
|
||||||
|
function Player:addCards(playerArea, cardIds, specialName)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param playerArea PlayerCardArea
|
||||||
|
---@param cardIds integer[]
|
||||||
|
---@param specialName string
|
||||||
|
function Player:removeCards(playerArea, cardIds, specialName)
|
||||||
|
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
|
||||||
|
|
||||||
|
table.removeOne(fromAreaIds, id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param playerAreas PlayerCardArea
|
||||||
|
---@param specialName string
|
||||||
|
---@return integer[]
|
||||||
|
function Player:getCardIds(playerAreas, specialName)
|
||||||
|
local rightAreas = { Player.Hand, Player.Equip, Player.Judge }
|
||||||
|
playerAreas = playerAreas or rightAreas
|
||||||
|
assert(type(playerAreas) == "number" or type(playerAreas) == "table")
|
||||||
|
local areas = type(playerAreas) == "table" and playerAreas or { playerAreas }
|
||||||
|
|
||||||
|
local rightAreas = { Player.Hand, Player.Equip, Player.Judge, Player.Special }
|
||||||
|
local cardIds = {}
|
||||||
|
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
|
||||||
|
|
||||||
|
function Player:getMaxCards()
|
||||||
|
local baseValue = math.max(self.hp, 0)
|
||||||
|
|
||||||
|
return baseValue
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param subtype CardSubtype
|
||||||
|
---@return integer|null
|
||||||
|
function Player:getEquipBySubtype(subtype)
|
||||||
|
local equipId = nil
|
||||||
|
for _, id in ipairs(self.player_cards[Player.Equip]) do
|
||||||
|
if Fk.getCardById(id).sub_type == subtype then
|
||||||
|
equipId = id
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return equipId
|
||||||
|
end
|
||||||
|
|
||||||
|
function Player:getAttackRange()
|
||||||
|
local weapon = Fk.getCardById(self:getEquipBySubtype(Card.SubtypeWeapon))
|
||||||
|
local baseAttackRange = math.max(weapon and weapon.attack_range or 1, 0)
|
||||||
|
|
||||||
|
return math.max(baseAttackRange, 0)
|
||||||
|
end
|
||||||
|
|
||||||
return Player
|
return Player
|
||||||
|
|
105
lua/fk_ex.lua
105
lua/fk_ex.lua
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
SkillCard = require "core.card_type.skill"
|
SkillCard = require "core.card_type.skill"
|
||||||
BasicCard = require "core.card_type.basic"
|
BasicCard = require "core.card_type.basic"
|
||||||
TrickCard = require "core.card_type.trick"
|
local Trick = require "core.card_type.trick"
|
||||||
EquipCard = require "core.card_type.equip"
|
TrickCard, DelayedTrickCard = table.unpack(Trick)
|
||||||
|
local Equip = require "core.card_type.equip"
|
||||||
|
_, Weapon, Armor, DefensiveRide, OffensiveRide, Treasure = table.unpack(Equip)
|
||||||
|
|
||||||
dofile "lua/server/event.lua"
|
dofile "lua/server/event.lua"
|
||||||
|
dofile "lua/server/system_enum.lua"
|
||||||
TriggerSkill = require "core.skill_type.trigger"
|
TriggerSkill = require "core.skill_type.trigger"
|
||||||
|
|
||||||
---@class CardSpec: Card
|
---@class CardSpec: Card
|
||||||
|
@ -27,10 +30,10 @@ TriggerSkill = require "core.skill_type.trigger"
|
||||||
---@return BasicCard
|
---@return BasicCard
|
||||||
function fk.CreateBasicCard(spec)
|
function fk.CreateBasicCard(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
if not spec.name then spec.name = spec.class_name
|
if not spec.name then spec.name = spec.class_name
|
||||||
elseif not spec.class_name then spec.class_name = spec.name end
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
if spec.suit then assert(type(spec.suit) == "number") end
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
if spec.number then assert(type(spec.number) == "number") end
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
local card = BasicCard:new(spec.name, spec.suit, spec.number)
|
local card = BasicCard:new(spec.name, spec.suit, spec.number)
|
||||||
return card
|
return card
|
||||||
|
@ -40,25 +43,91 @@ end
|
||||||
---@return TrickCard
|
---@return TrickCard
|
||||||
function fk.CreateTrickCard(spec)
|
function fk.CreateTrickCard(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
if not spec.name then spec.name = spec.class_name
|
if not spec.name then spec.name = spec.class_name
|
||||||
elseif not spec.class_name then spec.class_name = spec.name end
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
if spec.suit then assert(type(spec.suit) == "number") end
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
if spec.number then assert(type(spec.number) == "number") end
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
local card = TrickCard:new(spec.name, spec.suit, spec.number)
|
local card = TrickCard:new(spec.name, spec.suit, spec.number)
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return EquipCard
|
---@return DelayedTrickCard
|
||||||
function fk.CreateEquipCard(spec)
|
function fk.CreateDelayedTrickCard(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
if not spec.name then spec.name = spec.class_name
|
if not spec.name then spec.name = spec.class_name
|
||||||
elseif not spec.class_name then spec.class_name = spec.name end
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
if spec.suit then assert(type(spec.suit) == "number") end
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
if spec.number then assert(type(spec.number) == "number") end
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
local card = EquipCard:new(spec.name, spec.suit, spec.number)
|
local card = DelayedTrickCard:new(spec.name, spec.suit, spec.number)
|
||||||
|
return card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return Weapon
|
||||||
|
function fk.CreateWeapon(spec)
|
||||||
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
if spec.attack_range then assert(type(spec.attack_range) == "number" and spec.attack_range >= 0) end
|
||||||
|
|
||||||
|
local card = Weapon:new(spec.name, spec.suit, spec.number, spec.attack_range)
|
||||||
|
return card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return Armor
|
||||||
|
function fk.CreateArmor(spec)
|
||||||
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
|
local card = Armor:new(spec.name, spec.suit, spec.number)
|
||||||
|
return card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return DefensiveRide
|
||||||
|
function fk.CreateDefensiveRide(spec)
|
||||||
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
|
local card = DefensiveRide:new(spec.name, spec.suit, spec.number)
|
||||||
|
return card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return OffensiveRide
|
||||||
|
function fk.CreateOffensiveRide(spec)
|
||||||
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
|
local card = OffensiveRide:new(spec.name, spec.suit, spec.number)
|
||||||
|
return card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return Treasure
|
||||||
|
function fk.CreateTreasure(spec)
|
||||||
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
elseif not spec.class_name then spec.class_name = spec.name end
|
||||||
|
if spec.suit then assert(type(spec.suit) == "number") end
|
||||||
|
if spec.number then assert(type(spec.number) == "number") end
|
||||||
|
|
||||||
|
local card = Treasure:new(spec.name, spec.suit, spec.number)
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,30 +9,45 @@ fk.EventPhaseEnd = 6
|
||||||
fk.EventPhaseChanging = 7
|
fk.EventPhaseChanging = 7
|
||||||
fk.EventPhaseSkipping = 8
|
fk.EventPhaseSkipping = 8
|
||||||
|
|
||||||
fk.DrawNCards = 9
|
fk.BeforeCardsMove = 9
|
||||||
fk.AfterDrawNCards = 10
|
fk.AfterCardsMove = 10
|
||||||
fk.DrawInitialCards = 11
|
|
||||||
fk.AfterDrawInitialCards = 12
|
|
||||||
|
|
||||||
fk.PreHpRecover = 13
|
fk.DrawNCards = 11
|
||||||
fk.HpRecover = 14
|
fk.AfterDrawNCards = 12
|
||||||
fk.PreHpLost = 15
|
fk.DrawInitialCards = 13
|
||||||
fk.HpLost = 16
|
fk.AfterDrawInitialCards = 14
|
||||||
fk.HpChanged = 17
|
|
||||||
fk.MaxHpChanged = 18
|
|
||||||
|
|
||||||
fk.EventLoseSkill = 19
|
fk.PreHpRecover = 15
|
||||||
fk.EventAcquireSkill = 20
|
fk.HpRecover = 16
|
||||||
|
fk.PreHpLost = 17
|
||||||
|
fk.HpLost = 18
|
||||||
|
fk.BeforeHpChanged = 19
|
||||||
|
fk.HpChanged = 20
|
||||||
|
fk.MaxHpChanged = 21
|
||||||
|
|
||||||
fk.StartJudge = 21
|
fk.EventLoseSkill = 22
|
||||||
fk.AskForRetrial = 22
|
fk.EventAcquireSkill = 23
|
||||||
fk.FinishRetrial = 23
|
|
||||||
fk.FinishJudge = 24
|
|
||||||
|
|
||||||
fk.PindianVerifying = 25
|
fk.StartJudge = 24
|
||||||
fk.Pindian = 26
|
fk.AskForRetrial = 25
|
||||||
|
fk.FinishRetrial = 26
|
||||||
|
fk.FinishJudge = 27
|
||||||
|
|
||||||
fk.TurnedOver = 27
|
fk.PindianVerifying = 28
|
||||||
fk.ChainStateChanged = 28
|
fk.Pindian = 29
|
||||||
|
|
||||||
fk.NumOfEvents = 29
|
fk.TurnedOver = 30
|
||||||
|
fk.ChainStateChanged = 31
|
||||||
|
|
||||||
|
fk.PreDamage = 32
|
||||||
|
fk.DamageCaused = 33
|
||||||
|
fk.DamageInflicted = 34
|
||||||
|
fk.Damage = 35
|
||||||
|
fk.Damaged = 36
|
||||||
|
fk.DamageFinished = 37
|
||||||
|
|
||||||
|
fk.EnterDying = 38
|
||||||
|
fk.Dying = 39
|
||||||
|
fk.AfterDying = 40
|
||||||
|
|
||||||
|
fk.NumOfEvents = 41
|
||||||
|
|
|
@ -64,7 +64,7 @@ function GameLogic:chooseGenerals()
|
||||||
local lord = room:getLord()
|
local lord = room:getLord()
|
||||||
local lord_general = nil
|
local lord_general = nil
|
||||||
if lord ~= nil then
|
if lord ~= nil then
|
||||||
room.current = lord
|
room.current = lord
|
||||||
local generals = Fk:getGeneralsRandomly(3)
|
local generals = Fk:getGeneralsRandomly(3)
|
||||||
for i = 1, #generals do
|
for i = 1, #generals do
|
||||||
generals[i] = generals[i].name
|
generals[i] = generals[i].name
|
||||||
|
@ -129,6 +129,12 @@ function GameLogic:prepareForStart()
|
||||||
|
|
||||||
-- TODO: prepare drawPile
|
-- TODO: prepare drawPile
|
||||||
-- TODO: init cards in drawPile
|
-- TODO: init cards in drawPile
|
||||||
|
local allCardIds = Fk:getAllCardIds()
|
||||||
|
table.shuffle(allCardIds)
|
||||||
|
room.draw_pile = allCardIds
|
||||||
|
for _, id in ipairs(room.draw_pile) do
|
||||||
|
self.room:setCardArea(id, Card.DrawPile)
|
||||||
|
end
|
||||||
|
|
||||||
self:addTriggerSkill(GameRule)
|
self:addTriggerSkill(GameRule)
|
||||||
for _, trig in ipairs(Fk.global_trigger) do
|
for _, trig in ipairs(Fk.global_trigger) do
|
||||||
|
@ -139,6 +145,11 @@ end
|
||||||
function GameLogic:action()
|
function GameLogic:action()
|
||||||
self:trigger(fk.GameStart)
|
self:trigger(fk.GameStart)
|
||||||
local room = self.room
|
local room = self.room
|
||||||
|
|
||||||
|
for _, p in ipairs(room.players) do
|
||||||
|
self:trigger(fk.DrawInitialCards, p, { num = 4 })
|
||||||
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
self:trigger(fk.TurnStart, room.current)
|
self:trigger(fk.TurnStart, room.current)
|
||||||
if room.game_finished then break end
|
if room.game_finished then break end
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
---@field game_finished boolean
|
---@field game_finished boolean
|
||||||
---@field timeout integer
|
---@field timeout integer
|
||||||
---@field tag table<string, any>
|
---@field tag table<string, any>
|
||||||
|
---@field draw_pile integer[]
|
||||||
|
---@field discard_pile integer[]
|
||||||
|
---@field processing_area integer[]
|
||||||
|
---@field void integer[]
|
||||||
|
---@field card_place table<integer, CardArea>
|
||||||
local Room = class("Room")
|
local Room = class("Room")
|
||||||
|
|
||||||
-- load classes used by the game
|
-- load classes used by the game
|
||||||
|
@ -36,6 +41,11 @@ function Room:initialize(_room)
|
||||||
self.game_finished = false
|
self.game_finished = false
|
||||||
self.timeout = _room:getTimeout()
|
self.timeout = _room:getTimeout()
|
||||||
self.tag = {}
|
self.tag = {}
|
||||||
|
self.draw_pile = {}
|
||||||
|
self.discard_pile = {}
|
||||||
|
self.processing_area = {}
|
||||||
|
self.void = {}
|
||||||
|
self.card_place = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- When this function returns, the Room(C++) thread stopped.
|
-- When this function returns, the Room(C++) thread stopped.
|
||||||
|
@ -161,7 +171,244 @@ function Room:adjustSeats()
|
||||||
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return ServerPlayer | nil
|
function Room:shuffleDrawPile()
|
||||||
|
if #self.draw_pile + #self.discard_pile == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insertTable(self.draw_pile, self.discard_pile)
|
||||||
|
for _, id in ipairs(self.discard_pile) do
|
||||||
|
self:setCardArea(id, Card.DrawPile)
|
||||||
|
end
|
||||||
|
self.discard_pile = {}
|
||||||
|
table.shuffle(self.draw_pile)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param num integer
|
||||||
|
---@param from string
|
||||||
|
---@return integer[]
|
||||||
|
function Room:getNCards(num, from)
|
||||||
|
from = from or "top"
|
||||||
|
assert(from == "top" or from == "bottom")
|
||||||
|
|
||||||
|
local cardIds = {}
|
||||||
|
while num > 0 do
|
||||||
|
if #self.draw_pile < 1 then
|
||||||
|
self:shuffleDrawPile()
|
||||||
|
end
|
||||||
|
|
||||||
|
local index = from == "top" and 1 or #self.draw_pile
|
||||||
|
table.insert(cardIds, self.draw_pile[index])
|
||||||
|
table.remove(self.draw_pile, index)
|
||||||
|
|
||||||
|
num = num - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return cardIds
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param cardId integer
|
||||||
|
---@param cardArea CardArea
|
||||||
|
function Room:setCardArea(cardId, cardArea)
|
||||||
|
self.card_place[cardId] = cardArea
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param cardId integer
|
||||||
|
---@return CardArea
|
||||||
|
function Room:getCardArea(cardId)
|
||||||
|
return self.card_place[cardId] or Card.Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
---@vararg CardsMoveInfo
|
||||||
|
---@return boolean
|
||||||
|
function Room:moveCards(...)
|
||||||
|
---@type CardsMoveStruct[]
|
||||||
|
local cardsMoveStructs = {}
|
||||||
|
local infoCheck = function(info)
|
||||||
|
assert(table.contains({ Card.PlayerHand, Card.PlayerEquip, Card.PlayerJudge, Card.PlayerSpecial, Card.Processing, Card.DrawPile, Card.DiscardPile, Card.Void }, info.toArea))
|
||||||
|
assert(info.toArea ~= Card.PlayerSpecial or type(info.specialName) == "string")
|
||||||
|
assert(type(info.moveReason) == "number")
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, cardsMoveInfo in ipairs({...}) do
|
||||||
|
if #cardsMoveInfo.ids > 0 then
|
||||||
|
infoCheck(cardsMoveInfo)
|
||||||
|
|
||||||
|
---@type MoveInfo[]
|
||||||
|
local infos = {}
|
||||||
|
for _, id in ipairs(cardsMoveInfo.ids) do
|
||||||
|
table.insert(infos, { cardId = id, fromArea = self:getCardArea(id) })
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type CardsMoveStruct
|
||||||
|
local cardsMoveStruct = {
|
||||||
|
moveInfo = infos,
|
||||||
|
from = cardsMoveInfo.from,
|
||||||
|
to = cardsMoveInfo.to,
|
||||||
|
toArea = cardsMoveInfo.toArea,
|
||||||
|
moveReason = cardsMoveInfo.moveReason,
|
||||||
|
proposer = cardsMoveInfo.proposer,
|
||||||
|
skillName = cardsMoveInfo.skillName,
|
||||||
|
moveVisible = cardsMoveInfo.moveVisible,
|
||||||
|
specialName = cardsMoveInfo.specialName,
|
||||||
|
specialVisible = cardsMoveInfo.specialVisible,
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(cardsMoveStructs, cardsMoveStruct)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #cardsMoveStructs < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.logic:trigger(fk.BeforeCardsMove, nil, cardsMoveStructs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, data in ipairs(cardsMoveStructs) do
|
||||||
|
if #data.moveInfo > 0 then
|
||||||
|
infoCheck(data)
|
||||||
|
|
||||||
|
---@param info MoveInfo
|
||||||
|
for _, info in ipairs(data.moveInfo) do
|
||||||
|
local realFromArea = self:getCardArea(info.cardId)
|
||||||
|
local playerAreas = { Player.Hand, Player.Equip, Player.Judge, Player.Special }
|
||||||
|
|
||||||
|
if table.contains(playerAreas, realFromArea) and data.from then
|
||||||
|
self:getPlayerById(data.from):removeCards(realFromArea, { info.cardId }, data.specialName)
|
||||||
|
elseif realFromArea ~= Card.Unknown then
|
||||||
|
local fromAreaIds = {}
|
||||||
|
if realFromArea == Card.Processing then
|
||||||
|
fromAreaIds = self.processing_area
|
||||||
|
elseif realFromArea == Card.DrawPile then
|
||||||
|
fromAreaIds = self.draw_pile
|
||||||
|
elseif realFromArea == Card.DiscardPile then
|
||||||
|
fromAreaIds = self.discard_pile
|
||||||
|
elseif realFromArea == Card.Void then
|
||||||
|
fromAreaIds = self.void
|
||||||
|
end
|
||||||
|
|
||||||
|
table.removeOne(fromAreaIds, info.cardId)
|
||||||
|
end
|
||||||
|
|
||||||
|
if table.contains(playerAreas, data.toArea) and data.to then
|
||||||
|
self:getPlayerById(data.to):addCards(data.toArea, { info.cardId }, data.specialName)
|
||||||
|
else
|
||||||
|
local toAreaIds = {}
|
||||||
|
if data.toArea == Card.Processing then
|
||||||
|
toAreaIds = self.processing_area
|
||||||
|
elseif data.toArea == Card.DrawPile then
|
||||||
|
toAreaIds = self.draw_pile
|
||||||
|
elseif data.toArea == Card.DiscardPile then
|
||||||
|
toAreaIds = self.discard_pile
|
||||||
|
elseif data.toArea == Card.Void then
|
||||||
|
toAreaIds = self.void
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(toAreaIds, toAreaIds == Card.DrawPile and 1 or #toAreaIds + 1, info.cardId)
|
||||||
|
end
|
||||||
|
self:setCardArea(info.cardId, data.toArea)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.logic:trigger(fk.AfterCardsMove, nil, cardsMoveStructs)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param num integer
|
||||||
|
---@param skillName string
|
||||||
|
---@param fromPlace "top"|"bottom"
|
||||||
|
---@return integer[]
|
||||||
|
function Room:drawCards(player, num, skillName, fromPlace)
|
||||||
|
local topCards = self:getNCards(num, fromPlace)
|
||||||
|
self:moveCards({
|
||||||
|
ids = topCards,
|
||||||
|
to = player:getId(),
|
||||||
|
toArea = Card.PlayerHand,
|
||||||
|
moveReason = fk.ReasonDraw,
|
||||||
|
proposer = player:getId(),
|
||||||
|
skillName = skillName,
|
||||||
|
})
|
||||||
|
|
||||||
|
return { table.unpack(topCards) }
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param minNum integer
|
||||||
|
---@param maxNum integer
|
||||||
|
---@param includeEquip boolean
|
||||||
|
---@param skillName string
|
||||||
|
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName)
|
||||||
|
if minNum < 1 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local hands = player:getCardIds(Player.Hand)
|
||||||
|
local toDiscard = {}
|
||||||
|
for i = 1, minNum do
|
||||||
|
local randomId = hands[math.random(1, #hands)]
|
||||||
|
table.insert(toDiscard, randomId)
|
||||||
|
table.removeOne(hands, randomId)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:moveCards({
|
||||||
|
ids = toDiscard,
|
||||||
|
from = player:getId(),
|
||||||
|
toArea = Card.DiscardPile,
|
||||||
|
moveReason = fk.ReasonDiscard,
|
||||||
|
proposer = player:getId(),
|
||||||
|
skillName = skillName
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param id integer
|
||||||
|
---@return ServerPlayer
|
||||||
|
function Room:getPlayerById(id)
|
||||||
|
assert(type(id) == "number")
|
||||||
|
|
||||||
|
for _, p in ipairs(self.players) do
|
||||||
|
if p:getId() == id then
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error("cannot find player by " .. id)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param sortBySeat boolean
|
||||||
|
---@return ServerPlayer[]
|
||||||
|
function Room:getAlivePlayers(sortBySeat)
|
||||||
|
sortBySeat = sortBySeat or true
|
||||||
|
|
||||||
|
local alivePlayers = {}
|
||||||
|
for _, player in ipairs(self.players) do
|
||||||
|
if player:isAlive() then
|
||||||
|
table.insert(alivePlayers, player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return alivePlayers
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param sortBySeat boolean
|
||||||
|
---@return ServerPlayer[]
|
||||||
|
function Room:getOtherPlayers(player, sortBySeat)
|
||||||
|
local alivePlayers = self:getAlivePlayers(sortBySeat)
|
||||||
|
for _, p in ipairs(alivePlayers) do
|
||||||
|
if p:getId() == player:getId() then
|
||||||
|
table.removeOne(alivePlayers, player)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return alivePlayers
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return ServerPlayer | null
|
||||||
function Room:getLord()
|
function Room:getLord()
|
||||||
local lord = self.players[1]
|
local lord = self.players[1]
|
||||||
if lord.role == "lord" then return lord end
|
if lord.role == "lord" then return lord end
|
||||||
|
@ -210,16 +457,6 @@ function Room:gameOver()
|
||||||
self.room:gameOver()
|
self.room:gameOver()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param id integer
|
|
||||||
function Room:findPlayerById(id)
|
|
||||||
for _, p in ipairs(self.players) do
|
|
||||||
if p:getId() == id then
|
|
||||||
return p
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param player ServerPlayer
|
---@param player ServerPlayer
|
||||||
---@param choices string[]
|
---@param choices string[]
|
||||||
---@param skill_name string
|
---@param skill_name string
|
||||||
|
@ -246,6 +483,203 @@ function Room:askForSkillInvoke(player, skill_name, data)
|
||||||
return invoked
|
return invoked
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param num integer
|
||||||
|
---@param reason "loseHp"|"damage"|"recover"|null
|
||||||
|
---@param skillName string
|
||||||
|
---@param damageStruct DamageStruct|null
|
||||||
|
---@return boolean
|
||||||
|
function Room:changeHp(player, num, reason, skillName, damageStruct)
|
||||||
|
if num == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
assert(reason == nil or table.contains({ "loseHp", "damage", "recover" }, reason))
|
||||||
|
|
||||||
|
---@type HpChangedData
|
||||||
|
local data = {
|
||||||
|
num = num,
|
||||||
|
reason = reason,
|
||||||
|
skillName = skillName,
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.logic:trigger(fk.BeforeHpChanged, player, data) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(not (data.reason == "recover" and data.num < 0))
|
||||||
|
player.hp = math.min(player.hp + data.num, player.maxHp)
|
||||||
|
|
||||||
|
self.logic:trigger(fk.HpChanged, player, data)
|
||||||
|
|
||||||
|
if player.hp < 1 then
|
||||||
|
---@type DyingStruct
|
||||||
|
local dyingStruct = {
|
||||||
|
who = player:getId(),
|
||||||
|
damage = damageStruct,
|
||||||
|
}
|
||||||
|
self:enterDying(dyingStruct)
|
||||||
|
elseif player.dying then
|
||||||
|
player.dying = false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param num integer
|
||||||
|
---@param skillName string
|
||||||
|
---@return boolean
|
||||||
|
function Room:loseHp(player, num, skillName)
|
||||||
|
if num == nil then
|
||||||
|
num = 1
|
||||||
|
elseif num < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type HpLostData
|
||||||
|
local data = {
|
||||||
|
num = num,
|
||||||
|
skillName = skillName,
|
||||||
|
}
|
||||||
|
if self.logic:trigger(fk.PreHpLost, player, data) or data.num < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self:changeHp(player, -num, "loseHp", skillName) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
self.logic:trigger(fk.HpLost, player, data)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param num integer
|
||||||
|
---@return boolean
|
||||||
|
function Room:changeMaxHp(player, num)
|
||||||
|
if num == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
player.maxHp = math.max(player.maxHp + num, 0)
|
||||||
|
local diff = player.hp - player.maxHp
|
||||||
|
if diff > 0 then
|
||||||
|
if not self:changeHp(player, -diff) then
|
||||||
|
player.hp = player.hp - diff
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if player.maxHp == 0 then
|
||||||
|
self:killPlayer({ who = player:getId() })
|
||||||
|
end
|
||||||
|
|
||||||
|
self.logic:trigger(fk.MaxHpChanged, player, { num = num })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param damageStruct DamageStruct
|
||||||
|
---@return boolean
|
||||||
|
function Room:damage(damageStruct)
|
||||||
|
if damageStruct.damage < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(type(damageStruct.to) == "number")
|
||||||
|
|
||||||
|
local stages = {
|
||||||
|
[fk.PreDamage] = damageStruct.from,
|
||||||
|
[fk.DamageCaused] = damageStruct.from,
|
||||||
|
[fk.DamageInflicted] = damageStruct.to,
|
||||||
|
}
|
||||||
|
|
||||||
|
for event, playerId in ipairs(stages) do
|
||||||
|
local player = playerId and self:getPlayerById(playerId) or nil
|
||||||
|
if self.logic:trigger(event, player, damageStruct) or damageStruct.damage < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(type(damageStruct.to) == "number")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(self:getPlayerById(damageStruct.to))
|
||||||
|
local victim = self:getPlayerById(damageStruct.to)
|
||||||
|
if not victim:isAlive() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self:changeHp(victim, -damageStruct.damage, "damage", damageStruct.skillName, damageStruct) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
stages = {
|
||||||
|
[fk.Damage] = damageStruct.from,
|
||||||
|
[fk.Damaged] = damageStruct.to,
|
||||||
|
[fk.DamageFinished] = damageStruct.from,
|
||||||
|
}
|
||||||
|
|
||||||
|
for event, playerId in ipairs(stages) do
|
||||||
|
local player = playerId and self:getPlayerById(playerId) or nil
|
||||||
|
self.logic:trigger(event, player, damageStruct)
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param recoverStruct RecoverStruct
|
||||||
|
---@return boolean
|
||||||
|
function Room:recover(recoverStruct)
|
||||||
|
if recoverStruct.num < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local who = self:getPlayerById(recoverStruct.who)
|
||||||
|
if self.logic:trigger(fk.PreHpRecover, who, recoverStruct) or recoverStruct.num < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self:changeHp(who, recoverStruct.num, "recover", recoverStruct.skillName) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
self.logic:trigger(fk.HpRecover, who, recoverStruct)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param dyingStruct DyingStruct
|
||||||
|
function Room:enterDying(dyingStruct)
|
||||||
|
local dyingPlayer = self:getPlayerById(dyingStruct.who)
|
||||||
|
dyingPlayer.dying = true
|
||||||
|
self.logic:trigger(fk.EnterDying, dyingPlayer, dyingStruct)
|
||||||
|
|
||||||
|
if dyingPlayer.hp < 1 then
|
||||||
|
local alivePlayers = self:getAlivePlayers()
|
||||||
|
for _, player in ipairs(alivePlayers) do
|
||||||
|
self.logic:trigger(fk.Dying, player, dyingStruct)
|
||||||
|
|
||||||
|
if player.hp > 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if dyingPlayer.hp < 1 then
|
||||||
|
---@type DeathStruct
|
||||||
|
local deathData = {
|
||||||
|
who = dyingPlayer:getId(),
|
||||||
|
damage = dyingStruct.damage,
|
||||||
|
}
|
||||||
|
self:killPlayer(deathData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.logic:trigger(fk.AfterDying, dyingPlayer, dyingStruct)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param deathStruct DeathStruct
|
||||||
|
function Room:killPlayer(deathStruct)
|
||||||
|
print(self:getPlayerById(deathStruct.who).general .. " is dead")
|
||||||
|
self:gameOver()
|
||||||
|
end
|
||||||
|
|
||||||
fk.room_callback["QuitRoom"] = function(jsonData)
|
fk.room_callback["QuitRoom"] = function(jsonData)
|
||||||
-- jsonData: [ int uid ]
|
-- jsonData: [ int uid ]
|
||||||
local data = json.decode(jsonData)
|
local data = json.decode(jsonData)
|
||||||
|
@ -289,7 +723,7 @@ fk.room_callback["PlayerStateChanged"] = function(jsonData)
|
||||||
local data = json.decode(jsonData)
|
local data = json.decode(jsonData)
|
||||||
local id = data[1]
|
local id = data[1]
|
||||||
local stateString = data[2]
|
local stateString = data[2]
|
||||||
RoomInstance:findPlayerById(id).state = stateString
|
RoomInstance:getPlayerById(id).state = stateString
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.room_callback["RoomDeleted"] = function(jsonData)
|
fk.room_callback["RoomDeleted"] = function(jsonData)
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
---@alias CardsMoveInfo {ids: integer[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null }
|
||||||
|
---@alias MoveInfo {cardId: integer, fromArea: CardArea}
|
||||||
|
---@alias CardsMoveStruct {moveInfo: {id: integer, fromArea: CardArea}[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer|null, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null, fromSpecialName: string|null }
|
||||||
|
|
||||||
|
---@alias HpChangedData { num: integer, reason: string, skillName: string }
|
||||||
|
---@alias HpLostData { num: integer, skillName: string }
|
||||||
|
---@alias DamageStruct { from: integer|null, to: integer, damage: integer, damageType: DamageType, skillName: string }
|
||||||
|
---@alias RecoverStruct { who: integer, num: integer, recoverBy: integer|null, skillName: string|null }
|
||||||
|
|
||||||
|
---@alias DyingStruct { who: integer, damage: DamageStruct }
|
||||||
|
---@alias DeathStruct { who: integer, damage: DamageStruct }
|
||||||
|
|
||||||
|
|
||||||
|
---@alias MoveReason integer
|
||||||
|
|
||||||
|
fk.ReasonJustMove = 1
|
||||||
|
fk.ReasonDraw = 2
|
||||||
|
fk.ReasonDiscard = 3
|
||||||
|
fk.ReasonGive = 4
|
||||||
|
fk.ReasonPut = 5
|
||||||
|
fk.ReasonPutIntoDiscardPile = 6
|
||||||
|
fk.ReasonPrey = 7
|
||||||
|
fk.ReasonExchange = 8
|
||||||
|
|
||||||
|
---@alias DamageType integer
|
||||||
|
|
||||||
|
fk.NormalDamage = 1
|
||||||
|
fk.ThunderDamage = 2
|
||||||
|
fk.FireDamage = 3
|
|
@ -1,7 +1,7 @@
|
||||||
GameRule = fk.CreateTriggerSkill{
|
GameRule = fk.CreateTriggerSkill{
|
||||||
name = "game_rule",
|
name = "game_rule",
|
||||||
events = {
|
events = {
|
||||||
fk.GameStart, fk.TurnStart,
|
fk.GameStart, fk.DrawInitialCards, fk.TurnStart,
|
||||||
fk.EventPhaseProceeding, fk.EventPhaseEnd, fk.EventPhaseChanging,
|
fk.EventPhaseProceeding, fk.EventPhaseEnd, fk.EventPhaseChanging,
|
||||||
},
|
},
|
||||||
priority = 0,
|
priority = 0,
|
||||||
|
@ -26,6 +26,19 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
|
|
||||||
local room = player.room
|
local room = player.room
|
||||||
switch(event, {
|
switch(event, {
|
||||||
|
[fk.DrawInitialCards] = function()
|
||||||
|
if data.num > 0 then
|
||||||
|
-- TODO: need a new function to call the UI
|
||||||
|
local cardIds = room:getNCards(data.num)
|
||||||
|
player:addCards(Player.Hand, cardIds)
|
||||||
|
|
||||||
|
for _, id in ipairs(cardIds) do
|
||||||
|
room:setCardArea(id, Card.PlayerHand)
|
||||||
|
end
|
||||||
|
|
||||||
|
room.logic:trigger(fk.AfterDrawInitialCards, player, data)
|
||||||
|
end
|
||||||
|
end,
|
||||||
[fk.TurnStart] = function()
|
[fk.TurnStart] = function()
|
||||||
player = room.current
|
player = room.current
|
||||||
if room.tag["FirstRound"] == true then
|
if room.tag["FirstRound"] == true then
|
||||||
|
@ -59,6 +72,7 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
end,
|
end,
|
||||||
[Player.Draw] = function()
|
[Player.Draw] = function()
|
||||||
print("Proceeding Draw.")
|
print("Proceeding Draw.")
|
||||||
|
room:drawCards(player, 2, self.name)
|
||||||
end,
|
end,
|
||||||
[Player.Play] = function()
|
[Player.Play] = function()
|
||||||
print("Proceeding Play.")
|
print("Proceeding Play.")
|
||||||
|
@ -66,6 +80,10 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
end,
|
end,
|
||||||
[Player.Discard] = function()
|
[Player.Discard] = function()
|
||||||
print("Proceeding Discard.")
|
print("Proceeding Discard.")
|
||||||
|
local discardNum = #player:getCardIds(Player.Hand) - player:getMaxCards()
|
||||||
|
if discardNum > 0 then
|
||||||
|
room:askForDiscard(player, discardNum, discardNum, false, self.name)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
[Player.Finish] = function()
|
[Player.Finish] = function()
|
||||||
print("Proceeding Finish.")
|
print("Proceeding Finish.")
|
||||||
|
|
|
@ -3,6 +3,504 @@ extension.metadata = require "packages.standard_cards.metadata"
|
||||||
|
|
||||||
local slash = fk.CreateBasicCard{
|
local slash = fk.CreateBasicCard{
|
||||||
name = "slash",
|
name = "slash",
|
||||||
|
number = 7,
|
||||||
|
suit = Card.Spade,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["slash"] = "杀",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
slash,
|
||||||
|
slash:clone(Card.Spade, 8),
|
||||||
|
slash:clone(Card.Spade, 8),
|
||||||
|
slash:clone(Card.Spade, 9),
|
||||||
|
slash:clone(Card.Spade, 9),
|
||||||
|
slash:clone(Card.Spade, 10),
|
||||||
|
slash:clone(Card.Spade, 10),
|
||||||
|
|
||||||
|
slash:clone(Card.Club, 2),
|
||||||
|
slash:clone(Card.Club, 3),
|
||||||
|
slash:clone(Card.Club, 4),
|
||||||
|
slash:clone(Card.Club, 5),
|
||||||
|
slash:clone(Card.Club, 6),
|
||||||
|
slash:clone(Card.Club, 7),
|
||||||
|
slash:clone(Card.Club, 8),
|
||||||
|
slash:clone(Card.Club, 8),
|
||||||
|
slash:clone(Card.Club, 9),
|
||||||
|
slash:clone(Card.Club, 9),
|
||||||
|
slash:clone(Card.Club, 10),
|
||||||
|
slash:clone(Card.Club, 10),
|
||||||
|
slash:clone(Card.Club, 11),
|
||||||
|
slash:clone(Card.Club, 11),
|
||||||
|
|
||||||
|
slash:clone(Card.Heart, 10),
|
||||||
|
slash:clone(Card.Heart, 10),
|
||||||
|
slash:clone(Card.Heart, 11),
|
||||||
|
|
||||||
|
slash:clone(Card.Diamond, 6),
|
||||||
|
slash:clone(Card.Diamond, 7),
|
||||||
|
slash:clone(Card.Diamond, 8),
|
||||||
|
slash:clone(Card.Diamond, 9),
|
||||||
|
slash:clone(Card.Diamond, 10),
|
||||||
|
slash:clone(Card.Diamond, 13),
|
||||||
|
})
|
||||||
|
|
||||||
|
local jink = fk.CreateBasicCard{
|
||||||
|
name = "jink",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 2,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["jink"] = "闪",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
jink,
|
||||||
|
jink:clone(Card.Heart, 2),
|
||||||
|
jink:clone(Card.Heart, 13),
|
||||||
|
|
||||||
|
jink:clone(Card.Diamond, 2),
|
||||||
|
jink:clone(Card.Diamond, 2),
|
||||||
|
jink:clone(Card.Diamond, 3),
|
||||||
|
jink:clone(Card.Diamond, 4),
|
||||||
|
jink:clone(Card.Diamond, 5),
|
||||||
|
jink:clone(Card.Diamond, 6),
|
||||||
|
jink:clone(Card.Diamond, 7),
|
||||||
|
jink:clone(Card.Diamond, 8),
|
||||||
|
jink:clone(Card.Diamond, 9),
|
||||||
|
jink:clone(Card.Diamond, 10),
|
||||||
|
jink:clone(Card.Diamond, 11),
|
||||||
|
jink:clone(Card.Diamond, 11),
|
||||||
|
})
|
||||||
|
|
||||||
|
local peach = fk.CreateBasicCard{
|
||||||
|
name = "peach",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 3,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["peach"] = "桃",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
peach,
|
||||||
|
peach:clone(Card.Heart, 4),
|
||||||
|
peach:clone(Card.Heart, 6),
|
||||||
|
peach:clone(Card.Heart, 7),
|
||||||
|
peach:clone(Card.Heart, 8),
|
||||||
|
peach:clone(Card.Heart, 9),
|
||||||
|
peach:clone(Card.Heart, 12),
|
||||||
|
peach:clone(Card.Heart, 12),
|
||||||
|
})
|
||||||
|
|
||||||
|
local dismantlement = fk.CreateTrickCard{
|
||||||
|
name = "dismantlement",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 3,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["dismantlement"] = "过河拆桥",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
dismantlement,
|
||||||
|
dismantlement:clone(Card.Spade, 4),
|
||||||
|
dismantlement:clone(Card.Spade, 12),
|
||||||
|
|
||||||
|
dismantlement:clone(Card.Club, 3),
|
||||||
|
dismantlement:clone(Card.Club, 4),
|
||||||
|
|
||||||
|
dismantlement:clone(Card.Heart, 12),
|
||||||
|
})
|
||||||
|
|
||||||
|
local snatch = fk.CreateTrickCard{
|
||||||
|
name = "snatch",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 3,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["snatch"] = "顺手牵羊",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
snatch,
|
||||||
|
snatch:clone(Card.Spade, 4),
|
||||||
|
snatch:clone(Card.Spade, 11),
|
||||||
|
|
||||||
|
snatch:clone(Card.Diamond, 3),
|
||||||
|
snatch:clone(Card.Diamond, 4),
|
||||||
|
})
|
||||||
|
|
||||||
|
local duel = fk.CreateTrickCard{
|
||||||
|
name = "duel",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 1,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["duel"] = "决斗",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
duel,
|
||||||
|
|
||||||
|
duel:clone(Card.Club, 1),
|
||||||
|
|
||||||
|
duel:clone(Card.Diamond, 1),
|
||||||
|
})
|
||||||
|
|
||||||
|
local collateral = fk.CreateTrickCard{
|
||||||
|
name = "collateral",
|
||||||
|
suit = Card.Club,
|
||||||
|
number = 12,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["collateral"] = "借刀杀人",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
collateral,
|
||||||
|
collateral:clone(Card.Club, 13),
|
||||||
|
})
|
||||||
|
|
||||||
|
local exNihilo = fk.CreateTrickCard{
|
||||||
|
name = "ex_nihilo",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 7,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["ex_nihilo"] = "无中生有",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
exNihilo,
|
||||||
|
exNihilo:clone(Card.Heart, 8),
|
||||||
|
exNihilo:clone(Card.Heart, 9),
|
||||||
|
exNihilo:clone(Card.Heart, 11),
|
||||||
|
})
|
||||||
|
|
||||||
|
local nullification = fk.CreateTrickCard{
|
||||||
|
name = "nullification",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 11,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["nullification"] = "无懈可击",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
nullification,
|
||||||
|
|
||||||
|
nullification:clone(Card.Club, 12),
|
||||||
|
nullification:clone(Card.Club, 13),
|
||||||
|
|
||||||
|
nullification:clone(Card.Diamond, 12),
|
||||||
|
})
|
||||||
|
|
||||||
|
local savageAssault = fk.CreateTrickCard{
|
||||||
|
name = "savage_assault",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 7,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["savage_assault"] = "南蛮入侵",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
savageAssault,
|
||||||
|
savageAssault:clone(Card.Spade, 13),
|
||||||
|
savageAssault:clone(Card.Club, 7),
|
||||||
|
})
|
||||||
|
|
||||||
|
local archeryAttack = fk.CreateTrickCard{
|
||||||
|
name = "archery_attack",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 1,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["archery_attack"] = "万箭齐发",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
archeryAttack,
|
||||||
|
})
|
||||||
|
|
||||||
|
local godSalvation = fk.CreateTrickCard{
|
||||||
|
name = "god_salvation",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 1,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["god_salvation"] = "桃园结义",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
godSalvation,
|
||||||
|
})
|
||||||
|
|
||||||
|
local amazingGrace = fk.CreateTrickCard{
|
||||||
|
name = "amazing_grace",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 3,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["amazing_grace"] = "五谷丰登",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
amazingGrace,
|
||||||
|
amazingGrace:clone(Card.Heart, 4),
|
||||||
|
})
|
||||||
|
|
||||||
|
local lightning = fk.CreateDelayedTrickCard{
|
||||||
|
name = "lightning",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 1,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["lightning"] = "闪电",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
lightning,
|
||||||
|
lightning:clone(Card.Heart, 12),
|
||||||
|
})
|
||||||
|
|
||||||
|
local indulgence = fk.CreateDelayedTrickCard{
|
||||||
|
name = "indulgence",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 6,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["indulgence"] = "乐不思蜀",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
indulgence,
|
||||||
|
indulgence:clone(Card.Club, 6),
|
||||||
|
})
|
||||||
|
|
||||||
|
local crossbow = fk.CreateWeapon{
|
||||||
|
name = "crossbow",
|
||||||
|
suit = Card.Club,
|
||||||
|
number = 1,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["crossbow"] = "诸葛连弩",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
crossbow,
|
||||||
|
crossbow:clone(Card.Diamond, 1),
|
||||||
|
})
|
||||||
|
|
||||||
|
local qingGang = fk.CreateWeapon{
|
||||||
|
name = "qinggang_sword",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 6,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["qinggang_sword"] = "青釭剑",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
qingGang,
|
||||||
|
})
|
||||||
|
|
||||||
|
local iceSword = fk.CreateWeapon{
|
||||||
|
name = "ice_sword",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 2,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["ice_sword"] = "寒冰剑",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
iceSword,
|
||||||
|
})
|
||||||
|
|
||||||
|
local doubleSwords = fk.CreateWeapon{
|
||||||
|
name = "double_swords",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 2,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["double_swords"] = "雌雄双股剑",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
doubleSwords,
|
||||||
|
})
|
||||||
|
|
||||||
|
local blade = fk.CreateWeapon{
|
||||||
|
name = "blade",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["blade"] = "青龙偃月刀",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
blade,
|
||||||
|
})
|
||||||
|
|
||||||
|
local spear = fk.CreateWeapon{
|
||||||
|
name = "spear",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 12,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["spear"] = "丈八蛇矛",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
spear,
|
||||||
|
})
|
||||||
|
|
||||||
|
local axe = fk.CreateWeapon{
|
||||||
|
name = "axe",
|
||||||
|
suit = Card.Diamond,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["axe"] = "贯石斧",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
axe,
|
||||||
|
})
|
||||||
|
|
||||||
|
local halberd = fk.CreateWeapon{
|
||||||
|
name = "halberd",
|
||||||
|
suit = Card.Diamond,
|
||||||
|
number = 12,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["halberd"] = "方天画戟",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
halberd,
|
||||||
|
})
|
||||||
|
|
||||||
|
local kylinBow = fk.CreateWeapon{
|
||||||
|
name = "kylin_bow",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["kylin_bow"] = "麒麟弓",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
kylinBow,
|
||||||
|
})
|
||||||
|
|
||||||
|
local eightDiagram = fk.CreateArmor{
|
||||||
|
name = "eight_diagram",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 2,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["eight_diagram"] = "八卦阵",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
eightDiagram,
|
||||||
|
eightDiagram:clone(Card.Club, 2),
|
||||||
|
})
|
||||||
|
|
||||||
|
local niohShield = fk.CreateArmor{
|
||||||
|
name = "nioh_shield",
|
||||||
|
suit = Card.Club,
|
||||||
|
number = 2,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["nioh_shield"] = "仁王盾",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
niohShield,
|
||||||
|
})
|
||||||
|
|
||||||
|
local diLu = fk.CreateDefensiveRide{
|
||||||
|
name = "dilu",
|
||||||
|
suit = Card.Club,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["dilu"] = "的卢",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
diLu,
|
||||||
|
})
|
||||||
|
|
||||||
|
local jueYing = fk.CreateDefensiveRide{
|
||||||
|
name = "jueying",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["jueying"] = "绝影",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
jueYing,
|
||||||
|
})
|
||||||
|
|
||||||
|
local zhuaHuangFeiDian = fk.CreateDefensiveRide{
|
||||||
|
name = "zhuahuangfeidian",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 13,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["zhuahuangfeidian"] = "爪黄飞电",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
zhuaHuangFeiDian,
|
||||||
|
})
|
||||||
|
|
||||||
|
local chiTu = fk.CreateOffensiveRide{
|
||||||
|
name = "chitu",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["chitu"] = "赤兔",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
chiTu,
|
||||||
|
})
|
||||||
|
|
||||||
|
local daYuan = fk.CreateOffensiveRide{
|
||||||
|
name = "dayuan",
|
||||||
|
suit = Card.Spade,
|
||||||
|
number = 13,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["dayuan"] = "大宛",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
daYuan,
|
||||||
|
})
|
||||||
|
|
||||||
|
local ziXing = fk.CreateOffensiveRide{
|
||||||
|
name = "zixing",
|
||||||
|
suit = Card.Heart,
|
||||||
|
number = 5,
|
||||||
|
}
|
||||||
|
Fk:loadTranslationTable{
|
||||||
|
["zixing"] = "紫骍",
|
||||||
|
}
|
||||||
|
|
||||||
|
extension:addCards({
|
||||||
|
ziXing,
|
||||||
|
})
|
||||||
|
|
||||||
return extension
|
return extension
|
||||||
|
|
Loading…
Reference in New Issue