projects-jenz/Plugins/hexprops/scripting/hexprops.sp
2019-03-02 15:18:51 +01:00

1199 lines
27 KiB
SourcePawn

#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <hexprops>
#include <hexstocks>
#define PLUGIN_AUTHOR "Hexah"
#define PLUGIN_VERSION "<TAG>"
#pragma semicolon 1
#pragma newdecls required
//Handle
Handle fOnPressProp;
//Int
int iEntHP[MAX_ENTITIES];
//Boolean
bool bMoveProp[MAXPLAYERS+1];
bool bPhysicProp[MAXPLAYERS+1];
//String
char sPropPath[PLATFORM_MAX_PATH];
//Kv
KeyValues PropKv;
//Arrays
ArrayList PropsArray;
#include HexProps/model_moving.sp
//Plugin Info
public Plugin myinfo =
{
name = "HexProps, jenz edit for fixing (or causing) bugs",
author = PLUGIN_AUTHOR,
description = "Place, edit & save props!",
version = PLUGIN_VERSION,
url = "github.com/Hexer10/HexProps"
};
//Startup
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
RegPluginLibrary("hexprops");
CreateNative("IsEntProp", Native_IsEntProp);
fOnPressProp = CreateGlobalForward("OnPlayerPressProp", ET_Ignore, Param_Cell, Param_Cell);
}
public void OnPluginStart()
{
PropsArray = new ArrayList();
RegAdminCmd("sm_props", Cmd_Props, ADMFLAG_GENERIC);
HookEvent("round_poststart", Event_RoundPostStart);
}
public void OnMapStart()
{
PreparePropKv();
}
public void OnMapEnd()
{
delete PropKv;
}
void PreparePropKv()
{
char sMap[64];
GetCurrentMap(sMap, sizeof(sMap));
BuildPath(Path_SM, sPropPath, sizeof(sPropPath), "configs/props/%s.props.txt", sMap); //Get the right "map" file
PropKv = new KeyValues("Props");
if (!FileExists(sPropPath)) //Try to create kv file.
if (!PropKv.ExportToFile(sPropPath))
SetFailState(" - Props - Unable to (Kv)File: %s", sPropPath);
if (!PropKv.ImportFromFile(sPropPath)) //Import the kv file
SetFailState("- Props - Unable to import: %s", sPropPath);
}
//Commands
public Action Cmd_Props(int client, int args)
{
CreateMainMenu(client).Display(client, MENU_TIME_FOREVER);
return Plugin_Handled;
}
//Events
public void Event_RoundPostStart(Event event, const char[] name, bool dontBroadcast)
{
PropsArray.Clear();
LoadProps();
}
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])
{
Moving_OnPlayerRunCmd(client, buttons);
if (buttons & IN_USE)
{
int iEnt = GetAimEnt(client);
if (FindInArray(iEnt) == -1)
{
Call_StartForward(fOnPressProp);
Call_PushCell(client);
Call_PushCell(iEnt);
Call_Finish();
}
}
}
//Menu
Menu CreateMainMenu(int client)
{
//Prepare MainMenu
Menu MainMenu = new Menu(Handler_Main);
MainMenu.SetTitle("Props");
char sMoveDisplay[32];
char sPhysicDisplay[32];
Format(sMoveDisplay, sizeof(sMoveDisplay), "Move: %s", bMoveProp[client]? "On" : "Off");
Format(sPhysicDisplay, sizeof(sPhysicDisplay), "Physic: %s", bPhysicProp[client]? "On" : "Off");
MainMenu.AddItem("Place", "Place New Prop");
MainMenu.AddItem("Remove", "Remove Props");
MainMenu.AddItem("Edit", "Edit Props");
MainMenu.AddItem("Safe", "Save Props");
MainMenu.AddItem("Move", sMoveDisplay);
MainMenu.AddItem("Physic", sPhysicDisplay);
MainMenu.AddItem("Reset", "Reset Props");
MainMenu.AddItem("DeleteAll", "Delete All Props");
return MainMenu;
}
Menu CreatePropMenu()
{
//Prepare PropMenu
char sPath[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/props/props_list.txt"); //Get prop_list file
KeyValues kv = new KeyValues("Props");
if (!kv.ImportFromFile(sPath))
SetFailState("- Props - Unable to import: %s", sPath);
if (!kv.GotoFirstSubKey())
SetFailState(" - Props - Unable to read: %s", sPath);
Menu PropMenu = new Menu(Handler_Props);
PropMenu.SetTitle("Props");
do //Loop all kv keys
{
char sName[64];
char sModel[PLATFORM_MAX_PATH];
kv.GetSectionName(sName, sizeof(sName));
kv.GetString("model", sModel, sizeof(sModel));
PropMenu.AddItem(sModel, sName);
}
while (kv.GotoNextKey());
delete kv;
PropMenu.ExitBackButton = true;
return PropMenu;
}
Menu CreateEditMenu()
{
//Prepare EditMenu
Menu EditMenu = new Menu(Handler_Edit);
EditMenu.SetTitle("Edit");
EditMenu.AddItem("Alpha", "Set Transparency");
EditMenu.AddItem("Color", "Set Color");
EditMenu.AddItem("Life", "Set LifePoints");
EditMenu.AddItem("Solid", "Set Consistency");
EditMenu.AddItem("Size", "Set Size (Not working on all props)");
EditMenu.AddItem("Physic", "Make Physic");
EditMenu.AddItem("Rotate", "Rotate props");
EditMenu.ExitBackButton = true;
return EditMenu;
}
Menu CreateDeleteAllMenu()
{
Menu DeleteAllMenu = new Menu(Handler_DeleteAll);
DeleteAllMenu.SetTitle("Are you sure?");
DeleteAllMenu.AddItem("", "If you want to go back", ITEMDRAW_DISABLED);
DeleteAllMenu.AddItem("", "after you deleted the props", ITEMDRAW_DISABLED);
DeleteAllMenu.AddItem("", "press Reset Props and do NOT save the props!", ITEMDRAW_DISABLED);
DeleteAllMenu.AddItem("0", "NO");
DeleteAllMenu.AddItem("1", "YES");
DeleteAllMenu.ExitBackButton = true;
return DeleteAllMenu;
}
Menu CreateColorMenu()
{
//Prepare ColorMenu
Menu ColorMenu = new Menu(Handler_Color);
ColorMenu.SetTitle("Color");
ColorMenu.AddItem("Default", "Default");
ColorMenu.AddItem("Red", "Red");
ColorMenu.AddItem("Blue", "Blue");
ColorMenu.AddItem("Green", "Green");
ColorMenu.AddItem("Yellow", "Yellow");
ColorMenu.AddItem("Pink", "Pink");
ColorMenu.AddItem("Black", "Black");
ColorMenu.ExitBackButton = true;
return ColorMenu;
}
Menu CreateAlphaMenu()
{
//Prepare AlphaMenu
Menu AlphaMenu = new Menu(Handler_Alpha);
AlphaMenu.SetTitle("Trasparency");
AlphaMenu.AddItem("255", "Full Visible");
AlphaMenu.AddItem("191", "75% Visible");
AlphaMenu.AddItem("127", "Half Visible");
AlphaMenu.AddItem("63", "25% Visible");
AlphaMenu.AddItem("0", "Invisible");
AlphaMenu.ExitBackButton = true;
return AlphaMenu;
}
Menu CreateLifeMenu()
{
//Prepare LifeMenu
Menu LifeMenu = new Menu(Handler_Life);
LifeMenu.SetTitle("LifePoints");
LifeMenu.AddItem("0", "Unbreakable");
LifeMenu.AddItem("50", "50HP");
LifeMenu.AddItem("100", "100HP");
LifeMenu.AddItem("200", "200HP");
LifeMenu.ExitBackButton = true;
return LifeMenu;
}
Menu CreateSolidMenu()
{
Menu SolidMenu = new Menu(Handler_Solid);
SolidMenu.SetTitle("Consistency");
SolidMenu.AddItem("6", "Solid");
SolidMenu.AddItem("1", "Un-Solid");
SolidMenu.ExitBackButton = true;
return SolidMenu;
}
Menu CreateSizeMenu()
{
Menu SizeMenu = new Menu(Handler_Size);
SizeMenu.SetTitle("Size");
SizeMenu.AddItem("1.0", "Default");
SizeMenu.AddItem("2.0", "Double");
SizeMenu.AddItem("3.0", "Triple");
SizeMenu.AddItem("4.0", "Quadruple");
SizeMenu.AddItem("0.5", "Half");
SizeMenu.ExitBackButton = true;
return SizeMenu;
}
Menu CreateRotateMenu()
{
Menu RotateXMenu = new Menu(Handler_RotateX);
RotateXMenu.SetTitle("Rotation");
RotateXMenu.AddItem("Rotate X +45 Degrees", "Rotate X +45 Degrees");
RotateXMenu.AddItem("Rotate Y +45 Degrees", "Rotate Y +45 Degrees");
RotateXMenu.AddItem("Rotate Z +45 Degrees", "Rotate Z +45 Degrees");
RotateXMenu.ExitBackButton = true;
return RotateXMenu;
}
//Menu Handlers
public int Handler_Main(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
if (StrEqual(info, "Place"))
{
CreatePropMenu().DisplayAt(param1, param2, MENU_TIME_FOREVER);
}
else if(StrEqual(info, "Remove"))
{
if (RemoveProp(param1))
{
PrintToChat(param1, "[HexProps] Prop successfully removed!");
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found!");
}
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if(StrEqual(info, "Edit"))
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Move"))
{
//PrintToChatAll("param1 value: %N", param1);
if (CheckCommandAccess(param1, "generic_admin", ADMFLAG_GENERIC, false))
{
bMoveProp[param1] = !bMoveProp[param1];
PrintToChatAll("%N moving props!", param1);
}
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Physic"))
{
bPhysicProp[param1] = !bPhysicProp[param1];
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Safe"))
{
bool bSaved = SaveProps();
if (bSaved)
{
PrintToChat(param1, "[HexProps] Props successfully saved!");
}
else
{
PrintToChat(param1, "[HexProps] No props were saved!");
}
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Reset"))
{
ResetProps();
PrintToChat(param1, "[HexProps] Props successfully resetted!");
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else
{
CreateDeleteAllMenu().Display(param1, 20);
}
}
else if (action == MenuAction_End)
{
delete menu;
}
return 1;
}
public int Handler_Props(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[PLATFORM_MAX_PATH];
menu.GetItem(param2, info, sizeof(info));
if (!IsModelPrecached(info))
PrecacheModel(info);
char sClass[64] = "prop_dynamic_override";
if (bPhysicProp[param1])
{
strcopy(sClass, sizeof(sClass), "prop_physics_multiplayer");
}
SpawnTempProp(param1, sClass, info);
CreatePropMenu().DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Edit(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
if (StrEqual(info, "Alpha"))
{
CreateAlphaMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Color"))
{
CreateColorMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Life"))
{
CreateLifeMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Solid"))
{
CreateSolidMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Size"))
{
CreateSizeMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (StrEqual(info, "Rotate"))
{
CreateRotateMenu().Display(param1, MENU_TIME_FOREVER);
}
else
{
MakePhysic(param1);
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
}
else if (action == MenuAction_Cancel)
{
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
void MakePhysic(int client)
{
int iEnt = GetAimEnt(client);
if (iEnt == -1)
{
PrintToChat(client, "[HexProps] Prop couldn't be found");
return;
}
int iIndex = FindInArray(iEnt);
if (!iIndex || iIndex == -1)
{
PrintToChat(client, "[HexProps] Prop couldn't be found");
return;
}
char sModel[PLATFORM_MAX_PATH];
float vPos[3];
GetEntityModel(iEnt, sModel);
GetEntityOrigin(iEnt, vPos);
AcceptEntityInput(iEnt, "kill");
PropsArray.Erase(iIndex);
iEnt = -1;
iEnt = CreateEntityByName("prop_physics_multiplayer");
if (iEnt == -1)
{
PrintToChat(client, "[HexProps] Error occured while creating the physic prop!");
return;
}
DispatchKeyValue(iEnt, "Physics Mode", "1");
SetEntityModel(iEnt, sModel);
DispatchSpawn(iEnt);
TeleportEntity(iEnt, vPos, NULL_VECTOR, NULL_VECTOR);
PropsArray.Push(EntIndexToEntRef(iEnt));
}
public int Handler_DeleteAll(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
bool bDelete = view_as<bool>(StringToInt(info));
if (bDelete)
{
if (!PropKv.GotoFirstSubKey())
SetFailState("- HexProps - Failed to read: %s", sPropPath);
do
{
PropKv.DeleteThis();
}
while (PropKv.GotoNextKey());
PropKv.Rewind();
for (int i = 0; i < PropsArray.Length; i++)
{
int iEnt = EntRefToEntIndex(PropsArray.Get(i));
if (iEnt == INVALID_ENT_REFERENCE)
continue;
AcceptEntityInput(iEnt, "kill");
}
ReplyToCommand(param1, "[SM] Props deleted!");
}
CreateMainMenu(param1).Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Color(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
int r, g, b;
char info[64];
menu.GetItem(param2, info, sizeof(info));
if (StrEqual(info, "Red"))
{
r = 255;
}
else if (StrEqual(info, "Green"))
{
g = 255;
}
else if (StrEqual(info, "Blue"))
{
b = 255;
}
else if (StrEqual(info, "Pink"))
{
r = 255;
g = 102;
b = 178;
}
else if (StrEqual(info, "Yellow"))
{
r = 255;
g = 255;
}
else if (StrEqual(info, "Default"))
{
r = 255;
g = 255;
b = 255;
}
else{} //if black dont to anything
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1)
{
int r2, g2, b2, a;
GetEntityRenderColor(iAimEnt, r2, g2, b2, a);
SetEntityRenderColor(iAimEnt, r, g, b, a);
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateColorMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Alpha(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1)
{
int r, g, b, a;
SetEntityRenderMode(iAimEnt, RENDER_TRANSCOLOR);
GetEntityRenderColor(iAimEnt, r, g, b, a);
SetEntityRenderColor(iAimEnt, r, g, b, StringToInt(info));
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateAlphaMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Life(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
int r, b, g, a;
int iLife;
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1)
{
GetEntityRenderColor(iAimEnt, r, g, b, a);
iLife = StringToInt(info);
if (iLife)
{
iEntHP[iAimEnt] = iLife;
SetEntProp(iAimEnt, Prop_Data, "m_takedamage", 2);
SetEntProp(iAimEnt, Prop_Data, "m_iHealth", iLife);
}
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateLifeMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Solid(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1)
{
SetEntProp(iAimEnt, Prop_Send, "m_nSolidType", StringToInt(info));
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateSolidMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_Size(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1)
{
SetEntPropFloat(iAimEnt, Prop_Send, "m_flModelScale", StringToFloat(info));
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateSizeMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
public int Handler_RotateX(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[64];
char classname[64];
float RotateVec[3];
menu.GetItem(param2, info, sizeof(info));
int iAimEnt = GetAimEnt(param1);
if (FindInArray(iAimEnt) != -1 && iAimEnt != -1)
{
GetEdictClassname(iAimEnt, classname, sizeof(classname));
if (StrEqual(classname, "prop_physics") || StrEqual(classname, "prop_physics_override") || StrEqual(classname, "prop_dynamic") || StrEqual(classname, "prop_dynamic_override") || StrEqual(classname, "prop_physics_multiplayer") || StrEqual(classname, "prop_dynamic_ornament") || StrEqual(classname, "prop_static"))
{
PrintToChat(param1, "%s", info);
GetEntPropVector(iAimEnt, Prop_Send, "m_angRotation", RotateVec);
if (StrContains(info, "X", false) >= 0)
{
RotateVec[0] = RotateVec[0] + 45.0;
}
else if (StrContains(info, "Y", false) >= 0)
{
RotateVec[1] = RotateVec[1] + 45.0;
}
else if (StrContains(info, "Z", false) >= 0)
{
RotateVec[2] = RotateVec[2] + 45.0;
}
TeleportEntity(iAimEnt, NULL_VECTOR, RotateVec, NULL_VECTOR);
AcceptEntityInput(iAimEnt, "TurnOn", iAimEnt, iAimEnt, 0);
AcceptEntityInput(iAimEnt, "EnableCollision");
}
}
else
{
PrintToChat(param1, "[HexProps] Prop couldn't be found");
}
CreateRotateMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_Cancel)
{
CreateEditMenu().Display(param1, MENU_TIME_FOREVER);
}
else if (action == MenuAction_End)
{
delete menu;
}
}
//Functions
int SpawnProp(const char[] classname, const char[] model, float vPos[3], float vAng[3], int r, int g, int b, int a, bool solid, int iLife, float fSize)
{
int iEnt = CreateEntityByName(classname);
//PrintToChatAll("classname: %s", classname);
if (iEnt == -1)
{
//PrintToChatAll("Failed iEnt = -1");
return iEnt;
}
if (!IsModelPrecached(model))
PrecacheModel(model);
SetEntityModel(iEnt, model);
SetEntityRenderMode(iEnt, RENDER_TRANSCOLOR);
SetEntityRenderColor(iEnt, r, b, g, a);
SetEntProp(iEnt, Prop_Send, "m_nSolidType", 6);
if (!solid)
SetEntProp(iEnt, Prop_Send, "m_nSolidType", 1);
if (iLife)
{
SetEntProp(iEnt, Prop_Data, "m_takedamage", 2);
iEntHP[iEnt] = iLife;
SetEntProp(iEnt, Prop_Data, "m_iHealth", iLife);
}
SetEntPropFloat(iEnt, Prop_Send, "m_flModelScale", fSize);
if (StrContains(classname, "physics") != -1)
{
DispatchKeyValue(iEnt, "Physics Mode", "1");
DispatchSpawn(iEnt);
}
/*
PrintToChatAll("%i", view_as<int>(solid));
PrintToChatAll("vPos[0]: %f", vPos[0]);
PrintToChatAll("vPos[1]: %f", vPos[1]);
PrintToChatAll("vPos[2]: %f", vPos[2]);
PrintToChatAll("vAng[0]: %f", vAng[0]);
PrintToChatAll("vAng[1]: %f", vAng[1]);
PrintToChatAll("vAng[2]: %f", vAng[2]);
PrintToChatAll("fSize: %f", fSize);
PrintToChatAll("iLife: %i", iLife);
PrintToChatAll("model: %s", model);
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i))
{
TeleportEntity(i, vPos, vAng, NULL_VECTOR);
}
}
*/
TeleportEntity(iEnt, vPos, vAng, NULL_VECTOR);
return iEnt;
}
int SpawnTempProp(int client, const char[] classname, const char[] model)
{
int iEnt = CreateEntityByName(classname);
if (iEnt == -1)
{
CreatePropMenu().Display(client, MENU_TIME_FOREVER);
return -1;
}
SetEntityModel(iEnt, model);
SetEntProp(iEnt, Prop_Send, "m_nSolidType", 6);
SetEntityRenderMode(iEnt, RENDER_TRANSCOLOR);
SetEntityRenderColor(iEnt);
float vClientPos[3];
float vClientAng[3];
float vEndPoint[3];
float vEndAng[3];
GetClientEyePosition(client, vClientPos);
GetClientEyeAngles(client, vClientAng);
TR_TraceRayFilter(vClientPos, vClientAng, MASK_SOLID, RayType_Infinite, TraceRayDontHitPlayer, client);
if (TR_DidHit())
{
TR_GetEndPosition(vEndPoint);
TR_GetPlaneNormal(INVALID_HANDLE, vEndAng);
GetVectorAngles(vEndAng, vEndAng);
vEndAng[0] += 90.0;
}
else
{
CreatePropMenu().Display(client, MENU_TIME_FOREVER);
return -1;
}
if (StrContains(classname, "physics") != -1)
{
DispatchKeyValue(iEnt, "Physics Mode", "1");
DispatchSpawn(iEnt);
}
TeleportEntity(iEnt, vEndPoint, vEndAng, NULL_VECTOR);
int iIndex = PropsArray.Push(EntIndexToEntRef(iEnt));
SetEntityName(iEnt, "Prop_%i", iIndex);
return iEnt;
}
bool RemoveProp(int client)
{
int iAimEnt = GetAimEnt(client);
int iIndex;
if (iAimEnt == -1)
return false;
iIndex = FindInArray(iAimEnt) != -1;
if (!iIndex)
return false;
AcceptEntityInput(iAimEnt, "kill");
PropsArray.Erase(iIndex);
return true;
}
bool SaveProps()
{
ClearPropKv();
char sKey[8];
int iCount;
bool bReturn = false;
for (int i = 0; i < PropsArray.Length; i++)
{
PropKv.Rewind();
IntToString(++iCount, sKey, sizeof(sKey));
if (PropKv.JumpToKey(sKey, true))
{
int iEnt = EntRefToEntIndex(PropsArray.Get(i));
if (iEnt == INVALID_ENT_REFERENCE)
continue;
char sClass[64];
char sModel[PLATFORM_MAX_PATH];
char sColor[16];
float vPos[3];
float vAng[3];
int r, b, g, a;
GetEntityClassname(iEnt, sClass, sizeof(sClass));
GetEntityModel(iEnt, sModel);
GetEntityOrigin(iEnt, vPos);
GetEntityAngles(iEnt, vAng);
GetEntityRenderColor(iEnt, r, g, b, a);
bool solid = (GetEntProp(iEnt, Prop_Send, "m_nSolidType") == 6);
int iLife = iEntHP[iEnt];
float fSize = GetEntPropFloat(iEnt, Prop_Send, "m_flModelScale");
ColorToString(sColor, sizeof(sColor), r, b, g, a);
PropKv.SetString("classname", sClass);
PropKv.SetString("model", sModel);
PropKv.SetVector("position", vPos);
PropKv.SetVector("angles", vAng);
PropKv.SetString("color", sColor);
PropKv.SetNum("solid", solid);
PropKv.SetNum("life", iLife);
PropKv.SetFloat("size", fSize);
bReturn = true;
}
}
PropKv.Rewind();
PropKv.ExportToFile(sPropPath);
return bReturn;
}
void LoadProps()
{
if (!PropKv.GotoFirstSubKey())
return;
PropsArray.Clear();
//needs to edit this part to not rely on keyvalues
Handle l_hPropFile = INVALID_HANDLE;
char l_cReadLine[128];
char sClass[64];
char sModel[PLATFORM_MAX_PATH];
float vPos[3];
float vAng[3];
char sColors[24];
int r, g, b, a;
bool solid;
int iLife;
float fSize;
l_hPropFile = OpenFile(sPropPath, "r");
while (!IsEndOfFile(l_hPropFile) && ReadFileLine(l_hPropFile, l_cReadLine, sizeof(l_cReadLine)))
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "\"", "", true);
if (StrContains(l_cReadLine, "classname", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "classname", "", true);
Format(sClass, sizeof(sClass), l_cReadLine);
TrimString(sClass);
}
else if (StrContains(l_cReadLine, "model", false) > -1)
{
//trimming first part
strcopy(l_cReadLine, sizeof(l_cReadLine), l_cReadLine[7]);
Format(sModel, sizeof(sModel), l_cReadLine);
TrimString(sModel);
}
else if (StrContains(l_cReadLine, "position", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "position", "", true);
char sPart[3][64];
//spliting on whitespace
ExplodeString(l_cReadLine, " ", sPart, 3, 64);
vPos[0] = StringToFloat(sPart[0]);
vPos[1] = StringToFloat(sPart[1]);
vPos[2] = StringToFloat(sPart[2]);
}
else if (StrContains(l_cReadLine, "angles", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "angles", "", true);
char sPart[3][64];
//spliting on whitespace
ExplodeString(l_cReadLine, " ", sPart, 3, 64);
vAng[0] = StringToFloat(sPart[0]);
vAng[1] = StringToFloat(sPart[1]);
vAng[2] = StringToFloat(sPart[2]);
}
else if (StrContains(l_cReadLine, "color", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "color", "", true);
Format(sColors, sizeof(sColors), l_cReadLine);
}
else if (StrContains(l_cReadLine, "solid", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "solid", "", true);
TrimString(l_cReadLine);
solid = view_as<bool>(StringToInt(l_cReadLine));
}
else if (StrContains(l_cReadLine, "life", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "life", "", true);
TrimString(l_cReadLine);
iLife = StringToInt(l_cReadLine);
}
else if (StrContains(l_cReadLine, "size", false) > -1)
{
ReplaceString(l_cReadLine, sizeof(l_cReadLine), "size", "", true);
TrimString(l_cReadLine);
fSize = StringToFloat(l_cReadLine);
StringToColor(sColors, r, g, b, a);
int iEnt = SpawnProp(sClass, sModel, vPos, vAng, r, g, b, a, solid, iLife, fSize);
if (iEnt != -1)
{
//still works good with reading from files
int iIndex = PropsArray.Push(EntIndexToEntRef(iEnt));
SetEntityName(iEnt, "Prop_%i", iIndex);
//PrintToChatAll("iEnt: %i", iEnt);
}
}
}
delete l_hPropFile;
PropKv.Rewind();
}
void ResetProps()
{
for (int i = 0; i < PropsArray.Length; i++)
{
int iEnt = EntRefToEntIndex(PropsArray.Get(i));
if (iEnt != INVALID_ENT_REFERENCE)
AcceptEntityInput(iEnt, "kill");
}
PropsArray.Clear();
LoadProps();
}
//Trace
public bool TraceRayDontHitPlayer(int entity, int mask, any data)
{
if(entity != data && entity > MaxClients)
{
return true;
}
return false;
}
//Stocks
void ColorToString(char[] sColor, int maxlength, int r, int g, int b, int a)
{
Format(sColor, maxlength, "%i %i %i %i", r, g, b, a);
}
void StringToColor(char[] sColors, int &r, int &g, int &b, int &a)
{
char sColorsL[4][64];
//PrintToChatAll("sColors: %s", sColors);
ExplodeString(sColors, " ", sColorsL, sizeof(sColorsL), sizeof(sColorsL[]));
r = StringToInt(sColorsL[0]);
g = StringToInt(sColorsL[1]);
b = StringToInt(sColorsL[2]);
a = StringToInt(sColorsL[3]);
}
void ClearPropKv()
{
if (!PropKv.GotoFirstSubKey())
return;
do
{
PropKv.DeleteThis();
}
while (PropKv.GotoNextKey());
PropKv.Rewind();
}
int FindInArray(int iEnt)
{
if (iEnt == -1)
return 0;
for (int i = 0; i < PropsArray.Length; i++)
{
int iSavedEnt = EntRefToEntIndex(PropsArray.Get(i));
if (iSavedEnt == INVALID_ENT_REFERENCE)
return 0;
if (iSavedEnt == iEnt)
{
return i;
}
}
return 0;
}
//Use this(instead of GetClientAimTarget) since we need to get non-solid entites too.
int GetAimEnt(int client)
{
float vClientPos[3];
float vClientAng[3];
GetClientEyePosition(client, vClientPos);
GetClientEyeAngles(client, vClientAng);
TR_TraceRayFilter(vClientPos, vClientAng, MASK_ALL, RayType_Infinite, TraceRayDontHitPlayer, client);
int iEnt = TR_GetEntityIndex();
//PrintToChatAll("IsValidEntity");
if (iEnt == 0) //if it hits nothing dont do anything man
{
iEnt = -1;
}
return iEnt;
}
public void OnClientDisconnect(int iClient)
{
bMoveProp[iClient] = false;
}
public void OnClientPostAdminCheck(int iClient)
{
bMoveProp[iClient] = false;
}
//Natives
public int Native_IsEntProp(Handle plugin, int numParams)
{
int iEnt = GetNativeCell(1);
return (FindInArray(iEnt) == -1);
}