From 12be6eca3ee72c3a06889da0296406c68ed0f944 Mon Sep 17 00:00:00 2001 From: patrikjuvonen <22572159+patrikjuvonen@users.noreply.github.com> Date: Sun, 15 Aug 2021 17:08:53 +0300 Subject: [PATCH] Initial commit --- CODEOWNERS | 1 + LICENSE | 21 ++++++ README.md | 50 +++++++++++++ c_editor_addon.lua | 131 +++++++++++++++++++++++++++++++++ c_manager.lua | 151 +++++++++++++++++++++++++++++++++++++++ editor_addon_effects.edf | 43 +++++++++++ icon.png | Bin 0 -> 1146 bytes meta.xml | 34 +++++++++ screenshot.jpg | Bin 0 -> 99363 bytes 9 files changed, 431 insertions(+) create mode 100644 CODEOWNERS create mode 100644 LICENSE create mode 100644 README.md create mode 100644 c_editor_addon.lua create mode 100644 c_manager.lua create mode 100644 editor_addon_effects.edf create mode 100644 icon.png create mode 100644 meta.xml create mode 100644 screenshot.jpg diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..4fe3170 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @patrikjuvonen diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..26d8451 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 patrikjuvonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..deae8d2 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# Effects Add-on for MTA:SA Map Editor + +You want to add effects inside the MTA:SA Map Editor? You've come to the right place. + +![Screenshot](screenshot.jpg) + +## Installation + +1. Download the latest release +2. Put the resource inside your `MTA San Andreas 1.5/server/mods/deathmatch/resources` folder +3. Refresh resources by running `refreshall` in your server console +4. The add-on is ready for use! + +## How to use in map editor + +1. Start the map editor resource (`editor`) or enter the Map Editor from the main menu +2. Click "definitions" from the top editor menu +3. Add "editor_addon_effects" to your definitions and press OK +4. Hover on the buttons in the bottom-left corner, and scroll your mouse wheel once +5. Click the "Effect" button to place a new effect into the game world +6. Double-click the effect to change its properties, such as type, draw distance, sound, density, speed and respawn +7. Once you've finished with your map, save the map in a resource + +## How to use with a saved map + +Start your map resource **together** with this `editor_addon_effects` resource, and you should be able to see the effects placed in the game world using your defined settings! + +## License + +MIT License + +Copyright (c) 2021 patrikjuvonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/c_editor_addon.lua b/c_editor_addon.lua new file mode 100644 index 0000000..c1c31b5 --- /dev/null +++ b/c_editor_addon.lua @@ -0,0 +1,131 @@ +--[[ + This resource is officially available on GitHub at + https://github.com/patrikjuvonen/editor_addon_effects + + MIT License + + Copyright (c) 2021 patrikjuvonen + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +]] +local effectMatrix = {} +local _createEffect = createEffect + +local function getRepresentation(element, type) + local elemTable = {} + + for _, elem in pairs(getElementsByType(type, element)) do + if (elem ~= exports.edf:edfGetHandle(elem)) then + table.insert(elemTable, elem) + end + end + + if (#elemTable == 0) then + return false + elseif (#elemTable == 1) then + return elemTable[1] + end + + return elemTable +end + +local function createEffect(element) + element = element or source + + if (not isElement(element)) or (getElementType(element) ~= "addon_effect") then return end + + if (isElement(effectMatrix[element])) then + destroyElement(effectMatrix[element]) + end + + effectMatrix[element] = _createEffect( + exports.edf:edfGetElementProperty(element, "name"), + Vector3(exports.edf:edfGetElementPosition(element)), + Vector3(exports.edf:edfGetElementRotation(element)), + exports.edf:edfGetElementProperty(element, "drawDistance") or 100, + exports.edf:edfGetElementProperty(element, "soundEnable") == "true" + ) + setEffectDensity(effectMatrix[element], math.max(0, math.min(2, exports.edf:edfGetElementProperty(element, "density") or 1.5))) + setEffectSpeed(effectMatrix[element], math.max(0, exports.edf:edfGetElementProperty(element, "speed") or 1)) + setElementDimension(effectMatrix[element], exports.edf:edfGetElementDimension(element)) + setElementInterior(effectMatrix[element], exports.edf:edfGetElementInterior(element)) + setElementParent(effectMatrix[element], element) + + setElementAlpha(getRepresentation(element, "marker"), 0) +end +addEventHandler("onClientElementCreate", root, createEffect) + +local function localCleanUp() + if (not isElement(source)) or (getElementType(source) ~= "addon_effect") or (not effectMatrix[source]) then return end + + if (isElement(effectMatrix[source])) then + destroyElement(effectMatrix[source]) + end + + effectMatrix[source] = nil +end +addEventHandler("onClientElementDestroyed", root, localCleanUp) +addEventHandler("onClientElementDestroy", root, localCleanUp) + +addEventHandler("onClientElementPropertyChanged", root, function (propertyName) + if (not isElement(source)) or (getElementType(source) ~= "addon_effect") then return end + + if (not isElement(effectMatrix[source])) then + createEffect(source) + return + end + + if (propertyName == "density") then + setEffectDensity(effectMatrix[source], math.max(0, math.min(2, exports.edf:edfGetElementProperty(source, "density") or 1.5))) + elseif (propertyName == "speed") then + setEffectSpeed(effectMatrix[source], math.max(0, exports.edf:edfGetElementProperty(source, "speed") or 1)) + else + createEffect(source) + end +end) + +addEventHandler("onClientPreRender", root, function () + for element, effect in pairs(effectMatrix) do + if (isElement(element)) then + if (isElement(effect)) then + setElementPosition(effect, exports.edf:edfGetElementPosition(element)) + setElementRotation(effect, exports.edf:edfGetElementRotation(element)) + elseif (exports.edf:edfGetElementProperty(element, "respawn") == "true") then + createEffect(element) + end + end + end +end) + +function onStart() + for _, element in pairs(getElementsByType("addon_effect")) do + createEffect(element) + end +end + +function onStop() + for element, effect in pairs(effectMatrix) do + if (isElement(effect)) then + destroyElement(effect) + end + + effectMatrix[element] = nil + end +end +addEventHandler("onClientResourceStop", resourceRoot, onStop) diff --git a/c_manager.lua b/c_manager.lua new file mode 100644 index 0000000..1dac260 --- /dev/null +++ b/c_manager.lua @@ -0,0 +1,151 @@ +--[[ + This resource is officially available on GitHub at + https://github.com/patrikjuvonen/editor_addon_effects + + MIT License + + Copyright (c) 2021 patrikjuvonen + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +]] +local effectMatrix = {} +local _createEffect = createEffect +local rendering + +local function createEffect(element) + if (not isElement(element)) or (getElementType(element) ~= "addon_effect") then return end + + if (isElement(effectMatrix[element])) then + destroyElement(effectMatrix[element]) + end + + setElementDimension(element, getElementData(element, "dimension")) + setElementInterior(element, getElementData(element, "interior")) + + addEventHandler("onClientElementDimensionChange", element, function (_, newDimension) + if (newDimension == getElementDimension(localPlayer)) then + createEffect(source) + elseif (isElement(effectMatrix[source])) then + destroyElement(effectMatrix[source]) + end + end) + + addEventHandler("onClientElementInteriorChange", element, function (_, newInterior) + if (newInterior == getElementInterior(localPlayer)) then + createEffect(source) + elseif (isElement(effectMatrix[source])) then + destroyElement(effectMatrix[source]) + end + end) + + if (getElementDimension(element) == getElementDimension(localPlayer)) and (getElementInterior(element) == getElementInterior(localPlayer)) then + effectMatrix[element] = _createEffect( + getElementData(element, "name"), + Vector3(getElementPosition(element)), + Vector3(getElementRotation(element)), + getElementData(element, "drawDistance") or 100, + getElementData(element, "soundEnable") == "true" + ) + setElementDimension(effectMatrix[element], getElementDimension(element)) + setElementInterior(effectMatrix[element], getElementInterior(element)) + setEffectDensity(effectMatrix[element], math.max(0, math.min(2, getElementData(element, "density") or 1.5))) + setEffectSpeed(effectMatrix[element], math.max(0, getElementData(element, "speed") or 1)) + setElementParent(effectMatrix[element], element) + + addEventHandler("onClientElementDimensionChange", effectMatrix[element], function (_, newDimension) + if (newDimension == getElementDimension(localPlayer)) then + createEffect(getElementParent(source)) + else + destroyElement(source) + end + end) + + addEventHandler("onClientElementInteriorChange", effectMatrix[element], function (_, newInterior) + if (newInterior == getElementInterior(localPlayer)) then + createEffect(getElementParent(source)) + else + destroyElement(source) + end + end) + end +end + +local function renderEffectRespawn() + for element, effect in pairs(effectMatrix) do + if (isElement(element)) + and (not isElement(effect)) + and (getElementData(element, "respawn") == "true") + and (getElementDimension(element) == getElementDimension(localPlayer)) + and (getElementInterior(element) == getElementInterior(localPlayer)) + then + createEffect(element) + end + end +end + +local function toggleRendering(foundEffect) + if (foundEffect) and (not rendering) then + addEventHandler("onClientPreRender", root, renderEffectRespawn) + rendering = true + elseif (not foundEffect) and (rendering) then + removeEventHandler("onClientPreRender", root, renderEffectRespawn) + rendering = false + end +end + +addEventHandler("onClientResourceStart", root, function () + local foundEffect = false + + for _, element in pairs(getElementsByType("addon_effect", source == resourceRoot and root or source)) do + local effect = getElementChildren(element, "addon_effect")[1] + + if (isElement(effect)) then + effectMatrix[element] = effect + end + + createEffect(element) + foundEffect = true + end + + toggleRendering(foundEffect) +end) + +addEventHandler("onClientElementDimensionChange", localPlayer, function (_, newDimension) + for element, effect in pairs(effectMatrix) do + if (getElementDimension(element) == newDimension) then + createEffect(element) + elseif (isElement(effect)) then + destroyElement(effect) + end + end +end) + +addEventHandler("onClientElementInteriorChange", localPlayer, function (_, newInterior) + for element, effect in pairs(effectMatrix) do + if (getElementInterior(element) == newInterior) then + createEffect(element) + elseif (isElement(effect)) then + destroyElement(effect) + end + end +end) + +addEventHandler("onClientElementDestroy", root, function () + toggleRendering(#getElementsByType("addon_effect") > 0) +end) diff --git a/editor_addon_effects.edf b/editor_addon_effects.edf new file mode 100644 index 0000000..6a2aba9 --- /dev/null +++ b/editor_addon_effects.edf @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + +