mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 03:32:34 +08:00
Enhancement (#116)
给Card堆一个伤害牌属性 能添加虚拟牌为子卡 封装了“视为使用xx牌”的函数 护甲机制 interaction现在可以作为一个函数,以实现动态化 冰属性伤害 使用牌堆中的牌不再报错
This commit is contained in:
parent
a735013411
commit
9ae119028c
BIN
image/photo/magatama/shield.png
Normal file
BIN
image/photo/magatama/shield.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -82,7 +82,9 @@ function Client:moveCards(moves)
|
||||||
table.remove(from.player_cards[Player.Hand])
|
table.remove(from.player_cards[Player.Hand])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
from:removeCards(move.fromArea, move.ids, move.fromSpecialName)
|
if table.contains({ Player.Hand, Player.Equip, Player.Judge, Player.Special }, move.fromArea) then
|
||||||
|
from:removeCards(move.fromArea, move.ids, move.fromSpecialName)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif move.fromArea == Card.DiscardPile then
|
elseif move.fromArea == Card.DiscardPile then
|
||||||
table.removeOne(self.discard_pile, move.ids[1])
|
table.removeOne(self.discard_pile, move.ids[1])
|
||||||
|
|
|
@ -14,7 +14,8 @@ function GetGeneralData(name)
|
||||||
extension = general.package.extensionName,
|
extension = general.package.extensionName,
|
||||||
kingdom = general.kingdom,
|
kingdom = general.kingdom,
|
||||||
hp = general.hp,
|
hp = general.hp,
|
||||||
maxHp = general.maxHp
|
maxHp = general.maxHp,
|
||||||
|
shield = general.shield,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -168,28 +169,13 @@ function CanUseCard(card, player)
|
||||||
|
|
||||||
player = ClientInstance:getPlayerById(player)
|
player = ClientInstance:getPlayerById(player)
|
||||||
local ret = c.skill:canUse(player, c)
|
local ret = c.skill:canUse(player, c)
|
||||||
if ret then
|
ret = ret and not player:prohibitUse(c)
|
||||||
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
|
||||||
for _, skill in ipairs(status_skills) do
|
|
||||||
if skill:prohibitUse(player, c) then
|
|
||||||
ret = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return json.encode(ret)
|
return json.encode(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CardProhibitedUse(cid)
|
function CardProhibitedUse(cid)
|
||||||
local c = Fk:getCardById(cid)
|
local c = Fk:getCardById(cid)
|
||||||
local ret = false
|
local ret = Self:prohibitUse(c)
|
||||||
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
|
||||||
for _, skill in ipairs(status_skills) do
|
|
||||||
if skill:prohibitUse(Self, c) then
|
|
||||||
ret = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return json.encode(ret)
|
return json.encode(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -211,16 +197,7 @@ function CanUseCardToTarget(card, to_select, selected)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c)
|
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c)
|
||||||
if ret then
|
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
|
||||||
local r = Fk:currentRoom()
|
|
||||||
local status_skills = r.status_skills[ProhibitSkill] or {}
|
|
||||||
for _, skill in ipairs(status_skills) do
|
|
||||||
if skill:isProhibited(Self, r:getPlayerById(to_select), c) then
|
|
||||||
ret = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return json.encode(ret)
|
return json.encode(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -403,14 +380,7 @@ end
|
||||||
|
|
||||||
function CardProhibitedResponse(cid)
|
function CardProhibitedResponse(cid)
|
||||||
local c = Fk:getCardById(cid)
|
local c = Fk:getCardById(cid)
|
||||||
local ret = false
|
local ret = Self:prohibitResponse(c)
|
||||||
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
|
||||||
for _, skill in ipairs(status_skills) do
|
|
||||||
if skill:prohibitResponse(Self, c) then
|
|
||||||
ret = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return json.encode(ret)
|
return json.encode(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -453,12 +423,19 @@ end
|
||||||
|
|
||||||
function GetInteractionOfSkill(skill_name)
|
function GetInteractionOfSkill(skill_name)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
return skill and json.encode(skill.interaction) or "null"
|
if skill and skill.interaction then
|
||||||
|
if type(skill.interaction) == "function" then
|
||||||
|
return json.encode(skill:interaction())
|
||||||
|
else
|
||||||
|
return json.encode(skill.interaction)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "null"
|
||||||
end
|
end
|
||||||
|
|
||||||
function SetInteractionDataOfSkill(skill_name, data)
|
function SetInteractionDataOfSkill(skill_name, data)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
if skill and type(skill.interaction) == "table" then
|
if skill and skill.interaction then
|
||||||
skill.interaction.data = json.decode(data)
|
skill.interaction.data = json.decode(data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -171,6 +171,7 @@ Fk:loadTranslationTable{
|
||||||
["normal_damage"] = "无属性",
|
["normal_damage"] = "无属性",
|
||||||
["fire_damage"] = "火属性",
|
["fire_damage"] = "火属性",
|
||||||
["thunder_damage"] = "雷属性",
|
["thunder_damage"] = "雷属性",
|
||||||
|
["ice_damage"] = "冰属性",
|
||||||
|
|
||||||
["phase_judge"] = "判定阶段",
|
["phase_judge"] = "判定阶段",
|
||||||
["phase_draw"] = "摸牌阶段",
|
["phase_draw"] = "摸牌阶段",
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
---@field public skillNames string[]
|
---@field public skillNames string[]
|
||||||
---@field public skill Skill
|
---@field public skill Skill
|
||||||
---@field public special_skills string[] | nil
|
---@field public special_skills string[] | nil
|
||||||
|
---@field public is_damage_card boolean
|
||||||
local Card = class("Card")
|
local Card = class("Card")
|
||||||
|
|
||||||
---@alias Suit integer
|
---@alias Suit integer
|
||||||
|
@ -162,7 +163,7 @@ local function updateColorAndNumber(card)
|
||||||
number = math.min(number + c.number, 13)
|
number = math.min(number + c.number, 13)
|
||||||
if color ~= c.color then
|
if color ~= c.color then
|
||||||
if not different_color then
|
if not different_color then
|
||||||
if color ~= Card.NoColor then
|
if c.color ~= Card.NoColor then
|
||||||
different_color = true
|
different_color = true
|
||||||
end
|
end
|
||||||
color = c.color
|
color = c.color
|
||||||
|
@ -183,8 +184,16 @@ function Card:addSubcard(card)
|
||||||
table.insert(self.subcards, card)
|
table.insert(self.subcards, card)
|
||||||
else
|
else
|
||||||
assert(card:isInstanceOf(Card))
|
assert(card:isInstanceOf(Card))
|
||||||
assert(not card:isVirtual(), "Can not add virtual card as subcard")
|
-- assert(not card:isVirtual(), "Can not add virtual card as subcard")
|
||||||
table.insert(self.subcards, card.id)
|
if card:isVirtual() then
|
||||||
|
table.insertTable(self.subcards, card.subcards)
|
||||||
|
else
|
||||||
|
table.insert(self.subcards, card.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, skill in ipairs(card.skillNames) do
|
||||||
|
self.skillName = skill
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
updateColorAndNumber(self)
|
updateColorAndNumber(self)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
---@field public kingdom string @ 武将所属势力
|
---@field public kingdom string @ 武将所属势力
|
||||||
---@field public hp integer @ 武将初始体力
|
---@field public hp integer @ 武将初始体力
|
||||||
---@field public maxHp integer @ 武将初始最大体力
|
---@field public maxHp integer @ 武将初始最大体力
|
||||||
|
---@field public shield integer @ 初始护甲
|
||||||
---@field public gender Gender @ 武将性别
|
---@field public gender Gender @ 武将性别
|
||||||
---@field public skills Skill[] @ 武将技能
|
---@field public skills Skill[] @ 武将技能
|
||||||
---@field public other_skills string[] @ 武将身上属于其他武将的技能,通过字符串调用
|
---@field public other_skills string[] @ 武将身上属于其他武将的技能,通过字符串调用
|
||||||
|
@ -40,6 +41,7 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender)
|
||||||
self.hp = hp
|
self.hp = hp
|
||||||
self.maxHp = maxHp or hp
|
self.maxHp = maxHp or hp
|
||||||
self.gender = gender or General.Male
|
self.gender = gender or General.Male
|
||||||
|
self.shield = 0
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
---@field public id integer @ 玩家的id,每名玩家的id是唯一的。机器人的id是负数。
|
---@field public id integer @ 玩家的id,每名玩家的id是唯一的。机器人的id是负数。
|
||||||
---@field public hp integer @ 体力值
|
---@field public hp integer @ 体力值
|
||||||
---@field public maxHp integer @ 体力上限
|
---@field public maxHp integer @ 体力上限
|
||||||
|
---@field public shield integer @ 护甲数
|
||||||
---@field public kingdom string @ 势力
|
---@field public kingdom string @ 势力
|
||||||
---@field public role string @ 身份
|
---@field public role string @ 身份
|
||||||
---@field public general string @ 武将
|
---@field public general string @ 武将
|
||||||
|
@ -667,4 +668,50 @@ function Player:getAllSkills()
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param to Player
|
||||||
|
---@param card Card
|
||||||
|
function Player:isProhibited(to, card)
|
||||||
|
local r = Fk:currentRoom()
|
||||||
|
local status_skills = r.status_skills[ProhibitSkill] or {}
|
||||||
|
for _, skill in ipairs(status_skills) do
|
||||||
|
if skill:isProhibited(self, to, card) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param card Card
|
||||||
|
function Player:prohibitUse(card)
|
||||||
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
||||||
|
for _, skill in ipairs(status_skills) do
|
||||||
|
if skill:prohibitUse(self, card) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param card Card
|
||||||
|
function Player:prohibitResponse(card)
|
||||||
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
||||||
|
for _, skill in ipairs(status_skills) do
|
||||||
|
if skill:prohibitResponse(self, card) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param card Card
|
||||||
|
function Player:prohibitDiscard(card)
|
||||||
|
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
|
||||||
|
for _, skill in ipairs(status_skills) do
|
||||||
|
if skill:prohibitDiscard(self, card) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
return Player
|
return Player
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
local Util = {}
|
||||||
|
|
||||||
-- the iterator of QList object
|
-- the iterator of QList object
|
||||||
local qlist_iterator = function(list, n)
|
local qlist_iterator = function(list, n)
|
||||||
if n < list:length() - 1 then
|
if n < list:length() - 1 then
|
||||||
|
@ -52,9 +54,11 @@ function table:map(func)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- frequenly used filter & map functions
|
-- frequenly used filter & map functions
|
||||||
IdMapper = function(e) return e.id end
|
Util.IdMapper = function(e) return e.id end
|
||||||
Id2CardMapper = function(id) return Fk:getCardById(id) end
|
Util.Id2CardMapper = function(id) return Fk:getCardById(id) end
|
||||||
Id2PlayerMapper = function(id) return Fk:currentRoom():getPlayerById(id) end
|
Util.Id2PlayerMapper = function(id)
|
||||||
|
return Fk:currentRoom():getPlayerById(id)
|
||||||
|
end
|
||||||
|
|
||||||
---@generic T
|
---@generic T
|
||||||
---@param self T[]
|
---@param self T[]
|
||||||
|
@ -467,4 +471,4 @@ function AimGroup:getCancelledTargets(aimGroup)
|
||||||
return aimGroup[AimGroup.Cancelled]
|
return aimGroup[AimGroup.Cancelled]
|
||||||
end
|
end
|
||||||
|
|
||||||
return { TargetGroup, AimGroup }
|
return { TargetGroup, AimGroup, Util }
|
||||||
|
|
122
lua/fk_ex.lua
122
lua/fk_ex.lua
|
@ -345,6 +345,7 @@ end
|
||||||
---@class CardSpec: Card
|
---@class CardSpec: Card
|
||||||
---@field public skill Skill
|
---@field public skill Skill
|
||||||
---@field public equip_skill Skill
|
---@field public equip_skill Skill
|
||||||
|
---@field public is_damage_card boolean
|
||||||
|
|
||||||
local defaultCardSkill = fk.CreateActiveSkill{
|
local defaultCardSkill = fk.CreateActiveSkill{
|
||||||
name = "default_card_skill",
|
name = "default_card_skill",
|
||||||
|
@ -355,144 +356,105 @@ local defaultCardSkill = fk.CreateActiveSkill{
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
---@param spec CardSpec
|
local function preprocessCardSpec(spec)
|
||||||
---@return BasicCard
|
|
||||||
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
|
||||||
|
end
|
||||||
|
|
||||||
local card = BasicCard:new(spec.name, spec.suit, spec.number)
|
local function readCardSpecToCard(card, spec)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
card.skill = spec.skill or defaultCardSkill
|
||||||
card.special_skills = spec.special_skills
|
card.special_skills = spec.special_skills
|
||||||
|
card.is_damage_card = spec.is_damage_card
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec CardSpec
|
||||||
|
---@return BasicCard
|
||||||
|
function fk.CreateBasicCard(spec)
|
||||||
|
preprocessCardSpec(spec)
|
||||||
|
local card = BasicCard:new(spec.name, spec.suit, spec.number)
|
||||||
|
readCardSpecToCard(card, spec)
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return TrickCard
|
---@return TrickCard
|
||||||
function fk.CreateTrickCard(spec)
|
function fk.CreateTrickCard(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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 = TrickCard:new(spec.name, spec.suit, spec.number)
|
local card = TrickCard:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return DelayedTrickCard
|
---@return DelayedTrickCard
|
||||||
function fk.CreateDelayedTrickCard(spec)
|
function fk.CreateDelayedTrickCard(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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 = DelayedTrickCard:new(spec.name, spec.suit, spec.number)
|
local card = DelayedTrickCard:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function readCardSpecToEquip(card, spec)
|
||||||
|
card.equip_skill = spec.equip_skill
|
||||||
|
|
||||||
|
if spec.on_install then card.onInstall = spec.on_install end
|
||||||
|
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
||||||
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return Weapon
|
---@return Weapon
|
||||||
function fk.CreateWeapon(spec)
|
function fk.CreateWeapon(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
if not spec.name then spec.name = spec.class_name
|
if spec.attack_range then
|
||||||
elseif not spec.class_name then spec.class_name = spec.name end
|
assert(type(spec.attack_range) == "number" and spec.attack_range >= 0)
|
||||||
if spec.suit then assert(type(spec.suit) == "number") end
|
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)
|
local card = Weapon:new(spec.name, spec.suit, spec.number, spec.attack_range)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
readCardSpecToEquip(card, spec)
|
||||||
card.equip_skill = spec.equip_skill
|
|
||||||
|
|
||||||
if spec.on_install then card.onInstall = spec.on_install end
|
|
||||||
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return Armor
|
---@return Armor
|
||||||
function fk.CreateArmor(spec)
|
function fk.CreateArmor(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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)
|
local card = Armor:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.equip_skill = spec.equip_skill
|
readCardSpecToEquip(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
|
||||||
|
|
||||||
if spec.on_install then card.onInstall = spec.on_install end
|
|
||||||
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return DefensiveRide
|
---@return DefensiveRide
|
||||||
function fk.CreateDefensiveRide(spec)
|
function fk.CreateDefensiveRide(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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)
|
local card = DefensiveRide:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
readCardSpecToEquip(card, spec)
|
||||||
card.equip_skill = spec.equip_skill
|
|
||||||
|
|
||||||
if spec.on_install then card.onInstall = spec.on_install end
|
|
||||||
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return OffensiveRide
|
---@return OffensiveRide
|
||||||
function fk.CreateOffensiveRide(spec)
|
function fk.CreateOffensiveRide(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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)
|
local card = OffensiveRide:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
readCardSpecToEquip(card, spec)
|
||||||
card.equip_skill = spec.equip_skill
|
|
||||||
|
|
||||||
if spec.on_install then card.onInstall = spec.on_install end
|
|
||||||
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec CardSpec
|
---@param spec CardSpec
|
||||||
---@return Treasure
|
---@return Treasure
|
||||||
function fk.CreateTreasure(spec)
|
function fk.CreateTreasure(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
preprocessCardSpec(spec)
|
||||||
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)
|
local card = Treasure:new(spec.name, spec.suit, spec.number)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
readCardSpecToCard(card, spec)
|
||||||
card.special_skills = spec.special_skills
|
readCardSpecToEquip(card, spec)
|
||||||
card.equip_skill = spec.equip_skill
|
|
||||||
|
|
||||||
if spec.on_install then card.onInstall = spec.on_install end
|
|
||||||
if spec.on_uninstall then card.onUninstall = spec.on_uninstall end
|
|
||||||
return card
|
return card
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ json = require "json"
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
|
|
||||||
-- 加载实用类,让Lua编写起来更轻松。
|
-- 加载实用类,让Lua编写起来更轻松。
|
||||||
local GroupUtils = require "core.util"
|
local Utils = require "core.util"
|
||||||
TargetGroup, AimGroup = table.unpack(GroupUtils)
|
TargetGroup, AimGroup, Util = table.unpack(Utils)
|
||||||
dofile "lua/core/debug.lua"
|
dofile "lua/core/debug.lua"
|
||||||
|
|
||||||
-- 加载游戏核心类
|
-- 加载游戏核心类
|
||||||
|
|
|
@ -1,5 +1,36 @@
|
||||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
local damage_nature_table = {
|
||||||
|
[fk.NormalDamage] = "normal_damage",
|
||||||
|
[fk.FireDamage] = "fire_damage",
|
||||||
|
[fk.ThunderDamage] = "thunder_damage",
|
||||||
|
[fk.IceDamage] = "ice_damage",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function sendDamageLog(room, damageStruct)
|
||||||
|
if damageStruct.from then
|
||||||
|
room:sendLog{
|
||||||
|
type = "#Damage",
|
||||||
|
to = {damageStruct.from.id},
|
||||||
|
from = damageStruct.to.id,
|
||||||
|
arg = damageStruct.damage,
|
||||||
|
arg2 = damage_nature_table[damageStruct.damageType],
|
||||||
|
}
|
||||||
|
else
|
||||||
|
room:sendLog{
|
||||||
|
type = "#DamageWithNoFrom",
|
||||||
|
from = damageStruct.to.id,
|
||||||
|
arg = damageStruct.damage,
|
||||||
|
arg2 = damage_nature_table[damageStruct.damageType],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
room:sendLogEvent("Damage", {
|
||||||
|
to = damageStruct.to.id,
|
||||||
|
damageType = damage_nature_table[damageStruct.damageType],
|
||||||
|
damageNum = damageStruct.damage,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
GameEvent.functions[GameEvent.ChangeHp] = function(self)
|
GameEvent.functions[GameEvent.ChangeHp] = function(self)
|
||||||
local player, num, reason, skillName, damageStruct = table.unpack(self.data)
|
local player, num, reason, skillName, damageStruct = table.unpack(self.data)
|
||||||
local self = self.room
|
local self = self.room
|
||||||
|
@ -25,32 +56,7 @@ GameEvent.functions[GameEvent.ChangeHp] = function(self)
|
||||||
self:broadcastProperty(player, "hp")
|
self:broadcastProperty(player, "hp")
|
||||||
|
|
||||||
if reason == "damage" then
|
if reason == "damage" then
|
||||||
local damage_nature_table = {
|
sendDamageLog(self, damageStruct)
|
||||||
[fk.NormalDamage] = "normal_damage",
|
|
||||||
[fk.FireDamage] = "fire_damage",
|
|
||||||
[fk.ThunderDamage] = "thunder_damage",
|
|
||||||
}
|
|
||||||
if damageStruct.from then
|
|
||||||
self:sendLog{
|
|
||||||
type = "#Damage",
|
|
||||||
to = {damageStruct.from.id},
|
|
||||||
from = player.id,
|
|
||||||
arg = 0 - num,
|
|
||||||
arg2 = damage_nature_table[damageStruct.damageType],
|
|
||||||
}
|
|
||||||
else
|
|
||||||
self:sendLog{
|
|
||||||
type = "#DamageWithNoFrom",
|
|
||||||
from = player.id,
|
|
||||||
arg = 0 - num,
|
|
||||||
arg2 = damage_nature_table[damageStruct.damageType],
|
|
||||||
}
|
|
||||||
end
|
|
||||||
self:sendLogEvent("Damage", {
|
|
||||||
to = player.id,
|
|
||||||
damageType = damage_nature_table[damageStruct.damageType],
|
|
||||||
damageNum = damageStruct.damage,
|
|
||||||
})
|
|
||||||
elseif reason == "loseHp" then
|
elseif reason == "loseHp" then
|
||||||
self:sendLog{
|
self:sendLog{
|
||||||
type = "#LoseHP",
|
type = "#LoseHP",
|
||||||
|
@ -125,8 +131,21 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:changeHp(damageStruct.to, -damageStruct.damage, "damage", damageStruct.skillName, damageStruct) then
|
-- 先扣减护甲,再扣体力值
|
||||||
self.logic:breakEvent(false)
|
local shield_to_lose = math.min(damageStruct.damage, damageStruct.to.shield)
|
||||||
|
self:changeShield(damageStruct.to, -shield_to_lose)
|
||||||
|
|
||||||
|
if shield_to_lose < damageStruct.damage then
|
||||||
|
if not self:changeHp(
|
||||||
|
damageStruct.to,
|
||||||
|
shield_to_lose - damageStruct.damage,
|
||||||
|
"damage",
|
||||||
|
damageStruct.skillName,
|
||||||
|
damageStruct) then
|
||||||
|
self.logic:breakEvent(false)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
sendDamageLog(self, damageStruct)
|
||||||
end
|
end
|
||||||
|
|
||||||
stages = {
|
stages = {
|
||||||
|
|
|
@ -122,6 +122,7 @@ function GameLogic:prepareForStart()
|
||||||
local general = Fk.generals[p.general]
|
local general = Fk.generals[p.general]
|
||||||
p.maxHp = general.maxHp
|
p.maxHp = general.maxHp
|
||||||
p.hp = general.hp
|
p.hp = general.hp
|
||||||
|
p.shield = general.shield
|
||||||
-- TODO: setup AI here
|
-- TODO: setup AI here
|
||||||
|
|
||||||
if p.role ~= "lord" then
|
if p.role ~= "lord" then
|
||||||
|
@ -132,6 +133,7 @@ function GameLogic:prepareForStart()
|
||||||
end
|
end
|
||||||
room:broadcastProperty(p, "maxHp")
|
room:broadcastProperty(p, "maxHp")
|
||||||
room:broadcastProperty(p, "hp")
|
room:broadcastProperty(p, "hp")
|
||||||
|
room:broadcastProperty(p, "shield")
|
||||||
end
|
end
|
||||||
|
|
||||||
local allCardIds = Fk:getAllCardIds()
|
local allCardIds = Fk:getAllCardIds()
|
||||||
|
|
|
@ -1882,6 +1882,39 @@ function Room:responseCard(cardResponseEvent)
|
||||||
return execGameEvent(GameEvent.RespondCard, cardResponseEvent)
|
return execGameEvent(GameEvent.RespondCard, cardResponseEvent)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param card_name string @ 想要视为使用的牌名
|
||||||
|
---@param subcards integer[] @ 子卡,可以留空或者直接nil
|
||||||
|
---@param from ServerPlayer @ 使用来源
|
||||||
|
---@param tos ServerPlayer | ServerPlayer[] @ 目标角色(列表)
|
||||||
|
---@param skillName string @ 技能名
|
||||||
|
---@param extra boolean @ 是否计入次数
|
||||||
|
function Room:useVirtualCard(card_name, subcards, from, tos, skillName, extra)
|
||||||
|
local card = Fk:cloneCard(card_name)
|
||||||
|
card.skillName = skillName
|
||||||
|
|
||||||
|
if from:prohibitUse(card) then return false end
|
||||||
|
|
||||||
|
if tos.class then tos = { tos } end
|
||||||
|
for i, p in ipairs(tos) do
|
||||||
|
if from:isProhibited(p, card) then
|
||||||
|
table.remove(tos, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #tos == 0 then return false end
|
||||||
|
|
||||||
|
if subcards then card:addSubcards(Card:getIdList(subcards)) end
|
||||||
|
|
||||||
|
local use = {} ---@type CardUseStruct
|
||||||
|
use.from = from.id
|
||||||
|
use.tos = table.map(tos, function(p) return { p.id } end)
|
||||||
|
use.card = card
|
||||||
|
use.extraUse = extra
|
||||||
|
self:useCard(use)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- 移动牌
|
-- 移动牌
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
@ -1992,6 +2025,16 @@ function Room:changeHp(player, num, reason, skillName, damageStruct)
|
||||||
return execGameEvent(GameEvent.ChangeHp, player, num, reason, skillName, damageStruct)
|
return execGameEvent(GameEvent.ChangeHp, player, num, reason, skillName, damageStruct)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- 改变玩家的护甲数
|
||||||
|
---@param player ServerPlayer
|
||||||
|
---@param num integer @ 变化量
|
||||||
|
function Room:changeShield(player, num)
|
||||||
|
if num == 0 then return end
|
||||||
|
player.shield = math.max(player.shield + num, 0)
|
||||||
|
player.shield = math.min(player.shield, 5)
|
||||||
|
self:broadcastProperty(player, "shield")
|
||||||
|
end
|
||||||
|
|
||||||
--- 令一名玩家失去体力。
|
--- 令一名玩家失去体力。
|
||||||
---@param player ServerPlayer @ 玩家
|
---@param player ServerPlayer @ 玩家
|
||||||
---@param num integer @ 失去的数量
|
---@param num integer @ 失去的数量
|
||||||
|
|
|
@ -141,6 +141,7 @@ function ServerPlayer:marshal(player)
|
||||||
|
|
||||||
room:notifyProperty(player, self, "maxHp")
|
room:notifyProperty(player, self, "maxHp")
|
||||||
room:notifyProperty(player, self, "hp")
|
room:notifyProperty(player, self, "hp")
|
||||||
|
room:notifyProperty(player, self, "shield")
|
||||||
room:notifyProperty(player, self, "gender")
|
room:notifyProperty(player, self, "gender")
|
||||||
room:notifyProperty(player, self, "kingdom")
|
room:notifyProperty(player, self, "kingdom")
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
fk.NormalDamage = 1
|
fk.NormalDamage = 1
|
||||||
fk.ThunderDamage = 2
|
fk.ThunderDamage = 2
|
||||||
fk.FireDamage = 3
|
fk.FireDamage = 3
|
||||||
|
fk.IceDamage = 4
|
||||||
|
|
||||||
--- DamageStruct 用来描述和伤害事件有关的数据。
|
--- DamageStruct 用来描述和伤害事件有关的数据。
|
||||||
---@class DamageStruct
|
---@class DamageStruct
|
||||||
|
|
|
@ -27,6 +27,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{
|
||||||
local thunderSlash = fk.CreateBasicCard{
|
local thunderSlash = fk.CreateBasicCard{
|
||||||
name = "thunder__slash",
|
name = "thunder__slash",
|
||||||
skill = thunderSlashSkill,
|
skill = thunderSlashSkill,
|
||||||
|
is_damage_card = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
extension:addCards{
|
extension:addCards{
|
||||||
|
@ -64,6 +65,7 @@ local fireSlashSkill = fk.CreateActiveSkill{
|
||||||
local fireSlash = fk.CreateBasicCard{
|
local fireSlash = fk.CreateBasicCard{
|
||||||
name = "fire__slash",
|
name = "fire__slash",
|
||||||
skill = fireSlashSkill,
|
skill = fireSlashSkill,
|
||||||
|
is_damage_card = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
extension:addCards{
|
extension:addCards{
|
||||||
|
@ -259,6 +261,7 @@ local fireAttackSkill = fk.CreateActiveSkill{
|
||||||
local fireAttack = fk.CreateTrickCard{
|
local fireAttack = fk.CreateTrickCard{
|
||||||
name = "fire_attack",
|
name = "fire_attack",
|
||||||
skill = fireAttackSkill,
|
skill = fireAttackSkill,
|
||||||
|
is_damage_card = true,
|
||||||
}
|
}
|
||||||
extension:addCards{
|
extension:addCards{
|
||||||
fireAttack:clone(Card.Heart, 2),
|
fireAttack:clone(Card.Heart, 2),
|
||||||
|
|
|
@ -37,6 +37,7 @@ local slash = fk.CreateBasicCard{
|
||||||
name = "slash",
|
name = "slash",
|
||||||
number = 7,
|
number = 7,
|
||||||
suit = Card.Spade,
|
suit = Card.Spade,
|
||||||
|
is_damage_card = true,
|
||||||
skill = slashSkill,
|
skill = slashSkill,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +311,7 @@ local duel = fk.CreateTrickCard{
|
||||||
name = "duel",
|
name = "duel",
|
||||||
suit = Card.Spade,
|
suit = Card.Spade,
|
||||||
number = 1,
|
number = 1,
|
||||||
|
is_damage_card = true,
|
||||||
skill = duelSkill,
|
skill = duelSkill,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,6 +454,7 @@ local savageAssault = fk.CreateTrickCard{
|
||||||
name = "savage_assault",
|
name = "savage_assault",
|
||||||
suit = Card.Spade,
|
suit = Card.Spade,
|
||||||
number = 7,
|
number = 7,
|
||||||
|
is_damage_card = true,
|
||||||
skill = savageAssaultSkill,
|
skill = savageAssaultSkill,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,6 +502,7 @@ local archeryAttack = fk.CreateTrickCard{
|
||||||
name = "archery_attack",
|
name = "archery_attack",
|
||||||
suit = Card.Heart,
|
suit = Card.Heart,
|
||||||
number = 1,
|
number = 1,
|
||||||
|
is_damage_card = true,
|
||||||
skill = archeryAttackSkill,
|
skill = archeryAttackSkill,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,11 @@ local test_active = fk.CreateActiveSkill{
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
card_filter = function(self, card)
|
card_filter = function(self, card)
|
||||||
if self.interaction.data == "joy" then
|
-- if self.interaction.data == "joy" then
|
||||||
--local c = Fk:getCardById(card)
|
--local c = Fk:getCardById(card)
|
||||||
--return Self:getPileNameOfId(card) == self.name and c.color == Card.Red
|
--return Self:getPileNameOfId(card) == self.name and c.color == Card.Red
|
||||||
return true
|
return true
|
||||||
end
|
-- end
|
||||||
end,
|
end,
|
||||||
card_num = 2,
|
card_num = 2,
|
||||||
target_filter = function() return true end,
|
target_filter = function() return true end,
|
||||||
|
@ -86,11 +86,12 @@ local test_active = fk.CreateActiveSkill{
|
||||||
-- room:takeAG(from, id)
|
-- room:takeAG(from, id)
|
||||||
-- room:delay(2000)
|
-- room:delay(2000)
|
||||||
-- room:closeAG(from)
|
-- room:closeAG(from)
|
||||||
local cards = room:askForCardsChosen(from, from, 2, 3, "hej", "")
|
-- local cards = room:askForCardsChosen(from, from, 2, 3, "hej", "")
|
||||||
from:addToPile(self.name, cards)
|
-- from:addToPile(self.name, cards)
|
||||||
from.kingdom = "wei"
|
-- from.kingdom = "wei"
|
||||||
room:broadcastProperty(from, "kingdom")
|
-- room:broadcastProperty(from, "kingdom")
|
||||||
-- p(cards)
|
-- p(cards)
|
||||||
|
room:useVirtualCard("slash", nil, from, room:getOtherPlayers(from), self.name, true)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
local test_vs = fk.CreateViewAsSkill{
|
local test_vs = fk.CreateViewAsSkill{
|
||||||
|
@ -98,16 +99,18 @@ local test_vs = fk.CreateViewAsSkill{
|
||||||
card_filter = function(self, to_select, selected)
|
card_filter = function(self, to_select, selected)
|
||||||
return #selected == 0
|
return #selected == 0
|
||||||
end,
|
end,
|
||||||
interaction = UI.ComboBox {
|
interaction = function(self)
|
||||||
choices = {
|
return UI.ComboBox {
|
||||||
"ex_nihilo",
|
choices = {
|
||||||
"duel",
|
"ex_nihilo",
|
||||||
"snatch",
|
"duel",
|
||||||
"dismantlement",
|
"snatch",
|
||||||
"savage_assault",
|
"dismantlement",
|
||||||
"archery_attack",
|
"savage_assault",
|
||||||
|
"archery_attack",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
end,
|
||||||
view_as = function(self, cards)
|
view_as = function(self, cards)
|
||||||
if #cards ~= 1 then
|
if #cards ~= 1 then
|
||||||
return nil
|
return nil
|
||||||
|
@ -120,6 +123,7 @@ local test_vs = fk.CreateViewAsSkill{
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
local test2 = General(extension, "mouxusheng", "wu", 4, 4, General.Female)
|
local test2 = General(extension, "mouxusheng", "wu", 4, 4, General.Female)
|
||||||
|
test2.shield = 4
|
||||||
test2:addSkill("rende")
|
test2:addSkill("rende")
|
||||||
test2:addSkill(cheat)
|
test2:addSkill(cheat)
|
||||||
test2:addSkill(test_active)
|
test2:addSkill(test_active)
|
||||||
|
|
|
@ -192,6 +192,7 @@ Item {
|
||||||
netstate: model.netstate
|
netstate: model.netstate
|
||||||
maxHp: model.maxHp
|
maxHp: model.maxHp
|
||||||
hp: model.hp
|
hp: model.hp
|
||||||
|
shield: model.shield
|
||||||
seatNumber: model.seatNumber
|
seatNumber: model.seatNumber
|
||||||
dead: model.dead
|
dead: model.dead
|
||||||
dying: model.dying
|
dying: model.dying
|
||||||
|
@ -256,6 +257,7 @@ Item {
|
||||||
self.kingdom: dashboardModel.kingdom
|
self.kingdom: dashboardModel.kingdom
|
||||||
self.netstate: dashboardModel.netstate
|
self.netstate: dashboardModel.netstate
|
||||||
self.maxHp: dashboardModel.maxHp
|
self.maxHp: dashboardModel.maxHp
|
||||||
|
self.shield: dashboardModel.shield
|
||||||
self.hp: dashboardModel.hp
|
self.hp: dashboardModel.hp
|
||||||
self.seatNumber: dashboardModel.seatNumber
|
self.seatNumber: dashboardModel.seatNumber
|
||||||
self.dead: dashboardModel.dead
|
self.dead: dashboardModel.dead
|
||||||
|
@ -785,6 +787,7 @@ Item {
|
||||||
netstate: "online",
|
netstate: "online",
|
||||||
maxHp: 0,
|
maxHp: 0,
|
||||||
hp: 0,
|
hp: 0,
|
||||||
|
shield: 0,
|
||||||
seatNumber: 1,
|
seatNumber: 1,
|
||||||
dead: false,
|
dead: false,
|
||||||
dying: false,
|
dying: false,
|
||||||
|
@ -808,6 +811,7 @@ Item {
|
||||||
netstate: "online",
|
netstate: "online",
|
||||||
maxHp: 0,
|
maxHp: 0,
|
||||||
hp: 0,
|
hp: 0,
|
||||||
|
shield: 0,
|
||||||
seatNumber: i + 1,
|
seatNumber: i + 1,
|
||||||
dead: false,
|
dead: false,
|
||||||
dying: false,
|
dying: false,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import "PhotoElement"
|
||||||
import "../skin-bank.js" as SkinBank
|
import "../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
/* Layout of general card:
|
/* Layout of general card:
|
||||||
|
@ -18,6 +19,7 @@ CardItem {
|
||||||
property string kingdom
|
property string kingdom
|
||||||
property int hp
|
property int hp
|
||||||
property int maxHp
|
property int maxHp
|
||||||
|
property int shieldNum
|
||||||
property string pkgName: ""
|
property string pkgName: ""
|
||||||
name: ""
|
name: ""
|
||||||
// description: Sanguosha.getGeneralDescription(name)
|
// description: Sanguosha.getGeneralDescription(name)
|
||||||
|
@ -40,6 +42,7 @@ CardItem {
|
||||||
y: 4
|
y: 4
|
||||||
spacing: 1
|
spacing: 1
|
||||||
Repeater {
|
Repeater {
|
||||||
|
id: hpRepeater
|
||||||
model: (hp > 5 || hp !== maxHp) ? 1 : hp
|
model: (hp > 5 || hp !== maxHp) ? 1 : hp
|
||||||
Image {
|
Image {
|
||||||
source: SkinBank.getGeneralCardDir(kingdom) + kingdom + "-magatama"
|
source: SkinBank.getGeneralCardDir(kingdom) + kingdom + "-magatama"
|
||||||
|
@ -56,6 +59,14 @@ CardItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shield {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: hpRepeater.model > 4 ? 16 : 0
|
||||||
|
scale: 0.8
|
||||||
|
value: shieldNum
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
width: 20
|
width: 20
|
||||||
height: 80
|
height: 80
|
||||||
|
@ -114,6 +125,7 @@ CardItem {
|
||||||
kingdom = data.kingdom;
|
kingdom = data.kingdom;
|
||||||
hp = data.hp;
|
hp = data.hp;
|
||||||
maxHp = data.maxHp;
|
maxHp = data.maxHp;
|
||||||
|
shieldNum = data.shield;
|
||||||
|
|
||||||
let splited = name.split("__");
|
let splited = name.split("__");
|
||||||
if (splited.length > 1) {
|
if (splited.length > 1) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ Item {
|
||||||
property alias handcards: handcardAreaItem.length
|
property alias handcards: handcardAreaItem.length
|
||||||
property int maxHp: 0
|
property int maxHp: 0
|
||||||
property int hp: 0
|
property int hp: 0
|
||||||
|
property int shield: 0
|
||||||
property int seatNumber: 1
|
property int seatNumber: 1
|
||||||
property bool dead: false
|
property bool dead: false
|
||||||
property bool dying: false
|
property bool dying: false
|
||||||
|
@ -150,6 +151,7 @@ Item {
|
||||||
x: 8
|
x: 8
|
||||||
value: root.hp
|
value: root.hp
|
||||||
maxValue: root.maxHp
|
maxValue: root.maxHp
|
||||||
|
shieldNum: root.shield
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 36
|
anchors.bottomMargin: 36
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,31 @@
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import ".."
|
import ".."
|
||||||
|
import "../../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
property int maxValue: 4
|
property int maxValue: 4
|
||||||
property int value: 4
|
property int value: 4
|
||||||
property var colors: ["#F4180E", "#F4180E", "#E3B006", "#25EC27"]
|
property var colors: ["#F4180E", "#F4180E", "#E3B006", "#25EC27"]
|
||||||
|
property int shieldNum: 0
|
||||||
|
|
||||||
|
Shield {
|
||||||
|
id: shield
|
||||||
|
value: shieldNum
|
||||||
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: repeater
|
id: repeater
|
||||||
model: maxValue <= 4 ? maxValue : 0
|
model: column.visible ? 0 : maxValue
|
||||||
Magatama {
|
Magatama {
|
||||||
state: (maxValue - 1 - index) >= value ? 0 : (value >= 3 || value >= maxValue ? 3 : (value <= 0 ? 0 : value))
|
state: (maxValue - 1 - index) >= value ? 0 : (value >= 3 || value >= maxValue ? 3 : (value <= 0 ? 0 : value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
visible: maxValue > 4
|
id: column
|
||||||
|
visible: maxValue > 4 || value > maxValue || (shieldNum > 0 && maxValue > 3)
|
||||||
spacing: -4
|
spacing: -4
|
||||||
|
|
||||||
Magatama {
|
Magatama {
|
||||||
|
@ -43,11 +51,15 @@ Column {
|
||||||
|
|
||||||
GlowText {
|
GlowText {
|
||||||
id: splitter
|
id: splitter
|
||||||
|
height: 12
|
||||||
width: root.width
|
width: root.width
|
||||||
text: "/"
|
text: "/"
|
||||||
z: -10
|
z: -10
|
||||||
|
rotation: 40
|
||||||
color: hpItem.color
|
color: hpItem.color
|
||||||
font: hpItem.font
|
font.family: fontLibian.name
|
||||||
|
font.pixelSize: 14
|
||||||
|
font.bold: true
|
||||||
horizontalAlignment: hpItem.horizontalAlignment
|
horizontalAlignment: hpItem.horizontalAlignment
|
||||||
|
|
||||||
glow.color: hpItem.glow.color
|
glow.color: hpItem.glow.color
|
||||||
|
|
22
qml/Pages/RoomElement/PhotoElement/Shield.qml
Normal file
22
qml/Pages/RoomElement/PhotoElement/Shield.qml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import QtQuick
|
||||||
|
import "../../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: root
|
||||||
|
property int value: 0
|
||||||
|
width: 20
|
||||||
|
height: 21
|
||||||
|
visible: (value > 0)
|
||||||
|
source: SkinBank.MAGATAMA_DIR + "shield"
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: value
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
y: -2
|
||||||
|
font.family: fontLibian.name
|
||||||
|
font.pixelSize: 20
|
||||||
|
font.bold: true
|
||||||
|
color: "white"
|
||||||
|
style: Text.Outline
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user