Moderators Popular Post IIYAMA Posted November 25, 2018 Moderators Popular Post Share Posted November 25, 2018 (edited) Regeneration (health) This resource lets you regenerate player and vehicle* health. It is not an unique idea, I know... but there weren't good implementations for it at the community resource list. So that's why I share this with YOU. * Vehicle regeneration for the driver only. Version 1.0.0 Not compiled! Smooth health regeneration No UI, just the manager Settings (Admin panel) Settings Regeneration [on/off] (player/vehicle) Regeneration value (player/vehicle) Regeneration delay (player/vehicle) Regeneration [on/off] while the vehicle is burning Download link: https://community.multitheftauto.com/?p=resources&s=details&id=15757 Take a quick look into the source code (v1.0.0) Client Spoiler local developmentSettings = { basicFPS = 60, -- 60 fps for starters. When developing, set this basic fps to the same value as the server. developmentMode = false, -- View all the data memorySaving = false, --[[ [Enable] Will save memory. >> But can cause incapability with some gamemodes (for example race). [Disable] Will use more memory. When to disable? If the function `warpPedIntoVehicle` is used on players in your gamemode. https://wiki.multitheftauto.com/wiki/WarpPedIntoVehicle ]] } ----------------------------------------- --[[ Before you are going to change values, please keep in mind that serverside edits some of those values. ]] local healthRegeneration = { --[[ Regeneration things for the vehicle ]] vehicle = (function () local vehicleHealthRegeneration vehicleHealthRegeneration = { enabled = false, lastDamageTime = -1/0, -- infinity negative delay = 8000, -- [X milliseconds] delay before kicking in basicTimeSlice = 1000 / developmentSettings.basicFPS, -- basic timeslice for developers status = false, -- watching/updating or not? additionalHealth = 10, -- X health per second regenerationOnBurning = false, --[[ When the health of a vehicle is lower than 250, it will start burning. This setting makes health regen enabled or disabled for that scenario. ]] watchAndUpdate = function (timeSlice) -- The magic happens here! local self_ = vehicleHealthRegeneration local vehicle = getPedOccupiedVehicle (localPlayer) if vehicle and getPedOccupiedVehicleSeat (localPlayer) == 0 and not isVehicleBlown ( vehicle ) then local timeNow = getTickCount() if timeNow > self_.lastDamageTime + self_.delay then local currentHealth = getElementHealth(vehicle) if developmentSettings.regenerationOnBurning or currentHealth > 250 then local maxHealth = 1000 local additionalHealthMultiplier = self_.basicTimeSlice / timeSlice -- calculate the new health based on the time between the frames. local currentAdditionalHealth = self_.additionalHealth / 100 * additionalHealthMultiplier if currentHealth < maxHealth then setElementHealth(vehicle, math.min(currentHealth + currentAdditionalHealth, maxHealth)) else self_:stopWatchProcess () end else self_:stopWatchProcess () end end else self_:stopWatchProcess () end end, registerDamage = { handler = { status = false, }, onDamage = function () vehicleHealthRegeneration.lastDamageTime = getTickCount() vehicleHealthRegeneration:startWatchProcess() end } } -- functions for managing which vehicle should attach onClientVehicleDamage (Currently disabled, but you can enable it for memory saving, see developmentSettings on top) function vehicleHealthRegeneration.registerDamage.handler:add(vehicle) if not self.status then if self.lastVehicle and isElement(self.lastVehicle) then removeEventHandler("onClientVehicleDamage", self.lastVehicle, vehicleHealthRegeneration.registerDamage.onDamage) end self.lastVehicle = nil if not isVehicleBlown ( vehicle ) then addEventHandler("onClientVehicleDamage", vehicle, vehicleHealthRegeneration.registerDamage.onDamage, false) self.lastVehicle = vehicle self.status = true return true end end return false end function vehicleHealthRegeneration.registerDamage.handler:remove (vehicle) if self.status then removeEventHandler("onClientVehicleDamage", vehicle, vehicleHealthRegeneration.registerDamage.onDamage) self.lastVehicle = nil self.status = false return true end return false end -- main functions function vehicleHealthRegeneration:isDamaged () local vehicle = getPedOccupiedVehicle (localPlayer) if vehicle and getPedOccupiedVehicleSeat (localPlayer) == 0 then local currentHealth = getElementHealth(vehicle) return currentHealth < 1000 end return false end function vehicleHealthRegeneration:startWatchProcess () if not self.status then addEventHandler("onClientPreRender", root, self.watchAndUpdate) self.status = true end end function vehicleHealthRegeneration:stopWatchProcess () if self.status then removeEventHandler("onClientPreRender", root, self.watchAndUpdate) self.status = false end end return vehicleHealthRegeneration end)(), ------------------------------------------------------------------------------ --[[ Regeneration things for the player. ]] player = (function () local playerHealthRegeneration local getPedMaxHealth = function (ped) -- Grab his player health stat. local stat = getPedStat(ped, 24) -- Do a linear interpolation to get how many health a ped can have. -- Assumes: 100 health = 569 stat, 200 health = 1000 stat. local maxhealth = 100 + (stat - 569) / 4.31 -- Return the max health. Make sure it can't be below 1 return math.max(1, maxhealth) end -- Documentation/source of this function: https://wiki.multitheftauto.com/wiki/GetPedMaxHealth playerHealthRegeneration = { enabled = false, lastDamageTime = -1/0, -- infinity negative delay = 8000, -- [X milliseconds] delay before kicking in basicTimeSlice = 1000 / developmentSettings.basicFPS, -- basic timeslice for developers status = false, -- watching/updating or not? additionalHealth = 5, -- X health per second watchAndUpdate = function (timeSlice) -- The magic happens here! local self_ = playerHealthRegeneration local timeNow = getTickCount() if timeNow > self_.lastDamageTime + self_.delay then local currentHealth = getElementHealth(localPlayer) local maxHealth = getPedMaxHealth(localPlayer) local additionalHealthMultiplier = self_.basicTimeSlice / timeSlice -- calculate the new health based on the time between the frames. local currentAdditionalHealth = self_.additionalHealth / 100 * additionalHealthMultiplier if currentHealth < maxHealth then setElementHealth(localPlayer, math.min(currentHealth + currentAdditionalHealth, maxHealth)) else self_:stopWatchProcess () end end end } -- main functions function playerHealthRegeneration:isDamaged () local currentHealth = getElementHealth(localPlayer) local maxHealth = getPedMaxHealth(localPlayer) return currentHealth < maxHealth end function playerHealthRegeneration:startWatchProcess () if not self.status then addEventHandler("onClientPreRender", root, self.watchAndUpdate) self.status = true end end function playerHealthRegeneration:stopWatchProcess () if self.status then removeEventHandler("onClientPreRender", root, self.watchAndUpdate) self.status = false end end return playerHealthRegeneration end)() } do -- (Re)starting the script? It still works. addEvent("health-regeneration-settings--receive", true) -- receive the settings here! local function receiveSettings (settingsContainer) removeEventHandler("health-regeneration-settings--receive", resourceRoot, receiveSettings, false) receiveSettings = nil -- Apply the settings from serverside on clientside for i=1, #settingsContainer do local settingsGroup = settingsContainer[i] local settingsGroupType = settingsGroup.type local settings = settingsGroup.settings for j=1, #settings do local setting = settings[j] healthRegeneration[settingsGroupType][setting.key] = setting.value end end -- stop both regeneration types when you die addEventHandler("onClientPlayerWasted", localPlayer, function () if healthRegeneration.player.enabled then healthRegeneration.player:stopWatchProcess () end if healthRegeneration.vehicle.enabled then healthRegeneration.vehicle:stopWatchProcess () end end, false) -- enable health regeneration for players if healthRegeneration.player.enabled then if healthRegeneration.player:isDamaged() then healthRegeneration.player:startWatchProcess() end addEventHandler("onClientPlayerDamage", localPlayer, function () healthRegeneration.player.lastDamageTime = getTickCount() healthRegeneration.player:startWatchProcess() end, false) addEventHandler("onClientPlayerSpawn", localPlayer, function () healthRegeneration.player:stopWatchProcess () end, false) end -- enable health regeneration for vehicles with YOU as driver if healthRegeneration.vehicle.enabled then local vehicle = getPedOccupiedVehicle (localPlayer) if vehicle and getPedOccupiedVehicleSeat (localPlayer) == 0 then if healthRegeneration.vehicle:isDamaged() then healthRegeneration.vehicle:startWatchProcess() end if developmentSettings.memorySaving then healthRegeneration.vehicle.registerDamage.handler:add(vehicle) end end if developmentSettings.memorySaving then -- saving memory? addEventHandler("onClientPlayerVehicleEnter", localPlayer, function (vehicle, seat) if seat == 0 then healthRegeneration.vehicle.registerDamage.handler:add(vehicle) if healthRegeneration.vehicle:isDamaged () then healthRegeneration.vehicle.lastDamageTime = getTickCount() -- No cheating by getting in and out of the vehicle healthRegeneration.vehicle:startWatchProcess () end end end, false) addEventHandler("onClientPlayerVehicleExit", localPlayer, function (vehicle, seat) if seat == 0 then healthRegeneration.vehicle.registerDamage.handler:remove(vehicle) healthRegeneration.vehicle:stopWatchProcess () end end, false) else -- or more memory use and less bugs? addEventHandler("onClientPlayerVehicleEnter", localPlayer, function (vehicle, seat) if seat == 0 and healthRegeneration.vehicle:isDamaged () then healthRegeneration.vehicle.lastDamageTime = getTickCount() -- No cheating by getting in and out of the vehicle healthRegeneration.vehicle:startWatchProcess () end end, false) addEventHandler("onClientPlayerVehicleExit", localPlayer, function (vehicle, seat) if seat == 0 then healthRegeneration.vehicle:stopWatchProcess () end end, false) addEventHandler("onClientVehicleDamage", root, function () if source == getPedOccupiedVehicle(localPlayer) and getPedOccupiedVehicleSeat (localPlayer) == 0 and not isVehicleBlown ( source ) then local vehicleHealthRegeneration = healthRegeneration.vehicle vehicleHealthRegeneration.lastDamageTime = getTickCount() vehicleHealthRegeneration:startWatchProcess() end end) end end end local function resourceStartFunction () -- clean up removeEventHandler("onClientResourceStart", resourceRoot, resourceStartFunction) resourceStartFunction = nil -- get the settings! addEventHandler("health-regeneration-settings--receive", resourceRoot, receiveSettings, false) triggerServerEvent("health-regeneration-settings--request", resourceRoot) end addEventHandler("onClientResourceStart", resourceRoot, resourceStartFunction, false) end -- debug the whole thing! if developmentSettings.developmentMode then addEventHandler("onClientRender", root, function () dxDrawText(inspect(healthRegeneration), 20, 200) -- with just one line of output! Whohohoho! end) end Server Spoiler local settingsContainer do local _outputDebugString = outputDebugString local outputDebugString = function (...) local arg = {...} arg[1] = "[settings validation] " .. arg[1] _outputDebugString(unpack(arg), 0, 0, 0, 255) end settingsContainer = { { type = "vehicle", settings = { {key = "enabled", value = string.lower(tostring(get ("vehicleRegenerationEnabled" ))) == "true"}, { key = "additionalHealth", value = (function () local settingName = "vehicleRegenerationValue" local defaultValue = 10 local value = tonumber(get(settingName)) if not value then value = defaultValue outputDebugString(tostring(settingName) .. " must be filled in. Reset to: " .. tostring(value)) elseif value < 0 then value = defaultValue outputDebugString(tostring(settingName) .. " must be higher than 0. Reset to: " .. tostring(value)) end return value end)() }, { key = "delay", value = (function () local settingName = "vehicleRegenerationDelay" local defaultValue = 8000 local value = tonumber(get(settingName)) if not value then value = defaultValue outputDebugString(tostring(settingName) .. " must be filled in. Reset to: " .. tostring(value)) elseif value < 0 then value = defaultValue outputDebugString(tostring(settingName) .. " must be higher than 0. Reset to: " .. tostring(value)) end return value end)() }, {key = "regenerationOnBurning", value = string.lower(tostring(get ("vehicleRegenerationOnBurning" ))) == "true"} } }, { type = "player", settings = { {key = "enabled", value = string.lower(tostring(get ("playerRegenerationEnabled" ))) == "true"}, { key = "additionalHealth", value = (function () local settingName = "playerRegenerationValue" local defaultValue = 5 local value = tonumber(get(settingName)) if not value then value = defaultValue outputDebugString(tostring(settingName) .. " must be filled in. Reset to: " .. tostring(value)) elseif value < 0 then value = defaultValue outputDebugString(tostring(settingName) .. " must be higher than 0. Reset to: " .. tostring(value)) end return value end)() }, { key = "delay", value = (function () local settingName = "playerRegenerationDelay" local defaultValue = 8000 local value = tonumber(get(settingName)) if not value then value = defaultValue outputDebugString(tostring(settingName) .. " must be filled in. Reset to: " .. tostring(value)) elseif value < 0 then value = defaultValue outputDebugString(tostring(settingName) .. " must be higher than 0. Reset to: " .. tostring(value)) end return value end)() }, } } } end addEvent("health-regeneration-settings--request", true) addEventHandler("health-regeneration-settings--request", resourceRoot, function () -- send the settings to the client triggerClientEvent(client, "health-regeneration-settings--receive", resourceRoot, settingsContainer) end) Meta Spoiler <meta> <info author="IIYAMA" type="script" version="1.0.0" name="Health regeneration" desc="This resource lets you regenerate health of players and their vehicle while driving it.(driver only) You can edit the optional settings in Admin panel." /> <min_mta_version client="1.5.4" server="1.5.4" /> <script src="scripts/server.lua" /> <script src="scripts/client.lua" type="client" /> <settings> <setting group="vehicle" name="*vehicleRegenerationEnabled" friendlyname="Vehicle regeneration, yes or no?" accept="true,false,TRUE,FALSE" value="true" examples="true" desc="[vehicle] This setting toggles regeneration for vehicles" /> <setting group="vehicle" name="*vehicleRegenerationValue" friendlyname="Vehicle regeneration per second" accept="number" value="10" examples="10" desc="[vehicle] This setting is used for the amount of regeneration per second" /> <setting group="vehicle" name="*vehicleRegenerationDelay" friendlyname="Delay before vehicle regeneration" accept="number(milliseconds)" value="8000" examples="8000" desc="[vehicle] This setting is used for the regeneration delay" /> <setting group="vehicle" name="*vehicleRegenerationOnBurning" friendlyname="Vehicle regeneration while burning, yes or no?" accept="true,false,TRUE,FALSE" value="false" examples="false" desc="[vehicle] This setting toggles regeneration for burning vehicles" /> <setting group="player" name="*playerRegenerationEnabled" friendlyname="Player regeneration, yes or no?" accept="true,false,TRUE,FALSE" value="true" examples="true" desc="[player] This setting toggles regeneration for players" /> <setting group="player" name="*playerRegenerationValue" friendlyname="Player regeneration per second" accept="number" value="5" examples="5" desc="[player] This setting is used for the amount of regeneration per second" /> <setting group="player" name="*playerRegenerationDelay" friendlyname="Delay before player regeneration" accept="number(milliseconds)" value="8000" examples="8000" desc="[Player] This setting is used for the regeneration delay" /> </settings> </meta> Edited November 25, 2018 by IIYAMA 3 3 Link to comment
Gordon_G Posted November 25, 2018 Share Posted November 25, 2018 A simple but efficient resource 2 Link to comment
Moderators IIYAMA Posted November 25, 2018 Author Moderators Share Posted November 25, 2018 4 hours ago, Gordon_G said: A simple but efficient resource Yea, I believe that describes the resource the best. And yet, it surprised me how many conditions (for critical gamemode scenario's) it required to work properly. 1 Link to comment
Storm-Hanma Posted November 26, 2018 Share Posted November 26, 2018 Not a bad one ilyama its a best resource +1 1 Link to comment
Moderators IIYAMA Posted November 26, 2018 Author Moderators Share Posted November 26, 2018 8 hours ago, KINGKHAN said: Not a bad one ilyama its a best resource +1 You are making me shy Link to comment
Vazern Posted November 28, 2018 Share Posted November 28, 2018 Perfect resource! Thanks. 1 Link to comment
Ayush Rathore Posted November 29, 2018 Share Posted November 29, 2018 Good work keep it up! 1 Link to comment
koragg Posted November 30, 2018 Share Posted November 30, 2018 On 26/11/2018 at 00:31, IIYAMA said: Yea, I believe that describes the resource the best. And yet, it surprised me how many conditions (for critical gamemode scenario's) it required to work properly. It never amazes me how much if else i have to use for even the simplest resource haha. I like having everything green so ignoring warnings is not an option for me as well nice work bro 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now