mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 11:42:45 +08:00
Heg (#254)
1. 修复木马、真名无懈可击 2. 增加亮将、暗将时机 3. 增加武将珠联璧合关系 4. 增加武将选择框禁止替换 5. 增加变换武将不改变体力上限 6. 增加亮将禁止、不计入距离和座次的MarkEnum,相应的player函数 7. 状态技默认锁定技 8. 修复拼点 9. 增加出牌阶段亮将技能 10. 增加暗置武将函数 --------- Signed-off-by: Mechanel <nyutanislavsky@qq.com>
This commit is contained in:
parent
6dd1eded9a
commit
d0913e42ce
|
@ -40,6 +40,14 @@ Flickable {
|
|||
extra_data.generals.forEach((g) => {
|
||||
const data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [g]));
|
||||
skillDesc.append(Backend.translate(data.kingdom) + " " + Backend.translate(g) + " " + data.hp + "/" + data.maxHp);
|
||||
if (data.companions.length > 0){
|
||||
let ret = '';
|
||||
ret += "<font color=\"slategrey\"><b>" + Backend.translate("Companions") + "</b>: ";
|
||||
data.companions.forEach(t => {
|
||||
ret += Backend.translate(t) + ' '
|
||||
});
|
||||
skillDesc.append(ret)
|
||||
}
|
||||
data.skill.forEach(t => {
|
||||
skillDesc.append("<b>" + Backend.translate(t.name) + "</b>: " + t.description)
|
||||
});
|
||||
|
|
|
@ -188,6 +188,16 @@ Item {
|
|||
const data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [general]));
|
||||
generalText.clear();
|
||||
audioModel.clear();
|
||||
|
||||
if (data.companions.length > 0){
|
||||
let ret = '';
|
||||
ret += "<font color=\"slategrey\"><b>" + Backend.translate("Companions") + "</b>: ";
|
||||
data.companions.forEach(t => {
|
||||
ret += Backend.translate(t) + ' '
|
||||
});
|
||||
generalText.append(ret)
|
||||
}
|
||||
|
||||
data.skill.forEach(t => {
|
||||
generalText.append("<b>" + Backend.translate(t.name) +
|
||||
"</b>: " + t.description);
|
||||
|
|
|
@ -796,7 +796,8 @@ callbacks["AskForGeneral"] = (jsonData) => {
|
|||
const data = JSON.parse(jsonData);
|
||||
const generals = data[0];
|
||||
const n = data[1];
|
||||
const heg = data[2];
|
||||
const convert = data[2];
|
||||
const heg = data[3];
|
||||
roomScene.setPrompt(Backend.translate("#AskForGeneral"), true);
|
||||
roomScene.state = "replying";
|
||||
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChooseGeneralBox.qml");
|
||||
|
@ -805,6 +806,7 @@ callbacks["AskForGeneral"] = (jsonData) => {
|
|||
replyToServer(JSON.stringify(box.choices));
|
||||
});
|
||||
box.choiceNum = n;
|
||||
box.convertDisabled = !!convert;
|
||||
box.needSameKingdom = !!heg;
|
||||
for (let i = 0; i < generals.length; i++)
|
||||
box.generalList.append({ "name": generals[i] });
|
||||
|
|
|
@ -11,6 +11,7 @@ GraphicsBox {
|
|||
property var choices: []
|
||||
property var selectedItem: []
|
||||
property bool loaded: false
|
||||
property bool convertDisabled: false
|
||||
property bool needSameKingdom: false
|
||||
|
||||
ListModel {
|
||||
|
@ -91,6 +92,7 @@ GraphicsBox {
|
|||
|
||||
MetroButton {
|
||||
id: convertBtn
|
||||
visible: !convertDisabled
|
||||
text: Backend.translate("Same General Convert")
|
||||
onClicked: roomScene.startCheat("SameConvert", { cards: generalList });
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ function GetGeneralDetail(name)
|
|||
maxHp = general.maxHp,
|
||||
gender = general.gender,
|
||||
skill = {},
|
||||
related_skill = {}
|
||||
related_skill = {},
|
||||
companions = general.companions
|
||||
}
|
||||
for _, s in ipairs(general.skills) do
|
||||
table.insert(ret.skill, {
|
||||
|
@ -59,6 +60,11 @@ function GetGeneralDetail(name)
|
|||
description = Fk:getDescription(s)
|
||||
})
|
||||
end
|
||||
for _, g in pairs(Fk.generals) do
|
||||
if table.contains(g.companions, general.trueName) then
|
||||
table.insertIfNeed(ret.companions, g.trueName)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
end
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
-- ["Quit"] = "退出",
|
||||
["BanGeneral"] = "禁将",
|
||||
["ResumeGeneral"] = "解禁",
|
||||
["Companions"] = "珠联璧合",
|
||||
["Death audio"] = "阵亡",
|
||||
|
||||
["$WelcomeToLobby"] = "欢迎进入新月杀游戏大厅!",
|
||||
|
@ -436,6 +437,9 @@ Fk:loadTranslationTable{
|
|||
["#KillPlayerWithNoKiller"] = "%from [%arg] 阵亡,无伤害来源",
|
||||
["#Revive"] = "%from 竟然复活了",
|
||||
|
||||
-- change hero
|
||||
["#ChangeHero"] = "%from 的 %arg3 %arg 变更为 %arg2",
|
||||
|
||||
-- misc
|
||||
["#GuanxingResult"] = "%from 的观星结果为 %arg 上 %arg2 下",
|
||||
["#ChainStateChange"] = "%from %arg 了武将牌",
|
||||
|
|
|
@ -14,14 +14,17 @@
|
|||
---@field public subkingdom string @ 武将副势力
|
||||
---@field public hp integer @ 武将初始体力
|
||||
---@field public maxHp integer @ 武将初始最大体力
|
||||
---@field public mainMaxHpAdjustedValue integer @ 主将体力上限调整
|
||||
---@field public deputyMaxHpAdjustedValue integer @ 副将体力上限调整
|
||||
---@field public shield integer @ 初始护甲
|
||||
---@field public gender Gender @ 武将性别
|
||||
---@field public skills Skill[] @ 武将技能
|
||||
---@field public other_skills string[] @ 武将身上属于其他武将的技能,通过字符串调用
|
||||
---@field public related_skills Skill[] @ 武将相关的不属于其他武将的技能,例如邓艾的急袭
|
||||
---@field public related_other_skills string [] @ 武将相关的属于其他武将的技能,例如孙策的英姿
|
||||
---@field public hidden boolean
|
||||
---@field public total_hidden boolean
|
||||
---@field public companions string [] @ 有珠联璧合关系的武将
|
||||
---@field public hidden boolean @ 不在选将框里出现,可以点将,可以在武将一览里查询到
|
||||
---@field public total_hidden boolean @ 完全隐藏
|
||||
General = class("General")
|
||||
|
||||
---@alias Gender integer
|
||||
|
@ -48,6 +51,8 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender)
|
|||
self.hp = hp
|
||||
self.maxHp = maxHp or hp
|
||||
self.gender = gender or General.Male
|
||||
self.mainMaxHpAdjustedValue = 0
|
||||
self.deputyMaxHpAdjustedValue = 0
|
||||
self.shield = 0
|
||||
self.subkingdom = nil
|
||||
|
||||
|
@ -56,6 +61,8 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender)
|
|||
self.related_skills = {} -- skills related to this general, but not first added to it, e.g. "jixi" of dengai
|
||||
self.related_other_skills = {} -- skills related to this general and belong to other generals, e.g. "yingzi" of sunce
|
||||
|
||||
self.companions = {}
|
||||
|
||||
package:addGeneral(self)
|
||||
end
|
||||
|
||||
|
@ -96,4 +103,14 @@ function General:getSkillNameList(include_lord)
|
|||
return ret
|
||||
end
|
||||
|
||||
--- 为武将增加珠联璧合关系武将(1个或多个),只需写trueName。
|
||||
---@param name string[] @ 武将真名(表)
|
||||
function General:addCompanions(name)
|
||||
if type(name) == "table" then
|
||||
table.insertTable(self.companions, name)
|
||||
elseif type(name) == "string" then
|
||||
table.insert(self.companions, name)
|
||||
end
|
||||
end
|
||||
|
||||
return General
|
||||
|
|
|
@ -140,9 +140,9 @@ function Player:getGeneralMaxHp()
|
|||
local deputy = Fk.generals[type(self:getMark("__heg_deputy")) == "string" and self:getMark("__heg_deputy") or self.deputy]
|
||||
|
||||
if not deputy then
|
||||
return general.maxHp
|
||||
return general.maxHp + general.mainMaxHpAdjustedValue
|
||||
else
|
||||
return (general.maxHp + deputy.maxHp) // 2
|
||||
return (general.maxHp + general.mainMaxHpAdjustedValue + deputy.maxHp + deputy.deputyMaxHpAdjustedValue) // 2
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -459,6 +459,13 @@ function Player:getAttackRange()
|
|||
return math.max(baseAttackRange, 0)
|
||||
end
|
||||
|
||||
--- 获取角色是否被移除。
|
||||
function Player:isRemoved()
|
||||
return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s)
|
||||
return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0
|
||||
end)
|
||||
end
|
||||
|
||||
--- 修改玩家与其他角色的固定距离。
|
||||
---@param other Player @ 其他玩家
|
||||
---@param num integer @ 距离数
|
||||
|
@ -484,16 +491,19 @@ function Player:distanceTo(other, mode, ignore_dead)
|
|||
assert(other:isInstanceOf(Player))
|
||||
mode = mode or "both"
|
||||
if other == self then return 0 end
|
||||
if ignore_dead and other.dead then
|
||||
if not ignore_dead and other.dead then
|
||||
print(other.name .. " is dead!")
|
||||
return -1
|
||||
end
|
||||
if self:isRemoved() or other:isRemoved() then
|
||||
return -1
|
||||
end
|
||||
local right = 0
|
||||
local temp = self
|
||||
local try_time = 10
|
||||
for _ = 0, try_time do
|
||||
if temp == other then break end
|
||||
if ignore_dead or not temp.dead then
|
||||
if (ignore_dead or not temp.dead) and not temp:isRemoved() then
|
||||
right = right + 1
|
||||
end
|
||||
temp = temp.next
|
||||
|
@ -501,7 +511,7 @@ function Player:distanceTo(other, mode, ignore_dead)
|
|||
if temp ~= other then
|
||||
print("Distance malfunction: start and end does not matched.")
|
||||
end
|
||||
local left = #(ignore_dead and Fk:currentRoom().players or Fk:currentRoom().alive_players) - right
|
||||
local left = #(ignore_dead and Fk:currentRoom().players or Fk:currentRoom().alive_players) - right - #table.filter(Fk:currentRoom().alive_players, function(p) return p:isRemoved() end)
|
||||
local ret = 0
|
||||
if mode == "left" then
|
||||
ret = left
|
||||
|
@ -534,7 +544,7 @@ end
|
|||
---@param fixLimit number|null @ 卡牌距离限制增加专用
|
||||
function Player:inMyAttackRange(other, fixLimit)
|
||||
assert(other:isInstanceOf(Player))
|
||||
if self == other or (other and other.dead) then
|
||||
if self == other or (other and (other.dead or other:isRemoved())) or self:isRemoved() then
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -551,13 +561,20 @@ function Player:inMyAttackRange(other, fixLimit)
|
|||
return self:distanceTo(other) <= (baseAttackRange + fixLimit)
|
||||
end
|
||||
|
||||
function Player:getNextAlive()
|
||||
if Fk:currentRoom().alive_players == 0 then
|
||||
--- 获取下家。
|
||||
---@param ignoreRemoved bool @ 忽略被移除
|
||||
---@return ServerPlayer
|
||||
function Player:getNextAlive(ignoreRemoved)
|
||||
if #Fk:currentRoom().alive_players == 0 then
|
||||
return self
|
||||
end
|
||||
local doNotIgnore = not ignoreRemoved
|
||||
if doNotIgnore and table.every(Fk:currentRoom().alive_players, function(p) return p:isRemoved() end) then
|
||||
return self
|
||||
end
|
||||
|
||||
local ret = self.next
|
||||
while ret.dead do
|
||||
while ret.dead or (doNotIgnore and ret:isRemoved()) do
|
||||
ret = ret.next
|
||||
end
|
||||
return ret
|
||||
|
@ -884,6 +901,22 @@ function Player:prohibitDiscard(card)
|
|||
return false
|
||||
end
|
||||
|
||||
--- 确认角色是否被禁止亮将。
|
||||
function Player:prohibitReveal(isDeputy)
|
||||
local place = isDeputy and "d" or "m"
|
||||
if type(self:getMark(MarkEnum.RevealProhibited)) == "table" and table.contains(self:getMark(MarkEnum.RevealProhibited), place) then
|
||||
return true
|
||||
end
|
||||
for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
||||
return self:getMark(MarkEnum.RevealProhibited .. s)
|
||||
end)) do
|
||||
if type(m) == "table" and table.contains(m, place) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--转换技状态阳
|
||||
fk.SwitchYang = 0
|
||||
--转换技状态阴
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
---@field public anim_type string @ 技能类型定义
|
||||
---@field public related_skills Skill[] @ 和本技能相关的其他技能,有时候一个技能实际上是通过好几个技能拼接而实现的。
|
||||
---@field public attached_equip string @ 属于什么装备的技能?
|
||||
---@field public relate_to_place string @ 主将技/副将技
|
||||
---@field public switchSkillName string @ 转换技名字
|
||||
local Skill = class("Skill")
|
||||
|
||||
|
@ -56,6 +57,7 @@ function Skill:initialize(name, frequency)
|
|||
end
|
||||
|
||||
self.attached_equip = nil
|
||||
self.relate_to_place = nil
|
||||
end
|
||||
|
||||
function Skill:__index(k)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
local StatusSkill = Skill:subclass("StatusSkill")
|
||||
|
||||
function StatusSkill:initialize(name, frequency)
|
||||
frequency = frequency or Skill.NotFrequent
|
||||
frequency = frequency or Skill.Compulsory
|
||||
Skill.initialize(self, name, frequency)
|
||||
self.global = false
|
||||
end
|
||||
|
|
|
@ -38,6 +38,11 @@ local function readCommonSpecToSkill(skill, spec)
|
|||
assert(type(spec.switch_skill_name) == "string")
|
||||
skill.switchSkillName = spec.switch_skill_name
|
||||
end
|
||||
|
||||
if spec.relate_to_place then
|
||||
assert(type(spec.relate_to_place) == "string")
|
||||
skill.relate_to_place = spec.relate_to_place
|
||||
end
|
||||
end
|
||||
|
||||
local function readUsableSpecToSkill(skill, spec)
|
||||
|
|
|
@ -125,4 +125,7 @@ fk.AfterSkillEffect = 82
|
|||
fk.AreaAborted = 87
|
||||
fk.AreaResumed = 88
|
||||
|
||||
fk.NumOfEvents = 89
|
||||
fk.GeneralRevealed = 89
|
||||
fk.GeneralHidden = 90
|
||||
|
||||
fk.NumOfEvents = 91
|
||||
|
|
|
@ -154,8 +154,8 @@ GameEvent.functions[GameEvent.Round] = function(self)
|
|||
p = room.current
|
||||
GameEvent(GameEvent.Turn, p):exec()
|
||||
if room.game_finished then break end
|
||||
room.current = room.current:getNextAlive()
|
||||
until p.seat >= p:getNextAlive().seat
|
||||
room.current = room.current:getNextAlive(true)
|
||||
until p.seat >= p:getNextAlive(true).seat
|
||||
|
||||
logic:trigger(fk.RoundEnd, p)
|
||||
end
|
||||
|
|
|
@ -25,9 +25,25 @@ GameEvent.functions[GameEvent.Pindian] = function(self)
|
|||
local data = { "choose_cards_skill", prompt, true, json.encode(extraData) }
|
||||
|
||||
local targets = {}
|
||||
local moveInfos = {}
|
||||
if not pindianData.fromCard then
|
||||
table.insert(targets, pindianData.from)
|
||||
pindianData.from.request_data = json.encode(data)
|
||||
else
|
||||
local _pindianCard = pindianData.fromCard
|
||||
local pindianCard = _pindianCard:clone(_pindianCard.suit, _pindianCard.number)
|
||||
pindianCard:addSubcard(_pindianCard.id)
|
||||
|
||||
pindianData.fromCard = pindianCard
|
||||
|
||||
table.insert(moveInfos, {
|
||||
ids = { _pindianCard.id },
|
||||
fromArea = room:getCardArea(_pindianCard.id),
|
||||
toArea = Card.Processing,
|
||||
moveReason = fk.ReasonPut,
|
||||
skillName = pindianData.reason,
|
||||
moveVisible = true,
|
||||
})
|
||||
end
|
||||
for _, to in ipairs(pindianData.tos) do
|
||||
if not (pindianData.results[to.id] and pindianData.results[to.id].toCard) then
|
||||
|
@ -39,7 +55,6 @@ GameEvent.functions[GameEvent.Pindian] = function(self)
|
|||
room:notifyMoveFocus(targets, "AskForPindian")
|
||||
room:doBroadcastRequest("AskForUseActiveSkill", targets)
|
||||
|
||||
local moveInfos = {}
|
||||
for _, p in ipairs(targets) do
|
||||
local _pindianCard
|
||||
if p.reply_ready then
|
||||
|
|
|
@ -183,8 +183,7 @@ function GameLogic:broadcastGeneral()
|
|||
assert(p.general ~= "")
|
||||
local general = Fk.generals[p.general]
|
||||
local deputy = Fk.generals[p.deputyGeneral]
|
||||
p.maxHp = deputy and math.floor((deputy.maxHp + general.maxHp) / 2)
|
||||
or general.maxHp
|
||||
p.maxHp = p:getGeneralMaxHp()
|
||||
p.hp = deputy and math.floor((deputy.hp + general.hp) / 2) or general.hp
|
||||
p.shield = math.min(general.shield + (deputy and deputy.shield or 0), 5)
|
||||
-- TODO: setup AI here
|
||||
|
|
|
@ -29,6 +29,10 @@ MarkEnum.BypassTimesLimitTo = "BypassTimesLimitTo"
|
|||
MarkEnum.BypassDistancesLimitTo = "BypassDistancesLimitTo"
|
||||
---非锁定技失效,可带清除标记后缀
|
||||
MarkEnum.UncompulsoryInvalidity = "UncompulsoryInvalidity"
|
||||
---不可明置,可带清除标记后缀(值为表,m - 主将, d - 副将)
|
||||
MarkEnum.RevealProhibited = "RevealProhibited"
|
||||
---不计入距离、座次后缀,可带清除标记后缀
|
||||
MarkEnum.PlayerRemoved = "PlayerRemoved"
|
||||
|
||||
---各种清除标记后缀
|
||||
MarkEnum.TempMarkSuffix = { "-phase", "-turn", "-round" }
|
||||
|
|
|
@ -576,18 +576,25 @@ end
|
|||
---@param full bool @ 是否血量满状态变身
|
||||
---@param isDeputy bool @ 是否变的是副将
|
||||
---@param sendLog bool @ 是否发Log
|
||||
function Room:changeHero(player, new_general, full, isDeputy, sendLog)
|
||||
---@param maxHpChange bool @ 是否改变体力上限,默认改变
|
||||
function Room:changeHero(player, new_general, full, isDeputy, sendLog, maxHpChange)
|
||||
local orig = isDeputy and (player.deputyGeneral or "") or player.general
|
||||
|
||||
orig = Fk.generals[orig]
|
||||
local orig_skills = orig and orig:getSkillNameList() or Util.DummyTable
|
||||
local orig_skills = orig and orig:getSkillNameList()
|
||||
|
||||
local new = Fk.generals[new_general] or Fk.generals["sunce"] or Fk.generals["blank_shibing"]
|
||||
local new_skills = table.map(orig_skills, function(e)
|
||||
return "-" .. e
|
||||
end)
|
||||
local new_skills = {}
|
||||
for _, sname in ipairs(new:getSkillNameList()) do
|
||||
local s = Fk.skills[sname]
|
||||
if not s.relate_to_place or s.relate_to_place == (isDeputy and "d" or "m") then
|
||||
table.insert(new_skills, sname)
|
||||
end
|
||||
end
|
||||
|
||||
table.insertTable(new_skills, new:getSkillNameList())
|
||||
table.insertTable(new_skills, table.map(orig_skills, function(e)
|
||||
return "-" .. e
|
||||
end))
|
||||
|
||||
self:handleAddLoseSkills(player, table.concat(new_skills, "|"), nil, false)
|
||||
|
||||
|
@ -599,10 +606,23 @@ function Room:changeHero(player, new_general, full, isDeputy, sendLog)
|
|||
self:setPlayerProperty(player, "kingdom", new.kingdom)
|
||||
end
|
||||
|
||||
self:setPlayerProperty(player, "maxHp", player:getGeneralMaxHp())
|
||||
maxHpChange = (maxHpChange == nil) and true or maxHpChange
|
||||
if maxHpChange then
|
||||
self:setPlayerProperty(player, "maxHp", player:getGeneralMaxHp())
|
||||
end
|
||||
if full or player.hp > player.maxHp then
|
||||
self:setPlayerProperty(player, "hp", player.maxHp)
|
||||
end
|
||||
|
||||
if sendLog then
|
||||
self:sendLog{
|
||||
type = "#ChangeHero",
|
||||
from = player.id,
|
||||
arg = orig.name,
|
||||
arg2 = new.name,
|
||||
arg3 = isDeputy and "deputyGeneral" or "mainGeneral"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
@ -1271,8 +1291,9 @@ end
|
|||
---@param player ServerPlayer @ 询问目标
|
||||
---@param generals string[] @ 可选武将
|
||||
---@param n integer @ 可选数量,默认为1
|
||||
---@param noConvert bool @ 可否变更,默认可
|
||||
---@return string|string[] @ 选择的武将
|
||||
function Room:askForGeneral(player, generals, n)
|
||||
function Room:askForGeneral(player, generals, n, noConvert)
|
||||
local command = "AskForGeneral"
|
||||
self:notifyMoveFocus(player, command)
|
||||
|
||||
|
@ -1281,7 +1302,7 @@ function Room:askForGeneral(player, generals, n)
|
|||
local defaultChoice = table.random(generals, n)
|
||||
|
||||
if (player.serverplayer:getState() == fk.Player_Online) then
|
||||
local result = self:doRequest(player, command, json.encode{ generals, n })
|
||||
local result = self:doRequest(player, command, json.encode{ generals, n, noConvert })
|
||||
local choices
|
||||
if result == "" then
|
||||
choices = defaultChoice
|
||||
|
@ -2425,10 +2446,10 @@ function Room:handleCardEffect(event, cardEffectEvent)
|
|||
local players = {}
|
||||
Fk.currentResponsePattern = "nullification"
|
||||
for _, p in ipairs(self.alive_players) do
|
||||
local cards = p:getCardIds(Player.Hand)
|
||||
local cards = p:getHandlyIds(true)
|
||||
for _, cid in ipairs(cards) do
|
||||
if
|
||||
Fk:getCardById(cid).name == "nullification" and
|
||||
Fk:getCardById(cid).trueName == "nullification" and
|
||||
not (
|
||||
table.contains(cardEffectEvent.disresponsiveList or Util.DummyTable, p.id) or
|
||||
table.contains(cardEffectEvent.unoffsetableList or Util.DummyTable, p.id)
|
||||
|
|
|
@ -720,7 +720,10 @@ end
|
|||
|
||||
---@param skill Skill
|
||||
function ServerPlayer:addFakeSkill(skill)
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
assert(type(skill) == "string" or skill:isInstanceOf(Skill))
|
||||
if type(skill) == "string" then
|
||||
skill = Fk.skills[skill]
|
||||
end
|
||||
if table.contains(self._fake_skills, skill) then return end
|
||||
|
||||
table.insert(self._fake_skills, skill)
|
||||
|
@ -736,7 +739,10 @@ end
|
|||
|
||||
---@param skill Skill
|
||||
function ServerPlayer:loseFakeSkill(skill)
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
assert(type(skill) == "string" or skill:isInstanceOf(Skill))
|
||||
if type(skill) == "string" then
|
||||
skill = Fk.skills[skill]
|
||||
end
|
||||
if not table.contains(self._fake_skills, skill) then return end
|
||||
|
||||
table.removeOne(self._fake_skills, skill)
|
||||
|
@ -784,7 +790,9 @@ function ServerPlayer:prelightSkill(skill, isPrelight)
|
|||
self:doNotify("PrelightSkill", json.encode{ skill.name, isPrelight })
|
||||
end
|
||||
|
||||
function ServerPlayer:revealGeneral(isDeputy)
|
||||
---@param isDeputy bool
|
||||
---@param no_trigger bool
|
||||
function ServerPlayer:revealGeneral(isDeputy, no_trigger)
|
||||
local room = self.room
|
||||
local generalName
|
||||
if isDeputy then
|
||||
|
@ -801,19 +809,34 @@ function ServerPlayer:revealGeneral(isDeputy)
|
|||
self:loseFakeSkill(skill)
|
||||
end
|
||||
|
||||
local ret = true
|
||||
if not ((isDeputy and self.general ~= "anjiang") or (not isDeputy and self.deputyGeneral ~= "anjiang")) then
|
||||
local other = Fk.generals[self:getMark(isDeputy and "__heg_general" or "__heg_deputy")]
|
||||
for _, sname in ipairs(other:getSkillNameList()) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= (isDeputy and "m" or "d") then
|
||||
ret = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if ret then
|
||||
self:loseFakeSkill("reveal_skill")
|
||||
end
|
||||
|
||||
local oldKingdom = self.kingdom
|
||||
room:changeHero(self, generalName, false, isDeputy)
|
||||
local kingdom = general.kingdom
|
||||
self.kingdom = kingdom
|
||||
if oldKingdom == "unknown" and #table.filter(room:getOtherPlayers(self),
|
||||
function(p)
|
||||
return p.kingdom == kingdom
|
||||
end) >= #room.players // 2 then
|
||||
|
||||
self.kingdom = "wild"
|
||||
room:broadcastProperty(self, "kingdom")
|
||||
end
|
||||
room:broadcastProperty(self, "kingdom")
|
||||
|
||||
if self.gender ~= General.Male and self.gender ~= General.Female then
|
||||
if self.gender == General.Agender then
|
||||
self.gender = general.gender
|
||||
end
|
||||
|
||||
|
@ -824,7 +847,9 @@ function ServerPlayer:revealGeneral(isDeputy)
|
|||
arg2 = generalName,
|
||||
}
|
||||
|
||||
-- TODO: 阴阳鱼摸牌
|
||||
if not no_trigger then
|
||||
room.logic:trigger(fk.GeneralRevealed, self, generalName)
|
||||
end
|
||||
end
|
||||
|
||||
function ServerPlayer:revealBySkillName(skill_name)
|
||||
|
@ -848,6 +873,47 @@ function ServerPlayer:revealBySkillName(skill_name)
|
|||
end
|
||||
end
|
||||
|
||||
function ServerPlayer:hideGeneral(isDeputy)
|
||||
local room = self.room
|
||||
local generalName = isDeputy and self.deputyGeneral or self.general
|
||||
local mark = isDeputy and "__heg_deputy" or "__heg_general"
|
||||
|
||||
self:setMark(mark, generalName)
|
||||
self:doNotify("SetPlayerMark", json.encode{ self.id, mark, generalName})
|
||||
|
||||
if isDeputy then
|
||||
room:setDeputyGeneral(self, "anjiang")
|
||||
room:broadcastProperty(self, "deputyGeneral")
|
||||
else
|
||||
room:setPlayerGeneral(self, "anjiang", false)
|
||||
room:broadcastProperty(self, "general")
|
||||
end
|
||||
|
||||
local general = Fk.generals[generalName]
|
||||
local skills = general.skills
|
||||
local place = isDeputy and "m" or "d"
|
||||
for _, s in ipairs(skills) do
|
||||
room:handleAddLoseSkills(self, "-" .. s.name, nil, false, true)
|
||||
if s.relate_to_place ~= place then
|
||||
if s.frequency == Skill.Compulsory then
|
||||
self:addFakeSkill("reveal_skill")
|
||||
end
|
||||
self:addFakeSkill(s)
|
||||
end
|
||||
end
|
||||
for _, sname in ipairs(general.other_skills) do
|
||||
room:handleAddLoseSkills(self, "-" .. sname, nil, false, true)
|
||||
local s = Fk.skills[sname]
|
||||
if s.relate_to_place ~= place then
|
||||
if s.frequency == Skill.Compulsory then
|
||||
self:addFakeSkill("reveal_skill")
|
||||
end
|
||||
self:addFakeSkill(s)
|
||||
end
|
||||
end
|
||||
|
||||
room.logic:trigger(fk.GeneralHidden, room, generalName)
|
||||
end
|
||||
-- 神貂蝉
|
||||
|
||||
---@param p ServerPlayer
|
||||
|
|
|
@ -145,6 +145,79 @@ local uncompulsoryInvalidity = fk.CreateInvaliditySkill {
|
|||
end
|
||||
}
|
||||
|
||||
local revealProhibited = fk.CreateInvaliditySkill {
|
||||
name = "reveal_prohibited",
|
||||
global = true,
|
||||
invalidity_func = function(self, from, skill)
|
||||
local generals = {}
|
||||
if type(from:getMark(MarkEnum.RevealProhibited)) == "table" then
|
||||
generals = from:getMark(MarkEnum.RevealProhibited)
|
||||
end
|
||||
for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
||||
return from:getMark(MarkEnum.RevealProhibited .. s)
|
||||
end)) do
|
||||
if type(m) == "table" then
|
||||
for _, g in ipairs(m) do
|
||||
table.insertIfNeed(generals, g)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #generals == 0 then return false end
|
||||
if type(from._fake_skills) == "table" and not table.contains(from._fake_skills, skill) then return false end
|
||||
local sname = skill.name
|
||||
for _, g in ipairs(generals) do
|
||||
local ret = g == "m" and from:getMark("__heg_general") or from:getMark("__heg_deputy")
|
||||
local general = Fk.generals[ret]
|
||||
if table.contains(general:getSkillNameList(), sname) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
-- 亮将
|
||||
local revealSkill = fk.CreateActiveSkill{
|
||||
name = "reveal_skill",
|
||||
prompt = "#reveal_skill",
|
||||
interaction = function(self)
|
||||
local choiceList = {}
|
||||
if (Self.general == "anjiang" and not Self:prohibitReveal()) then
|
||||
local general = Fk.generals[Self:getMark("__heg_general")]
|
||||
for _, sname in ipairs(general:getSkillNameList()) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= "m" then
|
||||
table.insert(choiceList, "revealMain")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if (Self.deputyGeneral == "anjiang" and not Self:prohibitReveal(true)) then
|
||||
local general = Fk.generals[Self:getMark("__heg_deputy")]
|
||||
for _, sname in ipairs(general:getSkillNameList()) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= "d" then
|
||||
table.insert(choiceList, "revealDeputy")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if #choiceList == 0 then return false end
|
||||
return UI.ComboBox { choices = choiceList}
|
||||
end,
|
||||
target_num = 0,
|
||||
card_num = 0,
|
||||
card_filter = Util.FalseFunc,
|
||||
on_use = function(self, room, effect)
|
||||
local player = room:getPlayerById(effect.from)
|
||||
local choice = self.interaction.data
|
||||
if not choice then return false
|
||||
elseif choice == "revealMain" then player:revealGeneral(false)
|
||||
elseif choice == "revealDeputy" then player:revealGeneral(true) end
|
||||
end,
|
||||
}
|
||||
|
||||
AuxSkills = {
|
||||
discardSkill,
|
||||
chooseCardsSkill,
|
||||
|
@ -152,4 +225,6 @@ AuxSkills = {
|
|||
maxCardsSkill,
|
||||
choosePlayersToMoveCardInBoardSkill,
|
||||
uncompulsoryInvalidity,
|
||||
revealProhibited,
|
||||
revealSkill
|
||||
}
|
||||
|
|
|
@ -1,372 +1,6 @@
|
|||
local heg_description = [==[
|
||||
# 国战简介
|
||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
《三国杀·国战》是一款可以支持2\~12人(线上版4\~8人)同时参与的桌面卡牌游戏。在游戏中,每名玩家将甄选三国时代中包括魏国、蜀国、吴国、群雄在内的各位名将,组成自己的战斗团队,利用他们珠联璧合的组合技能发起进攻,消灭其他各方势力,赢得最终的胜利。
|
||||
-- deprecated file, only for update
|
||||
|
||||
## 准备游戏
|
||||
-- current hegemony repository is at https://gitee.com/qsgs-fans/hegemony
|
||||
|
||||
**挑选武将:**
|
||||
|
||||
发给每位玩家四张武将牌(会员5张),选出两张势力相同的武将牌并背面朝上放置,称为“暗置”(参考段落“明置和暗置”)。
|
||||
|
||||
靠近体力牌的武将视为副将,另一个视为主将。
|
||||
|
||||
游戏中,每名玩家扮演的角色由两张武将牌组成。
|
||||
|
||||
**分发体力牌:**
|
||||
|
||||
每位玩家拿取一张体力牌,翻到对应体力上限的一面,放置在武将牌旁边。体力上限为两张武将牌上的完整阴阳鱼的数量之和。两个单独的阴阳鱼可以组成一个完整的阴阳鱼。
|
||||
|
||||
注:当一名角色的两张武将牌第一次均明置时,若其武将牌上有单独的阴阳鱼没有组成1 点体力,则他可以立即摸一张牌。
|
||||
|
||||
扣减体力时,用主将挡住扣减的体力,露出当前体力值。
|
||||
|
||||
## 进行游戏
|
||||
|
||||
随机选择一名玩家作为起始玩家。由该玩家开始,按逆时针方向以回合的方式进行。即每名玩家有一个自己的回合,一名玩家的回合结束后, 右边玩家的回合开始,依次轮流进行。
|
||||
|
||||
每个玩家的回合可以分为六个阶段:
|
||||
|
||||
回合开始阶段 -> 判定阶段 -> 摸牌阶段 -> 出牌阶段 -> 弃牌阶段 -> 回合结束阶段
|
||||
|
||||
**回合开始阶段:**
|
||||
|
||||
有些技能可以在此阶段发动。你的暗置的武将牌也可于此阶段明置。
|
||||
|
||||
**判定阶段:**
|
||||
|
||||
若你的面前横置着延时类锦囊,你必须依次对这些延时类锦囊进行判定。若有多张延时类锦囊,先判定最后放置的那张,然后以此类推。
|
||||
|
||||
**摸牌阶段:**
|
||||
|
||||
你从牌堆顶摸两张牌。
|
||||
|
||||
**出牌阶段:**
|
||||
|
||||
你可以使用任意张牌,但必须遵守以下两条规则:
|
||||
|
||||
1. 每个出牌阶段仅限使用一次【杀】。
|
||||
2. 任何一名角色面前的判定区里不能放有两张同名的牌。
|
||||
|
||||
每使用一张牌,即执行该牌之效果,详见“游戏牌详解”。如无特殊说明,游戏牌在使用后均需置入弃牌堆。
|
||||
|
||||
**弃牌阶段:**
|
||||
|
||||
在出牌阶段中,不想出或没法出牌时,就进入弃牌阶段。此时检查你的手牌数是否超出你当前的体力值( 你的手牌上限等于你当前的体力值), 每超出一张,须弃置一张手牌。
|
||||
|
||||
**回合结束阶段:**
|
||||
|
||||
有些技能可以在此阶段发动。
|
||||
|
||||
|
||||
## 角色死亡
|
||||
|
||||
当一名角色的体力降到0 时,即进入濒死状态,除非该角色在此时使用【酒】,或有角色使用【桃】来挽救该角色,否则该角色死亡。
|
||||
|
||||
死亡的角色明置其武将牌,弃置该角色所有牌及其判定区里的牌,然后执行奖惩。
|
||||
|
||||
奖惩方式:
|
||||
|
||||
1. 已经确定势力的角色杀死相同势力的角色须弃置所有手牌和装备区的牌;
|
||||
2. 已经确定势力的角色杀死不同势力的角色,从牌堆摸取等同于该势力人数(包括刚刚杀死的角色)张牌。
|
||||
|
||||
例:“蜀”势力角色杀死了一名“魏”势力角色,此时还有其他两名“魏”势力角色存活,则该“蜀”势力角色摸三张牌。
|
||||
|
||||
注:若被杀死的角色还没有明置武将牌(即没确定势力),则须明置验明势力。 没有势力的角色(即武将牌没有明置的角色)杀死其他角色没有奖惩。
|
||||
|
||||
## 胜负结算
|
||||
|
||||
玩家的游戏目标与势力有关:消灭所有与自己不同势力的角色。
|
||||
|
||||
特殊的:野心家需要消灭所有其他角色。
|
||||
|
||||
当全场所有角色均确定势力后, 才可以进行胜利条件的判断:
|
||||
当全场只剩下一种势力存活时, 该势力的角色获胜( 没有确定势力的角色无法取得游戏胜利, 即使与存活的其他角色为同一势力)。
|
||||
|
||||
## 暗将规则
|
||||
|
||||
处于暗置状态的武将牌没有任何武将技能、性别以及势力。当暗置的武将牌发动技能时,将武将牌明置,然后发动相应的技能。
|
||||
|
||||
暗置的武将牌只有两个时机可以将武将牌明置:1. 回合开始阶段开始时;2. 发动武将牌的技能时。
|
||||
|
||||
例:郭嘉、司马懿等,受到伤害后发动技能时明置武将牌;
|
||||
马超、黄忠等,使用【杀】指定一名角色为目标后,发动技能并明置武将牌;
|
||||
孙权、甘宁等,在出牌阶段发动技能时明置武将牌;
|
||||
|
||||
没有明置武将牌的角色没有性别,任何与性别有关的技能和武器效果均不能对其发动。
|
||||
|
||||
有一张武将牌明置时,角色性别与明置的武将牌相同。当一名角色的两张武将牌均亮明后,性别与主将的武将牌相同。
|
||||
|
||||
没有明置武将牌的角色没有势力,明置一张武将牌后确定势力:与武将牌左上角所示的势力相同,或成为野心家。野心家用“野心家牌”表示。
|
||||
|
||||
野心家规则:
|
||||
|
||||
当一名角色明置武将牌确定势力时,若该势力的角色超过了游戏总玩家数的一半,则他视为野心家,拿取一张野心家牌表示。若之后仍然有该势力的角色明置武将牌,均视为野心家。野心家为单独的一种势力,与其他角色的势力均不同。他(们)需要杀死所有其他角色,成为唯一的存活者。
|
||||
|
||||
注意:野心家与野心家之间也是不同势力。
|
||||
|
||||
例:
|
||||
|
||||
★ 6 人、7 人游戏时,当出现第四名同势力角色时,该角色及之后明置的该势力角色均成为野心家。
|
||||
|
||||
★ 8 人、9 人游戏时,当出现第五名同势力角色时,该角色及之后明置的该势力角色均成为野心家。
|
||||
|
||||
## 珠联璧合
|
||||
|
||||
珠联璧合表示了部分武将之间的特殊联系。
|
||||
|
||||
武将牌中下方的其他武将姓名表示了可以和此武将牌形成珠联璧合的其他武将。
|
||||
|
||||
若你选择的两张武将牌形成珠联璧合,则在第一次两张武将牌均明置时,可以立即选择摸两张牌或回复1 点体力。
|
||||
|
||||
若触发珠联璧合时正在进行其他事件的结算,则先进行“珠联璧合”的选择,再继续结算该事件。
|
||||
]==]
|
||||
|
||||
local heg
|
||||
|
||||
---@class HegLogic: GameLogic
|
||||
local HegLogic = {}
|
||||
|
||||
function HegLogic:assignRoles()
|
||||
local room = self.room
|
||||
for _, p in ipairs(room.players) do
|
||||
p.role_shown = true
|
||||
p.role = "hidden"
|
||||
room:broadcastProperty(p, "role")
|
||||
end
|
||||
|
||||
-- for adjustSeats
|
||||
room.players[1].role = "lord"
|
||||
end
|
||||
|
||||
function HegLogic:chooseGenerals()
|
||||
local room = self.room
|
||||
local generalNum = math.max(room.settings.generalNum, 6)
|
||||
|
||||
local lord = room:getLord()
|
||||
room.current = lord
|
||||
lord.role = "hidden"
|
||||
|
||||
local nonlord = room.players
|
||||
local generals = Fk:getGeneralsRandomly(#nonlord * generalNum)
|
||||
-- table.shuffle(generals)
|
||||
for _, p in ipairs(nonlord) do
|
||||
local arg = { map = table.map }
|
||||
for i = 1, generalNum do
|
||||
table.insert(arg, table.remove(generals, 1))
|
||||
end
|
||||
table.sort(arg, function(a, b) return a.kingdom > b.kingdom end)
|
||||
|
||||
for idx, _ in ipairs(arg) do
|
||||
if arg[idx].kingdom == arg[idx + 1].kingdom then
|
||||
p.default_reply = { arg[idx].name, arg[idx + 1].name }
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
arg = arg:map(function(g) return g.name end)
|
||||
p.request_data = json.encode({ arg, 2, true })
|
||||
end
|
||||
|
||||
room:notifyMoveFocus(nonlord, "AskForGeneral")
|
||||
room:doBroadcastRequest("AskForGeneral", nonlord)
|
||||
for _, p in ipairs(nonlord) do
|
||||
local general, deputy
|
||||
if p.general == "" and p.reply_ready then
|
||||
local generals = json.decode(p.client_reply)
|
||||
general = generals[1]
|
||||
deputy = generals[2]
|
||||
room:setPlayerGeneral(p, general, true)
|
||||
room:setDeputyGeneral(p, deputy)
|
||||
else
|
||||
general = p.default_reply[1]
|
||||
deputy = p.default_reply[2]
|
||||
end
|
||||
|
||||
p:setMark("__heg_general", general)
|
||||
p:setMark("__heg_deputy", deputy)
|
||||
p:doNotify("SetPlayerMark", json.encode{ p.id, "__heg_general", general})
|
||||
p:doNotify("SetPlayerMark", json.encode{ p.id, "__heg_deputy", deputy})
|
||||
|
||||
room:setPlayerGeneral(p, "anjiang", true)
|
||||
room:setDeputyGeneral(p, "anjiang")
|
||||
|
||||
p.default_reply = ""
|
||||
end
|
||||
end
|
||||
|
||||
function HegLogic:broadcastGeneral()
|
||||
local room = self.room
|
||||
local players = room.players
|
||||
|
||||
for _, p in ipairs(players) do
|
||||
assert(p.general ~= "")
|
||||
local general = Fk.generals[p:getMark("__heg_general")]
|
||||
local deputy = Fk.generals[p:getMark("__heg_deputy")]
|
||||
p.maxHp = math.floor((deputy.maxHp + general.maxHp) / 2)
|
||||
p.hp = math.floor((deputy.hp + general.hp) / 2)
|
||||
-- p.shield = math.min(general.shield + deputy.shield, 5)
|
||||
p.shield = 0
|
||||
-- TODO: setup AI here
|
||||
|
||||
room:broadcastProperty(p, "general")
|
||||
room:broadcastProperty(p, "deputyGeneral")
|
||||
room:broadcastProperty(p, "maxHp")
|
||||
room:broadcastProperty(p, "hp")
|
||||
room:broadcastProperty(p, "shield")
|
||||
end
|
||||
end
|
||||
|
||||
function HegLogic:attachSkillToPlayers()
|
||||
local room = self.room
|
||||
local players = room.players
|
||||
|
||||
room:handleAddLoseSkills(players[1], "#_heg_invalid", nil, false, true)
|
||||
|
||||
local addHegSkills = function(player, skillName)
|
||||
local skill = Fk.skills[skillName]
|
||||
if skill.lordSkill and (player.role ~= "lord" or #room.players < 5) then
|
||||
return
|
||||
end
|
||||
|
||||
player:addFakeSkill(skill)
|
||||
end
|
||||
|
||||
for _, p in ipairs(room.alive_players) do
|
||||
local general = Fk.generals[p:getMark("__heg_general")]
|
||||
local skills = general.skills
|
||||
for _, s in ipairs(skills) do
|
||||
addHegSkills(p, s.name)
|
||||
end
|
||||
for _, sname in ipairs(general.other_skills) do
|
||||
addHegSkills(p, sname)
|
||||
end
|
||||
|
||||
local deputy = Fk.generals[p:getMark("__heg_deputy")]
|
||||
if deputy then
|
||||
skills = deputy.skills
|
||||
for _, s in ipairs(skills) do
|
||||
addHegSkills(p, s.name)
|
||||
end
|
||||
for _, sname in ipairs(deputy.other_skills) do
|
||||
addHegSkills(p, sname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
room:setTag("SkipNormalDeathProcess", true)
|
||||
end
|
||||
|
||||
local heg_getlogic = function()
|
||||
local h = GameLogic:subclass("HegLogic")
|
||||
for k, v in pairs(HegLogic) do
|
||||
h[k] = v
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
local heg_invalid = fk.CreateInvaliditySkill{
|
||||
name = "#_heg_invalid",
|
||||
invalidity_func = function(self, player, skill)
|
||||
end,
|
||||
}
|
||||
|
||||
local function getWinnerHeg(victim)
|
||||
local room = victim.room
|
||||
local alive = room.alive_players
|
||||
if #alive == 1 then
|
||||
local p = alive[1]
|
||||
p:revealGeneral(false)
|
||||
p:revealGeneral(true)
|
||||
return p.kingdom
|
||||
end
|
||||
|
||||
local winner = alive[1].kingdom
|
||||
if winner == "unknown" then return "" end
|
||||
for _, p in ipairs(alive) do
|
||||
if p.kingdom ~= winner or p.kingdom == "wild" then
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
return winner
|
||||
end
|
||||
|
||||
local heg_rule = fk.CreateTriggerSkill{
|
||||
name = "#heg_rule",
|
||||
priority = 0.001,
|
||||
events = {fk.TurnStart, fk.GameOverJudge, fk.BuryVictim},
|
||||
can_trigger = function(self, event, target, player, data)
|
||||
return target == player
|
||||
end,
|
||||
on_trigger = function(self, event, target, player, data)
|
||||
local room = player.room
|
||||
if event == fk.TurnStart then
|
||||
local choices = {}
|
||||
if player.general == "anjiang" then
|
||||
table.insert(choices, "revealMain")
|
||||
end
|
||||
if player.deputyGeneral == "anjiang" then
|
||||
table.insert(choices, "revealDeputy")
|
||||
end
|
||||
if #choices == 0 then return end
|
||||
if #choices == 2 then table.insert(choices, "revealAll") end
|
||||
table.insert(choices, "Cancel")
|
||||
|
||||
local choice = room:askForChoice(player, choices, self.name)
|
||||
if choice == "revealMain" then player:revealGeneral(false)
|
||||
elseif choice == "revealDeputy" then player:revealGeneral(true)
|
||||
elseif choice == "revealAll" then
|
||||
player:revealGeneral(false)
|
||||
player:revealGeneral(true)
|
||||
end
|
||||
elseif event == fk.GameOverJudge then
|
||||
player:revealGeneral(false)
|
||||
player:revealGeneral(true)
|
||||
local winner = getWinnerHeg(player)
|
||||
if winner ~= "" then
|
||||
room:gameOver("hidden")
|
||||
return true
|
||||
end
|
||||
room:setTag("SkipGameRule", true)
|
||||
elseif event == fk.BuryVictim then
|
||||
local damage = data.damage
|
||||
if damage and damage.from then
|
||||
local killer = damage.from
|
||||
if killer.kingdom == "unknown" then return end
|
||||
|
||||
local victim = damage.to
|
||||
if killer.kingdom ~= "wild" and killer.kingdom == victim.kingdom then
|
||||
killer:throwAllCards("he")
|
||||
else
|
||||
killer:drawCards(victim.kingdom == "wild" and 1 or
|
||||
#table.filter(room.alive_players, function(p)
|
||||
return p.kingdom == victim.kingdom
|
||||
end) + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
Fk:addSkill(heg_rule)
|
||||
|
||||
heg = fk.CreateGameMode{
|
||||
name = "heg_mode",
|
||||
minPlayer = 2,
|
||||
maxPlayer = 8,
|
||||
rule = heg_rule,
|
||||
logic = heg_getlogic,
|
||||
is_counted = Util.FalseFunc
|
||||
}
|
||||
|
||||
Fk:loadTranslationTable{
|
||||
["heg_mode"] = "国战测试版",
|
||||
[":heg_mode"] = heg_description,
|
||||
["wild"] = "野心家",
|
||||
["#heg_rule"] = "国战规则",
|
||||
["revealMain"] = "明置主将",
|
||||
["revealDeputy"] = "明置副将",
|
||||
["revealAll"] = "背水:全部明置",
|
||||
}
|
||||
|
||||
return heg
|
||||
|
|
|
@ -460,6 +460,9 @@ Fk:loadTranslationTable{
|
|||
["choose_cards_skill"] = "选牌",
|
||||
["choose_players_skill"] = "选择角色",
|
||||
["choose_players_to_move_card_in_board"] = "选择角色",
|
||||
["reveal_skill"] = "亮将",
|
||||
["#reveal_skill"] = "选择一个武将亮将(点击左侧选择框展开)",
|
||||
[":reveal_skill"] = "出牌阶段,你可亮出一张有锁定技的武将。",
|
||||
|
||||
["game_rule"] = "弃牌阶段",
|
||||
}
|
||||
|
|
|
@ -532,6 +532,7 @@ guanyu:addSkill(wusheng)
|
|||
|
||||
local paoxiaoAudio = fk.CreateTriggerSkill{
|
||||
name = "#paoxiaoAudio",
|
||||
visible = false,
|
||||
refresh_events = {fk.CardUsing},
|
||||
can_refresh = function(self, event, target, player, data)
|
||||
return target == player and player:hasSkill(self.name) and
|
||||
|
@ -549,6 +550,7 @@ local paoxiaoAudio = fk.CreateTriggerSkill{
|
|||
}
|
||||
local paoxiao = fk.CreateTargetModSkill{
|
||||
name = "paoxiao",
|
||||
frequency = Skill.Compulsory,
|
||||
bypass_times = function(self, player, skill, scope)
|
||||
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
|
||||
and scope == Player.HistoryPhase then
|
||||
|
@ -1283,9 +1285,6 @@ Fk:loadTranslationTable{
|
|||
["anjiang"] = "暗将",
|
||||
}
|
||||
|
||||
-- local heg_mode = require "packages.standard.hegemony"
|
||||
-- extension:addGameMode(heg_mode)
|
||||
|
||||
-- load translations of this package
|
||||
dofile "packages/standard/i18n/init.lua"
|
||||
|
||||
|
|
|
@ -692,7 +692,7 @@ local lightningSkill = fk.CreateActiveSkill{
|
|||
local to = room:getPlayerById(effect.to)
|
||||
local nextp = to
|
||||
repeat
|
||||
nextp = nextp:getNextAlive()
|
||||
nextp = nextp:getNextAlive(true)
|
||||
if nextp == to then break end
|
||||
until not nextp:hasDelayedTrick("lightning") and not nextp:isProhibited(nextp, effect.card)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user