1. 为选项框增加all_choices,可以看到无法选择的选项
2. 体力上限减到0以下不会再死两次
3. 预判超量回复
4. 可以在摸牌前事件打断摸牌
5. 修复卡牌可以使用判断
6. 添加移动场上牌的返回值(卡牌和玩家id)
7. 修复谋徐盛的属性伤害
8. 修改选择多张牌的翻译
9. 修复变更武将的hp设置

---------

Signed-off-by: Mechanel <nyutanislavsky@qq.com>
This commit is contained in:
Nyutanislavsky 2023-07-16 15:29:20 +08:00 committed by GitHub
parent 0e8005601f
commit adafcfbae1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 62 additions and 27 deletions

View File

@ -660,6 +660,7 @@ Item {
skillInteraction.item.default_choice = data["default"]; skillInteraction.item.default_choice = data["default"];
skillInteraction.item.choices = data.choices; skillInteraction.item.choices = data.choices;
skillInteraction.item.detailed = data.detailed; skillInteraction.item.detailed = data.detailed;
skillInteraction.item.all_choices = data.all_choices;
// skillInteraction.item.clicked(); // skillInteraction.item.clicked();
break; break;
case "spin": case "spin":

View File

@ -870,14 +870,16 @@ callbacks["AskForExchange"] = (jsonData) => {
replyToServer(JSON.stringify(box.getResult())); replyToServer(JSON.stringify(box.getResult()));
}); });
} }
callbacks["AskForChoice"] = (jsonData) => { callbacks["AskForChoice"] = (jsonData) => {
// jsonData: [ string[] choices, string skill ] // jsonData: [ string[] choices, string skill ]
// TODO: multiple choices, e.g. benxi_ol // TODO: multiple choices, e.g. benxi_ol
const data = JSON.parse(jsonData); const data = JSON.parse(jsonData);
const choices = data[0]; const choices = data[0];
const skill_name = data[1]; const all_choices = data[1];
const prompt = data[2]; const skill_name = data[2];
const detailed = data[3]; const prompt = data[3];
const detailed = data[4];
if (prompt === "") { if (prompt === "") {
roomScene.promptText = Backend.translate("#AskForChoice") roomScene.promptText = Backend.translate("#AskForChoice")
.arg(Backend.translate(skill_name)); .arg(Backend.translate(skill_name));
@ -895,6 +897,7 @@ callbacks["AskForChoice"] = (jsonData) => {
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;
box.options = choices; box.options = choices;
box.skill_name = skill_name; box.skill_name = skill_name;
box.all_options = all_choices;
box.accepted.connect(() => { box.accepted.connect(() => {
replyToServer(choices[box.result]); replyToServer(choices[box.result]);
}); });
@ -970,8 +973,8 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
delayedTricks.push(card_data); delayedTricks.push(card_data);
}); });
roomScene.promptText = Backend.translate("#AskForChooseCard") roomScene.promptText = Backend.translate("#AskForChooseCards")
.arg(Backend.translate(reason)); .arg(Backend.translate(reason)).arg(min).arg(max);
roomScene.state = "replying"; roomScene.state = "replying";
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/PlayerCardBox.qml"); roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/PlayerCardBox.qml");
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;

View File

