Initial commit
This commit is contained in:
178
scripting/towerdefense/util/log.sp
Normal file
178
scripting/towerdefense/util/log.sp
Normal file
@@ -0,0 +1,178 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#if defined INFO_INCLUDES
|
||||
#include "../info/constants.sp"
|
||||
#include "../info/enums.sp"
|
||||
#include "../info/variables.sp"
|
||||
#endif
|
||||
|
||||
enum TDLogLevel
|
||||
{
|
||||
TDLogLevel_None = 0, // disables all logging
|
||||
TDLogLevel_Error = 1, // is for critical errors, the plugin may no longer work correctly
|
||||
TDLogLevel_Warning = 2, // is for important warnings, the plugin will continue to work correctly
|
||||
TDLogLevel_Info = 3, // is for informative messages, typically used for deployment
|
||||
TDLogLevel_Debug = 4, // is for debug messages, this level is useful during development
|
||||
TDLogLevel_Trace = 5 // is for trace messages, this level is usually only needed when debugging a problem
|
||||
};
|
||||
|
||||
enum TDLogType
|
||||
{
|
||||
TDLogType_File = 0, // logs to SourceMod logs
|
||||
TDLogType_Console = 1, // logs to server console
|
||||
TDLogType_FileAndConsole = 2 // logs to SourceMod logs and server console
|
||||
};
|
||||
|
||||
static TDLogLevel m_iLogLevel = TDLogLevel_Info;
|
||||
static TDLogType m_iLogType = TDLogType_FileAndConsole;
|
||||
|
||||
stock void Log_Initialize(TDLogLevel iLogLevel = TDLogLevel_Info, TDLogType iLogType = TDLogType_FileAndConsole) {
|
||||
m_iLogLevel = iLogLevel;
|
||||
m_iLogType = iLogType;
|
||||
}
|
||||
|
||||
stock void Log(TDLogLevel iLogLevel, const char[] sMessage, any...) {
|
||||
if (m_iLogLevel >= iLogLevel) {
|
||||
char sFormattedMessage[256];
|
||||
VFormat(sFormattedMessage, sizeof(sFormattedMessage), sMessage, 3);
|
||||
|
||||
switch (m_iLogType) {
|
||||
case TDLogType_File: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
LogError("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
LogError("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
LogMessage("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
LogMessage("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
LogMessage("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
case TDLogType_Console: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
PrintToServer("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
PrintToServer("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
PrintToServer("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
PrintToServer("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
PrintToServer("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
case TDLogType_FileAndConsole: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
LogError("[TF2TD > Error] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
LogError("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
LogMessage("[TF2TD > Info] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
LogMessage("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
LogMessage("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stock void LogType(TDLogLevel iLogLevel, TDLogType iLogType, const char[] sMessage, any...) {
|
||||
if (m_iLogLevel >= iLogLevel) {
|
||||
char sFormattedMessage[256];
|
||||
VFormat(sFormattedMessage, sizeof(sFormattedMessage), sMessage, 4);
|
||||
|
||||
switch (iLogType) {
|
||||
case TDLogType_File: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
LogError("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
LogError("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
LogMessage("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
LogMessage("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
LogMessage("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
case TDLogType_Console: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
PrintToServer("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
PrintToServer("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
PrintToServer("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
PrintToServer("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
PrintToServer("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
case TDLogType_FileAndConsole: {
|
||||
switch (iLogLevel) {
|
||||
case TDLogLevel_Error: {
|
||||
LogError("[TF2TD > Error] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Error] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Warning: {
|
||||
LogError("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Warning] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Info: {
|
||||
LogMessage("[TF2TD > Info] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Info] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Debug: {
|
||||
LogMessage("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Debug] %s", sFormattedMessage);
|
||||
}
|
||||
case TDLogLevel_Trace: {
|
||||
LogMessage("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
PrintToServer("[TF2TD > Trace] %s", sFormattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
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);
|
||||
}
|
||||
}
|
||||
}
|
48
scripting/towerdefense/util/steamid.sp
Normal file
48
scripting/towerdefense/util/steamid.sp
Normal file
@@ -0,0 +1,48 @@
|
||||
#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 steam community id.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param sBuffer The destination string buffer.
|
||||
* @param iMaxLength The maximum length of the output string buffer.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool GetClientCommunityId(int iClient, char[] sBuffer, int iMaxLength) {
|
||||
if (!IsClientConnected(iClient) || IsFakeClient(iClient)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int iSteamAccountId = GetSteamAccountID(iClient);
|
||||
|
||||
if (iSteamAccountId > 0) {
|
||||
char sSteamAccountId[32];
|
||||
char[] sBase = "76561197960265728";
|
||||
// char[] sBase = { "7", "6", "5", "6", "1", "1", "9", "7", "9", "6", "0", "2", "6", "5", "7", "2", "8" };
|
||||
char[] sSteamId = new char[iMaxLength];
|
||||
|
||||
IntToString((iSteamAccountId - iSteamAccountId % 2) / 2, sSteamAccountId, sizeof(sSteamAccountId));
|
||||
|
||||
int iCurrent, iCarryOver = iSteamAccountId % 2;
|
||||
|
||||
|
||||
sSteamId[iMaxLength - 1] = '\0';
|
||||
|
||||
int iPos = FindCharInString(sSteamId, '7');
|
||||
|
||||
if (iPos > 0 && Substring(sBuffer, iMaxLength, sSteamId, iMaxLength, iPos, strlen(sSteamId))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
111
scripting/towerdefense/util/tf2items.sp
Normal file
111
scripting/towerdefense/util/tf2items.sp
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#if defined INFO_INCLUDES
|
||||
#include "../info/constants.sp"
|
||||
#include "../info/enums.sp"
|
||||
#include "../info/variables.sp"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gives a weapon to a client.
|
||||
* See https://wiki.alliedmods.net/Team_fortress_2_item_definition_indexes for item indexes and classnames.
|
||||
*
|
||||
* @param iClient The client who should get the weapon.
|
||||
* @param iItemDefinitionIndex The weapons items index.
|
||||
* @param iSlot The weapons slot.
|
||||
* @param iLevel The weapons level. (must be between 0 an 100)
|
||||
* @param iQuality The weapons quality. (must be between 0 an 10)
|
||||
* @param bPreserveAttributes Should attributes be preserved?
|
||||
* @param sClassname The weapons classname.
|
||||
* @param sAttributes The attributes to apply tp the weapon. (Format: "<AttributeId1>=<Value1>;<AttributeId2>=<Value2>;...")
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void TF2Items_GiveWeapon(int iClient, int iItemDefinitionIndex, int iSlot, int iLevel, int iQuality, bool bPreserveAttributes, char[] sClassname, char[] sAttributes) {
|
||||
Log(TDLogLevel_Trace, "%d, %d, %d, %d, %d, %s, \"%s\", \"%s\"", iClient, iItemDefinitionIndex, iSlot, iLevel, iQuality, (bPreserveAttributes ? "true" : "false"), sClassname, sAttributes);
|
||||
|
||||
Handle hItem = TF2Items_CreateItem(OVERRIDE_ALL);
|
||||
int iFlags = 0;
|
||||
|
||||
TF2Items_SetItemIndex(hItem, iItemDefinitionIndex);
|
||||
|
||||
if (iLevel >= 0 && iLevel <= 100) {
|
||||
TF2Items_SetLevel(hItem, iLevel);
|
||||
iFlags |= OVERRIDE_ITEM_LEVEL;
|
||||
}
|
||||
|
||||
if (iQuality >= 0 && iQuality <= 10) {
|
||||
TF2Items_SetQuality(hItem, iQuality);
|
||||
iFlags |= OVERRIDE_ITEM_QUALITY;
|
||||
}
|
||||
|
||||
if (bPreserveAttributes) {
|
||||
iFlags |= PRESERVE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
char sAttributeList[15][16], sAttribute[2][16];
|
||||
int iAttributeIndex;
|
||||
int iNumAttributes = 0;
|
||||
float fAttributeValue;
|
||||
|
||||
// More than 1 attribute
|
||||
if (FindCharInString(sAttributes, ';') != -1) {
|
||||
ExplodeString(sAttributes, ";", sAttributeList, sizeof(sAttributeList), sizeof(sAttributeList[]));
|
||||
|
||||
for (int i = 0; i < sizeof(sAttributeList); i++) {
|
||||
if (!StrEqual(sAttributeList[i], "")) {
|
||||
ExplodeString(sAttributeList[i], "=", sAttribute, sizeof(sAttribute), sizeof(sAttribute[]));
|
||||
|
||||
iAttributeIndex = StringToInt(sAttribute[0]);
|
||||
fAttributeValue = StringToFloat(sAttribute[1]);
|
||||
|
||||
PrintToServer("Attribute: %d, Value: %f", iAttributeIndex, fAttributeValue);
|
||||
|
||||
TF2Items_SetAttribute(hItem, i, iAttributeIndex, fAttributeValue);
|
||||
|
||||
iNumAttributes++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Exactly 1 attribute
|
||||
if (!StrEqual(sAttributes, "")) {
|
||||
ExplodeString(sAttributes, "=", sAttribute, sizeof(sAttribute), sizeof(sAttribute[]));
|
||||
|
||||
iAttributeIndex = StringToInt(sAttribute[0]);
|
||||
fAttributeValue = StringToFloat(sAttribute[1]);
|
||||
|
||||
PrintToServer("Attribute: %d, Value: %f", iAttributeIndex, fAttributeValue);
|
||||
|
||||
TF2Items_SetAttribute(hItem, 0, iAttributeIndex, fAttributeValue);
|
||||
|
||||
iNumAttributes++;
|
||||
}
|
||||
}
|
||||
|
||||
if (iNumAttributes != 0 && iNumAttributes <= 15) {
|
||||
TF2Items_SetNumAttributes(hItem, iNumAttributes);
|
||||
iFlags |= OVERRIDE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
TF2Items_SetFlags(hItem, iFlags | FORCE_GENERATION);
|
||||
|
||||
TF2Items_SetClassname(hItem, sClassname);
|
||||
|
||||
TF2_RemoveWeaponSlot(iClient, iSlot);
|
||||
int iWeapon = TF2Items_GiveNamedItem(iClient, hItem);
|
||||
|
||||
if (IsValidEntity(iWeapon)) {
|
||||
EquipPlayerWeapon(iClient, iWeapon);
|
||||
|
||||
Log(TDLogLevel_Debug, "Gave weapon (%d) to %N", iItemDefinitionIndex, iClient);
|
||||
}
|
||||
|
||||
if (IsTower(iClient)) {
|
||||
TDTowerId iTowerId = GetTowerId(iClient);
|
||||
Tower_OnWeaponChanged(iClient, iTowerId, iItemDefinitionIndex, iSlot, iWeapon);
|
||||
}
|
||||
|
||||
CloseHandle(hItem);
|
||||
}
|
307
scripting/towerdefense/util/zones.sp
Normal file
307
scripting/towerdefense/util/zones.sp
Normal file
@@ -0,0 +1,307 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#if defined INFO_INCLUDES
|
||||
#include "../info/constants.sp"
|
||||
#include "../info/enums.sp"
|
||||
#include "../info/variables.sp"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates a beam line.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param fStart The start point.
|
||||
* @param fEnd The end point.
|
||||
* @param fDuration The duration it should appear (in seconds).
|
||||
* @param iColors The colors.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CreateBeamLine(int iClient, float fStart[3], float fEnd[3], float fDuration = 5.0, const int[] iColors = { 255, 0, 0, 255 } ) {
|
||||
int iColors2[4];
|
||||
iColors2[0] = iColors[0];
|
||||
iColors2[1] = iColors[1];
|
||||
iColors2[2] = iColors[2];
|
||||
iColors2[3] = iColors[3];
|
||||
|
||||
TE_SetupBeamPoints(fStart, fEnd, g_iLaserMaterial, g_iHaloMaterial, 0, 0, fDuration + 0.1, 1.0, 1.0, 1, 0.0, iColors2, 0);
|
||||
|
||||
if (fDuration == 0.0) {
|
||||
DataPack hPack = new DataPack();
|
||||
|
||||
CreateDataTimer(fDuration, Timer_CreateBeam, hPack);
|
||||
|
||||
hPack.WriteCell(iClient);
|
||||
hPack.WriteFloat(fDuration);
|
||||
hPack.WriteFloat(fStart[0]);
|
||||
hPack.WriteFloat(fStart[1]);
|
||||
hPack.WriteFloat(fStart[2]);
|
||||
hPack.WriteFloat(fEnd[0]);
|
||||
hPack.WriteFloat(fEnd[1]);
|
||||
hPack.WriteFloat(fEnd[2]);
|
||||
hPack.WriteCell(iColors[0]);
|
||||
hPack.WriteCell(iColors[1]);
|
||||
hPack.WriteCell(iColors[2]);
|
||||
hPack.WriteCell(iColors[3]);
|
||||
}
|
||||
|
||||
TE_SendToAll();
|
||||
}
|
||||
|
||||
public Action Timer_CreateBeam(Handle hTimer, DataPack hPack) {
|
||||
int iClient, iColors[4];
|
||||
float fDuration, fStart[3], fEnd[3];
|
||||
|
||||
hPack.Reset();
|
||||
iClient = hPack.ReadCell();
|
||||
fDuration = hPack.ReadFloat();
|
||||
fStart[0] = hPack.ReadFloat();
|
||||
fStart[1] = hPack.ReadFloat();
|
||||
fStart[2] = hPack.ReadFloat();
|
||||
fEnd[0] = hPack.ReadFloat();
|
||||
fEnd[1] = hPack.ReadFloat();
|
||||
fEnd[2] = hPack.ReadFloat();
|
||||
iColors[0] = hPack.ReadCell();
|
||||
iColors[1] = hPack.ReadCell();
|
||||
iColors[2] = hPack.ReadCell();
|
||||
iColors[3] = hPack.ReadCell();
|
||||
|
||||
CreateBeamLine(iClient, fStart, fEnd, fDuration, iColors);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a beam box.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param fStart The start point.
|
||||
* @param fEnd The end point.
|
||||
* @param fDuration The duration it should appear (in seconds).
|
||||
* @param iColors The colors.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CreateBeamBox(int iClient, float fStart[3], float fEnd[3], float fDuration = 5.0, const int[] iColors = { 255, 0, 0, 255 } ) {
|
||||
float fPoint[8][3];
|
||||
|
||||
CopyVector(fStart, fPoint[0]);
|
||||
CopyVector(fEnd, fPoint[7]);
|
||||
|
||||
CreateZonePoints(fPoint);
|
||||
|
||||
for (int i = 0, i2 = 3; i2 >= 0; i += i2--) {
|
||||
for (int j = 1; j <= 7; j += (j / 2) + 1) {
|
||||
if (j != 7 - i) {
|
||||
CreateBeamLine(iClient, fPoint[i], fPoint[j], fDuration, iColors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates all 8 zone points by using start and end point.
|
||||
*
|
||||
* @param fPoint The array to store the points in.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CreateZonePoints(float fPoint[8][3]) {
|
||||
for (int i = 1; i < 7; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
fPoint[i][j] = fPoint[((i >> (2 - j)) & 1) * 7][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates all an beam box around a client.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param fStart The start point.
|
||||
* @param fEnd The end point.
|
||||
* @param fDuration The duration it should appear (in seconds).
|
||||
* @param iColors The colors.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CreateBeamBoxAroundClient(int iClient, float fDistance, bool OnlyPlayerHeight = true, float fDuration = 5.0, const int[] iColors = { 255, 0, 0, 255 } ) {
|
||||
if (!IsValidClient(iClient) || !IsClientConnected(iClient) || !IsClientInGame(iClient) || !IsPlayerAlive(iClient)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float fLocation[3], fStart[3], fEnd[3];
|
||||
|
||||
GetClientAbsOrigin(iClient, fLocation);
|
||||
|
||||
if (OnlyPlayerHeight) {
|
||||
fStart[0] = fLocation[0] - fDistance;
|
||||
fStart[1] = fLocation[1] - fDistance;
|
||||
fStart[2] = fLocation[2];
|
||||
|
||||
fEnd[0] = fLocation[0] + fDistance;
|
||||
fEnd[1] = fLocation[1] + fDistance;
|
||||
fEnd[2] = fLocation[2] + 83;
|
||||
} else {
|
||||
fStart[0] = fLocation[0] - fDistance;
|
||||
fStart[1] = fLocation[1] - fDistance;
|
||||
fStart[2] = fLocation[2] - fDistance;
|
||||
|
||||
fEnd[0] = fLocation[0] + fDistance;
|
||||
fEnd[1] = fLocation[1] + fDistance;
|
||||
fEnd[2] = fLocation[2] + 83 + fDistance;
|
||||
}
|
||||
|
||||
CreateBeamBox(iClient, fStart, fEnd, fDuration, iColors);
|
||||
|
||||
float fPoint[8][3];
|
||||
|
||||
CopyVector(fStart, fPoint[0]);
|
||||
CopyVector(fEnd, fPoint[7]);
|
||||
|
||||
CreateZonePoints(fPoint);
|
||||
|
||||
CopyZone(fPoint, g_fBeamPoints[iClient]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies one float vector onto another one.
|
||||
*
|
||||
* @param fSource The vector to copy.
|
||||
* @param fDestination The destination vector.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CopyVector(float fSource[3], float fDestination[3]) {
|
||||
for (int i = 0; i < sizeof(fSource); i++) {
|
||||
fDestination[i] = fSource[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies one zone array onto another one.
|
||||
*
|
||||
* @param fSource The array to copy.
|
||||
* @param fDestination The destination array.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void CopyZone(float fSource[8][3], float fDestination[8][3]) {
|
||||
for (int i = 0; i < sizeof(fSource); i++) {
|
||||
for (int j = 0; j < sizeof(fSource[]); j++) {
|
||||
fDestination[i][j] = fSource[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkes if an entity is inside a zone.
|
||||
*
|
||||
* @param iClient The entity.
|
||||
* @param fZone The zone array.
|
||||
* @return True if inside, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool IsEntityInZone(int iEntity, float fZone[8][3], float fDifferenceZ) {
|
||||
float fEntityPosition[3];
|
||||
|
||||
GetEntPropVector(iEntity, Prop_Send, "m_vecOrigin", fEntityPosition);
|
||||
fEntityPosition[2] += fDifferenceZ;
|
||||
|
||||
return IsPointInZone(fEntityPosition, fZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkes if a client is inside a zone.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @param fPoint The zone array.
|
||||
* @return True if inside, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool IsClientInZone(int iClient, float fPoint[8][3]) {
|
||||
float fPlayerPosition[3], fPlayerPoint[8][3];
|
||||
|
||||
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", fPlayerPosition);
|
||||
fPlayerPosition[2] += 41.5;
|
||||
|
||||
fPlayerPoint[0][0] = fPlayerPosition[0] - 12.0;
|
||||
fPlayerPoint[0][1] = fPlayerPosition[1] - 12.0;
|
||||
fPlayerPoint[0][2] = fPlayerPosition[2] - 20.0;
|
||||
fPlayerPoint[7][0] = fPlayerPosition[0] + 12.0;
|
||||
fPlayerPoint[7][1] = fPlayerPosition[1] + 12.0;
|
||||
fPlayerPoint[7][2] = fPlayerPosition[2] + 20.0;
|
||||
|
||||
CreateZonePoints(fPlayerPoint);
|
||||
|
||||
return Box3DIntersects(fPlayerPoint, fPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a bounding box around a client.
|
||||
*
|
||||
* @param iClient The client.
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void DrawClientBoundingBox(int iClient) {
|
||||
float fPlayerPosition[3], fPlayerPoint[8][3];
|
||||
|
||||
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", fPlayerPosition);
|
||||
fPlayerPosition[2] += 41.5;
|
||||
|
||||
fPlayerPoint[0][0] = fPlayerPosition[0] - 12.0;
|
||||
fPlayerPoint[0][1] = fPlayerPosition[1] - 12.0;
|
||||
fPlayerPoint[0][2] = fPlayerPosition[2] - 20.0;
|
||||
fPlayerPoint[7][0] = fPlayerPosition[0] + 12.0;
|
||||
fPlayerPoint[7][1] = fPlayerPosition[1] + 12.0;
|
||||
fPlayerPoint[7][2] = fPlayerPosition[2] + 20.0;
|
||||
|
||||
CreateZonePoints(fPlayerPoint);
|
||||
|
||||
CreateBeamBox(iClient, fPlayerPoint[0], fPlayerPoint[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkes if a zone intersects with another zone.
|
||||
*
|
||||
* @param fCheck The 1st zone array.
|
||||
* @param fSource The 2nd zone array.
|
||||
* @return True if intersects, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool Box3DIntersects(float fCheck[8][3], float fSource[8][3]) {
|
||||
if (fCheck[0][0] > fSource[4][0] || // fCheck is right of fSource
|
||||
fCheck[4][0] < fSource[0][0] || // fCheck is left of fSource
|
||||
fCheck[1][2] < fSource[0][2] || // fCheck is below fSource
|
||||
fCheck[0][2] > fSource[1][2] || // fCheck is above fSource
|
||||
fCheck[3][1] < fSource[1][1] || // fCheck is behind fSource
|
||||
fCheck[1][1] > fSource[3][1]) { // fCheck is in front fSource
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkes if a point is inside a zone.
|
||||
*
|
||||
* @param fPoint The point vector.
|
||||
* @param fZone The zone array.
|
||||
* @return True if inside, false otherwise.
|
||||
*/
|
||||
|
||||
stock bool IsPointInZone(float fPoint[3], float fZone[8][3]) {
|
||||
if (fPoint[0] > fZone[4][0] || // fPoint is right of fZone
|
||||
fPoint[0] < fZone[0][0] || // fPoint is left of fZone
|
||||
fPoint[2] < fZone[0][2] || // fPoint is below fZone
|
||||
fPoint[2] > fZone[1][2] || // fPoint is above fZone
|
||||
fPoint[1] < fZone[1][1] || // fPoint is behind fZone
|
||||
fPoint[1] > fZone[3][1]) { // fPoint is in front fZone
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user