堆一堆bugfix (#218)

- 重新写了固定距离计算方法,目前按先到先得处理(以先触发的技能为准)
- 距离函数在传入死人时会返回-1,一切与此相关的函数应当返回false
- 修复了自己挖的Player:canUse
- 修复了skillTimes的变量名(嗯)
- 修复了exclusived无法过滤目标的错误

---------

Co-authored-by: notify <notify-ctrl@qq.com>
This commit is contained in:
YoumuKon 2023-07-08 01:05:54 +08:00 committed by GitHub
parent 9db9dd6c59
commit 2ab9ad017a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 25 deletions

View File

@ -485,17 +485,17 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
all_photos.forEach(photo => {
photo.state = "candidate";
const id = photo.playerid;
if (roomScene.extra_data instanceof Object) {
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) return;
}
}
const ret = JSON.parse(Backend.callLuaFunction(
"CanUseCardToTarget",
[card, id, selected_targets]
));
photo.selectable = ret;
if (roomScene.extra_data instanceof Object) {
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) photo.selectable = false;
}
}
})
okButton.enabled = JSON.parse(Backend.callLuaFunction(

View File

@ -404,12 +404,14 @@ end
---@param other Player @ 其他玩家
---@param num integer @ 距离数
function Player:setFixedDistance(other, num)
print(self.name .. ": fixedDistance is deprecated. Use fixed_func instead.")
self.fixedDistance[other] = num
end
--- 移除玩家与其他角色的固定距离。
---@param other Player @ 其他玩家
function Player:removeFixedDistance(other)
print(self.name .. ": fixedDistance is deprecated. Use fixed_func instead.")
self.fixedDistance[other] = nil
end
@ -417,23 +419,47 @@ end
---
--- 通过 二者位次+距离技能之和 与 两者间固定距离 进行对比,更大的为实际距离。
---@param other Player @ 其他玩家
function Player:distanceTo(other)
---@param mode string @ 计算模式(left/right/both)
---@param ignore_dead boolean @ 是否忽略尸体
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
print(other.name .. " is dead!")
return -1
end
local right = 0
local temp = self
while temp ~= other do
if not temp.dead then
local try_time = 10
for _ = 0, try_time do
if temp == other then break end
if ignore_dead or not temp.dead then
right = right + 1
end
temp = temp.next
end
local left = #Fk:currentRoom().alive_players - right
local ret = math.min(left, right)
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 ret = 0
if mode == "left" then
ret = left
elseif mode == "right" then
ret = right
else
ret = math.min(left, right)
end
local status_skills = Fk:currentRoom().status_skills[DistanceSkill] or Util.DummyTable
for _, skill in ipairs(status_skills) do
local fixed = skill:getFixed(self, other)
local correct = skill:getCorrect(self, other)
if fixed ~= nil then
ret = fixed
break
end
if correct == nil then correct = 0 end
ret = ret + correct
end
@ -449,7 +475,8 @@ end
---@param other Player @ 其他玩家
---@param fixLimit number|null @ 卡牌距离限制增加专用
function Player:inMyAttackRange(other, fixLimit)
if self == other then
assert(other:isInstanceOf(Player))
if self == other or (other and other.dead) then
return false
end
@ -565,12 +592,12 @@ end
--- 获取玩家使用特定技能的历史次数。
---@param skill_name string @ 技能名
---@param scope integer @ 查询历史范围
function Player:usedSkillTimes(cardName, scope)
if not self.skillUsedHistory[cardName] then
function Player:usedSkillTimes(skill_name, scope)
if not self.skillUsedHistory[skill_name] then
return 0
end
scope = scope or Player.HistoryTurn
return self.skillUsedHistory[cardName][scope]
return self.skillUsedHistory[skill_name][scope]
end
--- 获取玩家是否无手牌。
@ -729,7 +756,7 @@ end
---@param card Card @ 特定牌
function Player:canUse(card)
assert(card, "Error: No Card")
return card.skill.canUse(self, card)
return card.skill:canUse(self, card)
end
--- 确认玩家是否被禁止对特定玩家使用特定牌。

View File

@ -10,4 +10,11 @@ function DistanceSkill:getCorrect(from, to)
return 0
end
---@param from Player
---@param to Player
---@return integer
function DistanceSkill:getFixed(from, to)
return nil
end
return DistanceSkill

View File

@ -25,6 +25,7 @@ function UsableSkill:getMaxUseTime(player, scope, card, to)
end
function UsableSkill:withinTimesLimit(player, scope, card, card_name, to)
if to and to.dead then return false end
scope = scope or Player.HistoryTurn
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable
if not card and self.name:endsWith("_skill") then
@ -46,6 +47,7 @@ function UsableSkill:withinTimesLimit(player, scope, card, card_name, to)
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))

