Skip to content

Stats and ammo ​

Group stats · 29 exports · from forks/gamexueren/scripthook.h (framework 1.0-beta7-wildm1, SH_API_VERSION 2)

Health, resources, skill points, stealth and ammo.

ExportSummary
ShGetHealthPlayerHealth, local player.
ShSetHealthPlayerSee ShGetHealthPlayer.
ShSetGodModePlayerSee ShGetHealthPlayer.
ShDamagePlayerDamage through the engine's own path, so death runs its real sequence.
ShKillPlayerSee ShDamagePlayer.
ShSetCannotDiePlayerFloors at the downed state instead of dying.
ShInvalidateHealthSee ShSetCannotDiePlayer.
ShGetHealthEntityEntity targeted variants.
ShSetHealthEntitySee ShGetHealthEntity.
ShSetGodModeEntitySee ShGetHealthEntity.
ShStatReadProtected ints, the general stat storage: four bit planes and an XOR key.
ShStatWriteSee ShStatRead.
ShGetResource—
ShSetResource—
ShSetAllResources—
ShGetResourceSlotOne entry of the resource node, by its own order rather than by name - for a probe.
ShGetSkillPointsSkill points, a plain int rather than a protected one.
ShSetSkillPointsSee ShGetSkillPoints.
ShSetVisibilityVisibility to enemies.
ShGetVisibilitySee ShSetVisibility.
ShSetAmmoScaleThe 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).
ShGetAmmoScaleWhat is in force, as the pair.
ShAmmoScaleActive1 while a scale other than 1/1 is in force.
ShGetAmmoRounds in weapon slot slot - slot 0 only, the weapon in hand, and the MAGAZINE rather than the reserve.
ShSetAmmoWrite one number into weapon slot slot - slot 0 only, the weapon in hand.
ShGetAmmoLookThe 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…
ShGetAmmoRoundsRounds 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.
ShGetAmmoObjectWhich weapon the last ShGetAmmoRounds reading was about.
ShGetAmmoCallsThe 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

WildM is an independent community project. It is not affiliated with or endorsed by Ubisoft. Ghost Recon Wildlands is a trademark of Ubisoft Entertainment.