Heg (#262)
1. 扩容到12人 2. 修复fake技能 3. 国战UI 4. 选将耦合双势力和野心家 5. fake看破修复 6. 重连bug修复 7. 复原武将修复 8. 亮将修复体力上限 9. 修复拼点不可取消 --------- Co-authored-by: notify <notify-ctrl@qq.com>
|
@ -43,6 +43,7 @@ QtObject {
|
||||||
property bool serverEnableBot: true
|
property bool serverEnableBot: true
|
||||||
property int roomCapacity: 0
|
property int roomCapacity: 0
|
||||||
property int roomTimeout: 0
|
property int roomTimeout: 0
|
||||||
|
property bool heg: false
|
||||||
property bool enableFreeAssign: false
|
property bool enableFreeAssign: false
|
||||||
property bool observing: false
|
property bool observing: false
|
||||||
property bool replaying: false
|
property bool replaying: false
|
||||||
|
|
|
@ -34,7 +34,7 @@ Flickable {
|
||||||
SpinBox {
|
SpinBox {
|
||||||
id: playerNum
|
id: playerNum
|
||||||
from: 2
|
from: 2
|
||||||
to: 8
|
to: 12
|
||||||
value: config.preferedPlayerNum
|
value: config.preferedPlayerNum
|
||||||
|
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
|
|
|
@ -134,6 +134,7 @@ callbacks["EnterRoom"] = (jsonData) => {
|
||||||
config.roomTimeout = data[1] - 1;
|
config.roomTimeout = data[1] - 1;
|
||||||
const roomSettings = data[2];
|
const roomSettings = data[2];
|
||||||
config.enableFreeAssign = roomSettings.enableFreeAssign;
|
config.enableFreeAssign = roomSettings.enableFreeAssign;
|
||||||
|
config.heg = roomSettings.gameMode.includes('heg_mode');
|
||||||
mainStack.push(room);
|
mainStack.push(room);
|
||||||
mainWindow.busy = false;
|
mainWindow.busy = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,73 @@ const Card = {
|
||||||
Void : 8
|
Void : 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function arrangeManyPhotos() {
|
||||||
|
/* Layout of photos:
|
||||||
|
* +----------------+
|
||||||
|
* | -2 ... 2 |
|
||||||
|
* | -1 1 |
|
||||||
|
* | 0 |
|
||||||
|
* +----------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
const photoBaseWidth = 175;
|
||||||
|
const photoMaxWidth = 175 * 0.75;
|
||||||
|
const verticalSpacing = 32;
|
||||||
|
// Padding is negative, because photos are scaled.
|
||||||
|
const roomAreaPadding = -16;
|
||||||
|
|
||||||
|
let horizontalSpacing = 8;
|
||||||
|
let photoWidth = (roomArea.width - horizontalSpacing * playerNum) / (playerNum - 1);
|
||||||
|
let photoScale = 0.75;
|
||||||
|
if (photoWidth > photoMaxWidth) {
|
||||||
|
photoWidth = photoMaxWidth;
|
||||||
|
horizontalSpacing = (roomArea.width - photoWidth * (playerNum - 1)) / playerNum;
|
||||||
|
} else {
|
||||||
|
photoScale = photoWidth / photoBaseWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const horizontalPadding = (photoWidth - photoBaseWidth) / 2;
|
||||||
|
const startX = horizontalPadding + horizontalSpacing;
|
||||||
|
const padding = photoWidth + horizontalSpacing;
|
||||||
|
let regions = [
|
||||||
|
{
|
||||||
|
x: startX + padding * (playerNum - 2),
|
||||||
|
y: roomScene.height - 220,
|
||||||
|
scale: photoScale
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < playerNum - 1; i++) {
|
||||||
|
regions.push({
|
||||||
|
x: startX + padding * (playerNum - 2 - i),
|
||||||
|
y: roomAreaPadding,
|
||||||
|
scale: photoScale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
regions[1].y += verticalSpacing * 3;
|
||||||
|
regions[regions.length - 1].y += verticalSpacing * 3;
|
||||||
|
regions[2].y += verticalSpacing;
|
||||||
|
regions[regions.length - 2].y += verticalSpacing;
|
||||||
|
|
||||||
|
let item, region;
|
||||||
|
|
||||||
|
for (i = 0; i < playerNum; i++) {
|
||||||
|
item = photos.itemAt(i);
|
||||||
|
if (!item)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
region = regions[photoModel.get(i).index];
|
||||||
|
item.x = region.x;
|
||||||
|
item.y = region.y;
|
||||||
|
item.scale = region.scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function arrangePhotos() {
|
function arrangePhotos() {
|
||||||
|
if (playerNum > 8) {
|
||||||
|
return arrangeManyPhotos();
|
||||||
|
}
|
||||||
|
|
||||||
/* Layout of photos:
|
/* Layout of photos:
|
||||||
* +---------------+
|
* +---------------+
|
||||||
* | 6 5 4 3 2 |
|
* | 6 5 4 3 2 |
|
||||||
|
|
|
@ -4,15 +4,16 @@ import QtQuick
|
||||||
import Fk
|
import Fk
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
source: SkinBank.MAGATAMA_DIR + "0"
|
source: SkinBank.MAGATAMA_DIR + "0" + (config.heg ? '-heg' : '')
|
||||||
state: "3"
|
state: "3"
|
||||||
|
height: 19; fillMode: Image.PreserveAspectFit
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "3"
|
name: "3"
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: main
|
target: main
|
||||||
source: SkinBank.MAGATAMA_DIR + "3"
|
source: SkinBank.MAGATAMA_DIR + "3" + (config.heg ? '-heg' : '')
|
||||||
opacity: 1
|
opacity: 1
|
||||||
scale: 1
|
scale: 1
|
||||||
}
|
}
|
||||||
|
@ -21,7 +22,7 @@ Image {
|
||||||
name: "2"
|
name: "2"
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: main
|
target: main
|
||||||
source: SkinBank.MAGATAMA_DIR + "2"
|
source: SkinBank.MAGATAMA_DIR + "2" + (config.heg ? '-heg' : '')
|
||||||
opacity: 1
|
opacity: 1
|
||||||
scale: 1
|
scale: 1
|
||||||
}
|
}
|
||||||
|
@ -30,7 +31,7 @@ Image {
|
||||||
name: "1"
|
name: "1"
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: main
|
target: main
|
||||||
source: SkinBank.MAGATAMA_DIR + "1"
|
source: SkinBank.MAGATAMA_DIR + "1" + (config.heg ? '-heg' : '')
|
||||||
opacity: 1
|
opacity: 1
|
||||||
scale: 1
|
scale: 1
|
||||||
}
|
}
|
||||||
|
@ -39,7 +40,7 @@ Image {
|
||||||
name: "0"
|
name: "0"
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: main
|
target: main
|
||||||
source: SkinBank.MAGATAMA_DIR + "0"
|
source: SkinBank.MAGATAMA_DIR + "0" + (config.heg ? '-heg' : '')
|
||||||
opacity: 0
|
opacity: 0
|
||||||
scale: 4
|
scale: 4
|
||||||
}
|
}
|
||||||
|
@ -55,5 +56,6 @@ Image {
|
||||||
Image {
|
Image {
|
||||||
id: main
|
id: main
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
height: 19; fillMode: Image.PreserveAspectFit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,43 @@ GraphicsBox {
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
主副将的主势力和副势力至少有一个相同;
|
||||||
|
副将不可野 主将可野
|
||||||
|
*/
|
||||||
|
function isHegPair(gcard1, gcard2) {
|
||||||
|
if (!gcard1 || gcard1 === gcard2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gcard2.kingdom == "wild") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gcard1.kingdom == "wild") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const k1 = gcard1.kingdom;
|
||||||
|
const k2 = gcard2.kingdom;
|
||||||
|
const sub1 = gcard1.subkingdom;
|
||||||
|
const sub2 = gcard2.subkingdom;
|
||||||
|
|
||||||
|
if (k1 == k2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub1 && (sub1 == k2 || sub1 == sub2)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub2 && sub2 == k1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function updatePosition()
|
function updatePosition()
|
||||||
{
|
{
|
||||||
choices = [];
|
choices = [];
|
||||||
|
@ -195,7 +232,7 @@ GraphicsBox {
|
||||||
|
|
||||||
for (i = 0; i < generalCardList.count; i++) {
|
for (i = 0; i < generalCardList.count; i++) {
|
||||||
item = generalCardList.itemAt(i);
|
item = generalCardList.itemAt(i);
|
||||||
item.selectable = needSameKingdom ? !(selectedItem[0] && (selectedItem[0].kingdom !== item.kingdom)) : true;
|
item.selectable = needSameKingdom ? isHegPair(selectedItem[0], item) : true;
|
||||||
if (selectedItem.indexOf(item) != -1)
|
if (selectedItem.indexOf(item) != -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,16 @@ CardItem {
|
||||||
card.source: SkinBank.getGeneralPicture(name)
|
card.source: SkinBank.getGeneralPicture(name)
|
||||||
glow.color: "white" //Engine.kingdomColor[kingdom]
|
glow.color: "white" //Engine.kingdomColor[kingdom]
|
||||||
|
|
||||||
|
// FIXME: 藕!!
|
||||||
|
property bool heg: name.startsWith('hs__') || name.startsWith('ld__') || name.includes('heg__')
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
source: SkinBank.GENERALCARD_DIR + "border"
|
source: SkinBank.GENERALCARD_DIR + "border"
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
scale: subkingdom ? 0.6 : 1
|
scale: subkingdom ? 0.6 : 1
|
||||||
|
width: 34; fillMode: Image.PreserveAspectFit
|
||||||
transformOrigin: Item.TopLeft
|
transformOrigin: Item.TopLeft
|
||||||
source: SkinBank.getGeneralCardDir(kingdom) + kingdom
|
source: SkinBank.getGeneralCardDir(kingdom) + kingdom
|
||||||
visible: detailed
|
visible: detailed
|
||||||
|
@ -46,6 +50,7 @@ CardItem {
|
||||||
Image {
|
Image {
|
||||||
scale: 0.6; x: 9; y: 12
|
scale: 0.6; x: 9; y: 12
|
||||||
transformOrigin: Item.TopLeft
|
transformOrigin: Item.TopLeft
|
||||||
|
width: 34; fillMode: Image.PreserveAspectFit
|
||||||
source: subkingdom ? SkinBank.getGeneralCardDir(subkingdom) + subkingdom : ""
|
source: subkingdom ? SkinBank.getGeneralCardDir(subkingdom) + subkingdom : ""
|
||||||
visible: detailed
|
visible: detailed
|
||||||
}
|
}
|
||||||
|
@ -54,10 +59,10 @@ CardItem {
|
||||||
x: 34
|
x: 34
|
||||||
y: 4
|
y: 4
|
||||||
spacing: 1
|
spacing: 1
|
||||||
visible: detailed
|
visible: detailed && !heg
|
||||||
Repeater {
|
Repeater {
|
||||||
id: hpRepeater
|
id: hpRepeater
|
||||||
model: (hp > 5 || hp !== maxHp) ? 1 : hp
|
model: (!heg) ? ((hp > 5 || hp !== maxHp) ? 1 : hp) : 0
|
||||||
Item {
|
Item {
|
||||||
width: childrenRect.width
|
width: childrenRect.width
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
@ -97,6 +102,43 @@ CardItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
x: 34
|
||||||
|
y: 3
|
||||||
|
spacing: 0
|
||||||
|
visible: detailed && heg
|
||||||
|
Repeater {
|
||||||
|
id: hegHpRepeater
|
||||||
|
model: heg ? ((hp > 7 || hp !== maxHp) ? 1 : Math.ceil(hp / 2)) : 0
|
||||||
|
Item {
|
||||||
|
width: childrenRect.width
|
||||||
|
height: childrenRect.height
|
||||||
|
Image {
|
||||||
|
height: 12; fillMode: Image.PreserveAspectFit
|
||||||
|
source: SkinBank.getGeneralCardDir(kingdom) + kingdom + "-magatama-l"
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
x: 4.4
|
||||||
|
opacity: (index + 1) * 2 <= hp ? 1 : 0
|
||||||
|
height: 12; fillMode: Image.PreserveAspectFit
|
||||||
|
source: {
|
||||||
|
const k = subkingdom ? subkingdom : kingdom;
|
||||||
|
SkinBank.getGeneralCardDir(k) + k + "-magatama-r"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
visible: hp > 7 || hp !== maxHp
|
||||||
|
text: hp === maxHp ? ("x" + hp / 2) : (" " + hp / 2 + "/" + maxHp / 2)
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 14
|
||||||
|
style: Text.Outline
|
||||||
|
y: -4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Shield {
|
Shield {
|
||||||
visible: shieldNum > 0 && detailed
|
visible: shieldNum > 0 && detailed
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
@ -326,7 +326,7 @@ Item {
|
||||||
Image {
|
Image {
|
||||||
id: turnedOver
|
id: turnedOver
|
||||||
visible: !root.faceup
|
visible: !root.faceup
|
||||||
source: SkinBank.PHOTO_DIR + "faceturned"
|
source: SkinBank.PHOTO_DIR + "faceturned" + (config.heg ? '-heg' : '')
|
||||||
x: 29; y: 5
|
x: 29; y: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ Item {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: -32
|
anchors.bottomMargin: -32
|
||||||
property var seatChr: ["一", "二", "三", "四", "五", "六", "七", "八"]
|
property var seatChr: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"]
|
||||||
font.family: fontLi2.name
|
font.family: fontLi2.name
|
||||||
font.pixelSize: 32
|
font.pixelSize: 32
|
||||||
text: seatChr[seatNumber - 1]
|
text: seatChr[seatNumber - 1]
|
||||||
|
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 8.0 KiB |
BIN
image/card/general/qun-magatama-l.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/qun-magatama-r.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/shu-magatama-l.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/shu-magatama-r.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wei-magatama-l.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wei-magatama-r.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wild-magatama-l.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wild-magatama-r.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wild.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
image/card/general/wu-magatama-l.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/card/general/wu-magatama-r.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
image/photo/faceturned-heg.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
image/photo/magatama/0-heg.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
image/photo/magatama/1-heg.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
image/photo/magatama/2-heg.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
image/photo/magatama/3-heg.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
|
@ -99,7 +99,7 @@ Fk:loadTranslationTable({
|
||||||
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
||||||
|
|
||||||
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
||||||
["#askForPindian"] = "请选择一张手牌作为拼点牌",
|
["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌",
|
||||||
|
|
||||||
-- ["Trust"] = "托管",
|
-- ["Trust"] = "托管",
|
||||||
-- ["Sort Cards"] = "牌序",
|
-- ["Sort Cards"] = "牌序",
|
||||||
|
|
|
@ -235,7 +235,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
||||||
|
|
||||||
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
||||||
["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张",
|
["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张",
|
||||||
["#askForPindian"] = "请选择一张手牌作为拼点牌",
|
["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌",
|
||||||
["#StartPindianReason"] = "%from 由于 %arg 而发起拼点",
|
["#StartPindianReason"] = "%from 由于 %arg 而发起拼点",
|
||||||
["#ShowPindianCard"] = "%from 的拼点牌是 %card",
|
["#ShowPindianCard"] = "%from 的拼点牌是 %card",
|
||||||
["#ShowPindianResult"] = "%from 在 %from 和 %to 之间的拼点中 %arg",
|
["#ShowPindianResult"] = "%from 在 %from 和 %to 之间的拼点中 %arg",
|
||||||
|
@ -255,6 +255,10 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
||||||
["seat#6"] = "六号位",
|
["seat#6"] = "六号位",
|
||||||
["seat#7"] = "七号位",
|
["seat#7"] = "七号位",
|
||||||
["seat#8"] = "八号位",
|
["seat#8"] = "八号位",
|
||||||
|
["seat#9"] = "九号位",
|
||||||
|
["seat#10"] = "十号位",
|
||||||
|
["seat#11"] = "十一号位",
|
||||||
|
["seat#12"] = "十二号位",
|
||||||
["@ControledBy"] = "控制者",
|
["@ControledBy"] = "控制者",
|
||||||
|
|
||||||
["Menu"] = "菜单",
|
["Menu"] = "菜单",
|
||||||
|
|
|
@ -21,7 +21,7 @@ local GameMode = class("GameMode")
|
||||||
function GameMode:initialize(name, min, max)
|
function GameMode:initialize(name, min, max)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.minPlayer = math.max(min, 2)
|
self.minPlayer = math.max(min, 2)
|
||||||
self.maxPlayer = math.min(max, 8)
|
self.maxPlayer = math.min(max, 12)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param victim ServerPlayer @ 死者
|
---@param victim ServerPlayer @ 死者
|
||||||
|
|
|
@ -62,7 +62,8 @@ function TriggerSkill:doCost(event, target, player, data)
|
||||||
|
|
||||||
local room = player.room
|
local room = player.room
|
||||||
-- 对于那种cost直接返回true的锁定技,如果是预亮技,那么还是询问一下好
|
-- 对于那种cost直接返回true的锁定技,如果是预亮技,那么还是询问一下好
|
||||||
if ret and player:isFakeSkill(self) and end_time - start_time < 10000 then
|
if ret and player:isFakeSkill(self) and end_time - start_time < 10000 and
|
||||||
|
(self.main_skill and self.main_skill or self).visible then
|
||||||
ret = room:askForSkillInvoke(player, self.name)
|
ret = room:askForSkillInvoke(player, self.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@ end
|
||||||
|
|
||||||
---@param player Player
|
---@param player Player
|
||||||
function ViewAsSkill:enabledAtPlay(player)
|
function ViewAsSkill:enabledAtPlay(player)
|
||||||
return player:hasSkill(self)
|
return self:isEffectable(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param player Player
|
---@param player Player
|
||||||
function ViewAsSkill:enabledAtResponse(player, cardResponsing)
|
function ViewAsSkill:enabledAtResponse(player, cardResponsing)
|
||||||
return player:hasSkill(self)
|
return self:isEffectable(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param player Player
|
---@param player Player
|
||||||
|
|
|
@ -21,8 +21,8 @@ GameEvent.functions[GameEvent.Pindian] = function(self)
|
||||||
pattern = ".",
|
pattern = ".",
|
||||||
reason = pindianData.reason,
|
reason = pindianData.reason,
|
||||||
}
|
}
|
||||||
local prompt = "#askForPindian"
|
local prompt = "#askForPindian:::" .. pindianData.reason
|
||||||
local data = { "choose_cards_skill", prompt, true, json.encode(extraData) }
|
local data = { "choose_cards_skill", prompt, false, json.encode(extraData) }
|
||||||
|
|
||||||
local targets = {}
|
local targets = {}
|
||||||
local moveInfos = {}
|
local moveInfos = {}
|
||||||
|
|
|
@ -36,6 +36,20 @@ local function tellRoomToObserver(self, player)
|
||||||
player:doNotify("UpdateDrawPile", #self.draw_pile)
|
player:doNotify("UpdateDrawPile", #self.draw_pile)
|
||||||
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
|
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
|
||||||
|
|
||||||
|
-- send printed_cards
|
||||||
|
for i = -2, -math.huge, -1 do
|
||||||
|
local c = Fk.printed_cards[i]
|
||||||
|
if not c then break end
|
||||||
|
player:doNotify("PrintCard", json.encode{ c.name, c.suit, c.number })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send card marks
|
||||||
|
for id, marks in pairs(room.card_marks) do
|
||||||
|
for k, v in pairs(marks) do
|
||||||
|
player:doNotify("SetCardMark", json.encode{ id, k, v })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
table.insert(self.observers, {observee.id, player, player:getId()})
|
table.insert(self.observers, {observee.id, player, player:getId()})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2480,7 +2480,7 @@ function Room:handleCardEffect(event, cardEffectEvent)
|
||||||
end
|
end
|
||||||
if not table.contains(players, p) then
|
if not table.contains(players, p) then
|
||||||
Self = p -- for enabledAtResponse
|
Self = p -- for enabledAtResponse
|
||||||
for _, s in ipairs(p.player_skills) do
|
for _, s in ipairs(table.connect(p.player_skills, p._fake_skills)) do
|
||||||
if
|
if
|
||||||
s.pattern and
|
s.pattern and
|
||||||
Exppattern:Parse("nullification"):matchExp(s.pattern) and
|
Exppattern:Parse("nullification"):matchExp(s.pattern) and
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
---@field public phase_index integer
|
---@field public phase_index integer
|
||||||
---@field public role_shown boolean
|
---@field public role_shown boolean
|
||||||
---@field private _fake_skills Skill[]
|
---@field private _fake_skills Skill[]
|
||||||
|
---@field private _manually_fake_skills Skill[]
|
||||||
---@field public prelighted_skills Skill[]
|
---@field public prelighted_skills Skill[]
|
||||||
---@field private _timewaste_count integer
|
---@field private _timewaste_count integer
|
||||||
---@field public ai AI
|
---@field public ai AI
|
||||||
|
@ -39,6 +40,7 @@ function ServerPlayer:initialize(_self)
|
||||||
self.skipped_phases = {}
|
self.skipped_phases = {}
|
||||||
|
|
||||||
self._fake_skills = {}
|
self._fake_skills = {}
|
||||||
|
self._manually_fake_skills = {}
|
||||||
self.prelighted_skills = {}
|
self.prelighted_skills = {}
|
||||||
self._prelighted_skills = {}
|
self._prelighted_skills = {}
|
||||||
|
|
||||||
|
@ -353,6 +355,28 @@ function ServerPlayer:reconnect()
|
||||||
self:doNotify("UpdateDrawPile", #room.draw_pile)
|
self:doNotify("UpdateDrawPile", #room.draw_pile)
|
||||||
self:doNotify("UpdateRoundNum", room:getTag("RoundCount") or 0)
|
self:doNotify("UpdateRoundNum", room:getTag("RoundCount") or 0)
|
||||||
|
|
||||||
|
-- send printed_cards
|
||||||
|
for i = -2, -math.huge, -1 do
|
||||||
|
local c = Fk.printed_cards[i]
|
||||||
|
if not c then break end
|
||||||
|
self:doNotify("PrintCard", json.encode{ c.name, c.suit, c.number })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send card marks
|
||||||
|
for id, marks in pairs(room.card_marks) do
|
||||||
|
for k, v in pairs(marks) do
|
||||||
|
self:doNotify("SetCardMark", json.encode{ id, k, v })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send fake skills
|
||||||
|
for _, s in ipairs(self._manually_fake_skills) do
|
||||||
|
self:doNotify("AddSkill", json.encode{ self.id, s.name, true })
|
||||||
|
if table.contains(self.prelighted_skills, s) then
|
||||||
|
self:doNotify("PrelightSkill", json.encode{ s.name, true })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
room:broadcastProperty(self, "state")
|
room:broadcastProperty(self, "state")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -702,11 +726,12 @@ function ServerPlayer:reset()
|
||||||
from = self.id,
|
from = self.id,
|
||||||
arg = "reset-general"
|
arg = "reset-general"
|
||||||
}
|
}
|
||||||
self:setChainState(false)
|
if self.chained then self:setChainState(false) end
|
||||||
if not self.faceup then self:turnOver() end
|
if not self.faceup then self:turnOver() end
|
||||||
end
|
end
|
||||||
|
|
||||||
--@param from ServerPlayer
|
--- 进行拼点。
|
||||||
|
---@param from ServerPlayer
|
||||||
---@param tos ServerPlayer[]
|
---@param tos ServerPlayer[]
|
||||||
---@param skillName string
|
---@param skillName string
|
||||||
---@param initialCard Card|nil
|
---@param initialCard Card|nil
|
||||||
|
@ -740,6 +765,8 @@ function ServerPlayer:addFakeSkill(skill)
|
||||||
end
|
end
|
||||||
if table.contains(self._fake_skills, skill) then return end
|
if table.contains(self._fake_skills, skill) then return end
|
||||||
|
|
||||||
|
table.insertIfNeed(self._manually_fake_skills, skill)
|
||||||
|
|
||||||
table.insert(self._fake_skills, skill)
|
table.insert(self._fake_skills, skill)
|
||||||
for _, s in ipairs(skill.related_skills) do
|
for _, s in ipairs(skill.related_skills) do
|
||||||
-- if s.main_skill == skill then -- TODO: need more detailed
|
-- if s.main_skill == skill then -- TODO: need more detailed
|
||||||
|
@ -759,6 +786,8 @@ function ServerPlayer:loseFakeSkill(skill)
|
||||||
end
|
end
|
||||||
if not table.contains(self._fake_skills, skill) then return end
|
if not table.contains(self._fake_skills, skill) then return end
|
||||||
|
|
||||||
|
table.removeOne(self._manually_fake_skills, skill)
|
||||||
|
|
||||||
table.removeOne(self._fake_skills, skill)
|
table.removeOne(self._fake_skills, skill)
|
||||||
for _, s in ipairs(skill.related_skills) do
|
for _, s in ipairs(skill.related_skills) do
|
||||||
table.removeOne(self._fake_skills, s)
|
table.removeOne(self._fake_skills, s)
|
||||||
|
@ -839,7 +868,7 @@ function ServerPlayer:revealGeneral(isDeputy, no_trigger)
|
||||||
end
|
end
|
||||||
|
|
||||||
local oldKingdom = self.kingdom
|
local oldKingdom = self.kingdom
|
||||||
room:changeHero(self, generalName, false, isDeputy)
|
room:changeHero(self, generalName, false, isDeputy, false, false)
|
||||||
if oldKingdom ~= "wild" then
|
if oldKingdom ~= "wild" then
|
||||||
local kingdom = general.kingdom
|
local kingdom = general.kingdom
|
||||||
self.kingdom = kingdom
|
self.kingdom = kingdom
|
||||||
|
|