View File

@ -268,6 +268,7 @@ end
---@class DistanceSpec: StatusSkillSpec
---@field public correct_func fun(self: DistanceSkill, from: Player, to: Player)
---@field public fixed_func fun(self: DistanceSkill, from: Player, to: Player)
---@param spec DistanceSpec
---@return DistanceSkill
@ -278,6 +279,7 @@ function fk.CreateDistanceSkill(spec)
local skill = DistanceSkill:new(spec.name)
readStatusSpecToSkill(skill, spec)
skill.getCorrect = spec.correct_func
skill.getFixed = spec.fixed_func
return skill
end

View File

@ -26,8 +26,8 @@ local function useActiveSkill(self, skill, card)
local max = skill:getMaxTargetNum(player, card)
local min_card = skill:getMinCardNum()
local max_card = skill:getMaxCardNum()
while not skill:feasible(selected_targets, selected_cards, self.player, card) do
if max_try_times <= 0 then break end
for _ = 0, max_try_times do
if skill:feasible(selected_targets, selected_cards, self.player, card) then break end
local avail_targets = table.filter(self.room:getAlivePlayers(), function(p)
local ret = skill:targetFilter(p.id, selected_targets, selected_cards, card or Fk:cloneCard'zixing')
if ret and card then
@ -50,7 +50,6 @@ local function useActiveSkill(self, skill, card)
if #avail_targets == 0 and #avail_cards == 0 then break end
table.insertIfNeed(selected_targets, table.random(avail_targets))
table.insertIfNeed(selected_cards, table.random(avail_cards))
max_try_times = max_try_times - 1
end
if skill:feasible(selected_targets, selected_cards, self.player, card) then
local ret = json.encode{
@ -98,8 +97,7 @@ local function useVSSkill(self, skill, pattern, cancelable, extra_data)
local selected_cards = {}
local max_try_time = 100
while true do
if max_try_time <= 0 then break end
for _ = 0, max_try_time do
local avail_cards = table.filter(player:getCardIds{ Player.Hand, Player.Equip }, function(id)
return skill:cardFilter(id, selected_cards)
end)
@ -111,7 +109,6 @@ local function useVSSkill(self, skill, pattern, cancelable, extra_data)
subcards = selected_cards,
}
end
max_try_time = max_try_time - 1
end
return nil
end

View File

@ -73,7 +73,7 @@ GameEvent.functions[GameEvent.DrawInitial] = function(self)
for _, player in ipairs(room.alive_players) do
local draw_data = luck_data[player.id]
draw_data.luckTime = nil
room.logic:trigger(fk.AfterDrawInitialCards, player, data)
room.logic:trigger(fk.AfterDrawInitialCards, player, draw_data)
end
return
end
@ -126,7 +126,7 @@ GameEvent.functions[GameEvent.DrawInitial] = function(self)
for _, player in ipairs(room.alive_players) do
local draw_data = luck_data[player.id]
draw_data.luckTime = nil
room.logic:trigger(fk.AfterDrawInitialCards, player, data)
room.logic:trigger(fk.AfterDrawInitialCards, player, draw_data)
end
room:removeTag("LuckCardData")

View File

@ -5,6 +5,7 @@
#include <qjsonarray.h>
#include <qjsondocument.h>
#include "client.h"
#include "client_socket.h"
#include "roomthread.h"
#include "server.h"
@ -268,7 +269,7 @@ void Room::removePlayer(ServerPlayer *player) {
server->addPlayer(runner);
// 如果走小道的人不是单机启动玩家 那么直接ban
if (!runner->getSocket()->peerAddress().contains("127.0.0.1") && !player->isDied()) {
if (!ClientInstance && !player->isDied()) {
server->temporarilyBan(runner->getId());
}