mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
parent
b50c94d171
commit
fc8be0ad40
104
docs/dev/shendiaochan.rst
Normal file
104
docs/dev/shendiaochan.rst
Normal file
|
@ -0,0 +1,104 @@
|
|||
神貂蝉
|
||||
======
|
||||
|
||||
“本回合改为由你操控。” ——神貂蝉
|
||||
|
||||
封装
|
||||
----
|
||||
|
||||
先画好靶子!想一下怎么定义函数才好!
|
||||
|
||||
- 你来操控别的角色
|
||||
- 别的角色重新操控自己
|
||||
- 你同时控制自己和别人
|
||||
- 询问无懈
|
||||
- 老朱然
|
||||
|
||||
考虑中:。...
|
||||
|
||||
.. code:: lua
|
||||
|
||||
ServerPlayer:control(ServerPlayer)
|
||||
ServerPlayer:observe(ServerPlayer)
|
||||
|
||||
两函数差不多了吧。。。
|
||||
|
||||
这样一来,神貂蝉就是让被控者observe,然后自己去control;回合结束后,被控者开始control。
|
||||
|
||||
observe
|
||||
-------
|
||||
|
||||
对机器人:无视。
|
||||
|
||||
对人:发送observe消息。但这个人依然处于room.players中,无论是Lua还是cpp。
|
||||
|
||||
只是这个人对应的cpp层面的ServerPlayer进旁观了而已。
|
||||
|
||||
control
|
||||
-------
|
||||
|
||||
控制者:发送control消息。控制者多了个可以控制的角色,仅此而已。
|
||||
|
||||
如果已有控制者:发送dontcontrol消息,不准打架 而这个消息最终还是走到observe消息处理
|
||||
|
||||
客户端实现
|
||||
----------
|
||||
|
||||
想好了怎么发消息那消息该怎么处理?
|
||||
|
||||
首先dontcontrol 把可控制者-1 没有可控了就进旁观呗
|
||||
|
||||
然后是control加一个受控者 要是旁观直接切视角
|
||||
|
||||
切视角
|
||||
------
|
||||
|
||||
先给个dashboard向下滑出并淡出消失的动画
|
||||
|
||||
Lua 改变 Self
|
||||
|
||||
根据服务端的信息填充这个新Self的信息
|
||||
|
||||
dashboard手牌清空
|
||||
|
||||
dashboard填入新Self的新手牌
|
||||
|
||||
dashboard重新出现
|
||||
|
||||
根据新Self重新安排所有photo
|
||||
|
||||
由于不影响烧条 这个动画效果越快越好
|
||||
|
||||
一控多时同时询问
|
||||
----------------
|
||||
|
||||
怎么办呢?问题的核心在于分属不同玩家的消息,却发送给了同一个人。这个可以通过在req/noti中堆个玩家id的参数搞定。但是然后呢?
|
||||
|
||||
一个很严重的问题就是目前对所有req的处理函数都是直接操作roomscene的元素的。实际上,这些元素对于每个被自己控制的player,都要单独有才行。
|
||||
|
||||
一个想法就是多创建room页面,模拟多开。但这个是做不到的,因为很多东西都依赖Self,而Self只有一个。所以就得在单页中解决这些问题。解决方案就是把那些跟req有关的分出去几个。
|
||||
|
||||
换句话说,捏几个元素出来表示各个player的状态,可能保存在Lua里面。当qml想要切换视角时,从Lua读取信息。
|
||||
|
||||
当某个人收到req时候,就切视角到他那里。所有人烧条打开。
|
||||
|
||||
或者也可以让req处理函数返回一个函数,切视角时执行之就行了。
|
||||
|
||||
也就是说 Room中元素还是那几个 只是随着视角改变他们的值也变 而改变视角会调用函数
|
||||
|
||||
其实可以考虑调用从Lua传来的cmdType和jsonData,然后就直接开函数了,更舒适。
|
||||
|
||||
延迟执行callback
|
||||
-----------------
|
||||
|
||||
考虑在notifyUI的时候,如果当前视角对应的玩家id和这个消息的id不同,那么就暂存到一个消息队列中,等到切视角时候就都拿出来。如果某时候,就把队列清空。
|
||||
|
||||
主要还是只过滤request吧。doNotify不需要过滤,换个视角也知道发生啥了。
|
||||
|
||||
也没必要维护队列。就一个单独的值保存最近的command和data即可。
|
||||
|
||||
当视角发生切换时,如果这个人有cmd和data,就执行相应的cb。
|
||||
|
||||
当向服务器发回答复后,cmd和data就没有了。
|
||||
|
||||
notify时只对看着这名角色主视角的玩家发送。
|
|
@ -114,7 +114,7 @@ function Client:appendLog(msg)
|
|||
return ""
|
||||
end
|
||||
local p = self:getPlayerById(pid)
|
||||
local str <const> = '<font color="%s"><b>%s</b></font>'
|
||||
local str = '<font color="%s"><b>%s</b></font>'
|
||||
if p.general == "anjiang" and (p.deputyGeneral == "anjiang"
|
||||
or not p.deputyGeneral) then
|
||||
local ret = Fk:translate("seat#" .. p.seat)
|
||||
|
@ -123,7 +123,7 @@ function Client:appendLog(msg)
|
|||
|
||||
local ret = p.general
|
||||
ret = Fk:translate(ret)
|
||||
if p.deputyGeneral then
|
||||
if p.deputyGeneral and p.deputyGeneral ~= "" then
|
||||
ret = ret .. "/" .. Fk:translate(p.deputyGeneral)
|
||||
end
|
||||
ret = string.format(str, color, ret)
|
||||
|
@ -672,6 +672,12 @@ fk.client_callback["Heartbeat"] = function()
|
|||
ClientInstance.client:notifyServer("Heartbeat", "")
|
||||
end
|
||||
|
||||
fk.client_callback["ChangeSelf"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
ClientInstance:getPlayerById(data.id).player_cards[Player.Hand] = data.handcards
|
||||
ClientInstance:notifyUI("ChangeSelf", data.id)
|
||||
end
|
||||
|
||||
-- Create ClientInstance (used by Lua)
|
||||
ClientInstance = Client:new()
|
||||
dofile "lua/client/client_util.lua"
|
||||
|
|
|
@ -324,6 +324,7 @@ function ActiveTargetFilter(skill_name, to_select, selected, selected_cards)
|
|||
local card = skill:viewAs(selected_cards)
|
||||
if card then
|
||||
ret = card.skill:targetFilter(to_select, selected, selected_cards)
|
||||
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), card)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -453,4 +454,16 @@ function SetInteractionDataOfSkill(skill_name, data)
|
|||
end
|
||||
end
|
||||
|
||||
function ChangeSelf(pid)
|
||||
local c = ClientInstance
|
||||
c.client:changeSelf(pid) -- for qml
|
||||
Self = c:getPlayerById(pid)
|
||||
end
|
||||
|
||||
function GetPlayerHandcards(pid)
|
||||
local c = ClientInstance
|
||||
local p = c:getPlayerById(pid)
|
||||
return json.encode(p.player_cards[Player.Hand])
|
||||
end
|
||||
|
||||
dofile "lua/client/i18n/init.lua"
|
||||
|
|
|
@ -163,6 +163,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["seat#6"] = "六号位",
|
||||
["seat#7"] = "七号位",
|
||||
["seat#8"] = "八号位",
|
||||
["@ControledBy"] = "控制者",
|
||||
|
||||
["Trust"] = "托管",
|
||||
["Sort Cards"] = "牌序",
|
||||
|
|
|
@ -44,10 +44,34 @@ function GameEvent:findParent(eventType)
|
|||
end
|
||||
|
||||
function GameEvent:clear()
|
||||
for _, f in ipairs(self.extra_clear_funcs) do
|
||||
if type(f) == "function" then f(self) end
|
||||
local clear_co = coroutine.create(function()
|
||||
for _, f in ipairs(self.extra_clear_funcs) do
|
||||
if type(f) == "function" then f(self) end
|
||||
end
|
||||
self:clear_func()
|
||||
end)
|
||||
|
||||
while true do
|
||||
local err, yield_result, extra_yield_result = coroutine.resume(clear_co)
|
||||
|
||||
if err == false then
|
||||
-- handle error, then break
|
||||
if not string.find(yield_result, "__manuallyBreak") then
|
||||
fk.qCritical(yield_result)
|
||||
print(debug.traceback(co))
|
||||
end
|
||||
coroutine.close(clear_co)
|
||||
break
|
||||
end
|
||||
|
||||
if yield_result == "__handleRequest" then
|
||||
-- yield to requestLoop
|
||||
coroutine.yield(yield_result, extra_yield_result)
|
||||
else
|
||||
coroutine.close(clear_co)
|
||||
break
|
||||
end
|
||||
end
|
||||
self:clear_func()
|
||||
end
|
||||
|
||||
local function breakEvent(self, extra_yield_result)
|
||||
|
|
|
@ -34,9 +34,11 @@ end
|
|||
|
||||
function GameLogic:run()
|
||||
-- default logic
|
||||
local room = self.room
|
||||
table.shuffle(self.room.players)
|
||||
self:assignRoles()
|
||||
self.room:adjustSeats()
|
||||
room:doBroadcastNotify("StartGame", "")
|
||||
room:adjustSeats()
|
||||
|
||||
self:chooseGenerals()
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
---@field public status_skills Skill[] @ 这个房间中含有的状态技列表
|
||||
---@field public settings table @ 房间的额外设置,差不多是json对象
|
||||
---@field public logic GameLogic @ 这个房间使用的游戏逻辑,可能根据游戏模式而变动
|
||||
---@field public request_queue table<userdata, table>
|
||||
---@field public request_self table<integer, integer>
|
||||
local Room = class("Room")
|
||||
|
||||
-- load classes used by the game
|
||||
|
@ -119,6 +121,8 @@ function Room:initialize(_room)
|
|||
for class, skills in pairs(Fk.global_status_skill) do
|
||||
self.status_skills[class] = {table.unpack(skills)}
|
||||
end
|
||||
self.request_queue = {}
|
||||
self.request_self = {}
|
||||
end
|
||||
|
||||
--- 正式在这个房间中开始游戏。
|
||||
|
@ -529,10 +533,13 @@ end
|
|||
---@return string | nil @ 收到的答复,如果wait为false的话就返回nil
|
||||
function Room:doRequest(player, command, jsonData, wait)
|
||||
if wait == nil then wait = true end
|
||||
self.request_queue = {}
|
||||
player:doRequest(command, jsonData, self.timeout)
|
||||
|
||||
if wait then
|
||||
return player:waitForReply(self.timeout)
|
||||
local ret = player:waitForReply(self.timeout)
|
||||
player.serverplayer:setBusy(false)
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -542,8 +549,9 @@ end
|
|||
---@param jsonData string @ 请求数据
|
||||
function Room:doBroadcastRequest(command, players, jsonData)
|
||||
players = players or self.players
|
||||
self.request_queue = {}
|
||||
for _, p in ipairs(players) do
|
||||
self:doRequest(p, command, jsonData or p.request_data, false)
|
||||
p:doRequest(command, jsonData or p.request_data)
|
||||
end
|
||||
|
||||
local remainTime = self.timeout
|
||||
|
@ -553,6 +561,10 @@ function Room:doBroadcastRequest(command, players, jsonData)
|
|||
elapsed = os.time() - currentTime
|
||||
p:waitForReply(remainTime - elapsed)
|
||||
end
|
||||
|
||||
for _, p in ipairs(players) do
|
||||
p.serverplayer:setBusy(false)
|
||||
end
|
||||
end
|
||||
|
||||
--- 向多名玩家发出竞争请求。
|
||||
|
@ -566,9 +578,12 @@ end
|
|||
---@return ServerPlayer | nil @ 在这次竞争请求中获胜的角色,可能是nil
|
||||
function Room:doRaceRequest(command, players, jsonData)
|
||||
players = players or self.players
|
||||
players = table.simpleClone(players)
|
||||
local player_len = #players
|
||||
-- self:notifyMoveFocus(players, command)
|
||||
self.request_queue = {}
|
||||
for _, p in ipairs(players) do
|
||||
self:doRequest(p, command, jsonData or p.request_data, false)
|
||||
p:doRequest(command, jsonData or p.request_data)
|
||||
end
|
||||
|
||||
local remainTime = self.timeout
|
||||
|
@ -576,10 +591,11 @@ function Room:doRaceRequest(command, players, jsonData)
|
|||
local elapsed = 0
|
||||
local winner
|
||||
local canceled_players = {}
|
||||
local ret
|
||||
while true do
|
||||
elapsed = os.time() - currentTime
|
||||
if remainTime - elapsed <= 0 then
|
||||
return nil
|
||||
break
|
||||
end
|
||||
for _, p in ipairs(players) do
|
||||
p:waitForReply(0)
|
||||
|
@ -589,21 +605,29 @@ function Room:doRaceRequest(command, players, jsonData)
|
|||
end
|
||||
|
||||
if p.reply_cancel then
|
||||
table.removeOne(players, p)
|
||||
table.insertIfNeed(canceled_players, p)
|
||||
end
|
||||
end
|
||||
if winner then
|
||||
self:doBroadcastNotify("CancelRequest", "")
|
||||
return winner
|
||||
ret = winner
|
||||
break
|
||||
end
|
||||
|
||||
if #players == #canceled_players then
|
||||
return nil
|
||||
if player_len == #canceled_players then
|
||||
break
|
||||
end
|
||||
|
||||
coroutine.yield("__handleRequest", remainTime - elapsed)
|
||||
fk.QThread_msleep(10)
|
||||
end
|
||||
|
||||
for _, p in ipairs(self.players) do
|
||||
p.serverplayer:setBusy(false)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
-- main loop for the request handling coroutine
|
||||
|
@ -691,6 +715,25 @@ function Room:requestLoop(rest_time)
|
|||
removeObserver(id)
|
||||
elseif command == "prelight" then
|
||||
self:getPlayerById(id):prelightSkill(reqlist[3], reqlist[4] == "true")
|
||||
elseif command == "changeself" then
|
||||
local toId = tonumber(reqlist[3])
|
||||
local from = self:getPlayerById(id)
|
||||
local to = self:getPlayerById(toId)
|
||||
local from_sp = from._splayer
|
||||
|
||||
-- 注意发来信息的玩家的主视角可能已经不是自己了
|
||||
-- 先换成正确的玩家
|
||||
from = table.find(self.players, function(p)
|
||||
return table.contains(p._observers, from_sp)
|
||||
end)
|
||||
|
||||
-- 切换视角
|
||||
table.removeOne(from._observers, from_sp)
|
||||
table.insert(to._observers, from_sp)
|
||||
from_sp:doNotify("ChangeSelf", json.encode {
|
||||
id = toId,
|
||||
handcards = to:getCardIds(Player.Hand),
|
||||
})
|
||||
end
|
||||
elseif rest_time > 10 then
|
||||
-- let current thread sleep 10ms
|
||||
|
@ -2399,6 +2442,33 @@ function Room:adjustSeats()
|
|||
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
||||
end
|
||||
|
||||
---@param a ServerPlayer
|
||||
---@param b ServerPlayer
|
||||
function Room:swapSeat(a, b)
|
||||
local ai, bi
|
||||
local players = self.players
|
||||
for i, v in ipairs(self.players) do
|
||||
if v == a then ai = i end
|
||||
if v == b then bi = i end
|
||||
end
|
||||
|
||||
players[ai] = b
|
||||
players[bi] = a
|
||||
a.seat, b.seat = b.seat, a.seat
|
||||
|
||||
local player_circle = {}
|
||||
for _, v in ipairs(players) do
|
||||
table.insert(player_circle, v.id)
|
||||
end
|
||||
|
||||
for i = 1, #players - 1 do
|
||||
players[i].next = players[i + 1]
|
||||
end
|
||||
players[#players].next = players[1]
|
||||
|
||||
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
||||
end
|
||||
|
||||
--- 洗牌。
|
||||
function Room:shuffleDrawPile()
|
||||
if #self.draw_pile + #self.discard_pile == 0 then
|
||||
|
|
|
@ -20,7 +20,9 @@ local ServerPlayer = Player:subclass("ServerPlayer")
|
|||
|
||||
function ServerPlayer:initialize(_self)
|
||||
Player.initialize(self)
|
||||
self.serverplayer = _self
|
||||
self.serverplayer = _self -- 控制者
|
||||
self._splayer = _self -- 真正在玩的玩家
|
||||
self._observers = { _self } -- "旁观"中的玩家,然而不包括真正的旁观者
|
||||
self.id = _self:getId()
|
||||
self.state = _self:getStateString()
|
||||
self.room = nil
|
||||
|
@ -39,7 +41,10 @@ end
|
|||
---@param command string
|
||||
---@param jsonData string
|
||||
function ServerPlayer:doNotify(command, jsonData)
|
||||
self.serverplayer:doNotify(command, jsonData)
|
||||
for _, p in ipairs(self._observers) do
|
||||
p:doNotify(command, jsonData)
|
||||
end
|
||||
|
||||
local room = self.room
|
||||
for _, t in ipairs(room.observers) do
|
||||
local id, p = table.unpack(t)
|
||||
|
@ -56,10 +61,24 @@ end
|
|||
---@param jsonData string
|
||||
---@param timeout integer
|
||||
function ServerPlayer:doRequest(command, jsonData, timeout)
|
||||
timeout = timeout or self.room.timeout
|
||||
self.client_reply = ""
|
||||
self.reply_ready = false
|
||||
self.reply_cancel = false
|
||||
|
||||
if self.serverplayer:busy() then
|
||||
self.room.request_queue[self.serverplayer] = self.room.request_queue[self.serverplayer] or {}
|
||||
table.insert(self.room.request_queue[self.serverplayer], { self.id, command, jsonData, timeout })
|
||||
return
|
||||
end
|
||||
|
||||
self.room.request_self[self.serverplayer:getId()] = self.id
|
||||
|
||||
if not table.contains(self._observers, self.serverplayer) then
|
||||
self.serverplayer:doNotify("StartChangeSelf", tostring(self.id))
|
||||
end
|
||||
|
||||
timeout = timeout or self.room.timeout
|
||||
self.serverplayer:setBusy(true)
|
||||
self.ai_data = {
|
||||
command = command,
|
||||
jsonData = jsonData,
|
||||
|
@ -115,13 +134,30 @@ end
|
|||
---@return string @ JSON data
|
||||
function ServerPlayer:waitForReply(timeout)
|
||||
local result = _waitForReply(self, timeout)
|
||||
local sid = self.serverplayer:getId()
|
||||
local id = self.id
|
||||
if self.room.request_self[sid] ~= id then
|
||||
result = ""
|
||||
end
|
||||
|
||||
self.request_data = ""
|
||||
self.client_reply = result
|
||||
if result == "__cancel" then
|
||||
result = ""
|
||||
self.reply_cancel = true
|
||||
self.serverplayer:setBusy(false)
|
||||
end
|
||||
if result ~= "" then self.reply_ready = true end
|
||||
if result ~= "" then
|
||||
self.reply_ready = true
|
||||
self.serverplayer:setBusy(false)
|
||||
end
|
||||
|
||||
local queue = self.room.request_queue[self.serverplayer]
|
||||
if queue and #queue > 0 and not self.serverplayer:busy() then
|
||||
local i, c, j, t = table.unpack(table.remove(queue, 1))
|
||||
self.room:getPlayerById(i):doRequest(c, j, t)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
@ -648,4 +684,15 @@ function ServerPlayer:revealBySkillName(skill_name)
|
|||
end
|
||||
end
|
||||
|
||||
-- 神貂蝉
|
||||
|
||||
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
|
||||
|
||||
return ServerPlayer
|
||||
|
|
|
@ -78,7 +78,11 @@ local test_active = fk.CreateActiveSkill{
|
|||
on_use = function(self, room, effect)
|
||||
--room:doSuperLightBox("packages/test/qml/Test.qml")
|
||||
local from = room:getPlayerById(effect.from)
|
||||
print(self.interaction.data)
|
||||
--print(self.interaction.data)
|
||||
local to = room:getPlayerById(effect.tos[1])
|
||||
-- room:swapSeat(from, to)
|
||||
from:control(to)
|
||||
-- from:pindian({to})
|
||||
-- local result = room:askForCustomDialog(from, "simayi", "packages/test/qml/TestDialog.qml", "Hello, world. FROM LUA")
|
||||
-- print(result)
|
||||
|
||||
|
@ -92,7 +96,7 @@ local test_active = fk.CreateActiveSkill{
|
|||
-- from.kingdom = "wei"
|
||||
-- room:broadcastProperty(from, "kingdom")
|
||||
-- p(cards)
|
||||
room:useVirtualCard("slash", nil, from, room:getOtherPlayers(from), self.name, true)
|
||||
-- room:useVirtualCard("slash", nil, from, room:getOtherPlayers(from), self.name, true)
|
||||
end,
|
||||
}
|
||||
local test_vs = fk.CreateViewAsSkill{
|
||||
|
|
|
@ -36,21 +36,21 @@ QtObject {
|
|||
|
||||
function loadConf() {
|
||||
conf = JSON.parse(Backend.loadConf());
|
||||
winX = conf.winX || 100;
|
||||
winY = conf.winY || 100;
|
||||
winWidth = conf.winWidth || 960;
|
||||
winHeight = conf.winHeight || 540;
|
||||
lastLoginServer = conf.lastLoginServer || "127.0.0.1";
|
||||
savedPassword = conf.savedPassword || {};
|
||||
lobbyBg = conf.lobbyBg || AppPath + "/image/background";
|
||||
roomBg = conf.roomBg || AppPath + "/image/gamebg";
|
||||
bgmFile = conf.bgmFile || AppPath + "/audio/system/bgm.mp3";
|
||||
language = conf.language || "zh_CN";
|
||||
disabledPack = conf.disabledPack || [ "test_p_0" ];
|
||||
preferedMode = conf.preferedMode || "aaa_role_mode";
|
||||
preferedPlayerNum = conf.preferedPlayerNum || 2;
|
||||
preferredGeneralNum = conf.preferredGeneralNum || 3;
|
||||
ladyImg = conf.ladyImg || AppPath + "/image/lady";
|
||||
winX = conf.winX ?? 100;
|
||||
winY = conf.winY ?? 100;
|
||||
winWidth = conf.winWidth ?? 960;
|
||||
winHeight = conf.winHeight ?? 540;
|
||||
lastLoginServer = conf.lastLoginServer ?? "127.0.0.1";
|
||||
savedPassword = conf.savedPassword ?? {};
|
||||
lobbyBg = conf.lobbyBg ?? AppPath + "/image/background";
|
||||
roomBg = conf.roomBg ?? AppPath + "/image/gamebg";
|
||||
bgmFile = conf.bgmFile ?? AppPath + "/audio/system/bgm.mp3";
|
||||
language = conf.language ?? "zh_CN";
|
||||
disabledPack = conf.disabledPack ?? [ "test_p_0" ];
|
||||
preferedMode = conf.preferedMode ?? "aaa_role_mode";
|
||||
preferedPlayerNum = conf.preferedPlayerNum ?? 2;
|
||||
preferredGeneralNum = conf.preferredGeneralNum ?? 3;
|
||||
ladyImg = conf.ladyImg ?? AppPath + "/image/lady";
|
||||
}
|
||||
|
||||
function saveConf() {
|
||||
|
|
|
@ -14,7 +14,7 @@ Item {
|
|||
id: roomScene
|
||||
|
||||
property int playerNum: 0
|
||||
property var dashboardModel
|
||||
// property var dashboardModel
|
||||
|
||||
property bool isOwner: false
|
||||
property bool isStarted: false
|
||||
|
@ -29,6 +29,7 @@ Item {
|
|||
property alias dynamicCardArea: dynamicCardArea
|
||||
property alias tableCards: tablePile.cards
|
||||
property alias dashboard: dashboard
|
||||
property alias drawPile: drawPile
|
||||
property alias skillInteraction: skillInteraction
|
||||
property alias miscStatus: miscStatus
|
||||
|
||||
|
@ -77,7 +78,7 @@ Item {
|
|||
}
|
||||
Button {
|
||||
text: "add robot"
|
||||
visible: dashboardModel.isOwner && !isStarted
|
||||
visible: isOwner && !isStarted
|
||||
anchors.centerIn: parent
|
||||
onClicked: {
|
||||
ClientInstance.notifyServer("AddRobot", "[]");
|
||||
|
@ -103,6 +104,8 @@ Item {
|
|||
endPhaseButton.visible = false;
|
||||
respond_play = false;
|
||||
extra_data = {};
|
||||
mainWindow.pending_message = [];
|
||||
mainWindow.is_pending = false;
|
||||
|
||||
if (dashboard.pending_skill !== "")
|
||||
dashboard.stopPending();
|
||||
|
@ -209,6 +212,10 @@ Item {
|
|||
onSelectedChanged: {
|
||||
Logic.updateSelectedTargets(playerid, selected);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (index === 0) dashboard.self = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,28 +262,6 @@ Item {
|
|||
anchors.top: roomArea.bottom
|
||||
anchors.left: dashboardBtn.right
|
||||
|
||||
self.playerid: dashboardModel.id
|
||||
self.general: dashboardModel.general
|
||||
self.screenName: dashboardModel.screenName
|
||||
self.deputyGeneral: dashboardModel.deputyGeneral
|
||||
self.role: dashboardModel.role
|
||||
self.kingdom: dashboardModel.kingdom
|
||||
self.netstate: dashboardModel.netstate
|
||||
self.maxHp: dashboardModel.maxHp
|
||||
self.shield: dashboardModel.shield
|
||||
self.hp: dashboardModel.hp
|
||||
self.seatNumber: dashboardModel.seatNumber
|
||||
self.dead: dashboardModel.dead
|
||||
self.dying: dashboardModel.dying
|
||||
self.faceup: dashboardModel.faceup
|
||||
self.chained: dashboardModel.chained
|
||||
self.drank: dashboardModel.drank
|
||||
self.isOwner: dashboardModel.isOwner
|
||||
|
||||
onSelectedChanged: {
|
||||
Logic.updateSelectedTargets(self.playerid, selected);
|
||||
}
|
||||
|
||||
onCardSelected: function(card) {
|
||||
Logic.enableTargets(card);
|
||||
|
||||
|
@ -809,37 +794,15 @@ Item {
|
|||
|
||||
Component.onCompleted: {
|
||||
toast.show(Backend.translate("$EnterRoom"));
|
||||
|
||||
dashboardModel = {
|
||||
id: Self.id,
|
||||
general: Self.avatar,
|
||||
deputyGeneral: "",
|
||||
screenName: Self.screenName,
|
||||
role: "unknown",
|
||||
kingdom: "unknown",
|
||||
netstate: "online",
|
||||
maxHp: 0,
|
||||
hp: 0,
|
||||
shield: 0,
|
||||
seatNumber: 1,
|
||||
dead: false,
|
||||
dying: false,
|
||||
faceup: true,
|
||||
chained: false,
|
||||
drank: 0,
|
||||
isOwner: false
|
||||
}
|
||||
|
||||
playerNum = config.roomCapacity;
|
||||
|
||||
let i;
|
||||
for (i = 1; i < playerNum; i++) {
|
||||
for (let i = 0; i < playerNum; i++) {
|
||||
photoModel.append({
|
||||
id: -1,
|
||||
index: i - 1, // For animating seat swap
|
||||
general: "",
|
||||
id: i ? -1 : Self.id,
|
||||
index: i, // For animating seat swap
|
||||
general: i ? "" : Self.avatar,
|
||||
deputyGeneral: "",
|
||||
screenName: "",
|
||||
screenName: i ? "" : Self.screenName,
|
||||
role: "unknown",
|
||||
kingdom: "unknown",
|
||||
netstate: "online",
|
||||
|
|
|
@ -7,13 +7,8 @@ import Qt5Compat.GraphicalEffects
|
|||
RowLayout {
|
||||
id: root
|
||||
|
||||
property alias self: selfPhoto
|
||||
property var self
|
||||
property alias handcardArea: handcardAreaItem
|
||||
property alias equipArea: selfPhoto.equipArea
|
||||
property alias delayedTrickArea: selfPhoto.delayedTrickArea
|
||||
property alias specialArea: selfPhoto.specialArea
|
||||
|
||||
property bool selected: selfPhoto.selected
|
||||
|
||||
property string pending_skill: ""
|
||||
property var pending_card
|
||||
|
@ -48,10 +43,11 @@ RowLayout {
|
|||
id: skillPanel
|
||||
}
|
||||
|
||||
Photo {
|
||||
id: selfPhoto
|
||||
Item {
|
||||
width: 175
|
||||
height: 233
|
||||
Layout.rightMargin: -175 / 8 + (roomArea.width - 175 * 0.75 * 7) / 8
|
||||
handcards: handcardAreaItem.length
|
||||
// handcards: handcardAreaItem.length
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -59,6 +55,9 @@ RowLayout {
|
|||
function onCardSelected(cardId, selected) {
|
||||
dashboard.selectCard(cardId, selected);
|
||||
}
|
||||
function onLengthChanged() {
|
||||
self.handcards = handcardAreaItem.length;
|
||||
}
|
||||
}
|
||||
|
||||
function disableAllCards() {
|
||||
|
@ -75,11 +74,11 @@ RowLayout {
|
|||
return;
|
||||
|
||||
let component = Qt.createComponent("CardItem.qml");
|
||||
let parentPos = roomScene.mapFromItem(selfPhoto, 0, 0);
|
||||
let parentPos = roomScene.mapFromItem(self, 0, 0);
|
||||
|
||||
expanded_piles[pile] = [];
|
||||
if (pile === "_equip") {
|
||||
let equips = selfPhoto.equipArea.getAllCards();
|
||||
let equips = self.equipArea.getAllCards();
|
||||
equips.forEach(data => {
|
||||
data.x = parentPos.x;
|
||||
data.y = parentPos.y;
|
||||
|
@ -90,7 +89,7 @@ RowLayout {
|
|||
})
|
||||
handcardAreaItem.updateCardPosition();
|
||||
} else {
|
||||
let ids = JSON.parse(Backend.callLuaFunction("GetPile", [selfPhoto.playerid, pile]));
|
||||
let ids = JSON.parse(Backend.callLuaFunction("GetPile", [self.playerid, pile]));
|
||||
ids.forEach(id => {
|
||||
let data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
|
||||
data.x = parentPos.x;
|
||||
|
@ -109,11 +108,11 @@ RowLayout {
|
|||
if (expanded_pile_names.indexOf(pile) === -1)
|
||||
return;
|
||||
|
||||
let parentPos = roomScene.mapFromItem(selfPhoto, 0, 0);
|
||||
let parentPos = roomScene.mapFromItem(self, 0, 0);
|
||||
|
||||
delete expanded_piles[pile];
|
||||
if (pile === "_equip") {
|
||||
let equips = selfPhoto.equipArea.getAllCards();
|
||||
let equips = self.equipArea.getAllCards();
|
||||
equips.forEach(data => {
|
||||
let card = handcardAreaItem.remove([data.cid])[0];
|
||||
card.origX = parentPos.x;
|
||||
|
@ -123,7 +122,7 @@ RowLayout {
|
|||
})
|
||||
handcardAreaItem.updateCardPosition();
|
||||
} else {
|
||||
let ids = JSON.parse(Backend.callLuaFunction("GetPile", [selfPhoto.playerid, pile]));
|
||||
let ids = JSON.parse(Backend.callLuaFunction("GetPile", [self.playerid, pile]));
|
||||
ids.forEach(id => {
|
||||
let card = handcardAreaItem.remove([id])[0];
|
||||
card.origX = parentPos.x;
|
||||
|
@ -166,7 +165,7 @@ RowLayout {
|
|||
ids.push(cards[i].cid);
|
||||
}
|
||||
}
|
||||
cards = selfPhoto.equipArea.getAllCards();
|
||||
cards = self.equipArea.getAllCards();
|
||||
cards.forEach(c => {
|
||||
if (cardValid(c.cid, cname)) {
|
||||
ids.push(c.cid);
|
||||
|
@ -178,7 +177,7 @@ RowLayout {
|
|||
|
||||
// Must manually analyze pattern here
|
||||
let pile_list = cname.split("|")[4];
|
||||
let pile_data = JSON.parse(Backend.callLuaFunction("GetAllPiles", [selfPhoto.playerid]));
|
||||
let pile_data = JSON.parse(Backend.callLuaFunction("GetAllPiles", [self.playerid]));
|
||||
if (pile_list && pile_list !== "." && !(pile_data instanceof Array)) {
|
||||
pile_list = pile_list.split(",");
|
||||
for (let pile_name of pile_list) {
|
||||
|
@ -254,7 +253,7 @@ RowLayout {
|
|||
enabled_cards.push(card.cid);
|
||||
});
|
||||
|
||||
let cards = selfPhoto.equipArea.getAllCards();
|
||||
let cards = self.equipArea.getAllCards();
|
||||
cards.forEach(c => {
|
||||
if (JSON.parse(Backend.callLuaFunction(
|
||||
"ActiveCardFilter",
|
||||
|
@ -268,7 +267,7 @@ RowLayout {
|
|||
})
|
||||
|
||||
let pile = Backend.callLuaFunction("GetExpandPileOfSkill", [pending_skill]);
|
||||
let pile_ids = JSON.parse(Backend.callLuaFunction("GetPile", [selfPhoto.playerid, pile]));
|
||||
let pile_ids = JSON.parse(Backend.callLuaFunction("GetPile", [self.playerid, pile]));
|
||||
pile_ids.forEach(cid => {
|
||||
if (JSON.parse(Backend.callLuaFunction(
|
||||
"ActiveCardFilter",
|
||||
|
@ -370,6 +369,32 @@ RowLayout {
|
|||
}
|
||||
|
||||
function tremble() {
|
||||
selfPhoto.tremble();
|
||||
self.tremble();
|
||||
}
|
||||
|
||||
function update() {
|
||||
unSelectAll();
|
||||
disableSkills();
|
||||
|
||||
let cards = handcardAreaItem.cards;
|
||||
let toRemove = [];
|
||||
for (let c of cards) {
|
||||
toRemove.push(c.cid);
|
||||
c.origY += 30;
|
||||
c.origOpacity = 0
|
||||
c.goBack(true);
|
||||
c.destroyOnStop();
|
||||
}
|
||||
handcardAreaItem.remove(toRemove);
|
||||
|
||||
skillPanel.clearSkills();
|
||||
|
||||
let skills = JSON.parse(Backend.callLuaFunction("GetPlayerSkills", [Self.id]));
|
||||
for (let s of skills) {
|
||||
addSkill(s.name);
|
||||
}
|
||||
|
||||
cards = roomScene.drawPile.remove(JSON.parse(Backend.callLuaFunction("GetPlayerHandcards", [Self.id])));
|
||||
handcardAreaItem.add(cards);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ Item {
|
|||
radius: 4
|
||||
border.color: "white"
|
||||
border.width: 1
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: 300; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
|
@ -38,6 +42,14 @@ Item {
|
|||
textFormat: Text.RichText
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation { duration: 300; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation { duration: 300; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
enabled: root.parent.state != "candidate" || !root.parent.selectable
|
||||
onTapped: {
|
||||
|
|
|
@ -50,7 +50,7 @@ Flickable {
|
|||
onPressedChanged: {
|
||||
if (!pressed) return;
|
||||
enabled = false;
|
||||
ClientInstance.notifyServer("PrelightSkill", [
|
||||
ClientInstance.notifyServer("PushRequest", [
|
||||
"prelight", orig, (!prelighted).toString()
|
||||
].join(","));
|
||||
}
|
||||
|
@ -154,4 +154,10 @@ Flickable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearSkills() {
|
||||
prelight_skills.clear();
|
||||
active_skills.clear();
|
||||
not_active_skills.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ function arrangePhotos() {
|
|||
* +---------------+
|
||||
* | 6 5 4 3 2 |
|
||||
* | 7 1 |
|
||||
* | dashboard |
|
||||
* | 0 |
|
||||
* +---------------+
|
||||
*/
|
||||
|
||||
|
@ -32,6 +32,7 @@ function arrangePhotos() {
|
|||
let startX = verticalPadding + verticalSpacing;
|
||||
let padding = photoWidth + verticalSpacing;
|
||||
let regions = [
|
||||
{ x: startX + padding * 6, y: roomScene.height - 220 },
|
||||
{ x: startX + padding * 6, y: roomAreaPadding + horizontalSpacing * 3 },
|
||||
{ x: startX + padding * 5, y: roomAreaPadding + horizontalSpacing },
|
||||
{ x: startX + padding * 4, y: roomAreaPadding },
|
||||
|
@ -42,24 +43,24 @@ function arrangePhotos() {
|
|||
];
|
||||
|
||||
const regularSeatIndex = [
|
||||
[4],
|
||||
[3, 5],
|
||||
[1, 4, 7],
|
||||
[1, 3, 5, 7],
|
||||
[1, 3, 4, 5, 7],
|
||||
[1, 2, 3, 5, 6, 7],
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
[0, 4],
|
||||
[0, 3, 5],
|
||||
[0, 1, 4, 7],
|
||||
[0, 1, 3, 5, 7],
|
||||
[0, 1, 3, 4, 5, 7],
|
||||
[0, 1, 2, 3, 5, 6, 7],
|
||||
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||
];
|
||||
let seatIndex = regularSeatIndex[playerNum - 2];
|
||||
|
||||
let item, region, i;
|
||||
|
||||
for (i = 0; i < playerNum - 1; i++) {
|
||||
for (i = 0; i < playerNum; i++) {
|
||||
item = photos.itemAt(i);
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
region = regions[seatIndex[photoModel.get(i).index] - 1];
|
||||
region = regions[seatIndex[photoModel.get(i).index]];
|
||||
item.x = region.x;
|
||||
item.y = region.y;
|
||||
}
|
||||
|
@ -106,8 +107,14 @@ function doCancelButton() {
|
|||
}
|
||||
|
||||
function replyToServer(jsonData) {
|
||||
roomScene.state = "notactive";
|
||||
ClientInstance.replyToServer("", jsonData);
|
||||
if (!mainWindow.is_pending) {
|
||||
roomScene.state = "notactive";
|
||||
} else {
|
||||
roomScene.state = "";
|
||||
let data = mainWindow.fetchMessage();
|
||||
return mainWindow.handleMessage(data.command, data.jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
function getPhotoModel(id) {
|
||||
|
@ -131,21 +138,9 @@ function getPhoto(id) {
|
|||
}
|
||||
|
||||
function getPhotoOrDashboard(id) {
|
||||
let photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
if (id === Self.id)
|
||||
return dashboard;
|
||||
}
|
||||
return photo;
|
||||
}
|
||||
|
||||
function getPhotoOrSelf(id) {
|
||||
let photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
if (id === Self.id)
|
||||
return dashboard.self;
|
||||
}
|
||||
return photo;
|
||||
if (id === Self.id)
|
||||
return dashboard;
|
||||
return getPhoto(id);
|
||||
}
|
||||
|
||||
function getAreaItem(area, id) {
|
||||
|
@ -157,13 +152,13 @@ function getAreaItem(area, id) {
|
|||
return popupBox.item;
|
||||
}
|
||||
|
||||
let photo = getPhotoOrDashboard(id);
|
||||
let photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (area === Card.PlayerHand) {
|
||||
return photo.handcardArea;
|
||||
return id === Self.id ? dashboard.handcardArea : photo.handcardArea;
|
||||
} else if (area === Card.PlayerEquip) {
|
||||
return photo.equipArea;
|
||||
} else if (area === Card.PlayerJudge) {
|
||||
|
@ -230,11 +225,7 @@ function setEmotion(id, emotion, isCardId) {
|
|||
} else {
|
||||
photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
if (id === dashboardModel.id) {
|
||||
photo = dashboard.self;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,11 +246,7 @@ function setEmotion(id, emotion, isCardId) {
|
|||
function changeHp(id, delta, losthp) {
|
||||
let photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
if (id === dashboardModel.id) {
|
||||
photo = dashboard.self;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (delta < 0) {
|
||||
if (!losthp) {
|
||||
|
@ -292,6 +279,30 @@ function doIndicate(from, tos) {
|
|||
line.running = true;
|
||||
}
|
||||
|
||||
function changeSelf(id) {
|
||||
Backend.callLuaFunction("ChangeSelf", [id]);
|
||||
|
||||
// move new selfPhoto to dashboard
|
||||
let order = new Array(photoModel.count);
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
order[item.seatNumber - 1] = item.id;
|
||||
if (item.id === Self.id) {
|
||||
dashboard.self = photos.itemAt(i);
|
||||
}
|
||||
}
|
||||
callbacks["ArrangeSeats"](JSON.stringify(order));
|
||||
|
||||
// update dashboard
|
||||
dashboard.update();
|
||||
|
||||
// handle pending messages
|
||||
if (mainWindow.is_pending) {
|
||||
let data = mainWindow.fetchMessage();
|
||||
return mainWindow.handleMessage(data.command, data.jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["AddPlayer"] = function(jsonData) {
|
||||
// jsonData: int id, string screenName, string avatar
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
|
@ -325,8 +336,8 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
|
|||
|
||||
let i = 0;
|
||||
let candidate = (!isNaN(card) && card !== -1) || typeof(card) === "string";
|
||||
let all_photos = [dashboard.self];
|
||||
for (i = 0; i < playerNum - 1; i++) {
|
||||
let all_photos = [];
|
||||
for (i = 0; i < playerNum; i++) {
|
||||
all_photos.push(photos.itemAt(i))
|
||||
}
|
||||
selected_targets = [];
|
||||
|
@ -383,8 +394,8 @@ function updateSelectedTargets(playerid, selected) {
|
|||
let i = 0;
|
||||
let card = dashboard.getSelectedCard();
|
||||
let candidate = (!isNaN(card) && card !== -1) || typeof(card) === "string";
|
||||
let all_photos = [dashboard.self]
|
||||
for (i = 0; i < playerNum - 1; i++) {
|
||||
let all_photos = [];
|
||||
for (i = 0; i < playerNum; i++) {
|
||||
all_photos.push(photos.itemAt(i))
|
||||
}
|
||||
|
||||
|
@ -451,10 +462,8 @@ callbacks["RoomOwner"] = function(jsonData) {
|
|||
// jsonData: int uid of the owner
|
||||
let uid = JSON.parse(jsonData)[0];
|
||||
|
||||
if (dashboardModel.id === uid) {
|
||||
dashboardModel.isOwner = true;
|
||||
roomScene.dashboardModelChanged();
|
||||
return;
|
||||
if (Self.id === uid) {
|
||||
roomScene.isOwner = true;
|
||||
}
|
||||
|
||||
let model = getPhotoModel(uid);
|
||||
|
@ -470,38 +479,35 @@ callbacks["PropertyUpdate"] = function(jsonData) {
|
|||
let property_name = data[1];
|
||||
let value = data[2];
|
||||
|
||||
if (Self.id === uid) {
|
||||
dashboardModel[property_name] = value;
|
||||
roomScene.dashboardModelChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
let model = getPhotoModel(uid);
|
||||
if (typeof(model) !== "undefined") {
|
||||
model[property_name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["ArrangeSeats"] = function(jsonData) {
|
||||
// jsonData: seat order
|
||||
let order = JSON.parse(jsonData);
|
||||
callbacks["StartGame"] = function(jsonData) {
|
||||
roomScene.isStarted = true;
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
item.seatNumber = order.indexOf(item.id) + 1;
|
||||
item.general = "";
|
||||
}
|
||||
}
|
||||
|
||||
dashboardModel.seatNumber = order.indexOf(Self.id) + 1;
|
||||
dashboardModel.general = "";
|
||||
roomScene.dashboardModelChanged();
|
||||
callbacks["ArrangeSeats"] = function(jsonData) {
|
||||
// jsonData: seat order
|
||||
let order = JSON.parse(jsonData);
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
item.seatNumber = order.indexOf(item.id) + 1;
|
||||
}
|
||||
|
||||
// make Self to the first of list, then reorder photomodel
|
||||
let selfIndex = order.indexOf(Self.id);
|
||||
let after = order.splice(selfIndex);
|
||||
after.push(...order);
|
||||
let photoOrder = after.slice(1);
|
||||
let photoOrder = after;
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
|
@ -513,7 +519,7 @@ callbacks["ArrangeSeats"] = function(jsonData) {
|
|||
|
||||
function cancelAllFocus() {
|
||||
let item;
|
||||
for (let i = 0; i < playerNum - 1; i++) {
|
||||
for (let i = 0; i < playerNum; i++) {
|
||||
item = photos.itemAt(i);
|
||||
item.progressBar.visible = false;
|
||||
item.progressTip = "";
|
||||
|
@ -528,7 +534,7 @@ callbacks["MoveFocus"] = function(jsonData) {
|
|||
let command = data[1];
|
||||
|
||||
let item, model;
|
||||
for (let i = 0; i < playerNum - 1; i++) {
|
||||
for (let i = 0; i < playerNum; i++) {
|
||||
model = photoModel.get(i);
|
||||
if (focuses.indexOf(model.id) != -1) {
|
||||
item = photos.itemAt(i);
|
||||
|
@ -546,14 +552,6 @@ callbacks["MoveFocus"] = function(jsonData) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command === "PlayCard") {
|
||||
if (focuses.indexOf(Self.id) != -1) {
|
||||
dashboard.self.playing = true;
|
||||
} else {
|
||||
dashboard.self.playing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["PlayerRunned"] = function(jsonData) {
|
||||
|
@ -793,8 +791,8 @@ function processPrompt(prompt) {
|
|||
let raw = Backend.translate(data[0]);
|
||||
let src = parseInt(data[1]);
|
||||
let dest = parseInt(data[2]);
|
||||
if (raw.match("%src")) raw = raw.replace("%src", Backend.translate(getPhotoOrSelf(src).general));
|
||||
if (raw.match("%dest")) raw = raw.replace("%dest", Backend.translate(getPhotoOrSelf(dest).general));
|
||||
if (raw.match("%src")) raw = raw.replace("%src", Backend.translate(getPhoto(src).general));
|
||||
if (raw.match("%dest")) raw = raw.replace("%dest", Backend.translate(getPhoto(dest).general));
|
||||
if (raw.match("%arg")) raw = raw.replace("%arg", Backend.translate(data[3]));
|
||||
if (raw.match("%arg2")) raw = raw.replace("%arg2", Backend.translate(data[4]));
|
||||
return raw;
|
||||
|
@ -878,7 +876,7 @@ callbacks["WaitForNullification"] = function() {
|
|||
|
||||
callbacks["SetPlayerMark"] = function(jsonData) {
|
||||
let data = JSON.parse(jsonData);
|
||||
let player = getPhotoOrSelf(data[0]);
|
||||
let player = getPhoto(data[0]);
|
||||
let mark = data[1];
|
||||
let value = data[2].toString();
|
||||
if (value == 0) {
|
||||
|
@ -922,11 +920,7 @@ callbacks["Animate"] = function(jsonData) {
|
|||
|
||||
let photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
if (id === dashboardModel.id) {
|
||||
photo = dashboard.self;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let animation = component.createObject(photo, {
|
||||
|
@ -974,9 +968,6 @@ callbacks["LogEvent"] = function(jsonData) {
|
|||
}
|
||||
case "Death": {
|
||||
let item = getPhoto(data.to);
|
||||
if (data.to === dashboardModel.id) {
|
||||
item = dashboard.self;
|
||||
}
|
||||
let extension = JSON.parse(Backend.callLuaFunction("GetGeneralData", [item.general])).extension;
|
||||
Backend.playSound("./packages/" + extension + "/audio/death/" + item.general);
|
||||
}
|
||||
|
@ -1010,7 +1001,7 @@ callbacks["TakeAG"] = (j) => {
|
|||
let data = JSON.parse(j);
|
||||
let pid = data[0];
|
||||
let cid = data[1];
|
||||
let item = getPhotoOrSelf(pid);
|
||||
let item = getPhoto(pid);
|
||||
let general = Backend.translate(item.general);
|
||||
|
||||
// the item should be AG box
|
||||
|
@ -1036,7 +1027,7 @@ callbacks["UpdateLimitSkill"] = (j) => {
|
|||
let skill = data[1];
|
||||
let time = data[2];
|
||||
|
||||
let photo = getPhotoOrSelf(id);
|
||||
let photo = getPhoto(id);
|
||||
if (photo) {
|
||||
photo.updateLimitSkill(skill, time);
|
||||
}
|
||||
|
@ -1051,3 +1042,21 @@ callbacks["UpdateRoundNum"] = (j) => {
|
|||
let data = parseInt(j);
|
||||
roomScene.miscStatus.roundNum = data;
|
||||
}
|
||||
|
||||
// 神貂蝉
|
||||
|
||||
callbacks["StartChangeSelf"] = (j) => {
|
||||
let id = parseInt(j);
|
||||
ClientInstance.notifyServer("PushRequest", "changeself," + j);
|
||||
}
|
||||
|
||||
callbacks["ChangeSelf"] = (j) => {
|
||||
let data = parseInt(j);
|
||||
if (Self.id === data) {
|
||||
let msg = mainWindow.fetchMessage();
|
||||
if (!msg) return;
|
||||
mainWindow.handleMessage(msg.command, msg.jsonData);
|
||||
return;
|
||||
}
|
||||
changeSelf(data);
|
||||
}
|
||||
|
|
29
qml/main.qml
29
qml/main.qml
|
@ -24,6 +24,8 @@ Item {
|
|||
? 540 : 960 * parent.height / parent.width
|
||||
scale: parent.width / width
|
||||
anchors.centerIn: parent
|
||||
property bool is_pending: false
|
||||
property var pending_message: []
|
||||
|
||||
Config {
|
||||
id: config
|
||||
|
@ -183,14 +185,33 @@ Item {
|
|||
errDialog.open();
|
||||
return;
|
||||
}
|
||||
let cb = callbacks[command]
|
||||
if (typeof(cb) === "function") {
|
||||
cb(jsonData);
|
||||
if (mainWindow.is_pending && command !== "ChangeSelf") {
|
||||
mainWindow.pending_message.push({ command: command, jsonData: jsonData });
|
||||
} else {
|
||||
callbacks["ErrorMsg"]("Unknown command " + command + "!");
|
||||
if (command === "StartChangeSelf") {
|
||||
mainWindow.is_pending = true;
|
||||
}
|
||||
mainWindow.handleMessage(command, jsonData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchMessage() {
|
||||
let ret = pending_message.splice(0, 1)[0];
|
||||
if (pending_message.length === 0) {
|
||||
is_pending = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function handleMessage(command, jsonData) {
|
||||
let cb = callbacks[command]
|
||||
if (typeof(cb) === "function") {
|
||||
cb(jsonData);
|
||||
} else {
|
||||
callbacks["ErrorMsg"]("Unknown command " + command + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
|
|
|
@ -12,6 +12,7 @@ ClientPlayer *Self;
|
|||
Client::Client(QObject *parent) : QObject(parent), callback(0) {
|
||||
ClientInstance = this;
|
||||
Self = new ClientPlayer(0, this);
|
||||
self = Self;
|
||||
QQmlApplicationEngine *engine = Backend->getEngine();
|
||||
engine->rootContext()->setContextProperty("ClientInstance", ClientInstance);
|
||||
engine->rootContext()->setContextProperty("Self", Self);
|
||||
|
@ -67,6 +68,12 @@ void Client::removePlayer(int id) {
|
|||
|
||||
void Client::clearPlayers() { players.clear(); }
|
||||
|
||||
void Client::changeSelf(int id) {
|
||||
auto p = players[id];
|
||||
Self = p ? p : self;
|
||||
Backend->getEngine()->rootContext()->setContextProperty("Self", Self);
|
||||
}
|
||||
|
||||
lua_State *Client::getLuaState() { return L; }
|
||||
|
||||
void Client::installAESKey(const QByteArray &key) { router->installAESKey(key); }
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
ClientPlayer *addPlayer(int id, const QString &name, const QString &avatar);
|
||||
void removePlayer(int id);
|
||||
Q_INVOKABLE void clearPlayers();
|
||||
void changeSelf(int id);
|
||||
|
||||
lua_State *getLuaState();
|
||||
void installAESKey(const QByteArray &key);
|
||||
|
@ -37,6 +38,7 @@ signals:
|
|||
private:
|
||||
Router *router;
|
||||
QMap<int, ClientPlayer *> players;
|
||||
ClientPlayer *self;
|
||||
|
||||
lua_State *L;
|
||||
};
|
||||
|
|
|
@ -250,7 +250,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
room->addRobot(player);
|
||||
} else if (command == "Chat") {
|
||||
room->chat(player, jsonData);
|
||||
} else if (command == "PrelightSkill") {
|
||||
} else if (command == "PushRequest") {
|
||||
room->pushRequest(QString("%1,").arg(player->getId()) + jsonData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ ServerPlayer::ServerPlayer(Room *room) {
|
|||
connect(this, &ServerPlayer::kicked, this, &ServerPlayer::kick);
|
||||
|
||||
alive = true;
|
||||
m_busy = false;
|
||||
}
|
||||
|
||||
ServerPlayer::~ServerPlayer() {
|
||||
|
|
|
@ -38,6 +38,8 @@ public:
|
|||
volatile bool alive; // For heartbeat
|
||||
void kick();
|
||||
|
||||
bool busy() const { return m_busy; }
|
||||
void setBusy(bool busy) { m_busy = busy; }
|
||||
signals:
|
||||
void disconnected();
|
||||
void kicked();
|
||||
|
@ -47,6 +49,7 @@ private:
|
|||
Router *router;
|
||||
Server *server;
|
||||
Room *room; // Room that player is in, maybe lobby
|
||||
bool m_busy;
|
||||
|
||||
QString requestCommand;
|
||||
QString requestData;
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
|
||||
ClientPlayer *addPlayer(int id, const QString &name, const QString &avatar);
|
||||
void removePlayer(int id);
|
||||
void changeSelf(int id);
|
||||
};
|
||||
|
||||
extern Client *ClientInstance;
|
||||
|
|
|
@ -118,4 +118,7 @@ public:
|
|||
void doNotify(const QString &command, const QString &json_data);
|
||||
|
||||
void prepareForRequest(const QString &command, const QString &data);
|
||||
|
||||
bool busy() const;
|
||||
void setBusy(bool busy);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user