mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 11:42:45 +08:00
忘了同步lua
This commit is contained in:
parent
ed6ce84584
commit
29d20089b4
|
@ -243,7 +243,7 @@ end
|
|||
|
||||
fk.client_callback["EnterRoom"] = function(_data)
|
||||
Self = ClientPlayer:new(fk.Self)
|
||||
-- 垃圾bug 怎么把这玩意忘了
|
||||
-- FIXME: 需要改Qml
|
||||
local ob = ClientInstance.observing
|
||||
ClientInstance = Client:new() -- clear old client data
|
||||
ClientInstance.observing = ob
|
||||
|
|
|
@ -902,8 +902,11 @@ function RevertSelection()
|
|||
local unselectData = { selected = false }
|
||||
local selectData = { selected = true }
|
||||
local to_select = {}
|
||||
local lastcid
|
||||
local lastselected = false
|
||||
for cid, cardItem in pairs(h.scene:getAllItems("CardItem")) do
|
||||
if table.contains(h.pendings, cid) then
|
||||
lastcid = cid
|
||||
h:selectCard(cid, unselectData)
|
||||
else
|
||||
table.insert(to_select, cardItem)
|
||||
|
@ -911,9 +914,16 @@ function RevertSelection()
|
|||
end
|
||||
for _, cardItem in ipairs(to_select) do
|
||||
if cardItem.enabled then
|
||||
lastcid = cardItem.id
|
||||
lastselected = true
|
||||
h:selectCard(cardItem.id, selectData)
|
||||
end
|
||||
end
|
||||
-- 最后模拟一次真实点击卡牌以更新目标和按钮状态
|
||||
if lastcid then
|
||||
h:selectCard(lastcid, { selected = not lastselected })
|
||||
h:update("CardItem", lastcid, "click", { selected = lastselected })
|
||||
end
|
||||
h.scene:notifyUI()
|
||||
end
|
||||
|
||||
|
@ -935,12 +945,11 @@ function FinishRequestUI()
|
|||
end
|
||||
end
|
||||
|
||||
-- TODO 传参带上cardMoveData...
|
||||
function CardVisibility(cardId, move)
|
||||
function CardVisibility(cardId)
|
||||
local player = Self
|
||||
local card = Fk:getCardById(cardId)
|
||||
if not card then return false end
|
||||
return player:cardVisible(cardId, move)
|
||||
return player:cardVisible(cardId)
|
||||
end
|
||||
|
||||
function RoleVisibility(targetId)
|
||||
|
|
|
@ -360,9 +360,9 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["Resume"] = "继续",
|
||||
|
||||
["Bulletin Info"] = [==[
|
||||
## v0.4.13
|
||||
## v0.4.21
|
||||
|
||||
优化性能
|
||||
UI重构!还有很长一段路要走……
|
||||
|
||||
]==],
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ function Card:initialize(name, suit, number, color)
|
|||
self.color = Card.Red
|
||||
elseif color ~= nil then
|
||||
self.color = color
|
||||
elseif suit == Card.Unknown then
|
||||
self.color = Card.Unknown
|
||||
else
|
||||
self.color = Card.NoColor
|
||||
end
|
||||
|
@ -242,7 +244,7 @@ end
|
|||
---@return string @ 描述花色的字符串
|
||||
function Card:getSuitString(symbol)
|
||||
local suit = self.suit
|
||||
local ret
|
||||
local ret = "unknown"
|
||||
if suit == Card.Spade then
|
||||
ret = "spade"
|
||||
elseif suit == Card.Heart then
|
||||
|
@ -251,7 +253,7 @@ function Card:getSuitString(symbol)
|
|||
ret = "club"
|
||||
elseif suit == Card.Diamond then
|
||||
ret = "diamond"
|
||||
else
|
||||
elseif suit == Card.NoSuit then
|
||||
ret = "nosuit"
|
||||
end
|
||||
return symbol and "log_" .. ret or ret
|
||||
|
@ -265,9 +267,11 @@ function Card:getColorString()
|
|||
return "black"
|
||||
elseif color == Card.Red then
|
||||
return "red"
|
||||
end
|
||||
elseif color == Card.NoColor then
|
||||
return "nocolor"
|
||||
end
|
||||
return "unknown"
|
||||
end
|
||||
|
||||
--- 获取卡牌类型并返回类型描述(例如基本牌/锦囊牌/装备牌)。
|
||||
function Card:getTypeString()
|
||||
|
@ -426,8 +430,11 @@ end
|
|||
--- 比较两张卡牌的花色是否相同
|
||||
---@param anotherCard Card @ 另一张卡牌
|
||||
---@param diff? boolean @ 比较二者不同
|
||||
---@return boolean 返回比较结果
|
||||
---@return boolean @ 返回比较结果
|
||||
function Card:compareSuitWith(anotherCard, diff)
|
||||
if table.contains({ self.suit, anotherCard.suit }, Card.Unknown) then
|
||||
return true
|
||||
end
|
||||
if self ~= anotherCard and table.contains({ self.suit, anotherCard.suit }, Card.NoSuit) then
|
||||
return false
|
||||
end
|
||||
|
@ -444,6 +451,9 @@ end
|
|||
---@param diff? boolean @ 比较二者不同
|
||||
---@return boolean @ 返回比较结果
|
||||
function Card:compareColorWith(anotherCard, diff)
|
||||
if table.contains({ self.color, anotherCard.color }, Card.Unknown) then
|
||||
return true
|
||||
end
|
||||
if self ~= anotherCard and table.contains({ self.color, anotherCard.color }, Card.NoColor) then
|
||||
return false
|
||||
end
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
---@field public id? integer[]
|
||||
|
||||
-- v0.2.6改动: cardType会被解析为trueName数组和name数组,而不是自己单独成立
|
||||
-- core改动: name数组为空时,将根据trueName数组生成对应的name数组
|
||||
|
||||
local numbertable = {
|
||||
["A"] = 1,
|
||||
|
@ -48,6 +49,8 @@ local placetable = {
|
|||
|
||||
local card_type_table = {}
|
||||
|
||||
local card_truename_table = {}
|
||||
|
||||
local function fillCardTypeTable()
|
||||
local tmp = {}
|
||||
for _, cd in ipairs(Fk.cards) do
|
||||
|
@ -66,6 +69,20 @@ local function fillCardTypeTable()
|
|||
end
|
||||
end
|
||||
|
||||
local function fillCardTrueNameTable()
|
||||
local tmp = {}
|
||||
for _, cd in ipairs(Fk.cards) do
|
||||
local tn = cd.trueName
|
||||
local n = cd.name
|
||||
|
||||
if not tmp[n] then
|
||||
card_truename_table[tn] = card_truename_table[tn] or {}
|
||||
table.insertIfNeed(card_truename_table[tn], n)
|
||||
tmp[n] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function matchSingleKey(matcher, card, key)
|
||||
local match = matcher[key]
|
||||
if not match then return true end
|
||||
|
@ -302,7 +319,9 @@ local function parseMatcher(str)
|
|||
|
||||
ret.suit = not table.contains(t[3], ".") and t[3] or nil
|
||||
ret.place = not table.contains(t[4], ".") and t[4] or nil
|
||||
ret.name = not table.contains(t[5], ".") and t[5] or nil
|
||||
if table.empty(card_truename_table) then
|
||||
fillCardTrueNameTable()
|
||||
end
|
||||
-- ret.cardType = not table.contains(t[6], ".") and t[6] or nil
|
||||
if table.empty(card_type_table) then
|
||||
fillCardTypeTable()
|
||||
|
@ -325,6 +344,29 @@ local function parseMatcher(str)
|
|||
table.insert(ret.trueName.neg, temp)
|
||||
end
|
||||
|
||||
if table.contains(t[5], ".") then
|
||||
if ret.trueName then
|
||||
ret.name = {}
|
||||
for _, tn in ipairs(ret.trueName) do
|
||||
table.insertTableIfNeed(ret.name, card_truename_table[tn] or Util.DummyTable)
|
||||
end
|
||||
for _, neg in ipairs(ret.trueName.neg or Util.DummyTable) do
|
||||
if type(neg) ~= "table" then neg = { neg } end
|
||||
if not ret.name.neg then ret.name.neg = {} end
|
||||
|
||||
local temp = {}
|
||||
for _, tn in ipairs(neg) do
|
||||
table.insertTableIfNeed(temp, card_truename_table[tn] or Util.DummyTable)
|
||||
end
|
||||
table.insert(ret.name.neg, temp)
|
||||
end
|
||||
else
|
||||
ret.name = nil
|
||||
end
|
||||
else
|
||||
ret.name = t[5]
|
||||
end
|
||||
|
||||
if not table.contains(t[7], ".") then
|
||||
ret.id = parseRawNumTable(t[7])
|
||||
end
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
-- 呃 起码要做出以下几种吧:
|
||||
-- Switch:那个开关组件 [boolean model=nil]
|
||||
-- RadioButton:那个多选一,圆圈里面打点组件 [string model={ label, value }[]]
|
||||
-- ComboBox: 那个多选一,下拉一个菜单并选择一个的组件 [string model同上]
|
||||
-- CheckBox: 那个多选多打钩组件 [string[], model={ choices = {label,value}[], min, max}]
|
||||
-- Spinner: 选integer的组件吧,带加号减号那个 [integer model={min, max}]
|
||||
|
||||
--- 定义一套配置项,供玩家在创建房间时配置。配置完成后返回一个表保存配置信息,
|
||||
--- 下面假设这个配置信息是表`cfg = {}`
|
||||
---@class GameModeConfigEntry
|
||||
---@field public name string @ 配置项的内部名,cfg的键
|
||||
---@field public label? string @ 界面上显示的提示信息
|
||||
---@field public delegate string @ 要显示哪种?
|
||||
---@field public model any @ 这种delegate需要的model:参见注释
|
||||
---@field public default? any @ 默认值 cfg的value
|
||||
|
||||
--- GameMode用来描述一个游戏模式。
|
||||
---
|
||||
--- 可以参考欢乐斗地主。
|
||||
|
@ -12,6 +28,7 @@
|
|||
---@field public logic? fun(): GameLogic @ 逻辑(通过function完成,通常用来初始化、分配身份及座次)
|
||||
---@field public whitelist? string[] @ 白名单
|
||||
---@field public blacklist? string[] @ 黑名单
|
||||
---@field public config_template? GameModeConfigEntry[] 游戏模式的配置页面,如此一个数组
|
||||
local GameMode = class("GameMode")
|
||||
|
||||
--- 构造函数,不可随意调用。
|
||||
|
@ -83,4 +100,14 @@ function GameMode:getAdjustedProperty (player)
|
|||
return list
|
||||
end
|
||||
|
||||
--- 向游戏模式中添加拓展包过滤。
|
||||
---@param whitelist string[] @ 白名单
|
||||
---@param blacklist string[] @ 黑名单
|
||||
function GameMode:addPackageFilter(whitelist, blacklist)
|
||||
assert(type(whitelist) == "table")
|
||||
assert(type(blacklist) == "table")
|
||||
table.insertTable(self.whitelist, whitelist)
|
||||
table.insertTable(self.blacklist, blacklist)
|
||||
end
|
||||
|
||||
return GameMode
|
||||
|
|
|
@ -1254,7 +1254,7 @@ function Player:roleVisible(target)
|
|||
end
|
||||
end
|
||||
|
||||
if room.observing == false and target == self then return true end
|
||||
if not room.observing and target == self then return true end
|
||||
|
||||
return target.role_shown
|
||||
end
|
||||
|
|
|
@ -100,10 +100,17 @@ function ReqPlayCard:doEndButton()
|
|||
end
|
||||
|
||||
function ReqPlayCard:selectCard(cid, data)
|
||||
ReqUseCard.selectCard(self, cid, data)
|
||||
if self.skill_name and not self.selected_card then return end
|
||||
if self.skill_name and not self.selected_card then
|
||||
return ReqActiveSkill.selectCard(self, cid, data)
|
||||
end
|
||||
local scene = self.scene
|
||||
local selected = data.selected
|
||||
scene:update("CardItem", cid, data)
|
||||
|
||||
if self.selected_card then
|
||||
if selected then
|
||||
self.skill_name = nil
|
||||
self.selected_card = Fk:getCardById(cid)
|
||||
scene:unselectOtherCards(cid)
|
||||
self:setSkillPrompt(self.selected_card.skill, self.selected_card:getEffectiveId())
|
||||
local sp_skills = {}
|
||||
if self.selected_card.special_skills then
|
||||
|
@ -114,11 +121,17 @@ function ReqPlayCard:selectCard(cid, data)
|
|||
end
|
||||
self.scene:update("SpecialSkills", "1", { skills = sp_skills })
|
||||
else
|
||||
self.selected_card = nil
|
||||
self:setPrompt(self.original_prompt)
|
||||
self.scene:update("SpecialSkills", "1", { skills = {} })
|
||||
end
|
||||
end
|
||||
|
||||
function ReqPlayCard:selectSkill(skill, data)
|
||||
ReqUseCard.selectSkill(self, skill, data)
|
||||
self.scene:update("SpecialSkills", "1", { skills = {} })
|
||||
end
|
||||
|
||||
function ReqPlayCard:update(elemType, id, action, data)
|
||||
if elemType == "Button" and id == "End" then
|
||||
self:doEndButton()
|
||||
|
|
|
@ -4,6 +4,12 @@ local ReqResponseCard = require 'core.request_type.response_card'
|
|||
---@class ReqUseCard: ReqResponseCard
|
||||
local ReqUseCard = ReqResponseCard:subclass("ReqUseCard")
|
||||
|
||||
function ReqUseCard:skillButtonValidity(name)
|
||||
local player = self.player
|
||||
local skill = Fk.skills[name]
|
||||
return skill:isInstanceOf(ViewAsSkill) and skill:enabledAtResponse(player, false)
|
||||
end
|
||||
|
||||
function ReqUseCard:cardValidity(cid)
|
||||
if self.skill_name then return ReqActiveSkill.cardValidity(self, cid) end
|
||||
local card = cid
|
||||
|
@ -31,6 +37,9 @@ end
|
|||
function ReqUseCard:feasible()
|
||||
local skill = Fk.skills[self.skill_name]
|
||||
local card = self.selected_card
|
||||
if skill then
|
||||
card = skill:viewAs(self.pendings)
|
||||
end
|
||||
local ret = false
|
||||
if card and self:cardFeasible(card) then
|
||||
ret = card.skill:feasible(self.selected_targets,
|
||||
|
|
|
@ -81,6 +81,7 @@ function CardManager:getCardsByArea(area, player, dup, special_name)
|
|||
assert(player ~= nil)
|
||||
if area == Player.Special then
|
||||
assert(special_name ~= nil)
|
||||
player.special_cards[special_name] = player.special_cards[special_name] or {}
|
||||
ret = player.special_cards[special_name]
|
||||
else
|
||||
ret = player.player_cards[area]
|
||||
|
|
|
@ -19,6 +19,7 @@ fk.EventPhaseEnd = 6
|
|||
fk.AfterPhaseEnd = 86
|
||||
fk.EventPhaseChanging = 7
|
||||
fk.EventPhaseSkipping = 8
|
||||
fk.EventPhaseSkipped = 101
|
||||
|
||||
fk.BeforeCardsMove = 9
|
||||
fk.AfterCardsMove = 10
|
||||
|
@ -149,4 +150,4 @@ fk.AfterPlayerRevived = 95
|
|||
-- 99 = AfterAskForCardResponse
|
||||
-- 100 = AfterAskForNullification
|
||||
|
||||
fk.NumOfEvents = 101
|
||||
fk.NumOfEvents = 102
|
||||
|
|
|
@ -336,17 +336,16 @@ function MoveEventWrappers:recastCard(card_ids, who, skillName)
|
|||
end
|
||||
|
||||
--- 将一些卡牌同时分配给一些角色。
|
||||
---@param room Room @ 房间
|
||||
---@param list table<integer[]> @ 分配牌和角色的数据表,键为角色id,值为分配给其的牌id数组
|
||||
---@param proposer? integer @ 操作者的id。默认为空
|
||||
---@param skillName? string @ 技能名。默认为“分配”
|
||||
---@return table<integer[]> @ 返回成功分配的卡牌
|
||||
function MoveEventWrappers:doYiji(room, list, proposer, skillName)
|
||||
function MoveEventWrappers:doYiji(list, proposer, skillName)
|
||||
skillName = skillName or "distribution_skill"
|
||||
local moveInfos = {}
|
||||
local move_ids = {}
|
||||
for to, cards in pairs(list) do
|
||||
local toP = room:getPlayerById(to)
|
||||
local toP = self:getPlayerById(to)
|
||||
local handcards = toP:getCardIds("h")
|
||||
cards = table.filter(cards, function (id) return not table.contains(handcards, id) end)
|
||||
if #cards > 0 then
|
||||
|
@ -354,7 +353,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName)
|
|||
local moveMap = {}
|
||||
local noFrom = {}
|
||||
for _, id in ipairs(cards) do
|
||||
local from = room.owner_map[id]
|
||||
local from = self.owner_map[id]
|
||||
if from then
|
||||
moveMap[from] = moveMap[from] or {}
|
||||
table.insert(moveMap[from], id)
|
||||
|
@ -366,7 +365,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName)
|
|||
table.insert(moveInfos, {
|
||||
ids = _cards,
|
||||
moveInfo = table.map(_cards, function(id)
|
||||
return {cardId = id, fromArea = room:getCardArea(id), fromSpecialName = room:getPlayerById(from):getPileNameOfId(id)}
|
||||
return {cardId = id, fromArea = self:getCardArea(id), fromSpecialName = self:getPlayerById(from):getPileNameOfId(id)}
|
||||
end),
|
||||
from = from,
|
||||
to = to,
|
||||
|
@ -389,7 +388,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName)
|
|||
end
|
||||
end
|
||||
if #moveInfos > 0 then
|
||||
room:moveCards(table.unpack(moveInfos))
|
||||
self:moveCards(table.unpack(moveInfos))
|
||||
end
|
||||
return move_ids
|
||||
end
|
||||
|
|
|
@ -491,13 +491,14 @@ end
|
|||
-- 作用是启动新事件 都是结构差不多的函数
|
||||
---@param event GameEvent
|
||||
---@return boolean, GameEvent?
|
||||
function GameLogic:resumeEvent(event, ...)
|
||||
function GameLogic:resumeEvent(event)
|
||||
local ret, evt
|
||||
|
||||
local co = event._co
|
||||
local resume_reason = "unknown"
|
||||
|
||||
while true do
|
||||
local err, yield_result, extra_yield_result = coroutine.resume(co, ...)
|
||||
local err, yield_result, extra_yield_result = coroutine.resume(co, resume_reason)
|
||||
|
||||
if err == false then
|
||||
-- handle error, then break
|
||||
|
@ -510,7 +511,8 @@ function GameLogic:resumeEvent(event, ...)
|
|||
|
||||
if yield_result == "__handleRequest" then
|
||||
-- yield to requestLoop
|
||||
coroutine.yield(yield_result, extra_yield_result)
|
||||
-- handleRequest类的最后被ResumeRoom唤醒,接收原因
|
||||
resume_reason = coroutine.yield(yield_result, extra_yield_result)
|
||||
|
||||
elseif type(yield_result) == "table" and yield_result.class
|
||||
and yield_result:isInstanceOf(GameEvent) then
|
||||
|
|
|
@ -176,6 +176,7 @@ function Request:ask()
|
|||
|
||||
local players = table.simpleClone(self.players)
|
||||
local currentTime = os.time()
|
||||
local resume_reason = "unknown"
|
||||
|
||||
-- 1. 向所有人发送询问请求
|
||||
for _, p in ipairs(players) do
|
||||
|
@ -191,7 +192,7 @@ function Request:ask()
|
|||
-- 判断1:若投降则直接结束全部询问,若超时则踢掉所有人类玩家(这样AI还可计算)
|
||||
if room.hasSurrendered then break end
|
||||
local elapsed = os.time() - currentTime
|
||||
if self.timeout - elapsed <= 0 then
|
||||
if self.timeout - elapsed <= 0 or resume_reason == "request_timer" then
|
||||
for i = #players, 1, -1 do
|
||||
if self.send_success[players[i].serverplayer] then
|
||||
table.remove(players, i)
|
||||
|
@ -246,7 +247,7 @@ function Request:ask()
|
|||
|
||||
-- 需要等待呢,等待被唤醒吧
|
||||
if not changed then
|
||||
coroutine.yield("__handleRequest")
|
||||
resume_reason = coroutine.yield("__handleRequest")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -89,7 +89,8 @@ function Room:initialize(_room)
|
|||
end
|
||||
|
||||
-- 供调度器使用的函数。能让房间开始运行/从挂起状态恢复。
|
||||
function Room:resume()
|
||||
---@param reason string?
|
||||
function Room:resume(reason)
|
||||
-- 如果还没运行的话就先创建自己的主协程
|
||||
if not self.main_co then
|
||||
self.main_co = coroutine.create(function()
|
||||
|
@ -107,7 +108,7 @@ function Room:resume()
|
|||
|
||||
if not self.game_finished then
|
||||
self.notify_count = 0
|
||||
ret, err_msg, rest_time = coroutine.resume(main_co, err_msg)
|
||||
ret, err_msg, rest_time = coroutine.resume(main_co, reason)
|
||||
|
||||
-- handle error
|
||||
if ret == false then
|
||||
|
@ -600,45 +601,6 @@ function Room:prepareGeneral(player, general, deputy, broadcast)
|
|||
end
|
||||
end
|
||||
|
||||
--- 房间信息摘要,返回房间的大致信息
|
||||
--- 用于旁观和重连,但也可用于debug
|
||||
function Room:getSummary(player, observe)
|
||||
local printed_cards = {}
|
||||
for i = -2, -math.huge, -1 do
|
||||
local c = Fk.printed_cards[i]
|
||||
if not c then break end
|
||||
table.insert(printed_cards, { c.name, c.suit, c.number })
|
||||
end
|
||||
|
||||
local players = {}
|
||||
for _, p in ipairs(self.players) do
|
||||
players[tostring(p.id)] = p:getSummary(player, observe)
|
||||
end
|
||||
|
||||
local cmarks = {}
|
||||
for k, v in pairs(self.card_marks) do
|
||||
cmarks[tostring(k)] = v
|
||||
end
|
||||
|
||||
return {
|
||||
you = player.id or player:getId(),
|
||||
-- data for EnterRoom
|
||||
d = {
|
||||
-- #self.players, 留给客户端自己思考
|
||||
self.timeout,
|
||||
self.settings,
|
||||
},
|
||||
pc = printed_cards,
|
||||
cm = cmarks,
|
||||
b = self.banners,
|
||||
|
||||
circle = table.map(self.players, Util.IdMapper),
|
||||
p = players,
|
||||
rnd = self:getTag("RoundCount") or 0,
|
||||
dp = #self.draw_pile,
|
||||
}
|
||||
end
|
||||
|
||||
function Room:toJsonObject(player)
|
||||
local o = AbstractRoom.toJsonObject(self)
|
||||
o.round_count = self:getTag("RoundCount") or 0
|
||||
|
@ -1169,7 +1131,7 @@ end
|
|||
---@param no_indicate? boolean @ 是否不显示指示线
|
||||
---@return integer[] @ 选择的牌的id列表,可能是空的
|
||||
function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt, expand_pile, no_indicate)
|
||||
if minNum < 1 then
|
||||
if maxNum < 1 then
|
||||
return {}
|
||||
end
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
|
@ -1312,7 +1274,7 @@ end
|
|||
---@param expand_pile? string @ 可选私人牌堆名称,如要分配你武将牌上的牌请填写
|
||||
---@param skipMove? boolean @ 是否跳过移动。默认不跳过
|
||||
---@param single_max? integer|table @ 限制每人能获得的最大牌数。输入整数或(以角色id为键以整数为值)的表
|
||||
---@return table<integer[]> @ 返回一个表,键为角色id,值为分配给其的牌id数组
|
||||
---@return table<integer, integer[]> @ 返回一个表,键为角色id转字符串,值为分配给其的牌id数组
|
||||
function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prompt, expand_pile, skipMove, single_max)
|
||||
targets = targets or self.alive_players
|
||||
cards = cards or player:getCardIds("he")
|
||||
|
@ -1347,7 +1309,7 @@ function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prom
|
|||
residued_list = residueMap,
|
||||
expand_pile = expand_pile
|
||||
}
|
||||
p(json.encode(residueMap))
|
||||
-- p(json.encode(residueMap))
|
||||
|
||||
while maxNum > 0 and #_cards > 0 do
|
||||
data.max_num = maxNum
|
||||
|
@ -1384,7 +1346,7 @@ function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prom
|
|||
end
|
||||
end
|
||||
if not skipMove then
|
||||
self:doYiji(self, list, player.id, skillName)
|
||||
self:doYiji(list, player.id, skillName)
|
||||
end
|
||||
|
||||
return list
|
||||
|
@ -2019,18 +1981,20 @@ end
|
|||
--- 询问玩家任意交换几堆牌堆。
|
||||
---
|
||||
---@param player ServerPlayer @ 要询问的玩家
|
||||
---@param piles table<string, integer[]> @ 卡牌id列表的列表,也就是……几堆牌堆的集合
|
||||
---@param piles_name string[] @ 牌堆名,必须一一对应,否则统一替换为“牌堆X”
|
||||
---@param piles (integer[])[] @ 卡牌id列表的列表,也就是……几堆牌堆的集合
|
||||
---@param piles_name string[] @ 牌堆名,不足部分替换为“牌堆1、牌堆2...”
|
||||
---@param customNotify? string @ 自定义读条操作提示
|
||||
---@return table<string, integer[]>
|
||||
---@return (integer[])[]
|
||||
function Room:askForExchange(player, piles, piles_name, customNotify)
|
||||
local command = "AskForExchange"
|
||||
piles_name = piles_name or Util.DummyTable
|
||||
if #piles_name ~= #piles then
|
||||
piles_name = {}
|
||||
for i, _ in ipairs(piles) do
|
||||
local x = #piles - #piles_name
|
||||
if x > 0 then
|
||||
for i = 1, x, 1 do
|
||||
table.insert(piles_name, Fk:translate("Pile") .. i)
|
||||
end
|
||||
elseif x < 0 then
|
||||
piles_name = table.slice(piles_name, 1, #piles + 1)
|
||||
end
|
||||
self:notifyMoveFocus(player, customNotify or command)
|
||||
local data = {
|
||||
|
@ -2884,6 +2848,7 @@ function Room:abortPlayerArea(player, playerSlots)
|
|||
from = player.id,
|
||||
toArea = Card.DiscardPile,
|
||||
moveReason = fk.ReasonPutIntoDiscardPile,
|
||||
skillName = "gamerule_aborted"
|
||||
})
|
||||
|
||||
table.insertTable(player.sealedSlots, slotsToSeal)
|
||||
|
|
|
@ -46,12 +46,12 @@ function HandleRequest(req)
|
|||
return true
|
||||
end
|
||||
|
||||
function ResumeRoom(roomId)
|
||||
function ResumeRoom(roomId, reason)
|
||||
local room = requestRoom:getRoom(roomId)
|
||||
if not room then return false end
|
||||
if not room:isReady() then return false end
|
||||
RoomInstance = (room ~= requestRoom and room or nil)
|
||||
local over = room:resume()
|
||||
local over = room:resume(reason)
|
||||
RoomInstance = nil
|
||||
|
||||
if over then
|
||||
|
|
|
@ -238,7 +238,7 @@ function ServerPlayer:gainAnExtraPhase(phase, delay)
|
|||
|
||||
local cancel_skip = true
|
||||
if phase ~= Player.NotActive and (skip) then
|
||||
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self)
|
||||
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, phase)
|
||||
end
|
||||
if (not skip) or (cancel_skip) then
|
||||
room:sendLog{
|
||||
|
@ -260,6 +260,7 @@ function ServerPlayer:gainAnExtraPhase(phase, delay)
|
|||
from = self.id,
|
||||
arg = Util.PhaseStrMapper(phase),
|
||||
}
|
||||
logic:trigger(fk.EventPhaseSkipped, self, phase)
|
||||
end
|
||||
|
||||
self.phase = current
|
||||
|
@ -322,7 +323,7 @@ function ServerPlayer:play(phase_table)
|
|||
|
||||
local cancel_skip = true
|
||||
if phases[i] ~= Player.NotActive and (skip) then
|
||||
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self)
|
||||
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, self.phase)
|
||||
end
|
||||
|
||||
if (not skip) or (cancel_skip) then
|
||||
|
@ -333,6 +334,7 @@ function ServerPlayer:play(phase_table)
|
|||
from = self.id,
|
||||
arg = Util.PhaseStrMapper(self.phase),
|
||||
}
|
||||
logic:trigger(fk.EventPhaseSkipped, self, self.phase)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,6 +48,7 @@ GameRule = fk.CreateTriggerSkill{
|
|||
end
|
||||
|
||||
cardNames = table.filter(cardNames, function (cardName)
|
||||
-- FIXME: 应该印一个“任何情况都适合”的牌,或者说根本不该有这个过滤
|
||||
local cardCloned = Fk:cloneCard(cardName)
|
||||
return not (player:prohibitUse(cardCloned) or player:isProhibited(dyingPlayer, cardCloned))
|
||||
end)
|
||||
|
|
|
@ -8,7 +8,8 @@ Fk:loadTranslationTable({
|
|||
["log_heart"] = '<font color="#CC3131">♥</font>',
|
||||
["log_club"] = '♣',
|
||||
["log_diamond"] = '<font color="#CC3131">♦</font>',
|
||||
["log_nosuit"] = "No suit",
|
||||
["log_nosuit"] = "X",
|
||||
["log_unknown"] = "?",
|
||||
-- ["spade"] = "Spade",
|
||||
-- ["heart"] = "Heart",
|
||||
-- ["club"] = "Club",
|
||||
|
|
|
@ -8,7 +8,9 @@ Fk:loadTranslationTable{
|
|||
["log_heart"] = '<font color="#CC3131">♥</font>',
|
||||
["log_club"] = '♣',
|
||||
["log_diamond"] = '<font color="#CC3131">♦</font>',
|
||||
["log_nosuit"] = "无花色",
|
||||
["log_nosuit"] = "X",
|
||||
["log_unknown"] = "?",
|
||||
["unknown"] = "未知",
|
||||
["spade"] = "黑桃",
|
||||
["heart"] = "红桃",
|
||||
["club"] = "梅花",
|
||||
|
|
Loading…
Reference in New Issue
Block a user