UI commands (#17)
* add cardarea * move cards * add util * delaytrick * equiparea * var -> let * photo loop anim * setEmotion & damage * photo status * doIndicate * add property to ClientPlayer * todo: movecards, waiting * handle moveCards at client * ui - moveCards * modify to lua * move visible * adjust position of tablepile Co-authored-by: Notify-ctrl <notify-ctrl@qq.com>
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 624 B After Width: | Height: | Size: 624 B |
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 512 B |
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 284 B |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 538 B |
Before Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 619 B |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 658 B |
Before Width: | Height: | Size: 575 B |
Before Width: | Height: | Size: 553 B |
Before Width: | Height: | Size: 673 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 540 B |
Before Width: | Height: | Size: 378 B |
Before Width: | Height: | Size: 427 B |
Before Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 540 B |
Before Width: | Height: | Size: 436 B |
Before Width: | Height: | Size: 505 B |
Before Width: | Height: | Size: 490 B |
Before Width: | Height: | Size: 517 B |
Before Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 550 B |
Before Width: | Height: | Size: 576 B |
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 755 B After Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
@ -1,3 +1,6 @@
|
||||||
|
---@class Client
|
||||||
|
---@field client fk.Client
|
||||||
|
---@field players ClientPlayer[]
|
||||||
Client = class('Client')
|
Client = class('Client')
|
||||||
|
|
||||||
-- load client classes
|
-- load client classes
|
||||||
|
@ -23,6 +26,15 @@ function Client:initialize()
|
||||||
self.players = {} -- ClientPlayer[]
|
self.players = {} -- ClientPlayer[]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param id integer
|
||||||
|
---@return ClientPlayer
|
||||||
|
function Client:findPlayer(id)
|
||||||
|
for _, p in ipairs(self.players) do
|
||||||
|
if p.player:getId() == id then return p end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
fk.client_callback["Setup"] = function(jsonData)
|
fk.client_callback["Setup"] = function(jsonData)
|
||||||
-- jsonData: [ int id, string screenName, string avatar ]
|
-- jsonData: [ int id, string screenName, string avatar ]
|
||||||
local data = json.decode(jsonData)
|
local data = json.decode(jsonData)
|
||||||
|
@ -31,6 +43,8 @@ fk.client_callback["Setup"] = function(jsonData)
|
||||||
self:setId(id)
|
self:setId(id)
|
||||||
self:setScreenName(name)
|
self:setScreenName(name)
|
||||||
self:setAvatar(avatar)
|
self:setAvatar(avatar)
|
||||||
|
Self = ClientPlayer:new(fk.Self)
|
||||||
|
table.insert(ClientInstance.players, Self)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddPlayer"] = function(jsonData)
|
fk.client_callback["AddPlayer"] = function(jsonData)
|
||||||
|
@ -47,13 +61,13 @@ fk.client_callback["RemovePlayer"] = function(jsonData)
|
||||||
-- jsonData: [ int id ]
|
-- jsonData: [ int id ]
|
||||||
local data = json.decode(jsonData)
|
local data = json.decode(jsonData)
|
||||||
local id = data[1]
|
local id = data[1]
|
||||||
fk.ClientInstance:removePlayer(id)
|
|
||||||
for _, p in ipairs(ClientInstance.players) do
|
for _, p in ipairs(ClientInstance.players) do
|
||||||
if p.player:getId() == id then
|
if p.player:getId() == id then
|
||||||
table.removeOne(ClientInstance.players, p)
|
table.removeOne(ClientInstance.players, p)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
fk.ClientInstance:removePlayer(id)
|
||||||
ClientInstance:notifyUI("RemovePlayer", jsonData)
|
ClientInstance:notifyUI("RemovePlayer", jsonData)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,20 +75,70 @@ fk.client_callback["ArrangeSeats"] = function(jsonData)
|
||||||
local data = json.decode(jsonData)
|
local data = json.decode(jsonData)
|
||||||
local n = #ClientInstance.players
|
local n = #ClientInstance.players
|
||||||
local players = {}
|
local players = {}
|
||||||
local function findPlayer(id)
|
|
||||||
for _, p in ipairs(ClientInstance.players) do
|
|
||||||
if p.player:getId() == id then return p end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, n do
|
for i = 1, n do
|
||||||
table.insert(players, findPlayer(data[i]))
|
table.insert(players, ClientInstance:findPlayer(data[i]))
|
||||||
end
|
end
|
||||||
ClientInstance.players = players
|
ClientInstance.players = players
|
||||||
|
|
||||||
ClientInstance:notifyUI("ArrangeSeats", jsonData)
|
ClientInstance:notifyUI("ArrangeSeats", jsonData)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fk.client_callback["PropertyUpdate"] = function(jsonData)
|
||||||
|
-- jsonData: [ int id, string property_name, value ]
|
||||||
|
local data = json.decode(jsonData)
|
||||||
|
local id, name, value = data[1], data[2], data[3]
|
||||||
|
ClientInstance:findPlayer(id)[name] = value
|
||||||
|
ClientInstance:notifyUI("PropertyUpdate", jsonData)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- separated moves to many moves(one card per move)
|
||||||
|
---@param moves CardsMoveStruct[]
|
||||||
|
local function separateMoves(moves)
|
||||||
|
local ret = {} ---@type CardsMoveInfo[]
|
||||||
|
for _, move in ipairs(moves) do
|
||||||
|
for _, info in ipairs(move.moveInfo) do
|
||||||
|
table.insert(ret, {
|
||||||
|
ids = {info.cardId},
|
||||||
|
from = move.from,
|
||||||
|
to = move.to,
|
||||||
|
toArea = move.toArea,
|
||||||
|
fromArea = info.fromArea,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
--- merge separated moves (one fromArea per move)
|
||||||
|
local function mergeMoves(moves)
|
||||||
|
local ret = {}
|
||||||
|
local temp = {}
|
||||||
|
for _, move in ipairs(moves) do
|
||||||
|
if temp[move.fromArea] == nil then
|
||||||
|
temp[move.fromArea] = {
|
||||||
|
ids = {},
|
||||||
|
from = move.from,
|
||||||
|
to = move.to,
|
||||||
|
fromArea = move.fromArea,
|
||||||
|
toArea = move.toArea
|
||||||
|
}
|
||||||
|
end
|
||||||
|
table.insert(temp[move.fromArea].ids, move.ids[1])
|
||||||
|
end
|
||||||
|
for _, v in pairs(temp) do
|
||||||
|
table.insert(ret, v)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
fk.client_callback["MoveCards"] = function(jsonData)
|
||||||
|
-- jsonData: CardsMoveStruct[]
|
||||||
|
local raw_moves = json.decode(jsonData)
|
||||||
|
local separated = separateMoves(raw_moves)
|
||||||
|
local merged = mergeMoves(separated)
|
||||||
|
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
||||||
|
end
|
||||||
|
|
||||||
-- Create ClientInstance (used by Lua)
|
-- Create ClientInstance (used by Lua)
|
||||||
ClientInstance = Client:new()
|
ClientInstance = Client:new()
|
||||||
|
|
|
@ -9,3 +9,18 @@ function GetGeneralData(name)
|
||||||
general.kingdom
|
general.kingdom
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GetCardData(id)
|
||||||
|
local card = Fk.cards[id]
|
||||||
|
if card == nil then return json.encode{
|
||||||
|
cid = id,
|
||||||
|
known = false
|
||||||
|
} end
|
||||||
|
return json.encode{
|
||||||
|
cid = id,
|
||||||
|
name = card.name,
|
||||||
|
number = card.number,
|
||||||
|
suit = card:getSuitString(),
|
||||||
|
color = card.color,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
---@class ClientPlayer
|
||||||
|
---@field player fk.Player
|
||||||
|
---@field handcardNum integer
|
||||||
|
---@field known_cards integer[]
|
||||||
local ClientPlayer = Player:subclass("ClientPlayer")
|
local ClientPlayer = Player:subclass("ClientPlayer")
|
||||||
|
|
||||||
function ClientPlayer:initialize(cp)
|
function ClientPlayer:initialize(cp)
|
||||||
self.player = cp
|
self.player = cp
|
||||||
|
self.handcardNum = 0
|
||||||
|
self.known_cards = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
return ClientPlayer
|
return ClientPlayer
|
||||||
|
|
|
@ -74,4 +74,19 @@ function Card:initialize(name, suit, number, color)
|
||||||
self.sub_type = Card.SubTypeNone
|
self.sub_type = Card.SubTypeNone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Card:getSuitString()
|
||||||
|
local suit = self.suit
|
||||||
|
if suit == Card.Spade then
|
||||||
|
return "spade"
|
||||||
|
elseif suit == Card.Heart then
|
||||||
|
return "heart"
|
||||||
|
elseif suit == Card.Club then
|
||||||
|
return "club"
|
||||||
|
elseif suit == Card.Diamond then
|
||||||
|
return "diamond"
|
||||||
|
else
|
||||||
|
return "unknown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return Card
|
return Card
|
||||||
|
|
|
@ -17,3 +17,4 @@ end
|
||||||
--debug.sethook(PrintWhenMethodCall, "c")
|
--debug.sethook(PrintWhenMethodCall, "c")
|
||||||
|
|
||||||
function p(v) print(inspect(v)) end
|
function p(v) print(inspect(v)) end
|
||||||
|
function pt(t) for k,v in pairs(t)do print(k,v) end end
|
||||||
|
|
|
@ -49,6 +49,23 @@ function table:removeOne(element)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Note: only clone key and value, no metatable
|
||||||
|
-- so dont use for class or instance
|
||||||
|
---@generic T
|
||||||
|
---@param self T
|
||||||
|
---@return T
|
||||||
|
function table.clone(self)
|
||||||
|
local ret = {}
|
||||||
|
for k, v in pairs(self) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
ret[k] = table.clone(v)
|
||||||
|
else
|
||||||
|
ret[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
---@class Sql
|
---@class Sql
|
||||||
Sql = {
|
Sql = {
|
||||||
---@param filename string
|
---@param filename string
|
||||||
|
|
|
@ -219,6 +219,42 @@ function Room:getCardArea(cardId)
|
||||||
return self.card_place[cardId] or Card.Unknown
|
return self.card_place[cardId] or Card.Unknown
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param players ServerPlayer[]
|
||||||
|
---@param card_moves CardsMoveStruct[]
|
||||||
|
---@param forceVisible boolean
|
||||||
|
function Room:notifyMoveCards(players, card_moves, forceVisible)
|
||||||
|
if players == nil or players == {} then players = self.players end
|
||||||
|
for _, p in ipairs(players) do
|
||||||
|
local arg = table.clone(card_moves)
|
||||||
|
for _, move in ipairs(arg) do
|
||||||
|
-- local to = self:getPlayerById(move.to)
|
||||||
|
|
||||||
|
-- forceVisible make the move visible
|
||||||
|
-- FIXME: move.moveInfo is an array, fix this
|
||||||
|
move.moveVisible = (forceVisible)
|
||||||
|
-- if move is relevant to player, it should be open
|
||||||
|
or ((move.from == p:getId()) or (move.to == p:getId() and move.toArea ~= Card.PlayerSpecial))
|
||||||
|
-- cards move from/to equip/judge/discard/processing should be open
|
||||||
|
or move.moveInfo.fromArea == Card.PlayerEquip
|
||||||
|
or move.toArea == Card.PlayerEquip
|
||||||
|
or move.moveInfo.fromArea == Card.PlayerJudge
|
||||||
|
or move.toArea == Card.PlayerJudge
|
||||||
|
or move.moveInfo.fromArea == Card.DiscardPile
|
||||||
|
or move.toArea == Card.DiscardPile
|
||||||
|
or move.moveInfo.fromArea == Card.Processing
|
||||||
|
or move.toArea == Card.Processing
|
||||||
|
-- TODO: PlayerSpecial
|
||||||
|
|
||||||
|
if not move.moveVisible then
|
||||||
|
for _, info in ipairs(move.moveInfo) do
|
||||||
|
info.cardId = -1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
p:doNotify("MoveCards", json.encode(arg))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@vararg CardsMoveInfo
|
---@vararg CardsMoveInfo
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function Room:moveCards(...)
|
function Room:moveCards(...)
|
||||||
|
@ -266,6 +302,8 @@ function Room:moveCards(...)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:notifyMoveCards(self.players, cardsMoveStructs)
|
||||||
|
|
||||||
for _, data in ipairs(cardsMoveStructs) do
|
for _, data in ipairs(cardsMoveStructs) do
|
||||||
if #data.moveInfo > 0 then
|
if #data.moveInfo > 0 then
|
||||||
infoCheck(data)
|
infoCheck(data)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---@alias CardsMoveInfo {ids: integer[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null }
|
---@alias CardsMoveInfo {ids: integer[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null }
|
||||||
---@alias MoveInfo {cardId: integer, fromArea: CardArea}
|
---@alias MoveInfo {cardId: integer, fromArea: CardArea}
|
||||||
---@alias CardsMoveStruct {moveInfo: {id: integer, fromArea: CardArea}[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer|null, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null, fromSpecialName: string|null }
|
---@alias CardsMoveStruct {moveInfo: MoveInfo[], from: integer|null, to: integer|null, toArea: CardArea, moveReason: CardMoveReason, proposer: integer|null, skillName: string|null, moveVisible: boolean|null, specialName: string|null, specialVisible: boolean|null, fromSpecialName: string|null }
|
||||||
|
|
||||||
---@alias HpChangedData { num: integer, reason: string, skillName: string }
|
---@alias HpChangedData { num: integer, reason: string, skillName: string }
|
||||||
---@alias HpLostData { num: integer, skillName: string }
|
---@alias HpLostData { num: integer, skillName: string }
|
||||||
|
|
|
@ -31,6 +31,15 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
-- TODO: need a new function to call the UI
|
-- TODO: need a new function to call the UI
|
||||||
local cardIds = room:getNCards(data.num)
|
local cardIds = room:getNCards(data.num)
|
||||||
player:addCards(Player.Hand, cardIds)
|
player:addCards(Player.Hand, cardIds)
|
||||||
|
local move_to_notify = {} ---@type CardsMoveStruct
|
||||||
|
move_to_notify.toArea = Card.PlayerHand
|
||||||
|
move_to_notify.to = player:getId()
|
||||||
|
move_to_notify.moveInfo = {}
|
||||||
|
for _, id in ipairs(cardIds) do
|
||||||
|
table.insert(move_to_notify.moveInfo,
|
||||||
|
{ cardId = id, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
room:notifyMoveCards(room.players, {move_to_notify})
|
||||||
|
|
||||||
for _, id in ipairs(cardIds) do
|
for _, id in ipairs(cardIds) do
|
||||||
room:setCardArea(id, Card.PlayerHand)
|
room:setCardArea(id, Card.PlayerHand)
|
||||||
|
@ -62,34 +71,31 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
error("You should never proceed PhaseNone")
|
error("You should never proceed PhaseNone")
|
||||||
end,
|
end,
|
||||||
[Player.RoundStart] = function()
|
[Player.RoundStart] = function()
|
||||||
print("Proceeding RoundStart.")
|
|
||||||
end,
|
end,
|
||||||
[Player.Start] = function()
|
[Player.Start] = function()
|
||||||
print("Proceeding Start.")
|
|
||||||
end,
|
end,
|
||||||
[Player.Judge] = function()
|
[Player.Judge] = function()
|
||||||
print("Proceeding Judge.")
|
|
||||||
end,
|
end,
|
||||||
[Player.Draw] = function()
|
[Player.Draw] = function()
|
||||||
print("Proceeding Draw.")
|
|
||||||
room:drawCards(player, 2, self.name)
|
room:drawCards(player, 2, self.name)
|
||||||
end,
|
end,
|
||||||
[Player.Play] = function()
|
[Player.Play] = function()
|
||||||
print("Proceeding Play.")
|
|
||||||
room:askForSkillInvoke(player, "rule")
|
room:askForSkillInvoke(player, "rule")
|
||||||
end,
|
end,
|
||||||
[Player.Discard] = function()
|
[Player.Discard] = function()
|
||||||
print("Proceeding Discard.")
|
|
||||||
local discardNum = #player:getCardIds(Player.Hand) - player:getMaxCards()
|
local discardNum = #player:getCardIds(Player.Hand) - player:getMaxCards()
|
||||||
if discardNum > 0 then
|
if discardNum > 0 then
|
||||||
room:askForDiscard(player, discardNum, discardNum, false, self.name)
|
room:askForDiscard(player, discardNum, discardNum, false, self.name)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
[Player.Finish] = function()
|
[Player.Finish] = function()
|
||||||
print("Proceeding Finish.")
|
|
||||||
end,
|
end,
|
||||||
[Player.NotActive] = function()
|
[Player.NotActive] = function()
|
||||||
print("Proceeding NotActive.")
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -17,6 +17,22 @@ Item {
|
||||||
property alias promptText: prompt.text
|
property alias promptText: prompt.text
|
||||||
|
|
||||||
// tmp
|
// tmp
|
||||||
|
Row {
|
||||||
|
Button{text:"摸1牌"
|
||||||
|
onClicked:{
|
||||||
|
Logic.moveCards([{
|
||||||
|
from:Logic.Player.DrawPile,
|
||||||
|
to:Logic.Player.PlaceHand,
|
||||||
|
cards:[1],
|
||||||
|
}])
|
||||||
|
}}
|
||||||
|
Button{text:"弃1牌"
|
||||||
|
onClicked:{Logic.moveCards([{
|
||||||
|
to:Logic.Player.DrawPile,
|
||||||
|
from:Logic.Player.PlaceHand,
|
||||||
|
cards:[1],
|
||||||
|
}])}}
|
||||||
|
}
|
||||||
Button {
|
Button {
|
||||||
text: "quit"
|
text: "quit"
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
@ -145,7 +161,7 @@ Item {
|
||||||
width: parent.width * 0.6
|
width: parent.width * 0.6
|
||||||
height: 150
|
height: 150
|
||||||
x: parent.width * 0.2
|
x: parent.width * 0.2
|
||||||
y: parent.height * 0.5
|
y: parent.height * 0.6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ Item {
|
||||||
property string suit: "club"
|
property string suit: "club"
|
||||||
property int number: 7
|
property int number: 7
|
||||||
property string name: "slash"
|
property string name: "slash"
|
||||||
|
property string subtype: ""
|
||||||
property string color: "" // only use when suit is empty
|
property string color: "" // only use when suit is empty
|
||||||
property string footnote: "曹操对刘备" // footnote, e.g. "A use card to B"
|
property string footnote: "" // footnote, e.g. "A use card to B"
|
||||||
property bool footnoteVisible: true
|
property bool footnoteVisible: true
|
||||||
property bool known: true // if false it only show a card back
|
property bool known: true // if false it only show a card back
|
||||||
property bool enabled: true // if false the card will be grey
|
property bool enabled: true // if false the card will be grey
|
||||||
|
@ -247,7 +248,7 @@ Item {
|
||||||
function destroyOnStop()
|
function destroyOnStop()
|
||||||
{
|
{
|
||||||
root.moveFinished.connect(function(){
|
root.moveFinished.connect(function(){
|
||||||
destroy();
|
root.destroy();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,25 @@ RowLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias self: selfPhoto
|
property alias self: selfPhoto
|
||||||
|
property alias handcardArea: handcardAreaItem
|
||||||
|
property alias equipArea: selfPhoto.equipArea
|
||||||
|
property alias delayedTrickArea: selfPhoto.delayedTrickArea
|
||||||
|
property alias specialArea: selfPhoto.specialArea
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: 40
|
||||||
|
}
|
||||||
|
|
||||||
HandcardArea {
|
HandcardArea {
|
||||||
id: handcardAreaItem
|
id: handcardAreaItem
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.preferredHeight: 130
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
Photo {
|
Photo {
|
||||||
id: selfPhoto
|
id: selfPhoto
|
||||||
|
handcards: handcardAreaItem.length
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { width: 5 }
|
Item { width: 5 }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
import "../../util.js" as Utility
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property alias cards: cardArea.cards
|
property alias cards: cardArea.cards
|
||||||
|
@ -68,12 +69,12 @@ Item {
|
||||||
for (i = 0; i < cards.length; i++) {
|
for (i = 0; i < cards.length; i++) {
|
||||||
card = cards[i];
|
card = cards[i];
|
||||||
if (card.selected)
|
if (card.selected)
|
||||||
card.homeY -= 20;
|
card.origY -= 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animated) {
|
if (animated) {
|
||||||
for (i = 0; i < cards.length; i++)
|
for (i = 0; i < cards.length; i++)
|
||||||
roomScene.cardItemGoBack(cards[i], true)
|
cards[i].goBack(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property point start: Qt.point(0, 0)
|
||||||
|
property var end: []
|
||||||
|
property alias running: pointToAnimation.running
|
||||||
|
property color color: "#96943D"
|
||||||
|
property real ratio: 0
|
||||||
|
property int lineWidth: 6
|
||||||
|
|
||||||
|
signal finished()
|
||||||
|
|
||||||
|
id: root
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: end
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 6
|
||||||
|
height: Math.sqrt(Math.pow(modelData.x - start.x, 2) + Math.pow(modelData.y - start.y, 2)) * ratio
|
||||||
|
x: start.x
|
||||||
|
y: start.y
|
||||||
|
antialiasing: true
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: Qt.rgba(255, 255, 255, 0)
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: Qt.rgba(200, 200, 200, 0.12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 3
|
||||||
|
height: parent.height
|
||||||
|
antialiasing: true
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: Qt.rgba(255, 255, 255, 0)
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: Qt.lighter(root.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transform: Rotation {
|
||||||
|
angle: 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var dx = modelData.x - start.x;
|
||||||
|
var dy = modelData.y - start.y;
|
||||||
|
if (dx > 0) {
|
||||||
|
angle = Math.atan2(dy, dx) / Math.PI * 180 - 90;
|
||||||
|
} else if (dx < 0) {
|
||||||
|
angle = Math.atan2(dy, dx) / Math.PI * 180 + 270;
|
||||||
|
} else if (dy < 0) {
|
||||||
|
angle = 180;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: pointToAnimation
|
||||||
|
|
||||||
|
PropertyAnimation {
|
||||||
|
target: root
|
||||||
|
property: "ratio"
|
||||||
|
to: 1
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
|
||||||
|
PauseAnimation {
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyAnimation {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
to: 0
|
||||||
|
easing.type: Easing.InQuart
|
||||||
|
duration: 300
|
||||||
|
}
|
||||||
|
|
||||||
|
onStopped: {
|
||||||
|
root.visible = false;
|
||||||
|
root.finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ Item {
|
||||||
let items = [];
|
let items = [];
|
||||||
for (let i = 0; i < outputs.length; i++) {
|
for (let i = 0; i < outputs.length; i++) {
|
||||||
if (_contains(outputs[i])) {
|
if (_contains(outputs[i])) {
|
||||||
let state = JSON.parse(Sanguosha.getCard4Qml(outputs[i]))
|
let state = JSON.parse(Backend.getCardData(outputs[i]))
|
||||||
state.x = parentPos.x;
|
state.x = parentPos.x;
|
||||||
state.y = parentPos.y;
|
state.y = parentPos.y;
|
||||||
state.opacity = 0;
|
state.opacity = 0;
|
||||||
|
|
|
@ -14,7 +14,7 @@ Item {
|
||||||
property string role: "unknown"
|
property string role: "unknown"
|
||||||
property string kingdom: "qun"
|
property string kingdom: "qun"
|
||||||
property string netstate: "online"
|
property string netstate: "online"
|
||||||
property int handcards: 0
|
property alias handcards: handcardAreaItem.length
|
||||||
property int maxHp: 0
|
property int maxHp: 0
|
||||||
property int hp: 0
|
property int hp: 0
|
||||||
property int seatNumber: 1
|
property int seatNumber: 1
|
||||||
|
@ -24,10 +24,19 @@ Item {
|
||||||
property bool chained: false
|
property bool chained: false
|
||||||
property bool drank: false
|
property bool drank: false
|
||||||
property bool isOwner: false
|
property bool isOwner: false
|
||||||
|
property string status: "normal"
|
||||||
|
|
||||||
|
property alias handcardArea: handcardAreaItem
|
||||||
|
property alias equipArea: equipAreaItem
|
||||||
|
property alias delayedTrickArea: delayedTrickAreaItem
|
||||||
|
property alias specialArea: handcardAreaItem
|
||||||
|
|
||||||
property alias progressBar: progressBar
|
property alias progressBar: progressBar
|
||||||
property alias progressTip: progressTip.text
|
property alias progressTip: progressTip.text
|
||||||
|
|
||||||
|
property bool selectable: false
|
||||||
|
property bool selected: false
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on x {
|
||||||
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
|
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
|
||||||
}
|
}
|
||||||
|
@ -36,6 +45,14 @@ Item {
|
||||||
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
|
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixmapAnimation {
|
||||||
|
id: animFrame
|
||||||
|
source: "selected"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
loop: true
|
||||||
|
scale: 1.1
|
||||||
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: back
|
id: back
|
||||||
source: SkinBank.PHOTO_BACK_DIR + root.kingdom
|
source: SkinBank.PHOTO_BACK_DIR + root.kingdom
|
||||||
|
@ -108,6 +125,18 @@ Item {
|
||||||
visible: screenName != "" && !roomScene.isStarted
|
visible: screenName != "" && !roomScene.isStarted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
visible: equipAreaItem.length > 0
|
||||||
|
source: SkinBank.PHOTO_DIR + "equipbg"
|
||||||
|
x: 31
|
||||||
|
y: 121
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: root.status != "normal" ? SkinBank.STATUS_DIR + root.status : ""
|
||||||
|
x: -6
|
||||||
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: turnedOver
|
id: turnedOver
|
||||||
visible: !root.faceup
|
visible: !root.faceup
|
||||||
|
@ -115,6 +144,13 @@ Item {
|
||||||
x: 29; y: 5
|
x: 29; y: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EquipArea {
|
||||||
|
id: equipAreaItem
|
||||||
|
|
||||||
|
x: 31
|
||||||
|
y: 139
|
||||||
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: chain
|
id: chain
|
||||||
visible: root.chained
|
visible: root.chained
|
||||||
|
@ -244,6 +280,30 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixmapAnimation {
|
||||||
|
id: animSelectable
|
||||||
|
source: "selectable"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
loop: true
|
||||||
|
}
|
||||||
|
|
||||||
|
InvisibleCardArea {
|
||||||
|
id: handcardAreaItem
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
DelayedTrickArea {
|
||||||
|
id: delayedTrickAreaItem
|
||||||
|
rows: 1
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 8
|
||||||
|
}
|
||||||
|
|
||||||
|
InvisibleCardArea {
|
||||||
|
id: defaultArea
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
onGeneralChanged: {
|
onGeneralChanged: {
|
||||||
if (!roomScene.isStarted) return;
|
if (!roomScene.isStarted) return;
|
||||||
generalName.text = Backend.translate(general);
|
generalName.text = Backend.translate(general);
|
||||||
|
|
|
@ -1 +1,65 @@
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import ".."
|
||||||
|
import "../../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property alias rows: grid.rows
|
||||||
|
property alias columns: grid.columns
|
||||||
|
|
||||||
|
InvisibleCardArea {
|
||||||
|
id: area
|
||||||
|
checkExisting: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: cards
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
id: grid
|
||||||
|
anchors.fill: parent
|
||||||
|
rows: 100
|
||||||
|
columns: 100
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: cards
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: SkinBank.DELAYED_TRICK_DIR + name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add(inputs)
|
||||||
|
{
|
||||||
|
area.add(inputs);
|
||||||
|
if (inputs instanceof Array) {
|
||||||
|
cards.append(...inputs);
|
||||||
|
} else {
|
||||||
|
cards.append(inputs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(outputs)
|
||||||
|
{
|
||||||
|
let result = area.remove(outputs);
|
||||||
|
for (let i = 0; i < result.length; i++) {
|
||||||
|
let item = result[i];
|
||||||
|
for (let j = 0; j < cards.count; j++) {
|
||||||
|
let icon = cards.get(j);
|
||||||
|
if (icon.cid === item.cid) {
|
||||||
|
cards.remove(j, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCardPosition(animated)
|
||||||
|
{
|
||||||
|
area.updateCardPosition(animated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,120 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import ".."
|
||||||
|
import "../../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
/* Layout of EquipArea:
|
||||||
|
* | Treasure |
|
||||||
|
| Weapon |
|
||||||
|
| Armor |
|
||||||
|
| +1 | -1 |
|
||||||
|
+---------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
Column {
|
||||||
|
height: 88
|
||||||
|
width: 138
|
||||||
|
property int itemHeight: Math.floor(height / 4)
|
||||||
|
property var items: [treasureItem, weaponItem, armorItem, defensiveHorseItem, offensiveHorseItem]
|
||||||
|
property var subtypes: ["treasure", "weapon", "armor", "defensive_horse", "offensive_horse"]
|
||||||
|
property int length: area.length
|
||||||
|
|
||||||
|
InvisibleCardArea {
|
||||||
|
id: area
|
||||||
|
checkExisting: true
|
||||||
|
}
|
||||||
|
|
||||||
|
EquipItem {
|
||||||
|
id: treasureItem
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
EquipItem {
|
||||||
|
id: weaponItem
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
EquipItem {
|
||||||
|
id: armorItem
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Math.ceil(parent.width / 2)
|
||||||
|
height: itemHeight
|
||||||
|
|
||||||
|
EquipItem {
|
||||||
|
id: defensiveHorseItem
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
icon: "horse"
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Math.floor(parent.width / 2)
|
||||||
|
height: itemHeight
|
||||||
|
|
||||||
|
EquipItem {
|
||||||
|
id: offensiveHorseItem
|
||||||
|
width: parent.width
|
||||||
|
height: itemHeight
|
||||||
|
icon: "horse"
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add(inputs)
|
||||||
|
{
|
||||||
|
area.add(inputs);
|
||||||
|
|
||||||
|
let card, item;
|
||||||
|
if (inputs instanceof Array) {
|
||||||
|
for (let i = 0; i < inputs.length; i++) {
|
||||||
|
card = inputs[i];
|
||||||
|
item = items[subtypes.indexOf(card.subtype)];
|
||||||
|
item.setCard(card);
|
||||||
|
item.show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
card = inputs;
|
||||||
|
item = items[subtypes.indexOf(card.subtype)];
|
||||||
|
item.setCard(card);
|
||||||
|
item.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(outputs)
|
||||||
|
{
|
||||||
|
let result = area.remove(outputs);
|
||||||
|
for (let i = 0; i < result.length; i++) {
|
||||||
|
let card = result[i];
|
||||||
|
for (let j = 0; j < items.length; j++) {
|
||||||
|
let item = items[j];
|
||||||
|
if (item.cid === card.cid) {
|
||||||
|
item.reset();
|
||||||
|
item.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCardPosition(animated)
|
||||||
|
{
|
||||||
|
area.updateCardPosition(animated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import ".."
|
||||||
|
import "../../../util.js" as Utility
|
||||||
|
import "../../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property int cid: 0
|
||||||
|
property string name: ""
|
||||||
|
property string suit: ""
|
||||||
|
property int number: 0
|
||||||
|
|
||||||
|
property string icon: ""
|
||||||
|
property alias text: textItem.text
|
||||||
|
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: iconItem
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
x: 3
|
||||||
|
|
||||||
|
source: icon ? SkinBank.EQUIP_ICON_DIR + icon : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: suitItem
|
||||||
|
anchors.right: parent.right
|
||||||
|
source: suit ? SkinBank.CARD_SUIT_DIR + suit : ""
|
||||||
|
width: implicitWidth / implicitHeight * height
|
||||||
|
height: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
GlowText {
|
||||||
|
id: numberItem
|
||||||
|
visible: number > 0 && number < 14
|
||||||
|
text: Utility.convertNumber(number)
|
||||||
|
color: "white"
|
||||||
|
font.family: "FZLiBian-S02"
|
||||||
|
font.pixelSize: 16
|
||||||
|
glow.color: "black"
|
||||||
|
glow.spread: 0.75
|
||||||
|
glow.radius: 2
|
||||||
|
glow.samples: 4
|
||||||
|
x: parent.width - 24
|
||||||
|
y: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
GlowText {
|
||||||
|
id: textItem
|
||||||
|
font.family: "FZLiBian-S02"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 18
|
||||||
|
glow.color: "black"
|
||||||
|
glow.spread: 0.9
|
||||||
|
glow.radius: 2
|
||||||
|
glow.samples: 6
|
||||||
|
anchors.left: iconItem.right
|
||||||
|
anchors.leftMargin: -8
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelAnimation {
|
||||||
|
id: showAnime
|
||||||
|
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "x"
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
from: 10
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelAnimation {
|
||||||
|
id: hideAnime
|
||||||
|
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "x"
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
from: 0
|
||||||
|
to: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset()
|
||||||
|
{
|
||||||
|
cid = 0;
|
||||||
|
name = "";
|
||||||
|
suit = "";
|
||||||
|
number = 0;
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCard(card)
|
||||||
|
{
|
||||||
|
cid = card.cid;
|
||||||
|
name = card.name;
|
||||||
|
suit = card.suit;
|
||||||
|
number = card.number;
|
||||||
|
if (card.subtype === "defensive_horse") {
|
||||||
|
text = "+1";
|
||||||
|
icon = "horse";
|
||||||
|
} else if (card.subtype === "offensive_horse") {
|
||||||
|
text = "-1"
|
||||||
|
icon = "horse";
|
||||||
|
} else {
|
||||||
|
text = name;
|
||||||
|
icon = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show()
|
||||||
|
{
|
||||||
|
showAnime.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide()
|
||||||
|
{
|
||||||
|
hideAnime.start();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import Qt.labs.folderlistmodel 2.15
|
||||||
|
import "../skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property string source: ""
|
||||||
|
property int currentFrame: 0
|
||||||
|
property alias interval: timer.interval
|
||||||
|
property int loadedFrameCount: 0
|
||||||
|
property bool autoStart: false
|
||||||
|
property bool loop: false
|
||||||
|
|
||||||
|
signal loaded()
|
||||||
|
signal started()
|
||||||
|
signal finished()
|
||||||
|
|
||||||
|
id: root
|
||||||
|
width: childrenRect.width
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
FolderListModel {
|
||||||
|
id: fileModel
|
||||||
|
folder: SkinBank.PIXANIM_DIR + source
|
||||||
|
nameFilters: ["*.png"]
|
||||||
|
showDirs: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: frames
|
||||||
|
model: fileModel
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: SkinBank.PIXANIM_DIR + root.source + "/" + index
|
||||||
|
visible: false
|
||||||
|
onStatusChanged: {
|
||||||
|
if (status == Image.Ready) {
|
||||||
|
loadedFrameCount++;
|
||||||
|
if (loadedFrameCount == fileModel.count)
|
||||||
|
root.loaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoaded: {
|
||||||
|
if (autoStart)
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
interval: 50
|
||||||
|
repeat: true
|
||||||
|
onTriggered: {
|
||||||
|
if (currentFrame >= fileModel.count) {
|
||||||
|
frames.itemAt(fileModel.count - 1).visible = false;
|
||||||
|
if (loop) {
|
||||||
|
currentFrame = 0;
|
||||||
|
} else {
|
||||||
|
timer.stop();
|
||||||
|
root.finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFrame > 0)
|
||||||
|
frames.itemAt(currentFrame - 1).visible = false;
|
||||||
|
frames.itemAt(currentFrame).visible = true;
|
||||||
|
|
||||||
|
currentFrame++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function start()
|
||||||
|
{
|
||||||
|
if (loadedFrameCount == fileModel.count) {
|
||||||
|
timer.start();
|
||||||
|
} else {
|
||||||
|
root.loaded.connect(function(){
|
||||||
|
timer.start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop()
|
||||||
|
{
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,9 +26,8 @@ Item {
|
||||||
if (toVanish) {
|
if (toVanish) {
|
||||||
for (i = 0; i < discardedCards.length; i++) {
|
for (i = 0; i < discardedCards.length; i++) {
|
||||||
card = discardedCards[i];
|
card = discardedCards[i];
|
||||||
card.homeOpacity = 0;
|
card.origOpacity = 0;
|
||||||
// card.goBack(true);
|
card.goBack(true);
|
||||||
roomScene.cardItemGoBack(card, true)
|
|
||||||
card.destroyOnStop()
|
card.destroyOnStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +100,12 @@ Item {
|
||||||
let overflow = false;
|
let overflow = false;
|
||||||
for (i = 0; i < cards.length; i++) {
|
for (i = 0; i < cards.length; i++) {
|
||||||
card = cards[i];
|
card = cards[i];
|
||||||
card.homeX = i * card.width;
|
card.origX = i * card.width;
|
||||||
if (card.homeX + card.width >= root.width) {
|
if (card.origX + card.width >= root.width) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
card.homeY = 0;
|
card.origY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow) {
|
if (overflow) {
|
||||||
|
@ -115,8 +114,8 @@ Item {
|
||||||
let spacing = xLimit / (cards.length - 1);
|
let spacing = xLimit / (cards.length - 1);
|
||||||
for (i = 0; i < cards.length; i++) {
|
for (i = 0; i < cards.length; i++) {
|
||||||
card = cards[i];
|
card = cards[i];
|
||||||
card.homeX = i * spacing;
|
card.origX = i * spacing;
|
||||||
card.homeY = 0;
|
card.origY = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,15 +123,13 @@ Item {
|
||||||
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||||
for (i = 0; i < cards.length; i++) {
|
for (i = 0; i < cards.length; i++) {
|
||||||
card = cards[i];
|
card = cards[i];
|
||||||
card.homeX += parentPos.x + offsetX;
|
card.origX += parentPos.x + offsetX;
|
||||||
card.homeY += parentPos.y;
|
card.origY += parentPos.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animated) {
|
if (animated) {
|
||||||
for (i = 0; i < cards.length; i++)
|
for (i = 0; i < cards.length; i++)
|
||||||
// cards[i].goBack() // WTF
|
cards[i].goBack(true)
|
||||||
// console.log(cards[i].homeOpacity)
|
|
||||||
roomScene.cardItemGoBack(cards[i], true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
var Card = {
|
||||||
|
Unknown : 0,
|
||||||
|
PlayerHand : 1,
|
||||||
|
PlayerEquip : 2,
|
||||||
|
PlayerJudge : 3,
|
||||||
|
PlayerSpecial : 4,
|
||||||
|
Processing : 5,
|
||||||
|
DrawPile : 6,
|
||||||
|
DiscardPile : 7,
|
||||||
|
Void : 8
|
||||||
|
}
|
||||||
|
|
||||||
function arrangePhotos() {
|
function arrangePhotos() {
|
||||||
/* Layout of photos:
|
/* Layout of photos:
|
||||||
* +---------------+
|
* +---------------+
|
||||||
|
@ -61,6 +73,134 @@ function replyToServer(jsonData) {
|
||||||
ClientInstance.replyToServer("", jsonData);
|
ClientInstance.replyToServer("", jsonData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPhotoModel(id) {
|
||||||
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
|
let item = photoModel.get(i);
|
||||||
|
if (item.id === id) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPhoto(id) {
|
||||||
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
|
let item = photoModel.get(i);
|
||||||
|
if (item.id === id) {
|
||||||
|
return photos.itemAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPhotoOrDashboard(id) {
|
||||||
|
let photo = getPhoto(id);
|
||||||
|
if (!photo) {
|
||||||
|
if (id === Self.id)
|
||||||
|
return dashboard;
|
||||||
|
}
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAreaItem(area, id) {
|
||||||
|
if (area === Card.DrawPile) {
|
||||||
|
return drawPile;
|
||||||
|
} else if (area === Card.DiscardPile || area === Card.Processing) {
|
||||||
|
return tablePile;
|
||||||
|
} else if (area === Card.AG) {
|
||||||
|
return popupBox.item;
|
||||||
|
}
|
||||||
|
|
||||||
|
let photo = getPhotoOrDashboard(id);
|
||||||
|
if (!photo) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (area === Card.PlayerHand) {
|
||||||
|
return photo.handcardArea;
|
||||||
|
} else if (area === Card.PlayerEquip)
|
||||||
|
return photo.equipArea;
|
||||||
|
else if (area === Card.PlayerJudge)
|
||||||
|
return photo.delayedTrickArea;
|
||||||
|
else if (area === Card.PlayerSpecial)
|
||||||
|
return photo.specialArea;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveCards(moves) {
|
||||||
|
for (let i = 0; i < moves.length; i++) {
|
||||||
|
let move = moves[i];
|
||||||
|
let from = getAreaItem(move.fromArea, move.from);
|
||||||
|
let to = getAreaItem(move.toArea, move.to);
|
||||||
|
if (!from || !to || from === to)
|
||||||
|
continue;
|
||||||
|
let items = from.remove(move.ids);
|
||||||
|
if (items.length > 0)
|
||||||
|
to.add(items);
|
||||||
|
to.updateCardPosition(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEmotion(id, emotion) {
|
||||||
|
let component = Qt.createComponent("RoomElement/PixmapAnimation.qml");
|
||||||
|
if (component.status !== Component.Ready)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let photo = getPhoto(id);
|
||||||
|
if (!photo) {
|
||||||
|
if (id === dashboardModel.id) {
|
||||||
|
photo = dashboard.self;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let animation = component.createObject(photo, {source: emotion, anchors: {centerIn: photo}});
|
||||||
|
animation.finished.connect(() => animation.destroy());
|
||||||
|
animation.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeHp(id, delta, losthp) {
|
||||||
|
let photo = getPhoto(id);
|
||||||
|
if (!photo) {
|
||||||
|
if (id === dashboardModel.id) {
|
||||||
|
photo = dashboard.self;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (delta < 0) {
|
||||||
|
if (!losthp) {
|
||||||
|
setEmotion(id, "damage")
|
||||||
|
photo.tremble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doIndicate(from, tos) {
|
||||||
|
let component = Qt.createComponent("RoomElement/IndicatorLine.qml");
|
||||||
|
if (component.status !== Component.Ready)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let fromItem = getPhotoOrDashboard(from);
|
||||||
|
let fromPos = mapFromItem(fromItem, fromItem.width / 2, fromItem.height / 2);
|
||||||
|
|
||||||
|
let end = [];
|
||||||
|
for (let i = 0; i < tos.length; i++) {
|
||||||
|
if (from === tos[i])
|
||||||
|
continue;
|
||||||
|
let toItem = getPhotoOrDashboard(tos[i]);
|
||||||
|
let toPos = mapFromItem(toItem, toItem.width / 2, toItem.height / 2);
|
||||||
|
end.push(toPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
let color = "#96943D";
|
||||||
|
let line = component.createObject(roomScene, {start: fromPos, end: end, color: color});
|
||||||
|
line.finished.connect(() => line.destroy());
|
||||||
|
line.running = true;
|
||||||
|
}
|
||||||
|
|
||||||
callbacks["AddPlayer"] = function(jsonData) {
|
callbacks["AddPlayer"] = function(jsonData) {
|
||||||
// jsonData: int id, string screenName, string avatar
|
// jsonData: int id, string screenName, string avatar
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
|
@ -81,14 +221,11 @@ callbacks["AddPlayer"] = function(jsonData) {
|
||||||
callbacks["RemovePlayer"] = function(jsonData) {
|
callbacks["RemovePlayer"] = function(jsonData) {
|
||||||
// jsonData: int uid
|
// jsonData: int uid
|
||||||
let uid = JSON.parse(jsonData)[0];
|
let uid = JSON.parse(jsonData)[0];
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
let model = getPhotoModel(uid);
|
||||||
let item = photoModel.get(i);
|
if (typeof(model) !== "undefined") {
|
||||||
if (item.id === uid) {
|
model.id = -1;
|
||||||
item.id = -1;
|
model.screenName = "";
|
||||||
item.screenName = "";
|
model.general = "";
|
||||||
item.general = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,12 +239,9 @@ callbacks["RoomOwner"] = function(jsonData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
let model = getPhotoModel(uid);
|
||||||
let item = photoModel.get(i);
|
if (typeof(model) !== "undefined") {
|
||||||
if (item.id === uid) {
|
model.isOwner = true;
|
||||||
item.isOwner = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +258,9 @@ callbacks["PropertyUpdate"] = function(jsonData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
let model = getPhotoModel(uid);
|
||||||
let item = photoModel.get(i);
|
if (typeof(model) !== "undefined") {
|
||||||
if (item.id === uid) {
|
model[property_name] = value;
|
||||||
item[property_name] = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,12 +324,9 @@ callbacks["PlayerRunned"] = function(jsonData) {
|
||||||
let runner = data[0];
|
let runner = data[0];
|
||||||
let robot = data[1];
|
let robot = data[1];
|
||||||
|
|
||||||
let model;
|
let model = getPhotoModel(runner);
|
||||||
for (let i = 0; i < playerNum - 1; i++) {
|
if (typeof(model) !== "undefined") {
|
||||||
model = photoModel.get(i);
|
model.id = robot;
|
||||||
if (model.id === runner) {
|
|
||||||
model.id = robot;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,3 +369,9 @@ callbacks["AskForChoice"] = function(jsonData) {
|
||||||
replyToServer(choices[box.result]);
|
replyToServer(choices[box.result]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callbacks["MoveCards"] = function(jsonData) {
|
||||||
|
// jsonData: merged moves
|
||||||
|
let moves = JSON.parse(jsonData);
|
||||||
|
moveCards(moves);
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
//var AppPath = "file://home/notify/develop/FreeKill";
|
//var AppPath = "file:///home/notify/develop/FreeKill";
|
||||||
var PHOTO_BACK_DIR = AppPath + "/image/photo/back/";
|
var PHOTO_BACK_DIR = AppPath + "/image/photo/back/";
|
||||||
var PHOTO_DIR = AppPath + "/image/photo/";
|
var PHOTO_DIR = AppPath + "/image/photo/";
|
||||||
var GENERAL_DIR = AppPath + "/image/generals/";
|
var GENERAL_DIR = AppPath + "/image/generals/";
|
||||||
var STATE_DIR = AppPath + "/image/photo/state/";
|
var STATE_DIR = AppPath + "/image/photo/state/";
|
||||||
|
var STATUS_DIR = AppPath + "/image/photo/status/";
|
||||||
var ROLE_DIR = AppPath + "/image/photo/role/";
|
var ROLE_DIR = AppPath + "/image/photo/role/";
|
||||||
var DEATH_DIR = AppPath + "/image/photo/death/";
|
var DEATH_DIR = AppPath + "/image/photo/death/";
|
||||||
var MAGATAMA_DIR = AppPath + "/image/photo/magatama/";
|
var MAGATAMA_DIR = AppPath + "/image/photo/magatama/";
|
||||||
var CARD_DIR = AppPath + "/image/card/";
|
var CARD_DIR = AppPath + "/image/card/";
|
||||||
var CARD_SUIT_DIR = AppPath + "/image/card/suit/";
|
var CARD_SUIT_DIR = AppPath + "/image/card/suit/";
|
||||||
|
var DELAYED_TRICK_DIR = AppPath + "/image/card/delayedTrick/";
|
||||||
|
var EQUIP_ICON_DIR = AppPath + "/image/card/equipIcon/";
|
||||||
|
var PIXANIM_DIR = AppPath + "/image/anim/"
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
.pragma library
|
||||||
|
|
||||||
|
function convertNumber(number) {
|
||||||
|
if (number === 1)
|
||||||
|
return "A";
|
||||||
|
if (number >= 2 && number <= 10)
|
||||||
|
return number;
|
||||||
|
if (number >= 11 && number <= 13) {
|
||||||
|
const strs = ["J", "Q", "K"];
|
||||||
|
return strs[number - 11];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.contains = function(element) {
|
||||||
|
return this.indexOf(element) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.prepend = function() {
|
||||||
|
this.splice(0, 0, ...arguments);
|
||||||
|
}
|
|
@ -85,20 +85,22 @@ bool QmlBackend::isDir(const QString &file) {
|
||||||
return QFileInfo(file).isDir();
|
return QFileInfo(file).isDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CALLFUNC int err = lua_pcall(L, 1, 1, 0); \
|
||||||
|
const char *result = lua_tostring(L, -1); \
|
||||||
|
if (err) { \
|
||||||
|
qDebug() << result; \
|
||||||
|
lua_pop(L, 1); \
|
||||||
|
return ""; \
|
||||||
|
} \
|
||||||
|
lua_pop(L, 1); \
|
||||||
|
return QString(result); \
|
||||||
|
|
||||||
QString QmlBackend::translate(const QString &src) {
|
QString QmlBackend::translate(const QString &src) {
|
||||||
lua_State *L = ClientInstance->getLuaState();
|
lua_State *L = ClientInstance->getLuaState();
|
||||||
lua_getglobal(L, "Translate");
|
lua_getglobal(L, "Translate");
|
||||||
lua_pushstring(L, src.toUtf8().data());
|
lua_pushstring(L, src.toUtf8().data());
|
||||||
|
|
||||||
int err = lua_pcall(L, 1, 1, 0);
|
CALLFUNC
|
||||||
const char *result = lua_tostring(L, -1);
|
|
||||||
if (err) {
|
|
||||||
qDebug() << result;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return QString(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlBackend::getGeneralData(const QString &general_name) {
|
QString QmlBackend::getGeneralData(const QString &general_name) {
|
||||||
|
@ -106,13 +108,15 @@ QString QmlBackend::getGeneralData(const QString &general_name) {
|
||||||
lua_getglobal(L, "GetGeneralData");
|
lua_getglobal(L, "GetGeneralData");
|
||||||
lua_pushstring(L, general_name.toUtf8().data());
|
lua_pushstring(L, general_name.toUtf8().data());
|
||||||
|
|
||||||
int err = lua_pcall(L, 1, 1, 0);
|
CALLFUNC
|
||||||
const char *result = lua_tostring(L, -1);
|
|
||||||
if (err) {
|
|
||||||
qDebug() << result;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return QString(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QmlBackend::getCardData(int id) {
|
||||||
|
lua_State *L = ClientInstance->getLuaState();
|
||||||
|
lua_getglobal(L, "GetCardData");
|
||||||
|
lua_pushinteger(L, id);
|
||||||
|
|
||||||
|
CALLFUNC
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CALLFUNC
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
// read data from lua, call lua functions
|
// read data from lua, call lua functions
|
||||||
Q_INVOKABLE QString translate(const QString &src);
|
Q_INVOKABLE QString translate(const QString &src);
|
||||||
Q_INVOKABLE QString getGeneralData(const QString &general_name);
|
Q_INVOKABLE QString getGeneralData(const QString &general_name);
|
||||||
|
Q_INVOKABLE QString getCardData(int id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void notifyUI(const QString &command, const QString &jsonData);
|
void notifyUI(const QString &command, const QString &jsonData);
|
||||||
|
|