standard equip skills (#49)
* install and uninstall equip skill * complete pr; filter skill viewAs equip --------- Co-authored-by: notify <notify-ctrl@qq.com>
This commit is contained in:
parent
cc271bcdf8
commit
3fe92b4344
|
@ -83,7 +83,9 @@ function Client:moveCards(moves)
|
|||
table.insert(self.discard_pile, move.ids[1])
|
||||
end
|
||||
|
||||
Fk:filterCard(move.ids[1], move.to == Self.id and Self or nil)
|
||||
if (move.ids[1] ~= -1) then
|
||||
Fk:filterCard(move.ids[1], ClientInstance:getPlayerById(move.to))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ end
|
|||
function Card:clone(suit, number)
|
||||
local newCard = self.class:new(self.name, suit, number)
|
||||
newCard.skill = self.skill
|
||||
newCard.equip_skill = self.equip_skill
|
||||
return newCard
|
||||
end
|
||||
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
---@class EquipCard : Card
|
||||
---@field equipSkill Skill
|
||||
---@field equip_skill Skill
|
||||
local EquipCard = Card:subclass("EquipCard")
|
||||
|
||||
function EquipCard:initialize(name, suit, number)
|
||||
Card.initialize(self, name, suit, number)
|
||||
self.type = Card.TypeEquip
|
||||
self.equipSkill = nil
|
||||
self.equip_skill = nil
|
||||
end
|
||||
|
||||
---@param room Room
|
||||
---@param player Player
|
||||
function EquipCard:onInstall(room, player)
|
||||
if self.equip_skill then
|
||||
room:handleAddLoseSkills(player, self.equip_skill.name, nil, false, true)
|
||||
end
|
||||
end
|
||||
|
||||
---@param room Room
|
||||
---@param player Player
|
||||
function EquipCard:onUninstall(room, player)
|
||||
if self.equip_skill then
|
||||
room:handleAddLoseSkills(player, "-" .. self.equip_skill.name, nil, false, true)
|
||||
end
|
||||
end
|
||||
|
||||
---@class Weapon : EquipCard
|
||||
|
|
|
@ -460,27 +460,10 @@ local function getActualSkill(skill)
|
|||
return skill
|
||||
end
|
||||
|
||||
---@param skill string | Skill
|
||||
function Player:hasEquipSkill(skill)
|
||||
skill = getActualSkill(skill)
|
||||
local equips = self.player_cards[Player.Equip]
|
||||
for _, id in ipairs(equips) do
|
||||
local card = Fk:getCardById(id)
|
||||
if card.skill == skill then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param skill string | Skill
|
||||
function Player:hasSkill(skill)
|
||||
skill = getActualSkill(skill)
|
||||
|
||||
if self:hasEquipSkill(skill) then
|
||||
return true
|
||||
end
|
||||
|
||||
if table.contains(self.player_skills, skill) then
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
---@field mute boolean
|
||||
---@field anim_type string
|
||||
---@field related_skills Skill[]
|
||||
---@field attached_equip string
|
||||
local Skill = class("Skill")
|
||||
|
||||
---@alias Frequency integer
|
||||
|
@ -32,6 +33,8 @@ function Skill:initialize(name, frequency)
|
|||
if string.sub(name, 1, 1) == "#" then
|
||||
self.visible = false
|
||||
end
|
||||
|
||||
self.attached_equip = nil
|
||||
end
|
||||
|
||||
---@param skill Skill
|
||||
|
@ -39,4 +42,9 @@ function Skill:addRelatedSkill(skill)
|
|||
table.insert(self.related_skills, skill)
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
function Skill:isEquipmentSkill()
|
||||
return self.attached_equip and type(self.attached_equip) == 'string' and self.attached_equip ~= ""
|
||||
end
|
||||
|
||||
return Skill
|
||||
|
|
|
@ -90,15 +90,17 @@ function fk.CreateTriggerSkill(spec)
|
|||
skill.refresh = spec.on_refresh
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
|
||||
if not spec.priority then
|
||||
if frequency == Skill.Wake then
|
||||
spec.priority = 3
|
||||
elseif frequency == Skill.Compulsory then
|
||||
spec.priority = 2
|
||||
else
|
||||
spec.priority = 0.1
|
||||
end
|
||||
elseif not spec.priority then
|
||||
spec.priority = 1
|
||||
end
|
||||
end
|
||||
|
||||
if type(spec.priority) == "number" then
|
||||
for _, event in ipairs(skill.events) do
|
||||
skill.priority_table[event] = spec.priority
|
||||
|
@ -137,6 +139,11 @@ function fk.CreateActiveSkill(spec)
|
|||
}
|
||||
skill.distance_limit = spec.distance_limit or skill.distance_limit
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
if spec.can_use then skill.canUse = spec.can_use end
|
||||
if spec.card_filter then skill.cardFilter = spec.card_filter end
|
||||
if spec.target_filter then skill.targetFilter = spec.target_filter end
|
||||
|
@ -173,6 +180,11 @@ function fk.CreateViewAsSkill(spec)
|
|||
}
|
||||
skill.distance_limit = spec.distance_limit or skill.distance_limit
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
skill.viewAs = spec.view_as
|
||||
if spec.card_filter then
|
||||
skill.cardFilter = spec.card_filter
|
||||
|
@ -205,6 +217,11 @@ function fk.CreateDistanceSkill(spec)
|
|||
skill.global = spec.global
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
@ -223,6 +240,11 @@ function fk.CreateProhibitSkill(spec)
|
|||
skill.global = spec.global
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
@ -241,6 +263,11 @@ function fk.CreateAttackRangeSkill(spec)
|
|||
skill.global = spec.global
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
@ -265,6 +292,11 @@ function fk.CreateMaxCardsSkill(spec)
|
|||
skill.global = spec.global
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
@ -292,6 +324,11 @@ function fk.CreateTargetModSkill(spec)
|
|||
skill.global = spec.global
|
||||
end
|
||||
|
||||
if spec.attached_equip then
|
||||
assert(type(spec.attached_equip) == "string")
|
||||
skill.attached_equip = spec.attached_equip
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
@ -382,6 +419,10 @@ function fk.CreateWeapon(spec)
|
|||
|
||||
local card = Weapon:new(spec.name, spec.suit, spec.number, spec.attack_range)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -396,6 +437,10 @@ function fk.CreateArmor(spec)
|
|||
|
||||
local card = Armor:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -410,6 +455,10 @@ function fk.CreateDefensiveRide(spec)
|
|||
|
||||
local card = DefensiveRide:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -424,6 +473,10 @@ function fk.CreateOffensiveRide(spec)
|
|||
|
||||
local card = OffensiveRide:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -438,5 +491,9 @@ function fk.CreateTreasure(spec)
|
|||
|
||||
local card = Treasure:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
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
|
||||
end
|
||||
|
|
|
@ -1660,6 +1660,19 @@ function Room:moveCards(...)
|
|||
end
|
||||
self:setCardArea(info.cardId, data.toArea, data.to)
|
||||
Fk:filterCard(info.cardId, self:getPlayerById(data.to))
|
||||
|
||||
local currentCard = Fk:getCardById(info.cardId)
|
||||
if
|
||||
data.toArea == Player.Equip and
|
||||
currentCard.type == Card.TypeEquip and
|
||||
data.to ~= nil and
|
||||
self:getPlayerById(data.to):isAlive() and
|
||||
currentCard.equip_skill
|
||||
then
|
||||
currentCard:onInstall(self, self:getPlayerById(data.to))
|
||||
elseif realFromArea == Player.Equip and currentCard.type == Card.TypeEquip and data.from ~= nil and currentCard.equip_skill then
|
||||
currentCard:onUninstall(self, self:getPlayerById(data.from))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2032,8 +2045,9 @@ end
|
|||
|
||||
---@param player ServerPlayer
|
||||
---@param skill_names string[] | string
|
||||
---@param source_skill string | Skill | nil
|
||||
function Room:handleAddLoseSkills(player, skill_names, source_skill, sendlog)
|
||||
---@param source_skill string | Skill | null
|
||||
---@param no_trigger boolean | null
|
||||
function Room:handleAddLoseSkills(player, skill_names, source_skill, sendlog, no_trigger)
|
||||
if type(skill_names) == "string" then
|
||||
skill_names = skill_names:split("|")
|
||||
end
|
||||
|
@ -2094,7 +2108,7 @@ function Room:handleAddLoseSkills(player, skill_names, source_skill, sendlog)
|
|||
end
|
||||
end
|
||||
|
||||
if #triggers > 0 then
|
||||
if (not no_trigger) and #triggers > 0 then
|
||||
for i = 1, #triggers do
|
||||
local event = losts[i] and fk.EventLoseSkill or fk.EventAcquireSkill
|
||||
self.logic:trigger(event, player, triggers[i])
|
||||
|
|
|
@ -722,11 +722,24 @@ extension:addCards({
|
|||
indulgence:clone(Card.Heart, 6),
|
||||
})
|
||||
|
||||
local crossbowSkill = fk.CreateTargetModSkill{
|
||||
name = "#crossbow_skill",
|
||||
attached_equip = "crossbow",
|
||||
residue_func = function(self, player, skill, scope)
|
||||
if player:hasSkill(self.name) and skill.name == "slash_skill"
|
||||
and scope == Player.HistoryPhase then
|
||||
return 999
|
||||
end
|
||||
end,
|
||||
}
|
||||
Fk:addSkill(crossbowSkill)
|
||||
|
||||
local crossbow = fk.CreateWeapon{
|
||||
name = "crossbow",
|
||||
suit = Card.Club,
|
||||
number = 1,
|
||||
attack_range = 1,
|
||||
equip_skill = crossbowSkill,
|
||||
}
|
||||
Fk:loadTranslationTable{
|
||||
["crossbow"] = "诸葛连弩",
|
||||
|
|
|
@ -1,22 +1,73 @@
|
|||
local fkp_extensions = require "packages.test.test"
|
||||
local extension = fkp_extensions[1]
|
||||
|
||||
local cheat = fk.CreateActiveSkill{
|
||||
name = "cheat",
|
||||
anim_type = "drawcard",
|
||||
can_use = function(self, player)
|
||||
return true
|
||||
end,
|
||||
feasible = function(self, selected, selected_cards)
|
||||
return #selected == 0 and #selected_cards == 0
|
||||
end,
|
||||
on_use = function(self, room, effect)
|
||||
local from = room:getPlayerById(effect.from)
|
||||
local cardTypeName = room:askForChoice(from, { 'BasicCard', 'TrickCard', 'Equip' }, "cheat")
|
||||
local cardType = Card.TypeBasic
|
||||
if cardTypeName == 'TrickCard' then
|
||||
cardType = Card.TypeTrick
|
||||
elseif cardTypeName == 'Equip' then
|
||||
cardType = Card.TypeEquip
|
||||
end
|
||||
|
||||
local allCardIds = Fk:getAllCardIds()
|
||||
local allCardMapper = {}
|
||||
local allCardNames = {}
|
||||
for _, id in ipairs(allCardIds) do
|
||||
local card = Fk:getCardById(id)
|
||||
if card.type == cardType then
|
||||
if allCardMapper[card.name] == nil then
|
||||
table.insert(allCardNames, card.name)
|
||||
end
|
||||
|
||||
allCardMapper[card.name] = allCardMapper[card.name] or {}
|
||||
table.insert(allCardMapper[card.name], id)
|
||||
end
|
||||
end
|
||||
|
||||
if #allCardNames == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local cardName = room:askForChoice(from, allCardNames, "cheat")
|
||||
local toGain = nil
|
||||
if #allCardMapper[cardName] > 0 then
|
||||
toGain = allCardMapper[cardName][math.random(1, #allCardMapper[cardName])]
|
||||
end
|
||||
|
||||
room:obtainCard(effect.from, toGain, true, fk.ReasonPrey)
|
||||
end
|
||||
}
|
||||
local test_filter = fk.CreateFilterSkill{
|
||||
name = "test_filter",
|
||||
card_filter = function(self, card)
|
||||
return true
|
||||
return card.number > 11
|
||||
end,
|
||||
view_as = function(self, card)
|
||||
return Fk:cloneCard("ex_nihilo", card.suit, card.number)
|
||||
return Fk:cloneCard("crossbow", card.suit, card.number)
|
||||
end,
|
||||
}
|
||||
local test2 = General(extension, "mouxusheng", "wu", 4)
|
||||
test2:addSkill(test_filter)
|
||||
test2:addSkill(cheat)
|
||||
|
||||
Fk:loadTranslationTable{
|
||||
["test"] = "测试",
|
||||
["test_filter"] = "破军",
|
||||
[":test_filter"] = "你的点数大于11的牌视为无中生有。",
|
||||
["mouxusheng"] = "谋徐盛",
|
||||
--["cheat"] = "开挂",
|
||||
[":cheat"] = "出牌阶段,你可以获得一张想要的牌。",
|
||||
}
|
||||
|
||||
return fkp_extensions
|
||||
|
|
|
@ -24,6 +24,8 @@ Item {
|
|||
for (let i = 0; i < cards.length; i++) {
|
||||
for (let j = 0; j < outputs.length; j++) {
|
||||
if (outputs[j] === cards[i].cid) {
|
||||
let state = JSON.parse(Backend.callLuaFunction("GetCardData", [cards[i].cid]));
|
||||
cards[i].setData(state);
|
||||
result.push(cards[i]);
|
||||
cards.splice(i, 1);
|
||||
i--;
|
||||
|
|
|
@ -241,6 +241,8 @@ Item {
|
|||
suit = data.suit;
|
||||
number = data.number;
|
||||
color = data.color;
|
||||
subtype = data.subtype ? data.subtype : "";
|
||||
virt_name = data.virt_name ? data.virt_name : "";
|
||||
}
|
||||
|
||||
function toData()
|
||||
|
@ -250,7 +252,9 @@ Item {
|
|||
name: name,
|
||||
suit: suit,
|
||||
number: number,
|
||||
color: color
|
||||
color: color,
|
||||
subtype: subtype,
|
||||
virt_name: virt_name,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -122,9 +122,13 @@ Item {
|
|||
icon = "horse";
|
||||
} else {
|
||||
text = Backend.translate(name);
|
||||
if (card.virt_name) {
|
||||
icon = card.virt_name;
|
||||
} else {
|
||||
icon = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function show()
|
||||
{
|
||||
|
|
12
qml/main.qml
12
qml/main.qml
|
@ -9,6 +9,8 @@ Window {
|
|||
visible: true
|
||||
width: 960
|
||||
height: 540
|
||||
minimumWidth: 160
|
||||
minimumHeight: 90
|
||||
property var callbacks: Logic.callbacks
|
||||
|
||||
Item {
|
||||
|
@ -36,7 +38,8 @@ Item {
|
|||
StackView {
|
||||
id: mainStack
|
||||
visible: !mainWindow.busy
|
||||
initialItem: OS !== "Web" ? init : webinit
|
||||
// If error occurs during loading initialItem, the program will fall into "polish()" loop
|
||||
// initialItem: OS !== "Web" ? init : webinit
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
|
@ -151,7 +154,7 @@ Item {
|
|||
anchors.centerIn: parent
|
||||
width: Math.min(contentWidth + 24, realMainWin.width * 0.9)
|
||||
height: Math.min(contentHeight + 24, realMainWin.height * 0.9)
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
padding: 12
|
||||
contentItem: Text {
|
||||
text: errDialog.txt
|
||||
|
@ -197,6 +200,11 @@ Item {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (OS !== "Web") {
|
||||
mainStack.push(init);
|
||||
} else {
|
||||
mainStack.push(webinit);
|
||||
}
|
||||
if (OS !== "Android" && OS !== "Web") {
|
||||
width = config.winWidth;
|
||||
height = config.winHeight;
|
||||
|
|
|
@ -77,8 +77,8 @@ void QmlBackend::quitLobby()
|
|||
{
|
||||
if (ClientInstance)
|
||||
delete ClientInstance;
|
||||
if (ServerInstance)
|
||||
delete ServerInstance;
|
||||
// if (ServerInstance)
|
||||
// delete ServerInstance;
|
||||
}
|
||||
|
||||
void QmlBackend::emitNotifyUI(const QString &command, const QString &jsonData) {
|
||||
|
|
Loading…
Reference in New Issue