parent
69137c9eba
commit
64127bffb6
|
@ -15,7 +15,7 @@ QtObject {
|
||||||
property string roomBg
|
property string roomBg
|
||||||
property string bgmFile
|
property string bgmFile
|
||||||
property string language
|
property string language
|
||||||
property var disabledPack: []
|
property list<string> disabledPack: []
|
||||||
property string preferedMode
|
property string preferedMode
|
||||||
property int preferedPlayerNum
|
property int preferedPlayerNum
|
||||||
property int preferredGeneralNum
|
property int preferredGeneralNum
|
||||||
|
@ -23,8 +23,8 @@ QtObject {
|
||||||
property real bgmVolume
|
property real bgmVolume
|
||||||
property bool disableMsgAudio
|
property bool disableMsgAudio
|
||||||
property bool hideUseless
|
property bool hideUseless
|
||||||
property var disabledGenerals: []
|
property list<string> disabledGenerals: []
|
||||||
property var disableGeneralSchemes: []
|
property list<var> disableGeneralSchemes: []
|
||||||
property int disableSchemeIdx: 0
|
property int disableSchemeIdx: 0
|
||||||
|
|
||||||
property int preferredTimeout
|
property int preferredTimeout
|
||||||
|
@ -39,13 +39,13 @@ QtObject {
|
||||||
|
|
||||||
// Client data
|
// Client data
|
||||||
property string serverMotd: ""
|
property string serverMotd: ""
|
||||||
property var serverHiddenPacks: []
|
property list<string> serverHiddenPacks: []
|
||||||
property int roomCapacity: 0
|
property int roomCapacity: 0
|
||||||
property int roomTimeout: 0
|
property int roomTimeout: 0
|
||||||
property bool enableFreeAssign: false
|
property bool enableFreeAssign: false
|
||||||
property bool observing: false
|
property bool observing: false
|
||||||
property bool replaying: false
|
property bool replaying: false
|
||||||
property var blockedUsers: []
|
property list<string> blockedUsers: []
|
||||||
|
|
||||||
onDisabledGeneralsChanged: {
|
onDisabledGeneralsChanged: {
|
||||||
disableGeneralSchemes[disableSchemeIdx] = disabledGenerals;
|
disableGeneralSchemes[disableSchemeIdx] = disabledGenerals;
|
||||||
|
|
|
@ -431,6 +431,7 @@ Item {
|
||||||
isOwner: model.isOwner
|
isOwner: model.isOwner
|
||||||
ready: model.ready
|
ready: model.ready
|
||||||
surrendered: model.surrendered
|
surrendered: model.surrendered
|
||||||
|
sealedSlots: JSON.parse(model.sealedSlots)
|
||||||
|
|
||||||
onSelectedChanged: {
|
onSelectedChanged: {
|
||||||
Logic.updateSelectedTargets(playerid, selected);
|
Logic.updateSelectedTargets(playerid, selected);
|
||||||
|
@ -1227,6 +1228,7 @@ Item {
|
||||||
isOwner: false,
|
isOwner: false,
|
||||||
ready: false,
|
ready: false,
|
||||||
surrendered: false,
|
surrendered: false,
|
||||||
|
sealedSlots: "[]",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -663,11 +663,14 @@ callbacks["PropertyUpdate"] = (jsonData) => {
|
||||||
const data = JSON.parse(jsonData);
|
const data = JSON.parse(jsonData);
|
||||||
const uid = data[0];
|
const uid = data[0];
|
||||||
const property_name = data[1];
|
const property_name = data[1];
|
||||||
const value = data[2];
|
let value = data[2];
|
||||||
|
|
||||||
let model = getPhotoModel(uid);
|
let model = getPhotoModel(uid);
|
||||||
|
|
||||||
if (typeof(model) !== "undefined") {
|
if (typeof(model) !== "undefined") {
|
||||||
|
if (property_name == "sealedSlots")
|
||||||
|
value = JSON.stringify(value); // 辣鸡qml
|
||||||
|
|
||||||
model[property_name] = value;
|
model[property_name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,16 @@ import Fk
|
||||||
import Fk.RoomElement
|
import Fk.RoomElement
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
property bool sealed: parent.sealedSlots.includes("JudgeSlot")
|
||||||
|
|
||||||
|
Image {
|
||||||
|
visible: sealed
|
||||||
|
x: -6; y: 8; z: 9
|
||||||
|
source: SkinBank.DELAYED_TRICK_DIR + "sealed"
|
||||||
|
height: 28
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
|
||||||
InvisibleCardArea {
|
InvisibleCardArea {
|
||||||
id: area
|
id: area
|
||||||
checkExisting: true
|
checkExisting: true
|
||||||
|
|
|
@ -13,9 +13,11 @@ import Fk.RoomElement
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
id: root
|
||||||
|
|
||||||
height: 70
|
height: 70
|
||||||
width: 138
|
width: 138
|
||||||
property int itemHeight: treasureItem.name === "" ? height / 3 : height / 4
|
property int itemHeight: (treasureItem.name === "" && !treasureItem.sealed) ? height / 3 : height / 4
|
||||||
property var items: [treasureItem, weaponItem, armorItem, defensiveHorseItem, offensiveHorseItem]
|
property var items: [treasureItem, weaponItem, armorItem, defensiveHorseItem, offensiveHorseItem]
|
||||||
property var subtypes: ["treasure", "weapon", "armor", "defensive_horse", "offensive_horse"]
|
property var subtypes: ["treasure", "weapon", "armor", "defensive_horse", "offensive_horse"]
|
||||||
property int length: area.length
|
property int length: area.length
|
||||||
|
@ -28,23 +30,29 @@ Column {
|
||||||
|
|
||||||
EquipItem {
|
EquipItem {
|
||||||
id: treasureItem
|
id: treasureItem
|
||||||
|
subtype: "treasure"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: name === "" ? 0 : itemHeight
|
height: (name === "" && !sealed) ? 0 : itemHeight
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
sealed: root.parent.sealedSlots.includes('TreasureSlot')
|
||||||
}
|
}
|
||||||
|
|
||||||
EquipItem {
|
EquipItem {
|
||||||
id: weaponItem
|
id: weaponItem
|
||||||
|
subtype: "weapon"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: itemHeight
|
height: itemHeight
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
sealed: root.parent.sealedSlots.includes('WeaponSlot')
|
||||||
}
|
}
|
||||||
|
|
||||||
EquipItem {
|
EquipItem {
|
||||||
id: armorItem
|
id: armorItem
|
||||||
|
subtype: "armor"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: itemHeight
|
height: itemHeight
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
sealed: root.parent.sealedSlots.includes('ArmorSlot')
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
@ -61,6 +69,7 @@ Column {
|
||||||
height: itemHeight
|
height: itemHeight
|
||||||
icon: "horse"
|
icon: "horse"
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
sealed: root.parent.sealedSlots.includes('DefensiveRideSlot')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +83,7 @@ Column {
|
||||||
height: itemHeight
|
height: itemHeight
|
||||||
icon: "horse"
|
icon: "horse"
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
sealed: root.parent.sealedSlots.includes('OffensiveRideSlot')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,31 +9,41 @@ Item {
|
||||||
property string name: ""
|
property string name: ""
|
||||||
property string suit: ""
|
property string suit: ""
|
||||||
property int number: 0
|
property int number: 0
|
||||||
|
property bool sealed: false
|
||||||
|
property string subtype
|
||||||
|
|
||||||
property string icon: ""
|
property string icon: ""
|
||||||
property alias text: textItem.text
|
property alias text: textItem.text
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 2
|
||||||
|
visible: sealed
|
||||||
|
color: "#CCC"
|
||||||
|
opacity: 0.8
|
||||||
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: iconItem
|
id: iconItem
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
x: 3
|
x: 3
|
||||||
|
|
||||||
source: icon ? SkinBank.getEquipIcon(cid, icon) : ""
|
source: sealed ? (SkinBank.EQUIP_ICON_DIR + "sealed") : (icon ? SkinBank.getEquipIcon(cid, icon) : "")
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: suitItem
|
id: suitItem
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
source: suit ? SkinBank.CARD_SUIT_DIR + suit : ""
|
source: (suit && !sealed) ? SkinBank.CARD_SUIT_DIR + suit : ""
|
||||||
width: implicitWidth / implicitHeight * height
|
width: implicitWidth / implicitHeight * height
|
||||||
height: 16
|
height: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
GlowText {
|
GlowText {
|
||||||
id: numberItem
|
id: numberItem
|
||||||
visible: number > 0 && number < 14
|
visible: !sealed && number > 0 && number < 14
|
||||||
text: Utility.convertNumber(number)
|
text: Utility.convertNumber(number)
|
||||||
color: "white"
|
color: "white"
|
||||||
font.family: fontLibian.name
|
font.family: fontLibian.name
|
||||||
|
@ -49,7 +59,7 @@ Item {
|
||||||
Text {
|
Text {
|
||||||
id: textItem
|
id: textItem
|
||||||
font.family: fontLibian.name
|
font.family: fontLibian.name
|
||||||
color: "white"
|
color: sealed ? "black" : "white"
|
||||||
font.pixelSize: 18
|
font.pixelSize: 18
|
||||||
anchors.left: iconItem.right
|
anchors.left: iconItem.right
|
||||||
anchors.leftMargin: -8
|
anchors.leftMargin: -8
|
||||||
|
@ -131,13 +141,24 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function show()
|
function show() {
|
||||||
{
|
if (!sealed) {
|
||||||
showAnime.start();
|
showAnime.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide()
|
function hide() {
|
||||||
{
|
if (!sealed) {
|
||||||
hideAnime.start();
|
hideAnime.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSealedChanged: {
|
||||||
|
showAnime.stop();
|
||||||
|
hideAnime.stop();
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
opacity = 1;
|
||||||
|
text = ' ' + Backend.translate(subtype + "_sealed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ Item {
|
||||||
property int winGame: 0
|
property int winGame: 0
|
||||||
property int runGame: 0
|
property int runGame: 0
|
||||||
property int totalGame: 0
|
property int totalGame: 0
|
||||||
|
property list<string> sealedSlots: []
|
||||||
|
|
||||||
property int distance: -1
|
property int distance: -1
|
||||||
property string status: "normal"
|
property string status: "normal"
|
||||||
|
@ -41,6 +42,7 @@ Item {
|
||||||
|
|
||||||
property alias handcardArea: handcardAreaItem
|
property alias handcardArea: handcardAreaItem
|
||||||
property alias equipArea: equipAreaItem
|
property alias equipArea: equipAreaItem
|
||||||
|
property alias areasSealed: equipAreaItem
|
||||||
property alias markArea: markAreaItem
|
property alias markArea: markAreaItem
|
||||||
property alias picMarkArea: picMarkAreaItem
|
property alias picMarkArea: picMarkAreaItem
|
||||||
property alias delayedTrickArea: delayedTrickAreaItem
|
property alias delayedTrickArea: delayedTrickAreaItem
|
||||||
|
|
|
@ -16,7 +16,7 @@ Window {
|
||||||
minimumHeight: 90
|
minimumHeight: 90
|
||||||
title: qsTr("FreeKill") + " v" + FkVersion
|
title: qsTr("FreeKill") + " v" + FkVersion
|
||||||
property var callbacks: Logic.callbacks
|
property var callbacks: Logic.callbacks
|
||||||
property var tipList: []
|
property list<string> tipList: []
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: mainWindow
|
id: mainWindow
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 1016 B |
|
@ -338,6 +338,11 @@ Fk:loadTranslationTable{
|
||||||
["Distance"] = "距离",
|
["Distance"] = "距离",
|
||||||
["Judge"] = "判定",
|
["Judge"] = "判定",
|
||||||
["Retrial"] = "改判",
|
["Retrial"] = "改判",
|
||||||
|
|
||||||
|
["_sealed"] = "废除",
|
||||||
|
["weapon_sealed"] = "武器栏废除",
|
||||||
|
["armor_sealed"] = "防具栏废除",
|
||||||
|
["treasure_sealed"] = "宝物栏废除",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- related to sendLog
|
-- related to sendLog
|
||||||
|
|
|
@ -61,6 +61,13 @@ Player.HistoryTurn = 2
|
||||||
Player.HistoryRound = 3
|
Player.HistoryRound = 3
|
||||||
Player.HistoryGame = 4
|
Player.HistoryGame = 4
|
||||||
|
|
||||||
|
Player.WeaponSlot = 'WeaponSlot'
|
||||||
|
Player.ArmorSlot = 'ArmorSlot'
|
||||||
|
Player.OffensiveRideSlot = 'OffensiveRideSlot'
|
||||||
|
Player.DefensiveRideSlot = 'DefensiveRideSlot'
|
||||||
|
Player.TreasureSlot = 'TreasureSlot'
|
||||||
|
Player.JudgeSlot = 'JudgeSlot'
|
||||||
|
|
||||||
--- 构造函数。总之这不是随便调用的函数
|
--- 构造函数。总之这不是随便调用的函数
|
||||||
function Player:initialize()
|
function Player:initialize()
|
||||||
self.id = 0
|
self.id = 0
|
||||||
|
@ -93,6 +100,15 @@ function Player:initialize()
|
||||||
self.virtual_equips = {}
|
self.virtual_equips = {}
|
||||||
self.special_cards = {}
|
self.special_cards = {}
|
||||||
|
|
||||||
|
self.equipSlots = {
|
||||||
|
Player.WeaponSlot,
|
||||||
|
Player.ArmorSlot,
|
||||||
|
Player.OffensiveRideSlot,
|
||||||
|
Player.DefensiveRideSlot,
|
||||||
|
Player.TreasureSlot,
|
||||||
|
}
|
||||||
|
self.sealedSlots = {}
|
||||||
|
|
||||||
self.cardUsedHistory = {}
|
self.cardUsedHistory = {}
|
||||||
self.skillUsedHistory = {}
|
self.skillUsedHistory = {}
|
||||||
self.fixedDistance = {}
|
self.fixedDistance = {}
|
||||||
|
@ -392,6 +408,20 @@ function Player:getEquipment(cardSubtype)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- 检索玩家装备区是否存在对应类型的装备列表。
|
||||||
|
---@param cardSubtype CardSubtype @ 卡牌子类
|
||||||
|
---@return integer[] @ 返回卡牌ID或空表
|
||||||
|
function Player:getEquipments(cardSubtype)
|
||||||
|
local cardIds = {}
|
||||||
|
for _, cardId in ipairs(self.player_cards[Player.Equip]) do
|
||||||
|
if Fk:getCardById(cardId).sub_type == cardSubtype then
|
||||||
|
table.insert(cardIds, cardId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cardIds
|
||||||
|
end
|
||||||
|
|
||||||
--- 获取玩家手牌上限。
|
--- 获取玩家手牌上限。
|
||||||
function Player:getMaxCards()
|
function Player:getMaxCards()
|
||||||
local baseValue = math.max(self.hp, 0)
|
local baseValue = math.max(self.hp, 0)
|
||||||
|
@ -799,6 +829,15 @@ end
|
||||||
---@param card Card @ 特定牌
|
---@param card Card @ 特定牌
|
||||||
function Player:isProhibited(to, card)
|
function Player:isProhibited(to, card)
|
||||||
local r = Fk:currentRoom()
|
local r = Fk:currentRoom()
|
||||||
|
|
||||||
|
if card.type == Card.TypeEquip and #to:getAvailableEquipSlots(card.sub_type) == 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if card.sub_type == Card.SubtypeDelayedTrick and table.contains(to.sealedSlots, Player.JudgeSlot) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
local status_skills = r.status_skills[ProhibitSkill] or Util.DummyTable
|
local status_skills = r.status_skills[ProhibitSkill] or Util.DummyTable
|
||||||
for _, skill in ipairs(status_skills) do
|
for _, skill in ipairs(status_skills) do
|
||||||
if skill:isProhibited(self, to, card) then
|
if skill:isProhibited(self, to, card) then
|
||||||
|
@ -871,11 +910,15 @@ function Player:canMoveCardInBoardTo(to, id)
|
||||||
assert(card.type == Card.TypeEquip or card.sub_type == Card.SubtypeDelayedTrick)
|
assert(card.type == Card.TypeEquip or card.sub_type == Card.SubtypeDelayedTrick)
|
||||||
|
|
||||||
if card.type == Card.TypeEquip then
|
if card.type == Card.TypeEquip then
|
||||||
return not to:getEquipment(card.sub_type)
|
return to:hasEmptyEquipSlot(card.sub_type)
|
||||||
else
|
else
|
||||||
return not table.find(to:getCardIds(Player.Judge), function(cardId)
|
return
|
||||||
return Fk:getCardById(cardId).name == card.name
|
not (
|
||||||
end)
|
table.find(to:getCardIds(Player.Judge), function(cardId)
|
||||||
|
return Fk:getCardById(cardId).name == card.name
|
||||||
|
end) or
|
||||||
|
table.contains(to.sealedSlots, Player.JudgeSlot)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -910,6 +953,41 @@ function Player:getQuestSkillState(skillName)
|
||||||
return type(questSkillState) == "string" and questSkillState or nil
|
return type(questSkillState) == "string" and questSkillState or nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Player:getAvailableEquipSlots(subtype)
|
||||||
|
local tempSlots = table.simpleClone(self.equipSlots)
|
||||||
|
local tempSealedSlots = table.simpleClone(self.sealedSlots)
|
||||||
|
|
||||||
|
if subtype then
|
||||||
|
local subtype2slot = {
|
||||||
|
[Card.SubtypeWeapon] = Player.WeaponSlot,
|
||||||
|
[Card.SubtypeArmor] = Player.ArmorSlot,
|
||||||
|
[Card.SubtypeOffensiveRide] = Player.OffensiveRideSlot,
|
||||||
|
[Card.SubtypeDefensiveRide] = Player.DefensiveRideSlot,
|
||||||
|
[Card.SubtypeTreasure] = Player.TreasureSlot,
|
||||||
|
}
|
||||||
|
|
||||||
|
local singleSlot = table.filter(tempSlots, function(slot)
|
||||||
|
return slot == subtype2slot[subtype]
|
||||||
|
end)
|
||||||
|
|
||||||
|
for _, sealedSlot in ipairs(tempSealedSlots) do
|
||||||
|
table.removeOne(singleSlot, sealedSlot)
|
||||||
|
end
|
||||||
|
|
||||||
|
return singleSlot
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, sealedSlot in ipairs(tempSealedSlots) do
|
||||||
|
table.removeOne(tempSlots, sealedSlot)
|
||||||
|
end
|
||||||
|
|
||||||
|
return tempSlots
|
||||||
|
end
|
||||||
|
|
||||||
|
function Player:hasEmptyEquipSlot(subtype)
|
||||||
|
return #self:getAvailableEquipSlots(subtype) - #self:getEquipments(subtype) > 0
|
||||||
|
end
|
||||||
|
|
||||||
function Player:addBuddy(other)
|
function Player:addBuddy(other)
|
||||||
table.insert(self.buddy_list, other.id)
|
table.insert(self.buddy_list, other.id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,30 @@ Util.lockTable = function(t)
|
||||||
return setmetatable({}, new_mt)
|
return setmetatable({}, new_mt)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Util.convertSubtypeAndEquipSlot = function(value)
|
||||||
|
if type(value) == "number" then
|
||||||
|
local mapper = {
|
||||||
|
[Card.SubtypeWeapon] = Player.WeaponSlot,
|
||||||
|
[Card.SubtypeArmor] = Player.ArmorSlot,
|
||||||
|
[Card.SubtypeOffensiveRide] = Player.OffensiveRideSlot,
|
||||||
|
[Card.SubtypeDefensiveRide] = Player.DefensiveRideSlot,
|
||||||
|
[Card.SubtypeTreasure] = Player.TreasureSlot,
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapper[value]
|
||||||
|
else
|
||||||
|
local mapper = {
|
||||||
|
[Player.WeaponSlot] = Card.SubtypeWeapon,
|
||||||
|
[Player.ArmorSlot] = Card.SubtypeArmor,
|
||||||
|
[Player.OffensiveRideSlot] = Card.SubtypeOffensiveRide,
|
||||||
|
[Player.DefensiveRideSlot] = Card.SubtypeDefensiveRide,
|
||||||
|
[Player.TreasureSlot] = Card.SubtypeTreasure,
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapper[value]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function printf(fmt, ...)
|
function printf(fmt, ...)
|
||||||
print(string.format(fmt, ...))
|
print(string.format(fmt, ...))
|
||||||
end
|
end
|
||||||
|
|
|
@ -438,6 +438,18 @@ local defaultCardSkill = fk.CreateActiveSkill{
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local defaultEquipSkill = fk.CreateActiveSkill{
|
||||||
|
name = "default_equip_skill",
|
||||||
|
can_use = function(self, player, card)
|
||||||
|
return #player:getAvailableEquipSlots(card.sub_type) > 0
|
||||||
|
end,
|
||||||
|
on_use = function(self, room, use)
|
||||||
|
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
||||||
|
use.tos = { { use.from } }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
local function preprocessCardSpec(spec)
|
local function preprocessCardSpec(spec)
|
||||||
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
|
||||||
if not spec.name then spec.name = spec.class_name
|
if not spec.name then spec.name = spec.class_name
|
||||||
|
@ -447,7 +459,7 @@ local function preprocessCardSpec(spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readCardSpecToCard(card, spec)
|
local function readCardSpecToCard(card, spec)
|
||||||
card.skill = spec.skill or defaultCardSkill
|
card.skill = spec.skill or (card.type == Card.TypeEquip and defaultEquipSkill or defaultCardSkill)
|
||||||
card.skill.cardSkill = true
|
card.skill.cardSkill = true
|
||||||
card.special_skills = spec.special_skills
|
card.special_skills = spec.special_skills
|
||||||
card.is_damage_card = spec.is_damage_card
|
card.is_damage_card = spec.is_damage_card
|
||||||
|
|
|
@ -17,33 +17,69 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
|
||||||
|
|
||||||
---@type MoveInfo[]
|
---@type MoveInfo[]
|
||||||
local infos = {}
|
local infos = {}
|
||||||
|
local abortMoveInfos = {}
|
||||||
for _, id in ipairs(cardsMoveInfo.ids) do
|
for _, id in ipairs(cardsMoveInfo.ids) do
|
||||||
table.insert(infos, {
|
local toAbortDrop = false
|
||||||
cardId = id,
|
if cardsMoveInfo.toArea == Card.PlayerEquip and cardsMoveInfo.to then
|
||||||
fromArea = room:getCardArea(id),
|
local moveToPlayer = room:getPlayerById(cardsMoveInfo.to)
|
||||||
fromSpecialName = cardsMoveInfo.from and room:getPlayerById(cardsMoveInfo.from):getPileNameOfId(id),
|
local card = moveToPlayer:getVirualEquip(id) or Fk:getCardById(id)
|
||||||
})
|
if card.type == Card.TypeEquip and #moveToPlayer:getAvailableEquipSlots(card.sub_type) == 0 then
|
||||||
|
table.insert(abortMoveInfos, {
|
||||||
|
cardId = id,
|
||||||
|
fromArea = room:getCardArea(id),
|
||||||
|
fromSpecialName = cardsMoveInfo.from and room:getPlayerById(cardsMoveInfo.from):getPileNameOfId(id),
|
||||||
|
})
|
||||||
|
toAbortDrop = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not toAbortDrop then
|
||||||
|
table.insert(infos, {
|
||||||
|
cardId = id,
|
||||||
|
fromArea = room:getCardArea(id),
|
||||||
|
fromSpecialName = cardsMoveInfo.from and room:getPlayerById(cardsMoveInfo.from):getPileNameOfId(id),
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type CardsMoveStruct
|
if #infos > 0 then
|
||||||
local cardsMoveStruct = {
|
---@type CardsMoveStruct
|
||||||
moveInfo = infos,
|
local cardsMoveStruct = {
|
||||||
from = cardsMoveInfo.from,
|
moveInfo = infos,
|
||||||
to = cardsMoveInfo.to,
|
from = cardsMoveInfo.from,
|
||||||
toArea = cardsMoveInfo.toArea,
|
to = cardsMoveInfo.to,
|
||||||
moveReason = cardsMoveInfo.moveReason,
|
toArea = cardsMoveInfo.toArea,
|
||||||
proposer = cardsMoveInfo.proposer,
|
moveReason = cardsMoveInfo.moveReason,
|
||||||
skillName = cardsMoveInfo.skillName,
|
proposer = cardsMoveInfo.proposer,
|
||||||
moveVisible = cardsMoveInfo.moveVisible,
|
skillName = cardsMoveInfo.skillName,
|
||||||
specialName = cardsMoveInfo.specialName,
|
moveVisible = cardsMoveInfo.moveVisible,
|
||||||
specialVisible = cardsMoveInfo.specialVisible,
|
specialName = cardsMoveInfo.specialName,
|
||||||
drawPilePosition = cardsMoveInfo.drawPilePosition,
|
specialVisible = cardsMoveInfo.specialVisible,
|
||||||
}
|
drawPilePosition = cardsMoveInfo.drawPilePosition,
|
||||||
|
}
|
||||||
|
|
||||||
table.insert(cardsMoveStructs, cardsMoveStruct)
|
table.insert(cardsMoveStructs, cardsMoveStruct)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #abortMoveInfos > 0 then
|
||||||
|
---@type CardsMoveStruct
|
||||||
|
local cardsMoveStruct = {
|
||||||
|
moveInfo = abortMoveInfos,
|
||||||
|
from = cardsMoveInfo.from,
|
||||||
|
toArea = Card.DiscardPile,
|
||||||
|
moveReason = fk.ReasonPutIntoDiscardPile,
|
||||||
|
specialName = cardsMoveInfo.specialName,
|
||||||
|
specialVisible = cardsMoveInfo.specialVisible,
|
||||||
|
drawPilePosition = cardsMoveInfo.drawPilePosition,
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(cardsMoveStructs, cardsMoveStruct)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.data = cardsMoveStructs
|
||||||
|
|
||||||
if #cardsMoveStructs < 1 then
|
if #cardsMoveStructs < 1 then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
|
@ -185,13 +185,7 @@ GameEvent.functions[GameEvent.UseCard] = function(self)
|
||||||
local room = self.room
|
local room = self.room
|
||||||
local logic = room.logic
|
local logic = room.logic
|
||||||
|
|
||||||
local from = cardUseEvent.from
|
room:moveCardTo(cardUseEvent.card, Card.Processing, nil, fk.ReasonUse)
|
||||||
room:moveCards({
|
|
||||||
ids = room:getSubcardsByRule(cardUseEvent.card),
|
|
||||||
from = from,
|
|
||||||
toArea = Card.Processing,
|
|
||||||
moveReason = fk.ReasonUse,
|
|
||||||
})
|
|
||||||
|
|
||||||
if cardUseEvent.card.skill then
|
if cardUseEvent.card.skill then
|
||||||
cardUseEvent.card.skill:onUse(room, cardUseEvent)
|
cardUseEvent.card.skill:onUse(room, cardUseEvent)
|
||||||
|
@ -270,12 +264,7 @@ GameEvent.functions[GameEvent.RespondCard] = function(self)
|
||||||
card = cardIds,
|
card = cardIds,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
room:moveCards({
|
room:moveCardTo(card, Card.Processing, nil, fk.ReasonResonpse)
|
||||||
ids = cardIds,
|
|
||||||
from = from,
|
|
||||||
toArea = Card.Processing,
|
|
||||||
moveReason = fk.ReasonResonpse,
|
|
||||||
})
|
|
||||||
if #cardIds > 0 then
|
if #cardIds > 0 then
|
||||||
room:sendFootnote(cardIds, {
|
room:sendFootnote(cardIds, {
|
||||||
type = "##ResponsePlayCard",
|
type = "##ResponsePlayCard",
|
||||||
|
|
|
@ -2210,7 +2210,7 @@ function Room:doCardUseEffect(cardUseEvent)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:getPlayerById(TargetGroup:getRealTargets(cardUseEvent.tos)[1]).dead then
|
if self:getPlayerById(TargetGroup:getRealTargets(cardUseEvent.tos)[1]).dead then
|
||||||
self.moveCards({
|
self:moveCards({
|
||||||
ids = realCardIds,
|
ids = realCardIds,
|
||||||
toArea = Card.DiscardPile,
|
toArea = Card.DiscardPile,
|
||||||
moveReason = fk.ReasonPutIntoDiscardPile,
|
moveReason = fk.ReasonPutIntoDiscardPile,
|
||||||
|
@ -2621,17 +2621,30 @@ function Room:moveCardTo(card, to_place, target, reason, skill_name, special_nam
|
||||||
to = target.id
|
to = target.id
|
||||||
end
|
end
|
||||||
|
|
||||||
self:moveCards{
|
local movesSplitedByOwner = {}
|
||||||
ids = ids,
|
for _, cardId in ipairs(ids) do
|
||||||
from = self.owner_map[ids[1]],
|
local moveFound = table.find(movesSplitedByOwner, function(move)
|
||||||
to = to,
|
return move.from == self.owner_map[cardId]
|
||||||
toArea = to_place,
|
end)
|
||||||
moveReason = reason,
|
|
||||||
skillName = skill_name,
|
if moveFound then
|
||||||
specialName = special_name,
|
table.insert(moveFound.ids, cardId)
|
||||||
moveVisible = visible,
|
else
|
||||||
proposer = proposer,
|
table.insert(movesSplitedByOwner, {
|
||||||
}
|
ids = { cardId },
|
||||||
|
from = self.owner_map[cardId],
|
||||||
|
to = to,
|
||||||
|
toArea = to_place,
|
||||||
|
moveReason = reason,
|
||||||
|
skillName = skill_name,
|
||||||
|
specialName = special_name,
|
||||||
|
moveVisible = visible,
|
||||||
|
proposer = proposer,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:moveCards(table.unpack(movesSplitedByOwner))
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
@ -3210,4 +3223,54 @@ function Room:updateQuestSkillState(player, skillName, failed)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Room:abortPlayerArea(player, playerSlots)
|
||||||
|
assert(type(playerSlots) == "string" or type(playerSlots) == "table")
|
||||||
|
|
||||||
|
if type(playerSlots) == "string" then
|
||||||
|
playerSlots = { playerSlots }
|
||||||
|
end
|
||||||
|
|
||||||
|
local cardsToDrop = {}
|
||||||
|
local slotsSealed = {}
|
||||||
|
local slotsToSeal = {}
|
||||||
|
for _, slot in ipairs(playerSlots) do
|
||||||
|
if slot == Player.JudgeSlot then
|
||||||
|
if not table.contains(player.sealedSlots, Player.JudgeSlot) then
|
||||||
|
table.insertIfNeed(slotsToSeal, slot)
|
||||||
|
|
||||||
|
local delayedTricks = player:getCardIds(Player.Judge)
|
||||||
|
if #delayedTricks > 0 then
|
||||||
|
table.insertTable(cardsToDrop, delayedTricks)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local subtype = Util.convertSubtypeAndEquipSlot(slot)
|
||||||
|
if #player:getAvailableEquipSlots(subtype) > 0 then
|
||||||
|
table.insert(slotsToSeal, slot)
|
||||||
|
|
||||||
|
local equipmentIndex = (slotsSealed[tostring(subtype)] or 0) + 1
|
||||||
|
slotsSealed[tostring(subtype)] = equipmentIndex
|
||||||
|
|
||||||
|
if equipmentIndex <= #player:getEquipments(subtype) then
|
||||||
|
table.insert(cardsToDrop, player:getEquipments(subtype)[equipmentIndex])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if next(slotsSealed) == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self:moveCards({
|
||||||
|
ids = cardsToDrop,
|
||||||
|
from = player.id,
|
||||||
|
toArea = Card.DiscardPile,
|
||||||
|
moveReason = fk.ReasonPutIntoDiscardPile,
|
||||||
|
})
|
||||||
|
|
||||||
|
table.insertTable(player.sealedSlots, slotsToSeal)
|
||||||
|
self:broadcastProperty(player, "sealedSlots")
|
||||||
|
end
|
||||||
|
|
||||||
return Room
|
return Room
|
||||||
|
|
|
@ -306,6 +306,10 @@ function ServerPlayer:marshal(player, observe)
|
||||||
if self.role_shown then
|
if self.role_shown then
|
||||||
room:notifyProperty(player, self, "role")
|
room:notifyProperty(player, self, "role")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if #self.sealedSlots > 0 then
|
||||||
|
room:notifyProperty(player, self, "sealedSlots")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ServerPlayer:reconnect()
|
function ServerPlayer:reconnect()
|
||||||
|
|
|
@ -51,7 +51,6 @@ local discardSkill = fk.CreateActiveSkill{
|
||||||
|
|
||||||
local chooseCardsSkill = fk.CreateActiveSkill{
|
local chooseCardsSkill = fk.CreateActiveSkill{
|
||||||
name = "choose_cards_skill",
|
name = "choose_cards_skill",
|
||||||
-- expand_pile = function(self) return self.expand_pile end,
|
|
||||||
card_filter = function(self, to_select, selected)
|
card_filter = function(self, to_select, selected)
|
||||||
if #selected >= self.num then
|
if #selected >= self.num then
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -648,7 +648,7 @@ extension:addCards({
|
||||||
local lightningSkill = fk.CreateActiveSkill{
|
local lightningSkill = fk.CreateActiveSkill{
|
||||||
name = "lightning_skill",
|
name = "lightning_skill",
|
||||||
can_use = function(self, player)
|
can_use = function(self, player)
|
||||||
return not Self:hasDelayedTrick("lightning")
|
return not (Self:hasDelayedTrick("lightning") or table.contains(player.sealedSlots, Player.JudgeSlot))
|
||||||
end,
|
end,
|
||||||
on_use = function(self, room, use)
|
on_use = function(self, room, use)
|
||||||
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
||||||
|
|
|
@ -293,6 +293,26 @@ local test_zhenggong = fk.CreateTriggerSkill{
|
||||||
player:gainAnExtraTurn()
|
player:gainAnExtraTurn()
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
local test_feichu = fk.CreateActiveSkill{
|
||||||
|
name = "test_feichu",
|
||||||
|
can_use = function(self, player)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
card_filter = function(self, card)
|
||||||
|
return false
|
||||||
|
end,
|
||||||
|
card_num = 0,
|
||||||
|
target_filter = function(self, to_select, selected)
|
||||||
|
return #selected < 1
|
||||||
|
end,
|
||||||
|
target_num = 1,
|
||||||
|
on_use = function(self, room, effect)
|
||||||
|
local from = room:getPlayerById(effect.from)
|
||||||
|
local eqipSlots = from:getAvailableEquipSlots()
|
||||||
|
table.insert(eqipSlots, Player.JudgeSlot)
|
||||||
|
room:abortPlayerArea(from, eqipSlots)
|
||||||
|
end,
|
||||||
|
}
|
||||||
local test2 = General(extension, "mouxusheng", "wu", 99, 99, General.Female)
|
local test2 = General(extension, "mouxusheng", "wu", 99, 99, General.Female)
|
||||||
test2.shield = 5
|
test2.shield = 5
|
||||||
test2:addSkill("rende")
|
test2:addSkill("rende")
|
||||||
|
@ -303,6 +323,7 @@ test2:addSkill(control)
|
||||||
test2:addSkill(damage_maker)
|
test2:addSkill(damage_maker)
|
||||||
test2:addSkill(change_hero)
|
test2:addSkill(change_hero)
|
||||||
test2:addSkill(test_zhenggong)
|
test2:addSkill(test_zhenggong)
|
||||||
|
test2:addSkill(test_feichu)
|
||||||
|
|
||||||
local shibing = General(extension, "blank_shibing", "qun", 5)
|
local shibing = General(extension, "blank_shibing", "qun", 5)
|
||||||
shibing.hidden = true
|
shibing.hidden = true
|
||||||
|
|
Loading…
Reference in New Issue