mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 03:32:34 +08:00
终结标记与界bugfix (#307)
- 正式移除了作为临时手段的-tmp标记,现在can_use和target_filter支持读取extra_data(card_filter暂时搁置) - 规范了askForUseCard中card_name和pattern的关系,现在的格式将以pattern为主,若无pattern才会将card_name视为pattern - 将withinDistanceLimit迁移至ActiveSkill内 - 添加了令卡牌无距离/次数限制的标记判断 - 添加放大了⑨倍的冰伤音效 - 优化了同将判断的逻辑,使其能够准确读取trueName - 身份场主公选将后其他角色能看见主公技能(只是看见,无实际功能) - 开局添加不存在的技能时会放出警报 - 修复了findParent在当前事件无parent时报错的bug - 修复了人工洗牌后不刷新摸牌堆的bug - 修复了getPile返回牌堆实例的bug - 修复了getSkillNameList无法过滤主公技的bug - 修复了死亡后武将牌没有圆角效果的bug
This commit is contained in:
parent
db651f572e
commit
21e4c65204
|
@ -483,7 +483,7 @@ Item {
|
|||
&& JSON.parse(Backend.callLuaFunction("GetPlayerHandcards", [Self.id])).includes(card)) {
|
||||
|
||||
const skills = JSON.parse(Backend.callLuaFunction("GetCardSpecialSkills", [card]));
|
||||
if (JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id]))) {
|
||||
if (JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id, JSON.stringify(roomScene.extra_data)]))) {
|
||||
skills.unshift("_normal_use");
|
||||
}
|
||||
specialCardSkills.model = skills;
|
||||
|
|
|
@ -570,7 +570,7 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
|
|||
const id = photo.playerid;
|
||||
const ret = JSON.parse(Backend.callLuaFunction(
|
||||
"CanUseCardToTarget",
|
||||
[card, id, selected_targets]
|
||||
[card, id, selected_targets, JSON.stringify(roomScene.extra_data)]
|
||||
));
|
||||
photo.selectable = ret;
|
||||
if (roomScene.extra_data instanceof Object) {
|
||||
|
@ -603,7 +603,7 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
|
|||
)) && (roomScene.autoPending || !JSON.parse(Backend.callLuaFunction(
|
||||
"CardProhibitedUse", [card])));
|
||||
} else if (okButton.enabled && roomScene.state === "playing") {
|
||||
okButton.enabled = JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id]));
|
||||
okButton.enabled = JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id, JSON.stringify(roomScene.extra_data)]));
|
||||
}
|
||||
if (okButton.enabled) {
|
||||
if (roomScene.extra_data instanceof Object) {
|
||||
|
@ -648,7 +648,7 @@ function updateSelectedTargets(playerid, selected) {
|
|||
const id = photo.playerid;
|
||||
const ret = JSON.parse(Backend.callLuaFunction(
|
||||
"CanUseCardToTarget",
|
||||
[card, id, selected_targets]
|
||||
[card, id, selected_targets, JSON.stringify(roomScene.extra_data)]
|
||||
));
|
||||
photo.selectable = ret;
|
||||
if (roomScene.extra_data instanceof Object) {
|
||||
|
@ -681,7 +681,7 @@ function updateSelectedTargets(playerid, selected) {
|
|||
)) && (roomScene.autoPending || !JSON.parse(Backend.callLuaFunction(
|
||||
"CardProhibitedUse", [card])));
|
||||
} else if (okButton.enabled && roomScene.state === "playing") {
|
||||
okButton.enabled = JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id]));
|
||||
okButton.enabled = JSON.parse(Backend.callLuaFunction("CanUseCard", [card, Self.id, JSON.stringify(roomScene.extra_data)]));
|
||||
}
|
||||
if (okButton.enabled) {
|
||||
if (roomScene.extra_data instanceof Object) {
|
||||
|
|
|
@ -223,14 +223,14 @@ RowLayout {
|
|||
const ids = [], cards = handcardAreaItem.cards;
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
cards[i].prohibitReason = "";
|
||||
if (JSON.parse(Backend.callLuaFunction("CanUseCard", [cards[i].cid, Self.id]))) {
|
||||
if (JSON.parse(Backend.callLuaFunction("CanUseCard", [cards[i].cid, Self.id, JSON.stringify(roomScene.extra_data)]))) {
|
||||
ids.push(cards[i].cid);
|
||||
} else {
|
||||
// cannot use? considering special_skills
|
||||
const skills = JSON.parse(Backend.callLuaFunction("GetCardSpecialSkills", [cards[i].cid]));
|
||||
for (let j = 0; j < skills.length; j++) {
|
||||
const s = skills[j];
|
||||
if (JSON.parse(Backend.callLuaFunction("ActiveCanUse", [s]))) {
|
||||
if (JSON.parse(Backend.callLuaFunction("ActiveCanUse", [s, JSON.stringify(roomScene.extra_data)]))) {
|
||||
ids.push(cards[i].cid);
|
||||
break;
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ RowLayout {
|
|||
continue;
|
||||
}
|
||||
|
||||
item.enabled = JSON.parse(Backend.callLuaFunction("ActiveCanUse", [item.orig]));
|
||||
item.enabled = JSON.parse(Backend.callLuaFunction("ActiveCanUse", [item.orig, JSON.stringify(roomScene.extra_data)]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,14 +247,15 @@ Item {
|
|||
}
|
||||
|
||||
OpacityMask {
|
||||
id: photoMaskEffect
|
||||
anchors.fill: photoMask
|
||||
source: generalImgItem
|
||||
maskSource: photoMask
|
||||
}
|
||||
|
||||
Colorize {
|
||||
anchors.fill: photoMask
|
||||
source: generalImgItem
|
||||
anchors.fill: photoMaskEffect
|
||||
source: photoMaskEffect
|
||||
saturation: 0
|
||||
visible: root.dead || root.surrendered
|
||||
}
|
||||
|
|
BIN
audio/system/ice_damage.mp3
Normal file
BIN
audio/system/ice_damage.mp3
Normal file
Binary file not shown.
BIN
audio/system/ice_damage2.mp3
Normal file
BIN
audio/system/ice_damage2.mp3
Normal file
Binary file not shown.
|
@ -251,8 +251,10 @@ end
|
|||
|
||||
---@param card string | integer
|
||||
---@param player integer
|
||||
function CanUseCard(card, player)
|
||||
---@param extra_data_str string
|
||||
function CanUseCard(card, player, extra_data_str)
|
||||
local c ---@type Card
|
||||
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
||||
if type(card) == "number" then
|
||||
c = Fk:getCardById(card)
|
||||
else
|
||||
|
@ -271,13 +273,13 @@ function CanUseCard(card, player)
|
|||
end
|
||||
|
||||
player = ClientInstance:getPlayerById(player)
|
||||
local ret = c.skill:canUse(player, c)
|
||||
local ret = c.skill:canUse(player, c, extra_data)
|
||||
ret = ret and not player:prohibitUse(c)
|
||||
if ret then
|
||||
local min_target = c.skill:getMinTargetNum()
|
||||
if min_target > 0 then
|
||||
for _, p in ipairs(ClientInstance.players) do
|
||||
if c.skill:targetFilter(p.id, {}, {}, c) then
|
||||
if c.skill:targetFilter(p.id, {}, {}, c, extra_data) then
|
||||
return "true"
|
||||
end
|
||||
end
|
||||
|
@ -311,7 +313,9 @@ end
|
|||
---@param card string | integer
|
||||
---@param to_select integer @ id of the target
|
||||
---@param selected integer[] @ ids of selected targets
|
||||
function CanUseCardToTarget(card, to_select, selected)
|
||||
---@param extra_data_str string @ extra data
|
||||
function CanUseCardToTarget(card, to_select, selected, extra_data_str)
|
||||
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
||||
if ClientInstance:getPlayerById(to_select).dead then
|
||||
return "false"
|
||||
end
|
||||
|
@ -322,10 +326,10 @@ function CanUseCardToTarget(card, to_select, selected)
|
|||
selected_cards = {card}
|
||||
else
|
||||
local t = json.decode(card)
|
||||
return ActiveTargetFilter(t.skill, to_select, selected, t.subcards)
|
||||
return ActiveTargetFilter(t.skill, to_select, selected, t.subcards, extra_data)
|
||||
end
|
||||
|
||||
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c)
|
||||
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c, extra_data)
|
||||
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
|
||||
return json.encode(ret)
|
||||
end
|
||||
|
@ -392,12 +396,13 @@ function GetSkillData(skill_name)
|
|||
}
|
||||
end
|
||||
|
||||
function ActiveCanUse(skill_name)
|
||||
function ActiveCanUse(skill_name, extra_data_str)
|
||||
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
||||
local skill = Fk.skills[skill_name]
|
||||
local ret = false
|
||||
if skill then
|
||||
if skill:isInstanceOf(ActiveSkill) then
|
||||
ret = skill:canUse(Self)
|
||||
ret = skill:canUse(Self, extra_data)
|
||||
elseif skill:isInstanceOf(ViewAsSkill) then
|
||||
ret = skill:enabledAtPlay(Self)
|
||||
if ret then
|
||||
|
@ -414,7 +419,7 @@ function ActiveCanUse(skill_name)
|
|||
for _, n in ipairs(cnames) do
|
||||
local c = Fk:cloneCard(n)
|
||||
c.skillName = skill_name
|
||||
ret = c.skill:canUse(Self, c)
|
||||
ret = c.skill:canUse(Self, c, extra_data)
|
||||
if ret then break end
|
||||
end
|
||||
end
|
||||
|
@ -449,7 +454,7 @@ function ActiveCardFilter(skill_name, to_select, selected, selected_targets)
|
|||
return json.encode(ret)
|
||||
end
|
||||
|
||||
function ActiveTargetFilter(skill_name, to_select, selected, selected_cards)
|
||||
function ActiveTargetFilter(skill_name, to_select, selected, selected_cards, extra_data)
|
||||
local skill = Fk.skills[skill_name]
|
||||
local ret = false
|
||||
if skill then
|
||||
|
@ -458,7 +463,7 @@ function ActiveTargetFilter(skill_name, to_select, selected, selected_cards)
|
|||
elseif skill:isInstanceOf(ViewAsSkill) then
|
||||
local card = skill:viewAs(selected_cards)
|
||||
if card then
|
||||
ret = card.skill:targetFilter(to_select, selected, selected_cards, card)
|
||||
ret = card.skill:targetFilter(to_select, selected, selected_cards, card, extra_data)
|
||||
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), card)
|
||||
end
|
||||
end
|
||||
|
@ -722,7 +727,7 @@ function PoxiPrompt(poxi_type, data, extra_data)
|
|||
local poxi = Fk.poxi_methods[poxi_type]
|
||||
if not poxi or not poxi.prompt then return "" end
|
||||
if type(poxi.prompt) == "string" then return Fk:translate(poxi.prompt) end
|
||||
return poxi.prompt(data, extra_data)
|
||||
return Fk:translate(poxi.prompt(data, extra_data))
|
||||
end
|
||||
|
||||
function PoxiFilter(poxi_type, to_select, selected, data, extra_data)
|
||||
|
|
|
@ -268,6 +268,7 @@ Fk:loadTranslationTable({
|
|||
["thunder_damage"] = "Thunder",
|
||||
["ice_damage"] = "Ice",
|
||||
["hp_lost"] = "HP lost",
|
||||
["lose_hp"] = "lose HP",
|
||||
|
||||
["phase_start"] = "Prepare phase",
|
||||
["phase_judge"] = "Judge phase",
|
||||
|
|
|
@ -324,6 +324,7 @@ Fk:loadTranslationTable{
|
|||
["thunder_damage"] = "雷属性",
|
||||
["ice_damage"] = "冰属性",
|
||||
["hp_lost"] = "体力流失",
|
||||
["lose_hp"] = "失去体力",
|
||||
|
||||
["phase_start"] = "准备阶段",
|
||||
["phase_judge"] = "判定阶段",
|
||||
|
|
|
@ -406,6 +406,9 @@ function Card:getMark(mark)
|
|||
if (not self:isVirtual()) and next(self.mark) == nil then
|
||||
self.mark = nil
|
||||
end
|
||||
if type(ret) == "table" then
|
||||
ret = table.simpleClone(ret)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
|
|
@ -275,8 +275,8 @@ end
|
|||
---@param name string @ 要查询的武将名字
|
||||
---@return string[] @ 这个武将对应的同名武将列表
|
||||
function Engine:getSameGenerals(name)
|
||||
local tmp = name:split("__")
|
||||
local tName = tmp[#tmp]
|
||||
if not self.generals[name] then return {} end
|
||||
local tName = self.generals[name].trueName
|
||||
local ret = self.same_generals[tName] or {}
|
||||
return table.filter(ret, function(g)
|
||||
return g ~= name and self.generals[g] ~= nil and self:canUseGeneral(g)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
2. 对于 Matcher 字符串,它是用 ('|') 分割的
|
||||
3. 然后在 Matcher 的每一个细分中,又可以用 ',' 来进行更进一步的分割
|
||||
|
||||
其中 Matcher 的格式为 牌名|花色|点数|位置|详细牌名|类型|牌的id
|
||||
其中 Matcher 的格式为 牌名|点数|花色|区域|完整牌名|牌类型|牌id
|
||||
更进一步,“点数” 可以用 '~' 符号表示数字的范围,并且可以用 AJQK 表示对应点数
|
||||
|
||||
例如:
|
||||
|
|
|
@ -94,12 +94,18 @@ function General:addRelatedSkill(skill)
|
|||
end
|
||||
|
||||
--- 获取武将所有技能。
|
||||
---@param include_lord bool
|
||||
function General:getSkillNameList(include_lord)
|
||||
local ret = table.map(self.skills, Util.NameMapper)
|
||||
table.insertTable(ret, self.other_skills)
|
||||
|
||||
if not include_lord then
|
||||
local ret = {}
|
||||
local other_skills = table.map(self.other_skills, Util.Name2SkillMapper)
|
||||
local skills = table.connect(self.skills, other_skills)
|
||||
for _, skill in ipairs(skills) do
|
||||
if include_lord or not skill.lordSkill then
|
||||
table.insert(ret, skill.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- table.insertTable(ret, self.other_skills)
|
||||
return ret
|
||||
end
|
||||
|
||||
|
|
|
@ -215,7 +215,10 @@ end
|
|||
---@param mark string @ 标记
|
||||
---@return any
|
||||
function Player:getMark(mark)
|
||||
return (self.mark[mark] or 0)
|
||||
local mark = self.mark[mark]
|
||||
if not mark then return 0 end
|
||||
if type(mark) == "table" then return table.simpleClone(mark) end
|
||||
return mark
|
||||
end
|
||||
|
||||
--- 判定角色是否拥有对应的Mark。
|
||||
|
@ -363,13 +366,13 @@ function Player:getCardIds(playerAreas, specialName)
|
|||
return cardIds
|
||||
end
|
||||
|
||||
--- 通过名字检索获取玩家是否存在对应私人牌堆。
|
||||
--- 通过名字检索获取玩家对应的私人牌堆。
|
||||
---@param name string @ 私人牌堆名
|
||||
function Player:getPile(name)
|
||||
return self.special_cards[name] or {}
|
||||
return table.simpleClone(self.special_cards[name] or {})
|
||||
end
|
||||
|
||||
--- 通过ID检索获取玩家是否存在对应私人牌堆。
|
||||
--- 通过ID检索获取玩家对应的私人牌堆。
|
||||
---@param id integer @ 私人牌堆ID
|
||||
---@return string?
|
||||
function Player:getPileNameOfId(id)
|
||||
|
|
|
@ -27,7 +27,7 @@ end
|
|||
--- Determine whether the skill can be used in playing phase
|
||||
---@param player Player
|
||||
---@param card Card @ helper
|
||||
function ActiveSkill:canUse(player, card)
|
||||
function ActiveSkill:canUse(player, card, extra_data)
|
||||
return self:isEffectable(player)
|
||||
end
|
||||
|
||||
|
@ -45,8 +45,9 @@ end
|
|||
---@param to_select integer @ id of the target
|
||||
---@param selected integer[] @ ids of selected targets
|
||||
---@param selected_cards integer[] @ ids of selected cards
|
||||
---@param extra_data any @ extra_data
|
||||
---@param card Card @ helper
|
||||
function ActiveSkill:targetFilter(to_select, selected, selected_cards, card)
|
||||
function ActiveSkill:targetFilter(to_select, selected, selected_cards, card, extra_data)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -142,6 +143,35 @@ function ActiveSkill:getDistanceLimit(player, card, to)
|
|||
return ret
|
||||
end
|
||||
|
||||
function ActiveSkill:withinDistanceLimit(player, isattack, card, to)
|
||||
if to and to.dead then return false end
|
||||
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable
|
||||
if not card and self.name:endsWith("_skill") then
|
||||
card = Fk:cloneCard(self.name:sub(1, #self.name - 6))
|
||||
end
|
||||
for _, skill in ipairs(status_skills) do
|
||||
if skill:bypassDistancesCheck(player, self, card, to) then return true end
|
||||
end
|
||||
|
||||
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
||||
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
||||
table.insert(temp_suf, 1, "")
|
||||
table.insert(temp_suf, "-tmp")
|
||||
table.insert(card_temp_suf, 1, "")
|
||||
|
||||
return (isattack and player:inMyAttackRange(to)) or
|
||||
(player:distanceTo(to) > 0 and player:distanceTo(to) <= self:getDistanceLimit(player, card, to)) or
|
||||
(card and table.find(card_temp_suf, function(s)
|
||||
return card:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
||||
end)) or
|
||||
(table.find(temp_suf, function(s)
|
||||
return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
||||
end)) or
|
||||
(to and (table.find(temp_suf, function(s)
|
||||
return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0
|
||||
end)))
|
||||
end
|
||||
|
||||
--- Determine if selected cards and targets are valid for this skill
|
||||
--- If returns true, the OK button should be enabled
|
||||
--- only used in skill of players
|
||||
|
|
|
@ -35,41 +35,24 @@ function UsableSkill:withinTimesLimit(player, scope, card, card_name, to)
|
|||
for _, skill in ipairs(status_skills) do
|
||||
if skill:bypassTimesCheck(player, self, scope, card, to) then return true end
|
||||
end
|
||||
|
||||
card_name = card_name or card.trueName
|
||||
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
||||
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
||||
table.insert(temp_suf, 1, "")
|
||||
table.insert(temp_suf, "-tmp")
|
||||
table.insert(card_temp_suf, 1, "")
|
||||
|
||||
return player:usedCardTimes(card_name, scope) < self:getMaxUseTime(player, scope, card, to) or
|
||||
(player:getMark(MarkEnum.BypassTimesLimit) ~= 0 or
|
||||
table.find(temp_suf, function(s)
|
||||
(card and table.find(card_temp_suf, function(s)
|
||||
return card:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
||||
end)) or
|
||||
(table.find(temp_suf, function(s)
|
||||
return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
||||
end)) or
|
||||
(to and (to:getMark(MarkEnum.BypassTimesLimitTo) ~= 0 or
|
||||
table.find(temp_suf, function(s)
|
||||
(to and (table.find(temp_suf, function(s)
|
||||
return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0
|
||||
end)))
|
||||
end
|
||||
|
||||
function UsableSkill:withinDistanceLimit(player, isattack, card, to)
|
||||
if to and to.dead then return false end
|
||||
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable
|
||||
if not card and self.name:endsWith("_skill") then
|
||||
card = Fk:cloneCard(self.name:sub(1, #self.name - 6))
|
||||
end
|
||||
for _, skill in ipairs(status_skills) do
|
||||
if skill:bypassDistancesCheck(player, self, card, to) then return true end
|
||||
end
|
||||
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
||||
table.insert(temp_suf, "-tmp")
|
||||
return (isattack and player:inMyAttackRange(to)) or
|
||||
(player:distanceTo(to) > 0 and player:distanceTo(to) <= self:getDistanceLimit(player, card, to)) or
|
||||
(player:getMark(MarkEnum.BypassDistancesLimit) ~= 0 or
|
||||
table.find(temp_suf, function(s)
|
||||
return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
||||
end)) or
|
||||
(to and (to:getMark(MarkEnum.BypassDistancesLimitTo) ~= 0 or
|
||||
table.find(temp_suf, function(s)
|
||||
return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0
|
||||
end)))
|
||||
end
|
||||
|
||||
return UsableSkill
|
||||
|
|
|
@ -170,9 +170,9 @@ function fk.CreateTriggerSkill(spec)
|
|||
end
|
||||
|
||||
---@class ActiveSkillSpec: UsableSkillSpec
|
||||
---@field public can_use? fun(self: ActiveSkill, player: Player, card: Card): boolean?
|
||||
---@field public can_use? fun(self: ActiveSkill, player: Player, card: Card, extra_data: any): boolean?
|
||||
---@field public card_filter? fun(self: ActiveSkill, to_select: integer, selected: integer[], selected_targets: integer[]): boolean?
|
||||
---@field public target_filter? fun(self: ActiveSkill, to_select: integer, selected: integer[], selected_cards: integer[], card: Card): boolean?
|
||||
---@field public target_filter? fun(self: ActiveSkill, to_select: integer, selected: integer[], selected_cards: integer[], card: Card, extra_data: any): boolean?
|
||||
---@field public feasible? fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): boolean?
|
||||
---@field public on_use? fun(self: ActiveSkill, room: Room, cardUseEvent: CardUseStruct): boolean?
|
||||
---@field public about_to_effect? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
||||
|
|
|
@ -27,6 +27,7 @@ function RandomAI:useActiveSkill(skill, card)
|
|||
-- local max = skill:getMaxTargetNum(player, card)
|
||||
-- local min_card = skill:getMinCardNum()
|
||||
-- local max_card = skill:getMaxCardNum()
|
||||
-- FIXME: ViewAsSkill can be buggy here
|
||||
for _ = 0, max_try_times do
|
||||
if skill:feasible(selected_targets, selected_cards, self.player, card) then break end
|
||||
local avail_targets = table.filter(room:getAlivePlayers(), function(p)
|
||||
|
@ -121,6 +122,9 @@ random_cb["AskForUseActiveSkill"] = function(self, jsonData)
|
|||
for k, v in pairs(extra_data) do
|
||||
skill[k] = v
|
||||
end
|
||||
if skill:isInstanceOf(ViewAsSkill) then
|
||||
return RandomAI.useVSSkill(skill)
|
||||
end
|
||||
return RandomAI.useActiveSkill(self, skill)
|
||||
end
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ GameEvent.functions[GameEvent.ChangeProperty] = function(self)
|
|||
|
||||
if data.general and data.general ~= "" and data.general ~= player.general then
|
||||
local originalGeneral = Fk.generals[player.general] or Fk.generals["blank_shibing"]
|
||||
local originalSkills = originalGeneral and originalGeneral:getSkillNameList() or Util.DummyTable
|
||||
local originalSkills = originalGeneral and originalGeneral:getSkillNameList(true) or Util.DummyTable
|
||||
table.insertTableIfNeed(skills, table.map(originalSkills, function(e)
|
||||
return "-" .. e
|
||||
end))
|
||||
local newGeneral = Fk.generals[data.general] or Fk.generals["blank_shibing"]
|
||||
for _, name in ipairs(newGeneral:getSkillNameList()) do
|
||||
for _, name in ipairs(newGeneral:getSkillNameList(data.isLord)) do
|
||||
local s = Fk.skills[name]
|
||||
if not s.relate_to_place or s.relate_to_place == "m" then
|
||||
table.insertIfNeed(skills, name)
|
||||
|
@ -45,14 +45,14 @@ GameEvent.functions[GameEvent.ChangeProperty] = function(self)
|
|||
|
||||
if data.deputyGeneral and data.deputyGeneral ~= player.deputyGeneral then
|
||||
local originalDeputy = Fk.generals[player.deputyGeneral] or Fk.generals["blank_shibing"]
|
||||
local originalSkills = originalDeputy and originalDeputy:getSkillNameList() or Util.DummyTable
|
||||
local originalSkills = originalDeputy and originalDeputy:getSkillNameList(true) or Util.DummyTable
|
||||
table.insertTableIfNeed(skills, table.map(originalSkills, function(e)
|
||||
return "-" .. e
|
||||
end))
|
||||
|
||||
if data.deputyGeneral ~= "" then
|
||||
local newDeputy = Fk.generals[data.deputyGeneral] or Fk.generals["blank_shibing"]
|
||||
for _, name in ipairs(newDeputy:getSkillNameList()) do
|
||||
for _, name in ipairs(newDeputy:getSkillNameList(data.isLord)) do
|
||||
local s = Fk.skills[name]
|
||||
if not s.relate_to_place or s.relate_to_place == "d" then
|
||||
table.insertIfNeed(skills, name)
|
||||
|
|
|
@ -85,10 +85,10 @@ end
|
|||
function GameEvent:findParent(eventType, includeSelf)
|
||||
if includeSelf and self.event == eventType then return self end
|
||||
local e = self.parent
|
||||
repeat
|
||||
while e do
|
||||
if e.event == eventType then return e end
|
||||
e = e.parent
|
||||
until not e
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
|
|
@ -218,6 +218,10 @@ function GameLogic:attachSkillToPlayers()
|
|||
|
||||
local addRoleModSkills = function(player, skillName)
|
||||
local skill = Fk.skills[skillName]
|
||||
if not skill then
|
||||
fk.qCritical("Skill: "..skillName.." doesn't exist!")
|
||||
return
|
||||
end
|
||||
if skill.lordSkill and (player.role ~= "lord" or #room.players < 5) then
|
||||
return
|
||||
end
|
||||
|
|
|
@ -1035,7 +1035,7 @@ function Room:notifySkillInvoked(player, skill_name, skill_type)
|
|||
self:doAnimate("InvokeUltSkill", {
|
||||
name = skill_name,
|
||||
player = player.id,
|
||||
deputy = player.deputyGeneral and player.deputyGeneral ~= "" and table.contains(Fk.generals[player.deputyGeneral]:getSkillNameList(), skill_name),
|
||||
deputy = player.deputyGeneral and player.deputyGeneral ~= "" and table.contains(Fk.generals[player.deputyGeneral]:getSkillNameList(true), skill_name),
|
||||
})
|
||||
self:delay(2000)
|
||||
end
|
||||
|
@ -1978,36 +1978,26 @@ end
|
|||
---@param event_data? CardEffectEvent @ 事件信息
|
||||
---@return CardUseStruct? @ 返回关于本次使用牌的数据,以便后续处理
|
||||
function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extra_data, event_data)
|
||||
pattern = pattern or card_name
|
||||
if event_data and (event_data.disresponsive or table.contains(event_data.disresponsiveList or Util.DummyTable, player.id)) then
|
||||
return nil
|
||||
end
|
||||
|
||||
if event_data and event_data.prohibitedCardNames and card_name then
|
||||
local splitedCardNames = card_name:split(",")
|
||||
splitedCardNames = table.filter(splitedCardNames, function(name)
|
||||
return not table.contains(event_data.prohibitedCardNames, name)
|
||||
end)
|
||||
|
||||
if #splitedCardNames == 0 then
|
||||
return nil
|
||||
if event_data and event_data.prohibitedCardNames then
|
||||
local exp = Exppattern:Parse(pattern)
|
||||
for _, matcher in ipairs(exp.matchers) do
|
||||
matcher.name = table.filter(matcher.name, function(name)
|
||||
return not table.contains(event_data.prohibitedCardNames, name)
|
||||
end)
|
||||
if #matcher.name == 0 then return nil end
|
||||
end
|
||||
|
||||
card_name = table.concat(splitedCardNames, ",")
|
||||
pattern = tostring(exp)
|
||||
end
|
||||
|
||||
if extra_data then
|
||||
if extra_data.bypass_distances then
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 1) -- FIXME: 缺少直接传入无限制的手段
|
||||
end
|
||||
if extra_data.bypass_times == nil or extra_data.bypass_times then
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 1) -- FIXME: 缺少直接传入无限制的手段
|
||||
end
|
||||
end
|
||||
local command = "AskForUseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
extra_data = extra_data or Util.DummyTable
|
||||
pattern = pattern or card_name
|
||||
prompt = prompt or ""
|
||||
|
||||
local askForUseCardData = {
|
||||
|
@ -2020,8 +2010,6 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
|
|||
self.logic:trigger(fk.AskForCardUse, player, askForUseCardData)
|
||||
|
||||
if askForUseCardData.result and type(askForUseCardData.result) == 'table' then
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
return askForUseCardData.result
|
||||
else
|
||||
local useResult
|
||||
|
@ -2036,8 +2024,6 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
|
|||
Fk.currentResponsePattern = nil
|
||||
|
||||
if result ~= "" then
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
useResult = self:handleUseCardReply(player, result)
|
||||
|
||||
if type(useResult) == "string" and useResult ~= "" then
|
||||
|
@ -2045,12 +2031,8 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
|
|||
end
|
||||
end
|
||||
until type(useResult) ~= "string"
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
return useResult
|
||||
end
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0) -- FIXME: 缺少直接传入无限制的手段
|
||||
return nil
|
||||
end
|
||||
|
||||
|
@ -3337,6 +3319,8 @@ function Room:shuffleDrawPile()
|
|||
self.discard_pile = {}
|
||||
table.shuffle(self.draw_pile)
|
||||
|
||||
self:doBroadcastNotify("UpdateDrawPile", #self.draw_pile)
|
||||
|
||||
self.logic:trigger(fk.AfterDrawPileShuffle, nil, {})
|
||||
end
|
||||
|
||||
|
|
|
@ -923,7 +923,7 @@ function ServerPlayer:revealGeneral(isDeputy, no_trigger)
|
|||
end
|
||||
|
||||
local general = Fk.generals[generalName] or Fk.generals["blank_shibing"]
|
||||
for _, s in ipairs(general:getSkillNameList()) do
|
||||
for _, s in ipairs(general:getSkillNameList(true)) do
|
||||
local skill = Fk.skills[s]
|
||||
self:loseFakeSkill(skill)
|
||||
end
|
||||
|
@ -931,7 +931,7 @@ function ServerPlayer:revealGeneral(isDeputy, no_trigger)
|
|||
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")] or Fk.generals["blank_shibing"]
|
||||
for _, sname in ipairs(other:getSkillNameList()) do
|
||||
for _, sname in ipairs(other:getSkillNameList(true)) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= (isDeputy and "m" or "d") then
|
||||
ret = false
|
||||
|
@ -1017,7 +1017,7 @@ function ServerPlayer:revealBySkillName(skill_name)
|
|||
|
||||
if main then
|
||||
if table.contains(Fk.generals[self:getMark("__heg_general")]
|
||||
:getSkillNameList(), skill_name) then
|
||||
:getSkillNameList(true), skill_name) then
|
||||
self:revealGeneral(false)
|
||||
return
|
||||
end
|
||||
|
@ -1025,7 +1025,7 @@ function ServerPlayer:revealBySkillName(skill_name)
|
|||
|
||||
if deputy then
|
||||
if table.contains(Fk.generals[self:getMark("__heg_deputy")]
|
||||
:getSkillNameList(), skill_name) then
|
||||
:getSkillNameList(true), skill_name) then
|
||||
self:revealGeneral(true)
|
||||
return
|
||||
end
|
||||
|
|
|
@ -109,13 +109,13 @@ local analepticSkill = fk.CreateActiveSkill{
|
|||
prompt = "#analeptic_skill",
|
||||
max_turn_use_time = 1,
|
||||
mod_target_filter = function(self, to_select, _, _, card, _)
|
||||
return self:withinTimesLimit(Fk:currentRoom():getPlayerById(to_select), Player.HistoryTurn, card, "analeptic", Fk:currentRoom():getPlayerById(to_select)) and
|
||||
not table.find(Fk:currentRoom().alive_players, function(p)
|
||||
return p.dying
|
||||
end)
|
||||
return not table.find(Fk:currentRoom().alive_players, function(p)
|
||||
return p.dying
|
||||
end)
|
||||
end,
|
||||
can_use = function(self, player, card)
|
||||
return self:withinTimesLimit(player, Player.HistoryTurn, card, "analeptic", player)
|
||||
can_use = function(self, player, card, extra_data)
|
||||
return ((extra_data and (extra_data.bypass_times or extra_data.analepticRecover)) or
|
||||
self:withinTimesLimit(player, Player.HistoryTurn, card, "analeptic", player))
|
||||
end,
|
||||
on_use = function(_, _, use)
|
||||
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
||||
|
@ -291,8 +291,9 @@ local supplyShortageSkill = fk.CreateActiveSkill{
|
|||
local from = Fk:currentRoom():getPlayerById(user)
|
||||
return from ~= player and not (distance_limited and not self:withinDistanceLimit(from, false, card, player))
|
||||
end,
|
||||
target_filter = function(self, to_select, selected, _, card)
|
||||
return #selected == 0 and self:modTargetFilter(to_select, selected, Self.id, card, true)
|
||||
target_filter = function(self, to_select, selected, _, card, extra_data)
|
||||
local count_distances = not (extra_data and extra_data.bypass_distances)
|
||||
return #selected == 0 and self:modTargetFilter(to_select, selected, Self.id, card, count_distances)
|
||||
end,
|
||||
target_num = 1,
|
||||
on_effect = function(self, room, effect)
|
||||
|
|
|
@ -207,7 +207,7 @@ local revealProhibited = fk.CreateInvaliditySkill {
|
|||
end
|
||||
local generalName = g == "m" and from:getMark("__heg_general") or from:getMark("__heg_deputy")
|
||||
local general = Fk.generals[generalName]
|
||||
if table.contains(general:getSkillNameList(), sname) then
|
||||
if table.contains(general:getSkillNameList(true), sname) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -223,7 +223,7 @@ local revealSkill = fk.CreateActiveSkill{
|
|||
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
|
||||
for _, sname in ipairs(general:getSkillNameList(true)) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= "m" then
|
||||
table.insert(choiceList, "revealMain")
|
||||
|
@ -233,7 +233,7 @@ local revealSkill = fk.CreateActiveSkill{
|
|||
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
|
||||
for _, sname in ipairs(general:getSkillNameList(true)) do
|
||||
local s = Fk.skills[sname]
|
||||
if s.frequency == Skill.Compulsory and s.relate_to_place ~= "d" then
|
||||
table.insert(choiceList, "revealDeputy")
|
||||
|
|
|
@ -53,7 +53,7 @@ GameRule = fk.CreateTriggerSkill{
|
|||
end)
|
||||
if #cardNames == 0 then return end
|
||||
|
||||
local peach_use = room:askForUseCard(player, "peach", table.concat(cardNames, ",") , prompt)
|
||||
local peach_use = room:askForUseCard(player, "peach", table.concat(cardNames, ",") , prompt, true, {analepticRecover = true})
|
||||
if not peach_use then break end
|
||||
peach_use.tos = { {dyingPlayer.id} }
|
||||
if peach_use.card.trueName == "analeptic" then
|
||||
|
|
|
@ -1172,6 +1172,56 @@ local role_getlogic = function()
|
|||
room:broadcastProperty(lord, "kingdom")
|
||||
room:setDeputyGeneral(lord, deputy)
|
||||
room:broadcastProperty(lord, "deputyGeneral")
|
||||
|
||||
-- 显示技能
|
||||
local canAttachSkill = function(player, skillName)
|
||||
local skill = Fk.skills[skillName]
|
||||
if not skill then
|
||||
fk.qCritical("Skill: "..skillName.." doesn't exist!")
|
||||
return false
|
||||
end
|
||||
if skill.lordSkill and (player.role ~= "lord" or #room.players < 5) then
|
||||
return false
|
||||
end
|
||||
|
||||
if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local lord_skills = {}
|
||||
for _, s in ipairs(Fk.generals[lord.general].skills) do
|
||||
if canAttachSkill(lord, s.name) then
|
||||
table.insertIfNeed(lord_skills, s.name)
|
||||
end
|
||||
end
|
||||
for _, sname in ipairs(Fk.generals[lord.general].other_skills) do
|
||||
if canAttachSkill(lord, sname) then
|
||||
table.insertIfNeed(lord_skills, sname)
|
||||
end
|
||||
end
|
||||
|
||||
local deputyGeneral = Fk.generals[lord.deputyGeneral]
|
||||
if deputyGeneral then
|
||||
for _, s in ipairs(deputyGeneral.skills) do
|
||||
if canAttachSkill(lord, s.name) then
|
||||
table.insertIfNeed(lord_skills, s.name)
|
||||
end
|
||||
end
|
||||
for _, sname in ipairs(deputyGeneral.other_skills) do
|
||||
if canAttachSkill(lord, sname) then
|
||||
table.insertIfNeed(lord_skills, sname)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, skill in ipairs(lord_skills) do
|
||||
room:doBroadcastNotify("AddSkill", json.encode{
|
||||
lord.id,
|
||||
skill
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local nonlord = room:getOtherPlayers(lord, true)
|
||||
|
|
|
@ -20,8 +20,8 @@ local slashSkill = fk.CreateActiveSkill{
|
|||
end,
|
||||
max_phase_use_time = 1,
|
||||
target_num = 1,
|
||||
can_use = function(self, player, card)
|
||||
return
|
||||
can_use = function(self, player, card, extra_data)
|
||||
return (extra_data and extra_data.bypass_times) or
|
||||
table.find(Fk:currentRoom().alive_players, function(p)
|
||||
return self:withinTimesLimit(player, Player.HistoryPhase, card, "slash", p)
|
||||
end)
|
||||
|
@ -31,11 +31,12 @@ local slashSkill = fk.CreateActiveSkill{
|
|||
local from = Fk:currentRoom():getPlayerById(user)
|
||||
return from ~= player and not (distance_limited and not self:withinDistanceLimit(from, true, card, player))
|
||||
end,
|
||||
target_filter = function(self, to_select, selected, _, card)
|
||||
target_filter = function(self, to_select, selected, _, card, extra_data)
|
||||
local count_distances = not (extra_data and extra_data.bypass_distances)
|
||||
if #selected < self:getMaxTargetNum(Self, card) then
|
||||
local player = Fk:currentRoom():getPlayerById(to_select)
|
||||
return self:modTargetFilter(to_select, selected, Self.id, card, true) and
|
||||
(#selected > 0 or self:withinTimesLimit(Self, Player.HistoryPhase, card, "slash", player))
|
||||
return self:modTargetFilter(to_select, selected, Self.id, card, count_distances) and
|
||||
(#selected > 0 or (extra_data and extra_data.bypass_times) or self:withinTimesLimit(Self, Player.HistoryPhase, card, "slash", player))
|
||||
end
|
||||
end,
|
||||
on_effect = function(self, room, effect)
|
||||
|
@ -229,9 +230,10 @@ local snatchSkill = fk.CreateActiveSkill{
|
|||
local from = Fk:currentRoom():getPlayerById(user)
|
||||
return from ~= player and not (player:isAllNude() or (distance_limited and not self:withinDistanceLimit(from, false, card, player)))
|
||||
end,
|
||||
target_filter = function(self, to_select, selected, _, card)
|
||||
target_filter = function(self, to_select, selected, _, card, extra_data)
|
||||
local count_distances = not (extra_data and extra_data.bypass_distances)
|
||||
if #selected < self:getMaxTargetNum(Self, card) then
|
||||
return self:modTargetFilter(to_select, selected, Self.id, card, true)
|
||||
return self:modTargetFilter(to_select, selected, Self.id, card, count_distances)
|
||||
end
|
||||
end,
|
||||
target_num = 1,
|
||||
|
|
|
@ -90,6 +90,8 @@ local control = fk.CreateActiveSkill{
|
|||
-- room:setPlayerMark(from, "@$b", {'slash','duel','axe'})
|
||||
--room:askForMiniGame({from}, "test", "test", { [from.id] = {"Helloworld"} })
|
||||
--print(from.client_reply)
|
||||
-- p(Fk.generals[to.general]:getSkillNameList())
|
||||
-- p(Fk.generals[to.general]:getSkillNameList(true))
|
||||
if to:getMark("mouxushengcontrolled") == 0 then
|
||||
room:addPlayerMark(to, "mouxushengcontrolled")
|
||||
from:control(to)
|
||||
|
@ -412,6 +414,11 @@ Fk:loadTranslationTable{
|
|||
["$change_hero"] = "敌军色厉内荏,可筑假城以退敌!",
|
||||
|
||||
["~mouxusheng"] = "来世,愿再为我江东之臣……",
|
||||
|
||||
["heal_hp"] = "回复体力",
|
||||
["lose_max_hp"] = "减少体力上限",
|
||||
["heal_max_hp"] = "增加体力上限",
|
||||
["revive"] = "复活",
|
||||
}
|
||||
|
||||
return { extension }
|
||||
|
|
Loading…
Reference in New Issue
Block a user