Initial commit
This commit is contained in:
237
scripting/towerdefense/util/metal.sp
Normal file
237
scripting/towerdefense/util/metal.sp
Normal file
@@ -0,0 +1,237 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#if defined INFO_INCLUDES
|
||||
#include "../info/constants.sp"
|
||||
#include "../info/enums.sp"
|
||||
#include "../info/variables.sp"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets a clients current metal amount.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @return The clients current metal.
|
||||
*/
|
||||
|
||||
stock int GetClientMetal(int iClient) {
|
||||
return GetEntData(iClient, FindDataMapInfo(iClient, "m_iAmmo") + (3 * 4), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a clients metal amount.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param iMetal The metal amount the client should get.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void SetClientMetal(int iClient, int iMetal) {
|
||||
SetEntData(iClient, FindDataMapInfo(iClient, "m_iAmmo") + (3 * 4), iMetal, 4);
|
||||
|
||||
Log(TDLogLevel_Trace, "Set %N's metal to %d", iClient, iMetal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a clients metal amount back to zero.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void ResetClientMetal(int iClient) {
|
||||
CreateTimer(0.0, ResetClientMetalDelayed, iClient, TIMER_FLAG_NO_MAPCHANGE); // Process next frame
|
||||
}
|
||||
|
||||
public Action ResetClientMetalDelayed(Handle hTimer, any iClient) {
|
||||
SetClientMetal(iClient, 0);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a amount to the clients metal amount.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param iMetal The metal amount to add.
|
||||
* @return True if amount could be added, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool AddClientMetal(int iClient, int iMetal) {
|
||||
if (iMetal < 0) {
|
||||
if (GetClientMetal(iClient) + iMetal >= 0) {
|
||||
SetClientMetal(iClient, GetClientMetal(iClient) + iMetal);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Player_CAddValue(iClient, PLAYER_METAL_PICK, iMetal);
|
||||
SetClientMetal(iClient, GetClientMetal(iClient) + iMetal);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a metal pack.
|
||||
*
|
||||
* @param iMetalPackSpawnType The metal pack type.
|
||||
* @param fLocation The location it should spawn at.
|
||||
* @param iMetal The amount of metal it should spawn with.
|
||||
* @return A TDMetalPackReturn value.
|
||||
*/
|
||||
|
||||
stock TDMetalPackReturn SpawnMetalPack(TDMetalPackSpawnType iMetalPackSpawnType, float fLocation[3], int iMetal) {
|
||||
int iEntity;
|
||||
return SpawnMetalPack2(iMetalPackSpawnType, fLocation, iMetal, iEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a metal pack.
|
||||
*
|
||||
* @param iMetalPackSpawnType The metal pack type.
|
||||
* @param fLocation The location it should spawn at.
|
||||
* @param iMetal The amount of metal it should spawn with.
|
||||
* @param iEntity The entity reference to the metal pack.
|
||||
* @return A TDMetalPackReturn value.
|
||||
*/
|
||||
|
||||
stock TDMetalPackReturn SpawnMetalPack2(TDMetalPackSpawnType iMetalPackSpawnType, float fLocation[3], int iMetal, int &iEntity) {
|
||||
Log(TDLogLevel_Trace, "SpawnMetalPack2: iMetalPackSpawnType=%d, fLocation=[%f, %f, %f], iMetal=%d", iMetalPackSpawnType, fLocation[0], fLocation[1], fLocation[2], iMetal);
|
||||
|
||||
if (iMetal <= 0) {
|
||||
return TDMetalPack_InvalidMetal;
|
||||
}
|
||||
|
||||
if (g_iMetalPackCount >= METALPACK_LIMIT) {
|
||||
return TDMetalPack_LimitReached;
|
||||
}
|
||||
|
||||
char sModelPath[PLATFORM_MAX_PATH];
|
||||
|
||||
switch (iMetalPackSpawnType) {
|
||||
case TDMetalPack_Small: {
|
||||
strcopy(sModelPath, sizeof(sModelPath), "models/items/ammopack_small.mdl");
|
||||
}
|
||||
case TDMetalPack_Medium: {
|
||||
strcopy(sModelPath, sizeof(sModelPath), "models/items/ammopack_medium.mdl");
|
||||
}
|
||||
case TDMetalPack_Large: {
|
||||
strcopy(sModelPath, sizeof(sModelPath), "models/items/ammopack_large.mdl");
|
||||
}
|
||||
default: {
|
||||
return TDMetalPack_InvalidType;
|
||||
}
|
||||
}
|
||||
|
||||
int iMetalPack = CreateEntityByName("prop_dynamic");
|
||||
|
||||
DispatchKeyValue(iMetalPack, "model", sModelPath);
|
||||
|
||||
char sMetal[32];
|
||||
IntToString(iMetal, sMetal, sizeof(sMetal));
|
||||
|
||||
DispatchKeyValue(iMetalPack, "targetname", sMetal);
|
||||
|
||||
if (DispatchSpawn(iMetalPack)) {
|
||||
// Make it not solid, but still "collidable"
|
||||
SetEntProp(iMetalPack, Prop_Send, "m_usSolidFlags", 12); // FSOLID_TRIGGER|FSOLID_NOT_SOLID
|
||||
SetEntProp(iMetalPack, Prop_Data, "m_nSolidType", 6); // SOLID_VPHYSICS
|
||||
SetEntProp(iMetalPack, Prop_Data, "m_CollisionGroup", 1); // COLLISION_GROUP_DEBRIS
|
||||
|
||||
SetVariantString("idle");
|
||||
AcceptEntityInput(iMetalPack, "SetAnimation");
|
||||
|
||||
TeleportEntity(iMetalPack, fLocation, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
SDKHook(iMetalPack, SDKHook_Touch, OnMetalPackPickup);
|
||||
|
||||
g_iMetalPackCount++;
|
||||
iEntity = EntIndexToEntRef(iMetalPack);
|
||||
}
|
||||
|
||||
Log(TDLogLevel_Debug, "Spawned metal pack (%d, Metal: %d)", iMetalPack, iMetal);
|
||||
|
||||
return TDMetalPack_SpawnedPack;
|
||||
}
|
||||
|
||||
public void OnMetalPackPickup(int iMetalPack, int iClient) {
|
||||
if (!IsDefender(iClient) || !IsValidEntity(iMetalPack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(hurp): Disperse / give metal to each client instead of just one.
|
||||
|
||||
char sMetal[32];
|
||||
GetEntPropString(iMetalPack, Prop_Data, "m_iName", sMetal, sizeof(sMetal));
|
||||
|
||||
int iMetal = StringToInt(sMetal);
|
||||
|
||||
AddClientMetal(iClient, iMetal);
|
||||
ResupplyClient(iClient, true, 0.25);
|
||||
EmitSoundToClient(iClient, "items/gunpickup2.wav");
|
||||
HideAnnotation(iMetalPack);
|
||||
|
||||
AcceptEntityInput(iMetalPack, "Kill");
|
||||
|
||||
g_iMetalPackCount--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refills a clients ammo, clip and/or ammo.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param bAmmoOnly Only refill ammo not clip.
|
||||
* @param fPercent The percent to refill (0.5 would be 50%).
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void ResupplyClient(int iClient, bool bAmmoOnly = false, float fPercent = 1.0) {
|
||||
if (!IsDefender(iClient) || !IsPlayerAlive(iClient)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int iWeapon = GetPlayerWeaponSlot(iClient, TFWeaponSlot_Primary);
|
||||
|
||||
if (IsValidEntity(iWeapon)) {
|
||||
// Engineer's Shotgun
|
||||
|
||||
GivePlayerAmmo(iClient, RoundToFloor(32 * fPercent), GetEntProp(iWeapon, Prop_Send, "m_iPrimaryAmmoType"), true);
|
||||
|
||||
if (!bAmmoOnly) {
|
||||
SetClientClip(iClient, TFWeaponSlot_Primary, 6);
|
||||
}
|
||||
}
|
||||
|
||||
iWeapon = GetPlayerWeaponSlot(iClient, TFWeaponSlot_Secondary);
|
||||
|
||||
if (IsValidEntity(iWeapon)) {
|
||||
// Engineer's Pistol
|
||||
|
||||
GivePlayerAmmo(iClient, RoundToFloor(200 * fPercent), GetEntProp(iWeapon, Prop_Send, "m_iPrimaryAmmoType"), true);
|
||||
|
||||
if (!bAmmoOnly) {
|
||||
SetClientClip(iClient, TFWeaponSlot_Secondary, 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clip of a weapon.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param iSlot The weapons slot index.
|
||||
* @param iClip The clip the weapon should get.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void SetClientClip(int iClient, int iSlot, int iClip) {
|
||||
if (IsValidClient(iClient) && IsClientInGame(iClient) && IsPlayerAlive(iClient)) {
|
||||
int iWeapon = GetPlayerWeaponSlot(iClient, iSlot);
|
||||
|
||||
if (IsValidEntity(iWeapon)) {
|
||||
int iAmmoTable = FindSendPropInfo("CTFWeaponBase", "m_iClip1");
|
||||
SetEntData(iWeapon, iAmmoTable, iClip, 4, true);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user