<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[G1R:MP Forum - G1 Remake Multiplayer Community - Scripts]]></title>
		<link>https://g1r-mp.com/forum/</link>
		<description><![CDATA[G1R:MP Forum - G1 Remake Multiplayer Community - https://g1r-mp.com/forum]]></description>
		<pubDate>Sat, 19 Sep 2026 07:34:58 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[no fall damage script.]]></title>
			<link>https://g1r-mp.com/forum/showthread.php?tid=51</link>
			<pubDate>Mon, 07 Sep 2026 12:34:03 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://g1r-mp.com/forum/member.php?action=profile&uid=62">asvra</a>]]></dc:creator>
			<guid isPermaLink="false">https://g1r-mp.com/forum/showthread.php?tid=51</guid>
			<description><![CDATA[NO FALL DAMAGE - G1R:MP (server API 0.1.2 / Protocol 31+)<br />
<br />
<br />
    Works in two layers:<br />
      1. The engine stat "resistance_falling" is set to STAT_VALUE when a player<br />
        spawns, after every revive and refreshed every REFRESH_MS (the engine may<br />
        overwrite the stat when it loads the character).<br />
      2. Fallback: if damage of a DAMAGE_TYPES kind with no attacker still arrives<br />
        (that is how the engine reports a fall), health is restored to the value<br />
        it had before the hit.<br />
<br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;scripts&gt;<br />
    &lt;script src="server.lua" type="server" /&gt;<br />
&lt;/scripts&gt;<br />
<br />
Server Script<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>-- === CONFIG ==============================================================<br />
local ENABLED_BY_DEFAULT = true          -- every player from the moment they join<br />
local STAT_VALUE        = 100000        -- resistance_falling; 0 = normal fall damage<br />
local REFRESH_MS        = 15000        -- stat refresh interval (ms)<br />
local DAMAGE_TYPES      = {environment = true, fall = true, falling = true}  -- damage kinds reported as a fall<br />
local RESTORE_HEALTH    = true          -- fallback: undo fall damage by restoring health<br />
local LOG                = false        -- outputDebugString on every restore<br />
local ADMIN_PERMISSION  = "admin.world" -- /nofall on|off: permission checked through the gothic_rp bridge<br />
-- =========================================================================<br />
<br />
local enabled = {}      -- playerId -&gt; true/false (nil = default)<br />
local previous = {}      -- playerId -&gt; stat value before enabling (restored on disable/stop)<br />
<br />
local function isEnabled(playerId)<br />
    if enabled[playerId] == nil then return ENABLED_BY_DEFAULT end<br />
    return enabled[playerId] == true<br />
end<br />
<br />
local function applyStat(playerId)<br />
    if not isPlayerConnected(playerId) then return false end<br />
    if isEnabled(playerId) then<br />
        if previous[playerId] == nil then<br />
            previous[playerId] = tonumber(getPlayerStat(playerId, "resistance_falling")) or 0<br />
        end<br />
        return setPlayerStat(playerId, "resistance_falling", STAT_VALUE) ~= false<br />
    elseif previous[playerId] ~= nil then<br />
        setPlayerStat(playerId, "resistance_falling", previous[playerId])<br />
        previous[playerId] = nil<br />
    end<br />
    return true<br />
end<br />
<br />
-- 1) the stat: on spawn, on revive, periodic refresh<br />
addEventHandler("onPlayerSpawn", root, function(playerId)<br />
    setTimer(function() applyStat(playerId) end, 500, 1)  -- the engine may still be loading stats right after spawn<br />
end)<br />
addEventHandler("onPlayerRevived", root, function(playerId)<br />
    setTimer(function() applyStat(playerId) end, 500, 1)<br />
end)<br />
setTimer(function()<br />
    for _, playerId in ipairs(getPlayers()) do applyStat(playerId) end<br />
end, REFRESH_MS, 0)<br />
<br />
-- 2) fallback: restore health after fall damage (no attacker)<br />
addEventHandler("onPlayerDamage", root, function(playerId, damage, healthAfter, attackerId, damageType)<br />
    if not RESTORE_HEALTH or not isEnabled(playerId) then return end<br />
    local kind = tostring(damageType or ""):lower()<br />
    if not DAMAGE_TYPES[kind] then return end<br />
    local attacker = tonumber(attackerId)<br />
    if attacker and attacker &gt;= 0 then return end  -- hit by someone or something - not a fall<br />
    damage = tonumber(damage) or 0<br />
    healthAfter = tonumber(healthAfter) or 0<br />
    if damage &lt;= 0 or healthAfter &lt;= 0 then return end  -- death cannot be undone here<br />
    local restored = math.min(healthAfter + damage, tonumber(getPlayerMaxHealth(playerId)) or (healthAfter + damage))<br />
    setPlayerHealth(playerId, restored)<br />
    if LOG then<br />
        outputDebugString(("[nofall] player=%s restored %d fall damage (%s)"):format(tostring(playerId), damage, kind), 3)<br />
    end<br />
end)<br />
<br />
-- API for other resources<br />
addEvent("nofall<img src="https://g1r-mp.com/forum/images/smilies/confused.png" alt="Confused" title="Confused" class="smilie smilie_13" />et", false)<br />
addEventHandler("nofall<img src="https://g1r-mp.com/forum/images/smilies/confused.png" alt="Confused" title="Confused" class="smilie smilie_13" />et", root, function(playerId, state)<br />
    playerId = tonumber(playerId)<br />
    if not playerId then return end<br />
    enabled[playerId] = state ~= false<br />
    applyStat(playerId)<br />
end)<br />
<br />
addEventHandler("onPlayerQuit", root, function(playerId)<br />
    enabled[playerId] = nil<br />
    previous[playerId] = nil<br />
end)<br />
<br />
-- Admin command: permission via gothic_rp's synchronous event bridge (permission_bridge.lua);<br />
-- refused when gothic_rp is not running.<br />
local bridgeGranted = false<br />
addEvent("g1r:permissionSeen", false)<br />
addEvent("g1r:permissionGrant", false)<br />
addEventHandler("g1r:permissionGrant", root, function() bridgeGranted = true end)<br />
local function isWorldAdmin(playerId)<br />
    bridgeGranted = false<br />
    triggerEvent("g1r:permissionQuery", root, playerId, ADMIN_PERMISSION)<br />
    return bridgeGranted<br />
end<br />
addCommandHandler("nofall", function(playerId, commandName, mode)<br />
    if not isWorldAdmin(playerId) then<br />
        outputChatBox("No permission.", playerId, 230, 90, 90, false)<br />
        return<br />
    end<br />
    mode = tostring(mode or ""):lower()<br />
    if mode == "on" then enabled[playerId] = true elseif mode == "off" then enabled[playerId] = false end<br />
    applyStat(playerId)<br />
    outputChatBox(("No fall damage: %s (/nofall on|off)."):format(isEnabled(playerId) and "ENABLED" or "disabled"), playerId, 216, 185, 120, false)<br />
end)<br />
<br />
addEventHandler("onResourceStart", resourceRoot, function()<br />
    for _, playerId in ipairs(getPlayers()) do applyStat(playerId) end<br />
    outputDebugString(("[nofall] start: default %s, resistance_falling=%d, restore health=%s"):format(<br />
        ENABLED_BY_DEFAULT and "enabled" or "disabled", STAT_VALUE, tostring(RESTORE_HEALTH)), 3)<br />
end)<br />
addEventHandler("onResourceStop", resourceRoot, function()<br />
    for _, playerId in ipairs(getPlayers()) do<br />
        if previous[playerId] ~= nil then setPlayerStat(playerId, "resistance_falling", previous[playerId]) end<br />
    end<br />
end)</blockquote>
]]></description>
			<content:encoded><![CDATA[NO FALL DAMAGE - G1R:MP (server API 0.1.2 / Protocol 31+)<br />
<br />
<br />
    Works in two layers:<br />
      1. The engine stat "resistance_falling" is set to STAT_VALUE when a player<br />
        spawns, after every revive and refreshed every REFRESH_MS (the engine may<br />
        overwrite the stat when it loads the character).<br />
      2. Fallback: if damage of a DAMAGE_TYPES kind with no attacker still arrives<br />
        (that is how the engine reports a fall), health is restored to the value<br />
        it had before the hit.<br />
<br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;scripts&gt;<br />
    &lt;script src="server.lua" type="server" /&gt;<br />
&lt;/scripts&gt;<br />
<br />
Server Script<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>-- === CONFIG ==============================================================<br />
local ENABLED_BY_DEFAULT = true          -- every player from the moment they join<br />
local STAT_VALUE        = 100000        -- resistance_falling; 0 = normal fall damage<br />
local REFRESH_MS        = 15000        -- stat refresh interval (ms)<br />
local DAMAGE_TYPES      = {environment = true, fall = true, falling = true}  -- damage kinds reported as a fall<br />
local RESTORE_HEALTH    = true          -- fallback: undo fall damage by restoring health<br />
local LOG                = false        -- outputDebugString on every restore<br />
local ADMIN_PERMISSION  = "admin.world" -- /nofall on|off: permission checked through the gothic_rp bridge<br />
-- =========================================================================<br />
<br />
local enabled = {}      -- playerId -&gt; true/false (nil = default)<br />
local previous = {}      -- playerId -&gt; stat value before enabling (restored on disable/stop)<br />
<br />
local function isEnabled(playerId)<br />
    if enabled[playerId] == nil then return ENABLED_BY_DEFAULT end<br />
    return enabled[playerId] == true<br />
end<br />
<br />
local function applyStat(playerId)<br />
    if not isPlayerConnected(playerId) then return false end<br />
    if isEnabled(playerId) then<br />
        if previous[playerId] == nil then<br />
            previous[playerId] = tonumber(getPlayerStat(playerId, "resistance_falling")) or 0<br />
        end<br />
        return setPlayerStat(playerId, "resistance_falling", STAT_VALUE) ~= false<br />
    elseif previous[playerId] ~= nil then<br />
        setPlayerStat(playerId, "resistance_falling", previous[playerId])<br />
        previous[playerId] = nil<br />
    end<br />
    return true<br />
end<br />
<br />
-- 1) the stat: on spawn, on revive, periodic refresh<br />
addEventHandler("onPlayerSpawn", root, function(playerId)<br />
    setTimer(function() applyStat(playerId) end, 500, 1)  -- the engine may still be loading stats right after spawn<br />
end)<br />
addEventHandler("onPlayerRevived", root, function(playerId)<br />
    setTimer(function() applyStat(playerId) end, 500, 1)<br />
end)<br />
setTimer(function()<br />
    for _, playerId in ipairs(getPlayers()) do applyStat(playerId) end<br />
end, REFRESH_MS, 0)<br />
<br />
-- 2) fallback: restore health after fall damage (no attacker)<br />
addEventHandler("onPlayerDamage", root, function(playerId, damage, healthAfter, attackerId, damageType)<br />
    if not RESTORE_HEALTH or not isEnabled(playerId) then return end<br />
    local kind = tostring(damageType or ""):lower()<br />
    if not DAMAGE_TYPES[kind] then return end<br />
    local attacker = tonumber(attackerId)<br />
    if attacker and attacker &gt;= 0 then return end  -- hit by someone or something - not a fall<br />
    damage = tonumber(damage) or 0<br />
    healthAfter = tonumber(healthAfter) or 0<br />
    if damage &lt;= 0 or healthAfter &lt;= 0 then return end  -- death cannot be undone here<br />
    local restored = math.min(healthAfter + damage, tonumber(getPlayerMaxHealth(playerId)) or (healthAfter + damage))<br />
    setPlayerHealth(playerId, restored)<br />
    if LOG then<br />
        outputDebugString(("[nofall] player=%s restored %d fall damage (%s)"):format(tostring(playerId), damage, kind), 3)<br />
    end<br />
end)<br />
<br />
-- API for other resources<br />
addEvent("nofall<img src="https://g1r-mp.com/forum/images/smilies/confused.png" alt="Confused" title="Confused" class="smilie smilie_13" />et", false)<br />
addEventHandler("nofall<img src="https://g1r-mp.com/forum/images/smilies/confused.png" alt="Confused" title="Confused" class="smilie smilie_13" />et", root, function(playerId, state)<br />
    playerId = tonumber(playerId)<br />
    if not playerId then return end<br />
    enabled[playerId] = state ~= false<br />
    applyStat(playerId)<br />
end)<br />
<br />
addEventHandler("onPlayerQuit", root, function(playerId)<br />
    enabled[playerId] = nil<br />
    previous[playerId] = nil<br />
end)<br />
<br />
-- Admin command: permission via gothic_rp's synchronous event bridge (permission_bridge.lua);<br />
-- refused when gothic_rp is not running.<br />
local bridgeGranted = false<br />
addEvent("g1r:permissionSeen", false)<br />
addEvent("g1r:permissionGrant", false)<br />
addEventHandler("g1r:permissionGrant", root, function() bridgeGranted = true end)<br />
local function isWorldAdmin(playerId)<br />
    bridgeGranted = false<br />
    triggerEvent("g1r:permissionQuery", root, playerId, ADMIN_PERMISSION)<br />
    return bridgeGranted<br />
end<br />
addCommandHandler("nofall", function(playerId, commandName, mode)<br />
    if not isWorldAdmin(playerId) then<br />
        outputChatBox("No permission.", playerId, 230, 90, 90, false)<br />
        return<br />
    end<br />
    mode = tostring(mode or ""):lower()<br />
    if mode == "on" then enabled[playerId] = true elseif mode == "off" then enabled[playerId] = false end<br />
    applyStat(playerId)<br />
    outputChatBox(("No fall damage: %s (/nofall on|off)."):format(isEnabled(playerId) and "ENABLED" or "disabled"), playerId, 216, 185, 120, false)<br />
end)<br />
<br />
addEventHandler("onResourceStart", resourceRoot, function()<br />
    for _, playerId in ipairs(getPlayers()) do applyStat(playerId) end<br />
    outputDebugString(("[nofall] start: default %s, resistance_falling=%d, restore health=%s"):format(<br />
        ENABLED_BY_DEFAULT and "enabled" or "disabled", STAT_VALUE, tostring(RESTORE_HEALTH)), 3)<br />
end)<br />
addEventHandler("onResourceStop", resourceRoot, function()<br />
    for _, playerId in ipairs(getPlayers()) do<br />
        if previous[playerId] ~= nil then setPlayerStat(playerId, "resistance_falling", previous[playerId]) end<br />
    end<br />
end)</blockquote>
]]></content:encoded>
		</item>
	</channel>
</rss>