Theme
Stats and ammo
Health, resources, skill points, stealth and ammo.
| Export | Summary |
|---|---|
ShGetHealthPlayer | Health, local player. |
ShSetHealthPlayer | See ShGetHealthPlayer. |
ShSetGodModePlayer | See ShGetHealthPlayer. |
ShDamagePlayer | Damage through the engine's own path, so death runs its real sequence. |
ShKillPlayer | See ShDamagePlayer. |
ShSetCannotDiePlayer | Floors at the downed state instead of dying. |
ShInvalidateHealth | See ShSetCannotDiePlayer. |
ShGetHealthEntity | Entity targeted variants. |
ShSetHealthEntity | See ShGetHealthEntity. |
ShSetGodModeEntity | See ShGetHealthEntity. |
ShStatRead | Protected ints, the general stat storage: four bit planes and an XOR key. |
ShStatWrite | See ShStatRead. |
ShGetResource | — |
ShSetResource | — |
ShSetAllResources | — |
ShGetResourceSlot | One entry of the resource node, by its own order rather than by name - for a probe. |
ShGetSkillPoints | Skill points, a plain int rather than a protected one. |
ShSetSkillPoints | See ShGetSkillPoints. |
ShSetVisibility | Visibility to enemies. |
ShGetVisibility | See ShSetVisibility. |
ShSetAmmoScale | The MAGAZINE CAPACITY the game computes for a weapon, scaled by a num/den pair (2,1 double, 1,2 half, 1,1 the game's own value). |
ShGetAmmoScale | What is in force, as the pair. |
ShAmmoScaleActive | 1 while a scale other than 1/1 is in force. |
ShGetAmmo | Rounds in weapon slot slot - slot 0 only, the weapon in hand, and the MAGAZINE rather than the reserve. |
ShSetAmmo | Write one number into weapon slot slot - slot 0 only, the weapon in hand. |
ShGetAmmoLook | The last capacity look, or 0 with SH_ERR_NO_CANDIDATE before the first one (and when no hook is installed at all - see ShSetAmmoScale: asking for 1/1 leaves the game alone and installs nothing, so a p… |
ShGetAmmoRounds | Rounds left in the magazine of the weapon the engine last asked for a capacity - the local player's own weapon, and the number the HUD shows. |
ShGetAmmoObject | Which weapon the last ShGetAmmoRounds reading was about. |
ShGetAmmoCalls | The last calls that changed WHICH object was asked about, oldest first, up to max of them. |
ShGetHealthPlayer
c
SH_API int ShGetHealthPlayer(uint32_t *cur, uint32_t *max);Health, local player. The API owns the reference: it resolves and caches internally, plugins never hold one.
scripthook.h, line 2842
ShSetHealthPlayer
c
SH_API int ShSetHealthPlayer(uint32_t value);Documented together with ShGetHealthPlayer just above.
scripthook.h, line 2843
ShSetGodModePlayer
c
SH_API int ShSetGodModePlayer(int on);Documented together with ShGetHealthPlayer just above.
scripthook.h, line 2844
ShDamagePlayer
c
SH_API int ShDamagePlayer(uint32_t amount);Damage through the engine's own path, so death runs its real sequence. Queued onto the game thread.
scripthook.h, line 2849
ShKillPlayer
c
SH_API int ShKillPlayer(void);Documented together with ShDamagePlayer just above.
scripthook.h, line 2850
ShSetCannotDiePlayer
c
SH_API int ShSetCannotDiePlayer(int on);Floors at the downed state instead of dying.
scripthook.h, line 2852
ShInvalidateHealth
c
SH_API void ShInvalidateHealth(void);Documented together with ShSetCannotDiePlayer just above.
scripthook.h, line 2853
ShGetHealthEntity
c
SH_API int ShGetHealthEntity(uint64_t entity, uint32_t *cur,
uint32_t *max);Entity targeted variants. The entity comes from the enumerator, never from a raw pointer a plugin invented.
scripthook.h, line 2858
ShSetHealthEntity
c
SH_API int ShSetHealthEntity(uint64_t entity, uint32_t value);Documented together with ShGetHealthEntity just above.
scripthook.h, line 2860
ShSetGodModeEntity
c
SH_API int ShSetGodModeEntity(uint64_t entity, int on);Documented together with ShGetHealthEntity just above.
scripthook.h, line 2861
ShStatRead
c
SH_API int ShStatRead(uint64_t stat, uint32_t *out);Protected ints, the general stat storage: four bit planes and an XOR key. Health, resources, skill points, XP.
scripthook.h, line 2866
ShStatWrite
c
SH_API int ShStatWrite(uint64_t stat, uint32_t value);Documented together with ShStatRead just above.
scripthook.h, line 2867
ShGetResource
c
SH_API int ShGetResource(int which, uint32_t *out);No doc comment in the header.
scripthook.h, line 2874
ShSetResource
c
SH_API int ShSetResource(int which, uint32_t value);No doc comment in the header.
scripthook.h, line 2875
ShSetAllResources
c
SH_API int ShSetAllResources(uint32_t value);No doc comment in the header.
scripthook.h, line 2876
ShGetResourceSlot
c
SH_API int ShGetResourceSlot(int i, uint32_t *spec, uint32_t *value,
uint64_t *prot);One entry of the resource node, by its own order rather than by name - for a probe. The node the four named resources live in holds EIGHT entries, and what the other four are is a question worth answering from a log instead of a heap scan: a count that moves by one per shot would be cheap to reach there, with no hook at all.
i runs from 0 to the count the node reports. *value is the decoded int behind the entry, *prot the address of the protected int itself; either may be NULL. 1 when the row exists, 0 with SH_ERR_NO_CANDIDATE past the end or while the manager is not up.
scripthook.h, line 2888
ShGetSkillPoints
c
SH_API int ShGetSkillPoints(uint32_t *out);Skill points, a plain int rather than a protected one.
scripthook.h, line 2892
ShSetSkillPoints
c
SH_API int ShSetSkillPoints(uint32_t value);Documented together with ShGetSkillPoints just above.
scripthook.h, line 2893
ShSetVisibility
c
SH_API int ShSetVisibility(float factor);Visibility to enemies. 1 normal, 0 invisible, 0.5 halves the detection range, above 1 is easier to spot.
scripthook.h, line 2898
ShGetVisibility
c
SH_API int ShGetVisibility(float *out);Documented together with ShSetVisibility just above.
scripthook.h, line 2899
ShSetAmmoScale
c
SH_API int ShSetAmmoScale(int num, int den);The MAGAZINE CAPACITY the game computes for a weapon, scaled by a num/den pair (2,1 double, 1,2 half, 1,1 the game's own value).
Capacity is the return value of one engine function (RVA 0x614CB0) and is stored nowhere, so this hook is the only way to change it - reading memory cannot find it. See docs/ammocapacity-reverse.md (kept out of the repository).
The hook installs on the first call that asks for something other than 1,1; asking for 1,1 first leaves the game alone and installs nothing. A change takes effect at the next refill: an ammo crate is what puts the number to use. 1 on success, 0 with ShLastError saying why (SH_ERR_BAD_ARG, SH_ERR_HOOK_FAILED).
scripthook.h, line 2914
ShGetAmmoScale
c
SH_API void ShGetAmmoScale(int *num, int *den);What is in force, as the pair. 1/1 when nothing was ever set.
scripthook.h, line 2916
ShAmmoScaleActive
c
SH_API int ShAmmoScaleActive(void);1 while a scale other than 1/1 is in force.
scripthook.h, line 2918
ShGetAmmo
c
SH_API int ShGetAmmo(int slot, uint32_t *out);Rounds in weapon slot slot - slot 0 only, the weapon in hand, and the MAGAZINE rather than the reserve.
This is the upstream framework's slot API, restored for the plugins that were written against it: the same arguments, the same error codes, and for slot 0 the same number. Those plugins resolve it by name out of this module, which is the only reason it is exported again - the rounds of the weapon in hand have ShGetAmmoRounds, which is the same answer.
Slot 0 is that weapon: exactly the protected int ShGetAmmoRounds reports, at exactly the address it is read from. Slots 1..7 answer 0 with SH_ERR_NO_CANDIDATE, and that is not a stub - the eight-slot table the upstream indexed does not exist in this build. Read-only forensics against the running process (2026-10-28) found nothing shaped like it: no owner handle at +0x250 on anything whose +0x180/+0x130 decode as numbers, and no 0x28-strided table in the player's component array or in the region the hand weapon lives in. Those eight magazines are not stored anywhere this framework can point at, so a caller is told that instead of being handed a plausible integer from unrelated memory. See the slot pair in scripthook_ammocap.c.
A caller that loops 0..7 expecting eight magazines is therefore not served here; one that asks for slot 0 - what an ammo readout does - is. Nothing is scanned to answer: the cost is one protected-int read on top of the same lookup ShGetAmmoRounds does, and nothing runs on the frame.
Not from a frame callback or the game thread: the answer there is 0 with SH_ERR_NO_CANDIDATE, without looking. Slot out of range or a NULL out is SH_ERR_BAD_ARG; no weapon in hand (before the capacity function has been asked once, or outside live play) is SH_ERR_NO_CANDIDATE, which is what the upstream answered in the same situation.
The version number did not move for this (see the note above it), so a caller must treat a NULL export as "this build predates the restoration".
scripthook.h, line 2955
ShSetAmmo
c
SH_API int ShSetAmmo(int slot, uint32_t value);Write one number into weapon slot slot - slot 0 only, the weapon in hand.
The write lands on the int the ShGetAmmo(0) reading comes from, so the two entry points cannot disagree about which magazine they mean. The engine recomputes a magazine's contents on its own schedule, so a value written here can be overwritten - the upstream entry point behaves the same way and this is deliberately not "improved" into something with different semantics. Same range, same thread rule and the same error codes as ShGetAmmo, plus SH_ERR_UNWRITABLE when the store itself fails.
scripthook.h, line 2968
ShGetAmmoLook
c
SH_API int ShGetAmmoLook(ShAmmoLook *out);The last capacity look, or 0 with SH_ERR_NO_CANDIDATE before the first one (and when no hook is installed at all - see ShSetAmmoScale: asking for 1/1 leaves the game alone and installs nothing, so a probe asks for some other scale first and puts 1/1 back once it has what it came for).
scripthook.h, line 2990
ShGetAmmoRounds
c
SH_API int ShGetAmmoRounds(int *rounds);Rounds left in the magazine of the weapon the engine last asked for a capacity - the local player's own weapon, and the number the HUD shows.
How it is reached, because finding it took a while: the engine hands that weapon to the one function that computes a magazine's capacity (the one ShSetAmmoScale hooks), ShGetAmmoLook reports which object that was, and the rounds are a protected int 0x180 into it - 0x130 for the weapons that keep them there. No heap scan, no class constant, nothing cached. ShGetAmmo and ShSetAmmo reach the same int through this one, so slot 0 of that pair and this function cannot disagree.
0 with SH_ERR_NO_CANDIDATE until the engine has asked once, which firing a round or switching a weapon makes it do - so the capacity hook has to be installed (asking for 1/1 alone installs nothing: see ShSetAmmoScale). SH_ERR_BAD_ARG for a NULL out. This is the magazine, not the reserve: reloading puts it back to the capacity that ShSetAmmoScale scales.
A weapon switch is followed within a frame or two: the engine asks about the weapon coming up (the HUD redraws its number, a shot asks) and stops asking about the one that went down, and the reading follows the newest of those calls that is the player's own before it follows anything else. ShGetAmmoObject names the object the answer came from.
scripthook.h, line 3014
ShGetAmmoObject
c
SH_API int ShGetAmmoObject(uint64_t *obj);Which weapon the last ShGetAmmoRounds reading was about.
The rounds alone cannot say that the weapon in hand changed - two weapons read the same number often, and the value a switch shows is the one the plugin was just told - so this is what a caller watches to notice that the magazine it was following has been put away. Set by ShGetAmmoRounds, which has to have answered at least once: 0 with SH_ERR_NO_CANDIDATE until then, and SH_ERR_BAD_ARG for a NULL out.
scripthook.h, line 3024
ShGetAmmoCalls
c
SH_API int ShGetAmmoCalls(ShAmmoCall *out, int max);The last calls that changed WHICH object was asked about, oldest first, up to max of them. A weapon switch runs both the weapon going down and the one coming up through this function, and nothing about those objects says which is which - so the order they were asked in is the only evidence there is. Only transitions are recorded, so one switch is one burst. A probe reads this while switching weapons; a plugin that ships has no reason to.
scripthook.h, line 3040