Enhancement (#116)

给Card堆一个伤害牌属性
能添加虚拟牌为子卡
封装了“视为使用xx牌”的函数
护甲机制
interaction现在可以作为一个函数,以实现动态化
冰属性伤害
使用牌堆中的牌不再报错
This commit is contained in:
notify 2023-04-13 20:17:39 +08:00 committed by GitHub
parent a735013411
commit 9ae119028c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 307 additions and 174 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -82,8 +82,10 @@ function Client:moveCards(moves)
table.remove(from.player_cards[Player.Hand])
end
else
if table.contains({ Player.Hand, Player.Equip, Player.Judge, Player.Special }, move.fromArea) then
from:removeCards(move.fromArea, move.ids, move.fromSpecialName)
end
end
elseif move.fromArea == Card.DiscardPile then
table.removeOne(self.discard_pile, move.ids[1])
end

View File

@ -14,7 +14,8 @@ function GetGeneralData(name)
extension = general.package.extensionName,
kingdom = general.kingdom,
hp = general.hp,
maxHp = general.maxHp
maxHp = general.maxHp,
shield = general.shield,
}
end
@ -168,28 +169,13 @@ function CanUseCard(card, player)
player = ClientInstance:getPlayerById(player)
local ret = c.skill:canUse(player, c)
if ret then
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
ret = ret and not player:prohibitUse(c)
return json.encode(ret)
end
function CardProhibitedUse(cid)
local c = Fk:getCardById(cid)
local ret = false
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
local ret = Self:prohibitUse(c)
return json.encode(ret)
end
@ -211,16 +197,7 @@ function CanUseCardToTarget(card, to_select, selected)
end
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c)
if ret then
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
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
return json.encode(ret)
end
@ -403,14 +380,7 @@ end
function CardProhibitedResponse(cid)
local c = Fk:getCardById(cid)
local ret = false
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
local ret = Self:prohibitResponse(c)
return json.encode(ret)
end
@ -453,12 +423,19 @@ end
function GetInteractionOfSkill(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
function SetInteractionDataOfSkill(skill_name, data)
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)
end
end

View File

@ -171,6 +171,7 @@ Fk:loadTranslationTable{
["normal_damage"] = "无属性",
["fire_damage"] = "火属性",
["thunder_damage"] = "雷属性",
["ice_damage"] = "冰属性",
["phase_judge"] = "判定阶段",
["phase_draw"] = "摸牌阶段",

View File

@ -20,6 +20,7 @@
---@field public skillNames string[]
---@field public skill Skill
---@field public special_skills string[] | nil
---@field public is_damage_card boolean
local Card = class("Card")
---@alias Suit integer
@ -162,7 +163,7 @@ local function updateColorAndNumber(card)
number = math.min(number + c.number, 13)
if color ~= c.color then
if not different_color then
if color ~= Card.NoColor then
if c.color ~= Card.NoColor then
different_color = true
end
color = c.color
@ -183,10 +184,18 @@ function Card:addSubcard(card)
table.insert(self.subcards, card)
else
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")
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
updateColorAndNumber(self)
end

View File

@ -13,6 +13,7 @@
---@field public kingdom string @ 武将所属势力
---@field public hp integer @ 武将初始体力
---@field public maxHp integer @ 武将初始最大体力
---@field public shield integer @ 初始护甲
---@field public gender Gender @ 武将性别
---@field public skills Skill[] @ 武将技能
---@field public other_skills string[] @ 武将身上属于其他武将的技能,通过字符串调用
@ -40,6 +41,7 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender)
self.hp = hp
self.maxHp = maxHp or hp
self.gender = gender or General.Male
self.shield = 0
self.skills = {} -- skills first added to this general
self.other_skills = {} -- skill belongs other general, e.g. "mashu" of pangde

View File

@ -10,6 +10,7 @@
---@field public id integer @ 玩家的id每名玩家的id是唯一的。机器人的id是负数。
---@field public hp integer @ 体力值
---@field public maxHp integer @ 体力上限
---@field public shield integer @ 护甲数
---@field public kingdom string @ 势力
---@field public role string @ 身份
---@field public general string @ 武将
@ -667,4 +668,50 @@ function Player:getAllSkills()
return ret
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

