From a9d01b4c9e7e8e5c8b8e544997feae59b0459c65 Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Sat, 4 Jan 2025 21:35:56 +0100
Subject: [PATCH 1/6] Prep: Delete old code
---
[gameplay]/headshot/headshot.lua | 25 -------------------------
1 file changed, 25 deletions(-)
delete mode 100644 [gameplay]/headshot/headshot.lua
diff --git a/[gameplay]/headshot/headshot.lua b/[gameplay]/headshot/headshot.lua
deleted file mode 100644
index 7f02c21de..000000000
--- a/[gameplay]/headshot/headshot.lua
+++ /dev/null
@@ -1,25 +0,0 @@
-local removeHeadOnHeadshot = get("removeHeadOnHeadshot")
-
-addEvent("onPlayerHeadshot", false)
-
-local function checkForHeadshot(attacker, weapon, bodypart, loss)
- if bodypart == 9 then
- local forceDeath = triggerEvent("onPlayerHeadshot", source, attacker, weapon, loss)
-
- if forceDeath then
- killPed(source, attacker, weapon, bodypart)
-
- if removeHeadOnHeadshot then
- setPedHeadless(source, true)
- end
- end
- end
-end
-addEventHandler("onPlayerDamage", root, checkForHeadshot)
-
-local function restorePlayerHead()
- if removeHeadOnHeadshot and isPedHeadless(source) then
- setPedHeadless(source, false) -- Restore head if it got blown off
- end
-end
-addEventHandler("onPlayerSpawn", root, restorePlayerHead)
\ No newline at end of file
From d942222dd147080cefa57d7c9256245158e18bcf Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Sat, 4 Jan 2025 21:36:22 +0100
Subject: [PATCH 2/6] Prep: Delete old meta and create a new one
---
[gameplay]/headshot/meta.xml | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/[gameplay]/headshot/meta.xml b/[gameplay]/headshot/meta.xml
index 28e79cc7d..e3e1f490a 100644
--- a/[gameplay]/headshot/meta.xml
+++ b/[gameplay]/headshot/meta.xml
@@ -1,11 +1,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 77bf75ae7156ed82cc9e193014c62196d9c16bbf Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Sat, 4 Jan 2025 21:36:32 +0100
Subject: [PATCH 3/6] Logic
---
[gameplay]/headshot/src/headshotDamage.lua | 30 ++++++++
[gameplay]/headshot/src/headshotSettings.lua | 77 ++++++++++++++++++++
[gameplay]/headshot/src/headshotSpawn.lua | 13 ++++
3 files changed, 120 insertions(+)
create mode 100644 [gameplay]/headshot/src/headshotDamage.lua
create mode 100644 [gameplay]/headshot/src/headshotSettings.lua
create mode 100644 [gameplay]/headshot/src/headshotSpawn.lua
diff --git a/[gameplay]/headshot/src/headshotDamage.lua b/[gameplay]/headshot/src/headshotDamage.lua
new file mode 100644
index 000000000..c8b7643a9
--- /dev/null
+++ b/[gameplay]/headshot/src/headshotDamage.lua
@@ -0,0 +1,30 @@
+addEvent("onPlayerHeadshot", false)
+addEvent("onPlayerPreHeadshot", false)
+
+addEventHandler("onPlayerDamage", root,
+ function(headshotAttacker, headshotCause, headshotBodypart, headshotDamage)
+ if not headshotAttacker or not isElement(headshotAttacker) or getElementType(headshotAttacker) ~= "player" then
+ return
+ end
+
+ if headshotBodypart ~= 9 then
+ return
+ end
+
+ triggerEvent("onPlayerPreHeadshot", source, headshotAttacker, headshotCause, headshotDamage)
+
+ if wasEventCancelled() then
+ return
+ end
+
+ killPed(source, headshotAttacker, headshotCause, headshotBodypart)
+
+ triggerEvent("onPlayerHeadshot", source, headshotAttacker, headshotCause)
+
+ if not headshotSettingsGet("decap") then
+ return
+ end
+
+ setPedHeadless(source, true)
+ end
+)
\ No newline at end of file
diff --git a/[gameplay]/headshot/src/headshotSettings.lua b/[gameplay]/headshot/src/headshotSettings.lua
new file mode 100644
index 000000000..9d9ae4f6b
--- /dev/null
+++ b/[gameplay]/headshot/src/headshotSettings.lua
@@ -0,0 +1,77 @@
+local headshotSettings = {}
+local headshotSettingsAvailable = {
+ {"decap", "boolean"}
+}
+
+function headshotSettingsGet(headshotSetting)
+ if not headshotSetting or type(headshotSetting) ~= "string" then
+ return
+ end
+
+ return headshotSettings[headshotSetting]
+end
+
+function headshotSettingsBooleanize(headshotValue)
+ if not headshotValue or type(headshotValue) ~= "string" then
+ return
+ end
+
+ if string.find(headshotValue, "true") then
+ return true
+ end
+
+ return false
+end
+
+addEventHandler("onResourceStart", resourceRoot,
+ function()
+ for _, headshotEntry in pairs(headshotSettingsAvailable) do
+ local headshotSetting = headshotEntry[1]
+ local headshotType = headshotEntry[2]
+ local headshotValue = get(headshotSetting)
+
+ if headshotValue and type(headshotValue) == "string" then
+ if headshotType == "boolean" then
+ headshotSettings[headshotSetting] = headshotSettingsBooleanize(headshotValue)
+ else
+ headshotSettings[headshotSetting] = headshotValue
+ end
+ end
+ end
+ end
+)
+
+addEventHandler("onSettingChange", root,
+ function(headshotSetting, _, headshotValue)
+ local headshotDot = string.find(headshotSetting, "%.")
+
+ if headshotDot and type(headshotDot) == "number" then
+ headshotSetting = string.sub(headshotSetting, headshotDot + 1)
+ end
+
+ local headshotFound
+
+ for _, headshotEntry in pairs(headshotSettingsAvailable) do
+ if headshotEntry[1] == headshotSetting then
+ headshotFound = headshotEntry
+ break
+ end
+ end
+
+ if not headshotFound then
+ return
+ end
+
+ local headshotType = headshotFound[2]
+
+ if not headshotValue or type(headshotValue) ~= "string" then
+ return
+ end
+
+ if headshotType == "boolean" then
+ headshotSettings[headshotSetting] = headshotSettingsBooleanize(headshotValue)
+ else
+ headshotSettings[headshotSetting] = headshotValue
+ end
+ end
+)
\ No newline at end of file
diff --git a/[gameplay]/headshot/src/headshotSpawn.lua b/[gameplay]/headshot/src/headshotSpawn.lua
new file mode 100644
index 000000000..68d2d231b
--- /dev/null
+++ b/[gameplay]/headshot/src/headshotSpawn.lua
@@ -0,0 +1,13 @@
+addEventHandler("onPlayerSpawn", root,
+ function()
+ if not isPedHeadless(source) then
+ return
+ end
+
+ if not headshotSettingsGet("decap") then
+ return
+ end
+
+ setPedHeadless(source, false)
+ end
+)
\ No newline at end of file
From 74dc4d19cd07a87af4b163b4174eb90374528925 Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Sat, 4 Jan 2025 21:36:38 +0100
Subject: [PATCH 4/6] Docs
---
[gameplay]/headshot/docs/README.md | 76 ++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 [gameplay]/headshot/docs/README.md
diff --git a/[gameplay]/headshot/docs/README.md b/[gameplay]/headshot/docs/README.md
new file mode 100644
index 000000000..eab05313a
--- /dev/null
+++ b/[gameplay]/headshot/docs/README.md
@@ -0,0 +1,76 @@
+# Headshot
+Headshot feature for enhanced combat realism and damage effect — Made with 💖 by Multi Theft Developers.
+
+> [!NOTE]
+> This resource is a part of the [mtasa-blue](https://github.com/multitheftauto/mtasa-resources) repository, any updates, fixes or patches are only available there.
+
+> [!IMPORTANT]
+> The minimum version requirement for the server is 1.6.0. You can always download the latest binaries [here](https://nightly.multitheftauto.com/).
+
+## Settings
+| name | description | default | accept |
+|-------|-----------------------------------------------------------------|---------|-------------|
+| decap | determines whether the player becomes headless after a headshot | true | false, true |
+
+## Events
+
+### onPlayerHeadshot
+This event is called when a player is shot in the head and dies.
+
+#### Parameters
+```lua
+player attacker, int cause
+```
+- attacker: a player element who was the attacker
+- cause: a number representing the attacker weapon or other damage type
+
+#### Cancel
+This event cannot be cancelled.
+
+#### Example
+```lua
+addEventHandler("onPlayerHeadshot", root,
+ function(attacker, cause)
+ local name = getPlayerName(source)
+
+ if attacker and isElement(attacker) and getElementType(attacker) == "player" then
+ attacker = getPlayerName(attacker)
+ else
+ attacker = "Unknown"
+ end
+
+ if cause and type(cause) == "number" then
+ cause = getWeaponNameFromID(cause)
+ else
+ cause = "Unknown"
+ end
+
+ outputServerLog(name .. " was shot in the head by " .. attacker .. " using " .. cause)
+ end
+)
+```
+
+### onPlayerPreHeadshot
+This event is called when a player is shot in the head but has not yet been killed by the resource.
+
+#### Parameters
+```lua
+player attacker, int cause, int damage
+```
+- attacker: a player element who was the attacker
+- cause: a number representing the attacker weapon or other damage type
+- damage: a number representing the health originally lost by the shot
+
+#### Cancel
+This event can be cancelled, preventing the player from being killed.
+
+#### Example
+```lua
+addEventHandler("onPlayerPreHeadshot", root,
+ function(_, _, damage)
+ if damage < 5 then
+ cancelEvent()
+ end
+ end
+)
+```
\ No newline at end of file
From c438f601277f3a02bbc590bd4efd870d81c27e1a Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Wed, 8 Jan 2025 23:04:27 +0100
Subject: [PATCH 5/6] Make suggested changes
---
[gameplay]/headshot/meta.xml | 2 +-
[gameplay]/headshot/src/headshotSettings.lua | 109 +++++++++++--------
2 files changed, 66 insertions(+), 45 deletions(-)
diff --git a/[gameplay]/headshot/meta.xml b/[gameplay]/headshot/meta.xml
index e3e1f490a..4c15bf3d4 100644
--- a/[gameplay]/headshot/meta.xml
+++ b/[gameplay]/headshot/meta.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/[gameplay]/headshot/src/headshotSettings.lua b/[gameplay]/headshot/src/headshotSettings.lua
index 9d9ae4f6b..0c8a68491 100644
--- a/[gameplay]/headshot/src/headshotSettings.lua
+++ b/[gameplay]/headshot/src/headshotSettings.lua
@@ -3,6 +3,34 @@ local headshotSettingsAvailable = {
{"decap", "boolean"}
}
+local function headshotSettingsNumberize(headshotValue)
+ if not headshotValue then
+ return
+ end
+
+ if type(headshotValue) == "number" then
+ return headshotValue
+ end
+
+ if type(headshotValue) == "string" then
+ return tonumber(headshotValue)
+ end
+
+ return 0
+end
+
+local function headshotSettingsBooleanize(headshotValue)
+ if type(headshotValue) == "boolean" then
+ return headshotValue
+ end
+
+ if type(headshotValue) == "string" then
+ return headshotValue == "[true]"
+ end
+
+ return false
+end
+
function headshotSettingsGet(headshotSetting)
if not headshotSetting or type(headshotSetting) ~= "string" then
return
@@ -11,67 +39,60 @@ function headshotSettingsGet(headshotSetting)
return headshotSettings[headshotSetting]
end
-function headshotSettingsBooleanize(headshotValue)
- if not headshotValue or type(headshotValue) ~= "string" then
+function headshotSettingsSet(headshotSetting, headshotValue)
+ if not headshotSetting or type(headshotSetting) ~= "string" then
return
end
- if string.find(headshotValue, "true") then
- return true
+ local headshotDot = string.find(headshotSetting, "%.")
+
+ if headshotDot and type(headshotDot) == "number" then
+ headshotSetting = string.sub(headshotSetting, headshotDot + 1)
end
- return false
+ local headshotFound
+
+ for _, headshotEntry in ipairs(headshotSettingsAvailable) do
+ if headshotEntry[1] == headshotSetting then
+ headshotFound = headshotEntry
+ break
+ end
+ end
+
+ if not headshotFound then
+ return
+ end
+
+ local headshotType = headshotFound[2]
+
+ if headshotType == "string" and type(headshotValue) == "string" then
+ headshotSettings[headshotSetting] = headshotValue
+ return
+ end
+
+ if headshotType == "number" and type(headshotValue) == "string" then
+ headshotSettings[headshotSetting] = headshotSettingsNumberize(headshotValue)
+ return
+ end
+
+ if headshotType == "boolean" then
+ headshotSettings[headshotSetting] = headshotSettingsBooleanize(headshotValue)
+ end
end
addEventHandler("onResourceStart", resourceRoot,
function()
- for _, headshotEntry in pairs(headshotSettingsAvailable) do
+ for _, headshotEntry in ipairs(headshotSettingsAvailable) do
local headshotSetting = headshotEntry[1]
- local headshotType = headshotEntry[2]
local headshotValue = get(headshotSetting)
- if headshotValue and type(headshotValue) == "string" then
- if headshotType == "boolean" then
- headshotSettings[headshotSetting] = headshotSettingsBooleanize(headshotValue)
- else
- headshotSettings[headshotSetting] = headshotValue
- end
- end
+ headshotSettingsSet(headshotSetting, headshotValue)
end
end
)
addEventHandler("onSettingChange", root,
function(headshotSetting, _, headshotValue)
- local headshotDot = string.find(headshotSetting, "%.")
-
- if headshotDot and type(headshotDot) == "number" then
- headshotSetting = string.sub(headshotSetting, headshotDot + 1)
- end
-
- local headshotFound
-
- for _, headshotEntry in pairs(headshotSettingsAvailable) do
- if headshotEntry[1] == headshotSetting then
- headshotFound = headshotEntry
- break
- end
- end
-
- if not headshotFound then
- return
- end
-
- local headshotType = headshotFound[2]
-
- if not headshotValue or type(headshotValue) ~= "string" then
- return
- end
-
- if headshotType == "boolean" then
- headshotSettings[headshotSetting] = headshotSettingsBooleanize(headshotValue)
- else
- headshotSettings[headshotSetting] = headshotValue
- end
+ headshotSettingsSet(headshotSetting, headshotValue)
end
)
\ No newline at end of file
From b880b5b73dda0f84f72086e674fa895d5bff3b48 Mon Sep 17 00:00:00 2001
From: Nico <122193236+Nico8340@users.noreply.github.com>
Date: Sat, 18 Jan 2025 06:19:30 +0100
Subject: [PATCH 6/6] Make requested changes
---
[gameplay]/headshot/docs/README.md | 76 ------------------------------
[gameplay]/headshot/meta.xml | 2 +-
2 files changed, 1 insertion(+), 77 deletions(-)
delete mode 100644 [gameplay]/headshot/docs/README.md
diff --git a/[gameplay]/headshot/docs/README.md b/[gameplay]/headshot/docs/README.md
deleted file mode 100644
index eab05313a..000000000
--- a/[gameplay]/headshot/docs/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# Headshot
-Headshot feature for enhanced combat realism and damage effect — Made with 💖 by Multi Theft Developers.
-
-> [!NOTE]
-> This resource is a part of the [mtasa-blue](https://github.com/multitheftauto/mtasa-resources) repository, any updates, fixes or patches are only available there.
-
-> [!IMPORTANT]
-> The minimum version requirement for the server is 1.6.0. You can always download the latest binaries [here](https://nightly.multitheftauto.com/).
-
-## Settings
-| name | description | default | accept |
-|-------|-----------------------------------------------------------------|---------|-------------|
-| decap | determines whether the player becomes headless after a headshot | true | false, true |
-
-## Events
-
-### onPlayerHeadshot
-This event is called when a player is shot in the head and dies.
-
-#### Parameters
-```lua
-player attacker, int cause
-```
-- attacker: a player element who was the attacker
-- cause: a number representing the attacker weapon or other damage type
-
-#### Cancel
-This event cannot be cancelled.
-
-#### Example
-```lua
-addEventHandler("onPlayerHeadshot", root,
- function(attacker, cause)
- local name = getPlayerName(source)
-
- if attacker and isElement(attacker) and getElementType(attacker) == "player" then
- attacker = getPlayerName(attacker)
- else
- attacker = "Unknown"
- end
-
- if cause and type(cause) == "number" then
- cause = getWeaponNameFromID(cause)
- else
- cause = "Unknown"
- end
-
- outputServerLog(name .. " was shot in the head by " .. attacker .. " using " .. cause)
- end
-)
-```
-
-### onPlayerPreHeadshot
-This event is called when a player is shot in the head but has not yet been killed by the resource.
-
-#### Parameters
-```lua
-player attacker, int cause, int damage
-```
-- attacker: a player element who was the attacker
-- cause: a number representing the attacker weapon or other damage type
-- damage: a number representing the health originally lost by the shot
-
-#### Cancel
-This event can be cancelled, preventing the player from being killed.
-
-#### Example
-```lua
-addEventHandler("onPlayerPreHeadshot", root,
- function(_, _, damage)
- if damage < 5 then
- cancelEvent()
- end
- end
-)
-```
\ No newline at end of file
diff --git a/[gameplay]/headshot/meta.xml b/[gameplay]/headshot/meta.xml
index 4c15bf3d4..c7b5cfb82 100644
--- a/[gameplay]/headshot/meta.xml
+++ b/[gameplay]/headshot/meta.xml
@@ -1,5 +1,5 @@
-
+