mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-08 08:03:21 +00:00
Added L4D2Tools and 200IQBots_FlyYouFools
This commit is contained in:
parent
aeb263064d
commit
7ef2a1b3cd
5 changed files with 331 additions and 9 deletions
BIN
200IQBots_FlyYouFools.smx
Normal file
BIN
200IQBots_FlyYouFools.smx
Normal file
Binary file not shown.
172
200IQBots_FlyYouFools.sp
Normal file
172
200IQBots_FlyYouFools.sp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#pragma semicolon 1
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#define PLUGIN_VERSION "1.4"
|
||||||
|
|
||||||
|
static bool bEscapeReady = false;
|
||||||
|
static int TankClient;
|
||||||
|
//static ConVar hTankDangerDistance;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "Fly You Fools",
|
||||||
|
author = "ConnerRia & Jackzmc",
|
||||||
|
description = "Survivor bots will retreat from tank. ",
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = "N/A"
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnPluginStart()
|
||||||
|
{
|
||||||
|
EngineVersion g_Game = GetEngineVersion();
|
||||||
|
if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2)
|
||||||
|
{
|
||||||
|
SetFailState("Plugin supports Left 4 Dead series only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateConVar("FlyYouFools_Version", PLUGIN_VERSION, "FlyYouFools Version", FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_DONTRECORD);
|
||||||
|
//hTankDangerDistance = CreateConVar("200IQBots_TankDangerRange", "800.0", "The range by which survivors bots will detect the presence of tank and retreat. ", FCVAR_NOTIFY|FCVAR_REPLICATED);
|
||||||
|
|
||||||
|
HookEvent("map_transition", Event_RoundStart, EventHookMode_Pre);
|
||||||
|
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
|
||||||
|
HookEvent("tank_spawn", Event_TankSpawn);
|
||||||
|
HookEvent("tank_killed", Event_RoundStart);
|
||||||
|
HookEvent("finale_vehicle_incoming", Event_FinaleArriving);
|
||||||
|
|
||||||
|
AutoExecConfig(true, "200IQBots_FlyYouFools");
|
||||||
|
|
||||||
|
FindExistingTank();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnMapStart() {
|
||||||
|
TankClient = -1;
|
||||||
|
bEscapeReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
TankClient = -1;
|
||||||
|
bEscapeReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_TankSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
TankClient = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||||
|
CreateTimer(0.1, BotControlTimer, _, TIMER_REPEAT);
|
||||||
|
}
|
||||||
|
public void Event_FinaleArriving(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
bEscapeReady = true;
|
||||||
|
}
|
||||||
|
public Action BotControlTimer(Handle timer)
|
||||||
|
{
|
||||||
|
//remove timer once tank no longer exists, is dead, or finale escape vehicle arrived
|
||||||
|
if(bEscapeReady || TankClient == -1 || !IsClientInGame(TankClient) || !IsPlayerAlive(TankClient)) {
|
||||||
|
return Plugin_Stop;
|
||||||
|
}
|
||||||
|
//Once an AI tank is awakened, m_lookatPlayer is set to a player ID
|
||||||
|
//Possible props: m_lookatPlayer, m_zombieState, m_hasVisibleThreats
|
||||||
|
int tank_target = GetEntPropEnt(TankClient, Prop_Send, "m_lookatPlayer", 0);
|
||||||
|
//bool hasVisibleThreats = GetEntProp(TankClient, Prop_Send, "m_hasVisibleThreats", 1) == 1;
|
||||||
|
//char targetted_name[64];
|
||||||
|
if(tank_target > -1) {
|
||||||
|
//debug shit:
|
||||||
|
//GetClientName(tank_target, targetted_name, sizeof(targetted_name));
|
||||||
|
//ShowHintToAll("tank_target: %d (%s) | visible threats: %b", tank_target, targetted_name, hasVisibleThreats);
|
||||||
|
for (new i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2 && IsFakeClient(i))
|
||||||
|
{
|
||||||
|
//If distance between bot and tank is less than 200IQBots_TankDangerRange's float value
|
||||||
|
//if not tank target, and tank != visible threats, then attack
|
||||||
|
if(tank_target == i) {
|
||||||
|
L4D2_RunScript("CommandABot({cmd=2,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(TankClient));
|
||||||
|
}else {
|
||||||
|
float TankPosition[3];
|
||||||
|
float BotPosition[3];
|
||||||
|
|
||||||
|
GetClientAbsOrigin(TankClient, TankPosition);
|
||||||
|
GetClientAbsOrigin(i, BotPosition);
|
||||||
|
|
||||||
|
float distance = GetVectorDistance(BotPosition, TankPosition);
|
||||||
|
if(distance < 200) {
|
||||||
|
L4D2_RunScript("CommandABot({cmd=2,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(TankClient));
|
||||||
|
//do not attack if super close.
|
||||||
|
} else {
|
||||||
|
L4D2_RunScript("CommandABot({cmd=0,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(TankClient));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void FindExistingTank() {
|
||||||
|
for (int i = 1; i < MaxClients+1 ;i++) {
|
||||||
|
if (!IsClientInGame(i)) continue;
|
||||||
|
if (!IsFakeClient(i)) continue;
|
||||||
|
char name[16];
|
||||||
|
GetClientName(i, name, sizeof(name));
|
||||||
|
|
||||||
|
if(StrContains(name,"Tank",true) > -1) {
|
||||||
|
PrintToServer("Found existing tank with id %d", i);
|
||||||
|
TankClient = i;
|
||||||
|
CreateTimer(0.1, BotControlTimer, _, TIMER_REPEAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Credits to Timocop for the stock :D
|
||||||
|
/**
|
||||||
|
* Runs a single line of vscript code.
|
||||||
|
* NOTE: Dont use the "script" console command, it starts a new instance and leaks memory. Use this instead!
|
||||||
|
*
|
||||||
|
* @param sCode The code to run.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
stock void L4D2_RunScript(const char[] sCode, any ...) {
|
||||||
|
static iScriptLogic = INVALID_ENT_REFERENCE;
|
||||||
|
if(iScriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(iScriptLogic)) {
|
||||||
|
iScriptLogic = EntIndexToEntRef(CreateEntityByName("logic_script"));
|
||||||
|
if(iScriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(iScriptLogic))
|
||||||
|
SetFailState("Could not create 'logic_script'");
|
||||||
|
|
||||||
|
DispatchSpawn(iScriptLogic);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char sBuffer[512];
|
||||||
|
VFormat(sBuffer, sizeof(sBuffer), sCode, 2);
|
||||||
|
|
||||||
|
SetVariantString(sBuffer);
|
||||||
|
AcceptEntityInput(iScriptLogic, "RunScriptCode");
|
||||||
|
}
|
||||||
|
stock void ShowHintToAll(const char[] format, any ...) {
|
||||||
|
char buffer[254];
|
||||||
|
VFormat(buffer, sizeof(buffer), format, 2);
|
||||||
|
static int hintInt = 0;
|
||||||
|
if(hintInt >= 9) {
|
||||||
|
PrintHintTextToAll("%s",buffer);
|
||||||
|
hintInt = 0;
|
||||||
|
}
|
||||||
|
hintInt++;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the classname of an item in a slot
|
||||||
|
*
|
||||||
|
* @param client The client to check inventory from
|
||||||
|
* @param slot The item slot index
|
||||||
|
* @param buffer The char[] buffer to set text to
|
||||||
|
* @param bufferSize The size of the buffer
|
||||||
|
* @return True if item, false if no item
|
||||||
|
*/
|
||||||
|
stock bool GetItemClassSlot(int client, int slot, char[] buffer, int bufferSize) {
|
||||||
|
int item = GetPlayerWeaponSlot(client, slot);
|
||||||
|
if(item > -1) {
|
||||||
|
GetEdictClassname(item, buffer, bufferSize);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
BIN
L4D2Tools.smx
Normal file
BIN
L4D2Tools.smx
Normal file
Binary file not shown.
142
L4D2Tools.sp
Normal file
142
L4D2Tools.sp
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
|
#define PLUGIN_NAME "Misc Tools"
|
||||||
|
#define PLUGIN_DESCRIPTION "Includes: Notice on laser use, Timer for gauntlet runs"
|
||||||
|
#define PLUGIN_AUTHOR "jackzmc"
|
||||||
|
#define PLUGIN_VERSION "1.0"
|
||||||
|
#define PLUGIN_URL ""
|
||||||
|
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
//#include <sdkhooks>
|
||||||
|
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
bool bLasersUsed[2048];
|
||||||
|
ConVar hLaserNotice, hFinaleTimer;
|
||||||
|
int iFinaleStartTime;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = PLUGIN_NAME,
|
||||||
|
author = PLUGIN_AUTHOR,
|
||||||
|
description = PLUGIN_DESCRIPTION,
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = PLUGIN_URL
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
EngineVersion g_Game = GetEngineVersion();
|
||||||
|
if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2)
|
||||||
|
{
|
||||||
|
SetFailState("This plugin is for L4D/L4D2 only.");
|
||||||
|
}
|
||||||
|
hLaserNotice = CreateConVar("sm_laser_use_notice", "1.0", "Enable notification of a laser box being used", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
|
hFinaleTimer = CreateConVar("sm_time_finale", "2.0", "Record the time it takes to complete finale. 0 -> OFF, 1 -> Gauntlets Only, 2 -> All finales", FCVAR_NONE, true, 0.0, true, 2.0);
|
||||||
|
|
||||||
|
HookEvent("player_use", Event_PlayerUse);
|
||||||
|
HookEvent("round_end", Event_RoundEnd);
|
||||||
|
HookEvent("gauntlet_finale_start", Event_GauntletStart);
|
||||||
|
HookEvent("finale_start", Event_FinaleStart);
|
||||||
|
HookEvent("finale_vehicle_leaving", Event_FinaleEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
//laserNotice
|
||||||
|
public void Event_PlayerUse(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
if(hLaserNotice.BoolValue) {
|
||||||
|
char player_name[32];
|
||||||
|
char entity_name[64];
|
||||||
|
int player_id = GetClientOfUserId(event.GetInt("userid"));
|
||||||
|
int target_id = event.GetInt("targetid");
|
||||||
|
|
||||||
|
GetClientName(player_id, player_name, sizeof(player_name));
|
||||||
|
GetEntityClassname(target_id, entity_name, sizeof(entity_name));
|
||||||
|
|
||||||
|
if(StrEqual(entity_name,"upgrade_laser_sight")) {
|
||||||
|
if(!bLasersUsed[target_id]) {
|
||||||
|
bLasersUsed[target_id] = true;
|
||||||
|
PrintToChatAll("%s picked up laser sights",player_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
for (int i = 1; i < sizeof(bLasersUsed) ;i++) {
|
||||||
|
bLasersUsed[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
//finaletimer
|
||||||
|
public void Event_GauntletStart(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
if(hFinaleTimer.IntValue > 0) {
|
||||||
|
iFinaleStartTime = GetTime();
|
||||||
|
PrintToChatAll("The finale timer has been started");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Event_FinaleStart(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
if(hFinaleTimer.IntValue == 2) {
|
||||||
|
iFinaleStartTime = GetTime();
|
||||||
|
PrintToChatAll("The finale timer has been started");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Event_FinaleEnd(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
if(hFinaleTimer.IntValue != 0) {
|
||||||
|
int difference = GetTime() - iFinaleStartTime;
|
||||||
|
iFinaleStartTime = 0;
|
||||||
|
|
||||||
|
char time[32];
|
||||||
|
FormatMs(difference, time, sizeof(time));
|
||||||
|
PrintToChatAll("Finale took %s to complete", time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Prints human readable duration from milliseconds
|
||||||
|
*
|
||||||
|
* @param ms The duration in milliseconds
|
||||||
|
* @param str The char array to use for text
|
||||||
|
* @param strSize The size of the string
|
||||||
|
*/
|
||||||
|
stock void FormatMs(int ms, char[] str, int strSize) {
|
||||||
|
int sec = ms / 1000;
|
||||||
|
int h = sec / 3600;
|
||||||
|
int m = (sec -(3600*h))/60;
|
||||||
|
int s = (sec -(3600*h)-(m*60));
|
||||||
|
if(h >= 1) {
|
||||||
|
Format(str, strSize, "%d hour, %d.%d minutes", h, m, s);
|
||||||
|
}else if(m >= 1) {
|
||||||
|
Format(str, strSize, "%d minutes and %d seconds", m, s);
|
||||||
|
}else {
|
||||||
|
float raw_seconds = float(ms) / 1000;
|
||||||
|
Format(str, strSize, "%0.1f seconds", raw_seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
stock void ShowHintToAll(const char[] format, any ...) {
|
||||||
|
char buffer[254];
|
||||||
|
VFormat(buffer, sizeof(buffer), format, 2);
|
||||||
|
static int hintInt = 0;
|
||||||
|
if(hintInt >= 10) {
|
||||||
|
PrintHintTextToAll("%s",buffer);
|
||||||
|
hintInt = 0;
|
||||||
|
}
|
||||||
|
hintInt++;
|
||||||
|
}
|
||||||
|
stock void ShowHint(int client, const char[] format, any ...) {
|
||||||
|
char buffer[254];
|
||||||
|
VFormat(buffer, sizeof(buffer), format, 2);
|
||||||
|
static int hintInt = 0;
|
||||||
|
if(hintInt >= 10) {
|
||||||
|
PrintHintText(client, "%s",buffer);
|
||||||
|
hintInt = 0;
|
||||||
|
}
|
||||||
|
hintInt++;
|
||||||
|
}
|
24
README.md
24
README.md
|
@ -5,17 +5,17 @@ All my sourcemod plugins... shitty probably
|
||||||
## Descriptions
|
## Descriptions
|
||||||
* `csgo-knifehp` - On knife kill, gives the player 100 HP (configurable)
|
* `csgo-knifehp` - On knife kill, gives the player 100 HP (configurable)
|
||||||
* **Convars:**
|
* **Convars:**
|
||||||
* `knifehp_enable` - Enable regaining health on knife kill
|
* `knifehp_enable <0/1>` - Enable regaining health on knife kill
|
||||||
* `knifehp_max_health` - Maximum health to set an attacker to
|
* `knifehp_max_health <#>` - Maximum health to set an attacker to
|
||||||
* `knifehp_amount` - Amount of health to give attacker
|
* `knifehp_amount <#>` - Amount of health to give attacker
|
||||||
* `l4d2-manual-director` - Probably going to be posted publicly sometime. allows you to spawn specials on cursor, or via director, forcefully, bypassing limits
|
* `l4d2-manual-director` - Probably going to be posted publicly sometime. allows you to spawn specials on cursor, or via director, forcefully, bypassing limits
|
||||||
* **Convars:**
|
* **Convars:**
|
||||||
* `manual_director_version|mandirector_version` - ... gets version
|
* `manual_director_version|mandirector_version` - ... gets version
|
||||||
* `mandirector_notify_spawn` - Should spawning specials notify on use?
|
* `mandirector_notify_spawn <1/0>` - Should spawning specials notify on use?
|
||||||
* `mandirector_announce_level` - Announcement types. 0 - None, 1 - Only bosses, 2 - Only specials+, 3 - Everything
|
* `mandirector_announce_level <0/1/2/3>` - Announcement types. 0 - None, 1 - Only bosses, 2 - Only specials+, 3 - Everything
|
||||||
* `mandirector_enable_tank` - Should tanks be allowed to be spawned?
|
* `mandirector_enable_tank <0/1>` - Should tanks be allowed to be spawned?
|
||||||
* `mandirector_enable_witch` - Should witches be allowed to be spawned?
|
* `mandirector_enable_witch <0/1>` - Should witches be allowed to be spawned?
|
||||||
* `mandirector_enable_mob` - Should mobs be allowed to be spawned
|
* `mandirector_enable_mob <0/1>` - Should mobs be allowed to be spawned
|
||||||
* **Commands:**
|
* **Commands:**
|
||||||
* `sm_spawnspecial` - Spawn a special via director
|
* `sm_spawnspecial` - Spawn a special via director
|
||||||
* `sm_forcespecial` - Force spawn a special via director, bypassing spawn limits
|
* `sm_forcespecial` - Force spawn a special via director, bypassing spawn limits
|
||||||
|
@ -37,3 +37,11 @@ All my sourcemod plugins... shitty probably
|
||||||
5,Louis,1,90,alive,0,,first_aid_kit,,Louis
|
5,Louis,1,90,alive,0,,first_aid_kit,,Louis
|
||||||
```
|
```
|
||||||
* `AutoWarpBot` - simple l4d2 plugin that will auto teleport everyone to checkpoint once all real players have reached the saferoom
|
* `AutoWarpBot` - simple l4d2 plugin that will auto teleport everyone to checkpoint once all real players have reached the saferoom
|
||||||
|
* `L4D2Tools` - A group of misc tools for l4d2. Including: Notify on lasers use, and a finale timer (gauntlets or all finales)
|
||||||
|
* **Convars:**
|
||||||
|
* `sm_laser_use_notice <1/0>` - Enable notification of a laser box being used
|
||||||
|
* `sm_time_finale <0/1/2>` - Record the time it takes to complete finale. 0 -> OFF, 1 -> Gauntlets Only, 2 -> All finales
|
||||||
|
* `200IQBots_FlyYouFools` - Updated version of ConnerRia's plugin. Improves bots avoidance of tanks.
|
||||||
|
* Change from original is updated source syntax, some optimizations/cleanup, and fixes such as bots avoiding tank that has not been activated, or not escaping in vehicle due to presence of tank
|
||||||
|
* **Convars:**
|
||||||
|
* `FlyYouFools_Version` - Prints the version of plugin
|
Loading…
Add table
Add a link
Reference in a new issue