diff --git a/plugins/l4d2_prophunt.smx b/plugins/l4d2_prophunt.smx index afcdef1..2265ef1 100644 Binary files a/plugins/l4d2_prophunt.smx and b/plugins/l4d2_prophunt.smx differ diff --git a/scripting/include/prophunt/phcmds.inc b/scripting/include/prophunt/phcmds.inc index 6399ca5..a26d0b0 100644 --- a/scripting/include/prophunt/phcmds.inc +++ b/scripting/include/prophunt/phcmds.inc @@ -166,13 +166,13 @@ public Action Command_PropHunt(int client, int args) { return Plugin_Handled; } else if(StrEqual(subcmd, "pos", false)) { float pos[3]; - GetAbsOrigin(client, pos); + GetClientAbsOrigin(client, pos); ReplyToCommand(client, "\"origin\" \"%f %f %f\"", pos[0], pos[1], pos[2]); GetClientEyeAngles(client, pos); ReplyToCommand(client, "\"rotation\" \"%f %f %f\"", pos[0], pos[1], pos[2]); } else if(StrEqual(subcmd, "prop", false)) { float pos[3]; - GetAbsOrigin(client, pos); + GetClientAbsOrigin(client, pos); ReplyToCommand(client, "\"MYPROP\""); ReplyToCommand(client, "{"); ReplyToCommand(client, "\t\"origin\" \"%f %f %f\"", pos[0], pos[1], pos[2]); @@ -220,10 +220,36 @@ public Action Command_PropHunt(int client, int args) { ReplyToTargetError(client, target_count); return Plugin_Handled; } - Game.ForceSetSeeker(target_list[0]); - ReplyToCommand(client, "Set the current seeker to %N", target_list[0]); + Game.SetSeeker(target_list[0], true); + ReplyToCommand(client, "Made %N a seeker", target_list[0]); } else { - ReplyToCommand(client, "The current seeker is: %N", Game.Seeker); + ReplyToCommand(client, "Specify a player to make a seeker"); + } + } else if(StrEqual(subcmd, "prop")) { + if(args == 2) { + char arg1[32]; + GetCmdArg(2, arg1, sizeof(arg1)); + char target_name[MAX_TARGET_LENGTH]; + int target_list[1], target_count; + bool tn_is_ml; + if ((target_count = ProcessTargetString( + arg1, + client, + target_list, + 1, + 0, + target_name, + sizeof(target_name), + tn_is_ml)) <= 0 + || target_list[0] <= 0){ + /* This function replies to the admin with a failure message */ + ReplyToTargetError(client, target_count); + return Plugin_Handled; + } + Game.SetSeeker(target_list[0], false); + ReplyToCommand(client, "Made %N a prop", target_list[0]); + } else { + ReplyToCommand(client, "Specify a player to make a prop"); } } else if(StrEqual(subcmd, "debug")) { ReplyToCommand(client, "- Game Info -"); @@ -236,9 +262,6 @@ public Action Command_PropHunt(int client, int args) { else ReplyToCommand(client, "Has Spawnpoint: no (possibly map spawn %f %f %f)", mapConfig.spawnpoint[0], mapConfig.spawnpoint[1], mapConfig.spawnpoint[2]); ReplyToCommand(client, "Map Time: %d", mapConfig.mapTime); - ReplyToCommand(client, "Flow Bounds: (%f, %f)", movePoints.MinFlow, movePoints.MaxFlow); - } else if(StrEqual(subcmd, "test")) { - } else { ReplyToCommand(client, "Unknown option. Leave blank for help"); } @@ -266,12 +289,18 @@ public Action Command_PropHunt(int client, int args) { public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs) { if(isEnabled) { if(!StrEqual(command, "say")) { //Is team message - if(currentSeeker <= 0 || currentSeeker == client) { - return Plugin_Continue; - } - for(int i = 1; i <= MaxClients; i++) { - if(IsClientConnected(i) && IsClientInGame(i) && i != currentSeeker) - PrintToChat(i, "[Hiders] %N: %s", client, sArgs); + if(Game.IsSeeker(client)) { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && Game.IsSeeker(i)) { + PrintToChat(i, "[Seekers] %N: %s", client, sArgs); + } + } + } else { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && !Game.IsSeeker(i)) { + PrintToChat(i, "[Hiders] %N: %s", client, sArgs); + } + } } return Plugin_Handled; } @@ -316,7 +345,7 @@ public Action Command_Join(int client, int args) { } ReplyToCommand(client, "Joined %s", target_name); } else { - if(currentSeeker == client) { + if(Game.IsSeeker(client)) { ReplyToCommand(client, "You are already in-game as a seeker."); return Plugin_Handled; } diff --git a/scripting/include/prophunt/phents.inc b/scripting/include/prophunt/phents.inc index 670c13e..e46bcee 100644 --- a/scripting/include/prophunt/phents.inc +++ b/scripting/include/prophunt/phents.inc @@ -126,3 +126,8 @@ void SetupEntities(bool blockers = true, bool props = true, bool portals = true) } } + +stock int Entity_GetHammerId(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_iHammerID"); +} \ No newline at end of file diff --git a/scripting/include/prophunt/phgame.inc b/scripting/include/prophunt/phgame.inc index f5f6d6f..d58f3b1 100644 --- a/scripting/include/prophunt/phgame.inc +++ b/scripting/include/prophunt/phgame.inc @@ -42,11 +42,10 @@ bool FindSpawnPosition(float pos[3], bool includePlayers = true) { static char buffer[128]; -bool isSeeker[MAXPLAYERS+1]; methodmap PropHuntGame < BaseGame { - property int Seekers { + property int SeekersCount { public get() { int count = 0; for(int i = 1; i <= MaxClients; i++) { @@ -55,13 +54,25 @@ methodmap PropHuntGame < BaseGame { return count; } } + property int PropsCount { + public get() { + int count = 0; + for(int i = 1; i <= MaxClients; i++) { + if(!isSeeker[i]) count++; + } + return count; + } + } public bool IsSeeker(int client) { return isSeeker[client]; } - public void SetSeeker(int client, bool value) { + public bool SetSeeker(int client, bool value) { isSeeker[client] = value; + hasBeenSeeker[client] = true; + DispatchKeyValue(client, "rendercolor", value ? WHITE : TRANSPARENT); + return true; } public void ClearSeekers() { @@ -135,36 +146,6 @@ methodmap PropHuntGame < BaseGame { DeleteCustomEnts(); } - public int _FindSeeker() { - if(!isEnabled) return -1; - L4D2_GetVScriptOutput("g_ModeScript.MutationState.CurrentSeeker && \"GetPlayerUserId\" in g_ModeScript.MutationState.CurrentSeeker ? g_ModeScript.MutationState.CurrentSeeker.GetPlayerUserId() : -1", buffer, sizeof(buffer)); - int uid = StringToInt(buffer); - if(uid > 0) { - return GetClientOfUserId(uid); - } else { - Game.Debug("Mutation has no seeker, manually attempting to find seeker"); - for(int i = 1; i <= MaxClients; i++) { - if(IsClientConnected(i) && IsClientInGame(i)) { - int entity = GetPlayerWeaponSlot(i, 1); - if(entity > -1 && GetEntityClassname(entity, buffer, sizeof(buffer)) && StrEqual(buffer, "melee")) { - GetEntPropString(entity, Prop_Data, "m_strMapSetScriptName", buffer, sizeof(buffer)); - if(StrEqual(buffer, "smg")) { - return i; - } - } - } - } - } - Game.Debug("All attempts to find a seeker failed"); - return -1; - } - - - public void ForceSetSeeker(int client, bool ignoreBalance = false) { - ignoreSeekerBalance = true; - this.Seeker = client; - } - public bool TeleportToSpawn(int client) { if(mapConfig.hasSpawnpoint) { TeleportEntity(client, mapConfig.spawnpoint, NULL_VECTOR, NULL_VECTOR); @@ -193,11 +174,22 @@ methodmap PropHuntGame < BaseGame { } // Ignores seeker - property int AlivePlayers { + property int PropsAlive { public get() { int amount = 0; for(int i = 1; i <= MaxClients; i++) { - if(!this.IsSeeker(i) && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && !IsFakeClient(i)) { + if(!isSeeker[i] && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) > 1 && IsPlayerAlive(i) && !IsFakeClient(i)) { + amount++; + } + } + return amount; + } + } + property int SeekersAlive { + public get() { + int amount = 0; + for(int i = 1; i <= MaxClients; i++) { + if(!isSeeker[i] && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) > 1 && IsPlayerAlive(i) && !IsFakeClient(i)) { amount++; } } @@ -205,20 +197,35 @@ methodmap PropHuntGame < BaseGame { } } - public void SetupInventory(int client) { - ClearInventory(client); - if(this.IsSeeker(client)) { - CheatCommand(client, "give", "smg"); - } + public void SetupProp(int client) { + PrintToChatAll("SetupProp"); + int propIndex = GetURandomInt() % MAX_VALID_MODELS; + + propData[client].prop = CreatePropInternal(VALID_MODELS[propIndex]); + DispatchKeyValue(client, "rendercolor", TRANSPARENT); + SDKHook(client, SDKHook_SetTransmit, OnPlayerTransmit); + } + + public void SetupSeeker(int client) { + CheatCommand(client, "give", "smg"); } public void SetupPlayer(int client) { - this.SetupInventory(client); + ClearInventory(client); + + ChangeClientTeam(client, 2); + SetEntProp(client, Prop_Send, "m_survivorCharacter", GetURandomInt() % 7); SDKHook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive); } public void UnsetupPlayer(int client) { + DispatchKeyValue(client, "rendercolor", WHITE); SDKUnhook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive); + hasBeenSeeker[client] = false; + isSeeker[client] = false; + SDKUnhook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive); + SetPlayerBlind(client, 0); + SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0); } } @@ -348,43 +355,3 @@ static char AUTO_VOCALIZATIONS[MAX_AUTO_VOCALIZATIONS][] = { "ResponseSoftDispleasureSwear", "PlayerAreaClear" }; - -enum struct HiderDistQueue { - int index; - float list[HIDER_DISTANCE_MAX_SIZE]; - int lastVocalize; - - void AddPos(const float pos[3]) { - this.list[this.index] = GetVectorDistance(seekerPos, pos); - if(++this.index == HIDER_DISTANCE_MAX_SIZE) { - this.index = 0; - } - } - - void Clear() { - for(int i = 0; i < HIDER_DISTANCE_MAX_SIZE; i++) { - this.list[i] = 0.0; - } - } - - float GetAverage() { - float sum = 0.0; - for(int i = 0; i < HIDER_DISTANCE_MAX_SIZE; i++) { - sum += this.list[i]; - } - return sum / float(HIDER_DISTANCE_MAX_SIZE); - } - - void Check(int i) { - if(this.GetAverage() > HIDER_MIN_AVG_DISTANCE_AUTO_VOCALIZE) { - int time = GetTime(); - if(time - this.lastVocalize > HIDER_AUTO_VOCALIZE_GRACE_TIME) { - this.lastVocalize = time; - int index = GetRandomInt(0, MAX_AUTO_VOCALIZATIONS - 1); - PerformScene(i, AUTO_VOCALIZATIONS[index]); - } - } - } -} - -HiderDistQueue distQueue[MAXPLAYERS+1]; \ No newline at end of file diff --git a/scripting/include/prophunt/phtimers.inc b/scripting/include/prophunt/phtimers.inc index 1a37392..ff1e165 100644 --- a/scripting/include/prophunt/phtimers.inc +++ b/scripting/include/prophunt/phtimers.inc @@ -1,23 +1,3 @@ - -Action Timer_RecordPoints(Handle h, int i) { - if(GetEntityFlags(i) & FL_ONGROUND && IsPlayerAlive(i)) { - LocationMeta meta; - GetClientAbsOrigin(i, meta.pos); - GetClientEyeAngles(i, meta.ang); - if(meta.pos[0] != vecLastLocation[i][0] || meta.pos[1] != vecLastLocation[i][1] || meta.pos[2] != vecLastLocation[i][2]) { - if(movePoints.AddPoint(meta)) { - recordTimer = null; - return Plugin_Stop; - } - Effect_DrawBeamBoxRotatableToClient(i, meta.pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {0, 0, 255, 64}, 0); - vecLastLocation[i] = meta.pos; - } - } - PrintHintText(i, "Points: %d / %d", movePoints.Length, MAX_VALID_LOCATIONS); - return Plugin_Continue; -} - -bool firstCheckDone = false; Action Timer_WaitForPlayers(Handle h) { if(!isEnabled) return Plugin_Stop; if(!ArePlayersJoining()) { @@ -36,27 +16,25 @@ Action Timer_WaitForPlayers(Handle h) { } -Action Timer_CheckHiders(Handle h) { - static float pos[3]; - static char classname[16]; +Action Timer_StartGame(Handle h) { + Game.State = State_Active; + Game.MapTime = DEFAULT_GAME_TIME; + Game.Tick = 0; for(int i = 1; i <= MaxClients; i++) { - if(IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) { - GetClientAbsOrigin(i, pos); - distQueue[i].AddPos(pos); - distQueue[i].Check(i); - - int activeWeapon = GetEntPropEnt(i, Prop_Send, "m_hActiveWeapon"); - if(IsValidEntity(activeWeapon)) { - GetEntityClassname(activeWeapon, classname, sizeof(classname)); - if(i == currentSeeker) { - if(StrEqual(classname, "weapon_melee")) continue; - Game.SetupInventory(i); - } else if(StrEqual(classname, "weapon_gnome")) continue; + if(IsClientConnected(i) && IsClientInGame(i)) { + if(Game.IsSeeker(i)) { + Game.SetupSeeker(i); } - Game.SetupInventory(i); + SetPlayerBlind(i, 0); + SetEntPropFloat(i, Prop_Send, "m_flLaggedMovementValue", 1.0); } } - Game.CleanupGnomes(true); + Game.Broadcast("Get ready here they come"); + return Plugin_Continue; +} + +Action Timer_TimesUp(Handle h) { + Game.End(State_PropsWin); return Plugin_Continue; } diff --git a/scripting/l4d2_prophunt.sp b/scripting/l4d2_prophunt.sp index c8624ca..3147d3a 100644 --- a/scripting/l4d2_prophunt.sp +++ b/scripting/l4d2_prophunt.sp @@ -4,12 +4,14 @@ //#define DEBUG #define PLUGIN_VERSION "1.0" +#define BLIND_TIME 30 +#define DEFAULT_GAME_TIME 600 #include #include #include -#include -#include +#include + enum GameState { State_Unknown = 0, @@ -20,12 +22,11 @@ enum GameState { } #define MAX_VALID_MODELS 2 -static char VALID_MODELS[MAX_VALID_MODELS][] = { +char VALID_MODELS[MAX_VALID_MODELS][] = { "models/props_crates/static_crate_40.mdl", "models/props_junk/gnome.mdl" }; -static float EMPTY_ANG[3]; #define TRANSPARENT "255 255 255 0" #define WHITE "255 255 255 255" @@ -34,8 +35,22 @@ enum struct PropData { bool rotationLock; } +UserMsg g_FadeUserMsgId; + PropData propData[MAXPLAYERS+1]; +bool isSeeker[MAXPLAYERS+1]; +bool hasBeenSeeker[MAXPLAYERS+1]; +bool isStarting, firstCheckDone; + +Handle timesUpTimer; +Handle waitTimer; + +PropHuntGame Game; + +#include +#include + public Plugin myinfo = { name = "Prophunt", @@ -50,13 +65,174 @@ public void OnPluginStart() { if(g_Game != Engine_Left4Dead2) { SetFailState("This plugin is for L4D2 only."); } + Game.Init("PropHunt"); + + g_FadeUserMsgId = GetUserMessageId("Fade"); + RegConsoleCmd("sm_game", Command_Test); + RegAdminCmd("sm_prophunt", Command_PropHunt, ADMFLAG_KICK); + RegAdminCmd("sm_ph", Command_PropHunt, ADMFLAG_KICK); + + ConVar hGamemode = FindConVar("mp_gamemode"); + hGamemode.AddChangeHook(Event_GamemodeChange); + Event_GamemodeChange(hGamemode, gamemode, gamemode); +} + +public void OnPluginEnd() { + OnMapEnd(); +} + +void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) { + waitTimer = CreateTimer(firstCheckDone ? 2.5 : 6.0, Timer_WaitForPlayers, _, TIMER_REPEAT); +} + +void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) { + // Skip the check, everyone's loaded in + firstCheckDone = true; +} + + +public void OnClientPutInServer(int client) { + if(!isEnabled) return; + if(IsFakeClient(client)) { + KickClient(client, "ph: Remove Special Infected"); + } else { + ChangeClientTeam(client, 1); + isPendingPlay[client] = true; + Game.Broadcast("%N will play next round", client); + Game.TeleportToSpawn(client); + } +} + + +public void OnClientDisconnect(int client) { + if(!isEnabled) return; + ResetPlayerData(client); + if(Game.IsSeeker(client)) { + if(Game.SeekersAlive == 0) { + Game.Broadcast("All seekers have disconnected, Props win"); + Game.End(State_PropsWin); + } + } else if(Game.PropsAlive == 0) { + Game.Broadcast("All hiders have disconnected, Seekers win"); + Game.End(State_SeekerWin); + } +} + +public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[] newValue) { + cvar.GetString(gamemode, sizeof(gamemode)); + bool shouldEnable = StrEqual(gamemode, "prophunt", false); + if(isEnabled == shouldEnable) return; + firstCheckDone = false; + if(shouldEnable) { + Game.Broadcast("Gamemode is starting"); + HookEvent("round_start", Event_RoundStart); + HookEvent("round_end", Event_RoundEnd); + HookEvent("player_death", Event_PlayerDeath); + } else if(!lateLoaded) { + UnhookEvent("round_start", Event_RoundStart); + UnhookEvent("round_end", Event_RoundEnd); + UnhookEvent("player_death", Event_PlayerDeath); + Game.Cleanup(); + } + isEnabled = shouldEnable; } public void OnMapStart() { for(int i = 0; i < MAX_VALID_MODELS; i++) { PrecacheModel(VALID_MODELS[i]); } + isStarting = false; + if(!isEnabled) return; + + char map[128]; + GetCurrentMap(map, sizeof(map)); + if(!StrEqual(g_currentMap, map)) { + firstCheckDone = false; + strcopy(g_currentSet, sizeof(g_currentSet), "default"); + ReloadMapDB(); + strcopy(g_currentMap, sizeof(g_currentMap), map); + } + + + if(lateLoaded) { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i)) { + Game.SetupPlayer(i); + } + } + InitGamemode(); + } + Game.State = State_Unknown; +} + +void InitGamemode() { + if(isStarting && Game.State != State_Unknown) { + Game.Warn("InitGamemode() called in an incorrect state (%d)", Game.State); + return; + } + SetupEntities(); + Game.DebugConsole("InitGamemode(): activating"); + ArrayList validPlayerIds = new ArrayList(); + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i)) { + if(IsFakeClient(i)) { + KickClient(i); + } else { + Game.SetupPlayer(i); + if(!IsPlayerAlive(i)) { + L4D_RespawnPlayer(i); + } + if(!hasBeenSeeker[i]) + validPlayerIds.Push(GetClientUserId(i)); + } + } + } + if(validPlayerIds.Length == 0) { + Game.Warn("Ignoring InitGamemode() with no valid survivors"); + return; + } + int numberOfSeekers = RoundToCeil(float(validPlayerIds.Length) / 3.0); + int timeout = 0; + while(numberOfSeekers > 0 && timeout < 2) { + int newSeeker = GetClientOfUserId(validPlayerIds.Get(GetURandomInt() % validPlayerIds.Length)); + if(newSeeker > 0) { + hasBeenSeeker[newSeeker] = true; + Game.SetSeeker(newSeeker, true); + Game.Broadcast("%N is a seeker", newSeeker); + numberOfSeekers--; + SetPlayerBlind(newSeeker, 255); + SetEntPropFloat(newSeeker, Prop_Send, "m_flLaggedMovementValue", 0.0); + } else { + timeout++; + } + } + delete validPlayerIds; + Game.TeleportAllToStart(); + Game.MapTime = BLIND_TIME; + Game.Tick = 0; + Game.State = State_Hiding; + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && !Game.IsSeeker(i)) { + PrintToChatAll("setting up non seeker %N", i); + Game.SetupProp(i); + } + } + CreateTimer(float(BLIND_TIME), Timer_StartGame); +} + +void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) { + int client = GetClientOfUserId(event.GetInt("userid")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); + if(client > 0 && Game.State == State_Active) { + if(Game.SeekersAlive == 0) { + Game.Broadcast("All seekers have perished. Hiders win!"); + Game.End(State_PropsWin); + } else if(Game.PropsAlive == 0) { + Game.Broadcast("Seekers win!"); + Game.End(State_SeekerWin); + } + } } void ResetPlayerData(int client) { @@ -71,33 +247,28 @@ public void OnMapEnd() { for(int i = 1; i <= MaxClients; i++) { ResetPlayerData(i); if(IsClientConnected(i) && IsClientInGame(i)) { - DispatchKeyValue(i, "rendercolor", WHITE); + Game.UnsetupPlayer(i); } } } -public void OnClientDisconnect(int client) { - ResetPlayerData(client); +void ClearInventory(int client) { + for(int i = 0; i <= 5; i++) { + int item = GetPlayerWeaponSlot(client, i); + if(item > 0) { + AcceptEntityInput(item, "Kill"); + } + } } public Action Command_Test(int client, int args) { - int prop = CreatePropInternal(VALID_MODELS[0]); - if(prop <= 0) { - ReplyToCommand(client, "Failed to spawn prop"); - return Plugin_Handled; - } - float pos[3]; - propData[client].prop = prop; - DispatchKeyValue(client, "rendercolor", TRANSPARENT); - // SetParent(prop, client); - // SetParentAttachment(prop, "eyes", true); - // TeleportEntity(prop, pos, EMPTY_ANG, NULL_VECTOR); - // SetParentAttachment(prop, "eyes", true); - SDKHook(client, SDKHook_SetTransmit, OnPlayerTransmit); - ReplyToCommand(client, "Game!"); + InitGamemode(); return Plugin_Handled; } +Action OnPropTransmit(int entity, int client) { + return propData[client].prop == entity ? Plugin_Stop : Plugin_Continue; +} Action OnPlayerTransmit(int entity, int client) { return entity == client ? Plugin_Continue : Plugin_Stop; @@ -116,12 +287,19 @@ int CreatePropInternal(const char[] model) { } public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) { + // if(!isEnabled) return Plugin_Continue; + int oldButtons = GetEntProp(client, Prop_Data, "m_nOldButtons"); + if(buttons & IN_RELOAD && !(oldButtons & IN_RELOAD)) { + propData[client].rotationLock = !propData[client].rotationLock; + PrintHintText(client, "Rotation lock now %s", propData[client].rotationLock ? "enabled" : "disabled"); + return Plugin_Continue; + } if(propData[client].prop > 0) { static float pos[3], ang[3]; GetClientAbsOrigin(client, pos); TeleportEntity(client, pos, NULL_VECTOR, NULL_VECTOR); if(propData[client].rotationLock) - TeleportEntity(propData[client].prop, NULL_VECTOR, angles, NULL_VECTOR); + TeleportEntity(propData[client].prop, pos, NULL_VECTOR, NULL_VECTOR); else { ang[0] = 0.0; ang[1] = angles[1]; @@ -133,19 +311,17 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3 } Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) { - /*if(attacker == currentSeeker) { - damage = 100.0; - ClearInventory(victim); - if(attacker > 0 && attacker <= MaxClients && IsFakeClient(victim)) { - PrintToChat(attacker, "That was a bot! -%.0f health", cvar_seekerFailDamageAmount.FloatValue); - SDKHooks_TakeDamage(attacker, 0, 0, cvar_seekerFailDamageAmount.FloatValue, DMG_DIRECT); + if(Game.IsSeeker(attacker)) { + if(victim <= MaxClients && victim > 0) { + damage = 10.0; + return Plugin_Changed; + } else { + SDKHooks_TakeDamage(attacker, 0, 0, 10.0, DMG_DIRECT); + damage = 0.0; + return Plugin_Handled; } - return Plugin_Changed; - } else if(attacker > 0 && attacker <= MaxClients) { - damage = 0.0; - return Plugin_Changed; } else { - return Plugin_Continue; - }*/ - return Plugin_Continue; + damage = 0.0; + return Plugin_Handled; + } }