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

430 lines
12 KiB
SourcePawn

/**
* Checks for clients near AoE Towers
*
* @param hTimer Timer Handle
* @param iTower The tower
* @noreturn
*/
public Action Timer_ClientNearAoETower(Handle hTimer) {
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsClientInGame(iClient) && IsPlayerAlive(iClient)) {
if (IsTower(iClient)) {
int iTower = iClient;
TDTowerId iTowerId = GetTowerId(iTower);
if (iTowerId == TDTower_AoE_Engineer) {
float fAreaScale = 80.0 * Tower_GetAreaScale(GetTowerId(iTower));
CreateBeamBoxAroundClient(iTower, fAreaScale, true, 0.2, { 231, 76, 60, 25 });
Tower_ObjectNearAoEEngineer(iTower, iClient);
}
if (iTowerId == TDTower_Medic) {
float fAreaScale = 160.0 * Tower_GetAreaScale(GetTowerId(iTower));
CreateBeamBoxAroundClient(iTower, fAreaScale, true, 0.2, { 46, 204, 113, 25 });
Tower_ObjectNearAoEMedic(iTower);
}
if (iTowerId == TDTower_Kritz_Medic) {
float fAreaScale = 60.0 * Tower_GetAreaScale(GetTowerId(iTower));
CreateBeamBoxAroundClient(iTower, fAreaScale, true, 0.2, { 41, 128, 185, 25 });
Tower_ObjectNearKritzMedic(iTower);
}
if (iTowerId == TDTower_Slow_Spy) {
float fAreaScale = 100.0 * Tower_GetAreaScale(GetTowerId(iTower));
CreateBeamBoxAroundClient(iTower, fAreaScale, false, 0.2, { 44, 62, 80, 25 });
Tower_ObjectNearAoESpy(iTower);
}
}
}
}
return Plugin_Continue;
}
/**
* Player is close to AoEMedic
*
* @param iTower The tower
* @param iClient The player
* @noreturn
*/
public void Tower_ObjectNearAoEMedic(int iTower) {
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsDefender(iClient) && IsClientInZone(iClient, g_fBeamPoints[iTower])) {
Player_AddHealth(iClient, 5);
// Check if there is no Beam
if (g_iHealBeamIndex[iClient][0] == 0 && g_iHealBeamIndex[iClient][1] == 0) {
AttachHealBeam(iTower, iClient);
}
} else {
Tower_ObjectNotNearAoEMedic(iClient);
}
}
}
/**
* Player isn't close to AoEMedic
*
* @param iTower The tower
* @param iClient The player
* @noreturn
*/
public void Tower_ObjectNotNearAoEMedic(int iClient) {
// Remove Beam if there is one
if (g_iHealBeamIndex[iClient][0] != 0) {
if (IsValidEdict(g_iHealBeamIndex[iClient][0])) {
RemoveEdict(g_iHealBeamIndex[iClient][0]);
g_iHealBeamIndex[iClient][0] = 0;
}
}
if (g_iHealBeamIndex[iClient][1] != 0) {
if (IsValidEdict(g_iHealBeamIndex[iClient][1])) {
RemoveEdict(g_iHealBeamIndex[iClient][1]);
g_iHealBeamIndex[iClient][1] = 0;
}
}
}
/**
* Player is close to AoEEngineer
*
* @param iTower The tower
* @param iClient The player
* @noreturn
*/
public void Tower_ObjectNearAoEEngineer(int iTower, int iClient) {
if (iAoEEngineerTimer < 3 && !IsTowerAttached(iTower)) {
iAoEEngineerTimer++;
return;
} else if (!IsTowerAttached(iTower)) {
iAoEEngineerTimer = 0;
}
int iSentry = -1, iDispenser = -1;
float fLocation[3];
// Sentries
while ((iSentry = FindEntityByClassname(iSentry, "obj_sentrygun")) != -1) {
if (!IsValidEntity(iSentry)) {
continue;
}
GetEntPropVector(iSentry, Prop_Send, "m_vecOrigin", fLocation);
fLocation[2] += 20.0;
if (IsPointInZone(fLocation, g_fBeamPoints[iTower])) {
int iShellsMax, iHealthMax, iRocketsMax, iMetalMax;
if (IsMiniSentry(iSentry)) {
iShellsMax = 150;
iHealthMax = 150;
iRocketsMax = 0;
iMetalMax = 0;
} else {
switch (GetBuildingLevel(iSentry)) {
case 1: {
iShellsMax = 150;
iHealthMax = 150;
iRocketsMax = 0;
iMetalMax = 1000;
}
case 2: {
iShellsMax = 200;
iHealthMax = 180;
iRocketsMax = 0;
iMetalMax = 1000;
}
case 3: {
iShellsMax = 200;
iHealthMax = 216;
iRocketsMax = 20;
iMetalMax = 0;
}
}
}
int iState = GetEntProp(iSentry, Prop_Send, "m_iState");
// If is not building up
if (iState != 0) {
int iShells = GetEntProp(iSentry, Prop_Send, "m_iAmmoShells");
int iHealth = GetEntProp(iSentry, Prop_Send, "m_iHealth");
int iRockets = GetEntProp(iSentry, Prop_Send, "m_iAmmoRockets");
int iMetal = GetEntProp(iSentry, Prop_Send, "m_iUpgradeMetal");
if (IsMiniSentry(iSentry)) {
int iShellsPerHit = 20; // Default: 40
if (iShells + iShellsPerHit < iShellsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoShells", iShells + iShellsPerHit);
} else if (iShells < iShellsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoShells", iShellsMax);
}
} else {
int iMetalPerHit = 10; // Default: 25
int iHealthPerHit = 50; // Default: 105
int iShellsPerHit = 20; // Default: 40
int iRocketsPerHit = 4; // Default: 8
if (iMetal < iMetalMax) {
SetEntProp(iSentry, Prop_Send, "m_iUpgradeMetal", iMetal + iMetalPerHit);
// Upgrade to the next level
} else if (iMetalMax != 0 && !g_bAoEEngineerAttack) {
float fLocationTower[3];
GetClientAbsOrigin(iTower, fLocationTower);
TeleportEntity(iTower, fLocation, NULL_VECTOR, NULL_VECTOR);
g_bAoEEngineerAttack = true;
DataPack hPack = new DataPack();
hPack.WriteFloat(float(iTower));
hPack.WriteFloat(fLocationTower[0]);
hPack.WriteFloat(fLocationTower[1]);
hPack.WriteFloat(fLocationTower[2]);
CreateTimer(0.2, Timer_TeleportAoEEngineerBack, hPack, _);
}
if (iHealth + iHealthPerHit < iHealthMax) {
SetEntProp(iSentry, Prop_Send, "m_iHealth", iHealth + iHealthPerHit);
} else if (iHealth < iHealthMax) {
SetEntProp(iSentry, Prop_Send, "m_iHealth", iHealthMax);
}
if (iShells + iShellsPerHit < iShellsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoShells", iShells + iShellsPerHit);
} else if (iShells < iShellsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoShells", iShellsMax);
}
if (iRockets + iRocketsPerHit < iRocketsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoRockets", iRockets + iRocketsPerHit);
} else if (iRockets < iRocketsMax) {
SetEntProp(iSentry, Prop_Send, "m_iAmmoRockets", iRocketsMax);
}
}
}
}
}
// Dispensers
while ((iDispenser = FindEntityByClassname(iDispenser, "obj_dispenser")) != -1) {
if (!IsValidEntity(iDispenser)) {
continue;
}
GetEntPropVector(iDispenser, Prop_Send, "m_vecOrigin", fLocation);
fLocation[2] += 20.0;
if (IsPointInZone(fLocation, g_fBeamPoints[iTower])) {
int iHealthMax, iMetalMax;
switch (GetBuildingLevel(iDispenser)) {
case 1: {
iHealthMax = 150;
iMetalMax = 500;
}
case 2: {
iHealthMax = 180;
iMetalMax = 500;
}
case 3: {
iHealthMax = 216;
iMetalMax = 0;
}
}
int iBuildingUp = GetEntProp(iDispenser, Prop_Send, "m_bBuilding");
if (iBuildingUp != 1) { // Is not building up
int iHealth = GetEntProp(iDispenser, Prop_Send, "m_iHealth");
int iMetal = GetEntProp(iDispenser, Prop_Send, "m_iUpgradeMetal");
int iMetalPerHit = 10; // Default: 25
int iHealthPerHit = 50; // Default: 105
if (iMetal < iMetalMax) {
SetEntProp(iDispenser, Prop_Send, "m_iUpgradeMetal", iMetal + iMetalPerHit);
} else if (iMetalMax != 0 && !g_bAoEEngineerAttack) { // Upgrade to the next level
float fLocationTower[3];
GetClientAbsOrigin(iTower, fLocationTower);
TeleportEntity(iTower, fLocation, NULL_VECTOR, NULL_VECTOR);
g_bAoEEngineerAttack = true;
DataPack hPack = new DataPack();
hPack.WriteFloat(float(iTower));
hPack.WriteFloat(fLocationTower[0]);
hPack.WriteFloat(fLocationTower[1]);
hPack.WriteFloat(fLocationTower[2]);
CreateTimer(0.5, Timer_TeleportAoEEngineerBack, hPack, _);
}
if (iHealth + iHealthPerHit < iHealthMax) {
SetEntProp(iDispenser, Prop_Send, "m_iHealth", iHealth + iHealthPerHit);
} else if (iHealth < iHealthMax) {
SetEntProp(iDispenser, Prop_Send, "m_iHealth", iHealthMax);
}
}
}
}
}
public Action Timer_TeleportAoEEngineerBack(Handle hTimer, DataPack hPack) {
hPack.Reset();
g_bAoEEngineerAttack = false;
int iTower = RoundToZero(ReadPackFloat(hPack));
float fLocation[3];
fLocation[0] = hPack.ReadFloat();
fLocation[1] = hPack.ReadFloat();
fLocation[2] = hPack.ReadFloat();
TeleportEntity(iTower, fLocation, NULL_VECTOR, NULL_VECTOR);
return Plugin_Continue;
}
/**
* Player is close to KritzMedic
*
* @param iTower The tower
* @noreturn
*/
public void Tower_ObjectNearKritzMedic(int iTower) {
// If Kritz Time is up
if (TF2_GetUberLevel(iTower) <= 0.0)
g_bKritzMedicCharged = false;
// If Bot is fully charged, charge player
if (g_bKritzMedicCharged && TF2_GetUberLevel(iTower) > 0.0) {
TF2_SetUberLevel(iTower, TF2_GetUberLevel(iTower) - 0.02);
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsValidClient(iClient))
TF2_AddCondition(iClient, TFCond_Kritzkrieged, 0.3);
}
// If Bot is fully charged
} else if (TF2_GetUberLevel(iTower) >= 1.0) {
g_bKritzMedicCharged = true;
} else if (iAoEKritzMedicTimer < 3 && !IsTowerAttached(iTower)) {
iAoEKritzMedicTimer++;
return;
} else if (!IsTowerAttached(iTower)) {
iAoEKritzMedicTimer = 0;
}
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsDefender(iClient) && IsClientInZone(iClient, g_fBeamPoints[iTower])) {
float fUberLevel = TF2_GetUberLevel(iTower);
TF2_SetUberLevel(iTower, fUberLevel + 0.01);
}
}
}
/**
* Player is close to AoESpy
*
* @param iTower The tower
* @param iClient The player
* @noreturn
*/
public void Tower_ObjectNearAoESpy(int iTower) {
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsAttacker(iClient) && IsClientInZone(iClient, g_fBeamPoints[iTower]) && !g_iSlowAttacker[iClient])
g_iSlowAttacker[iClient] = true;
else if (g_iSlowAttacker[iClient] && IsClientInZone(iClient, g_fBeamPoints[iTower]))
TF2_AddCondition(iClient, TFCond_TeleportedGlow, 1.0);
else if (g_iSlowAttacker[iClient])
g_iSlowAttacker[iClient] = false;
}
}
/**
* Gets the level of an building.
*
* @param iEntity The buildings entity index.
* @return The buildings level.
*/
public int GetBuildingLevel(int iEntity) {
return GetEntProp(iEntity, Prop_Send, "m_iUpgradeLevel");
}
/**
* Checks wheter a sentry is a Mini-Sentry or not.
*
* @param iSentry The sentries entity index.
* @return True if mini, false otherwise.
*/
public bool IsMiniSentry(int iSentry) {
return ((GetEntProp(iSentry, Prop_Send, "m_bMiniBuilding") == 0) ? false : true);
}
/**
* Attach a beam between two entities
*
* @param iEntity The start point
* @param iTarget The target
* @noreturn
*/
stock void AttachHealBeam(int iEntity, int iTarget) {
int iParticleIndex1 = CreateEntityByName("info_particle_system");
int iParticleIndex2 = CreateEntityByName("info_particle_system");
if (IsValidEdict(iParticleIndex1)) {
char sEntityName[128];
Format(sEntityName, sizeof(sEntityName), "target%i", iEntity);
DispatchKeyValue(iEntity, "targetname", sEntityName);
char sTargetName1[128];
Format(sTargetName1, sizeof(sTargetName1), "target%i", iTarget);
DispatchKeyValue(iTarget, "targetname", sTargetName1);
char sTargetName2[128];
Format(sTargetName2, sizeof(sTargetName2), "tf2particle%i", iTarget);
DispatchKeyValue(iParticleIndex2, "targetname", sTargetName2);
DispatchKeyValue(iParticleIndex2, "parentname", sTargetName1);
SetVariantString(sTargetName1);
AcceptEntityInput(iParticleIndex2, "SetParent");
SetVariantString("flag");
AcceptEntityInput(iParticleIndex2, "SetParentAttachment");
DispatchKeyValue(iParticleIndex1, "targetname", "tf2particle");
DispatchKeyValue(iParticleIndex1, "parentname", sEntityName);
DispatchKeyValue(iParticleIndex1, "effect_name", "dispenser_heal_blue");
DispatchKeyValue(iParticleIndex1, "cpoint1", sTargetName2);
DispatchSpawn(iParticleIndex1);
SetVariantString(sEntityName);
AcceptEntityInput(iParticleIndex1, "SetParent");
SetVariantString("flag");
AcceptEntityInput(iParticleIndex1, "SetParentAttachment");
ActivateEntity(iParticleIndex1);
AcceptEntityInput(iParticleIndex1, "start");
g_iHealBeamIndex[iTarget][0] = iParticleIndex1;
g_iHealBeamIndex[iTarget][1] = iParticleIndex2;
}
}
stock float TF2_GetUberLevel(int iClient) {
int iIndex = GetPlayerWeaponSlot(iClient, 1);
if (iIndex > 0)
return GetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel");
else
return 0.0;
}
stock void TF2_SetUberLevel(int iClient, float fUberLevel) {
int iIndex = GetPlayerWeaponSlot(iClient, 1);
if (iIndex > 0)
SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", fUberLevel);
}