2023-04-09 13:35:35 +08:00
|
|
|
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
2022-03-30 16:33:56 +08:00
|
|
|
|
---@class ServerPlayer : Player
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public serverplayer fk.ServerPlayer
|
|
|
|
|
---@field public room Room
|
|
|
|
|
---@field public next ServerPlayer
|
|
|
|
|
---@field public request_data string
|
2024-01-11 18:36:05 +08:00
|
|
|
|
---@field public mini_game_data any
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public client_reply string
|
|
|
|
|
---@field public default_reply string
|
|
|
|
|
---@field public reply_ready boolean
|
|
|
|
|
---@field public reply_cancel boolean
|
|
|
|
|
---@field public phases Phase[]
|
|
|
|
|
---@field public skipped_phases Phase[]
|
|
|
|
|
---@field public phase_state table[]
|
|
|
|
|
---@field public phase_index integer
|
2023-08-09 22:25:15 +08:00
|
|
|
|
---@field private _fake_skills Skill[]
|
2023-09-06 22:16:09 +08:00
|
|
|
|
---@field private _manually_fake_skills Skill[]
|
2023-08-09 22:25:15 +08:00
|
|
|
|
---@field public prelighted_skills Skill[]
|
2023-08-02 21:40:00 +08:00
|
|
|
|
---@field private _timewaste_count integer
|
2023-03-26 17:32:45 +08:00
|
|
|
|
---@field public ai AI
|
|
|
|
|
---@field public ai_data any
|
2022-03-27 14:49:41 +08:00
|
|
|
|
local ServerPlayer = Player:subclass("ServerPlayer")
|
2022-03-25 12:28:07 +08:00
|
|
|
|
|
2022-03-27 14:49:41 +08:00
|
|
|
|
function ServerPlayer:initialize(_self)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
Player.initialize(self)
|
2023-04-27 14:15:08 +08:00
|
|
|
|
self.serverplayer = _self -- 控制者
|
|
|
|
|
self._splayer = _self -- 真正在玩的玩家
|
|
|
|
|
self._observers = { _self } -- "旁观"中的玩家,然而不包括真正的旁观者
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.id = _self:getId()
|
|
|
|
|
self.room = nil
|
|
|
|
|
|
|
|
|
|
self.phases = {}
|
2022-12-20 18:40:17 +08:00
|
|
|
|
self.skipped_phases = {}
|
2023-12-09 21:57:47 +08:00
|
|
|
|
self.phase_state = {}
|
2023-08-09 22:25:15 +08:00
|
|
|
|
|
|
|
|
|
self._fake_skills = {}
|
2023-09-06 22:16:09 +08:00
|
|
|
|
self._manually_fake_skills = {}
|
2023-08-09 22:25:15 +08:00
|
|
|
|
self.prelighted_skills = {}
|
|
|
|
|
self._prelighted_skills = {}
|
|
|
|
|
|
2023-08-02 21:40:00 +08:00
|
|
|
|
self._timewaste_count = 0
|
2024-11-09 19:27:41 +08:00
|
|
|
|
self.ai = SmartAI:new(self)
|
2022-03-27 14:49:41 +08:00
|
|
|
|
end
|
|
|
|
|
|
2022-03-31 13:29:23 +08:00
|
|
|
|
---@param command string
|
|
|
|
|
---@param jsonData string
|
2022-03-28 22:24:30 +08:00
|
|
|
|
function ServerPlayer:doNotify(command, jsonData)
|
2024-06-10 15:19:47 +08:00
|
|
|
|
local room = self.room
|
2023-04-27 14:15:08 +08:00
|
|
|
|
for _, p in ipairs(self._observers) do
|
2024-06-10 15:19:47 +08:00
|
|
|
|
if p:getState() ~= fk.Player_Robot then
|
|
|
|
|
room.notify_count = room.notify_count + 1
|
|
|
|
|
end
|
2023-04-27 14:15:08 +08:00
|
|
|
|
p:doNotify(command, jsonData)
|
|
|
|
|
end
|
|
|
|
|
|
2023-02-15 19:54:35 +08:00
|
|
|
|
for _, t in ipairs(room.observers) do
|
|
|
|
|
local id, p = table.unpack(t)
|
2023-07-12 20:35:05 +08:00
|
|
|
|
if id == self.id and room.room:hasObserver(p) then
|
2023-02-15 19:54:35 +08:00
|
|
|
|
p:doNotify(command, jsonData)
|
|
|
|
|
end
|
|
|
|
|
end
|
2024-06-10 15:19:47 +08:00
|
|
|
|
|
|
|
|
|
if room.notify_count >= room.notify_max and
|
|
|
|
|
coroutine.status(room.main_co) == "normal" then
|
|
|
|
|
room:delay(100)
|
|
|
|
|
end
|
2022-03-28 22:24:30 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
-- FIXME: 基本都改成新写法后删了这个兼容玩意
|
|
|
|
|
function ServerPlayer:__index(k)
|
|
|
|
|
local request = self.room.last_request
|
|
|
|
|
if not request then return nil end
|
|
|
|
|
if k == "client_reply" then
|
|
|
|
|
return request.result[self.id]
|
|
|
|
|
elseif k == "reply_ready" then
|
|
|
|
|
return request.result[self.id] and request.result[self.id] ~= ""
|
2023-01-17 22:34:15 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-26 00:08:20 +08:00
|
|
|
|
-- FIXME: 理由同上,垃圾request体系赶紧狠狠重构
|
|
|
|
|
function ServerPlayer:__newindex(k, v)
|
|
|
|
|
if k == "client_reply" then
|
|
|
|
|
local request = self.room.last_request
|
|
|
|
|
if not request then return end
|
|
|
|
|
request.result[self.id] = v
|
|
|
|
|
return
|
|
|
|
|
elseif k == "reply_ready" then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
rawset(self, k, v)
|
|
|
|
|
end
|
|
|
|
|
|
2024-06-10 15:19:47 +08:00
|
|
|
|
--- 发送一句聊天
|
|
|
|
|
---@param msg string
|
|
|
|
|
function ServerPlayer:chat(msg)
|
|
|
|
|
self.room:doBroadcastNotify("Chat", json.encode {
|
|
|
|
|
type = 2,
|
|
|
|
|
sender = self.id,
|
|
|
|
|
msg = msg,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
function ServerPlayer:toJsonObject()
|
|
|
|
|
local o = Player.toJsonObject(self)
|
2024-04-19 20:53:19 +08:00
|
|
|
|
local sp = self._splayer
|
2024-10-22 00:10:53 +08:00
|
|
|
|
o.setup_data = {
|
|
|
|
|
self.id,
|
|
|
|
|
sp:getScreenName(),
|
|
|
|
|
sp:getAvatar(),
|
|
|
|
|
false,
|
|
|
|
|
sp:getTotalGameTime(),
|
2024-04-19 20:53:19 +08:00
|
|
|
|
}
|
2024-10-22 00:10:53 +08:00
|
|
|
|
return o
|
2023-01-17 22:34:15 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
-- 似乎没有必要
|
|
|
|
|
-- function ServerPlayer:loadJsonObject() end
|
|
|
|
|
|
2023-01-17 22:34:15 +08:00
|
|
|
|
function ServerPlayer:reconnect()
|
|
|
|
|
local room = self.room
|
2023-06-16 10:56:33 +08:00
|
|
|
|
self.serverplayer:setState(fk.Player_Online)
|
2023-01-17 22:34:15 +08:00
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
local summary = room:toJsonObject(self)
|
2024-04-19 20:53:19 +08:00
|
|
|
|
self:doNotify("Reconnect", json.encode(summary))
|
2023-01-17 22:34:15 +08:00
|
|
|
|
room:notifyProperty(self, self, "role")
|
2023-10-07 23:00:25 +08:00
|
|
|
|
self:doNotify("RoomOwner", json.encode{ room.room:getOwner():getId() })
|
2023-01-17 22:34:15 +08:00
|
|
|
|
|
2023-09-06 22:16:09 +08:00
|
|
|
|
-- send fake skills
|
|
|
|
|
for _, s in ipairs(self._manually_fake_skills) do
|
|
|
|
|
self:doNotify("AddSkill", json.encode{ self.id, s.name, true })
|
|
|
|
|
if table.contains(self.prelighted_skills, s) then
|
|
|
|
|
self:doNotify("PrelightSkill", json.encode{ s.name, true })
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-01-17 22:34:15 +08:00
|
|
|
|
room:broadcastProperty(self, "state")
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-01 20:51:01 +08:00
|
|
|
|
function ServerPlayer:isAlive()
|
2022-04-30 15:27:56 +08:00
|
|
|
|
return self.dead == false
|
2022-04-01 20:51:01 +08:00
|
|
|
|
end
|
|
|
|
|
|
2022-04-02 21:39:44 +08:00
|
|
|
|
function ServerPlayer:turnOver()
|
2023-05-28 18:45:54 +08:00
|
|
|
|
if self.room.logic:trigger(fk.BeforeTurnOver, self) then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.faceup = not self.faceup
|
|
|
|
|
self.room:broadcastProperty(self, "faceup")
|
2022-04-02 21:39:44 +08:00
|
|
|
|
|
2022-12-18 12:52:52 +08:00
|
|
|
|
self.room:sendLog{
|
|
|
|
|
type = "#TurnOver",
|
|
|
|
|
from = self.id,
|
|
|
|
|
arg = self.faceup and "face_up" or "face_down",
|
|
|
|
|
}
|
2023-05-28 18:45:54 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.room.logic:trigger(fk.TurnedOver, self)
|
2022-04-02 21:39:44 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
---@param cards integer|integer[]|Card|Card[]
|
2023-03-20 20:15:24 +08:00
|
|
|
|
function ServerPlayer:showCards(cards)
|
|
|
|
|
cards = Card:getIdList(cards)
|
2023-06-24 15:05:58 +08:00
|
|
|
|
for _, id in ipairs(cards) do
|
|
|
|
|
Fk:filterCard(id, self)
|
|
|
|
|
end
|
|
|
|
|
|
2023-03-20 20:15:24 +08:00
|
|
|
|
local room = self.room
|
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#ShowCard",
|
|
|
|
|
from = self.id,
|
|
|
|
|
card = cards,
|
|
|
|
|
}
|
|
|
|
|
room:doBroadcastNotify("ShowCard", json.encode{
|
|
|
|
|
from = self.id,
|
|
|
|
|
cards = cards,
|
|
|
|
|
})
|
2023-06-10 02:18:51 +08:00
|
|
|
|
room:sendFootnote(cards, {
|
|
|
|
|
type = "##ShowCard",
|
|
|
|
|
from = self.id,
|
|
|
|
|
})
|
2023-05-20 16:00:03 +08:00
|
|
|
|
|
|
|
|
|
room.logic:trigger(fk.CardShown, self, { cardIds = cards })
|
2023-03-20 20:15:24 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
|
2023-06-09 01:10:16 +08:00
|
|
|
|
|
2022-04-04 19:04:55 +08:00
|
|
|
|
---@param from_phase Phase
|
|
|
|
|
---@param to_phase Phase
|
|
|
|
|
function ServerPlayer:changePhase(from_phase, to_phase)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local room = self.room
|
|
|
|
|
local logic = room.logic
|
|
|
|
|
self.phase = Player.PhaseNone
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local phase_change = {
|
|
|
|
|
from = from_phase,
|
|
|
|
|
to = to_phase
|
|
|
|
|
}
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local skip = logic:trigger(fk.EventPhaseChanging, self, phase_change)
|
|
|
|
|
if skip and to_phase ~= Player.NotActive then
|
|
|
|
|
self.phase = from_phase
|
|
|
|
|
return true
|
|
|
|
|
end
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.phase = to_phase
|
2023-07-16 15:32:16 +08:00
|
|
|
|
room:broadcastProperty(self, "phase")
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2023-02-26 16:51:29 +08:00
|
|
|
|
if #self.phases > 0 then
|
2022-04-30 15:27:56 +08:00
|
|
|
|
table.remove(self.phases, 1)
|
|
|
|
|
end
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2024-06-10 15:19:47 +08:00
|
|
|
|
GameEvent.Phase:create(self, self.phase):exec()
|
2022-04-30 15:27:56 +08:00
|
|
|
|
|
|
|
|
|
return false
|
2022-04-04 19:04:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
---@param phase Phase
|
|
|
|
|
---@param delay? boolean
|
2023-06-09 01:10:16 +08:00
|
|
|
|
function ServerPlayer:gainAnExtraPhase(phase, delay)
|
2023-04-22 15:52:26 +08:00
|
|
|
|
local room = self.room
|
2023-06-09 01:10:16 +08:00
|
|
|
|
delay = (delay == nil) and true or delay
|
2023-12-09 21:57:47 +08:00
|
|
|
|
local logic = room.logic
|
2023-06-09 01:10:16 +08:00
|
|
|
|
if delay then
|
|
|
|
|
local turn = logic:getCurrentEvent():findParent(GameEvent.Phase, true)
|
|
|
|
|
if turn then
|
2023-09-19 14:27:54 +08:00
|
|
|
|
turn:prependExitFunc(function() self:gainAnExtraPhase(phase, false) end)
|
2023-06-09 01:10:16 +08:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-22 15:52:26 +08:00
|
|
|
|
local current = self.phase
|
2023-12-09 21:57:47 +08:00
|
|
|
|
|
|
|
|
|
local phase_change = {
|
|
|
|
|
from = current,
|
|
|
|
|
to = phase
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local skip = logic:trigger(fk.EventPhaseChanging, self, phase_change)
|
|
|
|
|
|
|
|
|
|
phase = phase_change.to
|
2023-04-22 15:52:26 +08:00
|
|
|
|
self.phase = phase
|
2023-07-16 15:32:16 +08:00
|
|
|
|
room:broadcastProperty(self, "phase")
|
2023-04-22 15:52:26 +08:00
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
local cancel_skip = true
|
|
|
|
|
if phase ~= Player.NotActive and (skip) then
|
2024-10-24 21:57:26 +08:00
|
|
|
|
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, phase)
|
2023-12-09 21:57:47 +08:00
|
|
|
|
end
|
|
|
|
|
if (not skip) or (cancel_skip) then
|
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#GainAnExtraPhase",
|
|
|
|
|
from = self.id,
|
2024-10-22 00:10:53 +08:00
|
|
|
|
arg = Util.PhaseStrMapper(phase),
|
2023-12-09 21:57:47 +08:00
|
|
|
|
}
|
2023-06-09 01:10:16 +08:00
|
|
|
|
|
2024-06-10 15:19:47 +08:00
|
|
|
|
GameEvent.Phase:create(self, self.phase):exec()
|
2023-12-09 21:57:47 +08:00
|
|
|
|
|
|
|
|
|
phase_change = {
|
|
|
|
|
from = phase,
|
|
|
|
|
to = current
|
|
|
|
|
}
|
|
|
|
|
logic:trigger(fk.EventPhaseChanging, self, phase_change)
|
|
|
|
|
else
|
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#PhaseSkipped",
|
|
|
|
|
from = self.id,
|
2024-10-22 00:10:53 +08:00
|
|
|
|
arg = Util.PhaseStrMapper(phase),
|
2023-12-09 21:57:47 +08:00
|
|
|
|
}
|
2024-10-24 21:57:26 +08:00
|
|
|
|
logic:trigger(fk.EventPhaseSkipped, self, phase)
|
2023-12-09 21:57:47 +08:00
|
|
|
|
end
|
2023-04-22 15:52:26 +08:00
|
|
|
|
|
|
|
|
|
self.phase = current
|
2023-07-16 15:32:16 +08:00
|
|
|
|
room:broadcastProperty(self, "phase")
|
2023-04-22 15:52:26 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param phase_table? Phase[]
|
2022-04-04 19:04:55 +08:00
|
|
|
|
function ServerPlayer:play(phase_table)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
phase_table = phase_table or {}
|
|
|
|
|
if #phase_table > 0 then
|
2024-11-09 19:27:41 +08:00
|
|
|
|
if not table.contains(phase_table, Player.RoundStart) then
|
|
|
|
|
table.insert(phase_table, 1, Player.RoundStart)
|
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if not table.contains(phase_table, Player.NotActive) then
|
|
|
|
|
table.insert(phase_table, Player.NotActive)
|
2022-04-04 19:04:55 +08:00
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
else
|
|
|
|
|
phase_table = {
|
|
|
|
|
Player.RoundStart, Player.Start,
|
|
|
|
|
Player.Judge, Player.Draw, Player.Play, Player.Discard,
|
|
|
|
|
Player.Finish, Player.NotActive,
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.phases = phase_table
|
|
|
|
|
self.phase_state = {}
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local phases = self.phases
|
|
|
|
|
local phase_state = self.phase_state
|
|
|
|
|
local room = self.room
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
for i = 1, #phases do
|
|
|
|
|
phase_state[i] = {
|
|
|
|
|
phase = phases[i],
|
2022-12-20 18:40:17 +08:00
|
|
|
|
skipped = self.skipped_phases[phases[i]] or false
|
2022-04-30 15:27:56 +08:00
|
|
|
|
}
|
|
|
|
|
end
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
for i = 1, #phases do
|
2024-10-22 00:10:53 +08:00
|
|
|
|
if self.dead or room:getTag("endTurn") or phases[i] == nil then
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self:changePhase(self.phase, Player.NotActive)
|
|
|
|
|
break
|
2022-04-04 19:04:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.phase_index = i
|
|
|
|
|
local phase_change = {
|
|
|
|
|
from = self.phase,
|
|
|
|
|
to = phases[i]
|
|
|
|
|
}
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local logic = self.room.logic
|
|
|
|
|
self.phase = Player.PhaseNone
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-12-20 18:40:17 +08:00
|
|
|
|
local skip = phase_state[i].skipped
|
|
|
|
|
if not skip then
|
|
|
|
|
skip = logic:trigger(fk.EventPhaseChanging, self, phase_change)
|
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
phases[i] = phase_change.to
|
|
|
|
|
phase_state[i].phase = phases[i]
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
self.phase = phases[i]
|
2023-07-16 15:32:16 +08:00
|
|
|
|
room:broadcastProperty(self, "phase")
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
local cancel_skip = true
|
2022-12-20 18:40:17 +08:00
|
|
|
|
if phases[i] ~= Player.NotActive and (skip) then
|
2024-10-24 21:57:26 +08:00
|
|
|
|
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, self.phase)
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-04 19:04:55 +08:00
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
|
if (not skip) or (cancel_skip) then
|
2024-06-10 15:19:47 +08:00
|
|
|
|
GameEvent.Phase:create(self, self.phase):exec()
|
2022-12-20 18:40:17 +08:00
|
|
|
|
else
|
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#PhaseSkipped",
|
|
|
|
|
from = self.id,
|
2024-10-22 00:10:53 +08:00
|
|
|
|
arg = Util.PhaseStrMapper(self.phase),
|
2022-12-20 18:40:17 +08:00
|
|
|
|
}
|
2024-10-24 21:57:26 +08:00
|
|
|
|
logic:trigger(fk.EventPhaseSkipped, self, self.phase)
|
2022-12-20 18:40:17 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@param phase Phase
|
|
|
|
|
function ServerPlayer:skip(phase)
|
|
|
|
|
if not table.contains({
|
|
|
|
|
Player.Judge,
|
|
|
|
|
Player.Draw,
|
|
|
|
|
Player.Play,
|
|
|
|
|
Player.Discard
|
|
|
|
|
}, phase) then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
self.skipped_phases[phase] = true
|
|
|
|
|
for _, t in ipairs(self.phase_state) do
|
|
|
|
|
if t.phase == phase then
|
|
|
|
|
t.skipped = true
|
2022-04-04 19:04:55 +08:00
|
|
|
|
end
|
2022-04-30 15:27:56 +08:00
|
|
|
|
end
|
2022-04-04 19:04:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-09-19 14:27:54 +08:00
|
|
|
|
--- 当进行到出牌阶段空闲点时,结束出牌阶段。
|
2023-08-12 00:50:17 +08:00
|
|
|
|
function ServerPlayer:endPlayPhase()
|
2024-10-22 00:10:53 +08:00
|
|
|
|
if self.phase == Player.Play then
|
|
|
|
|
self._phase_end = true
|
|
|
|
|
end
|
2023-08-12 00:50:17 +08:00
|
|
|
|
-- TODO: send log
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-22 00:10:53 +08:00
|
|
|
|
--- 结束当前阶段。
|
|
|
|
|
function ServerPlayer:endCurrentPhase()
|
|
|
|
|
self._phase_end = true
|
|
|
|
|
end
|
|
|
|
|
|
2024-02-04 15:30:27 +08:00
|
|
|
|
--- 获得一个额外回合
|
2024-11-09 19:27:41 +08:00
|
|
|
|
---@param delay? boolean @ 是否延迟到当前回合结束再开启额外回合,默认是
|
|
|
|
|
---@param skillName? string @ 额外回合原因
|
|
|
|
|
---@param turnData? TurnStruct @ 额外回合的信息
|
|
|
|
|
function ServerPlayer:gainAnExtraTurn(delay, skillName, turnData)
|
2023-03-13 20:51:12 +08:00
|
|
|
|
local room = self.room
|
2023-06-09 01:10:16 +08:00
|
|
|
|
delay = (delay == nil) and true or delay
|
2024-11-09 19:27:41 +08:00
|
|
|
|
skillName = skillName or room.logic:getCurrentSkillName() or "game_rule"
|
|
|
|
|
turnData = turnData or {}
|
|
|
|
|
turnData.reason = skillName
|
2023-06-09 01:10:16 +08:00
|
|
|
|
if delay then
|
2024-11-09 19:27:41 +08:00
|
|
|
|
local turn = room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
|
2023-06-09 01:10:16 +08:00
|
|
|
|
if turn then
|
2024-11-09 19:27:41 +08:00
|
|
|
|
turn:prependExitFunc(function() self:gainAnExtraTurn(false, skillName, turnData) end)
|
2023-06-09 01:10:16 +08:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-03-13 20:51:12 +08:00
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#GainAnExtraTurn",
|
|
|
|
|
from = self.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local current = room.current
|
|
|
|
|
room.current = self
|
2023-09-19 14:27:54 +08:00
|
|
|
|
|
2024-11-09 19:27:41 +08:00
|
|
|
|
room:addTableMark(self, "_extra_turn_count", skillName)
|
2023-09-19 14:27:54 +08:00
|
|
|
|
|
2024-11-09 19:27:41 +08:00
|
|
|
|
GameEvent.Turn:create(self, turnData):exec()
|
2023-09-19 14:27:54 +08:00
|
|
|
|
|
2024-11-09 19:27:41 +08:00
|
|
|
|
local mark = self:getTableMark("_extra_turn_count")
|
|
|
|
|
if #mark > 0 then
|
|
|
|
|
table.remove(mark)
|
|
|
|
|
room:setPlayerMark(self, "_extra_turn_count", mark)
|
|
|
|
|
end
|
2023-09-19 14:27:54 +08:00
|
|
|
|
|
2023-03-13 20:51:12 +08:00
|
|
|
|
room.current = current
|
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
--- 当前是否处于额外的回合。
|
|
|
|
|
--- @return boolean
|
2023-09-19 14:27:54 +08:00
|
|
|
|
function ServerPlayer:insideExtraTurn()
|
2024-11-09 19:27:41 +08:00
|
|
|
|
return self:getCurrentExtraTurnReason() ~= "game_rule"
|
2023-09-19 14:27:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-11-09 19:27:41 +08:00
|
|
|
|
--- 当前额外回合的技能原因。非额外回合则为game_rule
|
2023-09-19 14:27:54 +08:00
|
|
|
|
---@return string
|
|
|
|
|
function ServerPlayer:getCurrentExtraTurnReason()
|
2024-11-09 19:27:41 +08:00
|
|
|
|
local mark = self:getTableMark("_extra_turn_count")
|
|
|
|
|
return mark[#mark] or "game_rule"
|
2023-09-19 14:27:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
--- 角色摸牌。
|
|
|
|
|
---@param num integer @ 摸牌数
|
|
|
|
|
---@param skillName? string @ 技能名
|
|
|
|
|
---@param fromPlace? string @ 摸牌的位置,"top" 或者 "bottom"
|
2024-06-10 15:19:47 +08:00
|
|
|
|
---@param moveMark? table|string @ 移动后自动赋予标记,格式:{标记名(支持-inarea后缀,移出值代表区域后清除), 值}
|
2023-12-09 21:57:47 +08:00
|
|
|
|
---@return integer[] @ 摸到的牌
|
2024-06-10 15:19:47 +08:00
|
|
|
|
function ServerPlayer:drawCards(num, skillName, fromPlace, moveMark)
|
|
|
|
|
return self.room:drawCards(self, num, skillName, fromPlace, moveMark)
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-02-21 13:44:24 +08:00
|
|
|
|
---@param pile_name string
|
2024-06-10 15:19:47 +08:00
|
|
|
|
---@param card integer | integer[] | Card | Card[]
|
2023-12-09 21:57:47 +08:00
|
|
|
|
---@param visible? boolean
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param skillName? string
|
2024-06-10 15:19:47 +08:00
|
|
|
|
---@param proposer? integer
|
|
|
|
|
---@param visiblePlayers? integer | integer[] @ 为nil时默认对自己可见
|
|
|
|
|
function ServerPlayer:addToPile(pile_name, card, visible, skillName, proposer, visiblePlayers)
|
|
|
|
|
self.room:moveCardTo(card, Card.PlayerSpecial, self, fk.ReasonJustMove, skillName, pile_name, visible,
|
|
|
|
|
proposer or self.id, nil, visiblePlayers)
|
2023-02-21 13:44:24 +08:00
|
|
|
|
end
|
|
|
|
|
|
2022-12-20 12:51:54 +08:00
|
|
|
|
function ServerPlayer:bury()
|
2023-03-18 23:37:21 +08:00
|
|
|
|
self:setCardUseHistory("")
|
|
|
|
|
self:setSkillUseHistory("")
|
2022-12-20 12:51:54 +08:00
|
|
|
|
self:throwAllCards()
|
2023-03-18 23:37:21 +08:00
|
|
|
|
self:throwAllMarks()
|
|
|
|
|
self:clearPiles()
|
2024-11-09 19:27:41 +08:00
|
|
|
|
self:onAllSkillLose()
|
2023-07-11 23:16:46 +08:00
|
|
|
|
self:reset()
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:throwAllCards(flag)
|
2023-08-03 15:26:52 +08:00
|
|
|
|
local cardIds = {}
|
2022-12-20 12:51:54 +08:00
|
|
|
|
flag = flag or "hej"
|
|
|
|
|
if string.find(flag, "h") then
|
2023-08-03 15:26:52 +08:00
|
|
|
|
table.insertTable(cardIds, self.player_cards[Player.Hand])
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if string.find(flag, "e") then
|
2023-08-03 15:26:52 +08:00
|
|
|
|
table.insertTable(cardIds, self.player_cards[Player.Equip])
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if string.find(flag, "j") then
|
2023-08-03 15:26:52 +08:00
|
|
|
|
table.insertTable(cardIds, self.player_cards[Player.Judge])
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
2023-08-03 15:26:52 +08:00
|
|
|
|
|
|
|
|
|
self.room:throwCard(cardIds, "", self)
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-11-09 19:27:41 +08:00
|
|
|
|
function ServerPlayer:onAllSkillLose()
|
|
|
|
|
for _, skill in ipairs(self:getAllSkills()) do
|
|
|
|
|
skill:onLose(self, true)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-03-18 23:37:21 +08:00
|
|
|
|
function ServerPlayer:throwAllMarks()
|
|
|
|
|
for name, _ in pairs(self.mark) do
|
|
|
|
|
self.room:setPlayerMark(self, name, 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:clearPiles()
|
2023-08-03 15:26:52 +08:00
|
|
|
|
local cardIds = {}
|
2023-03-18 23:37:21 +08:00
|
|
|
|
for _, ids in pairs(self.special_cards) do
|
2023-08-03 15:26:52 +08:00
|
|
|
|
table.insertTable(cardIds, ids)
|
2023-03-18 23:37:21 +08:00
|
|
|
|
end
|
2023-08-03 15:26:52 +08:00
|
|
|
|
self.room:moveCardTo(cardIds, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, "", nil, true)
|
2023-03-18 23:37:21 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function ServerPlayer:addVirtualEquip(card)
|
2024-06-10 15:19:47 +08:00
|
|
|
|
self:removeVirtualEquip(card:getEffectiveId())
|
2023-01-29 18:11:41 +08:00
|
|
|
|
Player.addVirtualEquip(self, card)
|
|
|
|
|
self.room:doBroadcastNotify("AddVirtualEquip", json.encode{
|
|
|
|
|
player = self.id,
|
|
|
|
|
name = card.name,
|
|
|
|
|
subcards = card.subcards,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:removeVirtualEquip(cid)
|
|
|
|
|
local ret = Player.removeVirtualEquip(self, cid)
|
2024-06-10 15:19:47 +08:00
|
|
|
|
if ret then
|
|
|
|
|
self.room:doBroadcastNotify("RemoveVirtualEquip", json.encode{
|
|
|
|
|
player = self.id,
|
|
|
|
|
id = cid,
|
|
|
|
|
})
|
|
|
|
|
end
|
2023-01-29 18:11:41 +08:00
|
|
|
|
return ret
|
|
|
|
|
end
|
|
|
|
|
|
2022-12-20 12:51:54 +08:00
|
|
|
|
function ServerPlayer:addCardUseHistory(cardName, num)
|
|
|
|
|
Player.addCardUseHistory(self, cardName, num)
|
|
|
|
|
self:doNotify("AddCardUseHistory", json.encode{cardName, num})
|
|
|
|
|
end
|
|
|
|
|
|
2023-01-29 18:11:41 +08:00
|
|
|
|
function ServerPlayer:setCardUseHistory(cardName, num, scope)
|
|
|
|
|
Player.setCardUseHistory(self, cardName, num, scope)
|
|
|
|
|
self:doNotify("SetCardUseHistory", json.encode{cardName, num, scope})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:addSkillUseHistory(cardName, num)
|
|
|
|
|
Player.addSkillUseHistory(self, cardName, num)
|
2023-04-05 01:05:06 +08:00
|
|
|
|
self.room:doBroadcastNotify("AddSkillUseHistory", json.encode{self.id, cardName, num})
|
2023-01-29 18:11:41 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:setSkillUseHistory(cardName, num, scope)
|
|
|
|
|
Player.setSkillUseHistory(self, cardName, num, scope)
|
2023-04-05 01:05:06 +08:00
|
|
|
|
self.room:doBroadcastNotify("SetSkillUseHistory", json.encode{self.id, cardName, num, scope})
|
2022-12-20 12:51:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-03-09 12:19:16 +08:00
|
|
|
|
---@param chained boolean
|
|
|
|
|
function ServerPlayer:setChainState(chained)
|
2023-08-03 15:26:52 +08:00
|
|
|
|
local room = self.room
|
|
|
|
|
if room.logic:trigger(fk.BeforeChainStateChange, self) then
|
2023-05-28 18:45:54 +08:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2023-03-09 12:19:16 +08:00
|
|
|
|
self.chained = chained
|
2023-08-03 15:26:52 +08:00
|
|
|
|
|
|
|
|
|
room:broadcastProperty(self, "chained")
|
|
|
|
|
room:sendLog{
|
2023-03-09 12:19:16 +08:00
|
|
|
|
type = "#ChainStateChange",
|
|
|
|
|
from = self.id,
|
2023-07-11 23:16:46 +08:00
|
|
|
|
arg = self.chained and "chained" or "un-chained"
|
2023-03-09 12:19:16 +08:00
|
|
|
|
}
|
2023-08-03 15:26:52 +08:00
|
|
|
|
room:delay(150)
|
|
|
|
|
room:broadcastPlaySound("./audio/system/chain")
|
|
|
|
|
room.logic:trigger(fk.ChainStateChanged, self)
|
2023-03-09 12:19:16 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-07-11 23:16:46 +08:00
|
|
|
|
function ServerPlayer:reset()
|
2023-09-27 21:02:22 +08:00
|
|
|
|
if self.faceup and not self.chained then return end
|
2023-07-11 23:16:46 +08:00
|
|
|
|
self.room:sendLog{
|
2023-08-02 02:19:51 +08:00
|
|
|
|
type = "#ChainStateChange",
|
2023-07-11 23:16:46 +08:00
|
|
|
|
from = self.id,
|
2023-08-02 02:19:51 +08:00
|
|
|
|
arg = "reset-general"
|
2023-07-11 23:16:46 +08:00
|
|
|
|
}
|
2023-09-06 22:16:09 +08:00
|
|
|
|
if self.chained then self:setChainState(false) end
|
2023-07-11 23:16:46 +08:00
|
|
|
|
if not self.faceup then self:turnOver() end
|
|
|
|
|
end
|
|
|
|
|
|
2023-09-06 22:16:09 +08:00
|
|
|
|
--- 进行拼点。
|
2023-03-14 20:48:08 +08:00
|
|
|
|
---@param tos ServerPlayer[]
|
|
|
|
|
---@param skillName string
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param initialCard? Card
|
2023-03-14 20:48:08 +08:00
|
|
|
|
---@return PindianStruct
|
|
|
|
|
function ServerPlayer:pindian(tos, skillName, initialCard)
|
2023-04-30 18:55:59 +08:00
|
|
|
|
local pindianData = { from = self, tos = tos, reason = skillName, fromCard = initialCard, results = {} }
|
2023-03-14 20:48:08 +08:00
|
|
|
|
self.room:pindian(pindianData)
|
|
|
|
|
return pindianData
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:24 +08:00
|
|
|
|
--- 播放技能的语音。
|
|
|
|
|
---@param skill_name string @ 技能名
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param index? integer @ 语音编号,默认为-1(也就是随机播放)
|
2023-08-24 21:37:24 +08:00
|
|
|
|
function ServerPlayer:broadcastSkillInvoke(skill_name, index)
|
|
|
|
|
index = index or -1
|
|
|
|
|
self.room:sendLogEvent("PlaySkillSound", {
|
|
|
|
|
name = skill_name,
|
|
|
|
|
i = index,
|
|
|
|
|
general = self.general,
|
|
|
|
|
deputy = self.deputyGeneral,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
2023-04-23 21:10:07 +08:00
|
|
|
|
-- Hegemony func
|
|
|
|
|
|
2024-02-04 15:30:27 +08:00
|
|
|
|
---@param skill Skill | string
|
2023-08-09 22:25:15 +08:00
|
|
|
|
function ServerPlayer:addFakeSkill(skill)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
assert(type(skill) == "string" or skill:isInstanceOf(Skill))
|
|
|
|
|
if type(skill) == "string" then
|
|
|
|
|
skill = Fk.skills[skill]
|
|
|
|
|
end
|
2023-08-09 22:25:15 +08:00
|
|
|
|
if table.contains(self._fake_skills, skill) then return end
|
|
|
|
|
|
2023-09-06 22:16:09 +08:00
|
|
|
|
table.insertIfNeed(self._manually_fake_skills, skill)
|
|
|
|
|
|
2023-08-09 22:25:15 +08:00
|
|
|
|
table.insert(self._fake_skills, skill)
|
|
|
|
|
for _, s in ipairs(skill.related_skills) do
|
|
|
|
|
-- if s.main_skill == skill then -- TODO: need more detailed
|
|
|
|
|
table.insert(self._fake_skills, s)
|
|
|
|
|
-- end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- TODO
|
|
|
|
|
self:doNotify("AddSkill", json.encode{ self.id, skill.name, true })
|
|
|
|
|
end
|
|
|
|
|
|
2024-02-04 15:30:27 +08:00
|
|
|
|
---@param skill Skill | string
|
2023-08-09 22:25:15 +08:00
|
|
|
|
function ServerPlayer:loseFakeSkill(skill)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
assert(type(skill) == "string" or skill:isInstanceOf(Skill))
|
|
|
|
|
if type(skill) == "string" then
|
|
|
|
|
skill = Fk.skills[skill]
|
|
|
|
|
end
|
2023-08-09 22:25:15 +08:00
|
|
|
|
if not table.contains(self._fake_skills, skill) then return end
|
|
|
|
|
|
2023-09-06 22:16:09 +08:00
|
|
|
|
table.removeOne(self._manually_fake_skills, skill)
|
|
|
|
|
|
2023-08-09 22:25:15 +08:00
|
|
|
|
table.removeOne(self._fake_skills, skill)
|
|
|
|
|
for _, s in ipairs(skill.related_skills) do
|
|
|
|
|
table.removeOne(self._fake_skills, s)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- TODO
|
|
|
|
|
self:doNotify("LoseSkill", json.encode{ self.id, skill.name, true })
|
|
|
|
|
end
|
|
|
|
|
|
2024-02-04 15:30:27 +08:00
|
|
|
|
---@param skill Skill | string
|
2023-08-09 22:25:15 +08:00
|
|
|
|
function ServerPlayer:isFakeSkill(skill)
|
|
|
|
|
if type(skill) == "string" then skill = Fk.skills[skill] end
|
|
|
|
|
assert(skill:isInstanceOf(Skill))
|
|
|
|
|
return table.contains(self._fake_skills, skill)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@param skill string | Skill
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param isPrelight? boolean
|
2023-04-23 21:10:07 +08:00
|
|
|
|
function ServerPlayer:prelightSkill(skill, isPrelight)
|
2023-08-09 22:25:15 +08:00
|
|
|
|
if type(skill) == "string" then skill = Fk.skills[skill] end
|
|
|
|
|
assert(skill:isInstanceOf(Skill))
|
|
|
|
|
|
|
|
|
|
if not self._prelighted_skills[skill] and not self:hasSkill(skill) then
|
|
|
|
|
self._prelighted_skills[skill] = true
|
|
|
|
|
-- to attach skill to room
|
2023-04-23 21:10:07 +08:00
|
|
|
|
self:addSkill(skill)
|
|
|
|
|
self:loseSkill(skill)
|
|
|
|
|
end
|
2023-08-09 22:25:15 +08:00
|
|
|
|
|
|
|
|
|
if isPrelight then
|
|
|
|
|
-- self:addSkill(skill)
|
|
|
|
|
table.insert(self.prelighted_skills, skill)
|
|
|
|
|
for _, s in ipairs(skill.related_skills) do
|
|
|
|
|
table.insert(self.prelighted_skills, s)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
-- self:loseSkill(skill)
|
|
|
|
|
table.removeOne(self.prelighted_skills, skill)
|
|
|
|
|
for _, s in ipairs(skill.related_skills) do
|
|
|
|
|
table.removeOne(self.prelighted_skills, s)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self:doNotify("PrelightSkill", json.encode{ skill.name, isPrelight })
|
2023-04-23 21:10:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-12-03 19:35:14 +08:00
|
|
|
|
---@param isDeputy? boolean
|
|
|
|
|
---@param no_trigger? boolean
|
2023-08-24 21:37:06 +08:00
|
|
|
|
function ServerPlayer:revealGeneral(isDeputy, no_trigger)
|
2023-04-23 21:10:07 +08:00
|
|
|
|
local room = self.room
|
|
|
|
|
local generalName
|
|
|
|
|
if isDeputy then
|
|
|
|
|
if self.deputyGeneral ~= "anjiang" then return end
|
|
|
|
|
generalName = self:getMark("__heg_deputy")
|
|
|
|
|
else
|
|
|
|
|
if self.general ~= "anjiang" then return end
|
|
|
|
|
generalName = self:getMark("__heg_general")
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-25 17:14:43 +08:00
|
|
|
|
local general = Fk.generals[generalName] or Fk.generals["blank_shibing"]
|
2024-01-25 03:13:57 +08:00
|
|
|
|
for _, s in ipairs(general:getSkillNameList(true)) do
|
2023-04-23 21:10:07 +08:00
|
|
|
|
local skill = Fk.skills[s]
|
2023-08-09 22:25:15 +08:00
|
|
|
|
self:loseFakeSkill(skill)
|
2023-04-23 21:10:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:06 +08:00
|
|
|
|
local ret = true
|
|
|
|
|
if not ((isDeputy and self.general ~= "anjiang") or (not isDeputy and self.deputyGeneral ~= "anjiang")) then
|
2023-08-25 17:14:43 +08:00
|
|
|
|
local other = Fk.generals[self:getMark(isDeputy and "__heg_general" or "__heg_deputy")] or Fk.generals["blank_shibing"]
|
2024-01-25 03:13:57 +08:00
|
|
|
|
for _, sname in ipairs(other:getSkillNameList(true)) do
|
2023-08-24 21:37:06 +08:00
|
|
|
|
local s = Fk.skills[sname]
|
|
|
|
|
if s.frequency == Skill.Compulsory and s.relate_to_place ~= (isDeputy and "m" or "d") then
|
|
|
|
|
ret = false
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if ret then
|
2024-04-07 00:45:55 +08:00
|
|
|
|
self:loseFakeSkill("reveal_skill&")
|
2023-08-24 21:37:06 +08:00
|
|
|
|
end
|
|
|
|
|
|
2023-04-23 21:10:07 +08:00
|
|
|
|
local oldKingdom = self.kingdom
|
2023-09-30 11:51:17 +08:00
|
|
|
|
room:changeHero(self, generalName, false, isDeputy, false, false, false)
|
2023-08-25 17:14:43 +08:00
|
|
|
|
if oldKingdom ~= "wild" then
|
2023-09-30 11:51:17 +08:00
|
|
|
|
local kingdom = (self:getMark("__heg_wild") == 1 and not isDeputy) and "wild" or self:getMark("__heg_kingdom")
|
2023-08-25 17:14:43 +08:00
|
|
|
|
self.kingdom = kingdom
|
2023-09-30 11:51:17 +08:00
|
|
|
|
if oldKingdom == "unknown" and kingdom ~= "wild" and #table.filter(room:getOtherPlayers(self, false, true),
|
2023-08-25 17:14:43 +08:00
|
|
|
|
function(p)
|
|
|
|
|
return p.kingdom == kingdom
|
2023-09-30 11:51:17 +08:00
|
|
|
|
end) >= #room.players // 2 and table.every(room.alive_players, function(p) return p.kingdom ~= kingdom or not string.find(p.general, "lord") end) then
|
2023-08-25 17:14:43 +08:00
|
|
|
|
self.kingdom = "wild"
|
|
|
|
|
end
|
|
|
|
|
room:broadcastProperty(self, "kingdom")
|
|
|
|
|
else
|
|
|
|
|
room:setPlayerProperty(self, "kingdom", "wild")
|
|
|
|
|
end
|
2023-04-23 21:10:07 +08:00
|
|
|
|
|
2023-09-30 11:51:17 +08:00
|
|
|
|
if self.gender == General.Agender or self.gender ~= Fk.generals[self.general].gender then
|
|
|
|
|
room:setPlayerProperty(self, "gender", general.gender)
|
2023-04-23 21:10:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
room:sendLog{
|
|
|
|
|
type = "#RevealGeneral",
|
|
|
|
|
from = self.id,
|
|
|
|
|
arg = isDeputy and "deputyGeneral" or "mainGeneral",
|
|
|
|
|
arg2 = generalName,
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
|
local data = {[isDeputy and "d" or "m"] = generalName}
|
|
|
|
|
room.logic:trigger(fk.GeneralShown, self, data)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
if not no_trigger then
|
2023-11-07 21:14:51 +08:00
|
|
|
|
local current_event = room.logic:getCurrentEvent()
|
|
|
|
|
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.event) then
|
2023-12-09 21:57:47 +08:00
|
|
|
|
room.logic:trigger(fk.GeneralRevealed, self, data)
|
2023-11-07 21:14:51 +08:00
|
|
|
|
else
|
2023-12-09 21:57:47 +08:00
|
|
|
|
if current_event.parent then
|
|
|
|
|
repeat
|
|
|
|
|
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.parent.event) then break end
|
|
|
|
|
current_event = current_event.parent
|
|
|
|
|
until (not current_event.parent)
|
|
|
|
|
end
|
2023-11-07 21:14:51 +08:00
|
|
|
|
current_event:addExitFunc(function ()
|
2023-12-09 21:57:47 +08:00
|
|
|
|
room.logic:trigger(fk.GeneralRevealed, self, data)
|
2023-11-07 21:14:51 +08:00
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:revealGenerals()
|
|
|
|
|
self:revealGeneral(false, true)
|
|
|
|
|
self:revealGeneral(true, true)
|
|
|
|
|
local room = self.room
|
|
|
|
|
local current_event = room.logic:getCurrentEvent()
|
2023-12-09 21:57:47 +08:00
|
|
|
|
local data = {["m"] = self:getMark("__heg_general"), ["d"] = self:getMark("__heg_deputy")}
|
2023-11-07 21:14:51 +08:00
|
|
|
|
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.event) then
|
2023-12-09 21:57:47 +08:00
|
|
|
|
room.logic:trigger(fk.GeneralRevealed, self, data)
|
2023-11-07 21:14:51 +08:00
|
|
|
|
else
|
2023-12-09 21:57:47 +08:00
|
|
|
|
if current_event.parent then
|
|
|
|
|
repeat
|
|
|
|
|
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.parent.event) then break end
|
|
|
|
|
current_event = current_event.parent
|
|
|
|
|
until (not current_event.parent)
|
|
|
|
|
end
|
2023-11-07 21:14:51 +08:00
|
|
|
|
current_event:addExitFunc(function ()
|
2023-12-09 21:57:47 +08:00
|
|
|
|
room.logic:trigger(fk.GeneralRevealed, self, data)
|
2023-11-07 21:14:51 +08:00
|
|
|
|
end)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
end
|
2023-04-23 21:10:07 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:revealBySkillName(skill_name)
|
|
|
|
|
local main = self.general == "anjiang"
|
|
|
|
|
local deputy = self.deputyGeneral == "anjiang"
|
|
|
|
|
|
|
|
|
|
if main then
|
|
|
|
|
if table.contains(Fk.generals[self:getMark("__heg_general")]
|
2024-01-25 03:13:57 +08:00
|
|
|
|
:getSkillNameList(true), skill_name) then
|
2023-04-23 21:10:07 +08:00
|
|
|
|
self:revealGeneral(false)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if deputy then
|
|
|
|
|
if table.contains(Fk.generals[self:getMark("__heg_deputy")]
|
2024-01-25 03:13:57 +08:00
|
|
|
|
:getSkillNameList(true), skill_name) then
|
2023-04-23 21:10:07 +08:00
|
|
|
|
self:revealGeneral(true)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-24 21:37:06 +08:00
|
|
|
|
function ServerPlayer:hideGeneral(isDeputy)
|
|
|
|
|
local room = self.room
|
|
|
|
|
local generalName = isDeputy and self.deputyGeneral or self.general
|
|
|
|
|
local mark = isDeputy and "__heg_deputy" or "__heg_general"
|
|
|
|
|
|
|
|
|
|
self:setMark(mark, generalName)
|
|
|
|
|
self:doNotify("SetPlayerMark", json.encode{ self.id, mark, generalName})
|
|
|
|
|
|
|
|
|
|
if isDeputy then
|
|
|
|
|
room:setDeputyGeneral(self, "anjiang")
|
|
|
|
|
room:broadcastProperty(self, "deputyGeneral")
|
|
|
|
|
else
|
|
|
|
|
room:setPlayerGeneral(self, "anjiang", false)
|
|
|
|
|
room:broadcastProperty(self, "general")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local general = Fk.generals[generalName]
|
|
|
|
|
local place = isDeputy and "m" or "d"
|
2024-02-04 15:30:27 +08:00
|
|
|
|
for _, sname in ipairs(general:getSkillNameList()) do
|
2023-08-24 21:37:06 +08:00
|
|
|
|
room:handleAddLoseSkills(self, "-" .. sname, nil, false, true)
|
|
|
|
|
local s = Fk.skills[sname]
|
|
|
|
|
if s.relate_to_place ~= place then
|
|
|
|
|
if s.frequency == Skill.Compulsory then
|
2024-04-07 00:45:55 +08:00
|
|
|
|
self:addFakeSkill("reveal_skill&")
|
2023-08-24 21:37:06 +08:00
|
|
|
|
end
|
|
|
|
|
self:addFakeSkill(s)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2023-09-30 11:51:17 +08:00
|
|
|
|
self.gender = General.Agender
|
|
|
|
|
if Fk.generals[self.general].gender ~= General.Agender then
|
|
|
|
|
self.gender = Fk.generals[self.general].gender
|
|
|
|
|
elseif self.deputyGeneral and Fk.generals[self.deputyGeneral].gender ~= General.Agender then
|
|
|
|
|
self.gender = Fk.generals[self.deputyGeneral].gender
|
|
|
|
|
end
|
|
|
|
|
room:broadcastProperty(self, "gender")
|
|
|
|
|
|
|
|
|
|
room.logic:trigger(fk.GeneralHidden, self, generalName)
|
2023-08-24 21:37:06 +08:00
|
|
|
|
end
|
2023-09-30 11:51:17 +08:00
|
|
|
|
|
2023-04-27 14:15:08 +08:00
|
|
|
|
-- 神貂蝉
|
|
|
|
|
|
2023-07-14 23:12:46 +08:00
|
|
|
|
---@param p ServerPlayer
|
2023-04-27 14:15:08 +08:00
|
|
|
|
function ServerPlayer:control(p)
|
|
|
|
|
if self == p then
|
|
|
|
|
self.room:setPlayerMark(p, "@ControledBy", 0)
|
|
|
|
|
else
|
|
|
|
|
self.room:setPlayerMark(p, "@ControledBy", "seat#" .. self.seat)
|
|
|
|
|
end
|
|
|
|
|
p.serverplayer = self._splayer
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-12 00:50:17 +08:00
|
|
|
|
-- 22
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:addBuddy(other)
|
|
|
|
|
if type(other) == "number" then
|
|
|
|
|
other = self.room:getPlayerById(other)
|
|
|
|
|
end
|
|
|
|
|
Player.addBuddy(self, other)
|
2024-10-22 00:10:53 +08:00
|
|
|
|
self.room:doBroadcastNotify("AddBuddy", json.encode{ self.id, other.id })
|
2023-08-12 00:50:17 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ServerPlayer:removeBuddy(other)
|
|
|
|
|
if type(other) == "number" then
|
|
|
|
|
other = self.room:getPlayerById(other)
|
|
|
|
|
end
|
|
|
|
|
Player.removeBuddy(self, other)
|
2024-10-22 00:10:53 +08:00
|
|
|
|
self.room:doBroadcastNotify("RmBuddy", json.encode{ self.id, other.id })
|
2023-08-12 00:50:17 +08:00
|
|
|
|
end
|
|
|
|
|
|
2022-03-27 14:49:41 +08:00
|
|
|
|
return ServerPlayer
|