Advertisement
FlacoBey

Untitled

Feb 7th, 2019
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.85 KB | None | 0 0
  1. /********************************************************************************************
  2. * Plugin    : l4d_witches
  3. * Version   : 1.5
  4. * Game      : Left4Dead & Left4Dead 2
  5. * Author    : Sheleu
  6. * Testers   : Myself and Aquarius (Ja-Forces)
  7.  
  8. * Version 1.0 (05.09.10)
  9. *       -  Initial release
  10. * Version 1.1 (08.09.10)
  11. *       -  Fixed encountered error 23: Native detected error
  12. *       -  Fixed bug with counting alive witches
  13. *       -  Added removal of the witch when she far away from the survivors
  14. * Version 1.2 (09.09.10)
  15. *       -  Added precache for witch (L4D2)
  16. * Version 1.3 (16.09.10)
  17. *       -  Added removal director's witch
  18. *       -  Stopped spawn witches after finale start
  19. * Version 1.4 (24.09.10)
  20. *       -  Code optimization
  21. * Version 1.5 (17.05.11)
  22. *       -  Fixed error "Entity is not valid" (sapphire989's message)
  23. *********************************************************************************************/
  24.  
  25. #include <sourcemod>
  26. #include <sdktools>
  27.  
  28. #define PLUGIN_TAG     "[l4d_witches]"
  29. #define PLUGIN_VERSION "1.5"
  30. // Enable debug messages?
  31. #define DEBUG 0
  32. #define DEBUGFUll 0
  33.  
  34. static bool: L4DVersion; // Version 1.2
  35.  
  36. new countWitch;
  37. new maxCountWitchInRound;
  38. new maxCountWitchAlive;
  39. new Float: WitchTimeMin;
  40. new Float: WitchTimeMax;
  41. new Float: WitchDistance; // version 1.1
  42. new bool: NotRemoveDirectorWitch; // version 1.3
  43. new bool: SpawnAfterFinaleStart; // version 1.3
  44. new Handle: Witches_SpawnTimer;
  45. new Handle: g_hCvarCountWitchInRound;
  46. new Handle: g_hCvarCountAliveWitch;
  47. new Handle: g_hCvarWitchTimeMin;
  48. new Handle: g_hCvarWitchTimeMax;
  49. new Handle: g_hCvarWitchDistance; // version 1.1
  50. new Handle: g_hCvarDirectorWitch; // version 1.3
  51. new Handle: g_hCvarSpawnAfterFinaleStart; // version 1.3
  52. new bool: runTimer = false;
  53. new bool: roundStart = false;
  54. new bool: PluginWitch = false;
  55.  
  56. public Plugin: myinfo =
  57. {
  58.     name = "l4d_witches",
  59.     author = "Sheleu",  
  60.     description = "Many witches on map",
  61.     version = PLUGIN_VERSION   
  62. };
  63.  
  64. public OnPluginStart()
  65. {  
  66.     #if DEBUGFUll  
  67.     LogMessage("%s #DEBUG: Plugin start", PLUGIN_TAG); 
  68.     #endif
  69.     End_Timer(false);
  70.     // Console variables
  71.     g_hCvarCountWitchInRound = CreateConVar("l4d_witches_limit", "4", "Sets the limit for witches spawned. If 0, the plugin will not check count witches", FCVAR_NONE);
  72.     g_hCvarCountAliveWitch = CreateConVar("l4d_witches_limit_alive", "2", "Sets the limit alive witches. If 0, the plugin will not check count alive witches", FCVAR_NONE);
  73.     g_hCvarWitchTimeMin = CreateConVar("l4d_witches_spawn_time_min", "100.0", "Sets the min spawn time for witches spawned by the plugin in seconds", FCVAR_NONE);
  74.     g_hCvarWitchTimeMax = CreateConVar("l4d_witches_spawn_time_max", "120.0", "Sets the max spawn time for witches spawned by the plugin in seconds", FCVAR_NONE);
  75.     g_hCvarWitchDistance = CreateConVar("l4d_witches_distance", "1500.0", "The range from survivors that witch should be removed. If 0, the plugin will not remove witches", FCVAR_NONE); // version 1.1
  76.     g_hCvarDirectorWitch = CreateConVar("l4d_witches_director_witch", "1", "If 1, enable director's witch. If 0, disable director's witch", FCVAR_NONE, true, 0.0, true, 1.0); // version 1.3
  77.     g_hCvarSpawnAfterFinaleStart = CreateConVar("l4d_witches_spawn_after_finale_start", "1", "If 1, enable spawn witches after finale start. If 0, disable spawn witches after finale start", FCVAR_NONE, true, 0.0, true, 1.0); // version 1.3
  78.     HookConVarChange(g_hCvarCountWitchInRound, ConVarWitchLimit);
  79.     maxCountWitchInRound = GetConVarInt(g_hCvarCountWitchInRound);
  80.     HookConVarChange(g_hCvarCountAliveWitch, ConVarAliveWitchLimit);
  81.     maxCountWitchAlive = GetConVarInt(g_hCvarCountAliveWitch);
  82.     HookConVarChange(g_hCvarWitchTimeMin, ConVarWitchTimeMin);
  83.     WitchTimeMin = GetConVarFloat(g_hCvarWitchTimeMin);
  84.     HookConVarChange(g_hCvarWitchTimeMax, ConVarWitchTimeMax);
  85.     WitchTimeMax = GetConVarFloat(g_hCvarWitchTimeMax);
  86.     HookConVarChange(g_hCvarWitchDistance, ConVarWitchDistance); // version 1.1
  87.     WitchDistance = GetConVarFloat(g_hCvarWitchDistance); // version 1.1
  88.     HookConVarChange(g_hCvarDirectorWitch, ConVarDirectorWitch); // version 1.3
  89.     NotRemoveDirectorWitch = GetConVarBool(g_hCvarDirectorWitch); // version 1.3
  90.     HookConVarChange(g_hCvarSpawnAfterFinaleStart, ConVarSpawnAfterFinaleStart); // version 1.3
  91.     SpawnAfterFinaleStart = GetConVarBool(g_hCvarSpawnAfterFinaleStart); // version 1.3
  92.     // We hook some events
  93.     HookEvent("witch_spawn", Event_WitchSpawned, EventHookMode_PostNoCopy);
  94.     HookEvent("player_left_start_area", Event_PlayerLeftStartArea);
  95.     HookEvent("door_open", Event_DoorOpen);
  96.     HookEvent("round_start", Event_RoundStart);
  97.     HookEvent("finale_start", Event_FinaleStart); // version 1.3
  98.     // Autoconfig for plugin
  99.     AutoExecConfig(true, "l4d_witches");
  100. }
  101.  
  102. public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) // Version 1.2
  103. {  
  104.     decl String:GameName[64];
  105.     GetGameFolderName(GameName, sizeof(GameName));
  106.     if (StrEqual(GameName, "left4dead2", false))
  107.         L4DVersion = true;
  108.     else L4DVersion = false;
  109.     return APLRes_Success;
  110. }
  111.  
  112. public ConVarWitchLimit(Handle:convar, const String:oldValue[], const String:newValue[])
  113. {
  114.     maxCountWitchInRound = GetConVarInt(g_hCvarCountWitchInRound); 
  115.     SetConVarInt(FindConVar("l4d_witches_limit"), maxCountWitchInRound);
  116. }
  117.  
  118. public ConVarAliveWitchLimit(Handle:convar, const String:oldValue[], const String:newValue[])
  119. {
  120.     maxCountWitchAlive = GetConVarInt(g_hCvarCountAliveWitch); 
  121.     SetConVarInt(FindConVar("l4d_witches_limit_alive"), maxCountWitchAlive);
  122. }
  123.  
  124. public ConVarWitchTimeMin(Handle:convar, const String:oldValue[], const String:newValue[])
  125. {
  126.     WitchTimeMin = GetConVarFloat(g_hCvarWitchTimeMin);
  127.     SetConVarFloat(FindConVar("l4d_witches_spawn_time_min"), WitchTimeMin);
  128. }
  129.  
  130. public ConVarWitchTimeMax(Handle:convar, const String:oldValue[], const String:newValue[])
  131. {
  132.     WitchTimeMax = GetConVarFloat(g_hCvarWitchTimeMax);
  133.     SetConVarFloat(FindConVar("l4d_witches_spawn_time_max"), WitchTimeMax);
  134. }
  135.  
  136. public ConVarWitchDistance(Handle:convar, const String:oldValue[], const String:newValue[]) // version 1.1
  137. {
  138.     WitchDistance = GetConVarFloat(g_hCvarWitchDistance);  
  139.     SetConVarFloat(FindConVar("l4d_witches_distance"), WitchDistance);
  140. }
  141.  
  142. public ConVarDirectorWitch(Handle:convar, const String:oldValue[], const String:newValue[]) // version 1.3
  143. {
  144.     NotRemoveDirectorWitch = GetConVarBool(g_hCvarDirectorWitch);  
  145.     SetConVarBool(FindConVar("l4d_witches_director_witch"), NotRemoveDirectorWitch);
  146. }
  147.  
  148. public ConVarSpawnAfterFinaleStart(Handle:convar, const String:oldValue[], const String:newValue[]) // version 1.3
  149. {
  150.     SpawnAfterFinaleStart = GetConVarBool(g_hCvarSpawnAfterFinaleStart);   
  151.     SetConVarBool(FindConVar("l4d_witches_spawn_after_finale_start"), SpawnAfterFinaleStart);
  152. }
  153.  
  154. public OnPluginEnd()
  155. {
  156.     #if DEBUGFUll
  157.     LogMessage("%s #DEBUG: Plugin end", PLUGIN_TAG);   
  158.     #endif 
  159.     End_Timer(false);
  160. }
  161.  
  162. public OnConfigsExecuted()
  163. {  
  164.     #if DEBUGFUll  
  165.     LogMessage("%s #DEBUG: On configs executed", PLUGIN_TAG);  
  166.     #endif
  167.     End_Timer(false);
  168. }
  169.  
  170. public Action: Event_WitchSpawned(Handle:event, const String:name[], bool:dontBroadcast) // version 1.3
  171. {
  172.     if (!PluginWitch && !NotRemoveDirectorWitch)
  173.     {
  174.         new WitchID = GetEventInt(event, "witchid");
  175.         if (IsValidEdict(WitchID))
  176.         {
  177.             AcceptEntityInput(WitchID, "Kill"); //RemoveEdict(WitchID); //Version 1.5
  178.             #if DEBUGFUll
  179.             LogMessage("%s #DEBUG: Remove director's witch ID = %i; witch = %d, max count witch = %d", PLUGIN_TAG, WitchID, countWitch, maxCountWitchInRound); 
  180.             #endif
  181.         }
  182.         else
  183.         {          
  184.             #if DEBUGFUll
  185.             LogMessage("%s #DEBUG: Don't remove director's witch ID = %i because not an edict index (witch ID) is valid", PLUGIN_TAG, WitchID);
  186.             #endif
  187.         }
  188.     }
  189.     else
  190.     {
  191.         countWitch++;  
  192.         #if DEBUG
  193.         LogMessage("%s #DEBUG: Witch spawned; witch = %d, max count witch = %d", PLUGIN_TAG, countWitch, maxCountWitchInRound);
  194.         #endif
  195.     }
  196. }
  197.  
  198. public Action: Event_PlayerLeftStartArea(Handle:event, const String:name[], bool:dontBroadcast)
  199. {
  200.     if (!runTimer)
  201.     {
  202.         #if DEBUGFUll  
  203.         LogMessage("%s #DEBUG: Player left start area", PLUGIN_TAG);   
  204.         #endif
  205.         First_Start_Timer();
  206.     }
  207. }
  208.  
  209. public Action: Event_DoorOpen(Handle:event, const String:name[], bool:dontBroadcast)
  210. {
  211.     if (!runTimer)
  212.     {
  213.         if (GetEventBool(event, "checkpoint") && roundStart)
  214.         {
  215.             #if DEBUGFUll  
  216.             LogMessage("%s #DEBUG: Door open", PLUGIN_TAG);
  217.             #endif
  218.             First_Start_Timer();
  219.         }
  220.     }
  221. }
  222.  
  223. public Action: Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) // Version 1.2
  224. {
  225.     if (L4DVersion)
  226.     {
  227.         if (!IsModelPrecached("models/infected/witch.mdl")) PrecacheModel("models/infected/witch.mdl");
  228.         if (!IsModelPrecached("models/infected/witch_bride.mdl")) PrecacheModel("models/infected/witch_bride.mdl");
  229.     }
  230.     #if DEBUGFUll  
  231.     LogMessage("%s #DEBUG: End timer", PLUGIN_TAG);
  232.     #endif
  233.     End_Timer(false);
  234.     roundStart = true;
  235. }
  236.  
  237. public Action: Event_FinaleStart(Handle:event, const String:name[], bool:dontBroadcast) // Version 1.3
  238. {
  239.     if (!SpawnAfterFinaleStart)
  240.     {
  241.         #if DEBUGFUll  
  242.         LogMessage("%s #DEBUG: End timer (finale start)", PLUGIN_TAG); 
  243.         #endif
  244.         End_Timer(false);
  245.     }
  246. }
  247.  
  248. public First_Start_Timer()
  249. {      
  250.     runTimer = true;
  251.     roundStart = false;
  252.     countWitch = 0;
  253.     #if DEBUGFUll
  254.     LogMessage("%s #DEBUG: First_Start_Timer; leaved safe room; runTimer = %d", PLUGIN_TAG, runTimer); 
  255.     #endif
  256.     Start_Timer();
  257. }
  258.  
  259. public Start_Timer()
  260. {  
  261.     new Float: WitchSpawnTime = GetRandomFloat(WitchTimeMin, WitchTimeMax);
  262.     #if DEBUG
  263.     LogMessage("%s #DEBUG: Start_Timer; witch spawn time = %f", PLUGIN_TAG, WitchSpawnTime);           
  264.     #endif
  265.     Witches_SpawnTimer = CreateTimer(WitchSpawnTime, SpawnAWitch, _);
  266. }
  267.  
  268. public End_Timer(const bool: isClosedHandle) // version 1.1
  269. {
  270.     if (runTimer)
  271.     {
  272.         if (!isClosedHandle) CloseHandle(Witches_SpawnTimer);              
  273.         countWitch = 0;    
  274.         runTimer = false;
  275.         PluginWitch = false; // version 1.3
  276.         #if DEBUGFUll      
  277.         LogMessage("%s #DEBUG: End_Timer; close handle; runTimer = %d", PLUGIN_TAG, runTimer); 
  278.         #endif
  279.     }
  280. }
  281.  
  282. stock GetAnyClient()
  283. {
  284.     new i;
  285.     for (i = 1; i <= GetMaxClients(); i++)
  286.         if (IsClientConnected(i) && IsClientInGame(i) && (!IsFakeClient(i)))
  287.             return i;
  288.     return 0;
  289. }
  290.  
  291. stock FindEntityByClassname2(startEnt, const String:classname[]) // version 1.4
  292. {
  293.     while (startEnt < GetMaxEntities() && !IsValidEntity(startEnt)) startEnt++;
  294.     return FindEntityByClassname(startEnt, classname);
  295. }
  296.  
  297. public GetCountAliveWitches() // version 1.1 & version 1.4
  298. {  
  299.     new countWitchAlive = 0;   
  300.     new index = -1;
  301.     while ((index = FindEntityByClassname2(index, "witch")) != -1)
  302.     {      
  303.         countWitchAlive++;
  304.         #if DEBUGFUll
  305.         LogMessage("%s #DEBUG: witch ID = %i (alive witches = %i)", PLUGIN_TAG, index, countWitchAlive);
  306.         #endif 
  307.         if (WitchDistance > 0)
  308.         {
  309.             decl Float: WitchPos[3], Float: PlayerPos[3];
  310.             GetEntPropVector(index, Prop_Send, "m_vecOrigin", WitchPos);
  311.             new k = 0;
  312.             new maxRealClients = 0;
  313.             for (new i = 1; i <= GetMaxClients(); i++)
  314.                 if (IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2)
  315.                 {
  316.                     maxRealClients++;
  317.                     GetClientAbsOrigin(i, PlayerPos);
  318.                     new Float: distance = GetVectorDistance(WitchPos, PlayerPos);
  319.                     #if DEBUGFUll
  320.                     LogMessage("%s #DEBUG: distance from the witch = %f; max distance = %f", PLUGIN_TAG, distance, WitchDistance);
  321.                     #endif
  322.                     if (distance > WitchDistance) k++;                                         
  323.                 }
  324.             if (k == maxRealClients)
  325.             {
  326.                 AcceptEntityInput(index, "Kill"); //RemoveEdict(index); //Version 1.5
  327.                 countWitchAlive--;                 
  328.             }
  329.         }
  330.     }  
  331.     #if DEBUGFUll
  332.     LogMessage("%s #DEBUG: Alive witches = %d, max count alive witches = %d", PLUGIN_TAG, countWitchAlive, maxCountWitchAlive);    
  333.     #endif
  334.     return countWitchAlive;
  335. }
  336.  
  337. stock SpawnCommand(client, String:command[], String:arguments[] = "") // version 1.1
  338. {
  339.     if (client)
  340.     {      
  341.         new flags = GetCommandFlags(command);
  342.         SetCommandFlags(command, flags & ~FCVAR_CHEAT);
  343.         FakeClientCommand(client, "%s %s", command, arguments);
  344.         SetCommandFlags(command, flags);
  345.     }
  346. }
  347.  
  348. public Action: SpawnAWitch(Handle:timer)
  349. {  
  350.     if (runTimer)
  351.     {      
  352.         if (maxCountWitchInRound > 0 && countWitch >= maxCountWitchInRound)
  353.         {
  354.             #if DEBUGFUll
  355.             LogMessage("%s #DEBUG: Witch = %d, max count witch = %d; End_Timer()", PLUGIN_TAG, countWitch, maxCountWitchInRound);      
  356.             #endif
  357.             End_Timer(true);
  358.             return;
  359.         }
  360.         if (maxCountWitchAlive > 0 && countWitch >= maxCountWitchAlive && GetCountAliveWitches() >= maxCountWitchAlive)
  361.         {
  362.             Start_Timer();
  363.             return;
  364.         }
  365.         new anyclient = GetAnyClient()
  366.         if (anyclient == 0)
  367.         {
  368.             anyclient = CreateFakeClient("Bot");
  369.             if (anyclient == 0)
  370.             {
  371.                 #if DEBUGFUll
  372.                 LogMessage("%s #DEBUG: anyclient = 0", PLUGIN_TAG);    
  373.                 #endif
  374.                 Start_Timer();
  375.                 return;
  376.             }
  377.         }  
  378.         PluginWitch = true; // version 1.3
  379.         SpawnCommand(anyclient, "z_spawn", "witch auto");
  380.         #if DEBUGFUll
  381.         LogMessage("%s #DEBUG: plugin's witch", PLUGIN_TAG);       
  382.         #endif
  383.         PluginWitch = false; // version 1.3
  384.         Start_Timer();
  385.     }
  386.     else return;
  387. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement