add GGS Support
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
local OFGGSCasingDisablePatch = {
|
||||
patched = false,
|
||||
hasDebugStackInfo = type(debug) == "table" and type(debug.getinfo) == "function",
|
||||
}
|
||||
|
||||
local BLOCKED_GGS_CASING_TYPES = {
|
||||
["Base.pistol_casing"] = true,
|
||||
["Base.revolver_casing"] = true,
|
||||
["Base.rifle_casing"] = true,
|
||||
["Base.shells_casing"] = true,
|
||||
}
|
||||
|
||||
local function isGgsShellEmitterCall()
|
||||
if not OFGGSCasingDisablePatch.hasDebugStackInfo then
|
||||
return false
|
||||
end
|
||||
|
||||
for stackLevel = 3, 10 do
|
||||
local info = debug.getinfo(stackLevel, "S")
|
||||
if not info then
|
||||
break
|
||||
end
|
||||
|
||||
local source = info.source
|
||||
if type(source) == "string" and string.find(source, "GGS_ShellCasingEmitter.lua", 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function isPatchToggleEnabled()
|
||||
local vars = SandboxVars and SandboxVars.OpinionatedFirearms
|
||||
if vars and vars.HandleHotBrassCasingSpawnUseAmmoMaker ~= nil then
|
||||
return vars.HandleHotBrassCasingSpawnUseAmmoMaker == true
|
||||
end
|
||||
|
||||
-- Backward compatibility for existing worlds.
|
||||
if vars and vars.HBVCEFAmmoMakerPatch ~= nil then
|
||||
return vars.HBVCEFAmmoMakerPatch == true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function applyPatch()
|
||||
if OFGGSCasingDisablePatch.patched then
|
||||
return true
|
||||
end
|
||||
|
||||
if not isPatchToggleEnabled() then
|
||||
OFGGSCasingDisablePatch.patched = true
|
||||
return true
|
||||
end
|
||||
|
||||
if type(__classmetatables) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
if not zombie or not zombie.iso or not zombie.iso.IsoGridSquare or not zombie.iso.IsoGridSquare.class then
|
||||
return false
|
||||
end
|
||||
|
||||
local squareMetatable = __classmetatables[zombie.iso.IsoGridSquare.class]
|
||||
if not squareMetatable or type(squareMetatable.__index) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
local originalAddWorldInventoryItem = squareMetatable.__index.AddWorldInventoryItem
|
||||
if type(originalAddWorldInventoryItem) ~= "function" then
|
||||
return false
|
||||
end
|
||||
|
||||
squareMetatable.__index.AddWorldInventoryItem = function(square, itemType, ...)
|
||||
if BLOCKED_GGS_CASING_TYPES[itemType] and
|
||||
(not OFGGSCasingDisablePatch.hasDebugStackInfo or isGgsShellEmitterCall())
|
||||
then
|
||||
return nil
|
||||
end
|
||||
|
||||
return originalAddWorldInventoryItem(square, itemType, ...)
|
||||
end
|
||||
|
||||
OFGGSCasingDisablePatch.patched = true
|
||||
return true
|
||||
end
|
||||
|
||||
local function tryPatchOnTick()
|
||||
if applyPatch() then
|
||||
Events.OnTick.Remove(tryPatchOnTick)
|
||||
end
|
||||
end
|
||||
|
||||
if not applyPatch() then
|
||||
Events.OnTick.Add(tryPatchOnTick)
|
||||
end
|
||||
@@ -2,8 +2,24 @@ local OFHotBrassPatch = {
|
||||
patched = false,
|
||||
}
|
||||
|
||||
local AMMO_TYPE_ALIAS_BY_ITEM = {
|
||||
["Base.9x39Bullets"] = "9x39",
|
||||
["Base.Bullets22LR"] = "22LR",
|
||||
["Base.Bullets50Magnum"] = "50AE",
|
||||
["Base.762x54rBullets"] = "762x54R",
|
||||
["Base.792x57Bullets"] = "792x57Maus",
|
||||
-- Common spelling variants seen in third-party weapon scripts.
|
||||
["Base.308Bulets"] = "308Win",
|
||||
["Base.762x54rBulets"] = "762x54R",
|
||||
}
|
||||
|
||||
local function isPatchToggleEnabled()
|
||||
local vars = SandboxVars and SandboxVars.OpinionatedFirearms
|
||||
if vars and vars.HandleHotBrassCasingSpawnUseAmmoMaker ~= nil then
|
||||
return vars.HandleHotBrassCasingSpawnUseAmmoMaker == true
|
||||
end
|
||||
|
||||
-- Backward compatibility for existing worlds.
|
||||
if vars and vars.HBVCEFAmmoMakerPatch ~= nil then
|
||||
return vars.HBVCEFAmmoMakerPatch == true
|
||||
end
|
||||
@@ -15,92 +31,123 @@ local function isSessionEligible()
|
||||
return isPatchToggleEnabled()
|
||||
end
|
||||
|
||||
local function getAmmoMakerFiredFromAmmoDataKey(ammoDataKey)
|
||||
if type(ammoDataKey) ~= "string" or ammoDataKey == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
if type(ammoMakerAmmoData) ~= "table" or type(ammoMakerAmmoParts) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local ammoData = ammoMakerAmmoData[ammoDataKey]
|
||||
if type(ammoData) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local casingType = ammoData.casingType
|
||||
if type(casingType) ~= "string" or casingType == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local partData = ammoMakerAmmoParts[casingType]
|
||||
if type(partData) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local firedType = partData.partFired or partData.partOld
|
||||
if type(firedType) ~= "string" or firedType == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
return firedType
|
||||
end
|
||||
|
||||
local function getAmmoMakerFiredFromItemKey(ammoType)
|
||||
if type(ammoType) ~= "string" or ammoType == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
if type(ammoMakerAmmoTypes) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local typeData = ammoMakerAmmoTypes[ammoType]
|
||||
if type(typeData) ~= "table" or type(typeData.ammoTypes) ~= "table" or #typeData.ammoTypes == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local activeIndex = 1
|
||||
if type(typeData.modIds) == "table" and type(ammoMakerCompatibleMods) == "table" then
|
||||
for i = 1, #typeData.modIds do
|
||||
local modId = typeData.modIds[i]
|
||||
if ammoMakerCompatibleMods[modId] == true then
|
||||
activeIndex = i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if activeIndex < 1 or activeIndex > #typeData.ammoTypes then
|
||||
activeIndex = 1
|
||||
end
|
||||
|
||||
local activeAmmoKey = typeData.ammoTypes[activeIndex]
|
||||
local activeFiredType = getAmmoMakerFiredFromAmmoDataKey(activeAmmoKey)
|
||||
if activeFiredType then
|
||||
return activeFiredType
|
||||
end
|
||||
|
||||
for i = 1, #typeData.ammoTypes do
|
||||
local fallbackFiredType = getAmmoMakerFiredFromAmmoDataKey(typeData.ammoTypes[i])
|
||||
if fallbackFiredType then
|
||||
return fallbackFiredType
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function getAmmoMakerFiredCasing(ammoType)
|
||||
if type(ammoType) ~= "string" or ammoType == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local function getAmmoTypeData()
|
||||
if type(ammoMakerAmmoTypes) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local data = ammoMakerAmmoTypes[ammoType]
|
||||
if type(data) ~= "table" or type(data.ammoTypes) ~= "table" or #data.ammoTypes == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return data
|
||||
local directFiredType = getAmmoMakerFiredFromItemKey(ammoType)
|
||||
if directFiredType then
|
||||
return directFiredType
|
||||
end
|
||||
|
||||
local function getActiveAmmoData(typeData)
|
||||
if type(typeData) ~= "table" or type(typeData.ammoTypes) ~= "table" or type(ammoMakerAmmoData) ~= "table" then
|
||||
return nil
|
||||
local aliasAmmoDataKey = AMMO_TYPE_ALIAS_BY_ITEM[ammoType]
|
||||
if aliasAmmoDataKey then
|
||||
local aliasFiredType = getAmmoMakerFiredFromAmmoDataKey(aliasAmmoDataKey)
|
||||
if aliasFiredType then
|
||||
return aliasFiredType
|
||||
end
|
||||
end
|
||||
|
||||
local activeIndex = 1
|
||||
if type(typeData.modIds) == "table" and type(ammoMakerCompatibleMods) == "table" then
|
||||
for i = 1, #typeData.modIds do
|
||||
local modId = typeData.modIds[i]
|
||||
if ammoMakerCompatibleMods[modId] == true then
|
||||
activeIndex = i
|
||||
local lowerAmmoType = string.lower(ammoType)
|
||||
for aliasItemType, ammoDataKey in pairs(AMMO_TYPE_ALIAS_BY_ITEM) do
|
||||
if string.lower(aliasItemType) == lowerAmmoType then
|
||||
local aliasFiredType = getAmmoMakerFiredFromAmmoDataKey(ammoDataKey)
|
||||
if aliasFiredType then
|
||||
return aliasFiredType
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if type(ammoMakerAmmoTypes) == "table" then
|
||||
for itemType, typeData in pairs(ammoMakerAmmoTypes) do
|
||||
if type(itemType) == "string" and string.lower(itemType) == lowerAmmoType then
|
||||
if type(typeData) == "table" and type(typeData.ammoTypes) == "table" then
|
||||
for i = 1, #typeData.ammoTypes do
|
||||
local fallbackFiredType = getAmmoMakerFiredFromAmmoDataKey(typeData.ammoTypes[i])
|
||||
if fallbackFiredType then
|
||||
return fallbackFiredType
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if activeIndex < 1 or activeIndex > #typeData.ammoTypes then
|
||||
activeIndex = 1
|
||||
end
|
||||
|
||||
local activeAmmoKey = typeData.ammoTypes[activeIndex]
|
||||
if type(activeAmmoKey) == "string" then
|
||||
local activeAmmoData = ammoMakerAmmoData[activeAmmoKey]
|
||||
if type(activeAmmoData) == "table" then
|
||||
return activeAmmoData
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #typeData.ammoTypes do
|
||||
local ammoKey = typeData.ammoTypes[i]
|
||||
if type(ammoKey) == "string" then
|
||||
local ammoData = ammoMakerAmmoData[ammoKey]
|
||||
if type(ammoData) == "table" then
|
||||
return ammoData
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function partDataToFiredType(partData)
|
||||
if type(partData) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local firedType = partData.partFired or partData.partOld
|
||||
if type(firedType) ~= "string" or firedType == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
return firedType
|
||||
end
|
||||
|
||||
if type(ammoMakerAmmoParts) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local ammoTypeData = getAmmoTypeData()
|
||||
if not ammoTypeData then
|
||||
return nil
|
||||
end
|
||||
|
||||
local ammoData = getActiveAmmoData(ammoTypeData)
|
||||
if type(ammoData) == "table" and type(ammoData.casingType) == "string" then
|
||||
local firedType = partDataToFiredType(ammoMakerAmmoParts[ammoData.casingType])
|
||||
if firedType then
|
||||
return firedType
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
@@ -141,7 +188,8 @@ local function applyPatch()
|
||||
|
||||
SpentCasingPhysics.doSpawnCasing = function(player, weapon, params, racking, optionalItem)
|
||||
if not optionalItem and weapon and weapon.getAmmoType then
|
||||
local ammoType = weapon:getAmmoType()
|
||||
local ammoTypeObj = weapon:getAmmoType()
|
||||
local ammoType = ammoTypeObj and ammoTypeObj.getItemKey and ammoTypeObj:getItemKey() or ammoTypeObj
|
||||
if ammoType then
|
||||
local mappedType = getAmmoMakerFiredCasing(tostring(ammoType))
|
||||
if mappedType then
|
||||
|
||||
Reference in New Issue
Block a user