This is an include that provides a more consistent and responsive damage system with many new features.
It's pretty much plug-and-play if you don't have any filterscripts that interfere with the health or death events.
-
#include <weapon-config>
before any other script -
Replace
OnPlayerGiveDamage
andOnPlayerTakeDamage
with just one callback:public OnPlayerDamage(&playerid, &Float:amount, &issuerid, &WEAPON:weapon, &bodypart)
-
Add config functions in
OnGameModeInit
(or any other places, they can be called at any time).
Recommended:public OnGameModeInit() { SetVehiclePassengerDamage(true); SetDisableSyncBugs(true); }
This include file requires the SKY or Pawn.RakNet plugin.
Note: SKY has a higher priority if the user has not included any of these dependencies before weapon-config (it will automatically try to include SKY and only then Pawn.RakNet, if fail with the first). Also, SKY will take precedence if both dependencies are included (it will use the SKY plugin instead of Pawn.RakNet).
- Server-side health
- Impossible to use health hacks on lagcomp mode
- Any type of damage can be modified/prevented, even falling 1000m from the sky
- Vending machines are controlled server-side (buildings removed and objects created)
- Paused players can be killed (with death animations) and their HP bars always show the correct values
- Destroy vehicles with a passenger but no driver
- Custom falling damage (optional)
- Adjust the damage and at which speed a player will die
- Sounds and on-screen TextDraw indicators of damage given/taken
- Also shows another player's damage feed when spectating
- New weapon types detected:
WEAPON_PISTOLWHIP
- When you punch someone with a gunWEAPON_VEHICLE_M4
- Vehicles with M4 guns (e.g. Rustler)WEAPON_VEHICLE_MINIGUN
- Vehicles with miniguns (e.g. Hunter)WEAPON_VEHICLE_ROCKETLAUNCHER
- Vehicles with projectiles (e.g. Rhino)WEAPON_HELIBLADES
- HelikillWEAPON_CARPARK
- When you park your car on someone
- Extensive sanity checking on shots:
- Modified weapon.dat is automatically detected
- Shot vector, player distance, and much more is examined
- A callback is invoked for each so-called "rejected hit" so that the player is informed. A few of these are:
- Inflicting damage when already dead (due to lag)
- Hit a player too far from the shot hit position (due to severe lag or cheating)
- Hitting/shooting too fast (due to severe lag or cheating)
- Modify every weapon's damage amount
- To a single value
- To multiple values depending on the shot distance
- With custom logic in a callback, for example:
- Increase damage for headshots
- Increase/lower damage for combos
- Lower damage for c-bug rapid fire
- Knife sync fixed in both lagcomp and no-lagcomp
- New death animations and respawn logic
- Customize respawn time globally and for each death
- Fully customizable animations, with a nice set of defaults
- Different animation depending on weapon/bodypart, for example:
- Headshots make you fall back with both hands in your face
- Shotgun kills make you fly backward like in GTA:VC (unless killed from behind)
All players are given infinite health and set to the same team. Damage is counted by the script whenever OnPlayer(Give/Take)Damage
is called. The real GetPlayerHealth
is never read by the include file.
The players healthbars are modified by editing SA-MP packets, so they are very responsive.
The death animations are applied as "forcesync" and even the facing angle is force synced (with SKY or Pawn.RakNet). This allows perfect animations even for laggy/paused players.
The real OnPlayerDeath
is never called from the SA-MP server (only in some rare cases). A player never actually dies in their game - they just see a death animation applied and get respawned.
Many SA-MP functions are hooked to provide new values (such as GetPlayerState
, (Get/Set)Player(Health/Armour)
, GetPlayerTeam
).
At the moment, filterscripts are not fully supported. If you need to modify the health, go into spec mode, change the virtual world, and more then you should do it through the gamemode.
A simple workaround is to just do something like this:
// In the gamemode
forward SetHealth(playerid, Float:health);
public SetHealth(playerid, Float:health) {
SetPlayerHealth(playerid, health);
}
// In the filterscript
CallRemoteFunction("SetHealth", "if", playerid, health);
OnPlayerGiveDamage
and OnPlayerTakeDamage
are removed. Use OnPlayerDamage
(see below).
OnPlayerDeath
and OnPlayerWeaponShot
are called as usual.
public OnPlayerDamage(&playerid, &Float:amount, &issuerid, &WEAPON:weapon, &bodypart)
Called when damage is about to be inflicted on a player Most arguments can be modified (e.g. the damage could be adjusted)
playerid
- The player who is about to get damagedamount
- The amount of damage about to get inflicted (0.0 means all HP) This will not always be the same in OnPlayerDamageDone, for example: if amount is 50.0 and you have 10.0, only 10.0 will be reported in OnPlayerDamageDoneweapon
- The weapon used to inflict the damagebodypart
- The bodypart
Return 0 to prevent the damage from being inflicted
public OnPlayerDamageDone(playerid, Float:amount, issuerid, WEAPON:weapon, bodypart)
Called after damage has been inflicted
Same parameters as above, but they can not be modified
Return value ignored
public OnPlayerPrepareDeath(playerid, animlib[32], animname[32], &anim_lock, &respawn_time)
Before the death animation is applied
playerid
- The player that is about to dieanimlib
- The anim lib to play (change to empty string for no animation)animname
- The anim name to playanim_lock
- The "lock" parameter in ApplyAnimationrespawn_time
- The time (in milliseconds) until the player respawns
Return value ignored
public OnPlayerDeathFinished(playerid)
When the death animation has finished and the player has been sent to respawn
playerid
- The player
Return value ignored
public OnRejectedHit(playerid, hit[E_REJECTED_HIT])
When a shot or damage given is rejected See E_REJECTED_HIT and GetRejectedHit for more
playerid
- The player whose hit was rejectedhit
- An enum containing information about the rejected hit
Return value ignored
public OnInvalidWeaponDamage(playerid, damagedid, Float:amount, WEAPON:weaponid, bodypart, error, bool:given)
When a player takes or gives invalid damage (WC_* errors above)
playerid
- The player that inflicted the damagedamagedid
- The player that took or was given a hitamount
- The damage amount inflictedweaponid
- The weapon usedbodypart
- The bodyparterror
- Which error (see the enum containing WC_NO_ERROR)given
-true
means thatplayerid
reported the damage inOnPlayerGiveDamage
,false
means thatdamagedid
reported the damage inOnPlayerTakeDamage
Return value ignored
AverageShootRate(playerid, shots, &multiple_weapons = 0);
The average time (in milliseconds) between shots.
playerid
- The playerhits
- Number of hits to average on (max 10)multiple_weapons
- Will be set to 1 if different weapons were used in the last shots
Returns -1 if there is not enough data to calculate the rate, otherwise the average time is returned.
AverageHitRate(playerid, hits, &multiple_weapons = 0);
Same as above, but for hits inflicted with OnPlayerGiveDamage
DamagePlayer(playerid, Float:amount, issuerid = INVALID_PLAYER_ID, WEAPON:weaponid = WEAPON_UNKNOWN, bodypart = BODY_PART_UNKNOWN, bool:ignore_armour = false);
Inflict a hit on a player. All callbacks except OnPlayerWeaponShot
will be called.
Note: do not use it inside OnPlayerDamage as you can just modify amount
there
ignore_armour
- Whentrue
will do damage straight to health, and not armour.
Float:GetPlayerHealth(playerid, &Float:health = 0.0);
Hooked version of the original, which also returns the value
Float:GetPlayerArmour(playerid, &Float:armour = 0.0);
Hooked version of the original, which also returns the value
GetRejectedHit(playerid, idx, output[], maxlength = sizeof(output));
Get a string explaining why the hit was rejected at idx (max. WC_MAX_REJECTED_HITS - 1
)
SetRespawnTime(ms);
Set the respawn time in milliseconds
GetRespawnTime();
Get the respawn time
IsBulletWeapon(WEAPON:weaponid);
Returns true if the weapon shoots bullets
IsHighRateWeapon(WEAPON:weaponid);
Returns true if the weapon's damage can be reported in high rates to the server (such as fire)
IsMeleeWeapon(WEAPON:weaponid);
Returns true if it's a melee weapon (including WEAPON_PISTOLWHIP
)
IsPlayerDying(playerid);
Returns true if the player is between the dying animation and spawning
WC_IsPlayerSpawned(playerid);
Returns true if the player is spawned and not in a dying animation
WC_IsPlayerPaused(playerid);
Returns true if the player is paused (AFK) within last two seconds
GetWeaponName(WEAPON:weaponid, weapon[], len = sizeof(weapon));
Hooked version of the native, fixed and containing custom weapons (such as pistol whip)
ReturnWeaponName(WEAPON:weaponid);
Return the weapon name (uses the fixed GetWeaponName)
SetCustomFallDamage(bool:toggle, Float:damage_multiplier = 25.0, Float:death_velocity = -0.6);
Toggle custom falling damage
SetCustomVendingMachines(bool:toggle);
Toggle vending machines (they are removed and disabled by default)
SetCbugAllowed(bool:enabled, playerid = INVALID_PLAYER_ID);
Toggle anti-cbug per player or globally. (Using no playerid param will default all users to default)
bool:GetCbugAllowed(playerid = INVALID_PLAYER_ID);
Check if users anti-cbug is toggled. (Using no playerid param will show the global toggle value)
SetDamageFeed(bool:toggle);
Toggle damage feed for all
SetDamageFeedForPlayer(playerid, toggle = -1);
Toggle damage feed for player
IsDamageFeedActive(playerid = -1);
Returns true if damage feed is active for player (for all, if playerid
passed as -1)
SetDamageSounds(taken, given);
Set sounds when damage is given and taken (0 to disable)
SetVehiclePassengerDamage(bool:toggle);
Allow vehicles to be damaged when they have a passenger and no driver
SetVehicleUnoccupiedDamage(bool:toggle);
Allow vehicles to be damaged when they don't have any players inside them
SetWeaponDamage(WEAPON:weaponid, damage_type, Float:amount, Float:...);
Modify a weapon's damage
weaponid
- The weapon to modifydamage_type
- One of the following:- DAMAGE_TYPE_MULTIPLIER Multiply the original damage inflicted by amount This is default for melee, grenades, and other weapons that inflict different amounts of damage (shotguns excluded)
- DAMAGE_TYPE_STATIC Inflict a specific amount of damage for each hit For shotguns, this modifies the value for each bullet that hit the player Combat shotgun shoots 8 bullets, other shotguns shoot 15
- DAMAGE_TYPE_RANGE_MULTIPLIER Same as DAMAGE_TYPE_MULTIPLIER, but the damage depends on the distance
- DAMAGE_TYPE_RANGE Same as DAMAGE_TYPE_STATIC, but the damage depends on the distance
amount
- The amount of damage...
- Ifdamage_type
containsRANGE
, the arguments should be a list of ranges and damage For example:This will make sniper damage:SetWeaponDamage(WEAPON_SNIPER, DAMAGE_TYPE_RANGE, 40.0, 20.0, 30.0, 60.0, 20.0);
40
if distance is less than20
30
if distance is less than60
20
for any other distance
Float:GetWeaponDamage(WEAPON:weaponid);
Get the amount of damage of a weapon
SetWeaponMaxRange(WEAPON:weaponid, Float:range);
Set the max range of a weapon. The default value is those from weapon.dat Because of a SA-MP bug, weapons can (and will) exceed this range. This script, however, will block those out-of-range shots and give a rejected hit.
Float:GetWeaponMaxRange(WEAPON:weaponid);
Get the max range of a weapon
SetWeaponShootRate(WEAPON:weaponid, max_rate);
Set the max allowed shoot rate of a weapon. Could be used to prevent C-bug damage or allow infinite shooting if a script uses GivePlayerWeapon to do so.
GetWeaponShootRate(WEAPON:weaponid);
Get the max allowed shoot rate of a weapon
SetCustomArmourRules(bool:armour_rules, bool:torso_rules);
Toggle the custom armour rules on and off. Both are disabled by default.
armour_rules
- Toggle all of the rules. When off, nothing is affected. Armour is affected as it normally would. When on, weapons can be set to either damage armour before health or just take health and never damage armour.torso_rules
- Toggle all torso-only rules. When off, all weapons will have effects no matter which bodypart is 'hit'. When on, weapons with thetorso_only
rule (ofSetWeaponArmourRule
) on will only damage armour when the torso is 'hit' (and when it's off, armour is damaged no matter which body part is 'hit').
SetWeaponArmourRule(WEAPON:weaponid, bool:affects_armour, bool:torso_only);
Set custom rules for a weapon. The defaults aren't going to comfort EVERYONE, so everyone needs the ability to modify the weapons themselves.
weaponid
- The ID of the weapon to modify the rules of.affects_armour
- Whether this weapon will distribute damage over armour and health or just damage health directly.torso_only
- Whether this weapon will only damage armour when the 'hit' bodypart is the torso or all bodyparts. Only works whentorso_rules
are enabled usingSetCustomArmourRules
.
EnableHealthBarForPlayer(playerid, bool:enable);
Show or hide health bar for player.