FlacoBey

Untitled

Jun 5th, 2019
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 41.83 KB | None | 0 0
  1. #pragma semicolon 1
  2. #pragma newdecls required
  3.  
  4. #include <sourcemod>
  5. #include <sdktools>
  6.  
  7. #define CVAR_FLAGS          FCVAR_NOTIFY
  8. #define CHAT_TAG            "\x04[\x05Weapon Spawn\x04] \x01"
  9. #define CONFIG_SPAWNS       "data/l4d_spawn_weapon.cfg"
  10. #define MAX_SPAWNS          32
  11. #define MAX_WEAPONS         10
  12. #define MAX_WEAPONS2        29
  13.  
  14. ConVar g_hCvarAllow, g_hCvarCount, g_hCvarGlow, g_hCvarGlowCol, g_hCvarMPGameMode, g_hCvarModes, g_hCvarModesOff, g_hCvarModesTog, g_hCvarRandom, g_hCvarRandomise;
  15. int g_iCvarCount, g_iCvarGlow, g_iCvarGlowCol, g_iCvarRandom, g_iCvarRandomise, g_iPlayerSpawn, g_iRoundStart, g_iSave[MAXPLAYERS+1], g_iSpawnCount, g_iSpawns[MAX_SPAWNS][2];
  16. bool g_bCvarAllow, g_bLeft4Dead2, g_bLoaded;
  17. Menu g_hMenuAng, g_hMenuList, g_hMenuPos;
  18.  
  19. ConVar g_hAmmoAutoShot, g_hAmmoChainsaw, g_hAmmoGL, g_hAmmoHunting, g_hAmmoM60, g_hAmmoRifle, g_hAmmoShotgun, g_hAmmoSmg, g_hAmmoSniper;
  20. int g_iAmmoAutoShot, g_iAmmoChainsaw, g_iAmmoGL, g_iAmmoHunting, g_iAmmoM60, g_iAmmoRifle, g_iAmmoShotgun, g_iAmmoSmg, g_iAmmoSniper;
  21.  
  22. static char g_sWeaponNames[MAX_WEAPONS][] =
  23. {
  24.     "Rifle",
  25.     "Auto Shotgun",
  26.     "Hunting Rifle",
  27.     "SMG",
  28.     "Pump Shotgun",
  29.     "Pistol",
  30.     "Molotov",
  31.     "Pipe Bomb",
  32.     "First Aid Kit",
  33.     "Pain Pills"
  34. };
  35. static char g_sWeapons[MAX_WEAPONS][] =
  36. {
  37.     "weapon_rifle",
  38.     "weapon_autoshotgun",
  39.     "weapon_hunting_rifle",
  40.     "weapon_smg",
  41.     "weapon_pumpshotgun",
  42.     "weapon_pistol",
  43.     "weapon_molotov",
  44.     "weapon_pipe_bomb",
  45.     "weapon_first_aid_kit",
  46.     "weapon_pain_pills"
  47. };
  48. static char g_sWeaponModels[MAX_WEAPONS][] =
  49. {
  50.     "models/w_models/weapons/w_rifle_m16a2.mdl",
  51.     "models/w_models/weapons/w_autoshot_m4super.mdl",
  52.     "models/w_models/weapons/w_sniper_mini14.mdl",
  53.     "models/w_models/weapons/w_smg_uzi.mdl",
  54.     "models/w_models/weapons/w_pumpshotgun_A.mdl",
  55.     "models/w_models/weapons/w_pistol_a.mdl",
  56.     "models/w_models/weapons/w_eq_molotov.mdl",
  57.     "models/w_models/weapons/w_eq_pipebomb.mdl",
  58.     "models/w_models/weapons/w_eq_medkit.mdl",
  59.     "models/w_models/weapons/w_eq_painpills.mdl"
  60. };
  61. static char g_sWeaponNames2[MAX_WEAPONS2][] =
  62. {
  63.     "Rifle",
  64.     "Auto Shotgun",
  65.     "Hunting Rifle",
  66.     "SMG",
  67.     "Pump Shotgun",
  68.     "Pistol",
  69.     "Molotov",
  70.     "Pipe Bomb",
  71.     "First Aid Kit",
  72.     "Pain Pills",
  73.  
  74.     "Shotgun Chrome",
  75.     "Rifle Desert",
  76.     "Grenade Launcher",
  77.     "M60",
  78.     "AK47",
  79.     "SG552",
  80.     "Shotgun Spas",
  81.     "SMG Silenced",
  82.     "SMG MP5",
  83.     "Sniper AWP",
  84.     "Sniper Military",
  85.     "Sniper Scout",
  86.     "Chainsaw",
  87.     "Pistol Magnum",
  88.     "VomitJar",
  89.     "Defibrillator",
  90.     "Upgradepack Explosive",
  91.     "Upgradepack Incendiary",
  92.     "Adrenaline"
  93. };
  94. static char g_sWeapons2[MAX_WEAPONS2][] =
  95. {
  96.     "weapon_rifle",
  97.     "weapon_autoshotgun",
  98.     "weapon_hunting_rifle",
  99.     "weapon_smg",
  100.     "weapon_pumpshotgun",
  101.     "weapon_pistol",
  102.     "weapon_molotov",
  103.     "weapon_pipe_bomb",
  104.     "weapon_first_aid_kit",
  105.     "weapon_pain_pills",
  106.  
  107.     "weapon_shotgun_chrome",
  108.     "weapon_rifle_desert",
  109.     "weapon_grenade_launcher",
  110.     "weapon_rifle_m60",
  111.     "weapon_rifle_ak47",
  112.     "weapon_rifle_sg552",
  113.     "weapon_shotgun_spas",
  114.     "weapon_smg_silenced",
  115.     "weapon_smg_mp5",
  116.     "weapon_sniper_awp",
  117.     "weapon_sniper_military",
  118.     "weapon_sniper_scout",
  119.     "weapon_chainsaw",
  120.     "weapon_pistol_magnum",
  121.     "weapon_vomitjar",
  122.     "weapon_defibrillator",
  123.     "weapon_upgradepack_explosive",
  124.     "weapon_upgradepack_incendiary",
  125.     "weapon_adrenaline"
  126. };
  127. static char g_sWeaponModels2[MAX_WEAPONS2][] =
  128. {
  129.     "models/w_models/weapons/w_rifle_m16a2.mdl",
  130.     "models/w_models/weapons/w_autoshot_m4super.mdl",
  131.     "models/w_models/weapons/w_sniper_mini14.mdl",
  132.     "models/w_models/weapons/w_smg_uzi.mdl",
  133.     "models/w_models/weapons/w_pumpshotgun_A.mdl",
  134.     "models/w_models/weapons/w_pistol_a.mdl",
  135.     "models/w_models/weapons/w_eq_molotov.mdl",
  136.     "models/w_models/weapons/w_eq_pipebomb.mdl",
  137.     "models/w_models/weapons/w_eq_medkit.mdl",
  138.     "models/w_models/weapons/w_eq_painpills.mdl",
  139.  
  140.     "models/w_models/weapons/w_shotgun.mdl",
  141.     "models/w_models/weapons/w_desert_rifle.mdl",
  142.     "models/w_models/weapons/w_grenade_launcher.mdl",
  143.     "models/w_models/weapons/w_m60.mdl",
  144.     "models/w_models/weapons/w_rifle_ak47.mdl",
  145.     "models/w_models/weapons/w_rifle_sg552.mdl",
  146.     "models/w_models/weapons/w_shotgun_spas.mdl",
  147.     "models/w_models/weapons/w_smg_a.mdl",
  148.     "models/w_models/weapons/w_smg_mp5.mdl",
  149.     "models/w_models/weapons/w_sniper_awp.mdl",
  150.     "models/w_models/weapons/w_sniper_military.mdl",
  151.     "models/w_models/weapons/w_sniper_scout.mdl",
  152.     "models/weapons/melee/w_chainsaw.mdl",
  153.     "models/w_models/weapons/w_desert_eagle.mdl",
  154.     "models/w_models/weapons/w_eq_bile_flask.mdl",
  155.     "models/w_models/weapons/w_eq_defibrillator.mdl",
  156.     "models/w_models/weapons/w_eq_explosive_ammopack.mdl",
  157.     "models/w_models/weapons/w_eq_incendiary_ammopack.mdl",
  158.     "models/w_models/weapons/w_eq_adrenaline.mdl"
  159. };
  160.  
  161. public void OnPluginStart()
  162. {
  163.     g_hCvarAllow =      CreateConVar(   "l4d_weapon_spawn_allow",           "1",            "0=Plugin off, 1=Plugin on.", CVAR_FLAGS );
  164.     g_hCvarGlow =       CreateConVar(   "l4d_weapon_spawn_glow",            "100",          "0=Off. Any other value is the range at which the glow will turn on.", CVAR_FLAGS );
  165.     g_hCvarGlowCol =    CreateConVar(   "l4d_weapon_spawn_glow_color",      "0 255 0",      "0=Default glow color. Three values between 0-255 separated by spaces. RGB Color255 - Red Green Blue.", CVAR_FLAGS );
  166.     g_hCvarModes =      CreateConVar(   "l4d_weapon_spawn_modes",           "",             "Turn on the plugin in these game modes, separate by commas (no spaces). (Empty = all).", CVAR_FLAGS );
  167.     g_hCvarModesOff =   CreateConVar(   "l4d_weapon_spawn_modes_off",       "",             "Turn off the plugin in these game modes, separate by commas (no spaces). (Empty = none).", CVAR_FLAGS );
  168.     g_hCvarModesTog =   CreateConVar(   "l4d_weapon_spawn_modes_tog",       "0",            "Turn on the plugin in these game modes. 0=All, 1=Coop, 2=Survival, 4=Versus, 8=Scavenge. Add numbers together.", CVAR_FLAGS );
  169.     g_hCvarCount =      CreateConVar(   "l4d_weapon_spawn_count",           "1",            "0=Infinite. How many items/weapons to give from 1 spawner.", CVAR_FLAGS );
  170.     g_hCvarRandom =     CreateConVar(   "l4d_weapon_spawn_random",          "-1",           "-1=All, 0=None. Otherwise randomly select this many weapons to spawn from the maps config.", CVAR_FLAGS );
  171.     g_hCvarRandomise =  CreateConVar(   "l4d_weapon_spawn_randomise",       "25",           "0=Off. Chance out of 100 to randomise the type of item/weapon regardless of what it's set to.", CVAR_FLAGS );
  172.     AutoExecConfig(true,                "l4d_weapon_spawn");
  173.  
  174.     g_hCvarMPGameMode = FindConVar("mp_gamemode");
  175.     g_hCvarMPGameMode.AddChangeHook(ConVarChanged_Allow);
  176.     g_hCvarAllow.AddChangeHook(ConVarChanged_Allow);
  177.     g_hCvarModes.AddChangeHook(ConVarChanged_Allow);
  178.     g_hCvarModesOff.AddChangeHook(ConVarChanged_Allow);
  179.     g_hCvarModesTog.AddChangeHook(ConVarChanged_Allow);
  180.     g_hCvarCount.AddChangeHook(ConVarChanged_Cvars);
  181.     g_hCvarRandom.AddChangeHook(ConVarChanged_Cvars);
  182.     g_hCvarRandomise.AddChangeHook(ConVarChanged_Cvars);
  183.     g_hCvarGlow.AddChangeHook(ConVarChanged_Glow);
  184.     g_hCvarGlowCol.AddChangeHook(ConVarChanged_Glow);
  185.  
  186.  
  187.     g_hAmmoRifle =          FindConVar("ammo_assaultrifle_max");
  188.     g_hAmmoSmg =            FindConVar("ammo_smg_max");
  189.     g_hAmmoHunting =        FindConVar("ammo_huntingrifle_max");
  190.  
  191.     g_hAmmoRifle.AddChangeHook(ConVarChanged_Cvars);
  192.     g_hAmmoSmg.AddChangeHook(ConVarChanged_Cvars);
  193.     g_hAmmoHunting.AddChangeHook(ConVarChanged_Cvars);
  194.  
  195.     g_hAmmoShotgun =    FindConVar("ammo_shotgun_max");
  196.     g_hAmmoGL =         FindConVar("ammo_grenadelauncher_max");
  197.     g_hAmmoChainsaw =   FindConVar("ammo_chainsaw_max");
  198.     g_hAmmoAutoShot =   FindConVar("ammo_autoshotgun_max");
  199.     g_hAmmoM60 =        FindConVar("ammo_m60_max");
  200.     g_hAmmoSniper =     FindConVar("ammo_sniperrifle_max");
  201.  
  202.     g_hAmmoGL.AddChangeHook(ConVarChanged_Cvars);
  203.     g_hAmmoChainsaw.AddChangeHook(ConVarChanged_Cvars);
  204.     g_hAmmoAutoShot.AddChangeHook(ConVarChanged_Cvars);
  205.     g_hAmmoM60.AddChangeHook(ConVarChanged_Cvars);
  206.     g_hAmmoSniper.AddChangeHook(ConVarChanged_Cvars);
  207.  
  208.     RegAdminCmd("sm_weapon_spawn",          CmdSpawnerTemp,     ADMFLAG_ROOT,   "Opens a menu of weapons/items to spawn. Spawns a temporary weapon at your crosshair.");
  209.     RegAdminCmd("sm_weapon_spawn_save",     CmdSpawnerSave,     ADMFLAG_ROOT,   "Opens a menu of weapons/items to spawn. Spawns a weapon at your crosshair and saves to config.");
  210.     RegAdminCmd("sm_weapon_spawn_del",      CmdSpawnerDel,      ADMFLAG_ROOT,   "Removes the weapon you are pointing at and deletes from the config if saved.");
  211.     RegAdminCmd("sm_weapon_spawn_clear",    CmdSpawnerClear,    ADMFLAG_ROOT,   "Removes all weapons spawned by this plugin from the current map.");
  212.     RegAdminCmd("sm_weapon_spawn_wipe",     CmdSpawnerWipe,     ADMFLAG_ROOT,   "Removes all weapons spawned by this plugin from the current map and deletes them from the config.");
  213.     RegAdminCmd("sm_weapon_spawn_glow",     CmdSpawnerGlow,     ADMFLAG_ROOT,   "Toggle to enable glow on all weapons to see where they are placed.");
  214.     RegAdminCmd("sm_weapon_spawn_list",     CmdSpawnerList,     ADMFLAG_ROOT,   "Display a list weapon positions and the total number of.");
  215.     RegAdminCmd("sm_weapon_spawn_tele",     CmdSpawnerTele,     ADMFLAG_ROOT,   "Teleport to a weapon (Usage: sm_weapon_spawn_tele <index: 1 to MAX_SPAWNS (32)>).");
  216.     RegAdminCmd("sm_weapon_spawn_ang",      CmdSpawnerAng,      ADMFLAG_ROOT,   "Displays a menu to adjust the weapon angles your crosshair is over.");
  217.     RegAdminCmd("sm_weapon_spawn_pos",      CmdSpawnerPos,      ADMFLAG_ROOT,   "Displays a menu to adjust the weapon origin your crosshair is over.");
  218.  
  219.  
  220.  
  221.     g_hMenuList = new Menu(ListMenuHandler);
  222.     int max = MAX_WEAPONS;
  223.     if( g_bLeft4Dead2 ) max = MAX_WEAPONS2;
  224.     for( int i = 0; i < max; i++ )
  225.     {
  226.         if( g_bLeft4Dead2 )
  227.             g_hMenuList.AddItem("", g_sWeaponNames2[i]);
  228.         else
  229.             g_hMenuList.AddItem("", g_sWeaponNames[i]);
  230.     }
  231.     g_hMenuList.SetTitle("Spawn Weapon");
  232.     g_hMenuList.ExitBackButton = true;
  233. }
  234.  
  235. public void OnPluginEnd()
  236. {
  237.     ResetPlugin();
  238. }
  239.  
  240. public void OnMapStart()
  241. {
  242.     int max = MAX_WEAPONS;
  243.     if( g_bLeft4Dead2 ) max = MAX_WEAPONS2;
  244.     for( int i = 0; i < max; i++ )
  245.     {
  246.         if( g_bLeft4Dead2 )
  247.             PrecacheModel(g_sWeaponModels2[i], true);
  248.         else
  249.             PrecacheModel(g_sWeaponModels[i], true);
  250.     }
  251. }
  252.  
  253. public void OnMapEnd()
  254. {
  255.     ResetPlugin(false);
  256. }
  257.  
  258.  
  259.  
  260. // ====================================================================================================
  261. //                  CVARS
  262. // ====================================================================================================
  263. public void OnConfigsExecuted()
  264. {
  265.     IsAllowed();
  266. }
  267.  
  268. public void ConVarChanged_Allow(Handle convar, const char[] oldValue, const char[] newValue)
  269. {
  270.     IsAllowed();
  271. }
  272.  
  273. public void ConVarChanged_Cvars(Handle convar, const char[] oldValue, const char[] newValue)
  274. {
  275.     GetCvars();
  276. }
  277.  
  278. public void ConVarChanged_Glow(Handle convar, const char[] oldValue, const char[] newValue)
  279. {
  280.     g_iCvarGlow = g_hCvarGlow.IntValue;
  281.     g_iCvarGlowCol = GetColor(g_hCvarGlowCol);
  282.     VendorGlow(g_iCvarGlow);
  283. }
  284.  
  285. int GetColor(ConVar hCvar)
  286. {
  287.     char sTemp[12];
  288.     hCvar.GetString(sTemp, sizeof(sTemp));
  289.  
  290.     if( strcmp(sTemp, "") == 0 )
  291.         return 0;
  292.  
  293.     char sColors[3][4];
  294.     int color = ExplodeString(sTemp, " ", sColors, 3, 4);
  295.  
  296.     if( color != 3 )
  297.         return 0;
  298.  
  299.     color = StringToInt(sColors[0]);
  300.     color += 256 * StringToInt(sColors[1]);
  301.     color += 65536 * StringToInt(sColors[2]);
  302.  
  303.     return color;
  304. }
  305.  
  306. void GetCvars()
  307. {
  308.     g_iCvarCount = g_hCvarCount.IntValue;
  309.     g_iCvarRandom = g_hCvarRandom.IntValue;
  310.     g_iCvarRandomise = g_hCvarRandomise.IntValue;
  311.  
  312.     g_iAmmoRifle        = g_hAmmoRifle.IntValue;
  313.     g_iAmmoShotgun      = g_hAmmoShotgun.IntValue;
  314.     g_iAmmoSmg          = g_hAmmoSmg.IntValue;
  315.     g_iAmmoHunting      = g_hAmmoHunting.IntValue;
  316.  
  317.     if( g_bLeft4Dead2 )
  318.     {
  319.         g_iAmmoGL           = g_hAmmoGL.IntValue;
  320.         g_iAmmoChainsaw     = g_hAmmoChainsaw.IntValue;
  321.         g_iAmmoAutoShot     = g_hAmmoAutoShot.IntValue;
  322.         g_iAmmoM60          = g_hAmmoM60.IntValue;
  323.         g_iAmmoSniper       = g_hAmmoSniper.IntValue;
  324.     }
  325. }
  326.  
  327. void IsAllowed()
  328. {
  329.     bool bCvarAllow = g_hCvarAllow.BoolValue;
  330.     bool bAllowMode = IsAllowedGameMode();
  331.     GetCvars();
  332.  
  333.     if( g_bCvarAllow == false && bCvarAllow == true && bAllowMode == true )
  334.     {
  335.         g_bCvarAllow = true;
  336.         LoadSpawns();
  337.         HookEvent("player_spawn",       Event_PlayerSpawn,  EventHookMode_PostNoCopy);
  338.         HookEvent("round_start",        Event_RoundStart,   EventHookMode_PostNoCopy);
  339.         HookEvent("round_end",          Event_RoundEnd,     EventHookMode_PostNoCopy);
  340.     }
  341.  
  342.     else if( g_bCvarAllow == true && (bCvarAllow == false || bAllowMode == false) )
  343.     {
  344.         g_bCvarAllow = false;
  345.         ResetPlugin();
  346.         UnhookEvent("player_spawn",     Event_PlayerSpawn,  EventHookMode_PostNoCopy);
  347.         UnhookEvent("round_start",      Event_RoundStart,   EventHookMode_PostNoCopy);
  348.         UnhookEvent("round_end",        Event_RoundEnd,     EventHookMode_PostNoCopy);
  349.     }
  350. }
  351.  
  352. int g_iCurrentMode;
  353. bool IsAllowedGameMode()
  354. {
  355.     if( g_hCvarMPGameMode == null )
  356.         return false;
  357.  
  358.     int iCvarModesTog = g_hCvarModesTog.IntValue;
  359.     if( iCvarModesTog != 0 )
  360.     {
  361.         g_iCurrentMode = 0;
  362.  
  363.         int entity = CreateEntityByName("info_gamemode");
  364.         DispatchSpawn(entity);
  365.         HookSingleEntityOutput(entity, "OnCoop", OnGamemode, true);
  366.         HookSingleEntityOutput(entity, "OnSurvival", OnGamemode, true);
  367.         HookSingleEntityOutput(entity, "OnVersus", OnGamemode, true);
  368.         HookSingleEntityOutput(entity, "OnScavenge", OnGamemode, true);
  369.         ActivateEntity(entity);
  370.         AcceptEntityInput(entity, "PostSpawnActivate");
  371.         AcceptEntityInput(entity, "Kill");
  372.  
  373.         if( g_iCurrentMode == 0 )
  374.             return false;
  375.  
  376.         if( !(iCvarModesTog & g_iCurrentMode) )
  377.             return false;
  378.     }
  379.  
  380.     char sGameModes[64], sGameMode[64];
  381.     g_hCvarMPGameMode.GetString(sGameMode, sizeof(sGameMode));
  382.     Format(sGameMode, sizeof(sGameMode), ",%s,", sGameMode);
  383.  
  384.     g_hCvarModes.GetString(sGameModes, sizeof(sGameModes));
  385.     if( strcmp(sGameModes, "") )
  386.     {
  387.         Format(sGameModes, sizeof(sGameModes), ",%s,", sGameModes);
  388.         if( StrContains(sGameModes, sGameMode, false) == -1 )
  389.             return false;
  390.     }
  391.  
  392.     g_hCvarModesOff.GetString(sGameModes, sizeof(sGameModes));
  393.     if( strcmp(sGameModes, "") )
  394.     {
  395.         Format(sGameModes, sizeof(sGameModes), ",%s,", sGameModes);
  396.         if( StrContains(sGameModes, sGameMode, false) != -1 )
  397.             return false;
  398.     }
  399.  
  400.     return true;
  401. }
  402.  
  403. public void OnGamemode(const char[] output, int caller, int activator, float delay)
  404. {
  405.     if( strcmp(output, "OnCoop") == 0 )
  406.         g_iCurrentMode = 1;
  407.     else if( strcmp(output, "OnSurvival") == 0 )
  408.         g_iCurrentMode = 2;
  409.     else if( strcmp(output, "OnVersus") == 0 )
  410.         g_iCurrentMode = 4;
  411.     else if( strcmp(output, "OnScavenge") == 0 )
  412.         g_iCurrentMode = 8;
  413. }
  414.  
  415.  
  416.  
  417. // ====================================================================================================
  418. //                  EVENTS
  419. // ====================================================================================================
  420. public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
  421. {
  422.     ResetPlugin(false);
  423. }
  424.  
  425. public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
  426. {
  427.     if( g_iPlayerSpawn == 1 && g_iRoundStart == 0 )
  428.         CreateTimer(1.0, tmrStart, _, TIMER_FLAG_NO_MAPCHANGE);
  429.     g_iRoundStart = 1;
  430. }
  431.  
  432. public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast)
  433. {
  434.     if( g_iPlayerSpawn == 0 && g_iRoundStart == 1 )
  435.         CreateTimer(1.0, tmrStart, _, TIMER_FLAG_NO_MAPCHANGE);
  436.     g_iPlayerSpawn = 1;
  437. }
  438.  
  439. public Action tmrStart(Handle timer)
  440. {
  441.     ResetPlugin();
  442.     LoadSpawns();
  443. }
  444.  
  445.  
  446.  
  447. // ====================================================================================================
  448. //                  LOAD SPAWNS
  449. // ====================================================================================================
  450. void LoadSpawns()
  451. {
  452.     if( g_bLoaded || g_iCvarRandom == 0 ) return;
  453.     g_bLoaded = true;
  454.  
  455.     char sPath[PLATFORM_MAX_PATH];
  456.     BuildPath(Path_SM, sPath, sizeof(sPath), "%s", CONFIG_SPAWNS);
  457.     if( !FileExists(sPath) )
  458.         return;
  459.  
  460.     // Load config
  461.     KeyValues hFile = new KeyValues("spawns");
  462.     if( !hFile.ImportFromFile(sPath) )
  463.     {
  464.         delete hFile;
  465.         return;
  466.     }
  467.  
  468.     // Check for current map in the config
  469.     char sMap[64];
  470.     GetCurrentMap(sMap, 64);
  471.  
  472.     if( !hFile.JumpToKey(sMap) )
  473.     {
  474.         delete hFile;
  475.         return;
  476.     }
  477.  
  478.     // Retrieve how many weapons to display
  479.     int iCount = hFile.GetNum("num", 0);
  480.     if( iCount == 0 )
  481.     {
  482.         delete hFile;
  483.         return;
  484.     }
  485.  
  486.     // Spawn only a select few weapons?
  487.     int iIndexes[MAX_SPAWNS+1];
  488.     if( iCount > MAX_SPAWNS )
  489.         iCount = MAX_SPAWNS;
  490.  
  491.  
  492.     // Spawn saved weapons or create random
  493.     int iRandom = g_iCvarRandom;
  494.     if( iRandom == -1 || iRandom > iCount)
  495.         iRandom = iCount;
  496.     if( iRandom != -1 )
  497.     {
  498.         for( int i = 1; i <= iCount; i++ )
  499.             iIndexes[i-1] = i;
  500.  
  501.         SortIntegers(iIndexes, iCount, Sort_Random);
  502.         iCount = iRandom;
  503.     }
  504.  
  505.     // Get the weapon origins and spawn
  506.     char sTemp[10];
  507.     float vPos[3], vAng[3];
  508.     int index, iMod;
  509.     for( int i = 1; i <= iCount; i++ )
  510.     {
  511.         if( iRandom != -1 ) index = iIndexes[i-1];
  512.         else index = i;
  513.  
  514.         IntToString(index, sTemp, sizeof(sTemp));
  515.  
  516.         if( hFile.JumpToKey(sTemp) )
  517.         {
  518.             hFile.GetVector("ang", vAng);
  519.             hFile.GetVector("pos", vPos);
  520.             iMod = hFile.GetNum("mod");
  521.  
  522.             if( vPos[0] == 0.0 && vPos[1] == 0.0 && vPos[2] == 0.0 ) // Should never happen...
  523.                 LogError("Error: 0,0,0 origin. Iteration=%d. Index=%d. Random=%d. Count=%d.", i, index, iRandom, iCount);
  524.             else
  525.                 CreateSpawn(vPos, vAng, index, iMod, true);
  526.             hFile.GoBack();
  527.         }
  528.     }
  529.  
  530.     delete hFile;
  531. }
  532.  
  533.  
  534.  
  535. // ====================================================================================================
  536. //                  CREATE SPAWN
  537. // ====================================================================================================
  538. void CreateSpawn(const float vOrigin[3], const float vAngles[3], int index = 0, int model = 0, int autospawn = false)
  539. {
  540.     if( g_iSpawnCount >= MAX_SPAWNS )
  541.         return;
  542.  
  543.     int iSpawnIndex = -1;
  544.     for( int i = 0; i < MAX_SPAWNS; i++ )
  545.     {
  546.         if( g_iSpawns[i][0] == 0 )
  547.         {
  548.             iSpawnIndex = i;
  549.             break;
  550.         }
  551.     }
  552.  
  553.     if( iSpawnIndex == -1 )
  554.         return;
  555.  
  556.  
  557.     if( autospawn && g_iCvarRandomise && GetRandomInt(0, 100) <= g_iCvarRandomise )
  558.     {
  559.         if( g_bLeft4Dead2 )
  560.         {
  561.             model = GetRandomInt(0, MAX_WEAPONS2-1);
  562.  
  563.             if( model == 15 || model == 18 )        model = GetRandomInt(0, 14);
  564.             else if( model == 19 || model == 21 )   model = GetRandomInt(22, 28);
  565.         } else {
  566.             model = GetRandomInt(0, MAX_WEAPONS-1);
  567.         }
  568.     }
  569.  
  570.     char classname[64];
  571.     if( g_bLeft4Dead2 )
  572.         strcopy(classname, sizeof(classname), g_sWeapons2[model]);
  573.     else
  574.         strcopy(classname, sizeof(classname), g_sWeapons[model]);
  575.     int iCount = g_iCvarCount;
  576.  
  577.     if( iCount != 1 )
  578.     {
  579.         if( model != 15 && model != 18 && model != 19 && model != 21 )
  580.             StrCat(classname, sizeof(classname), "_spawn");
  581.         else
  582.             iCount = 1;
  583.     }
  584.  
  585.  
  586.     int entity_weapon = -1;
  587.     entity_weapon = CreateEntityByName(classname);
  588.     if( entity_weapon == -1 )
  589.         ThrowError("Failed to create entity '%s'", classname);
  590.  
  591.     DispatchKeyValue(entity_weapon, "solid", "6");
  592.     if( g_bLeft4Dead2 )
  593.         DispatchKeyValue(entity_weapon, "model", g_sWeaponModels2[model]);
  594.     else
  595.         DispatchKeyValue(entity_weapon, "model", g_sWeaponModels[model]);
  596.     DispatchKeyValue(entity_weapon, "rendermode", "3");
  597.     DispatchKeyValue(entity_weapon, "disableshadows", "1");
  598.  
  599.     if( iCount <= 0 ) // Infinite
  600.     {
  601.         DispatchKeyValue(entity_weapon, "spawnflags", "8");
  602.         DispatchKeyValue(entity_weapon, "count", "9999");
  603.     }
  604.     else if( iCount != 1 )
  605.     {
  606.         char sCount[5];
  607.         IntToString(iCount, sCount, sizeof(sCount));
  608.         DispatchKeyValue(entity_weapon, "count", sCount);
  609.     }
  610.  
  611.     float vAng[3], vPos[3];
  612.     vPos = vOrigin;
  613.     vAng = vAngles;
  614.     if( model == 8 ) // First aid
  615.     {
  616.         vAng[0] += 90.0;
  617.         vPos[2] += 1.0;
  618.     }
  619.     else if( g_bLeft4Dead2 && model == 28 ) // Adrenaline
  620.     {
  621.         vAng[1] -= 90.0;
  622.         vAng[2] -= 90.0;
  623.         vPos[2] += 1.0;
  624.     }
  625.     else if( g_bLeft4Dead2 && (model == 25 || model == 26 || model == 27 )) // Defib + Upgrades
  626.     {
  627.         vAng[1] -= 90.0;
  628.         vAng[2] += 90.0;
  629.     }
  630.     else if( g_bLeft4Dead2 && model == 22 ) // Chainsaw
  631.     {
  632.         vPos[2] += 3.0;
  633.     }
  634.  
  635.     TeleportEntity(entity_weapon, vPos, vAng, NULL_VECTOR);
  636.     DispatchSpawn(entity_weapon);
  637.  
  638.     if( iCount == 1 )
  639.     {
  640.         int ammo;
  641.  
  642.         if( model == 3 )                        ammo = g_iAmmoSmg;
  643.         else if( model == 0 )                   ammo = g_iAmmoRifle;
  644.         else if( model == 4 )                   ammo = g_iAmmoShotgun;
  645.         else if( model == 1 )                   ammo = g_iAmmoAutoShot;
  646.         else if( model == 2 )                   ammo = g_iAmmoHunting;
  647.         else if( g_bLeft4Dead2 )
  648.         {
  649.             if( model == 17 || model == 18 )                                ammo = g_iAmmoSmg;
  650.             else if( model == 11 || model == 14 || model == 15 )            ammo = g_iAmmoRifle;
  651.             else if( model == 10 )                                          ammo = g_iAmmoShotgun;
  652.             else if( model == 16 )                                          ammo = g_iAmmoAutoShot;
  653.             else if( model == 22 )                                          ammo = g_iAmmoChainsaw;
  654.             else if( model == 13 )                                          ammo = g_iAmmoM60;
  655.             else if( model == 12 )                                          ammo = g_iAmmoGL;
  656.             else if( model == 19 || model == 20 || model == 21 )            ammo = g_iAmmoSniper;
  657.         }
  658.         if( !g_bLeft4Dead2 && model == 1 ) ammo = g_iAmmoShotgun;
  659.  
  660.         SetEntProp(entity_weapon, Prop_Send, "m_iExtraPrimaryAmmo", ammo, 4);
  661.     }
  662.     SetEntityMoveType(entity_weapon, MOVETYPE_NONE);
  663.  
  664.     g_iSpawns[iSpawnIndex][0] = EntIndexToEntRef(entity_weapon);
  665.     g_iSpawns[iSpawnIndex][1] = index;
  666.  
  667.     g_iSpawnCount++;
  668. }
  669.  
  670.  
  671.  
  672. // ====================================================================================================
  673. //                  COMMANDS
  674. // ====================================================================================================
  675. //                  sm_weapon_spawn
  676. // ====================================================================================================
  677. public int ListMenuHandler(Menu menu, MenuAction action, int client, int index)
  678. {
  679.     if( action == MenuAction_Select )
  680.     {
  681.         if( g_iSave[client] == 0 )
  682.         {
  683.             CmdSpawnerTempMenu(client, index);
  684.         } else {
  685.             CmdSpawnerSaveMenu(client, index);
  686.         }
  687.  
  688.         g_hMenuList.Display(client, MENU_TIME_FOREVER);
  689.     }
  690. }
  691.  
  692. public Action CmdSpawnerTemp(int client, int args)
  693. {
  694.     if( !client )
  695.     {
  696.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  697.         return Plugin_Handled;
  698.     }
  699.     else if( g_iSpawnCount >= MAX_SPAWNS )
  700.     {
  701.         PrintToChat(client, "%sError: Cannot add anymore weapons. Used: (\x05%d/%d\x01).", CHAT_TAG, g_iSpawnCount, MAX_SPAWNS);
  702.         return Plugin_Handled;
  703.     }
  704.  
  705.     g_iSave[client] = 0;
  706.     g_hMenuList.Display(client, MENU_TIME_FOREVER);
  707.  
  708.     return Plugin_Handled;
  709. }
  710.  
  711. void CmdSpawnerTempMenu(int client, int weapon)
  712. {
  713.     if( !client )
  714.     {
  715.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  716.         return;
  717.     }
  718.     else if( g_iSpawnCount >= MAX_SPAWNS )
  719.     {
  720.         PrintToChat(client, "%sError: Cannot add anymore weapons. Used: (\x05%d/%d\x01).", CHAT_TAG, g_iSpawnCount, MAX_SPAWNS);
  721.         return;
  722.     }
  723.  
  724.     float vPos[3], vAng[3];
  725.     if( !SetTeleportEndPoint(client, vPos, vAng) )
  726.     {
  727.         PrintToChat(client, "%sCannot place weapon, please try again.", CHAT_TAG);
  728.         return;
  729.     }
  730.  
  731.     CreateSpawn(vPos, vAng, 0, weapon);
  732.     return;
  733. }
  734.  
  735. // ====================================================================================================
  736. //                  sm_weapon_spawn_save
  737. // ====================================================================================================
  738. public Action CmdSpawnerSave(int client, int args)
  739. {
  740.     if( !client )
  741.     {
  742.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  743.         return Plugin_Handled;
  744.     }
  745.     else if( g_iSpawnCount >= MAX_SPAWNS )
  746.     {
  747.         PrintToChat(client, "%sError: Cannot add anymore weapons. Used: (\x05%d/%d\x01).", CHAT_TAG, g_iSpawnCount, MAX_SPAWNS);
  748.         return Plugin_Handled;
  749.     }
  750.  
  751.     g_iSave[client] = 1;
  752.     g_hMenuList.Display(client, MENU_TIME_FOREVER);
  753.  
  754.     return Plugin_Handled;
  755. }
  756.  
  757. void CmdSpawnerSaveMenu(int client, int weapon)
  758. {
  759.     char sPath[PLATFORM_MAX_PATH];
  760.     BuildPath(Path_SM, sPath, sizeof(sPath), "%s", CONFIG_SPAWNS);
  761.     if( !FileExists(sPath) )
  762.     {
  763.         File hCfg = OpenFile(sPath, "w");
  764.         hCfg.WriteLine("");
  765.         delete hCfg;
  766.     }
  767.  
  768.     // Load config
  769.     KeyValues hFile = new KeyValues("spawns");
  770.     if( !hFile.ImportFromFile(sPath) )
  771.     {
  772.         PrintToChat(client, "%sError: Cannot read the weapon config, assuming empty file. (\x05%s\x01).", CHAT_TAG, sPath);
  773.     }
  774.  
  775.     // Check for current map in the config
  776.     char sMap[64];
  777.     GetCurrentMap(sMap, 64);
  778.     if( !hFile.JumpToKey(sMap, true) )
  779.     {
  780.         PrintToChat(client, "%sError: Failed to add map to weapon spawn config.", CHAT_TAG);
  781.         delete hFile;
  782.         return;
  783.     }
  784.  
  785.     // Retrieve how many weapons are saved
  786.     int iCount = hFile.GetNum("num", 0);
  787.     if( iCount >= MAX_SPAWNS )
  788.     {
  789.         PrintToChat(client, "%sError: Cannot add anymore weapons. Used: (\x05%d/%d\x01).", CHAT_TAG, iCount, MAX_SPAWNS);
  790.         delete hFile;
  791.         return;
  792.     }
  793.  
  794.     // Save count
  795.     iCount++;
  796.     hFile.SetNum("num", iCount);
  797.  
  798.     char sTemp[10];
  799.  
  800.     IntToString(iCount, sTemp, sizeof(sTemp));
  801.  
  802.     if( hFile.JumpToKey(sTemp, true) )
  803.     {
  804.         float vPos[3], vAng[3];
  805.         // Set player position as weapon spawn location
  806.         if( !SetTeleportEndPoint(client, vPos, vAng) )
  807.         {
  808.             PrintToChat(client, "%sCannot place weapon, please try again.", CHAT_TAG);
  809.             delete hFile;
  810.             return;
  811.         }
  812.  
  813.         // Save angle / origin
  814.         hFile.SetVector("ang", vAng);
  815.         hFile.SetVector("pos", vPos);
  816.         hFile.SetNum("mod", weapon);
  817.  
  818.         CreateSpawn(vPos, vAng, iCount, weapon);
  819.  
  820.         // Save cfg
  821.         hFile.Rewind();
  822.         hFile.ExportToFile(sPath);
  823.  
  824.         PrintToChat(client, "%s(\x05%d/%d\x01) - Saved at pos:[\x05%f %f %f\x01] ang:[\x05%f %f %f\x01]", CHAT_TAG, iCount, MAX_SPAWNS, vPos[0], vPos[1], vPos[2], vAng[0], vAng[1], vAng[2]);
  825.     }
  826.     else
  827.         PrintToChat(client, "%s(\x05%d/%d\x01) - Failed to save weapon.", CHAT_TAG, iCount, MAX_SPAWNS);
  828.  
  829.     delete hFile;
  830. }
  831.  
  832. // ====================================================================================================
  833. //                  sm_weapon_spawn_del
  834. // ====================================================================================================
  835. public Action CmdSpawnerDel(int client, int args)
  836. {
  837.     if( !g_bCvarAllow )
  838.     {
  839.         ReplyToCommand(client, "[Weapon Spawn] Plugin turned off.");
  840.         return Plugin_Handled;
  841.     }
  842.  
  843.     if( !client )
  844.     {
  845.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  846.         return Plugin_Handled;
  847.     }
  848.  
  849.     int entity = GetClientAimTarget(client, false);
  850.     if( entity == -1 ) return Plugin_Handled;
  851.     entity = EntIndexToEntRef(entity);
  852.  
  853.     int cfgindex, index = -1;
  854.     for( int i = 0; i < MAX_SPAWNS; i++ )
  855.     {
  856.         if( g_iSpawns[i][0] == entity )
  857.         {
  858.             index = i;
  859.             break;
  860.         }
  861.     }
  862.  
  863.     if( index == -1 )
  864.         return Plugin_Handled;
  865.  
  866.     cfgindex = g_iSpawns[index][1];
  867.     if( cfgindex == 0 )
  868.     {
  869.         RemoveSpawn(index);
  870.         return Plugin_Handled;
  871.     }
  872.  
  873.     for( int i = 0; i < MAX_SPAWNS; i++ )
  874.     {
  875.         if( g_iSpawns[i][1] > cfgindex )
  876.             g_iSpawns[i][1]--;
  877.     }
  878.  
  879.     g_iSpawnCount--;
  880.  
  881.     // Load config
  882.     char sPath[PLATFORM_MAX_PATH];
  883.     BuildPath(Path_SM, sPath, sizeof(sPath), "%s", CONFIG_SPAWNS);
  884.     if( !FileExists(sPath) )
  885.     {
  886.         PrintToChat(client, "%sError: Cannot find the weapon config (\x05%s\x01).", CHAT_TAG, CONFIG_SPAWNS);
  887.         return Plugin_Handled;
  888.     }
  889.  
  890.     KeyValues hFile = new KeyValues("spawns");
  891.     if( !hFile.ImportFromFile(sPath) )
  892.     {
  893.         PrintToChat(client, "%sError: Cannot load the weapon config (\x05%s\x01).", CHAT_TAG, sPath);
  894.         delete hFile;
  895.         return Plugin_Handled;
  896.     }
  897.  
  898.     // Check for current map in the config
  899.     char sMap[64];
  900.     GetCurrentMap(sMap, 64);
  901.  
  902.     if( !hFile.JumpToKey(sMap) )
  903.     {
  904.         PrintToChat(client, "%sError: Current map not in the weapon config.", CHAT_TAG);
  905.         delete hFile;
  906.         return Plugin_Handled;
  907.     }
  908.  
  909.     // Retrieve how many weapons
  910.     int iCount = hFile.GetNum("num", 0);
  911.     if( iCount == 0 )
  912.     {
  913.         delete hFile;
  914.         return Plugin_Handled;
  915.     }
  916.  
  917.     bool bMove;
  918.     char sTemp[16];
  919.  
  920.     // Move the other entries down
  921.     for( int i = cfgindex; i <= iCount; i++ )
  922.     {
  923.         IntToString(i, sTemp, sizeof(sTemp));
  924.  
  925.         if( hFile.JumpToKey(sTemp) )
  926.         {
  927.             if( !bMove )
  928.             {
  929.                 bMove = true;
  930.                 hFile.DeleteThis();
  931.                 RemoveSpawn(index);
  932.             }
  933.             else
  934.             {
  935.                 IntToString(i-1, sTemp, sizeof(sTemp));
  936.                 hFile.SetSectionName(sTemp);
  937.             }
  938.         }
  939.  
  940.         hFile.Rewind();
  941.         hFile.JumpToKey(sMap);
  942.     }
  943.  
  944.     if( bMove )
  945.     {
  946.         iCount--;
  947.         hFile.SetNum("num", iCount);
  948.  
  949.         // Save to file
  950.         hFile.Rewind();
  951.         hFile.ExportToFile(sPath);
  952.  
  953.         PrintToChat(client, "%s(\x05%d/%d\x01) - weapon removed from config.", CHAT_TAG, iCount, MAX_SPAWNS);
  954.     }
  955.     else
  956.         PrintToChat(client, "%s(\x05%d/%d\x01) - Failed to remove weapon from config.", CHAT_TAG, iCount, MAX_SPAWNS);
  957.  
  958.     delete hFile;
  959.     return Plugin_Handled;
  960. }
  961.  
  962. // ====================================================================================================
  963. //                  sm_weapon_spawn_clear
  964. // ====================================================================================================
  965. public Action CmdSpawnerClear(int client, int args)
  966. {
  967.     if( !client )
  968.     {
  969.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  970.         return Plugin_Handled;
  971.     }
  972.  
  973.     ResetPlugin();
  974.  
  975.     PrintToChat(client, "%s(0/%d) - All weapons removed from the map.", CHAT_TAG, MAX_SPAWNS);
  976.     return Plugin_Handled;
  977. }
  978.  
  979. // ====================================================================================================
  980. //                  sm_weapon_spawn_wipe
  981. // ====================================================================================================
  982. public Action CmdSpawnerWipe(int client, int args)
  983. {
  984.     if( !client )
  985.     {
  986.         ReplyToCommand(client, "[Weapon Spawn] Commands may only be used in-game on a dedicated server..");
  987.         return Plugin_Handled;
  988.     }
  989.  
  990.     char sPath[PLATFORM_MAX_PATH];
  991.     BuildPath(Path_SM, sPath, sizeof(sPath), "%s", CONFIG_SPAWNS);
  992.     if( !FileExists(sPath) )
  993.     {
  994.         PrintToChat(client, "%sError: Cannot find the weapon config (\x05%s\x01).", CHAT_TAG, sPath);
  995.         return Plugin_Handled;
  996.     }
  997.  
  998.     // Load config
  999.     KeyValues hFile = new KeyValues("spawns");
  1000.     if( !hFile.ImportFromFile(sPath) )
  1001.     {
  1002.         PrintToChat(client, "%sError: Cannot load the weapon config (\x05%s\x01).", CHAT_TAG, sPath);
  1003.         delete hFile;
  1004.         return Plugin_Handled;
  1005.     }
  1006.  
  1007.     // Check for current map in the config
  1008.     char sMap[64];
  1009.     GetCurrentMap(sMap, 64);
  1010.  
  1011.     if( !hFile.JumpToKey(sMap, false) )
  1012.     {
  1013.         PrintToChat(client, "%sError: Current map not in the weapon config.", CHAT_TAG);
  1014.         delete hFile;
  1015.         return Plugin_Handled;
  1016.     }
  1017.  
  1018.     hFile.DeleteThis();
  1019.     ResetPlugin();
  1020.  
  1021.     // Save to file
  1022.     hFile.Rewind();
  1023.     hFile.ExportToFile(sPath);
  1024.     delete hFile;
  1025.  
  1026.     PrintToChat(client, "%s(0/%d) - All weapons removed from config, add with \x05sm_weapon_spawn_save\x01.", CHAT_TAG, MAX_SPAWNS);
  1027.     return Plugin_Handled;
  1028. }
  1029.  
  1030. // ====================================================================================================
  1031. //                  sm_weapon_spawn_glow
  1032. // ====================================================================================================
  1033. public Action CmdSpawnerGlow(int client, int args)
  1034. {
  1035.     static bool glow;
  1036.     glow = !glow;
  1037.     PrintToChat(client, "%sGlow has been turned %s", CHAT_TAG, glow ? "on" : "off");
  1038.  
  1039.     VendorGlow(glow);
  1040.     return Plugin_Handled;
  1041. }
  1042.  
  1043. void VendorGlow(int glow)
  1044. {
  1045.     int ent;
  1046.  
  1047.     for( int i = 0; i < MAX_SPAWNS; i++ )
  1048.     {
  1049.         ent = g_iSpawns[i][0];
  1050.         if( IsValidEntRef(ent) )
  1051.         {
  1052.             SetEntProp(ent, Prop_Send, "m_iGlowType", glow ? 3 : 0);
  1053.             if( glow )
  1054.             {
  1055.                 SetEntProp(ent, Prop_Send, "m_glowColorOverride", g_iCvarGlowCol);
  1056.                 SetEntProp(ent, Prop_Send, "m_nGlowRange", glow ? 0 : g_iCvarGlow);
  1057.             }
  1058.         }
  1059.     }
  1060. }
  1061.  
  1062. // ====================================================================================================
  1063. //                  sm_weapon_spawn_list
  1064. // ====================================================================================================
  1065. public Action CmdSpawnerList(int client, int args)
  1066. {
  1067.     float vPos[3];
  1068.     int count;
  1069.     for( int i = 0; i < MAX_SPAWNS; i++ )
  1070.     {
  1071.         if( IsValidEntRef(g_iSpawns[i][0]) )
  1072.         {
  1073.             count++;
  1074.             GetEntPropVector(g_iSpawns[i][0], Prop_Data, "m_vecOrigin", vPos);
  1075.             PrintToChat(client, "%s%d) %f %f %f", CHAT_TAG, i+1, vPos[0], vPos[1], vPos[2]);
  1076.         }
  1077.     }
  1078.     PrintToChat(client, "%sTotal: %d.", CHAT_TAG, count);
  1079.     return Plugin_Handled;
  1080. }
  1081.  
  1082. // ====================================================================================================
  1083. //                  sm_weapon_spawn_tele
  1084. // ====================================================================================================
  1085. public Action CmdSpawnerTele(int client, int args)
  1086. {
  1087.     if( args == 1 )
  1088.     {
  1089.         char arg[16];
  1090.         GetCmdArg(1, arg, 16);
  1091.         int index = StringToInt(arg) - 1;
  1092.         if( index > -1 && index < MAX_SPAWNS && IsValidEntRef(g_iSpawns[index][0]) )
  1093.         {
  1094.             float vPos[3];
  1095.             GetEntPropVector(g_iSpawns[index][0], Prop_Data, "m_vecOrigin", vPos);
  1096.             vPos[2] += 20.0;
  1097.             TeleportEntity(client, vPos, NULL_VECTOR, NULL_VECTOR);
  1098.             PrintToChat(client, "%sTeleported to %d.", CHAT_TAG, index + 1);
  1099.             return Plugin_Handled;
  1100.         }
  1101.  
  1102.         PrintToChat(client, "%sCould not find index for teleportation.", CHAT_TAG);
  1103.     }
  1104.     else
  1105.         PrintToChat(client, "%sUsage: sm_weapon_spawn_tele <index 1-%d>.", CHAT_TAG, MAX_SPAWNS);
  1106.     return Plugin_Handled;
  1107. }
  1108.  
  1109. // ====================================================================================================
  1110. //                  MENU ANGLE
  1111. // ====================================================================================================
  1112. public Action CmdSpawnerAng(int client, int args)
  1113. {
  1114.     ShowMenuAng(client);
  1115.     return Plugin_Handled;
  1116. }
  1117.  
  1118. void ShowMenuAng(int client)
  1119. {
  1120.     CreateMenus();
  1121.     g_hMenuAng.Display(client, MENU_TIME_FOREVER);
  1122. }
  1123.  
  1124. public int AngMenuHandler(Menu menu, MenuAction action, int client, int index)
  1125. {
  1126.     if( action == MenuAction_Select )
  1127.     {
  1128.         if( index == 6 )
  1129.             SaveData(client);
  1130.         else
  1131.             SetAngle(client, index);
  1132.         ShowMenuAng(client);
  1133.     }
  1134. }
  1135.  
  1136. void SetAngle(int client, int index)
  1137. {
  1138.     int aim = GetClientAimTarget(client, false);
  1139.     if( aim != -1 )
  1140.     {
  1141.         float vAng[3];
  1142.         int entity;
  1143.         aim = EntIndexToEntRef(aim);
  1144.  
  1145.         for( int i = 0; i < MAX_SPAWNS; i++ )
  1146.         {
  1147.             entity = g_iSpawns[i][0];
  1148.  
  1149.             if( entity == aim  )
  1150.             {
  1151.                 GetEntPropVector(entity, Prop_Send, "m_angRotation", vAng);
  1152.  
  1153.                 if( index == 0 ) vAng[0] += 2.0;
  1154.                 else if( index == 1 ) vAng[1] += 2.0;
  1155.                 else if( index == 2 ) vAng[2] += 2.0;
  1156.                 else if( index == 3 ) vAng[0] -= 2.0;
  1157.                 else if( index == 4 ) vAng[1] -= 2.0;
  1158.                 else if( index == 5 ) vAng[2] -= 2.0;
  1159.  
  1160.                 TeleportEntity(entity, NULL_VECTOR, vAng, NULL_VECTOR);
  1161.  
  1162.                 PrintToChat(client, "%sNew angles: %f %f %f", CHAT_TAG, vAng[0], vAng[1], vAng[2]);
  1163.                 break;
  1164.             }
  1165.         }
  1166.     }
  1167. }
  1168.  
  1169. // ====================================================================================================
  1170. //                  MENU ORIGIN
  1171. // ====================================================================================================
  1172. public Action CmdSpawnerPos(int client, int args)
  1173. {
  1174.     ShowMenuPos(client);
  1175.     return Plugin_Handled;
  1176. }
  1177.  
  1178. void ShowMenuPos(int client)
  1179. {
  1180.     CreateMenus();
  1181.     g_hMenuPos.Display(client, MENU_TIME_FOREVER);
  1182. }
  1183.  
  1184. public int PosMenuHandler(Menu menu, MenuAction action, int client, int index)
  1185. {
  1186.     if( action == MenuAction_Select )
  1187.     {
  1188.         if( index == 6 )
  1189.             SaveData(client);
  1190.         else
  1191.             SetOrigin(client, index);
  1192.         ShowMenuPos(client);
  1193.     }
  1194. }
  1195.  
  1196. void SetOrigin(int client, int index)
  1197. {
  1198.     int aim = GetClientAimTarget(client, false);
  1199.     if( aim != -1 )
  1200.     {
  1201.         float vPos[3];
  1202.         int entity;
  1203.         aim = EntIndexToEntRef(aim);
  1204.  
  1205.         for( int i = 0; i < MAX_SPAWNS; i++ )
  1206.         {
  1207.             entity = g_iSpawns[i][0];
  1208.  
  1209.             if( entity == aim  )
  1210.             {
  1211.                 GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vPos);
  1212.  
  1213.                 if( index == 0 ) vPos[0] += 0.5;
  1214.                 else if( index == 1 ) vPos[1] += 0.5;
  1215.                 else if( index == 2 ) vPos[2] += 0.5;
  1216.                 else if( index == 3 ) vPos[0] -= 0.5;
  1217.                 else if( index == 4 ) vPos[1] -= 0.5;
  1218.                 else if( index == 5 ) vPos[2] -= 0.5;
  1219.  
  1220.                 TeleportEntity(entity, vPos, NULL_VECTOR, NULL_VECTOR);
  1221.  
  1222.                 PrintToChat(client, "%sNew origin: %f %f %f", CHAT_TAG, vPos[0], vPos[1], vPos[2]);
  1223.                 break;
  1224.             }
  1225.         }
  1226.     }
  1227. }
  1228.  
  1229. void SaveData(int client)
  1230. {
  1231.     int entity, index;
  1232.     int aim = GetClientAimTarget(client, false);
  1233.     if( aim == -1 )
  1234.         return;
  1235.  
  1236.     aim = EntIndexToEntRef(aim);
  1237.  
  1238.     for( int i = 0; i < MAX_SPAWNS; i++ )
  1239.     {
  1240.         entity = g_iSpawns[i][0];
  1241.  
  1242.         if( entity == aim  )
  1243.         {
  1244.             index = g_iSpawns[i][1];
  1245.             break;
  1246.         }
  1247.     }
  1248.  
  1249.     if( index == 0 )
  1250.         return;
  1251.  
  1252.     // Load config
  1253.     char sPath[PLATFORM_MAX_PATH];
  1254.     BuildPath(Path_SM, sPath, sizeof(sPath), "%s", CONFIG_SPAWNS);
  1255.     if( !FileExists(sPath) )
  1256.     {
  1257.         PrintToChat(client, "%sError: Cannot find the Weapon Spawn config (\x05%s\x01).", CHAT_TAG, CONFIG_SPAWNS);
  1258.         return;
  1259.     }
  1260.  
  1261.     KeyValues hFile = new KeyValues("spawns");
  1262.     if( !hFile.ImportFromFile(sPath) )
  1263.     {
  1264.         PrintToChat(client, "%sError: Cannot load the Weapon Spawn config (\x05%s\x01).", CHAT_TAG, sPath);
  1265.         delete hFile;
  1266.         return;
  1267.     }
  1268.  
  1269.     // Check for current map in the config
  1270.     char sMap[64];
  1271.     GetCurrentMap(sMap, 64);
  1272.  
  1273.     if( !hFile.JumpToKey(sMap) )
  1274.     {
  1275.         PrintToChat(client, "%sError: Current map not in the Weapon Spawn config.", CHAT_TAG);
  1276.         delete hFile;
  1277.         return;
  1278.     }
  1279.  
  1280.     float vAng[3], vPos[3];
  1281.     char sTemp[32];
  1282.     GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vPos);
  1283.     GetEntPropVector(entity, Prop_Send, "m_angRotation", vAng);
  1284.  
  1285.     IntToString(index, sTemp, sizeof(sTemp));
  1286.     if( hFile.JumpToKey(sTemp) )
  1287.     {
  1288.         hFile.SetVector("ang", vAng);
  1289.         hFile.SetVector("pos", vPos);
  1290.  
  1291.         // Save cfg
  1292.         hFile.Rewind();
  1293.         hFile.ExportToFile(sPath);
  1294.  
  1295.         PrintToChat(client, "%sSaved origin and angles to the data config", CHAT_TAG);
  1296.     }
  1297. }
  1298.  
  1299. void CreateMenus()
  1300. {
  1301.     if( g_hMenuAng == null )
  1302.     {
  1303.         g_hMenuAng = new Menu(AngMenuHandler);
  1304.         g_hMenuAng.AddItem("", "X + 2.0");
  1305.         g_hMenuAng.AddItem("", "Y + 2.0");
  1306.         g_hMenuAng.AddItem("", "Z + 2.0");
  1307.         g_hMenuAng.AddItem("", "X - 2.0");
  1308.         g_hMenuAng.AddItem("", "Y - 2.0");
  1309.         g_hMenuAng.AddItem("", "Z - 2.0");
  1310.         g_hMenuAng.AddItem("", "SAVE");
  1311.         g_hMenuAng.SetTitle("Set Angle");
  1312.         g_hMenuAng.ExitButton = true;
  1313.     }
  1314.  
  1315.     if( g_hMenuPos == null )
  1316.     {
  1317.         g_hMenuPos = new Menu(PosMenuHandler);
  1318.         g_hMenuPos.AddItem("", "X + 0.5");
  1319.         g_hMenuPos.AddItem("", "Y + 0.5");
  1320.         g_hMenuPos.AddItem("", "Z + 0.5");
  1321.         g_hMenuPos.AddItem("", "X - 0.5");
  1322.         g_hMenuPos.AddItem("", "Y - 0.5");
  1323.         g_hMenuPos.AddItem("", "Z - 0.5");
  1324.         g_hMenuPos.AddItem("", "SAVE");
  1325.         g_hMenuPos.SetTitle("Set Position");
  1326.         g_hMenuPos.ExitButton = true;
  1327.     }
  1328. }
  1329.  
  1330.  
  1331.  
  1332. // ====================================================================================================
  1333. //                  STUFF
  1334. // ====================================================================================================
  1335. bool IsValidEntRef(int entity)
  1336. {
  1337.     if( entity && EntRefToEntIndex(entity) != INVALID_ENT_REFERENCE )
  1338.         return true;
  1339.     return false;
  1340. }
  1341.  
  1342. void ResetPlugin(bool all = true)
  1343. {
  1344.     g_bLoaded = false;
  1345.     g_iSpawnCount = 0;
  1346.     g_iRoundStart = 0;
  1347.     g_iPlayerSpawn = 0;
  1348.  
  1349.     if( all )
  1350.         for( int i = 0; i < MAX_SPAWNS; i++ )
  1351.             RemoveSpawn(i);
  1352. }
  1353.  
  1354. void RemoveSpawn(int index)
  1355. {
  1356.     int entity, client;
  1357.  
  1358.     entity = g_iSpawns[index][0];
  1359.     g_iSpawns[index][0] = 0;
  1360.     g_iSpawns[index][1] = 0;
  1361.  
  1362.     if( IsValidEntRef(entity) )
  1363.     {
  1364.         client = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
  1365.         if( client < 0 || client > MaxClients || !IsClientInGame(client) )
  1366.         {
  1367.             AcceptEntityInput(entity, "kill");
  1368.         }
  1369.     }
  1370. }
  1371.  
  1372.  
  1373.  
  1374. // ====================================================================================================
  1375. //                  POSITION
  1376. // ====================================================================================================
  1377. float GetGroundHeight(float vPos[3])
  1378. {
  1379.     float vAng[3];
  1380.     Handle trace = TR_TraceRayFilterEx(vPos, view_as<float>({ 90.0, 0.0, 0.0 }), MASK_ALL, RayType_Infinite, _TraceFilter);
  1381.     if( TR_DidHit(trace) )
  1382.         TR_GetEndPosition(vAng, trace);
  1383.  
  1384.     delete trace;
  1385.     return vAng[2];
  1386. }
  1387.  
  1388. // Taken from "[L4D2] Weapon/Zombie Spawner"
  1389. // By "Zuko & McFlurry"
  1390. bool SetTeleportEndPoint(int client, float vPos[3], float vAng[3])
  1391. {
  1392.     GetClientEyePosition(client, vPos);
  1393.     GetClientEyeAngles(client, vAng);
  1394.  
  1395.     Handle trace = TR_TraceRayFilterEx(vPos, vAng, MASK_SHOT, RayType_Infinite, _TraceFilter);
  1396.  
  1397.     if(TR_DidHit(trace))
  1398.     {
  1399.         float vNorm[3];
  1400.         float degrees = vAng[1];
  1401.         TR_GetEndPosition(vPos, trace);
  1402.         GetGroundHeight(vPos);
  1403.         vPos[2] += 1.0;
  1404.         TR_GetPlaneNormal(trace, vNorm);
  1405.         GetVectorAngles(vNorm, vAng);
  1406.         if( vNorm[2] == 1.0 )
  1407.         {
  1408.             vAng[0] = 0.0;
  1409.             vAng[1] = degrees + 180;
  1410.         }
  1411.         else
  1412.         {
  1413.             if( degrees > vAng[1] )
  1414.                 degrees = vAng[1] - degrees;
  1415.             else
  1416.                 degrees = degrees - vAng[1];
  1417.             vAng[0] += 90.0;
  1418.             RotateYaw(vAng, degrees + 180);
  1419.         }
  1420.     }
  1421.     else
  1422.     {
  1423.         delete trace;
  1424.         return false;
  1425.     }
  1426.     delete trace;
  1427.  
  1428.     vAng[1] += 90.0;
  1429.     vAng[2] -= 90.0;
  1430.     return true;
  1431. }
  1432.  
  1433. public bool _TraceFilter(int entity, int contentsMask)
  1434. {
  1435.     return entity > MaxClients || !entity;
  1436. }
  1437.  
  1438.  
  1439.  
  1440. //---------------------------------------------------------
  1441. // do a specific rotation on the given angles
  1442. //---------------------------------------------------------
  1443. void RotateYaw(float angles[3], float degree)
  1444. {
  1445.     float direction[3], normal[3];
  1446.     GetAngleVectors( angles, direction, NULL_VECTOR, normal );
  1447.  
  1448.     float sin = Sine( degree * 0.01745328 );     // Pi/180
  1449.     float cos = Cosine( degree * 0.01745328 );
  1450.     float a = normal[0] * sin;
  1451.     float b = normal[1] * sin;
  1452.     float c = normal[2] * sin;
  1453.     float x = direction[2] * b + direction[0] * cos - direction[1] * c;
  1454.     float y = direction[0] * c + direction[1] * cos - direction[2] * a;
  1455.     float z = direction[1] * a + direction[2] * cos - direction[0] * b;
  1456.     direction[0] = x;
  1457.     direction[1] = y;
  1458.     direction[2] = z;
  1459.  
  1460.     GetVectorAngles( direction, angles );
  1461.  
  1462.     float up[3];
  1463.     GetVectorVectors( direction, NULL_VECTOR, up );
  1464.  
  1465.     float roll = GetAngleBetweenVectors( up, normal, direction );
  1466.     angles[2] += roll;
  1467. }
  1468.  
  1469. //---------------------------------------------------------
  1470. // calculate the angle between 2 vectors
  1471. // the direction will be used to determine the sign of angle (right hand rule)
  1472. // all of the 3 vectors have to be normalized
  1473. //---------------------------------------------------------
  1474. float GetAngleBetweenVectors(const float vector1[3], const float vector2[3], const float direction[3])
  1475. {
  1476.     float vector1_n[3], vector2_n[3], direction_n[3], cross[3];
  1477.     NormalizeVector( direction, direction_n );
  1478.     NormalizeVector( vector1, vector1_n );
  1479.     NormalizeVector( vector2, vector2_n );
  1480.     float degree = ArcCosine( GetVectorDotProduct( vector1_n, vector2_n ) ) * 57.29577951;   // 180/Pi
  1481.     GetVectorCrossProduct( vector1_n, vector2_n, cross );
  1482.  
  1483.     if ( GetVectorDotProduct( cross, direction_n ) < 0.0 )
  1484.         degree *= -1.0;
  1485.  
  1486.     return degree;
  1487. }
Advertisement
Add Comment
Please, Sign In to add comment