DetailComboBox等各种功能+bug fix (#192)

- 当你可用的武将数<玩家数*选将框数时发出警告(新禁/解禁(将/包)请退出重进)
- 修复人均克己的bug
- 修复帷幕能被挂闪的bug
- 为杀新增各种判定
- 添加AOE条件以修复无目标AOE的bug
- 延后Fk.currentResponsePattern = nil的时机,使视为技可以视为Fk.currentResponsePattern
- 主动技可以传更详细的ComboBox,谋徐盛现在会教你普通锦囊牌的用法
- 为防bug,由单挑王顶替小霸王的候补位
- 武将一览中没有翻译表的台词将设为空
- 新增exclusive_targets,可限定使用牌的目标(优先级高于一切目标筛选)
This commit is contained in:
YoumuKon 2023-06-15 21:19:57 +08:00 committed by GitHub
parent c2d304fa4d
commit 623007aca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 17 deletions

View File

@ -70,7 +70,7 @@ Flickable {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Select general num")
text: Backend.translate("Select generals num")
}
SpinBox {
id: generalNum
@ -84,6 +84,14 @@ Flickable {
}
}
Text {
id: warning
anchors.rightMargin: 8
visible: JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", [])) < config.preferredGeneralNum * config.preferedPlayerNum
text: Backend.translate("No enough generals")
color: "red"
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
@ -149,6 +157,7 @@ Flickable {
spacing: 16
Button {
text: Backend.translate("OK")
enabled: !(warning.visible)
onClicked: {
root.finished();
mainWindow.busy = true;

View File

@ -243,7 +243,7 @@ Item {
}
Text {
Layout.fillWidth: true
text: Backend.translate("$" + name + (idx ? idx.toString() : ""))
text: (Backend.translate("$" + name + (idx ? idx.toString() : "")) == "$" + name + (idx ? idx.toString() : "") ? "" : Backend.translate("$" + name + (idx ? idx.toString() : "")))
wrapMode: Text.WordWrap
}
}
@ -269,7 +269,7 @@ Item {
}
Text {
Layout.fillWidth: true
text: Backend.translate("~" + generalDetail.general)
text: Backend.translate("~" + generalDetail.general) == "~" + generalDetail.general ? "" : Backend.translate("~" + generalDetail.general)
wrapMode: Text.WordWrap
}
}

View File

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

View File

@ -444,6 +444,10 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
all_photos.forEach(photo => {
photo.state = "candidate";
const id = photo.playerid;
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) return;
}
const ret = JSON.parse(Backend.callLuaFunction(
"CanUseCardToTarget",
[card, id, selected_targets]

View File

@ -9,6 +9,7 @@ MetroButton {
property var choices: []
property string default_choice
property string answer: default_choice
property bool detailed: false
function processPrompt(prompt) {
const data = prompt.split(":");
@ -34,7 +35,11 @@ MetroButton {
}
onClicked: {
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChoiceBox.qml");
if (detailed) {
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/DetailedChoiceBox.qml");
} else {
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChoiceBox.qml");
}
const box = roomScene.popupBox.item;
box.options = choices;
box.accepted.connect(() => {

View File

@ -126,6 +126,29 @@ function GetGenerals(pack_name)
return json.encode(ret)
end
function GetAvailableGeneralsNum()
local generalPool = Fk:getAllGenerals()
local except = {}
local ret = 0
for _, g in ipairs(Fk.packages["test_p_0"].generals) do
table.insert(except, g.name)
end
local availableGenerals = {}
for _, general in pairs(generalPool) do
if not table.contains(except, general.name) then
if (not general.hidden and not general.total_hidden) and
#table.filter(availableGenerals, function(g)
return g.trueName == general.trueName
end) == 0 then
ret = ret + 1
end
end
end
return ret
end
function GetAllCardPack()
local ret = {}
for _, name in ipairs(Fk.package_names) do

View File

@ -29,7 +29,8 @@ Fk:loadTranslationTable{
["Room Name"] = "房间名字",
["$RoomName"] = "%1的房间",
["Player num"] = "玩家数目",
["Select general num"] = "选将数目",
["Select generals num"] = "选将数目",
["No enough generals"] = "可用武将不足!",
["Operation timeout"] = "操作时长(秒)",
["Luck Card Times"] = "手气卡次数",
["Room Password"] = "房间密码",

View File

@ -486,7 +486,7 @@ function Room:changeHero(player, new_general, full, isDeputy, sendLog)
orig = Fk.generals[orig]
local orig_skills = orig and orig:getSkillNameList() or Util.DummyTable
local new = Fk.generals[new_general] or Fk.generals["sunce"]
local new = Fk.generals[new_general] or Fk.generals["liubei"]
local new_skills = new:getSkillNameList()
table.insertTable(new_skills, table.map(orig_skills, function(e)
@ -981,8 +981,11 @@ function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, can
-- maxNum = math.min(#canDiscards, maxNum)
-- minNum = math.min(#canDiscards, minNum)
if minNum < #canDiscards and not cancelable then
return {}
if minNum >= #canDiscards and not cancelable then
if not skipDiscard then
self:throwCard(canDiscards, skillName, player, player)
end
return canDiscards
end
local toDiscard = {}
@ -1455,6 +1458,7 @@ end
-- available extra_data:
-- * must_targets: integer[]
-- * exclusive_targets: integer[]
--- 询问玩家使用一张牌。
---@param player ServerPlayer @ 要询问的玩家
---@param card_name string @ 使用牌的牌名若pattern指定了则可随意写它影响的是烧条的提示信息
@ -1505,11 +1509,11 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
Fk.currentResponsePattern = pattern
local result = self:doRequest(player, command, json.encode(data))
Fk.currentResponsePattern = nil
if result ~= "" then
return self:handleUseCardReply(player, result)
end
Fk.currentResponsePattern = nil
end
return nil
end
@ -1550,7 +1554,6 @@ function Room:askForResponse(player, card_name, pattern, prompt, cancelable, ext
Fk.currentResponsePattern = pattern
local result = self:doRequest(player, command, json.encode(data))
Fk.currentResponsePattern = nil
if result ~= "" then
local use = self:handleUseCardReply(player, result)
@ -1558,6 +1561,7 @@ function Room:askForResponse(player, card_name, pattern, prompt, cancelable, ext
return use.card
end
end
Fk.currentResponsePattern = nil
end
return nil
end
@ -1591,12 +1595,12 @@ function Room:askForNullification(players, card_name, pattern, prompt, cancelabl
Fk.currentResponsePattern = pattern
local winner = self:doRaceRequest(command, players, json.encode(data))
Fk.currentResponsePattern = nil
if winner then
local result = winner.client_reply
return self:handleUseCardReply(winner, result)
end
Fk.currentResponsePattern = nil
return nil
end
@ -2210,7 +2214,6 @@ function Room:handleCardEffect(event, cardEffectEvent)
self:useCard(use)
end
end
Fk.currentResponsePattern = nil
elseif event == fk.CardEffecting then
if cardEffectEvent.card.skill then
execGameEvent(GameEvent.SkillEffect, function ()
@ -2231,7 +2234,7 @@ end
---@param from ServerPlayer @ 使用来源
---@param tos ServerPlayer | ServerPlayer[] @ 目标角色(列表)
---@param skillName string @ 技能名
---@param extra boolean @ 是否计入次数
---@param extra boolean @ 是否计入次数
function Room:useVirtualCard(card_name, subcards, from, tos, skillName, extra)
local card = Fk:cloneCard(card_name)
card.skillName = skillName

View File

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

View File

@ -3,6 +3,24 @@
local extension = Package:new("standard_cards", Package.CardPack)
extension.metadata = require "packages.standard_cards.metadata"
local global_can_use = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if not player:isProhibited(p, card) then
return true
end
end
end
local aoe_can_use = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if p ~= player and not player:isProhibited(p, card) then
return true
end
end
end
local global_on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
@ -38,7 +56,8 @@ local slashSkill = fk.CreateActiveSkill{
target_filter = function(self, to_select, selected, _, card)
if #selected < self:getMaxTargetNum(Self, card) then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player and Self:inMyAttackRange(player, self:getDistanceLimit(Self, card, player))
return Self ~= player and Self:inMyAttackRange(player, self:getDistanceLimit(Self, card, player)) and
(#selected > 0 or Self:usedCardTimes("slash", Player.HistoryPhase) < self:getMaxUseTime(Self, Player.HistoryPhase, card, player))
end
end,
on_effect = function(self, room, effect)
@ -439,6 +458,7 @@ extension:addCards({
local savageAssaultSkill = fk.CreateActiveSkill{
name = "savage_assault_skill",
can_use = aoe_can_use,
on_use = aoe_on_use,
on_effect = function(self, room, effect)
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash', nil, nil, false, nil, effect)
@ -477,6 +497,7 @@ extension:addCards({
local archeryAttackSkill = fk.CreateActiveSkill{
name = "archery_attack_skill",
can_use = aoe_can_use,
on_use = aoe_on_use,
on_effect = function(self, room, effect)
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'jink', nil, nil, false, nil, effect)
@ -513,6 +534,7 @@ extension:addCards({
local godSalvationSkill = fk.CreateActiveSkill{
name = "god_salvation_skill",
can_use = global_can_use,
on_use = global_on_use,
about_to_effect = function(self, room, effect)
if not room:getPlayerById(effect.to):isWounded() then
@ -541,6 +563,7 @@ extension:addCards({
local amazingGraceSkill = fk.CreateActiveSkill{
name = "amazing_grace_skill",
can_use = global_can_use,
on_use = global_on_use,
on_effect = function(self, room, effect)
local to = room:getPlayerById(effect.to)
@ -664,7 +687,8 @@ local lightningSkill = fk.CreateActiveSkill{
repeat
nextp = nextp:getNextAlive()
if nextp == to then break end
until not nextp:hasDelayedTrick("lightning")
until not nextp:hasDelayedTrick("lightning") and not nextp:isProhibited(nextp, effect.card)
if effect.card:isVirtual() then
nextp:addVirtualEquip(effect.card)
@ -918,7 +942,7 @@ local bladeSkill = fk.CreateTriggerSkill{
on_cost = function(self, event, target, player, data)
local room = player.room
local use = room:askForUseCard(player, "slash", nil, "#blade_slash:" .. target.id,
true, { must_targets = {target.id} })
true, { must_targets = {target.id}, exclusive_targets = {target.id} })
if use then
use.extraUse = true
self.cost_data = use

View File

@ -136,7 +136,8 @@ local test_vs = fk.CreateViewAsSkill{
"archery_attack",
"lightning",
"nullification",
}
},
detailed = true,
}
end,
view_as = function(self, cards)

View File

@ -390,6 +390,12 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
client->disconnect(this);
if (players.count() <= 10) {
broadcast("ServerMessage", tr("%1 backed").arg(player->getScreenName()));
if (room->getOwner() == player) {
auto owner = room->getOwner();
auto jsonData = QJsonArray();
jsonData << owner->getId();
player->doNotify("RoomOwner", JsonArray2Bytes(jsonData));
}
}
if (room && !room->isLobby()) {