mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
isInLimit等各种功能 + bugfix (#201)
没来得及转远程url,这是最后一次从fork来的更新了 - 修复了fk.currentresponsepattern = nil的时机 - 添加unlimited/withinTimesLimit和withinDistanceLimit,整合并实现真正的“无次数限制”/“无距离限制” - 给观星框上了标题(暂时不往上加标题变量) - 青龙刀会临时追加“对此人不限次数”+“对此人不限距离”的标记,响应(包括取消)后清除 - 添加了“对某人无次数/距离限制”的标记及对应两个global技能
This commit is contained in:
parent
0c9701b74a
commit
d5330d5bed
|
@ -746,6 +746,7 @@ callbacks["AskForGuanxing"] = (jsonData) => {
|
|||
const max_bottom_cards = data.max_bottom_cards;
|
||||
const top_area_name = data.top_area_name;
|
||||
const bottom_area_name = data.bottom_area_name;
|
||||
const prompt = data.prompt;
|
||||
roomScene.state = "replying";
|
||||
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/GuanxingBox.qml");
|
||||
data.cards.forEach(id => {
|
||||
|
@ -753,6 +754,7 @@ callbacks["AskForGuanxing"] = (jsonData) => {
|
|||
cards.push(JSON.parse(d));
|
||||
});
|
||||
const box = roomScene.popupBox.item;
|
||||
box.prompt = prompt;
|
||||
if (max_top_cards === 0) {
|
||||
box.areaCapacities = [max_bottom_cards];
|
||||
box.areaLimits = [min_bottom_cards];
|
||||
|
|
|
@ -6,6 +6,7 @@ import Fk.Pages
|
|||
|
||||
GraphicsBox {
|
||||
id: root
|
||||
property string prompt
|
||||
property var cards: []
|
||||
property var result: []
|
||||
property var areaCapacities: []
|
||||
|
@ -13,7 +14,7 @@ GraphicsBox {
|
|||
property var areaNames: []
|
||||
property int padding: 25
|
||||
|
||||
title.text: Backend.translate("Please arrange cards")
|
||||
title.text: Backend.translate(prompt !== "" ? prompt : "Please arrange cards")
|
||||
width: body.width + padding * 2
|
||||
height: title.height + body.height + padding * 2
|
||||
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
---@class TargetModSkill : StatusSkill
|
||||
local TargetModSkill = StatusSkill:subclass("TargetModSkill")
|
||||
|
||||
---@param player Player
|
||||
---@param card_skill ActiveSkill
|
||||
---@param scope integer
|
||||
---@param card Card
|
||||
function TargetModSkill:isUnlimited(player, card_skill, scope, card, to)
|
||||
return false
|
||||
end
|
||||
|
||||
---@param player Player
|
||||
---@param card_skill ActiveSkill
|
||||
---@param scope integer
|
||||
|
|
|
@ -24,4 +24,21 @@ function UsableSkill:getMaxUseTime(player, scope, card, to)
|
|||
return ret
|
||||
end
|
||||
|
||||
function UsableSkill:withinTimesLimit(player, scope, card, to)
|
||||
scope = scope or Player.HistoryTurn
|
||||
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable
|
||||
for _, skill in ipairs(status_skills) do
|
||||
if skill:isUnlimited(player, self, scope, card, to) then return true end
|
||||
end
|
||||
return player:usedCardTimes(card.trueName, scope) < self:getMaxUseTime(player, scope, card, to)
|
||||
end
|
||||
|
||||
function UsableSkill:withinDistanceLimit(player, isattack, card, to)
|
||||
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable
|
||||
for _, skill in ipairs(status_skills) do
|
||||
if skill:withinAttackRange(player, to) then return true end
|
||||
end
|
||||
return isattack and player:inMyAttackRange(to, self:getDistanceLimit(player, card, to)) or player:distanceTo(to) <= self:getDistanceLimit(player, card, to)
|
||||
end
|
||||
|
||||
return UsableSkill
|
||||
|
|
|
@ -350,6 +350,7 @@ function fk.CreateMaxCardsSkill(spec)
|
|||
end
|
||||
|
||||
---@class TargetModSpec: StatusSkillSpec
|
||||
---@field public unlimited fun(self: TargetModSkill, player: Player, skill: ActiveSkill, scope: integer, card: Card, to: Player)
|
||||
---@field public residue_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, scope: integer, card: Card, to: Player)
|
||||
---@field public distance_limit_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, card: Card, to: Player)
|
||||
---@field public extra_target_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, card: Card)
|
||||
|
@ -361,6 +362,9 @@ function fk.CreateTargetModSkill(spec)
|
|||
|
||||
local skill = TargetModSkill:new(spec.name)
|
||||
readStatusSpecToSkill(skill, spec)
|
||||
if spec.unlimited then
|
||||
skill.isUnlimited = spec.unlimited
|
||||
end
|
||||
if spec.residue_func then
|
||||
skill.getResidueNum = spec.residue_func
|
||||
end
|
||||
|
|
|
@ -258,7 +258,7 @@ GameEvent.functions[GameEvent.Phase] = function(self)
|
|||
tos = { {player.id} },
|
||||
}
|
||||
room:doCardEffect(effect_data)
|
||||
if effect_data.isCancellOut and card.skill then
|
||||
if effect_data.isCanCellout and card.skill then
|
||||
card.skill:onNullified(room, effect_data)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -311,10 +311,10 @@ GameEvent.functions[GameEvent.CardEffect] = function(self)
|
|||
local self = self.room
|
||||
|
||||
for _, event in ipairs({ fk.PreCardEffect, fk.BeforeCardEffect, fk.CardEffecting, fk.CardEffectFinished }) do
|
||||
if cardEffectEvent.isCancellOut then
|
||||
if cardEffectEvent.isCanCellout then
|
||||
local user = cardEffectEvent.from and self:getPlayerById(cardEffectEvent.from) or nil
|
||||
if self.logic:trigger(fk.CardEffectCancelledOut, user, cardEffectEvent) then
|
||||
cardEffectEvent.isCancellOut = false
|
||||
cardEffectEvent.isCanCellout = false
|
||||
else
|
||||
self.logic:breakEvent()
|
||||
end
|
||||
|
|
|
@ -19,6 +19,10 @@ MarkEnum.MinusMaxCards = "MinusMaxCards"
|
|||
---@field AddMaxCards string @ 于本回合内减少标记值数量的手牌上限
|
||||
MarkEnum.MinusMaxCardsInTurn = "MinusMaxCards-turn"
|
||||
|
||||
---@field BypassTimesLimit string @ 对其使用牌无次数限制,可带清除标记后缀
|
||||
MarkEnum.BypassTimesLimit = "bypasstimeslimit"
|
||||
---@field BypassDistanceLimit string @ 对其使用牌无距离限制,可带清除标记后缀
|
||||
MarkEnum.BypassDistanceLimit = "bypassdistancelimit"
|
||||
---@field UncompulsoryInvalidity string @ 非锁定技失效,可带清除标记后缀
|
||||
MarkEnum.UncompulsoryInvalidity = "uncompulsoryInvalidity"
|
||||
|
||||
|
|
|
@ -642,6 +642,7 @@ function Room:doRequest(player, command, jsonData, wait)
|
|||
if wait then
|
||||
local ret = player:waitForReply(self.timeout)
|
||||
player.serverplayer:setBusy(false)
|
||||
player.serverplayer:setThinking(false)
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
@ -667,6 +668,7 @@ function Room:doBroadcastRequest(command, players, jsonData)
|
|||
|
||||
for _, p in ipairs(players) do
|
||||
p.serverplayer:setBusy(false)
|
||||
p.serverplayer:setThinking(false)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -731,6 +733,7 @@ function Room:doRaceRequest(command, players, jsonData)
|
|||
|
||||
for _, p in ipairs(self.players) do
|
||||
p.serverplayer:setBusy(false)
|
||||
p.serverplayer:setThinking(false)
|
||||
end
|
||||
|
||||
return ret
|
||||
|
@ -1365,6 +1368,7 @@ end
|
|||
---@param top_limit integer[] @ 置于牌堆顶的牌的限制(下限,上限),不填写则不限
|
||||
---@param bottom_limit integer[] @ 置于牌堆底的牌的限制(下限,上限),不填写则不限
|
||||
---@param customNotify string|null @ 自定义读条操作提示
|
||||
---@param prompt string|null @ 观星框的标题(暂时雪藏)
|
||||
---@param noPut boolean|null @ 是否进行放置牌操作
|
||||
---@param areaNames string[]|null @ 左侧提示信息
|
||||
---@return table<top|bottom, cardId[]>
|
||||
|
@ -1389,6 +1393,7 @@ function Room:askForGuanxing(player, cards, top_limit, bottom_limit, customNotif
|
|||
local command = "AskForGuanxing"
|
||||
self:notifyMoveFocus(player, customNotify or command)
|
||||
local data = {
|
||||
prompt = prompt or "",
|
||||
cards = cards,
|
||||
min_top_cards = top_limit and top_limit[1] or 0,
|
||||
max_top_cards = top_limit and top_limit[2] or #cards,
|
||||
|
@ -2231,11 +2236,11 @@ function Room:handleCardEffect(event, cardEffectEvent)
|
|||
self:useCard(use)
|
||||
end
|
||||
|
||||
if not cardEffectEvent.isCancellOut then
|
||||
if not cardEffectEvent.isCanCellout then
|
||||
break
|
||||
end
|
||||
|
||||
cardEffectEvent.isCancellOut = i == loopTimes
|
||||
cardEffectEvent.isCanCellout = i == loopTimes
|
||||
end
|
||||
elseif
|
||||
cardEffectEvent.card.type == Card.TypeTrick and
|
||||
|
|
|
@ -140,10 +140,12 @@ function ServerPlayer:waitForReply(timeout)
|
|||
result = ""
|
||||
self.reply_cancel = true
|
||||
self.serverplayer:setBusy(false)
|
||||
self.serverplayer:setThinking(false)
|
||||
end
|
||||
if result ~= "" then
|
||||
self.reply_ready = true
|
||||
self.serverplayer:setBusy(false)
|
||||
self.serverplayer:setThinking(false)
|
||||
end
|
||||
|
||||
local queue = self.room.request_queue[self.serverplayer]
|
||||
|
|
|
@ -133,7 +133,7 @@ fk.IceDamage = 4
|
|||
---@field public cardsResponded Card[]|null
|
||||
---@field public disresponsive boolean|null
|
||||
---@field public unoffsetable boolean|null
|
||||
---@field public isCancellOut boolean|null
|
||||
---@field public isCanCellout boolean|null
|
||||
---@field public fixedResponseTimes table<string, integer>|integer|null
|
||||
---@field public fixedAddTimesResponsors integer[]
|
||||
---@field public prohibitedCardNames string[]|null
|
||||
|
|
|
@ -80,7 +80,7 @@ local analepticSkill = fk.CreateActiveSkill{
|
|||
name = "analeptic_skill",
|
||||
max_turn_use_time = 1,
|
||||
can_use = function(self, player, card)
|
||||
return player:usedCardTimes("analeptic", Player.HistoryTurn) < self:getMaxUseTime(Self, Player.HistoryTurn, card, Self)
|
||||
return self:withinTimesLimit(player, Player.HistoryTurn, card, player)
|
||||
end,
|
||||
on_use = function(self, room, use)
|
||||
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
||||
|
@ -240,7 +240,7 @@ local supplyShortageSkill = fk.CreateActiveSkill{
|
|||
local player = Fk:currentRoom():getPlayerById(to_select)
|
||||
if Self ~= player then
|
||||
return not player:hasDelayedTrick("supply_shortage") and
|
||||
Self:distanceTo(player) <= self:getDistanceLimit(Self, card, player)
|
||||
self:withinDistanceLimit(Self, false, card, player)
|
||||
end
|
||||
end
|
||||
return false
|
||||
|
|
|
@ -122,6 +122,27 @@ local uncompulsoryInvalidity = fk.CreateInvaliditySkill {
|
|||
end
|
||||
}
|
||||
|
||||
local noTimesLimit = fk.CreateTargetModSkill{
|
||||
name = "noTimesLimit",
|
||||
global = true,
|
||||
unlimited = function(self, player, skill, scope, card, to)
|
||||
return to:getMark(MarkEnum.BypassTimesLimit) ~= 0 or
|
||||
table.find(MarkEnum.TempMarkSuffix, function(s)
|
||||
return to:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
local noDistanceLimit = fk.CreateAttackRangeSkill{
|
||||
name = "noDistanceLimit",
|
||||
global = true,
|
||||
within_func = function(self, player, to)
|
||||
return to:getMark(MarkEnum.BypassDistanceLimit) ~= 0 or
|
||||
table.find(MarkEnum.TempMarkSuffix, function(s)
|
||||
return to:getMark(MarkEnum.BypassDistanceLimit .. s) ~= 0
|
||||
end)
|
||||
end
|
||||
}
|
||||
AuxSkills = {
|
||||
discardSkill,
|
||||
chooseCardsSkill,
|
||||
|
@ -129,4 +150,6 @@ AuxSkills = {
|
|||
maxCardsSkill,
|
||||
choosePlayersToMoveCardInBoardSkill,
|
||||
uncompulsoryInvalidity,
|
||||
noTimesLimit,
|
||||
noDistanceLimit,
|
||||
}
|
||||
|
|
|
@ -509,10 +509,10 @@ local paoxiaoAudio = fk.CreateTriggerSkill{
|
|||
}
|
||||
local paoxiao = fk.CreateTargetModSkill{
|
||||
name = "paoxiao",
|
||||
residue_func = function(self, player, skill, scope)
|
||||
unlimited = function(self, player, skill, scope)
|
||||
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
|
||||
and scope == Player.HistoryPhase then
|
||||
return 999
|
||||
return true
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
|
|
@ -50,14 +50,14 @@ local slashSkill = fk.CreateActiveSkill{
|
|||
can_use = function(self, player, card)
|
||||
return
|
||||
table.find(Fk:currentRoom().alive_players, function(p)
|
||||
return player:usedCardTimes("slash", Player.HistoryPhase) < self:getMaxUseTime(Self, Player.HistoryPhase, card, p)
|
||||
return self:withinTimesLimit(player, Player.HistoryPhase, card, p)
|
||||
end)
|
||||
end,
|
||||
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)) and
|
||||
(#selected > 0 or Self:usedCardTimes("slash", Player.HistoryPhase) < self:getMaxUseTime(Self, Player.HistoryPhase, card, player))
|
||||
return Self ~= player and self:withinDistanceLimit(Self, true, card, player) and
|
||||
(#selected > 0 or self:withinTimesLimit(Self, Player.HistoryPhase, card, player))
|
||||
end
|
||||
end,
|
||||
on_effect = function(self, room, effect)
|
||||
|
@ -125,7 +125,7 @@ local jinkSkill = fk.CreateActiveSkill{
|
|||
end,
|
||||
on_effect = function(self, room, effect)
|
||||
if effect.responseToEvent then
|
||||
effect.responseToEvent.isCancellOut = true
|
||||
effect.responseToEvent.isCanCellout = true
|
||||
end
|
||||
end
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ local snatchSkill = fk.CreateActiveSkill{
|
|||
local player = Fk:currentRoom():getPlayerById(to_select)
|
||||
return
|
||||
Self ~= player and
|
||||
Self:distanceTo(player) <= self:getDistanceLimit(Self, card, player) and -- for no distance limit for snatch
|
||||
self:withinDistanceLimit(Self, false, card, player) and -- for no distance limit for snatch
|
||||
not player:isAllNude()
|
||||
end
|
||||
end,
|
||||
|
@ -436,7 +436,7 @@ local nullificationSkill = fk.CreateActiveSkill{
|
|||
end,
|
||||
on_effect = function(self, room, effect)
|
||||
if effect.responseToEvent then
|
||||
effect.responseToEvent.isCancellOut = true
|
||||
effect.responseToEvent.isCanCellout = true
|
||||
end
|
||||
end
|
||||
}
|
||||
|
@ -778,10 +778,10 @@ local crossbowAudio = fk.CreateTriggerSkill{
|
|||
local crossbowSkill = fk.CreateTargetModSkill{
|
||||
name = "#crossbow_skill",
|
||||
attached_equip = "crossbow",
|
||||
residue_func = function(self, player, skill, scope)
|
||||
unlimited = function(self, player, skill, scope)
|
||||
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
|
||||
and scope == Player.HistoryPhase then
|
||||
return 999
|
||||
return true
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
@ -941,8 +941,12 @@ local bladeSkill = fk.CreateTriggerSkill{
|
|||
end,
|
||||
on_cost = function(self, event, target, player, data)
|
||||
local room = player.room
|
||||
room:setPlayerMark(target, MarkEnum.BypassDistanceLimit, 1)
|
||||
room:setPlayerMark(target, MarkEnum.BypassTimesLimit, 1)
|
||||
local use = room:askForUseCard(player, "slash", nil, "#blade_slash:" .. target.id,
|
||||
true, { must_targets = {target.id}, exclusive_targets = {target.id} })
|
||||
room:setPlayerMark(target, MarkEnum.BypassDistanceLimit, 0)
|
||||
room:setPlayerMark(target, MarkEnum.BypassTimesLimit, 0)
|
||||
if use then
|
||||
use.extraUse = true
|
||||
self.cost_data = use
|
||||
|
|
Loading…
Reference in New Issue
Block a user