View File

@ -1,5 +1,7 @@
-- SPDX-License-Identifier: GPL-3.0-or-later
local Util = {}
-- the iterator of QList object
local qlist_iterator = function(list, n)
if n < list:length() - 1 then
@ -52,9 +54,11 @@ function table:map(func)
end
-- frequenly used filter & map functions
IdMapper = function(e) return e.id end
Id2CardMapper = function(id) return Fk:getCardById(id) end
Id2PlayerMapper = function(id) return Fk:currentRoom():getPlayerById(id) end
Util.IdMapper = function(e) return e.id end
Util.Id2CardMapper = function(id) return Fk:getCardById(id) end
Util.Id2PlayerMapper = function(id)
return Fk:currentRoom():getPlayerById(id)
end
---@generic T
---@param self T[]
@ -467,4 +471,4 @@ function AimGroup:getCancelledTargets(aimGroup)
return aimGroup[AimGroup.Cancelled]
end
return { TargetGroup, AimGroup }
return { TargetGroup, AimGroup, Util }

View File

@ -345,6 +345,7 @@ end
---@class CardSpec: Card
---@field public skill Skill
---@field public equip_skill Skill
---@field public is_damage_card boolean
local defaultCardSkill = fk.CreateActiveSkill{
name = "default_card_skill",
@ -355,144 +356,105 @@ local defaultCardSkill = fk.CreateActiveSkill{
end
}
---@param spec CardSpec
---@return BasicCard
function fk.CreateBasicCard(spec)
local function preprocessCardSpec(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
end
local card = BasicCard:new(spec.name, spec.suit, spec.number)
local function readCardSpecToCard(card, spec)
card.skill = spec.skill or defaultCardSkill
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
end
---@param spec CardSpec
---@return TrickCard
function fk.CreateTrickCard(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
preprocessCardSpec(spec)
local card = TrickCard:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
readCardSpecToCard(card, spec)
return card
end
---@param spec CardSpec
---@return DelayedTrickCard
function fk.CreateDelayedTrickCard(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
preprocessCardSpec(spec)
local card = DelayedTrickCard:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
readCardSpecToCard(card, spec)
return card
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
---@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
preprocessCardSpec(spec)
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)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
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
readCardSpecToCard(card, spec)
readCardSpecToEquip(card, spec)
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
preprocessCardSpec(spec)
local card = Armor:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.equip_skill = spec.equip_skill
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
readCardSpecToCard(card, spec)
readCardSpecToEquip(card, spec)
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
preprocessCardSpec(spec)
local card = DefensiveRide:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
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
readCardSpecToCard(card, spec)
readCardSpecToEquip(card, spec)
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
preprocessCardSpec(spec)
local card = OffensiveRide:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
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
readCardSpecToCard(card, spec)
readCardSpecToEquip(card, spec)
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
preprocessCardSpec(spec)
local card = Treasure:new(spec.name, spec.suit, spec.number)
card.skill = spec.skill or defaultCardSkill
card.special_skills = spec.special_skills
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
readCardSpecToCard(card, spec)
readCardSpecToEquip(card, spec)
return card
end

View File

@ -17,8 +17,8 @@ json = require "json"
math.randomseed(os.time())
-- 加载实用类让Lua编写起来更轻松。
local GroupUtils = require "core.util"
TargetGroup, AimGroup = table.unpack(GroupUtils)
local Utils = require "core.util"
TargetGroup, AimGroup, Util = table.unpack(Utils)
dofile "lua/core/debug.lua"
-- 加载游戏核心类

View File

@ -1,5 +1,36 @@
-- 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)
local player, num, reason, skillName, damageStruct = table.unpack(self.data)
local self = self.room
@ -25,32 +56,7 @@ GameEvent.functions[GameEvent.ChangeHp] = function(self)
self:broadcastProperty(player, "hp")
if reason == "damage" then
local damage_nature_table = {
[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,
})
sendDamageLog(self, damageStruct)
elseif reason == "loseHp" then
self:sendLog{
type = "#LoseHP",
@ -125,9 +131,22 @@ GameEvent.functions[GameEvent.Damage] = function(self)
return false
end
if not self:changeHp(damageStruct.to, -damageStruct.damage, "damage", damageStruct.skillName, damageStruct) then
-- 先扣减护甲,再扣体力值
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
stages = {
{fk.Damage, damageStruct.from},

View File

@ -122,6 +122,7 @@ function GameLogic:prepareForStart()
local general = Fk.generals[p.general]
p.maxHp = general.maxHp
p.hp = general.hp
p.shield = general.shield
-- TODO: setup AI here
if p.role ~= "lord" then
@ -132,6 +133,7 @@ function GameLogic:prepareForStart()
end
room:broadcastProperty(p, "maxHp")
room:broadcastProperty(p, "hp")
room:broadcastProperty(p, "shield")
end
local allCardIds = Fk:getAllCardIds()

View File

@ -1882,6 +1882,39 @@ function Room:responseCard(cardResponseEvent)
return execGameEvent(GameEvent.RespondCard, cardResponseEvent)
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)
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 num integer @ 失去的数量

View File

@ -141,6 +141,7 @@ function ServerPlayer:marshal(player)
room:notifyProperty(player, self, "maxHp")
room:notifyProperty(player, self, "hp")
room:notifyProperty(player, self, "shield")
room:notifyProperty(player, self, "gender")
room:notifyProperty(player, self, "kingdom")

View File

@ -51,6 +51,7 @@
fk.NormalDamage = 1
fk.ThunderDamage = 2
fk.FireDamage = 3
fk.IceDamage = 4
--- DamageStruct 用来描述和伤害事件有关的数据。
---@class DamageStruct

View File

@ -27,6 +27,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{
local thunderSlash = fk.CreateBasicCard{
name = "thunder__slash",
skill = thunderSlashSkill,
is_damage_card = true,
}
extension:addCards{
@ -64,6 +65,7 @@ local fireSlashSkill = fk.CreateActiveSkill{
local fireSlash = fk.CreateBasicCard{
name = "fire__slash",
skill = fireSlashSkill,
is_damage_card = true,
}
extension:addCards{
@ -259,6 +261,7 @@ local fireAttackSkill = fk.CreateActiveSkill{
local fireAttack = fk.CreateTrickCard{
name = "fire_attack",
skill = fireAttackSkill,
is_damage_card = true,
}
extension:addCards{
fireAttack:clone(Card.Heart, 2),

View File

@ -37,6 +37,7 @@ local slash = fk.CreateBasicCard{
name = "slash",
number = 7,
suit = Card.Spade,
is_damage_card = true,
skill = slashSkill,
}
@ -310,6 +311,7 @@ local duel = fk.CreateTrickCard{
name = "duel",
suit = Card.Spade,
number = 1,
is_damage_card = true,
skill = duelSkill,
}
@ -452,6 +454,7 @@ local savageAssault = fk.CreateTrickCard{
name = "savage_assault",
suit = Card.Spade,
number = 7,
is_damage_card = true,
skill = savageAssaultSkill,
}
@ -499,6 +502,7 @@ local archeryAttack = fk.CreateTrickCard{
name = "archery_attack",
suit = Card.Heart,
number = 1,
is_damage_card = true,
skill = archeryAttackSkill,
}

View File

@ -63,11 +63,11 @@ local test_active = fk.CreateActiveSkill{
return true
end,
card_filter = function(self, card)
if self.interaction.data == "joy" then
-- if self.interaction.data == "joy" then
--local c = Fk:getCardById(card)
--return Self:getPileNameOfId(card) == self.name and c.color == Card.Red
return true
end
-- end
end,
card_num = 2,
target_filter = function() return true end,
@ -86,11 +86,12 @@ local test_active = fk.CreateActiveSkill{
-- room:takeAG(from, id)
-- room:delay(2000)
-- room:closeAG(from)
local cards = room:askForCardsChosen(from, from, 2, 3, "hej", "")
from:addToPile(self.name, cards)
from.kingdom = "wei"
room:broadcastProperty(from, "kingdom")
-- local cards = room:askForCardsChosen(from, from, 2, 3, "hej", "")
-- from:addToPile(self.name, cards)
-- from.kingdom = "wei"
-- room:broadcastProperty(from, "kingdom")
-- p(cards)
room:useVirtualCard("slash", nil, from, room:getOtherPlayers(from), self.name, true)
end,
}
local test_vs = fk.CreateViewAsSkill{
@ -98,7 +99,8 @@ local test_vs = fk.CreateViewAsSkill{
card_filter = function(self, to_select, selected)
return #selected == 0
end,
interaction = UI.ComboBox {
interaction = function(self)
return UI.ComboBox {
choices = {
"ex_nihilo",
"duel",
@ -107,7 +109,8 @@ local test_vs = fk.CreateViewAsSkill{
"savage_assault",
"archery_attack",
}
},
}
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
@ -120,6 +123,7 @@ local test_vs = fk.CreateViewAsSkill{
end,
}
local test2 = General(extension, "mouxusheng", "wu", 4, 4, General.Female)
test2.shield = 4
test2:addSkill("rende")
test2:addSkill(cheat)
test2:addSkill(test_active)

View File

@ -192,6 +192,7 @@ Item {
netstate: model.netstate
maxHp: model.maxHp
hp: model.hp
shield: model.shield
seatNumber: model.seatNumber
dead: model.dead
dying: model.dying
@ -256,6 +257,7 @@ Item {
self.kingdom: dashboardModel.kingdom
self.netstate: dashboardModel.netstate
self.maxHp: dashboardModel.maxHp
self.shield: dashboardModel.shield
self.hp: dashboardModel.hp
self.seatNumber: dashboardModel.seatNumber
self.dead: dashboardModel.dead
@ -785,6 +787,7 @@ Item {
netstate: "online",
maxHp: 0,
hp: 0,
shield: 0,
seatNumber: 1,
dead: false,
dying: false,
@ -808,6 +811,7 @@ Item {
netstate: "online",
maxHp: 0,
hp: 0,
shield: 0,
seatNumber: i + 1,
dead: false,
dying: false,

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import "PhotoElement"
import "../skin-bank.js" as SkinBank
/* Layout of general card:
@ -18,6 +19,7 @@ CardItem {
property string kingdom
property int hp
property int maxHp
property int shieldNum
property string pkgName: ""
name: ""
// description: Sanguosha.getGeneralDescription(name)
@ -40,6 +42,7 @@ CardItem {
y: 4
spacing: 1
Repeater {
id: hpRepeater
model: (hp > 5 || hp !== maxHp) ? 1 : hp
Image {
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 {
width: 20
height: 80
@ -114,6 +125,7 @@ CardItem {
kingdom = data.kingdom;
hp = data.hp;
maxHp = data.maxHp;
shieldNum = data.shield;
let splited = name.split("__");
if (splited.length > 1) {

View File

@ -20,6 +20,7 @@ Item {
property alias handcards: handcardAreaItem.length
property int maxHp: 0
property int hp: 0
property int shield: 0
property int seatNumber: 1
property bool dead: false
property bool dying: false
@ -150,6 +151,7 @@ Item {
x: 8
value: root.hp
maxValue: root.maxHp
shieldNum: root.shield
anchors.bottom: parent.bottom
anchors.bottomMargin: 36
}

View File

@ -2,23 +2,31 @@
import QtQuick
import ".."
import "../../skin-bank.js" as SkinBank
Column {
id: root
property int maxValue: 4
property int value: 4
property var colors: ["#F4180E", "#F4180E", "#E3B006", "#25EC27"]
property int shieldNum: 0
Shield {
id: shield
value: shieldNum
}
Repeater {
id: repeater
model: maxValue <= 4 ? maxValue : 0
model: column.visible ? 0 : maxValue
Magatama {
state: (maxValue - 1 - index) >= value ? 0 : (value >= 3 || value >= maxValue ? 3 : (value <= 0 ? 0 : value))
}
}
Column {
visible: maxValue > 4
id: column
visible: maxValue > 4 || value > maxValue || (shieldNum > 0 && maxValue > 3)
spacing: -4
Magatama {
@ -43,11 +51,15 @@ Column {
GlowText {
id: splitter
height: 12
width: root.width
text: "/"
z: -10
rotation: 40
color: hpItem.color
font: hpItem.font
font.family: fontLibian.name
font.pixelSize: 14
font.bold: true
horizontalAlignment: hpItem.horizontalAlignment
glow.color: hpItem.glow.color

View 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
}
}