mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-06 21:53:21 +00:00
h&s stuff
This commit is contained in:
parent
3b035750f1
commit
956df81ba8
1 changed files with 397 additions and 0 deletions
397
scripting/l4d2_hideandseek.sp
Normal file
397
scripting/l4d2_hideandseek.sp
Normal file
|
@ -0,0 +1,397 @@
|
||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
//#define DEBUG
|
||||||
|
|
||||||
|
#define PLUGIN_VERSION "1.0"
|
||||||
|
// #define FORCE_ENABLED 1
|
||||||
|
//TODO: Preload models
|
||||||
|
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <left4dhooks>
|
||||||
|
//#include <sdkhooks>
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "L4D2 Hide & Seek",
|
||||||
|
author = "jackzmc",
|
||||||
|
description = "",
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PROP_DUMPSTER "models/props_junk/dumpster.mdl"
|
||||||
|
#define PROP_DOCK "models/props_swamp/boardwalk_384.mdl"
|
||||||
|
#define PROP_SHELF "models/props/cs_office/shelves_metal.mdl"
|
||||||
|
#define PROP_SIGN "models/props_swamp/river_sign01.mdl"
|
||||||
|
|
||||||
|
static char gamemode[32];
|
||||||
|
static bool isEnabled, lateLoaded;
|
||||||
|
|
||||||
|
static bool isPendingPlay[MAXPLAYERS+1];
|
||||||
|
static bool isNavBlockersEnabled = true;
|
||||||
|
static bool hasFiredRoundStart = false;
|
||||||
|
|
||||||
|
static const float C8M3_SEWERS_A[3] = { 13265.965820, 8547.057617, -250.7 };
|
||||||
|
static const float C8M3_SEWERS_A_PROP[3] = { 13265.965820, 8497.057617, -240.7 };
|
||||||
|
static const float C8M3_SEWERS_B[3] = { 14130.535156, 8026.46386, -254.7 };
|
||||||
|
|
||||||
|
static const float C3M4_PLANTATION_A[3] = { 2122.044189, -588.200195, 470.435608};
|
||||||
|
static const float C3M4_PLANTATION_A2[3] = {2000.802612, -426.686829, 402.803497};
|
||||||
|
|
||||||
|
static const float C1M3_MALL_A[3] = { 1714.133179, -1023.777527, 347.735168};
|
||||||
|
static const float C1M3_MALL_A_PROP[3] = { 1581.286865, -1029.394043, 280.079254};
|
||||||
|
|
||||||
|
|
||||||
|
static const float SCALE_FLAT_MEDIUM[3] = { 50.0, 50.00, 1.0 };
|
||||||
|
static const float SCALE_FLAT_LARGE[3] = { 150.0, 150.00, 1.0 };
|
||||||
|
static const float SCALE_TALL_MEDIUM[3] = { 25.0, 25.00, 100.0 };
|
||||||
|
|
||||||
|
static const float ROT_H_90[3] = { 0.0, 90.0, 0.0 };
|
||||||
|
static const float ROT_V_90_H_90[3] = { 90.0, 90.0, 0.0 };
|
||||||
|
static const float ROT_V_90[3] = { 90.0, 00.0, 0.0 };
|
||||||
|
static const float DEFAULT_SCALE[3] = { 5.0, 5.0, 5.0 };
|
||||||
|
|
||||||
|
static ArrayList entities;
|
||||||
|
static char currentMapConfig[32];
|
||||||
|
|
||||||
|
static KeyValues kv;
|
||||||
|
static StringMap mapConfigs;
|
||||||
|
enum struct EntityConfig {
|
||||||
|
float origin[3];
|
||||||
|
float rotation[3];
|
||||||
|
char type[16];
|
||||||
|
char model[64];
|
||||||
|
float scale[3];
|
||||||
|
|
||||||
|
bool toggleable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) {
|
||||||
|
lateLoaded = late;
|
||||||
|
return APLRes_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginStart() {
|
||||||
|
EngineVersion g_Game = GetEngineVersion();
|
||||||
|
if(g_Game != Engine_Left4Dead2) {
|
||||||
|
SetFailState("This plugin is for L4D2 only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = new KeyValues("EntityConfig");
|
||||||
|
|
||||||
|
char sPath[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sPath, sizeof(sPath), "data/hideandseek.cfg");
|
||||||
|
|
||||||
|
if(!FileExists(sPath) || !kv.ImportFromFile(sPath)) {
|
||||||
|
delete kv;
|
||||||
|
SetFailState("Could not load entity config from data/hideandseek.cfg");
|
||||||
|
}
|
||||||
|
|
||||||
|
mapConfigs = new StringMap();
|
||||||
|
|
||||||
|
ConVar hGamemode = FindConVar("mp_gamemode");
|
||||||
|
hGamemode.GetString(gamemode, sizeof(gamemode));
|
||||||
|
hGamemode.AddChangeHook(Event_GamemodeChange);
|
||||||
|
Event_GamemodeChange(hGamemode, gamemode, gamemode);
|
||||||
|
|
||||||
|
lateLoaded = false;
|
||||||
|
|
||||||
|
RegConsoleCmd("sm_joingame", Command_Join, "Joins or joins someone else");
|
||||||
|
RegAdminCmd("sm_hs_toggle", Command_ToggleBlockers, ADMFLAG_KICK, "Toggle nav blockers");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList LoadConfigForMap(const char[] map) {
|
||||||
|
if (kv.JumpToKey(map)) {
|
||||||
|
strcopy(currentMapConfig, sizeof(currentMapConfig), map);
|
||||||
|
ArrayList configs = new ArrayList(sizeof(EntityConfig));
|
||||||
|
if(kv.JumpToKey("blockers")) {
|
||||||
|
kv.GotoFirstSubKey();
|
||||||
|
do {
|
||||||
|
EntityConfig config;
|
||||||
|
kv.GetVector("origin", config.origin, NULL_VECTOR);
|
||||||
|
kv.GetVector("rotation", config.rotation, NULL_VECTOR);
|
||||||
|
kv.GetString("type", config.type, sizeof(config.type), "env_physics_blocker");
|
||||||
|
kv.GetString("model", config.model, sizeof(config.model), "");
|
||||||
|
kv.GetVector("scale", config.scale, DEFAULT_SCALE);
|
||||||
|
|
||||||
|
config.toggleable = true;
|
||||||
|
|
||||||
|
configs.PushArray(config);
|
||||||
|
} while (kv.GotoNextKey());
|
||||||
|
}
|
||||||
|
if(kv.JumpToKey("props")) {
|
||||||
|
do {
|
||||||
|
EntityConfig config;
|
||||||
|
kv.GetVector("origin", config.origin, NULL_VECTOR);
|
||||||
|
kv.GetVector("rotation", config.rotation, NULL_VECTOR);
|
||||||
|
kv.GetString("type", config.type, sizeof(config.type), "env_physics_blocker");
|
||||||
|
kv.GetString("model", config.model, sizeof(config.model), "");
|
||||||
|
kv.GetVector("scale", config.scale, DEFAULT_SCALE);
|
||||||
|
|
||||||
|
configs.PushArray(config);
|
||||||
|
} while (kv.GotoNextKey());
|
||||||
|
}
|
||||||
|
kv.GoBack();
|
||||||
|
// Store ArrayList<EntityConfig> handle
|
||||||
|
mapConfigs.SetValue(map, configs);
|
||||||
|
return configs;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_ToggleBlockers(int client, int args) {
|
||||||
|
static char targetname[32];
|
||||||
|
int entity = INVALID_ENT_REFERENCE;
|
||||||
|
while ((entity = FindEntityByClassname(entity, "env_physics_blocker")) != INVALID_ENT_REFERENCE) {
|
||||||
|
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
|
||||||
|
if(StrEqual(targetname, "hsblocker")) {
|
||||||
|
if(isNavBlockersEnabled)
|
||||||
|
AcceptEntityInput(entity, "Disable");
|
||||||
|
else
|
||||||
|
AcceptEntityInput(entity, "Enable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isNavBlockersEnabled) {
|
||||||
|
ReplyToCommand(client, "Disabled all custom nav blockers");
|
||||||
|
} else {
|
||||||
|
ReplyToCommand(client, "Enabled all custom nav blockers");
|
||||||
|
}
|
||||||
|
isNavBlockersEnabled = !isNavBlockersEnabled;
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_Join(int client, int args) {
|
||||||
|
static float tpLoc[3];
|
||||||
|
if(args == 1) {
|
||||||
|
GetClientAbsOrigin(client, tpLoc);
|
||||||
|
static char arg1[32];
|
||||||
|
GetCmdArg(1, arg1, sizeof(arg1));
|
||||||
|
char target_name[MAX_TARGET_LENGTH];
|
||||||
|
int target_list[MAXPLAYERS], target_count;
|
||||||
|
bool tn_is_ml;
|
||||||
|
if ((target_count = ProcessTargetString(
|
||||||
|
arg1,
|
||||||
|
client,
|
||||||
|
target_list,
|
||||||
|
MAXPLAYERS,
|
||||||
|
COMMAND_FILTER_ALIVE,
|
||||||
|
target_name,
|
||||||
|
sizeof(target_name),
|
||||||
|
tn_is_ml)) <= 0)
|
||||||
|
{
|
||||||
|
/* This function replies to the admin with a failure message */
|
||||||
|
ReplyToTargetError(client, target_count);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < target_count; i++) {
|
||||||
|
int target = target_list[i];
|
||||||
|
if(GetClientTeam(target) != 2) {
|
||||||
|
ChangeClientTeam(target, 2);
|
||||||
|
L4D_RespawnPlayer(target);
|
||||||
|
TeleportEntity(target, tpLoc, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
isPendingPlay[client] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReplyToCommand(client, "Joined %s", target_name);
|
||||||
|
} else {
|
||||||
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
|
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) {
|
||||||
|
GetClientAbsOrigin(i, tpLoc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isPendingPlay[client] = false;
|
||||||
|
ChangeClientTeam(client, 2);
|
||||||
|
L4D_RespawnPlayer(client);
|
||||||
|
TeleportEntity(client, tpLoc, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart() {
|
||||||
|
static char map[16];
|
||||||
|
GetCurrentMap(map, sizeof(map));
|
||||||
|
|
||||||
|
ArrayList configs;
|
||||||
|
if(!mapConfigs.GetValue(map, configs)) {
|
||||||
|
configs = LoadConfigForMap(map);
|
||||||
|
PrintToServer("H&S: Fetching config for map %s", map);
|
||||||
|
}
|
||||||
|
if(isEnabled) {
|
||||||
|
for(int i = 0; i < configs.Length; i++) {
|
||||||
|
EntityConfig config;
|
||||||
|
configs.GetArray(i, config);
|
||||||
|
if(config.model[0] != '\0')
|
||||||
|
PrecacheModel(config.model);
|
||||||
|
bool isEnabled = true;
|
||||||
|
if(config.toggleable && !isNavBlockersEnabled) {
|
||||||
|
isEnabled = false;
|
||||||
|
}
|
||||||
|
if(StrEqual(config.type, "env_physics_blocker")) {
|
||||||
|
CreateEnvBlockerBoxScaled(config.origin, config.scale, isEnabled);
|
||||||
|
} else {
|
||||||
|
CreateProp(config.model, config.origin, config.rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// if(StrEqual(map, "c8m3_sewers")) {
|
||||||
|
// if(isNavBlockersEnabled) {
|
||||||
|
// CreateEnvBlockerBox(C8M3_SEWERS_A, isNavBlockersEnabled);
|
||||||
|
// CreateEnvBlockerBox(C8M3_SEWERS_B, isNavBlockersEnabled);
|
||||||
|
// CreateProp(PROP_SHELF, C8M3_SEWERS_A_PROP, ROT_V_90_H_90);
|
||||||
|
// CreateProp(PROP_SIGN, C8M3_SEWERS_B, ROT_V_90);
|
||||||
|
// }
|
||||||
|
// } else if(StrEqual(map, "c3m4_plantation")) {
|
||||||
|
// if(isNavBlockersEnabled) {
|
||||||
|
// CreateEnvBlockerBoxScaled(C3M4_PLANTATION_A2, SCALE_FLAT_LARGE);
|
||||||
|
// CreateProp(PROP_DOCK, C3M4_PLANTATION_A2, ROT_H_90);
|
||||||
|
// }
|
||||||
|
// // CreateEnvBlockerBoxScaled(C3M4_PLANTATION_A, SCALE_FLAT_LARGE);
|
||||||
|
// } else if(StrEqual(map, "c1m3_mall")) {
|
||||||
|
// CreateProp(PROP_DUMPSTER, C1M3_MALL_A_PROP, ROT_H_90);
|
||||||
|
// if(isNavBlockersEnabled) {
|
||||||
|
// CreateEnvBlockerBoxScaled(C1M3_MALL_A, SCALE_TALL_MEDIUM);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stock int CreateEnvBlockerBox(const float pos[3], bool enabled = true) {
|
||||||
|
int entity = CreateEntityByName("env_physics_blocker");
|
||||||
|
DispatchKeyValue(entity, "targetname", "hsblocker");
|
||||||
|
DispatchKeyValue(entity, "initialstate", "1");
|
||||||
|
DispatchKeyValue(entity, "BlockType", "0");
|
||||||
|
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
DispatchSpawn(entity);
|
||||||
|
if(enabled)
|
||||||
|
AcceptEntityInput(entity, "Enable");
|
||||||
|
PrintToServer("spawn blocker %f %f %f", pos[0], pos[1], pos[2]);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock int CreateEnvBlockerBoxScaled(const float pos[3], const float scale[3], bool enabled = true) {
|
||||||
|
int entity = CreateEntityByName("env_physics_blocker");
|
||||||
|
DispatchKeyValue(entity, "targetname", "hsblocker");
|
||||||
|
DispatchKeyValue(entity, "initialstate", "1");
|
||||||
|
DispatchKeyValue(entity, "BlockType", "0");
|
||||||
|
static float mins[3];
|
||||||
|
mins = scale;
|
||||||
|
NegateVector(mins);
|
||||||
|
DispatchKeyValueVector(entity, "boxmins", mins);
|
||||||
|
DispatchKeyValueVector(entity, "boxmaxs", scale);
|
||||||
|
DispatchKeyValueVector(entity, "mins", mins);
|
||||||
|
DispatchKeyValueVector(entity, "maxs", scale);
|
||||||
|
|
||||||
|
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
DispatchSpawn(entity);
|
||||||
|
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
|
||||||
|
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
|
||||||
|
if(enabled)
|
||||||
|
AcceptEntityInput(entity, "Enable");
|
||||||
|
PrintToServer("spawn blocker scaled %f %f %f scale [%f %f %f]", pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock int CreateProp(const char[] model, const float pos[3], const float ang[3]) {
|
||||||
|
int entity = CreateEntityByName("prop_dynamic");
|
||||||
|
DispatchKeyValue(entity, "model", model);
|
||||||
|
DispatchKeyValue(entity, "solid", "6");
|
||||||
|
DispatchKeyValue(entity, "targetname", "hsprop");
|
||||||
|
DispatchKeyValue(entity, "disableshadows", "1");
|
||||||
|
TeleportEntity(entity, pos, ang, NULL_VECTOR);
|
||||||
|
DispatchSpawn(entity);
|
||||||
|
PrintToServer("spawn prop %f %f %f", pos[0], pos[1], pos[2]);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[] newValue) {
|
||||||
|
cvar.GetString(gamemode, sizeof(gamemode));
|
||||||
|
#if defined FORCE_ENABLED
|
||||||
|
isEnabled = true;
|
||||||
|
#else
|
||||||
|
isEnabled = StrEqual(gamemode, "hideandseek");
|
||||||
|
#endif
|
||||||
|
if(isEnabled) {
|
||||||
|
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
||||||
|
HookEvent("round_end", Event_RoundEnd);
|
||||||
|
HookEvent("round_start", Event_RoundStart);
|
||||||
|
} else if(!lateLoaded) {
|
||||||
|
UnhookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
||||||
|
UnhookEvent("round_end", Event_RoundEnd);
|
||||||
|
UnhookEvent("round_start", Event_RoundStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Event_PlayerFirstSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||||
|
if(client && GetClientTeam(client) != 2 && !isPendingPlay[client]) {
|
||||||
|
PrintToChat(client, "You will be put in game next round.");
|
||||||
|
isPendingPlay[client] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
CreateTimer(10.0, Timer_CheckItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
static float tpLoc[3];
|
||||||
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
|
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) {
|
||||||
|
GetClientAbsOrigin(i, tpLoc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
|
if(isPendingPlay[i]) {
|
||||||
|
isPendingPlay[i] = false;
|
||||||
|
ChangeClientTeam(i, 2);
|
||||||
|
L4D_RespawnPlayer(i);
|
||||||
|
TeleportEntity(i, tpLoc, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
public Action Timer_CheckItems(Handle h) {
|
||||||
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
|
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) {
|
||||||
|
// Check if has no melee:
|
||||||
|
if(GetPlayerWeaponSlot(i, 1) == -1) {
|
||||||
|
GiveClientWeapon(i, "knife", false);
|
||||||
|
}
|
||||||
|
int item = GetPlayerWeaponSlot(i, 0);
|
||||||
|
if(item != -1) AcceptEntityInput(item, "Kill");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintToServer("H&S: Pressing buttons");
|
||||||
|
int entity = INVALID_ENT_REFERENCE;
|
||||||
|
while ((entity = FindEntityByClassname(entity, "func_button")) != INVALID_ENT_REFERENCE) {
|
||||||
|
AcceptEntityInput(entity, "Press");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool GiveClientWeapon(int client, const char[] wpnName, bool lasers) {
|
||||||
|
char sTemp[64];
|
||||||
|
float pos[3];
|
||||||
|
GetClientAbsOrigin(client, pos);
|
||||||
|
Format(sTemp, sizeof(sTemp), "weapon_%s", wpnName);
|
||||||
|
|
||||||
|
int entity = CreateEntityByName(sTemp);
|
||||||
|
if( entity != -1 ) {
|
||||||
|
DispatchSpawn(entity);
|
||||||
|
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
|
||||||
|
if(lasers) SetEntProp(entity, Prop_Send, "m_upgradeBitVec", 4);
|
||||||
|
|
||||||
|
EquipPlayerWeapon(client, entity);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue