Skip to content

Instantly share code, notes, and snippets.

@SandeMC
Forked from JuniorDjjr/Reload Mod (Junior_Djjr).sc
Last active September 15, 2026 21:28
Show Gist options
  • Select an option

  • Save SandeMC/4c6d52a05f71af24702eaa28f6b692cf to your computer and use it in GitHub Desktop.

Select an option

Save SandeMC/4c6d52a05f71af24702eaa28f6b692cf to your computer and use it in GitHub Desktop.
Fixed Reload Mod by Junior_Djjr, details in comments
// Originally made by Junior_Djjr - https://www.mixmods.com.br/2019/07/reload-mod.html
// Fixed by GillianMC - https://gist.github.com/SandeMC/4c6d52a05f71af24702eaa28f6b692cf
CONST_INT OFFSET_PED_ACTIVE_WEAPON_SLOT 0x718
CONST_INT OFFSET_PED_WEAPONS 0x5A0
CONST_INT SIZEOF_CWEAPON 0x1C
CONST_INT OFFSET_WEAPON_STATE 0x04
CONST_INT OFFSET_WEAPON_AMMO_CLIP 0x08
CONST_INT OFFSET_WEAPON_TOTAL_AMMO 0x0C
CONST_INT OFFSET_WEAPON_SHOT_TIMER 0x10
CONST_INT OFFSET_WEAPONINFO_CLIP_SIZE 0x20
CONST_INT ADDR_TIMER_MS 0xB7CB84
CONST_INT FUNC_PED_GETSKILL 0x5E3B60
CONST_INT FUNC_WEAPONINFO_GETINFO 0x743C60
CONST_INT FUNC_WEAPONINFO_GETRELOADTIME 0x743D70
CONST_INT PATCH_VEHICLE_RELOAD 0x7422A6
CONST_INT PATCH_SCROLL_RELOAD 0x60B4FA
// Custom Weapon IDs
CONST_INT WEP_FLAMETHROWER 37
CONST_INT WEP_MINIGUN 38
CONST_INT WEP_SPRAYCAN 41
CONST_INT WEP_EXTINGUISHER 42
CONST_INT WEP_CAMERA 43
SCRIPT_START
{
// 31 local variable registers used (Engine limit: 32)
LVAR_INT iCmds[2] iLastCurAmmo[2] iLastTotalAmmo[2] iLastWeapon[2]
LVAR_INT bDontReloadIfFull bDisableWeaponsWithoutAnim bRealisticReload bDisabledOnSAMP bKeepNoAmmo bDisableScrollReload bDisableVehicleAutoReload bDisablePickupClipRefill
LVAR_INT i j iPlayerIdx iCmd scplayer pPed pWeapon iCurWeapon pWeaponInfo iMaxAmmo iCurAmmo iState iTotalAmmo iReloadTime iGameTime
// INI Parser (Split across two blocks to honor 8-condition engine limit)
i = 0
IF NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Controls" "CMD_Player1" (iCmds[0])
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Controls" "CMD_Player2" (iCmds[1])
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DontReloadIfFull" (bDontReloadIfFull)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DisableWeaponsWithoutAnim" (bDisableWeaponsWithoutAnim)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "RealisticReload" (bRealisticReload)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DisabledOnSAMP" (bDisabledOnSAMP)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "KeepNoAmmo" (bKeepNoAmmo)
i = 1
ENDIF
IF NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DisableScrollReload" (bDisableScrollReload)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DisableVehicleAutoReload" (bDisableVehicleAutoReload)
OR NOT READ_INT_FROM_INI_FILE "CLEO/Reload Mod.ini" "Settings" "DisablePickupClipRefill" (bDisablePickupClipRefill)
OR i = 1
timera = 0
WHILE timera < 3000
WAIT 0
PRINT_STRING_NOW "Error: Fail to read 'Reload Mod.ini'" 1000
ENDWHILE
TERMINATE_THIS_CUSTOM_SCRIPT
ENDIF
IF bRealisticReload = TRUE
bDisablePickupClipRefill = TRUE
ENDIF
// SAMP Compatibility Check
IF bDisabledOnSAMP = TRUE
IF LOAD_DYNAMIC_LIBRARY "kernel32" (i)
GET_DYNAMIC_LIBRARY_PROCEDURE "GetModuleHandleA" i (j)
IF j > 0
CALL_FUNCTION_RETURN j 1 0 ("SAMP.dll")(j)
IF j > 0
FREE_DYNAMIC_LIBRARY i
TERMINATE_THIS_CUSTOM_SCRIPT
ENDIF
ENDIF
FREE_DYNAMIC_LIBRARY i
ENDIF
ENDIF
// KeepNoAmmo Hook
IF bKeepNoAmmo = TRUE
IF LOAD_DYNAMIC_LIBRARY "KeepNoAmmo.SA.asi" (i)
IF GET_DYNAMIC_LIBRARY_PROCEDURE "PatchNoReload" i (j)
CALL_FUNCTION j 0 0
ENDIF
FREE_DYNAMIC_LIBRARY i
ENDIF
WRITE_MEMORY PATCH_SCROLL_RELOAD 6 (0x90) TRUE
ENDIF
// Memory Patches
IF bRealisticReload = TRUE
WRITE_MEMORY PATCH_VEHICLE_RELOAD 3 (0x90) TRUE
WRITE_MEMORY PATCH_SCROLL_RELOAD 6 (0x90) TRUE
ELSE
IF bDisableScrollReload = TRUE
WRITE_MEMORY PATCH_SCROLL_RELOAD 6 (0x90) TRUE
ENDIF
IF bDisableVehicleAutoReload = TRUE
WRITE_MEMORY PATCH_VEHICLE_RELOAD 3 (0x90) TRUE
ENDIF
ENDIF
// Initialize tracking arrays
iLastCurAmmo[0] = 0
iLastCurAmmo[1] = 0
iLastTotalAmmo[0] = 0
iLastTotalAmmo[1] = 0
iLastWeapon[0] = 0
iLastWeapon[1] = 0
// Main Loop
WHILE TRUE
WAIT 0
IF IS_PLAYER_CONTROL_ON 0
GET_PLAYER_CHAR 0 (scplayer)
iCmd = iCmds[0]
iPlayerIdx = 0
GOSUB ProcessReload
ENDIF
IF IS_2PLAYER_GAME_GOING_ON
IF IS_PLAYER_CONTROL_ON 1
GET_PLAYER_CHAR 1 (scplayer)
iCmd = iCmds[1]
iPlayerIdx = 1
GOSUB ProcessReload
ENDIF
ENDIF
ENDWHILE
// Subroutine: Reload Handler
ProcessReload:
IF IS_CHAR_DEAD scplayer
RETURN
ENDIF
// Check button / key press (j stores whether trigger button is pressed)
j = FALSE
IF iCmd <= 19
IF IS_BUTTON_PRESSED iPlayerIdx iCmd
j = TRUE
ENDIF
ELSE
IF IS_KEY_PRESSED iCmd
j = TRUE
ENDIF
ENDIF
GET_PED_POINTER scplayer (pPed)
i = pPed + OFFSET_PED_ACTIVE_WEAPON_SLOT
READ_MEMORY i 1 FALSE (i)
IF i = 0
RETURN
ENDIF
pWeapon = i * SIZEOF_CWEAPON
pWeapon += pPed
pWeapon += OFFSET_PED_WEAPONS
GET_CURRENT_CHAR_WEAPON scplayer (iCurWeapon)
// Weapons without reload animations
IF bDisableWeaponsWithoutAnim = TRUE
IF iCurWeapon = WEP_FLAMETHROWER
OR iCurWeapon = WEP_MINIGUN
OR iCurWeapon = WEP_EXTINGUISHER
OR iCurWeapon = WEP_SPRAYCAN
OR iCurWeapon = WEP_CAMERA
RETURN
ENDIF
ENDIF
// Fetch Weapon Capacity & Info
CALL_METHOD_RETURN FUNC_PED_GETSKILL pPed 1 0 (iCurWeapon)(i)
CALL_FUNCTION_RETURN FUNC_WEAPONINFO_GETINFO 2 2 (i iCurWeapon)(pWeaponInfo)
i = pWeaponInfo + OFFSET_WEAPONINFO_CLIP_SIZE
READ_MEMORY i 2 FALSE (iMaxAmmo)
IF iMaxAmmo <= 1
RETURN
ENDIF
i = pWeapon + OFFSET_WEAPON_AMMO_CLIP
READ_MEMORY i 4 FALSE (iCurAmmo)
i = pWeapon + OFFSET_WEAPON_TOTAL_AMMO
READ_MEMORY i 4 FALSE (iTotalAmmo)
i = pWeapon + OFFSET_WEAPON_STATE
READ_MEMORY i 4 FALSE (iState)
// Pickup Magazine Watcher
// iTotalAmmo includes clip ammo, so a reload never bumps it, only a pickup does.
IF bDisablePickupClipRefill = TRUE
IF iCurWeapon = iLastWeapon[iPlayerIdx]
AND iTotalAmmo > iLastTotalAmmo[iPlayerIdx]
AND iCurAmmo > iLastCurAmmo[iPlayerIdx]
AND NOT iState = 2
AND iLastTotalAmmo[iPlayerIdx] > 0
iCurAmmo = iLastCurAmmo[iPlayerIdx]
i = pWeapon + OFFSET_WEAPON_AMMO_CLIP
WRITE_MEMORY i 4 iCurAmmo FALSE
ENDIF
iLastWeapon[iPlayerIdx] = iCurWeapon
iLastCurAmmo[iPlayerIdx] = iCurAmmo
iLastTotalAmmo[iPlayerIdx] = iTotalAmmo
ENDIF
// In a vehicle, reload triggers if the player presses the key OR if the clip hits 0
IF IS_CHAR_IN_ANY_CAR scplayer
IF j = FALSE
IF NOT iCurAmmo = 0
RETURN
ENDIF
ENDIF
ELSE
// On foot, reload is triggered strictly via user key press
IF j = FALSE
RETURN
ENDIF
ENDIF
// Abort if clip is already full (and configured not to reload)
IF bDontReloadIfFull = TRUE
IF iCurAmmo = iMaxAmmo
RETURN
ENDIF
ENDIF
// Abort if no reserve ammunition remains
IF iTotalAmmo <= iCurAmmo
RETURN
ENDIF
READ_MEMORY ADDR_TIMER_MS 4 FALSE (iGameTime)
// Vehicle Drive-By Reload Handler
IF IS_CHAR_IN_ANY_CAR scplayer
i = pWeapon + OFFSET_WEAPON_SHOT_TIMER
READ_MEMORY i 4 FALSE (j)
// Still cooling down from a previous shot or reload
IF iGameTime < j
RETURN
ENDIF
CALL_METHOD_RETURN FUNC_WEAPONINFO_GETRELOADTIME pWeaponInfo 0 0 ()(iReloadTime)
j = iGameTime + iReloadTime
i = pWeapon + OFFSET_WEAPON_SHOT_TIMER
WRITE_MEMORY i 4 j FALSE
// Realistic reload: discard active clip bullets
IF bRealisticReload = TRUE
IF iTotalAmmo < 25000
iTotalAmmo -= iCurAmmo
IF iTotalAmmo < 0
iTotalAmmo = 0
ENDIF
i = pWeapon + OFFSET_WEAPON_TOTAL_AMMO
WRITE_MEMORY i 4 iTotalAmmo FALSE
ENDIF
iCurAmmo = 0
ENDIF
// Refill clip directly
IF iTotalAmmo >= iMaxAmmo
iCurAmmo = iMaxAmmo
ELSE
iCurAmmo = iTotalAmmo
ENDIF
i = pWeapon + OFFSET_WEAPON_AMMO_CLIP
WRITE_MEMORY i 4 iCurAmmo FALSE
IF bDisablePickupClipRefill = TRUE
iLastCurAmmo[iPlayerIdx] = iCurAmmo
iLastTotalAmmo[iPlayerIdx] = iTotalAmmo
ENDIF
RETURN
ENDIF
// On-Foot Reload Handler
IF iState = 2
RETURN
ENDIF
CALL_METHOD_RETURN FUNC_WEAPONINFO_GETRELOADTIME pWeaponInfo 0 0 ()(iReloadTime)
j = iGameTime + iReloadTime
i = pWeapon + OFFSET_WEAPON_SHOT_TIMER
WRITE_MEMORY i 4 j FALSE
IF bRealisticReload = TRUE
IF iTotalAmmo < 25000
iTotalAmmo -= iCurAmmo
IF iTotalAmmo < 0
iTotalAmmo = 0
ENDIF
i = pWeapon + OFFSET_WEAPON_TOTAL_AMMO
WRITE_MEMORY i 4 iTotalAmmo FALSE
ENDIF
i = pWeapon + OFFSET_WEAPON_AMMO_CLIP
WRITE_MEMORY i 4 0 FALSE
ENDIF
// Initiate On-Foot Reload State
i = pWeapon + OFFSET_WEAPON_STATE
WRITE_MEMORY i 4 2 FALSE
RETURN
}
SCRIPT_END
@SandeMC

SandeMC commented Sep 15, 2026 •

Copy link
Copy Markdown
Author

Update

  • Added a new option, DisablePickupClipRefill
  • Cleaned up code and made use of new gta3sc features (could improve perf)
  • Reimplemented vehicle driveby logic
  • Infinite ammo fixes
  • Universal single-ammo weapon implementation
  • Two-player mode fix: both players can reload at the same time now

most of this was done by Gemini

@JuniorDjjr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment