diff --git a/scripts/commandHandler.lua b/scripts/commandHandler.lua index b5bfb959..70c44605 100644 --- a/scripts/commandHandler.lua +++ b/scripts/commandHandler.lua @@ -731,7 +731,7 @@ function commandHandler.ProcessCommand(pid, cmd) end end - elseif cmd[1] == "resetkills" and moderator then + elseif cmd[1] == "resetkills" and moderator and config.shareKills == true then -- Set all currently recorded kills to 0 for connected players for refId, killCount in pairs(WorldInstance.data.kills) do @@ -741,7 +741,21 @@ function commandHandler.ProcessCommand(pid, cmd) WorldInstance:QuicksaveToDrive() WorldInstance:LoadKills(pid, true) tes3mp.SendMessage(pid, "All the kill counts for creatures and NPCs have been reset.\n", true) + + elseif cmd[1] == "resetkills" and config.shareKills == false then + + if Players[pid].data.kills == nil then + Players[pid].data.kills = {} + end + -- Set all currently recorded kills to 0 for players + for refId, killCount in pairs(Players[pid].data.kills) do + Players[pid].data.kills[refId] = 0 + end + Players[pid]:QuicksaveToDrive() + Players[pid]:LoadKills(pid, false) + tes3mp.SendMessage(pid, "All the kill counts for creatures and NPCs have been reset.\n", false) + elseif cmd[1] == "suicide" then if config.allowSuicideCommand == true then tes3mp.SetHealthCurrent(pid, 0) diff --git a/scripts/config.lua b/scripts/config.lua index 723b59df..0e5fafdd 100644 --- a/scripts/config.lua +++ b/scripts/config.lua @@ -115,6 +115,9 @@ config.shareMapExploration = false -- Whether ingame videos should be played for other players when triggered by one player config.shareVideos = true +-- Whether mobs and npcs in the game should be shared for all players when killed +config.shareKills = true + -- Which clientside script records should be blanked out so they are not run -- Note: By default, the original character generation scripts are included -- because they're not suitable for multiplayer @@ -190,6 +193,9 @@ config.forbiddenCells = { "ToddTest" } -- The maximum value that any attribute except Speed is allowed to have config.maxAttributeValue = 200 +-- Allow modifier values to bypass allowed attribute values +config.ignoreModifierWithMaxAttribute = false + -- The maximum value that Speed is allowed to have -- Note: Speed is given special treatment because of the Boots of Blinding Speed config.maxSpeedValue = 365 diff --git a/scripts/eventHandler.lua b/scripts/eventHandler.lua index 70943b5c..8a965559 100644 --- a/scripts/eventHandler.lua +++ b/scripts/eventHandler.lua @@ -4,6 +4,8 @@ commandHandler = require("commandHandler") local consoleKickMessage = " has been kicked for using the console despite not having the permission to do so.\n" +local sendKills = {} + eventHandler.InitializeDefaultValidators = function() -- Don't validate object deletions for currently unusable containers (such as @@ -185,20 +187,92 @@ eventHandler.InitializeDefaultHandlers = function() local cell = LoadedCells[cellDescription] tes3mp.ClearKillChanges() - - for uniqueIndex, actor in pairs(actors) do - if WorldInstance.data.kills[actor.refId] == nil then - WorldInstance.data.kills[actor.refId] = 0 - end - - WorldInstance.data.kills[actor.refId] = WorldInstance.data.kills[actor.refId] + 1 - WorldInstance:QuicksaveToDrive() - tes3mp.AddKill(actor.refId, WorldInstance.data.kills[actor.refId]) - - table.insert(cell.unusableContainerUniqueIndexes, uniqueIndex) - end - - tes3mp.SendWorldKillCount(pid, true) + + if config.shareKills == true then + + for uniqueIndex, actor in pairs(actors) do + if WorldInstance.data.kills[actor.refId] == nil then + WorldInstance.data.kills[actor.refId] = 0 + end + + WorldInstance.data.kills[actor.refId] = WorldInstance.data.kills[actor.refId] + 1 + WorldInstance:QuicksaveToDrive() + tes3mp.AddKill(actor.refId, WorldInstance.data.kills[actor.refId]) + + table.insert(cell.unusableContainerUniqueIndexes, uniqueIndex) + end + + tes3mp.SendWorldKillCount(pid, true) + + else + + if Players[pid].data.kills == nil then + Players[pid].data.kills = {} + end + + for uniqueIndex, actor in pairs(actors) do + + if Players[pid].data.kills[actor.refId] == nil then + Players[pid].data.kills[actor.refId] = 0 + end + + Players[pid].data.kills[actor.refId] = Players[pid].data.kills[actor.refId] + 1 + Players[pid]:QuicksaveToDrive() + + if sendKills[uniqueIndex] == nil then + sendKills[uniqueIndex] = {timestamp = os.time(), playersName = {}} + end + tableHelper.insertValueIfMissing(sendKills[uniqueIndex].playersName, string.lower(Players[pid].accountName)) + + tes3mp.AddKill(actor.refId, Players[pid].data.kills[actor.refId]) + + for _, alliedName in ipairs(Players[pid].data.alliedPlayers) do + + if logicHandler.GetPlayerByName(alliedName) then + + local alliedPid = logicHandler.GetPlayerByName(alliedName).pid + + if Players[alliedPid] ~= nil and Players[alliedPid]:IsLoggedIn() then + + if Players[alliedPid].data.kills == nil then + Players[alliedPid].data.kills = {} + end + + if Players[alliedPid].data.kills[actor.refId] == nil then + Players[alliedPid].data.kills[actor.refId] = 0 + end + + Players[alliedPid].data.kills[actor.refId] = Players[alliedPid].data.kills[actor.refId] + 1 + Players[alliedPid]:QuicksaveToDrive() + tableHelper.insertValueIfMissing(sendKills[uniqueIndex].playersName, string.lower(Players[alliedPid].accountName)) + + end + + end + + end + + table.insert(cell.unusableContainerUniqueIndexes, uniqueIndex) + + end + + for targetIndex, actor in pairs(actors) do + + for _, targetName in ipairs(sendKills[targetIndex].playersName) do + + local targetPid = logicHandler.GetPlayerByName(targetName).pid + + if Players[targetPid] ~= nil and Players[targetPid]:IsLoggedIn() then + tes3mp.SendWorldKillCount(targetPid, false) + end + + end + + sendKills[targetIndex] = nil + + end + + end cell:RequestContainers(pid, tableHelper.getArrayFromIndexes(actors)) end) @@ -321,6 +395,23 @@ eventHandler.InitializeDefaultHandlers = function() if object.hit.success == true then debugMessage = debugMessage .. " has successfully hit " + + if config.shareKills == false and object.hittingPid ~= nil then + + if sendKills[uniqueIndex] == nil then + sendKills[uniqueIndex] = {timestamp = os.time(), playersName = {}} + else + if os.time() - sendKills[uniqueIndex].timestamp >= 600 then + sendKills[uniqueIndex] = {timestamp = os.time(), playersName = {}} + else + sendKills[uniqueIndex].timestamp = os.time() + end + end + + tableHelper.insertValueIfMissing(sendKills[uniqueIndex].playersName, string.lower(Players[object.hittingPid].accountName)) + + end + else debugMessage = debugMessage .. " has missed hitting " end diff --git a/scripts/player/base.lua b/scripts/player/base.lua index 1e149e1d..9c63e3c6 100644 --- a/scripts/player/base.lua +++ b/scripts/player/base.lua @@ -284,7 +284,11 @@ function BasePlayer:FinishLogin() self:LoadReputation() end - WorldInstance:LoadKills(self.pid) + if config.shareKills == true then + WorldInstance:LoadKills(self.pid) + else + self:LoadKills(self.pid, false) + end self:LoadSpecialStates() @@ -376,7 +380,11 @@ function BasePlayer:EndCharGen() WorldInstance:LoadTopics(self.pid) end - WorldInstance:LoadKills(self.pid) + if config.shareKills == true then + WorldInstance:LoadKills(self.pid) + else + self:LoadKills(self.pid, false) + end if spawnUsed ~= nil and spawnUsed.cellDescription ~= nil then tes3mp.SetCell(self.pid, spawnUsed.cellDescription) @@ -831,7 +839,7 @@ function BasePlayer:SaveAttributes(playerPacket) local message = "Your base " .. attributeName .. " has exceeded the maximum allowed value " .. "and been reset to its last recorded one.\n" tes3mp.SendMessage(self.pid, message) - elseif (attribute.base + attribute.modifier) > maxAttributeValue then + elseif (attribute.base + attribute.modifier) > maxAttributeValue and not config.ignoreModifierWithMaxAttribute then tes3mp.ClearAttributeModifier(self.pid, attributeId) tes3mp.SendAttributes(self.pid) @@ -1485,6 +1493,21 @@ function BasePlayer:SaveClientScriptGlobal(variables) stateHelper:SaveClientScriptGlobal(self, variables) end +function BasePlayer:LoadKills(pid, forEveryone) + + if self.data.kills == nil then + self.data.kills = {} + end + + tes3mp.ClearKillChanges() + + for refId, killCount in pairs(self.data.kills) do + tes3mp.AddKill(refId, killCount) + end + + tes3mp.SendWorldKillCount(pid, forEveryone) +end + function BasePlayer:LoadDestinationOverrides(pid) stateHelper:LoadDestinationOverrides(self.pid, self) end