Files
2025-04-15 22:27:20 -04:00

1032 lines
24 KiB
SourcePawn

#pragma semicolon 1
#include <sourcemod>
#if defined INFO_INCLUDES
#include "../info/constants.sp"
#include "../info/enums.sp"
#include "../info/variables.sp"
#endif
/**
* Called when a buy-tower button is being shot.
*
* @param iTowerId The tower id.
* @param iButton The button entity.
* @param iActivator The activator entity.
* @noreturn
*/
stock void Tower_OnButtonBuy(TDTowerId iTowerId, int iButton, int iActivator) {
if (!g_bEnabled) {
return;
}
if (!IsDefender(iActivator)) {
return;
}
if (!g_bTowerBought[view_as<int>(iTowerId)]) {
int iPrice = Tower_GetPrice(iTowerId);
char sName[MAX_NAME_LENGTH];
Tower_GetName(iTowerId, sName, sizeof(sName));
int iClients = GetRealClientCount(true);
if (iClients <= 0) {
iClients = 1;
}
iPrice /= iClients;
if (!CanAfford(iPrice, true)) {
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerBuyAttempt", GetClientNameShort(iActivator), sName, iPrice);
}
if (CanAfford(iPrice, false)) {
Tower_Spawn(iTowerId);
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsDefender(iClient)) {
AddClientMetal(iClient, -iPrice);
Player_CAddValue(iClient, PLAYER_TOWERS_BOUGHT, 1);
}
}
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerBought", GetClientNameShort(iActivator), sName);
g_bTowerBought[view_as<int>(iTowerId)] = true;
AcceptEntityInput(iButton, "Break");
}
}
}
/**
* Called when a teleport-tower button is being shot.
*
* @param iTowerId The tower id.
* @param iButton The button entity.
* @param iActivator The activator entity.
* @noreturn
*/
stock void Tower_OnButtonTeleport(TDTowerId iTowerId, int iButton, int iActivator) {
if (!g_bEnabled) {
return;
}
int iTower = GetTower(iTowerId);
if (!IsTower(iTower)) {
return;
}
if (!IsTowerAttached(iTower)) {
Tower_TeleportToSpawn(iTower);
}
}
/**
* Called when a tower spawned.
*
* @param iTower The tower.
* @param iTowerId The tower id.
* @noreturn
*/
stock void Tower_OnSpawn(int iTower, TDTowerId iTowerId) {
if (!g_bEnabled) {
return;
}
g_iUpgradeMetal[iTower] = 0;
g_iUpgradeLevel[iTower] = 1;
g_iLastMover[iTower] = 0;
SetEntProp(iTower, Prop_Data, "m_bloodColor", view_as<int>(TDBlood_None));
SetRobotModel(iTower);
// Change weapon
Tower_ChangeWeapon(iTower, Tower_GetWeapon(iTowerId));
// Teleport
Tower_TeleportToSpawn(iTower);
// Check for AoE
Tower_AoeSetup(iTower, iTowerId);
}
/**
* Check if Tower is AoE and execute timer if this is true
*
* @param iTower The tower.
* @param iTowerId The tower id.
* @noreturn
*/
stock void Tower_AoeSetup(int iTower, TDTowerId iTowerId) {
if (!IsTower(iTower)) {
return;
}
char sDamagetype[20];
if (Tower_GetDamagetype(iTowerId, sDamagetype, sizeof(sDamagetype))) {
if (StrEqual(sDamagetype, "AoE")) {
if (hAoETimer == null)
hAoETimer = CreateTimer(0.2, Timer_ClientNearAoETower, _, TIMER_REPEAT);
}
}
}
/**
* Called when a tower touches a func_nobuild brush.
*
* @param iTower The tower.
* @param iTowerId The tower id.
* @noreturn
*/
stock void Tower_OnTouchNobuild(int iTower) {
if (!g_bEnabled) {
return;
}
Forbid(g_iLastMover[iTower], true, "%s %t", PLUGIN_PREFIX, "forbidCantPlaceTowerThere");
Tower_TeleportToSpawn(iTower);
}
/**
* Called when a tower is upgraded by a client.
*
* @param iTower The tower.
* @param iClient The client upgrading.
* @noreturn
*/
stock void Tower_OnUpgrade(int iTower, int iClient) {
if (!g_bEnabled) {
return;
}
TDTowerId iTowerId = GetTowerId(iTower);
int iMaxLevel = Tower_GetMaxLevel(iTowerId);
if (g_iUpgradeLevel[iTower] < iMaxLevel) {
if (!AddClientMetal(iClient, -50)) {
return;
}
g_iUpgradeMetal[iTower] += 50;
if (g_iUpgradeMetal[iTower] >= Tower_GetMetal(iTowerId)) {
int iWeapon = Tower_GetWeapon(iTowerId);
g_iUpgradeMetal[iTower] = 0;
g_iUpgradeLevel[iTower]++;
if (iWeapon != Tower_GetWeapon(iTowerId)) {
Tower_ChangeWeapon(iTower, Tower_GetWeapon(iTowerId));
} else {
Tower_SetLevelAttributes(iTower, iTowerId);
}
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerUpgradeLevel", GetClientNameShort(iTower), g_iUpgradeLevel[iTower]);
float fDamageScale = Tower_GetDamageScale(iTowerId);
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerUpgradeDamageBonus", GetClientNameShort(iTower),RoundFloat(fDamageScale * 100 - ((fDamageScale > 1.0) ? 100 : 0)));
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerUpgradeAttackSpeed", GetClientNameShort(iTower),RoundFloat(fDamageScale * 100 - ((fDamageScale > 1.0) ? 100 : 0)));
if (Tower_GetRotate(iTowerId)) {
PrintToChatAll("%s %t", PLUGIN_PREFIX, "towerUpgradeCanRotate", GetClientNameShort(iTower));
}
}
}
HideAnnotation(iTower);
HideAdvancedAnnotation(iClient, iTower);
if (g_iUpgradeLevel[iTower] == iMaxLevel) {
AttachAnnotation(iTower, 2.0, "%t", "towerUpgradeMaxLevel", GetClientNameShort(iTower), g_iUpgradeLevel[iTower]);
} else {
AttachAnnotation(iTower, 2.0, "%t", "towerUpgradeProgress", GetClientNameShort(iTower), g_iUpgradeLevel[iTower], g_iUpgradeMetal[iTower], Tower_GetMetal(iTowerId));
}
}
/**
* Called when a tower changes weapons.
*
* @param iTower The tower.
* @param iTowerId The tower id.
* @param iItemDefinitionIndex The items index.
* @param iSlot The weapons slot.
* @param iWeapon The weapon entity.
* @noreturn
*/
stock void Tower_OnWeaponChanged(int iTower, TDTowerId iTowerId, int iItemDefinitionIndex, int iSlot, int iWeapon) {
SetEntPropEnt(iTower, Prop_Send, "m_hActiveWeapon", GetPlayerWeaponSlot(iTower, iSlot));
Tower_SetLevelAttributes(iTower, iTowerId);
}
/**
* Called when a carrier of a tower disconnects or has a timeout.
*
* @param iTower The tower.
* @param iCarrier The carrier.
* @noreturn
*/
stock void Tower_OnCarrierDisconnected(int iTower, int iCarrier) {
SetEntityMoveType(iTower, MOVETYPE_WALK);
HideAnnotation(iCarrier);
g_iLastMover[iTower] = iCarrier;
g_bCarryingObject[iCarrier] = false;
g_iAttachedTower[iCarrier] = 0;
Log(TDLogLevel_Debug, "%N dropped tower (%N)", iCarrier, iTower);
Tower_TeleportToSpawn(iTower);
}
/**
* Called when a carrier of a tower dies.
*
* @param iTower The tower.
* @param iCarrier The carrier.
* @noreturn
*/
stock void Tower_OnCarrierDeath(int iTower, int iCarrier) {
SetEntityMoveType(iTower, MOVETYPE_WALK);
HideAnnotation(iCarrier);
g_iLastMover[iTower] = iCarrier;
g_bCarryingObject[iCarrier] = false;
g_iAttachedTower[iCarrier] = 0;
Log(TDLogLevel_Debug, "%N dropped tower (%N)", iCarrier, iTower);
Tower_TeleportToSpawn(iTower);
}
/**
* Spawns a tower.
*
* @param iTowerId The towers id.
* @return True on success, false otherwise.
*/
stock bool Tower_Spawn(TDTowerId iTowerId) {
if (!g_bEnabled) {
return false;
}
char sName[MAX_NAME_LENGTH], sClass[32];
if (Tower_GetName(iTowerId, sName, sizeof(sName))) {
if (Tower_GetClassString(iTowerId, sClass, sizeof(sClass))) {
ServerCommand("bot -team blue -class %s -name %s", sClass, sName);
Log(TDLogLevel_Info, "Tower (%s) spawned", sName);
return true;
}
}
return false;
}
/**
* Teleports a tower to his spawn location.
*
* @param iTower The tower.
* @return True on success, false otherwise.
*/
stock bool Tower_TeleportToSpawn(int iTower) {
if (!g_bEnabled) {
return false;
}
TDTowerId iTowerId = GetTowerId(iTower);
if (iTowerId == TDTower_Invalid) {
return false;
}
float fLocation[3], fAngles[3];
if (Tower_GetLocation(iTowerId, fLocation)) {
if (Tower_GetAngles(iTowerId, fAngles)) {
TeleportEntity(iTower, fLocation, fAngles, view_as<float>({ 0.0, 0.0, 0.0 }));
char sName[MAX_NAME_LENGTH];
if (Tower_GetName(iTowerId, sName, sizeof(sName))) {
Log(TDLogLevel_Debug, "Tower (%s) teleported", sName);
}
return true;
}
}
return false;
}
/**
* Changes a towers weapon.
*
* @param iTower The tower.
* @param iWeaponId The weapons id.
* @return True on success, false otherwise.
*/
stock bool Tower_ChangeWeapon(int iTower, int iWeaponId) {
if (!g_bEnabled) {
return false;
}
if (IsTower(iTower)) {
int iIndex = -1;
if ((iIndex = Weapon_GetIndex(iWeaponId)) != -1) {
int iSlot = -1;
if ((iSlot = Weapon_GetSlot(iWeaponId)) != -1) {
int iLevel = -1;
if ((iLevel = Weapon_GetLevel(iWeaponId)) != -1) {
int iQuality = -1;
if ((iQuality = Weapon_GetQuality(iWeaponId)) != -1) {
char sClassname[64];
if (Weapon_GetClassname(iWeaponId, sClassname, sizeof(sClassname))) {
bool bPreserveAttributes = Weapon_GetPreserveAttributes(iWeaponId);
for (int i = 0; i < 3; i++) {
if (i != iSlot) {
TF2_RemoveWeaponSlot(iTower, i);
}
}
TF2Items_GiveWeapon(iTower, iIndex, iSlot, iLevel, iQuality, bPreserveAttributes, sClassname, "");
return true;
}
}
}
}
}
}
return false;
}
/**
* Sets a towers level attributes.
*
* @param iTower The tower.
* @param iTowerId The towers id.
* @noreturn
*/
stock void Tower_SetLevelAttributes(int iTower, TDTowerId iTowerId) {
int iWeapon = GetEntPropEnt(iTower, Prop_Send, "m_hActiveWeapon");
if (TF2Attrib_SetByDefIndex(iWeapon, 2, Tower_GetDamageScale(iTowerId))) {
Log(TDLogLevel_Trace, "Successfully set attribute %d on %N to %f", 2, iTower, Tower_GetDamageScale(iTowerId));
}
if (TF2Attrib_SetByDefIndex(iTower, 6, 1.0 / Tower_GetAttackspeedScale(iTowerId))) {
Log(TDLogLevel_Trace, "Successfully set attribute %d on %N to %f", 6, iTower, 1.0 / Tower_GetAttackspeedScale(iTowerId));
}
}
/**
* Attaches a tower to a client.
*
* @param iClient The client.
* @noreturn
*/
stock void Tower_Pickup(int iClient) {
if (!g_bEnabled) {
return;
}
int iTower = GetAimTarget(iClient);
if (IsTower(iTower)) {
if (IsTowerAttached(iTower)) {
Forbid(iClient, true, "%s %t", PLUGIN_PREFIX, "forbidTowerAlreadyCarried", GetClientNameShort(iTower));
return;
}
if(g_bTowersLocked){
Forbid(iClient, true, "%s %t", PLUGIN_PREFIX, "forbidTowerLockedMidwave");
return;
}
TF2Attrib_SetByName(iClient, "cannot pick up buildings", 1.0);
SetEntityMoveType(iTower, MOVETYPE_NOCLIP);
TeleportEntity(iTower, view_as<float>({ 0.0, 0.0, -8192.0 }), NULL_VECTOR, NULL_VECTOR); // Teleport out of the map
HideAnnotation(iTower);
AttachAnnotation(iClient, 86400.0, "%t", "towerMoving", GetClientNameShort(iTower));
g_bCarryingObject[iClient] = true;
g_iAttachedTower[iClient] = iTower;
TDTowerId iTowerId = GetTowerId(iTower);
char sName[MAX_NAME_LENGTH];
Tower_GetName(iTowerId, sName, sizeof(sName));
CPrintToChat(iClient, "%t", "towerPickedUp", sName);
Log(TDLogLevel_Debug, "%N picked up tower (%N)", iClient, iTower);
}
}
/**
* Detaches a tower from a client.
*
* @param iClient The client.
* @noreturn
*/
stock void Tower_Drop(int iClient) {
if (!g_bEnabled) {
return;
}
if (g_bInsideNobuild[iClient]) {
Forbid(iClient, true, "%s %t", PLUGIN_PREFIX, "forbidCantPlaceTowerOnPath");
return;
}
if(g_bTowersLocked){
Forbid(iClient, true, "%s %t", PLUGIN_PREFIX, "forbidCantPlaceTowerMidwave");
return;
}
int iTower = g_iAttachedTower[iClient];
float fLocation[3], fAngles[3];
SetEntityMoveType(iTower, MOVETYPE_WALK);
GetClientAbsOrigin(iClient, fLocation);
GetClientAbsAngles(iClient, fAngles);
fAngles[0] = Tower_GetPitch(GetTowerId(iTower));
TeleportEntity(iTower, fLocation, fAngles, NULL_VECTOR);
HideAnnotation(iClient);
TF2Attrib_RemoveByName(iClient, "cannot pick up buildings");
g_iLastMover[iTower] = iClient;
g_bCarryingObject[iClient] = false;
g_iAttachedTower[iClient] = 0;
Log(TDLogLevel_Debug, "%N dropped tower (%N)", iClient, iTower);
}
/**
* Shows tower info to a client.
*
* @param iClient The client.
* @noreturn
*/
stock void Tower_ShowInfo(int iClient) {
if (!g_bEnabled) {
return;
}
int iTower = GetAimTarget(iClient);
if (IsTower(iTower)) {
TDTowerId iTowerId = GetTowerId(iTower);
if (g_iUpgradeLevel[iTower] == Tower_GetMaxLevel(iTowerId)) {
AttachAdvancedAnnotation(iClient, iTower, 4.0, "%N\nCurrent Level: %d\nMax. Level Reached", iTower, g_iUpgradeLevel[iTower]);
} else {
AttachAdvancedAnnotation(iClient, iTower, 4.0, "%N\nCurrent Level: %d\nUpgrade Progress: %d/%d", iTower, g_iUpgradeLevel[iTower], g_iUpgradeMetal[iTower], Tower_GetMetal(iTowerId));
}
}
}
/*=========================================
= Utility Functions =
=========================================*/
/**
* Gets a visibility bitfield which determines if a player should see an annotation.
*
* @param iClient The client who should see it.
* @return The bitfield.
*/
stock int GetVisibilityBitfield(int iClient) {
if (!IsDefender(iClient)) {
return 1;
}
int iBitField = 1;
iBitField |= RoundFloat(Pow(2.0, float(iClient)));
return iBitField;
}
/**
* Checks if a tower is attached to a client.
*
* @param iTower The tower.
* @return True if tower is attached, false otherwise.
*/
stock bool IsTowerAttached(int iTower) {
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (g_iAttachedTower[iClient] == iTower) {
return true;
}
}
return false;
}
/**
* Gets a towers client index.
*
* @param iTowerId The towers id.
* @return The towers client index, or -1 on failure.
*/
stock int GetTower(TDTowerId iTowerId) {
char sName2[MAX_NAME_LENGTH];
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsTower(iClient)) {
Tower_GetName(iTowerId, sName2, sizeof(sName2));
if (StrEqual(GetClientNameShort(iClient), sName2)) {
return iClient;
}
}
}
return -1;
}
/**
* Gets the towers id.
*
* @param iTower The tower.
* @return The towers id, or -1 on error.
*/
stock TDTowerId GetTowerId(int iTower) {
if (IsValidClient(iTower)) {
char sName[MAX_NAME_LENGTH];
char sName2[MAX_NAME_LENGTH];
GetClientName(iTower, sName, sizeof(sName));
int iClient, iTowerId;
for (iClient = 1; iClient <= MaxClients; iClient++) {
if (IsClientInGame(iClient)) {
for (iTowerId = 0; iTowerId < view_as<int>(TDTower_Quantity); iTowerId++) {
Tower_GetName(view_as<TDTowerId>(iTowerId), sName2, sizeof(sName2));
if (StrEqual(sName, sName2)) {
return view_as<TDTowerId>(iTowerId);
}
}
}
}
}
return TDTower_Invalid;
}
/*======================================
= Data Functions =
======================================*/
/**
* Gets the name of a tower.
*
* @param iTowerId The towers id.
* @param sBuffer The destination string buffer.
* @param iMaxLength The maximum length of the output string buffer.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetName(TDTowerId iTowerId, char[] sBuffer, int iMaxLength) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_name", view_as<int>(iTowerId));
return GetTrieString(g_hMapTowers, sKey, sBuffer, iMaxLength);
}
/**
* Gets the class of a tower.
*
* @param iTowerId The towers id.
* @param sBuffer The destination string buffer.
* @param iMaxLength The maximum length of the output string buffer.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetClassString(TDTowerId iTowerId, char[] sBuffer, int iMaxLength) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_class", view_as<int>(iTowerId));
return GetTrieString(g_hMapTowers, sKey, sBuffer, iMaxLength);
}
/**
* Gets the class of a tower.
*
* @param iTowerId The towers id.
* @return The towers class type, or TFClass_Unknown on error.
*/
stock TFClassType Tower_GetClass(TDTowerId iTowerId) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_class", view_as<int>(iTowerId));
char sClass[32];
GetTrieString(g_hMapTowers, sKey, sClass, sizeof(sClass));
if (StrEqual(sClass, "Scout")) {
return TFClass_Scout;
} else if (StrEqual(sClass, "Sniper")) {
return TFClass_Sniper;
} else if (StrEqual(sClass, "Soldier")) {
return TFClass_Soldier;
} else if (StrEqual(sClass, "Demoman")) {
return TFClass_DemoMan;
} else if (StrEqual(sClass, "Medic")) {
return TFClass_Medic;
} else if (StrEqual(sClass, "Heavy")) {
return TFClass_Heavy;
} else if (StrEqual(sClass, "Pyro")) {
return TFClass_Pyro;
} else if (StrEqual(sClass, "Spy")) {
return TFClass_Spy;
} else if (StrEqual(sClass, "Spy")) {
return TFClass_Engineer;
}
return TFClass_Unknown;
}
/**
* Gets the price of a tower.
*
* @param iTowerId The towers id.
* @return The towers price, or -1 on failure.
*/
stock int Tower_GetPrice(TDTowerId iTowerId) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_price", view_as<int>(iTowerId));
int iPrice = 0;
if (!GetTrieValue(g_hMapTowers, sKey, iPrice)) {
return -1;
}
return iPrice;
}
/**
* Gets the location of a tower.
*
* @param iTowerId The towers id.
* @param fLocation The location vector.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetLocation(TDTowerId iTowerId, float fLocation[3]) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_location", view_as<int>(iTowerId));
char sLocation[64];
if (GetTrieString(g_hMapTowers, sKey, sLocation, sizeof(sLocation))) {
char sLocationParts[6][16];
ExplodeString(sLocation, " ", sLocationParts, sizeof(sLocationParts), sizeof(sLocationParts[]));
fLocation[0] = StringToFloat(sLocationParts[0]);
fLocation[1] = StringToFloat(sLocationParts[1]);
fLocation[2] = StringToFloat(sLocationParts[2]);
return true;
}
return false;
}
/**
* Gets the angles of a tower.
*
* @param iTowerId The towers id.
* @param iTowerLevel The towers level.
* @param fAngles The angles vector.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetAngles(TDTowerId iTowerId, float fAngles[3]) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_location", view_as<int>(iTowerId));
char sAngles[64];
if (GetTrieString(g_hMapTowers, sKey, sAngles, sizeof(sAngles))) {
char sAnglesParts[6][16];
ExplodeString(sAngles, " ", sAnglesParts, sizeof(sAnglesParts), sizeof(sAnglesParts[]));
fAngles[0] = Tower_GetPitch(iTowerId);
fAngles[1] = StringToFloat(sAnglesParts[4]);
fAngles[2] = StringToFloat(sAnglesParts[5]);
return true;
}
return false;
}
/**
* Gets the metal to upgrade the tower to the next level.
*
* @param iTowerId The towers id.
* @return The towers upgrade metal, or -1 on failure.
*/
stock int Tower_GetMetal(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_metal", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
int iMetal = 0;
if (!GetTrieValue(g_hMapTowers, sKey, iMetal)) {
return -1;
}
return iMetal;
}
return -1;
}
/**
* Gets the weapon of a tower.
*
* @param iTowerId The towers id.
* @return The towers weapon id, or -1 on failure.
*/
stock int Tower_GetWeapon(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_weapon", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
int iWeapon = 0;
if (!GetTrieValue(g_hMapTowers, sKey, iWeapon)) {
return -1;
}
return iWeapon;
}
return -1;
}
/**
* Checks if a tower should do primary attacks.
*
* @param iTowerId The towers id.
* @return True if should attack, false otherwise.
*/
stock bool Tower_GetAttackPrimary(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_attack", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
char sAttackMode[64];
if (!GetTrieString(g_hMapTowers, sKey, sAttackMode, sizeof(sAttackMode))) {
return false;
}
return StrEqual(sAttackMode, "Primary");
}
return false;
}
/**
* Checks if a tower should do secondary attacks.
*
* @param iTowerId The towers id.
* @return True if should attack, false otherwise.
*/
stock bool Tower_GetAttackSecondary(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_attack", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
char sAttackMode[64];
if (!GetTrieString(g_hMapTowers, sKey, sAttackMode, sizeof(sAttackMode))) {
return false;
}
return StrEqual(sAttackMode, "Secondary");
}
return false;
}
/**
* Checks if a tower should rotate towards enemies.
*
* @param iTowerId The towers id.
* @return True if should rotate, false otherwise.
*/
stock bool Tower_GetRotate(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_rotate", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
int iRotate = 0;
if (!GetTrieValue(g_hMapTowers, sKey, iRotate)) {
return false;
}
if (iRotate != 0)
return true;
}
return false;
}
/**
* Gets the towers pitch.
*
* @param iTowerId The towers id.
* @return The pitch, or 10.0 on failure.
*/
stock float Tower_GetPitch(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_pitch", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
int iPitch = 0;
if (!GetTrieValue(g_hMapTowers, sKey, iPitch)) {
return 0.0;
}
return float(iPitch);
}
return 0.0;
}
/**
* Gets the towers damage scale.
*
* @param iTowerId The towers id.
* @return The damage scale, or 1.0 on failure.
*/
stock float Tower_GetDamageScale(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_damage", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
float fDamage = 1.0;
if (!GetTrieValue(g_hMapTowers, sKey, fDamage)) {
return 1.0;
}
return fDamage;
}
return 1.0;
}
/**
* Gets the towers attackspeed scale.
*
* @param iTowerId The towers id.
* @return The attackspeed scale, or 1.0 on failure.
*/
stock float Tower_GetAttackspeedScale(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_attackspeed", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
float fAttackspeed = 1.0;
if (!GetTrieValue(g_hMapTowers, sKey, fAttackspeed)) {
return 1.0;
}
return fAttackspeed;
}
return 1.0;
}
/**
* Gets the towers area scale.
*
* @param iTowerId The towers id.
* @return The area scale, or 1.0 on failure.
*/
stock float Tower_GetAreaScale(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_%d_area", view_as<int>(iTowerId), g_iUpgradeLevel[iTower]);
float fArea = 1.0;
if (!GetTrieValue(g_hMapTowers, sKey, fArea)) {
return 1.0;
}
return fArea;
}
return 1.0;
}
/**
* Gets the towers max level.
*
* @param iTowerId The towers id.
* @return The max level, or 1 on failure.
*/
stock int Tower_GetMaxLevel(TDTowerId iTowerId) {
int iTower = GetTower(iTowerId);
if (IsTower(iTower)) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_1_metal", view_as<int>(iTowerId));
int iLevel = 1, iMetal = 0;
while (GetTrieValue(g_hMapTowers, sKey, iMetal)) {
iLevel++;
Format(sKey, sizeof(sKey), "%d_%d_metal", view_as<int>(iTowerId), iLevel);
}
return iLevel - 1;
}
return 1;
}
/**
* Gets the description of a tower.
*
* @param iTowerId The towers id.
* @param sBuffer The destination string buffer.
* @param iMaxLength The maximum length of the output string buffer.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetDescription(TDTowerId iTowerId, char[] sBuffer, int iMaxLength) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_description", view_as<int>(iTowerId));
return GetTrieString(g_hMapTowers, sKey, sBuffer, iMaxLength);
}
/**
* Gets the damagetype of a tower.
*
* @param iTowerId The towers id.
* @param sBuffer The destination string buffer.
* @param iMaxLength The maximum length of the output string buffer.
* @return True on success, false if tower was not found.
*/
stock bool Tower_GetDamagetype(TDTowerId iTowerId, char[] sBuffer, int iMaxLength) {
char sKey[32];
Format(sKey, sizeof(sKey), "%d_damagetype", view_as<int>(iTowerId));
return GetTrieString(g_hMapTowers, sKey, sBuffer, iMaxLength);
}