parent
9ec500f82c
commit
16b6800811
|
@ -466,6 +466,19 @@ fk.client_callback["MoveCards"] = function(jsonData)
|
|||
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
||||
end
|
||||
|
||||
fk.client_callback["ShowCard"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
local from = data.from
|
||||
local cards = data.cards
|
||||
ClientInstance:notifyUI("MoveCards", json.encode{
|
||||
{
|
||||
ids = cards,
|
||||
fromArea = Card.DrawPile,
|
||||
toArea = Card.Processing,
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
fk.client_callback["LoseSkill"] = function(jsonData)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
|
|
|
@ -115,6 +115,10 @@ function GetCards(pack_name)
|
|||
return json.encode(ret)
|
||||
end
|
||||
|
||||
function GetCardSpecialSkills(cid)
|
||||
return json.encode(Fk:getCardById(cid).special_skills or {})
|
||||
end
|
||||
|
||||
function DistanceTo(from, to)
|
||||
local a = ClientInstance:getPlayerById(from)
|
||||
local b = ClientInstance:getPlayerById(to)
|
||||
|
|
|
@ -127,6 +127,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["PlayCard"] = "出牌",
|
||||
|
||||
["AskForCardChosen"] = "选牌",
|
||||
["AskForCardsChosen"] = "选牌",
|
||||
["#AskForChooseCard"] = "%1:请选择其一张卡牌",
|
||||
["$ChooseCard"] = "请选择一张卡牌",
|
||||
["$Hand"] = "手牌区",
|
||||
|
@ -202,6 +203,8 @@ Fk:loadTranslationTable{
|
|||
["$InstallEquip"] = "%from 装备了 %card",
|
||||
["$UninstallEquip"] = "%from 卸载了 %card",
|
||||
|
||||
["#ShowCard"] = "%from 展示了牌 %card",
|
||||
|
||||
-- phase
|
||||
["#PhaseSkipped"] = "%from 跳过了 %arg",
|
||||
["#GainAnExtraTurn"] = "%from 开始进行一个额外的回合",
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
---@field area CardArea
|
||||
---@field subcards integer[]
|
||||
---@field skillName string @ for virtual cards
|
||||
---@field skill Skill
|
||||
---@field special_skills string[] | nil
|
||||
local Card = class("Card")
|
||||
|
||||
---@alias Suit integer
|
||||
|
@ -88,6 +90,7 @@ end
|
|||
function Card:clone(suit, number)
|
||||
local newCard = self.class:new(self.name, suit, number)
|
||||
newCard.skill = self.skill
|
||||
newCard.special_skills = self.special_skills
|
||||
newCard.equip_skill = self.equip_skill
|
||||
return newCard
|
||||
end
|
||||
|
|
|
@ -344,6 +344,7 @@ function fk.CreateBasicCard(spec)
|
|||
|
||||
local card = BasicCard:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
card.special_skills = spec.special_skills
|
||||
return card
|
||||
end
|
||||
|
||||
|
@ -358,6 +359,7 @@ function fk.CreateTrickCard(spec)
|
|||
|
||||
local card = TrickCard:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
card.special_skills = spec.special_skills
|
||||
return card
|
||||
end
|
||||
|
||||
|
@ -372,6 +374,7 @@ function fk.CreateDelayedTrickCard(spec)
|
|||
|
||||
local card = DelayedTrickCard:new(spec.name, spec.suit, spec.number)
|
||||
card.skill = spec.skill or defaultCardSkill
|
||||
card.special_skills = spec.special_skills
|
||||
return card
|
||||
end
|
||||
|
||||
|
@ -387,6 +390,7 @@ function fk.CreateWeapon(spec)
|
|||
|
||||
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
|
||||
|
@ -406,6 +410,7 @@ 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
|
||||
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
|
||||
|
@ -423,6 +428,7 @@ function fk.CreateDefensiveRide(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
|
||||
|
@ -441,6 +447,7 @@ function fk.CreateOffensiveRide(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
|
||||
|
@ -459,6 +466,7 @@ function fk.CreateTreasure(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
|
||||
|
|
|
@ -750,18 +750,21 @@ end
|
|||
---@param maxNum integer
|
||||
---@param includeEquip boolean
|
||||
---@param skillName string
|
||||
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable)
|
||||
---@param pattern string
|
||||
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern)
|
||||
if minNum < 1 then
|
||||
return nil
|
||||
end
|
||||
cancelable = cancelable or false
|
||||
pattern = pattern or ""
|
||||
|
||||
local toDiscard = {}
|
||||
local data = {
|
||||
num = maxNum,
|
||||
min_num = minNum,
|
||||
include_equip = includeEquip,
|
||||
reason = skillName
|
||||
reason = skillName,
|
||||
pattern = pattern,
|
||||
}
|
||||
local prompt = "#AskForDiscard:::" .. maxNum .. ":" .. minNum
|
||||
local _, ret = self:askForUseActiveSkill(player, "discard_skill", prompt, cancelable, data)
|
||||
|
@ -817,18 +820,21 @@ end
|
|||
---@param includeEquip boolean
|
||||
---@param skillName string
|
||||
---@param cancelable boolean
|
||||
function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancelable)
|
||||
---@param pattern string
|
||||
function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern)
|
||||
if minNum < 1 then
|
||||
return nil
|
||||
end
|
||||
cancelable = cancelable or false
|
||||
pattern = pattern or ""
|
||||
|
||||
local chosenCards = {}
|
||||
local data = {
|
||||
num = maxNum,
|
||||
min_num = minNum,
|
||||
include_equip = includeEquip,
|
||||
reason = skillName
|
||||
reason = skillName,
|
||||
pattern = pattern,
|
||||
}
|
||||
local prompt = "#askForCard:::" .. maxNum .. ":" .. minNum
|
||||
local _, ret = self:askForUseActiveSkill(player, "choose_cards_skill", prompt, cancelable, data)
|
||||
|
@ -1078,6 +1084,16 @@ function Room:handleUseCardReply(player, data)
|
|||
end
|
||||
end
|
||||
else
|
||||
if data.special_skill then
|
||||
local skill = Fk.skills[data.special_skill]
|
||||
assert(skill:isInstanceOf(ActiveSkill))
|
||||
skill:onUse(self, {
|
||||
from = player.id,
|
||||
cards = { card },
|
||||
tos = targets,
|
||||
})
|
||||
return nil
|
||||
end
|
||||
local use = {} ---@type CardUseStruct
|
||||
use.from = player.id
|
||||
use.tos = {}
|
||||
|
|
|
@ -290,6 +290,20 @@ function ServerPlayer:turnOver()
|
|||
self.room.logic:trigger(fk.TurnedOver, self)
|
||||
end
|
||||
|
||||
function ServerPlayer:showCards(cards)
|
||||
cards = Card:getIdList(cards)
|
||||
local room = self.room
|
||||
room:sendLog{
|
||||
type = "#ShowCard",
|
||||
from = self.id,
|
||||
card = cards,
|
||||
}
|
||||
room:doBroadcastNotify("ShowCard", json.encode{
|
||||
from = self.id,
|
||||
cards = cards,
|
||||
})
|
||||
end
|
||||
|
||||
---@param from_phase Phase
|
||||
---@param to_phase Phase
|
||||
function ServerPlayer:changePhase(from_phase, to_phase)
|
||||
|
|
|
@ -199,6 +199,8 @@ local ironChainCardSkill = fk.CreateActiveSkill{
|
|||
local ironChain = fk.CreateTrickCard{
|
||||
name = "iron_chain",
|
||||
skill = ironChainCardSkill,
|
||||
-- FIXME! FIXME! FIXME!
|
||||
special_skills = { "zhiheng" },
|
||||
}
|
||||
extension:addCards{
|
||||
ironChain:clone(Card.Spade, 11),
|
||||
|
@ -209,6 +211,45 @@ extension:addCards{
|
|||
ironChain:clone(Card.Club, 13),
|
||||
}
|
||||
|
||||
local fireAttackSkill = fk.CreateActiveSkill{
|
||||
name = "fire_attack_skill",
|
||||
target_num = 1,
|
||||
target_filter = function(self, to_select)
|
||||
return not Fk:currentRoom():getPlayerById(to_select):isKongcheng()
|
||||
end,
|
||||
on_effect = function(self, room, cardEffectEvent)
|
||||
local from = room:getPlayerById(cardEffectEvent.from)
|
||||
local to = room:getPlayerById(cardEffectEvent.to)
|
||||
if to:isKongcheng() then return end
|
||||
|
||||
local showCard = room:askForCard(to, 1, 1, false, self.name, false)[1]
|
||||
to:showCards(showCard)
|
||||
|
||||
showCard = Fk:getCardById(showCard)
|
||||
local cards = room:askForDiscard(from, 1, 1, false, self.name, true,
|
||||
".|.|" .. showCard:getSuitString())
|
||||
if #cards > 0 then
|
||||
room:damage({
|
||||
from = from,
|
||||
to = to,
|
||||
card = cardEffectEvent.card,
|
||||
damage = 1,
|
||||
damageType = fk.FireDamage,
|
||||
skillName = self.name
|
||||
})
|
||||
end
|
||||
end,
|
||||
}
|
||||
local fireAttack = fk.CreateTrickCard{
|
||||
name = "fire_attack",
|
||||
skill = fireAttackSkill,
|
||||
}
|
||||
extension:addCards{
|
||||
fireAttack:clone(Card.Heart, 2),
|
||||
fireAttack:clone(Card.Heart, 3),
|
||||
fireAttack:clone(Card.Diamond, 12),
|
||||
}
|
||||
|
||||
local supplyShortageSkill = fk.CreateActiveSkill{
|
||||
name = "supply_shortage_skill",
|
||||
distance_limit = 1,
|
||||
|
@ -390,6 +431,9 @@ Fk:loadTranslationTable{
|
|||
["fire__slash"] = "火杀",
|
||||
["analeptic"] = "酒",
|
||||
["iron_chain"] = "铁锁连环",
|
||||
["_normal_use"] = "正常使用",
|
||||
["recast"] = "重铸",
|
||||
["fire_attack"] = "火攻",
|
||||
["supply_shortage"] = "兵粮寸断",
|
||||
["guding_blade"] = "古锭刀",
|
||||
["vine"] = "藤甲",
|
||||
|
|
|
@ -5,11 +5,15 @@ local discardSkill = fk.CreateActiveSkill{
|
|||
return false
|
||||
end
|
||||
|
||||
local checkpoint = true
|
||||
if not self.include_equip then
|
||||
return Fk:currentRoom():getCardArea(to_select) ~= Player.Equip
|
||||
checkpoint = checkpoint and (Fk:currentRoom():getCardArea(to_select) ~= Player.Equip)
|
||||
end
|
||||
|
||||
return true
|
||||
if self.pattern ~= "" then
|
||||
checkpoint = checkpoint and (Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)))
|
||||
end
|
||||
return checkpoint
|
||||
end,
|
||||
min_card_num = function(self) return self.min_num end,
|
||||
max_card_num = function(self) return self.num end,
|
||||
|
@ -17,17 +21,7 @@ local discardSkill = fk.CreateActiveSkill{
|
|||
|
||||
local chooseCardsSkill = fk.CreateActiveSkill{
|
||||
name = "choose_cards_skill",
|
||||
card_filter = function(self, to_select, selected)
|
||||
if #selected >= self.num then
|
||||
return false
|
||||
end
|
||||
|
||||
if not self.include_equip then
|
||||
return Fk:currentRoom():getCardArea(to_select) ~= Player.Equip
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
card_filter = discardSkill.cardFilter,
|
||||
min_card_num = function(self) return self.min_num end,
|
||||
max_card_num = function(self) return self.num end,
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ Fk:loadTranslationTable{
|
|||
["god_salvation"] = "桃园结义",
|
||||
|
||||
["amazing_grace"] = "五谷丰登",
|
||||
["amazing_grace_skill"] = "五谷选牌",
|
||||
|
||||
["lightning"] = "闪电",
|
||||
|
||||
|
|
|
@ -263,6 +263,14 @@ Item {
|
|||
|
||||
onCardSelected: function(card) {
|
||||
Logic.enableTargets(card);
|
||||
|
||||
if (typeof card === "number" && card !== -1 && roomScene.state === "playing") {
|
||||
let skills = JSON.parse(Backend.callLuaFunction("GetCardSpecialSkills", [card]));
|
||||
skills.unshift("_normal_use");
|
||||
specialCardSkills.model = skills;
|
||||
} else {
|
||||
specialCardSkills.model = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,6 +340,41 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 8
|
||||
anchors.right: okCancel.left
|
||||
anchors.rightMargin: 20
|
||||
color: "#88EEEEEE"
|
||||
radius: 8
|
||||
visible: roomScene.state == "playing" && specialCardSkills.count > 1
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height - 20
|
||||
|
||||
RowLayout {
|
||||
y: -10
|
||||
Repeater {
|
||||
id: specialCardSkills
|
||||
RadioButton {
|
||||
property string orig_text: modelData
|
||||
text: Backend.translate(modelData)
|
||||
checked: index === 0
|
||||
onCheckedChanged: {
|
||||
if (modelData === "_normal_use") {
|
||||
Logic.enableTargets(dashboard.selected_card);
|
||||
} else {
|
||||
Logic.enableTargets(JSON.stringify({
|
||||
skill: modelData,
|
||||
subcards: [dashboard.selected_card],
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
id: okCancel
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -574,6 +617,17 @@ Item {
|
|||
onActivated: Logic.doCancelButton();
|
||||
}
|
||||
|
||||
function getCurrentCardUseMethod() {
|
||||
for (let i = 1; i < specialCardSkills.count; i++) {
|
||||
let item = specialCardSkills.itemAt(i);
|
||||
if (item.checked) {
|
||||
let ret = item.orig_text;
|
||||
console.log(ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addToChat(pid, raw, msg) {
|
||||
chat.append(msg);
|
||||
let photo = Logic.getPhotoOrSelf(pid);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ".."
|
||||
|
||||
GraphicsBox {
|
||||
|
@ -11,18 +12,20 @@ GraphicsBox {
|
|||
width: Math.max(140, body.width + 20)
|
||||
height: body.height + title.height + 20
|
||||
|
||||
Column {
|
||||
GridLayout {
|
||||
id: body
|
||||
x: 10
|
||||
y: title.height + 5
|
||||
spacing: 10
|
||||
flow: GridLayout.TopToBottom
|
||||
rows: 8
|
||||
columnSpacing: 10
|
||||
|
||||
Repeater {
|
||||
model: options
|
||||
|
||||
MetroButton {
|
||||
Layout.fillWidth: true
|
||||
text: Backend.translate(modelData)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
onClicked: {
|
||||
result = index;
|
||||
|
|
|
@ -68,7 +68,8 @@ function doOkButton() {
|
|||
replyToServer(JSON.stringify(
|
||||
{
|
||||
card: dashboard.getSelectedCard(),
|
||||
targets: selected_targets
|
||||
targets: selected_targets,
|
||||
special_skill: roomScene.getCurrentCardUseMethod(),
|
||||
}
|
||||
));
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue