From 559d88ac7a40f308bd76518e7210159731ec6065 Mon Sep 17 00:00:00 2001 From: Jackz Date: Thu, 5 Nov 2020 23:06:44 -0600 Subject: [PATCH] Add sm_ai_remove_far & add wpn support for ai_holdout --- scripting/include/jutils.inc | 40 ++++++++++++++++++--- scripting/l4d2_ai_minigun.sp | 68 +++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 16 deletions(-) diff --git a/scripting/include/jutils.inc b/scripting/include/jutils.inc index a1e6716..409bd27 100644 --- a/scripting/include/jutils.inc +++ b/scripting/include/jutils.inc @@ -66,14 +66,46 @@ stock void ShowDelayedHintToAll(const char[] format, any ...) { } hintInt++; } +stock int GetSurvivorId(const char str[16]) { + int possibleNumber = StringToInt(str, 10); + if(strlen(str) == 1) { + if(possibleNumber <= 7 && possibleNumber >= 0) { + return possibleNumber; + } + }else if(possibleNumber == 0) { + if(StrEqual(str, "nick", false)) return 0; + else if(StrEqual(str, "rochelle", false)) return 1; + else if(StrEqual(str, "coach", false)) return 2; + else if(StrEqual(str, "ellis", false)) return 3; + else if(StrEqual(str, "bill", false)) return 4; + else if(StrEqual(str, "zoey", false)) return 5; + else if(StrEqual(str, "francis", false)) return 6; + else if(StrEqual(str, "louis", false)) return 7; + } + return -1; +} +stock bool GetSurvivorModel(int character, char[] model, int modelStrSize) { + switch(character) { + case 0: strcopy(model, modelStrSize, MODEL_NICK); + case 1: strcopy(model, modelStrSize, MODEL_ROCHELLE); + case 2: strcopy(model, modelStrSize, MODEL_COACH); + case 3: strcopy(model, modelStrSize, MODEL_ELLIS); + case 4: strcopy(model, modelStrSize, MODEL_BILL); + case 5: strcopy(model, modelStrSize, MODEL_ZOEY); + case 6: strcopy(model, modelStrSize, MODEL_FRANCIS); + case 7: strcopy(model, modelStrSize, MODEL_LOUIS); + default: return false; + } + return true; +} stock bool FindSurvivorModel(const char str[16], char[] model, int modelStrSize) { int possibleNumber = StringToInt(str, 10); - if(sizeof(str) == 1 && possibleNumber <= 7 && possibleNumber >= 0) { + if(strlen(str) == 1 && possibleNumber <= 7 && possibleNumber >= 0) { switch(possibleNumber) { case 0: strcopy(model, modelStrSize, MODEL_NICK); - case 3: strcopy(model, modelStrSize, MODEL_ELLIS); - case 2: strcopy(model, modelStrSize, MODEL_COACH); case 1: strcopy(model, modelStrSize, MODEL_ROCHELLE); + case 2: strcopy(model, modelStrSize, MODEL_COACH); + case 3: strcopy(model, modelStrSize, MODEL_ELLIS); case 4: strcopy(model, modelStrSize, MODEL_BILL); case 5: strcopy(model, modelStrSize, MODEL_ZOEY); case 6: strcopy(model, modelStrSize, MODEL_FRANCIS); @@ -124,7 +156,7 @@ stock bool GetGround(int client, float[3] vPos, float[3] vAng) { GetClientAbsAngles(client, vAng); return true; } - +//Taken from https://forums.alliedmods.net/showthread.php?p=1741099 stock bool SpawnMinigun(const float vPos[3], const float vAng[3]) { float vDir[3], newPos[3]; GetAngleVectors(vAng, vDir, NULL_VECTOR, NULL_VECTOR); diff --git a/scripting/l4d2_ai_minigun.sp b/scripting/l4d2_ai_minigun.sp index d8d10b5..7d246a7 100644 --- a/scripting/l4d2_ai_minigun.sp +++ b/scripting/l4d2_ai_minigun.sp @@ -34,6 +34,8 @@ public void OnPluginStart() { RegAdminCmd("sm_ai_holdout", Command_SpawnHoldoutBot, ADMFLAG_ROOT); RegAdminCmd("sm_ai_minigun", Command_SpawnMinigunBot, ADMFLAG_ROOT); + RegAdminCmd("sm_ai_remove_far", Command_RemoveFar, ADMFLAG_ROOT); + //todo: add cmd to remove any that are out of range? possibly only ones you past } public void OnMapStart() { @@ -52,6 +54,38 @@ public void OnClientPutInServer(int client) { } } +public Action Command_RemoveFar(int client, int args) { + for(int bot = 1; bot < MaxClients; bot++) { + if(IsClientConnected(bot) && IsClientInGame(bot) && GetClientTeam(bot) == 4 && IsFakeClient(bot)) { + char name[64]; + GetClientName(bot, name, sizeof(name)); + //Only work on Bot's + if(StrContains(name, "HoldoutBot", true) || StrContains(name, "MinigunBot", true)) { + float botPos[3]; + GetClientAbsOrigin(bot, botPos); + bool isClose = false; + //Loop all players, if distance is less than 750, break out of loop + for(int i = 1; i < MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && !IsFakeClient(i)) { + float playerPos[3]; + GetClientAbsOrigin(i, playerPos); + + float distance = GetVectorDistance(playerPos, botPos); + if(distance <= 750) { + isClose = true; + break; + } + } + } + if(!isClose) { + KickClient(bot); + ReplyToCommand(client, "Removed %N", bot); + } + } + } + } +} + public Action Command_SpawnMinigunBot(int client, int args) { char arg1[16]; if(args > 0) { @@ -90,12 +124,16 @@ public Action Command_SpawnHoldoutBot(int client, int args) { if(args > 0) { GetCmdArg(1, arg1, sizeof(arg1)); char model[64]; - if(!FindSurvivorModel(arg1, model, sizeof(model))) { + int survivorId = GetSurvivorId(arg1); + if(survivorId == -1) { + ReplyToCommand(client, "That is not a valid survivor."); + return Plugin_Handled; + } + if(!GetSurvivorModel(survivorId, model, sizeof(model))) { LogError("Could not find a survivor model."); ReplyToCommand(client, "Could not find that survivor."); return Plugin_Handled; } - //get ground: float vPos[3], vAng[3]; if(!GetGround(client, vPos, vAng)) { @@ -106,15 +144,22 @@ public Action Command_SpawnHoldoutBot(int client, int args) { //make sure spawns a little above vPos[2] += 1.0; + char wpn[64]; + if(args > 1) { + GetCmdArg(2, wpn, sizeof(wpn)); + }else { + wpn = "rifle_ak47"; + } + int survivor = SpawnSurvivor(vPos, vAng, model, false); if(survivor > -1) { - GiveClientWeapon(survivor, "rifle_ak47", true); - SetEntProp(survivor, Prop_Send, "m_survivorCharacter", GetSurvivorType(model)); + GiveClientWeapon(survivor, wpn, true); + SetEntProp(survivor, Prop_Send, "m_survivorCharacter", survivorId); }else{ ReplyToCommand(client, "Failed to spawn survivor."); } }else{ - ReplyToCommand(client, "Usage: sm_spawn_minigun_bot <4=Bill, 5=Zoey, 6=Francis, 7=Louis>"); + ReplyToCommand(client, "Usage: sm_spawn_minigun_bot <4=Bill, 5=Zoey, 6=Francis, 7=Louis> [weapon]"); } return Plugin_Handled; } @@ -125,17 +170,16 @@ public Action Command_SpawnHoldoutBot(int client, int args) { // /////////////////////////////////////////// - +//Taken from https://forums.alliedmods.net/showthread.php?p=1741099 and modified slightly (and documented) stock int SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] model, bool spawn_minigun) { int entity = CreateEntityByName("info_l4d1_survivor_spawn"); if( entity == -1 ) { LogError("Failed to create \"info_l4d1_survivor_spawn\""); return -1; } - //set character type (7 = Louis) - DispatchKeyValue(entity, "character", "7"); //on spawn, to kill spawner //AcceptEntityInput(entity, "AddOutput"); + DispatchKeyValue(entity, "character", "7"); AcceptEntityInput(entity, "Kill"); //teleport spawner to valid spot & spawn it @@ -147,6 +191,7 @@ stock int SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] m AvoidCharacter(7, true); AcceptEntityInput(entity, "SpawnSurvivor"); AvoidCharacter(7, false); + //remove reference to last spawn id int bot_user_id = g_iLastSpawnClient, bot_client_id; @@ -167,8 +212,7 @@ stock int SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] m return -1; } TeleportEntity(bot_client_id, vPos, NULL_VECTOR, NULL_VECTOR); - SetEntityModel(bot_client_id, model); - CreateTimer(1.5, TimerMove, bot_user_id); + SetEntityModel(bot_client_id, model); //set entity model to custom survivor model //probably return user_id? return bot_client_id; } @@ -191,8 +235,8 @@ void AvoidCharacter(int type, bool avoid) { { case 4: set = 3; // Bill case 5: set = 2; // Zoey - case 7: set = 1; // Francis - case 6: set = 0; // Louis + case 6: set = 1; // Francis + case 7: set = 0; // Louis default: return; } SetEntProp(i, Prop_Send, "m_survivorCharacter", set);