This is a simple tag plugin that I'm probably never going to finish
Forces one player on to red team, everybody else to blue.
Forces everyone be scout
Strips all doors, objectives, and resupply lockers
Strips all weapons except the scout bat.
From there on, it plays out like good old fashioned school yard tag, it seems to work best in CTF maps right now.
I have yet to incorporate a "win" system, nor have I incorporated scoring (no extensions support proper scoreboard modification).
Other plans were to do as follows:
Provide a beacon if a player has been away from the red player a.k.a. "it" player for too long.
Provide a significant score increase if a "non-it" player manages to hit the "it" player.
The two above here would make it so it's not worth it to just 'hide somewhere'
Some bits of code in here are meant towards basic scoring, longest time not-it would end up winning, as well as most bat-hits.
Only mp_timelimit based for now.
So yeah, seeing as I'm most likely never going to finish this, I decided to post it here for someone else to make use of.
Credits:
FlyingMongoose - main code base
Antithysis - A few bug fixes, feature implementations, and improvements
Code:
/* Plugin Template generated by Pawn Studio */
#pragma semicolon 1
#pragma dynamic 65536
#include <sourcemod>
#include <tf2_stocks>
/*#include "calcplayerscore"*/
#define BLUETEAM 3
#define REDTEAM 2
new bool:IsPlayerIt[MAXPLAYERS+1];
new playerCurrentScore[MAXPLAYERS+1];
new timeNotIt[MAXPLAYERS+1];
new String:entsToRemove[12][] =
{
"filter_activator_tfteam",
"func_door",
"func_respawnroomvisualizer",
"team_control_point_master",
"team_control_point",
"trigger_capture_area",
"func_capturezone",
"item_teamflag",
"team_control_point_round",
"func_tracktrain",
"path_track",
"team_train_watcher"
};
public Plugin:myinfo =
{
name = "TF2 Tag",
author = "FlyingMongoose",
description = "Tag game for Team Fortress 2",
version = "1.0.0",
url = "http://www.interwavestudios.com/"
}
public OnPluginStart()
{
HookEvent("player_hurt", ev_PlayerHurt, EventHookMode_Post);
HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre);
HookEvent("arena_round_start", ev_RoundStart, EventHookMode_Post);
HookEvent("teamplay_round_start", ev_RoundStart, EventHookMode_Post);
HookEvent("teamplay_round_win",ev_RoundEnd, EventHookMode_Post);
HookEvent("teamplay_round_stalemate",ev_RoundEnd, EventHookMode_Post);
HookEvent("teamplay_game_over",ev_RoundEnd,EventHookMode_Post);
HookEvent("player_changeclass", ev_ClassChange, EventHookMode_Post);
HookEvent("player_spawn", ev_PlayerSpawn, EventHookMode_Post);
HookEvent("player_death", ev_PlayerDeathPre, EventHookMode_Pre);
HookEvent("player_death", ev_PlayerDeathPost, EventHookMode_Post);
RegConsoleCmd("equip", Command_Equip);
}
public OnAllPluginsLoaded()
{
ServerCommand("mp_teamoverride 0");
ServerCommand("mp_autoteambalance 0");
ServerCommand("tf_weapon_criticals 0");
}
public Action:ev_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
ResetInfo();
}
stock ResetInfo(){
for(new i = 0; i <= GetMaxClients(); ++i)
{
IsPlayerIt[i] = false;
playerCurrentScore[i] = 0;
timeNotIt[i] = 0;
}
}
public OnMapStart()
{
CreateTimer(3.0,Timer_DelayedOnMapStart);
}
public Action:Timer_DelayedOnMapStart(Handle:timer){
new teamRoundTimer = FindEntityByClassname(-1, "team_round_timer");
SetVariantInt(0);
AcceptEntityInput(teamRoundTimer, "setup_length");
}
public OnMapEnd()
{
/*ResetScores();*/
ResetInfo();
}
public OnClientDisconnect(client)
{
if(IsPlayerIt[client]) {
IsPlayerIt[client] = false;
SetEntProp(client, Prop_Data, "m_takedamage", 2, 1);
SetItPlayer(ChooseItPlayer());
}
}
public Action:Command_Equip(client,args)
{
CreateTimer(0.2,Timer_RemoveWeapons,client);
}
public Action:ev_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
ResetInfo();
RemoveEnts();
SetItPlayer(ChooseItPlayer());
CreateTimer(1.0,Timer_ForceSetupFinished);
}
public Action:Timer_ForceSetupFinished(Handle:timer){
new Handle:setupFinished = CreateEvent("teamplay_setup_finished",true);
if(setupFinished != INVALID_HANDLE){
FireEvent(setupFinished,false);
}
setupFinished = INVALID_HANDLE;
}
public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast)
{
new currTeam = GetEventInt(event, "team");
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (IsPlayerIt[client] && currTeam != REDTEAM)
ChangePlayersTeam(client, REDTEAM);
else if (!IsPlayerIt[client] && currTeam != BLUETEAM)
ChangePlayersTeam(client, BLUETEAM);
return Plugin_Handled;
}
public Action:ev_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
if(attacker != 0 && attacker != client && IsPlayerIt[attacker]) {
SetItPlayer(client);
SetTimeScore(client);
ClearItPlayer(attacker);
}
if(!IsPlayerIt[attacker] && IsPlayerIt[client]){
playerCurrentScore[attacker] = TF2_GetPlayerResourceData(attacker,TFResource_Score);
new newScore = playerCurrentScore[attacker] + 10;
TF2_SetPlayerResourceData(attacker,TFResource_Score,newScore);
}
}
stock SetTimeScore(client){
playerCurrentScore[client] = TF2_GetPlayerResourceData(client,TFResource_Score);
new currTime = GetTime();
new newScore = playerCurrentScore[client] + (currTime - timeNotIt[client]);
TF2_SetPlayerResourceData(client,TFResource_Score,newScore);
}
public Action:ev_ClassChange(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
TF2_SetPlayerClass(client, TFClass_Scout);
}
public Action:ev_PlayerDeathPre(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event,"userid"));
new attacker = GetClientOfUserId(GetEventInt(event,"attacker"));
playerCurrentScore[client] = TF2_GetPlayerResourceData(client,TFResource_Score);
playerCurrentScore[attacker] = TF2_GetPlayerResourceData(attacker,TFResource_Score);
return Plugin_Handled;
}
public Action:ev_PlayerDeathPost(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event,"userid"));
new attacker = GetClientOfUserId(GetEventInt(event,"attacker"));
TF2_SetPlayerResourceData(client,TFResource_Score,playerCurrentScore[client]);
TF2_SetPlayerResourceData(attacker,TFResource_Score,playerCurrentScore[attacker]);
TF2_SetPlayerResourceData(client,TFResource_Deaths,0);
TF2_SetPlayerResourceData(attacker,TFResource_Deaths,0);
}
public Action:ev_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event,"userid"));
CreateTimer(0.2, Timer_RemoveWeapons, client);
if (IsPlayerIt[client])
{
SetEntProp(client, Prop_Data, "m_takedamage", 0, 1);
}else{
SetEntProp(client, Prop_Data, "m_takedamage", 2, 1);
timeNotIt[client] = GetTime();
}
}
public Action:Timer_ChangePlayersTeam(Handle:timer, any:pack)
{
new client, team;
ResetPack(pack);
client = ReadPackCell(pack);
team = ReadPackCell(pack);
ChangeClientTeam(client, team);
TF2_SetPlayerClass(client, TFClass_Scout);
TF2_RespawnPlayer(client);
}
public Action:Timer_RemoveWeapons(Handle:timer,any:client)
{EquipPlayerWeapon
for (new weaponslot = 0; weaponslot <= 5; weaponslot++) {
if (weaponslot == 2)
continue;
TF2_RemoveWeaponSlot(client, weaponslot);
}
ClientCommand(client, "slot3");
}
stock ChooseItPlayer()
{
new player = 0;
do {
player = GetRandomInt(1, GetMaxClients());
} while (!IsClientInGame(player));
return player;
}
stock SetItPlayer(client)
{
IsPlayerIt[client] = true;
new String:ClientName[64];
GetClientName(client,ClientName, sizeof(ClientName));
PrintCenterTextAll("%s is now it!", ClientName);
ChangePlayersTeam(client, REDTEAM);
}
stock ClearItPlayer(client)
{
IsPlayerIt[client] = false;
timeNotIt[client] = GetTime();
ChangePlayersTeam(client, BLUETEAM);
}
stock ChangePlayersTeam(client, team)
{
new Handle:pack;
CreateDataTimer(0.1, Timer_ChangePlayersTeam, pack, TIMER_FLAG_NO_MAPCHANGE);
WritePackCell(pack, client);
WritePackCell(pack, team);
}
stock RemoveEnts()
{
new iCurrentEnt = -1;
while ((iCurrentEnt = FindEntityByClassname(iCurrentEnt, "func_regenerate")) != -1) {
AcceptEntityInput(iCurrentEnt, "Disable");
}
for(new i = 0; i < sizeof(entsToRemove); i++) {
iCurrentEnt = -1;
while ((iCurrentEnt = FindEntityByClassname(iCurrentEnt, entsToRemove[i])) != -1) {
AcceptEntityInput(iCurrentEnt, "Kill");
}
}
}
/*public OnCalcPlayerScore(client, score)
{
if (playerCurrentScore[client] > -1)
{
return playerCurrentScore[client];
}
if (newScore[client] != 0)
{
score += newScore[client];
}
return score;
}
stock ResetScores(client=0)
{
if (client != 0)
{
newScore[client] = 0;
playerCurrentScore[client] = -1;
return;
}
for (new i = 1; i <= MAXPLAYERS; i++)
{
newScore[i] = 0;
playerCurrentScore[i] = -1;
}
}*/
To emphasize, I will not support this as a plugin. If anyone picks it up or completes it they are the one who should be asked for support. I will provide help to whomever decides to complete this in the form of answers to questions, but I will not write any more of it, I don't have the time.
__________________