Initial commit
This commit is contained in:
386
scripting/towerdefense/events.sp
Normal file
386
scripting/towerdefense/events.sp
Normal file
@@ -0,0 +1,386 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#if defined INFO_INCLUDES
|
||||
#include "info/constants.sp"
|
||||
#include "info/enums.sp"
|
||||
#include "info/variables.sp"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Hooks all necessary events.
|
||||
* Some events may be hooked with EventHookMode_Pre or EventHookMode_Post.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
|
||||
stock void HookEvents() {
|
||||
HookEvent("player_activate", Event_PlayerActivate);
|
||||
HookEvent("player_carryobject", Event_PlayerCarryObject);
|
||||
HookEvent("player_changeclass", Event_PlayerChangeClass);
|
||||
HookEvent("player_team", Event_PlayerChangeTeamPre, EventHookMode_Pre);
|
||||
HookEvent("player_connect_client", Event_PlayerConnectPre, EventHookMode_Pre);
|
||||
HookEvent("player_death", Event_PlayerDeath);
|
||||
HookEvent("player_disconnect", Event_PlayerDisconnectPre, EventHookMode_Pre);
|
||||
HookEvent("player_dropobject", Event_PlayerDropObject);
|
||||
HookEvent("post_inventory_application", Event_PostInventoryApplication, EventHookMode_Post);
|
||||
HookEvent("teamplay_round_win", Event_RoundWin);
|
||||
|
||||
// User Messages
|
||||
HookUserMessage(GetUserMessageId("VGUIMenu"), Event_PlayerVGUIMenu, true);
|
||||
|
||||
AddNormalSoundHook(Event_Sound);
|
||||
}
|
||||
|
||||
public void Event_PlayerActivate(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
int iUserId = GetEventInt(hEvent, "userid");
|
||||
int iClient = GetClientOfUserId(iUserId);
|
||||
|
||||
char sSteamId[32];
|
||||
GetClientAuthId(iClient, AuthId_Steam2, sSteamId, sizeof(sSteamId));
|
||||
|
||||
if (!StrEqual(sSteamId, "BOT")) {
|
||||
Player_Loaded(iUserId, iClient);
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PlayerCarryObject(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
||||
|
||||
if (IsDefender(iClient)) {
|
||||
g_bCarryingObject[iClient] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PlayerChangeClass(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
||||
|
||||
if (IsValidClient(iClient) && !IsFakeClient(iClient)) {
|
||||
TF2_SetPlayerClass(iClient, TFClass_Engineer, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Event_PlayerChangeTeamPre(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
if (GetEventBool(hEvent, "disconnect")) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
||||
|
||||
SetEventBroadcast(hEvent, true); // Block the chat output (Player ... joined team BLU)
|
||||
|
||||
if (IsValidClient(iClient) && !IsFakeClient(iClient)) {
|
||||
CPrintToChatAll("%s %t", PLUGIN_PREFIX, "eventPlayerJoined", GetClientNameShort(iClient));
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Event_PlayerConnectPre(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
SetEventBroadcast(hEvent, true); // Block the original chat output (Player ... has joined the game)
|
||||
Database_UpdateServerPlayerCount();
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Event_PlayerDeath(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
int iUserId = GetEventInt(hEvent, "userid");
|
||||
int iClient = GetClientOfUserId(iUserId);
|
||||
int iAttackerId = GetEventInt(hEvent, "attacker");
|
||||
// Check if attacker is a Defender
|
||||
if (IsValidClient(GetClientOfUserId(iAttackerId)) && IsDefender(GetClientOfUserId(iAttackerId))) {
|
||||
int iAttacker = GetClientOfUserId(iAttackerId);
|
||||
Player_CAddValue(iAttacker, PLAYER_KILLS, 1);
|
||||
}
|
||||
// Check if assister is a Defender
|
||||
int iAssisterId = GetEventInt(hEvent, "assister");
|
||||
if (IsValidClient(GetClientOfUserId(iAssisterId)) && IsDefender(GetClientOfUserId(iAssisterId))) {
|
||||
int iAssister = GetClientOfUserId(iAssisterId);
|
||||
Player_CAddValue(iAssister, PLAYER_ASSISTS, 1);
|
||||
}
|
||||
|
||||
if (IsDefender(iClient)) {
|
||||
Player_OnDeath(iUserId, iClient);
|
||||
} else if (IsAttacker(iClient)) {
|
||||
int entity = GetEventInt(hEvent, "victim_entindex");
|
||||
|
||||
float position[3];
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", position);
|
||||
|
||||
Wave_OnDeath(iClient, position);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Event_PlayerDisconnectPre(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
int iUserId = GetEventInt(hEvent, "userid");
|
||||
int iClient = GetClientOfUserId(iUserId);
|
||||
|
||||
if (IsDefender(iClient)) {
|
||||
Player_OnDisconnectPre(iUserId, iClient);
|
||||
Database_UpdateServerPlayerCount();
|
||||
} else {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Event_PlayerDropObject(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
||||
|
||||
if (IsDefender(iClient)) {
|
||||
g_bCarryingObject[iClient] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PostInventoryApplication(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
int iUserId = GetEventInt(hEvent, "userid");
|
||||
int iClient = GetClientOfUserId(iUserId);
|
||||
|
||||
if (IsValidClient(iClient) && IsClientConnected(iClient) && IsClientInGame(iClient) && !IsFakeClient(iClient) && GetClientTeam(iClient) == TEAM_ATTACKER) {
|
||||
ChangeClientTeam(iClient, TEAM_DEFENDER);
|
||||
CreateTimer(0.5, RespawnPlayer, iClient);
|
||||
} else if (IsDefender(iClient)) {
|
||||
Player_OnSpawn(iUserId, iClient);
|
||||
} else if (IsTower(iClient)) {
|
||||
Tower_OnSpawn(iClient, GetTowerId(iClient));
|
||||
} else if (IsAttacker(iClient)) {
|
||||
Wave_OnSpawn(iClient);
|
||||
RequestFrame(Wave_OnSpawnPost, iClient);
|
||||
}
|
||||
|
||||
SetEntProp(iClient, Prop_Data, "m_CollisionGroup", 13); // COLLISION_GROUP_PROJECTILE
|
||||
}
|
||||
|
||||
public Action Event_RoundWin(Handle hEvent, const char[] sName, bool bDontBroadcast) {
|
||||
int iTeam = GetEventInt(hEvent, "team");
|
||||
Server_UAddValue(g_iServerId, SERVER_ROUNDS_PLAYED, 1);
|
||||
|
||||
for (int iClient = 1; iClient <= MaxClients; iClient++) {
|
||||
if (IsDefender(iClient)) {
|
||||
int iUserId = GetClientUserId(iClient);
|
||||
int iTime = GetTime() - g_iTime;
|
||||
Player_CSetValue(iClient, PLAYER_PLAYTIME, iTime);
|
||||
Server_UAddValue(g_iServerId, SERVER_PLAYTIME, iTime);
|
||||
Player_CSetValue(iClient, PLAYER_ROUNDS_PLAYED, 1);
|
||||
Database_UpdatePlayerDisconnect(iUserId);
|
||||
}
|
||||
}
|
||||
|
||||
Database_ServerStatsUpdate();
|
||||
|
||||
ServerCommand("bot_kick all");
|
||||
ServerCommand("mp_autoteambalance 0");
|
||||
|
||||
if (iTeam == TEAM_ATTACKER) {
|
||||
CPrintToChatAll("%s %t", PLUGIN_PREFIX, "eventGameOver");
|
||||
//PrintToChatAll("\x07FF0000Game over! Resetting the map...");
|
||||
}
|
||||
Server_Reset();
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Event_Sound(int iClients[64], int &iNumClients, char sSample[PLATFORM_MAX_PATH], int &iEntity, int &iChannel, float &fVolume, int &iLevel, int &iPitch, int &iFlags) {
|
||||
if (!g_bEnabled) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
if (IsValidEntity(iEntity) && IsTower(iEntity)) {
|
||||
// Allow engineer hitting building sounds
|
||||
if (StrContains(sSample, "wrench_hit_build_") != -1 || StrContains(sSample, "wrench_swing") != -1) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
/*====================================
|
||||
= Usermessages =
|
||||
====================================*/
|
||||
public Action Event_PlayerVGUIMenu(UserMsg iMessageId, Handle hBitBuffer, const int[] iPlayers, int iPlayersNum, bool bReliable, bool bInit) {
|
||||
char sBuffer1[64];
|
||||
char sBuffer2[256];
|
||||
|
||||
// check menu name
|
||||
BfReadString(hBitBuffer, sBuffer1, sizeof(sBuffer1));
|
||||
if (strcmp(sBuffer1, "info") != 0) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
// Skip hidden motd
|
||||
if (BfReadByte(hBitBuffer) != 1) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
int iCount = BfReadByte(hBitBuffer);
|
||||
|
||||
if (iCount == 0) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
Handle hKeyValues = CreateKeyValues("data");
|
||||
|
||||
for (int i = 0; i < iCount; i++) {
|
||||
BfReadString(hBitBuffer, sBuffer1, sizeof(sBuffer1));
|
||||
BfReadString(hBitBuffer, sBuffer2, sizeof(sBuffer2));
|
||||
|
||||
if (StrEqual(sBuffer1, "customsvr") || (StrEqual(sBuffer1, "msg") && !StrEqual(sBuffer2, "motd"))) {
|
||||
delete hKeyValues;
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
KvSetString(hKeyValues, sBuffer1, sBuffer2);
|
||||
}
|
||||
|
||||
Handle hPack;
|
||||
|
||||
CreateDataTimer(0.0, ShowMotd, hPack, TIMER_FLAG_NO_MAPCHANGE);
|
||||
|
||||
WritePackCell(hPack, GetClientUserId(iPlayers[0]));
|
||||
WritePackCell(hPack, view_as<int>(hKeyValues));
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action ShowMotd(Handle hTimer, Handle hPack) {
|
||||
ResetPack(hPack);
|
||||
|
||||
int iClient = GetClientOfUserId(ReadPackCell(hPack));
|
||||
Handle hKeyValues = view_as<Handle>(ReadPackCell(hPack));
|
||||
|
||||
if (!IsValidClient(iClient)) {
|
||||
CloseHandle(hKeyValues);
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
KvSetNum(hKeyValues, "customsvr", 1);
|
||||
KvSetNum(hKeyValues, "cmd", 5); // closed_htmlpage
|
||||
KvSetNum(hKeyValues, "type", MOTDPANEL_TYPE_URL);
|
||||
|
||||
KvSetString(hKeyValues, "title", "Welcome to TF2 Tower Defense!");
|
||||
KvSetString(hKeyValues, "msg", "https://tf2td.github.io/towerdefense/");
|
||||
|
||||
ShowVGUIPanel(iClient, "info", hKeyValues, true);
|
||||
|
||||
CloseHandle(hKeyValues);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
/*==================================
|
||||
= TF2 Events =
|
||||
==================================*/
|
||||
|
||||
/**
|
||||
* Called on weapon fire to decide if the current shot should be critical.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
public Action TF2_CalcIsAttackCritical(int iClient, int iWeapon, char[] sClassname, bool &bResult) {
|
||||
if (!g_bEnabled) {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
// If hitting with Wrench
|
||||
if (StrEqual(sClassname, "tf_weapon_wrench") || StrEqual(sClassname, "tf_weapon_robot_arm")) {
|
||||
float fLocation[3], fAngles[3];
|
||||
|
||||
GetClientEyePosition(iClient, fLocation);
|
||||
GetClientEyeAngles(iClient, fAngles);
|
||||
|
||||
TR_TraceRayFilter(fLocation, fAngles, MASK_PLAYERSOLID, RayType_Infinite, TraceRayPlayers, iClient);
|
||||
|
||||
if (TR_DidHit()) {
|
||||
int iTower = TR_GetEntityIndex();
|
||||
|
||||
if (IsTower(iTower)) {
|
||||
float fHitLocation[3];
|
||||
TR_GetEndPosition(fHitLocation);
|
||||
|
||||
if (GetVectorDistance(fLocation, fHitLocation) <= 70.0) {
|
||||
Tower_OnUpgrade(iTower, iClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unlimited ammo/metal for towers
|
||||
if (IsTower(iClient)) {
|
||||
SetEntData(iWeapon, FindSendPropInfo("CTFWeaponBase", "m_iClip1"), 100, _, true);
|
||||
SetEntData(iClient, FindSendPropInfo("CTFPlayer", "m_iAmmo") + 4, 100);
|
||||
SetEntData(iClient, FindSendPropInfo("CTFPlayer", "m_iAmmo") + 8, 100);
|
||||
SetEntData(iClient, FindDataMapInfo(iClient, "m_iAmmo") + (3 * 4), 100);
|
||||
}
|
||||
|
||||
// Calculate crit chances
|
||||
if (fMultiplier[Multiplier_GetInt("crit")] == 0.0) {
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
if (fMultiplier[Multiplier_GetInt("crit")] * 0.05 * 100 >= GetRandomInt(0, 100)) {
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/*=======================================
|
||||
= TF2Items Events =
|
||||
=======================================*/
|
||||
|
||||
/**
|
||||
* Called when an item was given to a client.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
public int TF2Items_OnGiveNamedItem_Post(int iClient, char[] sClassname, int iItemDefinitionIndex, int iItemLevel, int iItemQuality, int iEntityIndex) {
|
||||
if (!g_bEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDefender(iClient)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iItemDefinitionIndex != 9 || iItemDefinitionIndex != 199) {
|
||||
// Engineers primaries => Engineer's Shotgun
|
||||
|
||||
g_bReplaceWeapon[iClient][TFWeaponSlot_Primary] = true;
|
||||
}
|
||||
|
||||
if (iItemDefinitionIndex != 22 || iItemDefinitionIndex != 209 || iItemDefinitionIndex != 160 || iItemDefinitionIndex != 294) {
|
||||
// Engineers secondaries => Engineer's Pistol
|
||||
|
||||
g_bReplaceWeapon[iClient][TFWeaponSlot_Secondary] = true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user