@ -6,6 +6,7 @@ import Fk.Pages
GraphicsBox { GraphicsBox {
property var options: [] property var options: []
property var all_options: []
property string skill_name: "" property string skill_name: ""
property int result property int result
@ -35,11 +36,12 @@ GraphicsBox {
columnSpacing: 10 columnSpacing: 10
Repeater { Repeater {
model: options model: all_options
MetroButton { MetroButton {
Layout.fillWidth: true Layout.fillWidth: true
text: processPrompt(modelData) text: processPrompt(modelData)
enabled: options.indexOf(modelData) !== -1
onClicked: { onClicked: {
result = index; result = index;

View File

@ -7,6 +7,7 @@ import Fk.Pages
GraphicsBox { GraphicsBox {
property var options: [] property var options: []
property var all_options: []
property string skill_name: "" property string skill_name: ""
property int result property int result
@ -25,7 +26,7 @@ GraphicsBox {
clip: true clip: true
spacing: 20 spacing: 20
model: options model: all_options
delegate: Item { delegate: Item {
width: 200 width: 200
@ -35,6 +36,7 @@ GraphicsBox {
id: choicetitle id: choicetitle
width: parent.width width: parent.width
text: Backend.translate(modelData) text: Backend.translate(modelData)
enabled: options.indexOf(modelData) !== -1
textFont.pixelSize: 24 textFont.pixelSize: 24
anchors.top: choiceDetail.bottom anchors.top: choiceDetail.bottom
anchors.topMargin: 8 anchors.topMargin: 8

View File

@ -6,7 +6,9 @@ import Fk.Pages
GraphicsBox { GraphicsBox {
id: root id: root
title.text: Backend.translate("$ChooseCard")
title.text: root.multiChoose ? Backend.translate("$ChooseCards").arg(root.min).arg(root.max) : Backend.translate("$ChooseCard")
// TODO: Adjust the UI design in case there are more than 7 cards // TODO: Adjust the UI design in case there are more than 7 cards
width: 70 + Math.min(7, Math.max(1, handcards.count, equips.count, delayedTricks.count)) * 100 width: 70 + Math.min(7, Math.max(1, handcards.count, equips.count, delayedTricks.count)) * 100
height: 50 + (handcards.count > 0 ? 150 : 0) + (equips.count > 0 ? 150 : 0) + (delayedTricks.count > 0 ? 150 : 0) height: 50 + (handcards.count > 0 ? 150 : 0) + (equips.count > 0 ? 150 : 0) + (delayedTricks.count > 0 ? 150 : 0)

View File

@ -7,6 +7,7 @@ MetroButton {
id: root id: root
property string skill property string skill
property var choices: [] property var choices: []
property var all_choices: []
property string default_choice property string default_choice
property string answer: default_choice property string answer: default_choice
property bool detailed: false property bool detailed: false
@ -42,6 +43,7 @@ MetroButton {
} }
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;
box.options = choices; box.options = choices;
box.all_options = all_choices;
box.accepted.connect(() => { box.accepted.connect(() => {
answer = choices[box.result]; answer = choices[box.result];
}); });

View File

@ -377,12 +377,14 @@ function ActiveCanUse(skill_name)
for _, m in ipairs(exp.matchers) do for _, m in ipairs(exp.matchers) do
if m.name then if m.name then
table.insertTable(cnames, m.name) table.insertTable(cnames, m.name)
elseif m.trueName then end
if m.trueName then
table.insertTable(cnames, m.trueName) table.insertTable(cnames, m.trueName)
end end
end end
for _, n in ipairs(cnames) do for _, n in ipairs(cnames) do
local c = Fk:cloneCard(n) local c = Fk:cloneCard(n)
c.skillName = skill_name
ret = c.skill:canUse(Self, c) ret = c.skill:canUse(Self, c)
if ret then break end if ret then break end
end end

View File

@ -180,7 +180,9 @@ FreeKill使用的是libgit2的C API与此同时使用Git完成拓展包的下
["AskForCardChosen"] = "选牌", ["AskForCardChosen"] = "选牌",
["AskForCardsChosen"] = "选牌", ["AskForCardsChosen"] = "选牌",
["#AskForChooseCard"] = "%1请选择其一张卡牌", ["#AskForChooseCard"] = "%1请选择其一张卡牌",
["#AskForChooseCards"] = "%1请选择其%2至%3张卡牌",
["$ChooseCard"] = "请选择一张卡牌", ["$ChooseCard"] = "请选择一张卡牌",
["$ChooseCards"] = "请选择%1至%2张卡牌",
["$Hand"] = "手牌区", ["$Hand"] = "手牌区",
["$Equip"] = "装备区", ["$Equip"] = "装备区",
["$Judge"] = "判定区", ["$Judge"] = "判定区",

View File

@ -114,7 +114,7 @@ GameEvent.functions[GameEvent.Damage] = function(self)
end end
damageStruct.damageType = damageStruct.damageType or fk.NormalDamage damageStruct.damageType = damageStruct.damageType or fk.NormalDamage
if damageStruct.from and not damageStruct.from:isAlive() then if damageStruct.from and damageStruct.from.dead then
damageStruct.from = nil damageStruct.from = nil
end end
@ -135,7 +135,7 @@ GameEvent.functions[GameEvent.Damage] = function(self)
assert(damageStruct.to:isInstanceOf(ServerPlayer)) assert(damageStruct.to:isInstanceOf(ServerPlayer))
end end
if not damageStruct.to:isAlive() then if damageStruct.to.dead then
return false return false
end end
@ -249,6 +249,7 @@ GameEvent.functions[GameEvent.Recover] = function(self)
end end
local who = recoverStruct.who local who = recoverStruct.who
if self.logic:trigger(fk.PreHpRecover, who, recoverStruct) or recoverStruct.num < 1 then if self.logic:trigger(fk.PreHpRecover, who, recoverStruct) or recoverStruct.num < 1 then
self.logic:breakEvent(false) self.logic:breakEvent(false)
end end
@ -274,8 +275,22 @@ GameEvent.functions[GameEvent.ChangeMaxHp] = function(self)
player = player.id, player = player.id,
num = num, num = num,
}) })
self:sendLog{
type = num > 0 and "#HealMaxHP" or "#LoseMaxHP",
from = player.id,
arg = num > 0 and num or - num,
}
if player.maxHp == 0 then if player.maxHp == 0 then
player.hp = 0
self:broadcastProperty(player, "hp")
self:sendLog{
type = "#ShowHPAndMaxHP",
from = player.id,
arg = 0,
arg2 = 0,
}
self:killPlayer({ who = player.id }) self:killPlayer({ who = player.id })
return false
end end
local diff = player.hp - player.maxHp local diff = player.hp - player.maxHp
@ -285,12 +300,6 @@ GameEvent.functions[GameEvent.ChangeMaxHp] = function(self)
end end
end end
self:sendLog{
type = num > 0 and "#HealMaxHP" or "#LoseMaxHP",
from = player.id,
arg = num > 0 and num or - num,
}
self:sendLog{ self:sendLog{
type = "#ShowHPAndMaxHP", type = "#ShowHPAndMaxHP",
from = player.id, from = player.id,

View File

@ -594,7 +594,7 @@ function Room:changeHero(player, new_general, full, isDeputy, sendLog)
player.maxHp = player:getGeneralMaxHp() player.maxHp = player:getGeneralMaxHp()
self:broadcastProperty(player, "maxHp") self:broadcastProperty(player, "maxHp")
if full then if full or player.hp > player.maxHp then
player.hp = player.maxHp player.hp = player.maxHp
self:broadcastProperty(player, "hp") self:broadcastProperty(player, "hp")
end end
@ -1338,15 +1338,18 @@ end
---@param choices string[] @ 可选选项列表 ---@param choices string[] @ 可选选项列表
---@param skill_name string|nil @ 技能名 ---@param skill_name string|nil @ 技能名
---@param prompt string|nil @ 提示信息 ---@param prompt string|nil @ 提示信息
---@param detailed boolean|nil @ 暂未使用 ---@param detailed boolean|nil @ 选项详细描述
---@param all_choices string[]|nil @ 所有选项(不可选变灰)
---@return string @ 选择的选项 ---@return string @ 选择的选项
function Room:askForChoice(player, choices, skill_name, prompt, detailed) function Room:askForChoice(player, choices, skill_name, prompt, detailed, all_choices)
if #choices == 1 then return choices[1] end if #choices == 1 and not all_choices then return choices[1] end
assert(not all_choices or table.every(choices, function(c) return table.contains(all_choices, c) end))
local command = "AskForChoice" local command = "AskForChoice"
prompt = prompt or "" prompt = prompt or ""
all_choices = all_choices or choices
self:notifyMoveFocus(player, skill_name) self:notifyMoveFocus(player, skill_name)
local result = self:doRequest(player, command, json.encode{ local result = self:doRequest(player, command, json.encode{
choices, skill_name, prompt, detailed choices, all_choices, skill_name, prompt, detailed
}) })
if result == "" then result = choices[1] end if result == "" then result = choices[1] end
return result return result
@ -1785,7 +1788,7 @@ end
---@param skillName string @ 技能名 ---@param skillName string @ 技能名
---@param flag string|null @ 限定可移动的区域值为nil装备区和判定区ej ---@param flag string|null @ 限定可移动的区域值为nil装备区和判定区ej
---@param moveFrom ServerPlayer|null @ 是否只是目标1移动给目标2 ---@param moveFrom ServerPlayer|null @ 是否只是目标1移动给目标2
---@return integer ---@return table<"card"|"from"|"to"> @ 选择的卡牌、起点玩家id和终点玩家id列表
function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName, flag, moveFrom) function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName, flag, moveFrom)
if flag then if flag then
assert(flag == "e" or flag == "j") assert(flag == "e" or flag == "j")
@ -1863,15 +1866,18 @@ function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName, fla
end end
local cardToMove = Fk:getCardById(result.cardId) local cardToMove = Fk:getCardById(result.cardId)
local from, to = result.pos == 0 and targetOne, targetTwo or targetTwo, targetOne
self:moveCardTo( self:moveCardTo(
cardToMove, cardToMove,
cardToMove.type == Card.TypeEquip and Player.Equip or Player.Judge, cardToMove.type == Card.TypeEquip and Player.Equip or Player.Judge,
result.pos == 0 and targetTwo or targetOne, to,
fk.ReasonPut, fk.ReasonPut,
skillName, skillName,
nil, nil,
true true
) )
return { card = cardToMove, from = from.id, to = to.id }
end end
--- 询问一名玩家从targets中选择出若干名玩家来移动场上的牌。 --- 询问一名玩家从targets中选择出若干名玩家来移动场上的牌。
@ -2422,7 +2428,9 @@ function Room:drawCards(player, num, skillName, fromPlace)
skillName = skillName, skillName = skillName,
fromPlace = fromPlace, fromPlace = fromPlace,
} }
self.logic:trigger(fk.BeforeDrawCard, player, drawData) if self.logic:trigger(fk.BeforeDrawCard, player, drawData) or drawData.num < 1 then
self.logic:breakEvent(false)
end
num = drawData.num num = drawData.num
fromPlace = drawData.fromPlace fromPlace = drawData.fromPlace

View File

@ -13,12 +13,14 @@ local UI = {}
-- * choices: string[] 类型,保存着可选项,会被前端翻译 -- * choices: string[] 类型,保存着可选项,会被前端翻译
-- * default: string默认的选项默认为choices的第一个 -- * default: string默认的选项默认为choices的第一个
-- * detailed: bool为真的话送详细信息 -- * detailed: bool为真的话送详细信息
-- * all_choices: string[] 类型,保存着所有选项,会被前端翻译
UI.ComboBox = function(spec) UI.ComboBox = function(spec)
-- assert(type(spec.choices) == "table", "Choices is not a table") -- assert(type(spec.choices) == "table", "Choices is not a table")
-- assert(#spec.choices > 0, "Choices is empty") -- assert(#spec.choices > 0, "Choices is empty")
spec.choices = type(spec.choices) == "table" and spec.choices or Util.DummyTable spec.choices = type(spec.choices) == "table" and spec.choices or Util.DummyTable
spec.default = spec.default or spec.choices[1] spec.default = spec.default or spec.choices[1]
spec.detailed = spec.detailed or false spec.detailed = spec.detailed or false
spec.all_choices = type(spec.all_choices) == "table" and spec.all_choices or spec.choices
spec.type = "combo" spec.type = "combo"
return spec return spec
end end

View File

@ -187,7 +187,7 @@ local damage_maker = fk.CreateActiveSkill{
end, end,
target_num = 1, target_num = 1,
interaction = function()return UI.ComboBox { interaction = function()return UI.ComboBox {
choices = {"normal_damage", "fire_damage", "thunder_damage", "ice_damage", "lose_hp", "heal_hp", "lose_max_hp", "heal_max_hp"} choices = {"normal_damage", "thunder_damage", "fire_damage", "ice_damage", "lose_hp", "heal_hp", "lose_max_hp", "heal_max_hp"}
}end, }end,
on_use = function(self, room, effect) on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from) local from = room:getPlayerById(effect.from)
@ -212,7 +212,7 @@ local damage_maker = fk.CreateActiveSkill{
elseif choice == "lose_hp" then elseif choice == "lose_hp" then
room:loseHp(target, number, self.name) room:loseHp(target, number, self.name)
else else
choices = {"normal_damage", "fire_damage", "thunder_damage", "ice_damage"} choices = {"normal_damage", "thunder_damage", "fire_damage", "ice_damage"}
room:damage({ room:damage({
from = from, from = from,
to = target, to = target,