Skip to content

Commit

Permalink
Few changes:
Browse files Browse the repository at this point in the history
- Fixed fixed-size array syntax error in tf2utils.inc
- Fixed few warnings in cwx.sp
- Moved IsEmpty() check in GetLoadoutItem so if we no longer equip a custom weapon, it equips our loadout's instead.
  • Loading branch information
CppHorse committed Apr 18, 2023
1 parent 311a08a commit 2033269
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 29 deletions.
18 changes: 10 additions & 8 deletions scripting/cwx.sp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ Action OnPlayerLoadoutUpdated(UserMsg msg_id, BfRead msg, const int[] players,
int playersNum, bool reliable, bool init) {
int client = msg.ReadByte();
s_LastUpdatedClient = GetClientSerial(client);
return Plugin_Continue;
}

/**
Expand Down Expand Up @@ -431,18 +432,17 @@ MRESReturn OnGetLoadoutItemPost(int client, Handle hReturn, Handle hParams) {
if (loadoutSlot < 0 || loadoutSlot >= NUM_ITEMS) {
return MRES_Ignored;
}

if (g_CurrentLoadout[client][playerClass][loadoutSlot].IsEmpty()) {
// we don't have nor want a custom item; let the game process it
return MRES_Ignored;
}

// the loadout entity we keep track of isn't valid, so we may need to make one
// we expect to have to equip something new at this point
int storedItem = g_CurrentLoadout[client][playerClass][loadoutSlot].entity;
if (!IsValidEntity(storedItem) || GetEntityFlags(storedItem) & FL_KILLME
|| !HasEntProp(storedItem, Prop_Send, "m_Item")) {
// the loadout entity we keep track of isn't valid, so we may need to make one
// we expect to have to equip something new at this point

if (g_CurrentLoadout[client][playerClass][loadoutSlot].IsEmpty()) {
// we don't have nor want a custom item; let the game process it
return MRES_Ignored;
}

/**
* We have a custom item we'd like to spawn in; don't return a loadout item, otherwise
* we may equip / unequip a user's inventory weapon that has side effects
Expand Down Expand Up @@ -546,6 +546,7 @@ public Action OnClientCommandKeyValues(int client, KeyValues kv) {
if (StrEqual(cmd, "MVM_Respec")) {
g_bForceReequipItems[client] = true;
}
return Plugin_Continue;
}

public void OnClientCommandKeyValues_Post(int client, KeyValues kv) {
Expand Down Expand Up @@ -632,6 +633,7 @@ int Native_RemovePlayerLoadoutItem(Handle plugin, int argc) {
int flags = GetNativeCell(4);

UnsetClientCustomLoadoutItem(client, playerClass, itemSlot, flags);
return 0;
}

/**
Expand Down
222 changes: 201 additions & 21 deletions third_party/vendored/tf2utils.inc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
#define TAKEHEALTH_IGNORE_DEBUFFS (DMG_SLASH) // Currently unused? Looks like it was originally for Pyro's FT healing debuff mechanism

/**
* Attempts to heal the player for the specified amount.
* Attempts to heal the player for the specified amount. This does not provide any indicators;
* you will need to fire any related events yourself.
*
* @param flHealth Amount of health to heal.
* @param bitsHealType TakeHealth flags. See TAKEHEALTH_* constants.
Expand All @@ -43,16 +44,180 @@ native int TF2Util_GetPlayerMaxAmmo(int client, int iAmmoIndex,
TFClassType playerClass = TFClass_Unknown);

/**
* Returns the current maximum health of the player.
* Returns the current maximum allowed health of an entity.
*/
native int TF2Util_GetPlayerMaxHealth(int client, bool bIgnoreAttributes = false,
native int TF2Util_GetEntityMaxHealth(int entity);

/**
* Returns the maximum allowed overhealed health of a player, taking into account the amount
* it can gain through overhealing by mediguns.
*
* @param bIgnoreAttributes
* @param bIgnoreOverheal Ignores excessive overheal.
*/
native int TF2Util_GetPlayerMaxHealthBoost(int client, bool bIgnoreAttributes = false,
bool bIgnoreOverheal = false);

/**
* Returns the number of conditions currently available in the game. This value will be one
* higher than the last valid condition.
*/
native int TF2Util_GetConditionCount();

/**
* Returns the last valid condition. Convenience function intended for loop termination.
*/
stock TFCond TF2Util_GetLastCondition() {
return view_as<TFCond>(TF2Util_GetConditionCount() - 1);
}

/**
* Given a valid condition index, stores its name in the given buffer.
*
* @param cond Condition index.
* @param buffer Buffer to store name.
* @param maxlen Maximum length of buffer.
* @return Number of bytes written.
* @error Condition index is invalid.
*/
native int TF2Util_GetConditionName(TFCond cond, char[] buffer, int maxlen);

/**
* Returns the remaining time on a player condition, or 0.0 if the condition is not active.
*
* This is just a wrapper around the internal condition list; some conditions may not accurately
* report their duration here (such as burning).
*/
native float TF2Util_GetPlayerConditionDuration(int client, TFCond cond);

/**
* Sets the remaining time on a player condition without reapplying the condition.
*
* @error Condition is not active.
*/
native void TF2Util_SetPlayerConditionDuration(int client, TFCond cond, float duration);

/**
* Returns the entity providing a player condition, or INVALID_ENT_REFERENCE if the condition is
* not active. 0 is returned for "no inflictor".
*
* (This is the entity described as the "inflictor" for `TF2_AddCondition`.)
*/
native int TF2Util_GetPlayerConditionProvider(int client, TFCond cond);

/**
* Sets the entity providing a player condition without reapplying the condition.
*
* (This is the entity described as the "inflictor" for `TF2_AddCondition`.)
*
* @error Condition is not active.
*/
native void TF2Util_SetPlayerConditionProvider(int client, TFCond cond, int inflictor);

/**
* Returns the remaining burn time on a given player. By default this decreases at a fixed rate
* over time; the rate may change based on fire resistances (such as while cloaked).
*
* If the player is not burning, 0.0 is returned.
*/
native float TF2Util_GetPlayerBurnDuration(int client);

/**
* Updates the remaining burn time on a given player. This does not ignite players. This
* bypasses the 10 second maximum burn duration limitation added in Jungle Inferno; however,
* this will be clamped the next time the game needs to update the burn duration.
*
* @error Player is not already burning.
*/
native void TF2Util_SetPlayerBurnDuration(int client, float duration);

/**
* Sets a client on fire. This is effectively the same as `TF2_IgnitePlayer` but with the
* additional ability to set the weapon (allowing attribute modifiers to take effect).
*
* @param client Target client index.
* @param attacker Attacker client index, or INVALID_ENT_REFERENCE for none.
* @param duration Duration of fire, in seconds.
* @param weapon Weapon entity, or INVALID_ENT_REFERENCE for none.
*
* @note As of Jungle Inferno, fire duration is capped to 10 seconds.
* @error Invalid clients, or non-weapon entity.
*/
native void TF2Util_IgnitePlayer(int client, int attacker, float duration,
int weapon = INVALID_ENT_REFERENCE);

/**
* Returns true if the given player is immune to pushback.
*
* @param client Client index.
*
* @error Invalid client or not in game.
*/
native bool TF2Util_IsPlayerImmuneToPushback(int client);

/**
* Returns the player's respawn time override, if any. This is the number of seconds that a
* player will spend waiting to be respawned after their last death (CTFPlayer::m_flDeathTime).
*
* When a player dies, the game will set this value to -1.0 or the RespawnTime value of an
* active trigger_player_respawn_override entity that the player died in, if one exists.
* (This happens *after* the `player_death` event is fired, so you cannot retrieve their respawn
* time override during a hook on that event.)
*
* The amount of time remaining can be computed as follows:
*
* flRemainingTime = flDeathTime + flRespawnTimeOverride - GetGameTime();
*
* If the player does not have an override on their respawn time (i.e. they are part of normal
* respawn waves), this will return -1.0. If the player is alive, this will return whatever is
* stored on the entity (normally -1.0), and *not* any buffered value that was set using
* `TF2Util_SetPlayerRespawnTimeOverride`.
*
* @error Invalid client.
*/
native float TF2Util_GetPlayerRespawnTimeOverride(int client);

/**
* Changes the player's respawn time override. See `TF2Util_GetPlayerRespawnTimeOverride` above
* for an explanation of the value.
*
* If the player is not alive, setting this value to -1.0 will remove any existing respawn time
* overrides, and the player will respawn in the next wave they are allowed to spawn in.
*
* If the player is alive, setting this value to one other than -1.0 will cause TF2Utils to
* buffer the value and update the player's respawn time override at some point after they die
* (allowing plugins to set a respawn time override while the player is alive or during a
* `player_death` event hook).
*
* @error Invalid client.
*/
native void TF2Util_SetPlayerRespawnTimeOverride(int client, float time);

/**
* Returns the player's shoot position.
*/
native void TF2Util_GetPlayerShootPosition(int client, float result[3]);

/**
* @return Object (building) entity index at the given index.
* @error Entity is not a client or index is out of bounds.
*/
native int TF2Util_GetPlayerObject(int client, int index);

/**
* @return Number of objects (buildings) in a given client's object array.
* @error Entity is not a client.
*/
native int TF2Util_GetPlayerObjectCount(int client);

/**
* Returns the healer entity index at the given position in the player's healer array.
* To get the number of healers available, use the m_nNumHealers netprop.
*
* @return Healer entity index at the given index.
*/
native int TF2Util_GetPlayerHealer(int client, int index);

/**
* Returns whether or not the given entity is a weapon.
*
Expand All @@ -68,29 +233,31 @@ native bool TF2Util_IsEntityWeapon(int entity);
native bool TF2Util_IsEntityWearable(int entity);

/**
* Returns the slot for the given weapon entity.
* Returns the slot for the given weapon entity. This corresponds to the TFWeaponSlot_*
* constants in tf2_stocks.
*
* @error Entity is not valid or not a weapon.
*/
native int TF2Util_GetWeaponSlot(int entity);

/**
* Returns the weapon entity's weapon ID. This corresponds to the TF_WEAPON_* weapon codes in
* Returns the weapon entity's weapon ID. This corresponds to the TF_WEAPON_* constants in
* tf2_stocks, *not* the item definition index.
*
* @error Entity is not valid or not a weapon.
*/
native int TF2Util_GetWeaponID(int entity);

/**
* Returns the weapon entity's maximum clip.
* Returns the weapon entity's maximum clip (that is, the maximum number of times it can be
* fired before reloading).
*
* @error Entity is not valid or not a weapon.
*/
native int TF2Util_GetWeaponMaxClip(int entity);

/**
* @return Wearable entity at the given index.
* @return Client's wearable entity at the given index.
* @error Index is negative or out of bounds.
*/
native int TF2Util_GetPlayerWearable(int client, int index);
Expand All @@ -102,11 +269,16 @@ native int TF2Util_GetPlayerWearableCount(int client);

/**
* If `includeWearableWeapons` is true, weapon slots (primary, secondary, melee, utility,
* building, pda, pda2) are also checked for wearable items. Otherwise, non-wearables are
* ignored.
* building, pda, pda2) are also checked for wearable items. Otherwise, wearables in those
* slots (Sniper / Demoman shields) are ignored.
*
* Note that this validates that the player is using a class that can equip the given item; any
* items not applicable to the class are ignored.
* Note that the game validates that the player is using a class that can equip the given item;
* any items not applicable to the class are ignored.
*
* This also does not differentiate between different cosmetic slots (all cosmetics will match
* on the first loadout slot). If you want to get cosmetic entities on a given player, you will
* instead want to use `TF2Util_GetPlayerWearable` / `TF2Util_GetPlayerWearableCount`.
* Identifying specific occupied cosmetic loadout slots is currently not supported.
*
* @return Entity on the given client occupying the given loadout slot.
*/
Expand All @@ -116,7 +288,8 @@ native int TF2Util_GetPlayerLoadoutEntity(int client, int loadoutSlot,
/**
* Equips the given wearable entity onto the given client.
*
* @error Client is invalid or entity is not a wearable.
* @error Client is invalid, entity is not a wearable, wearable was not spawned, or assertion
* failed to verify that the wearable was successfully attached (outdated gamedata).
*/
native void TF2Util_EquipPlayerWearable(int client, int wearable);

Expand All @@ -125,8 +298,8 @@ native void TF2Util_EquipPlayerWearable(int client, int wearable);
*
* @param immediate Whether or not the speed is updated immediately. If this is set to
* false, the call will be defered and batched so all non-immediate calls
* will only trigger one update to the player's speed at most. (This is
* designed to accomodate plugins using detours on player speed
* will only trigger one update to the player's speed at most per frame.
* (This is designed to accomodate plugins using detours on player speed
* calculations.)
*/
native void TF2Util_UpdatePlayerSpeed(int client, bool immediate = false);
Expand All @@ -136,16 +309,23 @@ native void TF2Util_UpdatePlayerSpeed(int client, bool immediate = false);
* passed in, this also checks if the entity is touching an active respawn room, instead of just
* the given position.
*
* @param position A position to check. Should be the center / origin of an entity.
* @param entity An optional entity to check.
* @param bTouchingSameTeam Whether or not the respawn room must either match the entity's
* team, or not be assigned to a team. Always treated as true if
* the position is in an active spawn room. Has no effect if no
* entity is provided.
* @param position Position to check; should be the center / origin of an entity.
* @param entity An optional entity to check.
* @param bRestrictToSameTeam Whether or not the respawn room must either match the entity's
* team, or not be assigned to a team. Always treated as true if
* the position is in an active spawn room. Has no effect if no
* entity is provided.
*/
native bool TF2Util_IsPointInRespawnRoom(const float[3] position,
native bool TF2Util_IsPointInRespawnRoom(const float position[3],
int entity = INVALID_ENT_REFERENCE, bool bRestrictToSameTeam = false);

/**
* Returns the current maximum health of the player.
*/
#pragma deprecated Misnamed; use TF2Util_GetEntityMaxHealth or TF2Util_GetPlayerMaxHealthBoost.
native int TF2Util_GetPlayerMaxHealth(int client, bool bIgnoreAttributes = false,
bool bIgnoreOverheal = false);

// compile-time compatibility shim for tf2wearables natives
#if defined USE_TF2WEARABLE_FUNCTION_SHIMS
#define TF2_GetPlayerLoadoutSlot TF2Util_GetPlayerLoadoutEntity
Expand Down

0 comments on commit 2033269

Please sign in to comment.