mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 23:03:20 +00:00
Add ability to override attachment point, add hat presets
This commit is contained in:
parent
1c31a1ef46
commit
0f251e7d4f
3 changed files with 325 additions and 39 deletions
245
scripting/include/hats/hat_presets.sp
Normal file
245
scripting/include/hats/hat_presets.sp
Normal file
|
@ -0,0 +1,245 @@
|
|||
#define MODEL_LENGTH 64
|
||||
char SURVIVOR_NAMES[8][] = { "nick", "rochelle", "coach", "ellis", "bill", "zoey", "francis", "louis"};
|
||||
|
||||
enum struct PresetLocation {
|
||||
int survivorSet;
|
||||
float offset[3];
|
||||
float angles[3];
|
||||
}
|
||||
|
||||
enum struct HatPreset {
|
||||
float offset[3];
|
||||
float angles[3];
|
||||
char model[MODEL_LENGTH];
|
||||
char type[32];
|
||||
float size;
|
||||
|
||||
ArrayList locations;
|
||||
|
||||
int Spawn() {
|
||||
PrecacheModel(this.model);
|
||||
int entity = CreateEntityByName(this.type);
|
||||
DispatchKeyValue(entity, "model", this.model);
|
||||
if(HasEntProp(entity, Prop_Send, "m_flModelScale"))
|
||||
SetEntPropFloat(entity, Prop_Send, "m_flModelScale", this.size);
|
||||
if(!DispatchSpawn(entity)) {
|
||||
LogError("Could not spawn entity of type %s model \"%s\"", this.type, this.model);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
int Apply(int client) {
|
||||
int entity = this.Spawn();
|
||||
float offset[3], angles[3];
|
||||
EquipHat(client, entity, this.type, HAT_PRESET);
|
||||
this.GetLocation(client, offset, angles);
|
||||
hatData[client].offset = offset;
|
||||
hatData[client].angles = angles;
|
||||
CreateTimer(0.1, Timer_RemountSimple, GetClientUserId(client));
|
||||
return entity;
|
||||
}
|
||||
|
||||
void GetLocation(int client, float offset[3], float angles[3]) {
|
||||
if(this.locations != null) {
|
||||
int survivorSet = GetEntProp(client, Prop_Send, "m_survivorCharacter");
|
||||
if(survivorSet < 0 || survivorSet > 7) survivorSet = 0;
|
||||
PresetLocation location;
|
||||
for(int i = 0; i < this.locations.Length; i++) {
|
||||
this.locations.GetArray(i, location, sizeof(location));
|
||||
if(location.survivorSet == survivorSet) {
|
||||
offset = location.offset;
|
||||
angles = location.angles;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
offset = this.offset;
|
||||
angles = this.angles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Action Timer_RemountSimple(Handle h, int userid) {
|
||||
int client = GetClientOfUserId(userid);
|
||||
if(client > 0) {
|
||||
int entity = GetHat(client);
|
||||
if(entity > 0)
|
||||
TeleportEntity(entity, hatData[client].offset, hatData[client].angles, NULL_VECTOR);
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
void LoadPresets() {
|
||||
KeyValues kv = new KeyValues("Presets");
|
||||
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, sizeof(sPath), "data/hat_presets.cfg");
|
||||
|
||||
if(!FileExists(sPath) || !kv.ImportFromFile(sPath)) {
|
||||
PrintToServer("[Hats] Missing presets list");
|
||||
delete kv;
|
||||
}
|
||||
StringMap presets = new StringMap();
|
||||
|
||||
kv.GotoFirstSubKey();
|
||||
// char type[32];
|
||||
int count = 0;
|
||||
char name[32];
|
||||
do {
|
||||
kv.GetSectionName(name, sizeof(name));
|
||||
HatPreset preset;
|
||||
// kv.GetString("type", entCfg.type, sizeof(entCfg.type), "prop_physics");
|
||||
kv.GetString("model", preset.model, sizeof(preset.model), "");
|
||||
kv.GetString("type", preset.type, sizeof(preset.type), "prop_dynamic");
|
||||
preset.size = kv.GetFloat("size", 1.0);
|
||||
if(preset.model[0] == '\0') {
|
||||
PrintToServer("[Hats] Warn: Skipping %s, no model", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kv.JumpToKey("default")) {
|
||||
kv.GetVector("offset", preset.offset, NULL_VECTOR);
|
||||
kv.GetVector("angles", preset.angles, NULL_VECTOR);
|
||||
kv.GoBack();
|
||||
} else {
|
||||
PrintToServer("[Hats] Warn: Missing default for %s", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 7; i++) {
|
||||
if(kv.JumpToKey(SURVIVOR_NAMES[i])) {
|
||||
if(preset.locations == null) {
|
||||
preset.locations = new ArrayList(sizeof(PresetLocation));
|
||||
}
|
||||
PresetLocation location;
|
||||
location.survivorSet = i; // TODO: confirm with l4d/l4d2 modes?
|
||||
kv.GetVector("offset", location.offset, NULL_VECTOR);
|
||||
kv.GetVector("angles", location.angles, NULL_VECTOR);
|
||||
preset.locations.PushArray(location);
|
||||
kv.GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
presets.SetArray(name, preset, sizeof(preset));
|
||||
} while(kv.GotoNextKey(true));
|
||||
kv.GoBack();
|
||||
|
||||
PrintToServer("[Hats] Loaded %d presets", count);
|
||||
|
||||
|
||||
if(g_HatPresets != null) {
|
||||
HatPreset preset;
|
||||
StringMapSnapshot snapshot = g_HatPresets.Snapshot();
|
||||
for(int i = 0; i <= snapshot.Length; i++) {
|
||||
snapshot.GetKey(i, name, sizeof(name));
|
||||
g_HatPresets.GetArray(name, preset, sizeof(preset));
|
||||
if(preset.locations != null) {
|
||||
delete preset.locations;
|
||||
}
|
||||
}
|
||||
delete g_HatPresets;
|
||||
}
|
||||
g_HatPresets = presets;
|
||||
}
|
||||
|
||||
|
||||
Action Command_DoAHatPreset(int client, int args) {
|
||||
AdminId adminId = GetUserAdmin(client);
|
||||
if(cvar_sm_hats_enabled.IntValue == 1) {
|
||||
if(adminId == INVALID_ADMIN_ID) {
|
||||
PrintToChat(client, "[Hats] Hats are for admins only");
|
||||
return Plugin_Handled;
|
||||
} else if(!adminId.HasFlag(Admin_Cheats)) {
|
||||
PrintToChat(client, "[Hats] You do not have permission");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
} else if(cvar_sm_hats_enabled.IntValue == 0) {
|
||||
ReplyToCommand(client, "[Hats] Hats are disabled");
|
||||
return Plugin_Handled;
|
||||
} else if(GetClientTeam(client) != 2 && ~cvar_sm_hats_flags.IntValue & view_as<int>(HatConfig_InfectedHats)) {
|
||||
PrintToChat(client, "[Hats] Hats are only available for survivors.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
||||
int entity = GetHat(client);
|
||||
if(entity > 0) {
|
||||
if(args > 0) {
|
||||
char arg[64];
|
||||
GetCmdArg(1, arg, sizeof(arg));
|
||||
if(arg[0] == 'v') {
|
||||
ReplyToCommand(client, "\t{");
|
||||
GetEntPropString(entity, Prop_Data, "m_ModelName", arg, sizeof(arg));
|
||||
ReplyToCommand(client, "\t\t\"model\"\t\"%s\"", arg);
|
||||
ReplyToCommand(client, "\t\t\"default\"\n\t\t{");
|
||||
ReplyToCommand(client, "\t\t\t\"origin\"\t\"%f %f %f\"", hatData[client].offset[0], hatData[client].offset[1], hatData[client].offset[2]);
|
||||
ReplyToCommand(client, "\t\t\t\"angles\"\t\"%f %f %f\"", hatData[client].angles[0], hatData[client].angles[1], hatData[client].angles[2]);
|
||||
ReplyToCommand(client, "\t\t}");
|
||||
ReplyToCommand(client, "\t\t\"size\"\t\"%.1f\"", GetEntPropFloat(entity, Prop_Send, "m_flModelScale"));
|
||||
GetEntityClassname(entity, arg, sizeof(arg));
|
||||
ReplyToCommand(client, "\t\t\"type\"\t\"%.1f\"", arg);
|
||||
ReplyToCommand(client, "\t}");
|
||||
ReplyToCommand(client, "Flags: %d", hatData[client].flags);
|
||||
} else {
|
||||
ReplyToCommand(client, "Unknown option");
|
||||
}
|
||||
// ReplyToCommand(client, "CurOffset: %f %f %f", );
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(HasFlag(client, HAT_PRESET)) {
|
||||
ClearHat(client);
|
||||
RemoveEntity(entity);
|
||||
PrintToChat(client, "[Hats] Cleared your hat preset");
|
||||
hatPresetCookie.Set(client, "");
|
||||
ActivePreset[client][0] = '\0';
|
||||
|
||||
} else {
|
||||
PrintToChat(client, "[Hats] You already have a hat. Clear your hat to apply a preset.");
|
||||
}
|
||||
} else {
|
||||
Menu menu = new Menu(HatPresetHandler);
|
||||
menu.SetTitle("Choose a Hat", client);
|
||||
char id[32];
|
||||
StringMapSnapshot snapshot = g_HatPresets.Snapshot();
|
||||
if(snapshot.Length == 0) {
|
||||
PrintToChat(client, "[Hats] Seems there is no presets...");
|
||||
delete snapshot;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
for(int i = 0; i < snapshot.Length; i++) {
|
||||
snapshot.GetKey(i, id, sizeof(id));
|
||||
menu.AddItem(id, id);
|
||||
}
|
||||
menu.Display(client, 0);
|
||||
delete snapshot;
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
||||
int HatPresetHandler(Menu menu, MenuAction action, int param1, int param2) {
|
||||
if (action == MenuAction_Select) {
|
||||
static char info[32];
|
||||
menu.GetItem(param2, info, sizeof(info));
|
||||
HatPreset preset;
|
||||
if(g_HatPresets.GetArray(info, preset, sizeof(preset))) {
|
||||
strcopy(ActivePreset[param1], 32, info);
|
||||
hatPresetCookie.Set(param1, info);
|
||||
preset.Apply(param1);
|
||||
ReplyToCommand(param1, "[Hats] Hat preset \"%s\" applied, enjoy!", info);
|
||||
} else {
|
||||
ReplyToCommand(param1, "Unknown hat preset \"%s\"", info);
|
||||
}
|
||||
} else if (action == MenuAction_End)
|
||||
delete menu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RestoreActivePreset(int client) {
|
||||
if(ActivePreset[client][0] != '\0') {
|
||||
HatPreset preset;
|
||||
g_HatPresets.GetArray(ActivePreset[client], preset, sizeof(preset));
|
||||
preset.Apply(client);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,8 @@ enum hatFlags {
|
|||
HAT_POCKET = 1,
|
||||
HAT_REVERSED = 2,
|
||||
HAT_COMMANDABLE = 4,
|
||||
HAT_RAINBOW = 8
|
||||
HAT_RAINBOW = 8,
|
||||
HAT_PRESET = 16
|
||||
}
|
||||
enum struct HatData {
|
||||
int entity; // The entity REFERENCE
|
||||
|
@ -24,6 +25,7 @@ enum struct HatData {
|
|||
float rainbowColor[3];
|
||||
int rainbowTicks;
|
||||
bool rainbowReverse;
|
||||
char attachPoint[32];
|
||||
}
|
||||
enum hatFeatures {
|
||||
HatConfig_None = 0,
|
||||
|
@ -38,6 +40,8 @@ enum hatFeatures {
|
|||
}
|
||||
|
||||
HatData hatData[MAXPLAYERS+1];
|
||||
char ActivePreset[MAXPLAYERS+1][32];
|
||||
StringMap g_HatPresets;
|
||||
int lastHatRequestTime[MAXPLAYERS+1];
|
||||
|
||||
#define MAX_FORBIDDEN_CLASSNAMES 13
|
||||
|
@ -61,7 +65,7 @@ char FORBIDDEN_CLASSNAMES[MAX_FORBIDDEN_CLASSNAMES][] = {
|
|||
|
||||
#define MAX_FORBIDDEN_MODELS 1
|
||||
char FORBIDDEN_MODELS[MAX_FORBIDDEN_MODELS][] = {
|
||||
"models/props_vehicles/c130.mdl"
|
||||
"models/props_vehicles/c130.mdl",
|
||||
};
|
||||
|
||||
#define MAX_REVERSE_CLASSNAMES 2
|
||||
|
@ -70,7 +74,7 @@ static char REVERSE_CLASSNAMES[MAX_REVERSE_CLASSNAMES][] = {
|
|||
"func_movelinear"
|
||||
};
|
||||
|
||||
public Action Command_DoAHat(int client, int args) {
|
||||
Action Command_DoAHat(int client, int args) {
|
||||
static char cmdName[8];
|
||||
GetCmdArg(0, cmdName, sizeof(cmdName));
|
||||
|
||||
|
@ -107,8 +111,21 @@ public Action Command_DoAHat(int client, int args) {
|
|||
|
||||
int entity = GetHat(client);
|
||||
if(entity > 0) {
|
||||
if(HasFlag(client, HAT_PRESET)) {
|
||||
PrintToChat(client, "[Hats] Your hat is a preset, use /hatp to remove it.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
char arg[4];
|
||||
GetCmdArg(1, arg, sizeof(arg));
|
||||
if(arg[0] == 'e') {
|
||||
ReplyToCommand(client, "\t\t\"origin\"\t\"%f %f %f\"", hatData[client].offset[0], hatData[client].offset[1], hatData[client].offset[2]);
|
||||
ReplyToCommand(client, "\t\t\"angles\"\t\"%f %f %f\"", hatData[client].angles[0], hatData[client].angles[1], hatData[client].angles[2]);
|
||||
return Plugin_Handled;
|
||||
} else if(arg[0] == 'v') {
|
||||
ReplyToCommand(client, "Flags: %d", hatData[client].flags);
|
||||
// ReplyToCommand(client, "CurOffset: %f %f %f", );
|
||||
return Plugin_Handled;
|
||||
}
|
||||
// int orgEntity = entity;
|
||||
if(HasFlag(client, HAT_REVERSED)) {
|
||||
entity = client;
|
||||
|
@ -421,15 +438,6 @@ public Action Command_DoAHat(int client, int args) {
|
|||
|
||||
char classname[64];
|
||||
GetEntityClassname(entity, classname, sizeof(classname));
|
||||
// Check is pretty redudant as the traceray itself shouldn't grab it, but just in case:
|
||||
if(cvar_sm_hats_blacklist_enabled.BoolValue) {
|
||||
for(int i = 0; i < MAX_FORBIDDEN_CLASSNAMES; i++) {
|
||||
if(StrEqual(FORBIDDEN_CLASSNAMES[i], classname)) {
|
||||
PrintToChat(client, "[Hats] Entity (%s) is a blacklisted entity. Naughty.", classname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any class that should always be reversed
|
||||
if(~flags & view_as<int>(HAT_REVERSED)) {
|
||||
|
@ -446,6 +454,8 @@ public Action Command_DoAHat(int client, int args) {
|
|||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Handles consent that a person to be hatted by another player
|
||||
public int HatConsentHandler(Menu menu, MenuAction action, int target, int param2) {
|
||||
if (action == MenuAction_Select) {
|
||||
|
@ -483,7 +493,7 @@ void ClearHats() {
|
|||
}
|
||||
}
|
||||
void ClearHat(int i, bool restore = false) {
|
||||
|
||||
|
||||
int entity = EntRefToEntIndex(hatData[i].entity);
|
||||
int visibleEntity = EntRefToEntIndex(hatData[i].visibleEntity);
|
||||
int modifyEntity = HasFlag(i, HAT_REVERSED) ? i : entity;
|
||||
|
@ -561,6 +571,7 @@ bool CanTarget(int victim) {
|
|||
|
||||
bool IsHatAllowedInSaferoom(int client) {
|
||||
if(L4D_IsMissionFinalMap()) return true;
|
||||
if(HasFlag(client, HAT_PRESET)) return true;
|
||||
char name[32];
|
||||
GetEntityClassname(hatData[client].entity, name, sizeof(name));
|
||||
// Don't allow non-weapons in saferoom
|
||||
|
@ -617,7 +628,7 @@ bool HasFlag(int client, hatFlags flag) {
|
|||
return hatData[client].flags & view_as<int>(flag) != 0;
|
||||
}
|
||||
|
||||
void EquipHat(int client, int entity, const char[] classname = "", int flags = HAT_NONE) {
|
||||
void EquipHat(int client, int entity, const char[] classname = "", int flags = HAT_NONE, const char[] attachPoint = "eyes") {
|
||||
if(HasHat(client))
|
||||
ClearHat(client, true);
|
||||
|
||||
|
@ -633,12 +644,12 @@ void EquipHat(int client, int entity, const char[] classname = "", int flags = H
|
|||
hatData[client].collisionGroup = GetEntProp(modifyEntity, Prop_Send, "m_CollisionGroup");
|
||||
hatData[client].solidType = GetEntProp(modifyEntity, Prop_Send, "m_nSolidType");
|
||||
hatData[client].moveType = GetEntProp(modifyEntity, Prop_Send, "movetype");
|
||||
strcopy(hatData[client].attachPoint, 32, attachPoint);
|
||||
|
||||
if(client <= MaxClients) SDKHook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive);
|
||||
if(entity <= MaxClients) SDKHook(entity, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive);
|
||||
|
||||
if(modifyEntity <= MaxClients) {
|
||||
|
||||
AcceptEntityInput(modifyEntity, "DisableLedgeHang");
|
||||
} else if(cvar_sm_hats_flags.IntValue & view_as<int>(HatConfig_FakeHat)) {
|
||||
return;
|
||||
|
@ -672,6 +683,10 @@ void EquipHat(int client, int entity, const char[] classname = "", int flags = H
|
|||
hatData[client].offset[0] = hatData[client].offset[1] = hatData[client].offset[2] = 0.0;
|
||||
hatData[client].angles[0] = hatData[client].angles[1] = hatData[client].angles[2] = 0.0;
|
||||
|
||||
if(flags & view_as<int>(HAT_PRESET)) {
|
||||
hatData[client].flags |= view_as<int>(HAT_PRESET);
|
||||
}
|
||||
|
||||
if(modifyEntity <= MaxClients) {
|
||||
if(HasFlag(client, HAT_REVERSED)) {
|
||||
hatData[client].offset[2] += 7.2;
|
||||
|
@ -732,9 +747,9 @@ void EquipHat(int client, int entity, const char[] classname = "", int flags = H
|
|||
TeleportEntity(modifyEntity, hatData[client].offset, hatData[client].angles, NULL_VECTOR);
|
||||
SetParentAttachment(modifyEntity, "head", true);
|
||||
} else {
|
||||
SetParentAttachment(modifyEntity, "eyes", true);
|
||||
SetParentAttachment(modifyEntity, attachPoint, true);
|
||||
TeleportEntity(modifyEntity, hatData[client].offset, hatData[client].angles, NULL_VECTOR);
|
||||
SetParentAttachment(modifyEntity, "eyes", true);
|
||||
SetParentAttachment(modifyEntity, attachPoint, true);
|
||||
}
|
||||
|
||||
if(HasFlag(client, HAT_COMMANDABLE)) {
|
||||
|
@ -743,17 +758,17 @@ void EquipHat(int client, int entity, const char[] classname = "", int flags = H
|
|||
}
|
||||
} else {
|
||||
SetParent(entity, client);
|
||||
SetParentAttachment(modifyEntity, "eyes", true);
|
||||
SetParentAttachment(modifyEntity, attachPoint, true);
|
||||
TeleportEntity(modifyEntity, hatData[client].offset, hatData[client].angles, NULL_VECTOR);
|
||||
SetParentAttachment(modifyEntity, "eyes", true);
|
||||
SetParentAttachment(modifyEntity, attachPoint, true);
|
||||
}
|
||||
|
||||
if(visibleEntity > 0) {
|
||||
SetParent(visibleEntity, client);
|
||||
SetParentAttachment(visibleEntity, "eyes", true);
|
||||
SetParentAttachment(visibleEntity, attachPoint, true);
|
||||
hatData[client].offset[2] += 10.0;
|
||||
TeleportEntity(visibleEntity, hatData[client].offset, hatData[client].angles, NULL_VECTOR);
|
||||
SetParentAttachment(visibleEntity, "eyes", true);
|
||||
SetParentAttachment(visibleEntity, attachPoint, true);
|
||||
#if defined DEBUG_HAT_SHOW_FAKE
|
||||
L4D2_SetEntityGlow(visibleEntity, L4D2Glow_Constant, 0, 0, color2, false);
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@ static float EMPTY_ANG[3] = { 0.0, 0.0, 0.0 };
|
|||
#include <jutils>
|
||||
#include <gamemodes/ents>
|
||||
#include <smlib/effects>
|
||||
#include <multicolors>
|
||||
|
||||
|
||||
bool tempGod[MAXPLAYERS+1];
|
||||
|
@ -24,9 +25,9 @@ int g_iLaserIndex;
|
|||
|
||||
float cmdThrottle[MAXPLAYERS+1];
|
||||
static bool onLadder[MAXPLAYERS+1];
|
||||
float lastAng[MAXPLAYERS+1][3];
|
||||
|
||||
Cookie noHatVictimCookie;
|
||||
Cookie hatPresetCookie;
|
||||
|
||||
ConVar cvar_sm_hats_enabled;
|
||||
ConVar cvar_sm_hats_flags;
|
||||
|
@ -37,6 +38,7 @@ ConVar cvar_sm_hats_max_distance;
|
|||
|
||||
#include <hats/walls.sp>
|
||||
#include <hats/hats.sp>
|
||||
#include <hats/hat_presets.sp>
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
|
@ -63,6 +65,7 @@ public void OnPluginStart() {
|
|||
HookEvent("player_left_checkpoint", OnLeaveSaferoom);
|
||||
HookEvent("player_bot_replace", Event_PlayerToIdle);
|
||||
HookEvent("bot_player_replace", Event_PlayerOutOfIdle);
|
||||
HookEvent("player_spawn", Event_PlayerSpawn);
|
||||
|
||||
RegConsoleCmd("sm_hat", Command_DoAHat, "Hats");
|
||||
RegAdminCmd("sm_hatf", Command_DoAHat, ADMFLAG_ROOT, "Hats");
|
||||
|
@ -70,6 +73,7 @@ public void OnPluginStart() {
|
|||
RegAdminCmd("sm_walls", Command_ManageWalls, ADMFLAG_CHEATS);
|
||||
RegAdminCmd("sm_wall", Command_ManageWalls, ADMFLAG_CHEATS);
|
||||
RegAdminCmd("sm_edit", Command_ManageWalls, ADMFLAG_CHEATS);
|
||||
RegConsoleCmd("sm_hatp", Command_DoAHatPreset);
|
||||
|
||||
cvar_sm_hats_blacklist_enabled = CreateConVar("sm_hats_blacklist_enabled", "1", "Is the prop blacklist enabled", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
cvar_sm_hats_enabled = CreateConVar("sm_hats_enabled", "1.0", "Enable hats.\n0=OFF, 1=Admins Only, 2=Any", FCVAR_NONE, true, 0.0, true, 2.0);
|
||||
|
@ -81,6 +85,8 @@ public void OnPluginStart() {
|
|||
noHatVictimCookie = new Cookie("hats_no_target", "Disables other players from making you their hat", CookieAccess_Public);
|
||||
noHatVictimCookie.SetPrefabMenu(CookieMenu_OnOff_Int, "Disable player hats for self", OnLocalPlayerHatCookieSelect);
|
||||
|
||||
hatPresetCookie = new Cookie("hats_preset", "Sets the preset hat you spawn with", CookieAccess_Public);
|
||||
|
||||
int entity = -1;
|
||||
char targetName[32];
|
||||
while((entity = FindEntityByClassname(entity, "func_brush")) != INVALID_ENT_REFERENCE) {
|
||||
|
@ -95,14 +101,10 @@ public void OnPluginStart() {
|
|||
WallBuilder[i].Reset(true);
|
||||
hatData[i].yeetGroundTimer = null;
|
||||
}
|
||||
|
||||
LoadPresets();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -129,7 +131,7 @@ public void OnEnterSaferoom(Event event, const char[] name, bool dontBroadcast)
|
|||
if(client > 0 && client <= MaxClients && IsValidClient(client) && GetClientTeam(client) == 2) {
|
||||
inSaferoom[client] = true;
|
||||
if(cvar_sm_hats_flags.IntValue & view_as<int>(HatConfig_NoSaferoomHats)) {
|
||||
if(HasHat(client)) {
|
||||
if(HasHat(client) && !HasFlag(client, HAT_PRESET)) {
|
||||
if(!IsHatAllowedInSaferoom(client)) {
|
||||
PrintToChat(client, "[Hats] Hat is not allowed in the saferoom and has been returned");
|
||||
ClearHat(client, true);
|
||||
|
@ -245,14 +247,14 @@ void Frame_Remount(int i) {
|
|||
int entity = GetHat(i);
|
||||
if(entity == -1) return;
|
||||
SetParent(entity, i);
|
||||
SetParentAttachment(entity, "eyes", false);
|
||||
SetParentAttachment(entity, "eyes", true);
|
||||
SetParentAttachment(entity, hatData[i].attachPoint, false);
|
||||
SetParentAttachment(entity, hatData[i].attachPoint, true);
|
||||
|
||||
int visibleEntity = EntRefToEntIndex(hatData[i].visibleEntity);
|
||||
if(visibleEntity > 0) {
|
||||
SetParent(visibleEntity, i);
|
||||
SetParentAttachment(visibleEntity, "eyes", false);
|
||||
SetParentAttachment(visibleEntity, "eyes", true);
|
||||
SetParentAttachment(visibleEntity, hatData[i].attachPoint, false);
|
||||
SetParentAttachment(visibleEntity, hatData[i].attachPoint, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,7 +265,9 @@ Action Timer_PropSleep(Handle h, DataPack pack) {
|
|||
int ref = pack.ReadCell();
|
||||
int client = GetClientOfUserId(pack.ReadCell());
|
||||
if(client > 0 && IsValidEntity(ref)) {
|
||||
CheckKill(ref, client);
|
||||
// CheckKill(ref, client);
|
||||
float vel[3];
|
||||
TeleportEntity(ref, NULL_VECTOR, NULL_VECTOR, vel);
|
||||
PrintToServer("Hats: Yeet delete timeout");
|
||||
if(hatData[client].yeetGroundTimer != null) {
|
||||
delete hatData[client].yeetGroundTimer;
|
||||
|
@ -280,7 +284,11 @@ Action Timer_GroundKill(Handle h, DataPack pack) {
|
|||
GetEntPropVector(ref, Prop_Data, "m_vecVelocity", vel);
|
||||
if(FloatAbs(vel[2]) < 0.2 || IsNearGround(ref)) {
|
||||
PrintToServer("Hats: Yeet ground check %b %b", FloatAbs(vel[2]) < 0.2, IsNearGround(ref));
|
||||
CheckKill(ref, client);
|
||||
vel[0] = 0.0;
|
||||
vel[1] = 0.0;
|
||||
vel[2] = 0.0;
|
||||
TeleportEntity(ref, NULL_VECTOR, NULL_VECTOR, vel);
|
||||
// CheckKill(ref, client);
|
||||
hatData[client].yeetGroundTimer = null;
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
@ -552,7 +560,6 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
|
|||
ClientCommand(client, "sm_hat");
|
||||
}
|
||||
cmdThrottle[client] = tick;
|
||||
lastAng[client] = angles;
|
||||
hatData[client].angles = angles;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
@ -694,6 +701,17 @@ public Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float
|
|||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0 && !HasHat(client) && !IsFakeClient(client)) {
|
||||
hatPresetCookie.Get(client, ActivePreset[client], 32);
|
||||
if(ActivePreset[client][0] != '\0') {
|
||||
RestoreActivePreset(client);
|
||||
ReplyToCommand(client, "[Hats] Applied your hat preset! Clear it with /hatp");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client) {
|
||||
tempGod[client] = false;
|
||||
WallBuilder[client].Reset();
|
||||
|
@ -722,9 +740,9 @@ public void OnMapStart() {
|
|||
tempGod[i] = false;
|
||||
}
|
||||
NavAreas = GetSpawnLocations();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void OnMapEnd() {
|
||||
delete NavAreas;
|
||||
for(int i = 1; i <= createdWalls.Length; i++) {
|
||||
|
@ -788,15 +806,19 @@ bool Filter_ValidHats(int entity, int mask, int data) {
|
|||
int client = GetRealClient(data);
|
||||
return CanTarget(client); // Don't target if player targetting off
|
||||
}
|
||||
return CheckBlacklist(entity);
|
||||
}
|
||||
|
||||
bool CheckBlacklist(int entity) {
|
||||
if(cvar_sm_hats_blacklist_enabled.BoolValue) {
|
||||
static char buffer[32];
|
||||
static char buffer[64];
|
||||
GetEntityClassname(entity, buffer, sizeof(buffer));
|
||||
for(int i = 0; i < MAX_FORBIDDEN_CLASSNAMES; i++) {
|
||||
if(StrEqual(FORBIDDEN_CLASSNAMES[i], buffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(StrContains(buffer, "prop_") != -1) {
|
||||
if(StrContains(buffer, "prop_") > -1) {
|
||||
GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, sizeof(buffer));
|
||||
for(int i = 0; i < MAX_FORBIDDEN_MODELS; i++) {
|
||||
if(StrEqual(FORBIDDEN_MODELS[i], buffer)) {
|
||||
|
@ -804,6 +826,10 @@ bool Filter_ValidHats(int entity, int mask, int data) {
|
|||
}
|
||||
}
|
||||
}
|
||||
GetEntPropString(entity, Prop_Data, "m_iName", buffer, sizeof(buffer));
|
||||
if(StrEqual(buffer, "l4d2_randomizer")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue