#include <sourcemod>
#include <sdktools>
public Plugin:myinfo = {
name = "sm_dods_hns_plugin",
author = "Clément Vuchener",
description = "",
version = "1.0.0.0",
url = "afk-clan.bplaced.de"
};
#define MAX_MODELS 64
#define MAX_MODELNAME_SIZE 128
#define MINPLAYERS 2
// Modelle
new String:models[MAX_MODELS][MAX_MODELNAME_SIZE];
new modelCount = 0;
// Phase des Spiels
#define WAITING 0
#define PREPARATION 1
#define SEEKING 2
#define END 3
new roundState;
new Handle:preptimer = INVALID_HANDLE;
// Rollenspieler
new bool:bSeeker[33];
// Nehmen Sie Änderungen an Team Control
new bool:bSwitching[33];
// CVars
new Handle:cvar_active = INVALID_HANDLE;
new Handle:cvar_preptime = INVALID_HANDLE;
new Handle:cvar_blind = INVALID_HANDLE;
new Handle:cvar_freeze = INVALID_HANDLE;
// Offsets
new m_hObserverTarget_offs;
new m_iObserverMode_offs;
new m_iFOV_offs;
new m_Local_offs;
new m_bDrawViewmodel_offs;
// UserMessageId for Fade.
new UserMsg:g_FadeUserMsgId;
// Initializing Plugin
////////////////////////////
public OnPluginStart () {
new i;
// Initialisierung variab
roundState = PREPARATION;
for (i = 0; i <= 32; i++)
bSwitching
= false;
// Loading Vorlagenliste
new Handle:file;
file = OpenFile("hns_models.txt", "r");
if (file == INVALID_HANDLE) {
SetFailState("Unable to open file cc_models.txt");
}
decl String:buffer[MAX_MODELNAME_SIZE];
i = 0;
while (ReadFileLine(file, buffer, MAX_MODELNAME_SIZE) && i < MAX_MODELS) {
TrimString(buffer);
strcopy(models[i], MAX_MODELNAME_SIZE, buffer);
i++;
}
modelCount = i;
if (modelCount == 0) {
SetFailState("Kein Modell in der Datei hns_models.txt");
}
// Initialize Offsets
m_hObserverTarget_offs = FindSendPropOffs("CDODPlayer", "m_hObserverTarget");
m_iObserverMode_offs = FindSendPropOffs("CDODPlayer", "m_iObserverMode");
m_iFOV_offs = FindSendPropOffs("CDODPlayer", "m_iFOV");
m_Local_offs = FindSendPropOffs("CDODPlayer", "m_Local");
m_bDrawViewmodel_offs = FindSendPropOffs("CDODPlayer", "m_bDrawViewmodel");
// Erklärung Convar
cvar_active = CreateConVar ("hns_active", "0", "Aktivierung des Cache-Cache", FCVAR_NOTIFY | FCVAR_REPLICATED, true, 0.0, true, 1.0);
cvar_preptime = CreateConVar ("hns_preparation_time", "60", "Zeit zum verstecken", FCVAR_NOTIFY | FCVAR_REPLICATED, true, 0.0);
cvar_blind = CreateConVar ("hns_blind_seeker", "0", "Blinded Sucher bei der Vorbereitung", FCVAR_NOTIFY | FCVAR_REPLICATED, true, 0.0, true, 1.0);
cvar_freeze = CreateConVar ("hns_freeze_seeker", "0", "Freeze Sucher bei der Vorbereitung", FCVAR_NOTIFY | FCVAR_REPLICATED, true, 0.0, true, 1.0);
HookConVarChange(cvar_active, Activate);
// User message
g_FadeUserMsgId = GetUserMessageId("Fade");
// Commandes
RegServerCmd("hns_restart", Restart)
RegConsoleCmd("+1st", ThirdOff);
RegConsoleCmd("-1st", ThirdOn);
RegConsoleCmd("+3rd", ThirdOn);
RegConsoleCmd("-3rd", ThirdOff);
// Veranstaltungen
HookEvent ("player_spawn", OnPlayerSpawn);
HookEvent ("player_death", OnPlayerDeath);
HookEvent ("player_team", OnPlayerTeam);
HookEvent ("dod_round_start", OnRoundStart, EventHookMode_Pre);
}
// Enable / Disable-Modus
//////////////////////////////////////
public Activate (Handle:cvar, const StringldVal[], const String:newVal[]) {
if (StringToInt(newVal) != StringToInt(oldVal))
ServerCommand("mp_clan_restartround 3");
if (StringToInt(newVal) == 0 && preptimer != INVALID_HANDLE) {
KillTimer(preptimer);
preptimer = INVALID_HANDLE;
}
}
// Commande hns_restart
////////////////////////
public Action:Restart(args) {
ServerCommand("mp_clan_restartround 1");
}
// Startet das Spiel von einem Timer
////////////////////////////////
public Action:StartT (Handle:timer) {
Start();
}
// Läuft das Spiel
////////////////
Start () {
new maxclients = GetMaxClients();
new client;
new n = GetRandomInt(0, ActivePlayerCount()-1);
roundState = PREPARATION;
for (client = 1; client <= maxclients; client++) {
if (Playing(client)) {
if (n == 0) { // Wählen Sie die Sucher
bSeeker[client] = true;
SetTeam(client, 3);
}
else {
bSeeker[client] = false;
SetTeam(client, 2);
}
n--;
}
else {
// Der Spieler kann das Team beitreten, aber das wollten wir ihn in Ruhe lassen
bSeeker[client] = false;
}
}
new String:class[64];
new maxentities = GetMaxEntities();
for (new i = maxclients+1; i <= maxentities; i++) {
if (IsValidEntity(i)) {
GetEdictClassname(i, class, sizeof(class));
if (strcmp(class, "dod_capture_area") == 0 ||
strcmp(class, "dod_bomb_target") == 0 ||
strcmp(class, "func_team_wall") == 0 ||
strcmp(class, "func_teamblocker") == 0) {
RemoveEdict(i);
}
}
}
// Vorbereitungszeit
if (preptimer != INVALID_HANDLE) {
KillTimer(preptimer);
preptimer = INVALID_HANDLE;
}
preptimer = CreateTimer(0.0, BeginCountDown, GetConVarInt(cvar_preptime));
}
// Test-Sieg
////////////////////
bool:Won () {
new maxclients = GetMaxClients();
new client;
for (client = 1; client <= maxclients; client++)
if (Playing(client)) {
if (!bSeeker[client])
return false;
}
return true;
}
// Testen Sie, ob ein Spieler
//////////////////////////
boollaying (client) {
return IsClientInGame(client) && !IsClientObserver(client);
}
// Anzahl der beteiligten Akteure
///////////////////////////
_:ActivePlayerCount () {
new maxclients = GetMaxClients();
new n = 0;
for (new client = 1; client <= maxclients; client++)
if (Playing(client))
n++;
return n;
}
// Suche starten
/////////////////////////
public Action:BeginCountDown(Handle:timer, any:timeleft) {
preptimer = INVALID_HANDLE;
if (timeleft == 0) {
PrintCenterTextAll("Here we go!");
roundState = SEEKING;
new maxclients = GetMaxClients();
new client;
for (client = 1; client <= maxclients; client++) {
if (Playing(client) && bSeeker[client]) { // Unlock Sucher
if (GetConVarBool(cvar_blind))
PerformBlind(client, 0);
if (GetConVarBool(cvar_freeze))
UnfreezeClient(client);
}
if (!Playing(client)) {
// Die Spieler spielen nicht beitreten werden Sucher
bSeeker[client] = true;
}
}
}
else {
if (timeleft > 10) { // Es zeigt die alle 10 Sekunden
if (timeleft%10 == 0) {
PrintCenterTextAll("%d Sekunden verbleibenden", timeleft);
preptimer = CreateTimer(10.0, BeginCountDown, timeleft-10);
}
else {
preptimer = CreateTimer(float(timeleft%10), BeginCountDown, timeleft-(timeleft%10));
}
}
else { // Es zeigt die Zeit an jedem zweiten
if (timeleft > 1)
PrintCenterTextAll("%d Sekunden verbleibenden", timeleft);
else
PrintCenterTextAll("1 Sekunden verbleibenden", timeleft);
preptimer = CreateTimer(1.0, BeginCountDown, timeleft-1);
}
}
}
// Beginn der Runde: Startet das Spiel, wenn genügend Leute
///////////////////////////////////////////////////
public Action:OnRoundStart (Handle:event, const String:name[], bool:dontBroadcast) {
if (ActivePlayerCount() >= MINPLAYERS) {
roundState = PREPARATION;
if (GetConVarBool(cvar_active))
Start();
}
else
roundState = WAITING;
}
// Ein Spieler ins Spiel
/////////////////////////
public OnClientPutInServer(client) {
if (GetConVarBool(cvar_active)) {
if (roundState == SEEKING) {
bSeeker[client] = true;
}
else {
bSeeker[client] = false;
}
}
}
// Spawn einem Spieler
/////////////////////
public Action:OnPlayerSpawn (Handle:event, const String:name[], bool:dontBroadcast) {
decl ent, i;
new String:model[MAX_MODELNAME_SIZE+12];
if (GetConVarBool(cvar_active)) {
if (roundState == WAITING) {
if (ActivePlayerCount() >= MINPLAYERS) {
Start();
}
}
else {
new userid = GetEventInt(event, "userid");
new client = GetClientOfUserId(userid);
new team = GetTeam(client);
if (team > 1) { // Der Player ist nicht Zuschauer
// Controle des teams
if (bSeeker[client] && team != 3) {
SetTeam(client, 3);
return;
}
if (!bSeeker[client] && team != 2) {
SetTeam(client, 2);
return;
}
// Strip Weapons
for (i = 0; i < 4; i++) {
ent = GetPlayerWeaponSlot(client, i);
if(ent != -1)
RemovePlayerItem(client, ent);
}
if (team == 2) { // USA verstecken muss
// Gibt einen unsichtbaren Messer
ent = GivePlayerItem(client, "weapon_amerknife");
SetEntityRenderMode(ent, RENDER_TRANSCOLOR);
SetEntityRenderColor(ent, 0, 0, 0, 0);
// Random-Modell
i = GetRandomInt(0, modelCount-1);
Format(model, sizeof(model), "models/%s.mdl", models[i]);
if (!IsModelPrecached(model))
PrecacheModel(model)
SetEntityModel(client, model);
// Mal in der dritten Person
SetPOV(client, true);
}
else if (team == 3) { // Deutsch Sucher
GivePlayerItem(client, "weapon_spade");
//Blockiert die Sucher bei der Vorbereitung
if (roundState == PREPARATION) {
if (GetConVarBool(cvar_blind)) {
PerformBlind(client, 0);
PerformBlind(client, 255);
}
if (GetConVarBool(cvar_freeze))
FreezeClient(client);
}
}
}
}
}
}
// Tod eines Spielers
////////////////////
public Action:OnPlayerDeath (Handle:event, const String:name[], bool:dontBroadcast) {
if (GetConVarBool(cvar_active) && roundState == SEEKING) {
new userid = GetEventInt(event, "userid");
new client = GetClientOfUserId(userid);
new team = GetTeam(client);
if (team == 2) {
bSeeker[client] = true;
CreateTimer(0.5, ChangeTeamDelayed, client);
if(Won()) {
PrintCenterTextAll("Alle wurden Gefunden");
ServerCommand("mp_clan_restartround 5");
}
}
}
}
// Ein Spieler das Team wechselt
/////////////////////////////
public Action:OnPlayerTeam (Handle:event, const String:name[], bool:dontBroadcast) {
if (GetConVarBool(cvar_active)) {
new team = GetEventInt(event, "team");
if (roundState > WAITING) {
new userid = GetEventInt(event, "userid");
new client = GetClientOfUserId(userid);
if (bSwitching[client])
bSwitching[client] = false;
else {
if (bSeeker[client] && team != 3) {
SetTeam(client, 3);
}
else if (!bSeeker[client] && team != 2) {
SetTeam(client, 2);
}
}
}
}
}
// Ändern Sie den Teamgeist mit einem Timer
///////////////////////////////////////////
public Action:ChangeTeamDelayed (Handle:timer, any:client) {
SetTeam (client, 3)
}
// Ändern Sie ein Team-Player
/////////////////////////////
SetTeam (client, team) {
new oldTeam = GetTeam(client);
bSwitching[client] = true;
ChangeClientTeam(client, 1);
ChangeClientTeam(client, team);
if (oldTeam > 1)
ShowVGUIPanel(client, team == 3 ? "class_ger" : "class_us", INVALID_HANDLE, false);
}
// Sie ein Team-Player
/////////////////////////////////
GetTeam (client) {
return GetClientTeam(client);
}
// Commandes : +3rd -1st
/////////////////////////
public Action:ThirdOn(client, args) {
if (GetConVarBool(cvar_active))
SetPOV(client, true);
else
PrintToConsole(client, "Command verboten: Cache-Cache ist deaktiviert");
}
// Commandes : -3rd +1st
/////////////////////////
public Action:ThirdOff(client, args) {
if (GetConVarBool(cvar_active))
SetPOV(client, false);
else
PrintToConsole(client, "Command verboten: Cache-Cache ist deaktiviert");
}
// Wechseln Sie die Perspektive eines Spielers
//////////////////////////////////////
SetPOV (client, bool:bThird) {
if (bThird) {
SetEntData(client, m_hObserverTarget_offs, 0, 4, true);
SetEntData(client, m_iObserverMode_offs, 1, 4, true);
SetEntData(client, m_iFOV_offs, 120, 4, true);
SetEntData(client, m_Local_offs+m_bDrawViewmodel_offs, 0, 4, true);
}
else {
SetEntData(client, m_hObserverTarget_offs, 0, 4, true);
SetEntData(client, m_iObserverMode_offs, 0, 4, true);
SetEntData(client, m_iFOV_offs, 90, 4, true);
SetEntData(client, m_Local_offs+m_bDrawViewmodel_offs, 1, 4, true);
}
}
PerformBlind(target, amount)
{
new targets[2];
targets[0] = target;
targets[1] = 0;
new Handle:message = StartMessageEx(g_FadeUserMsgId, targets, 1);
BfWriteShort(message, 1536);
BfWriteShort(message, 1536);
if (amount == 0)
{
BfWriteShort(message, (0x0001 | 0x0010));
}
else
{
BfWriteShort(message, (0x0002 | 0x000);
}
BfWriteByte(message, 0);
BfWriteByte(message, 0);
BfWriteByte(message, 0);
BfWriteByte(message, amount);
EndMessage();
}
FreezeClient(client)
{
SetEntityMoveType(client, MOVETYPE_NONE);
}
UnfreezeClient(client)
{
SetEntityMoveType(client, MOVETYPE_WALK);
}