diff --git a/newmodels_reborn/core/client.lua b/newmodels_reborn/core/client.lua
index db3bc49..4ba33ad 100644
--- a/newmodels_reborn/core/client.lua
+++ b/newmodels_reborn/core/client.lua
@@ -1,13 +1,13 @@
addEvent("newmodels_reborn:receiveCustomModels", true)
-local loadedModels = {}
+loadedModels = {}
-local FREE_ID_DELAY = 10000 -- ms
+local FREE_ID_DELAY = 10000 -- ms
local FREE_ID_DELAY_STEP = 500 -- ms
local currFreeIdDelay = FREE_ID_DELAY
local function applyElementCustomModel(element)
- local customModel = tonumber(getElementData(element, CUSTOM_MODEL_DATA_KEY))
+ local customModel = tonumber(getElementData(element, getCustomModelDataKey(element)))
if not customModel then return end
local loadedModel = loadedModels[customModel]
if not loadedModel then return end
@@ -19,7 +19,7 @@ local function applyElementCustomModel(element)
paintjob = getVehiclePaintjob(element)
end
- _setElementModel(element, loadedModel.id)
+ _setElementModel(element, loadedModel.id)
if upgrades then
for _, v in pairs(upgrades) do
@@ -47,7 +47,7 @@ local function loadCustomModel(customModel, elementToApply)
if not allocatedModel then return end
local colPath, txdPath, dffPath = customInfo.col, customInfo.txd, customInfo.dff
-
+
local col, txd, dff
if colPath then
col = engineLoadCOL(colPath)
@@ -58,10 +58,10 @@ local function loadCustomModel(customModel, elementToApply)
if dffPath then
dff = engineLoadDFF(dffPath)
end
-
+
if (colPath and not col)
- or (txdPath and not txd)
- or (dffPath and not dff) then
+ or (txdPath and not txd)
+ or (dffPath and not dff) then
if col and isElement(col) then destroyElement(col) end
if txd and isElement(txd) then destroyElement(txd) end
if dff and isElement(dff) then destroyElement(dff) end
@@ -70,8 +70,8 @@ local function loadCustomModel(customModel, elementToApply)
end
if (col and not engineReplaceCOL(col, allocatedModel))
- or (txd and not engineImportTXD(txd, allocatedModel))
- or (dff and not engineReplaceModel(dff, allocatedModel)) then
+ or (txd and not engineImportTXD(txd, allocatedModel))
+ or (dff and not engineReplaceModel(dff, allocatedModel)) then
if col and isElement(col) then destroyElement(col) end
if txd and isElement(txd) then destroyElement(txd) end
if dff and isElement(dff) then destroyElement(dff) end
@@ -87,15 +87,16 @@ local function loadCustomModel(customModel, elementToApply)
elseif customInfo.type == "object" then
elementTypes = { "object", "pickup" }
end
-
+
-- Set loadedModel info
loadedModels[customModel] = {
- id = allocatedModel, baseModel = customInfo.baseModel,
+ id = allocatedModel,
+ baseModel = customInfo.baseModel,
elementTypes = elementTypes,
freeAllocatedTimer = nil,
elements = { txd = txd, dff = dff, col = col }
}
-
+
if isElement(elementToApply) then
applyElementCustomModel(elementToApply)
end
@@ -105,7 +106,7 @@ local function countStreamedElementsWithCustomModel(elementTypes, customModel)
local count = 0
for _, elementType in pairs(elementTypes) do
for _, v in pairs(getElementsByType(elementType, root, true)) do
- if getElementData(v, CUSTOM_MODEL_DATA_KEY) == customModel then
+ if getElementData(v, getCustomModelDataKey(elementType)) == customModel then
count = count + 1
end
end
@@ -129,10 +130,10 @@ local function freeAllocatedModel(customModel, loadedModel)
if isElement(loadedModel.elements.col) then destroyElement(loadedModel.elements.col) end
if isElement(loadedModel.elements.txd) then destroyElement(loadedModel.elements.txd) end
if isElement(loadedModel.elements.dff) then destroyElement(loadedModel.elements.dff) end
-
+
-- Unset loadedModel info
loadedModels[customModel] = nil
-
+
currFreeIdDelay = currFreeIdDelay - FREE_ID_DELAY_STEP
end, currFreeIdDelay, 1)
end
@@ -145,19 +146,19 @@ local function freeAllocatedModelIfUnused(customModel)
end
end
-local function setElementCustomModel(veh)
- local customModel = getElementData(veh, CUSTOM_MODEL_DATA_KEY)
+local function setElementCustomModel(element)
+ local customModel = getElementData(element, getCustomModelDataKey(element))
if not customModel then return end
if not loadedModels[customModel] then
- loadCustomModel(customModel, veh)
+ loadCustomModel(customModel, element)
else
- applyElementCustomModel(veh)
+ applyElementCustomModel(element)
end
end
addEventHandler("onClientElementDataChange", root, function(key, prevCustomModel, newCustomModel)
if not isValidElement(source) then return end
- if key ~= CUSTOM_MODEL_DATA_KEY then return end
+ if key ~= getCustomModelDataKey(source) then return end
prevCustomModel = tonumber(prevCustomModel)
-- Get the base model of the previous custom model the element has
@@ -179,7 +180,6 @@ addEventHandler("onClientElementDataChange", root, function(key, prevCustomModel
setElementCustomModel(source)
end
if prevCustomModel then
-
-- Force-set the base model of the previous custom model if resetting the custom model
if (not newCustomModel) and prevLoadedModelBaseModel then
_setElementModel(source, prevLoadedModelBaseModel)
@@ -197,14 +197,14 @@ end)
addEventHandler("onClientElementStreamOut", root, function()
if not isValidElement(source) then return end
- local customModel = getElementData(source, CUSTOM_MODEL_DATA_KEY)
+ local customModel = getElementData(source, getCustomModelDataKey(source))
if not customModel then return end
freeAllocatedModelIfUnused(customModel)
end)
addEventHandler("onClientElementDestroy", root, function()
if not isValidElement(source) then return end
- local customModel = getElementData(source, CUSTOM_MODEL_DATA_KEY)
+ local customModel = getElementData(source, getCustomModelDataKey(source))
if not customModel then return end
freeAllocatedModelIfUnused(customModel)
end)
@@ -218,3 +218,18 @@ addEventHandler("newmodels_reborn:receiveCustomModels", resourceRoot, function(c
end
end
end, false)
+
+addEventHandler("onClientResourceStop", resourceRoot, function()
+ -- Restore the base models of all elements with custom models
+ for _, elementType in pairs(ELEMENT_TYPES) do
+ for _, v in pairs(getElementsByType(elementType, root, true)) do
+ local model = getElementModel(v)
+ for _, loadedModel in pairs(loadedModels) do
+ if loadedModel.id == model then
+ setElementModel(v, loadedModel.baseModel)
+ break
+ end
+ end
+ end
+ end
+end, false)
diff --git a/newmodels_reborn/core/shared.lua b/newmodels_reborn/core/shared.lua
index d3d4bd1..35e0a05 100644
--- a/newmodels_reborn/core/shared.lua
+++ b/newmodels_reborn/core/shared.lua
@@ -1,4 +1,3 @@
-CUSTOM_MODEL_DATA_KEY = "newmodels_simple:customModel"
ELEMENT_TYPES = { "vehicle", "ped", "player", "object", "pickup" }
customModels = {}
@@ -69,6 +68,11 @@ function isDefaultID(elementType, id)
return false
end
+-- Variable is unused, it is only necessary for backwards compatibility
+function getCustomModelDataKey(elementOrElementType)
+ return "newmodels_reborn:customModel"
+end
+
function isValidElement(element)
local elementType = getElementType(element)
for _, elementType2 in pairs(ELEMENT_TYPES) do
@@ -123,7 +127,7 @@ local function createElementSafe(elementType, id, ...)
return false
end
if baseModel ~= id then
- setElementData(element, CUSTOM_MODEL_DATA_KEY, id, not isClientsideScript)
+ setElementData(element, getCustomModelDataKey(elementType), id, not isClientsideScript)
end
return element
end
@@ -181,12 +185,12 @@ function setPickupType(thePickup, theType, id, ammo)
if theType and theType == 3 then
local baseModel = getBaseModelIdFromCustomModelId(id)
if baseModel ~= id then
- setElementData(thePickup, CUSTOM_MODEL_DATA_KEY, id, not isClientsideScript)
+ setElementData(thePickup, getCustomModelDataKey("pickup"), id, not isClientsideScript)
return true
end
end
- setElementData(thePickup, CUSTOM_MODEL_DATA_KEY, nil, not isClientsideScript)
+ setElementData(thePickup, getCustomModelDataKey("pickup"), nil, not isClientsideScript)
return _setPickupType(thePickup, theType, id, ammo)
end
@@ -194,7 +198,7 @@ end
function getElementModel(element)
assert(isElement(element), "Invalid element passed: " .. tostring(element))
assert(isValidElement(element), "Invalid element type passed: " .. getElementType(element))
- return getElementData(element, CUSTOM_MODEL_DATA_KEY) or _getElementModel(element)
+ return getElementData(element, getCustomModelDataKey(element)) or _getElementModel(element)
end
-- PS. You can't set element model on a pickup
@@ -209,9 +213,9 @@ function setElementModel(element, id)
end
if baseModel ~= id then
- setElementData(element, CUSTOM_MODEL_DATA_KEY, id, not isClientsideScript)
+ setElementData(element, getCustomModelDataKey(element), id, not isClientsideScript)
else
- setElementData(element, CUSTOM_MODEL_DATA_KEY, nil, not isClientsideScript)
+ setElementData(element, getCustomModelDataKey(element), nil, not isClientsideScript)
end
return true
diff --git a/newmodels_reborn/meta.xml b/newmodels_reborn/meta.xml
index 4a4d708..1cd5d8f 100644
--- a/newmodels_reborn/meta.xml
+++ b/newmodels_reborn/meta.xml
@@ -5,12 +5,17 @@
https://nightly.mtasa.com -->
-
-
+
+
+
+
+
+
+
diff --git a/newmodels_reborn/optional/compatibility/shared/funcs.lua b/newmodels_reborn/optional/compatibility/shared/funcs.lua
new file mode 100644
index 0000000..dff222a
--- /dev/null
+++ b/newmodels_reborn/optional/compatibility/shared/funcs.lua
@@ -0,0 +1,137 @@
+-- Backwards compatibility with newmodels 3.3.0
+
+local OLD_DATA_NAMES = {
+ ped = "skinID",
+ vehicle = "vehicleID",
+ object = "objectID",
+}
+OLD_DATA_NAMES.pickup = OLD_DATA_NAMES.object
+OLD_DATA_NAMES.player = OLD_DATA_NAMES.ped
+
+local OLD_BASE_DATA_NAME = "baseID"
+
+local function convertCustomModelInfoToOldFormat(customModelInfo)
+ local baseModel = customModelInfo.baseModel
+ local customModel = customModelInfo.id
+ local colPath, txdPath, dffPath = customModelInfo.col, customModelInfo.txd, customModelInfo.dff
+ local mod = {
+ id = customModel,
+ base_id = baseModel,
+ name = "",
+ path = { col = colPath, txd = txdPath, dff = dffPath },
+ }
+ mod.paths = mod.path
+ return mod
+end
+
+-- Exported
+function getDataNameFromType(elementType)
+ if type(elementType) == "string" then
+ return OLD_DATA_NAMES[elementType]
+ end
+end
+
+-- Rewrite this function
+function getCustomModelDataKey(elementType)
+ if type(elementType) == "string" then
+ return OLD_DATA_NAMES[elementType]
+ end
+end
+
+-- Exported
+function getBaseModelDataName()
+ return OLD_BASE_DATA_NAME
+end
+
+-- Exported
+function getModDataFromID(id)
+ id = tonumber(id)
+ if not id then return end
+ local customInfo = customModels[id]
+ if not customInfo then return end
+ local mod = convertCustomModelInfoToOldFormat(customInfo)
+ return mod, customInfo.type
+end
+
+-- Exported
+function getModList()
+ local modList = {}
+ for customModel, customInfo in pairs(customModels) do
+ modList[customModel] = convertCustomModelInfoToOldFormat(customInfo)
+ end
+ return modList
+end
+
+-- Exported
+function getBaseModel(element)
+ if not isElement(localPlayer) then
+ return getElementModel(element)
+ else
+ local customModel = tonumber(getElementData(element, getCustomModelDataKey(element)))
+ if customModel then
+ return customModels[customModel] and customModels[customModel].baseModel or nil
+ else
+ return getElementModel(element)
+ end
+ end
+end
+
+-- Exported
+function isCustomModID(id)
+ local mod, modType = getModDataFromID(id)
+ if not mod then return false end
+ return true, mod, modType
+end
+
+-- Exported
+function isRightModType(et, modEt)
+ if et == modEt then
+ return true
+ end
+ if (et == "player" or et == "ped") and (modEt == "player" or modEt == "ped") then
+ return true
+ end
+ if (et == "pickup" or et == "object") and (modEt == "pickup" or modEt == "object") then
+ return true
+ end
+ return false
+end
+
+-- Exported
+function checkModelID(id, elementType)
+ assert(tonumber(id), "Non-number ID passed")
+ assert(
+ (elementType == "ped" or elementType == "player" or elementType == "object" or elementType == "vehicle" or elementType == "pickup"),
+ "Invalid element type passed: " .. tostring(elementType))
+ local dataName = OLD_DATA_NAMES[elementType]
+ assert(dataName, "No data name for element type: " .. tostring(elementType))
+ if elementType == "pickup" then
+ elementType = "object"
+ end
+ local baseModel
+ local isCustom, mod, modType = isCustomModID(id)
+ if isCustom then
+ if not isRightModType(elementType, modType) then
+ return "WRONG_MOD"
+ end
+ if mod then baseModel = mod.base_id end
+ elseif isDefaultID(elementType, id) then
+ baseModel = id
+ else
+ return "INVALID_MODEL"
+ end
+
+ return baseModel, isCustom, dataName, OLD_BASE_DATA_NAME
+end
+
+if isElement(localPlayer) then
+ -- Exported
+ function isClientReady() return true end -- Now the client is always ready :-)
+
+ -- Exported
+ function isModAllocated(id)
+ id = tonumber(id)
+ if not id then return end
+ return loadedModels[id] ~= nil
+ end
+end