mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-08 19:03:21 +00:00
Improved to work with multiple bots
This commit is contained in:
parent
ba5da00525
commit
63107d13f5
2 changed files with 124 additions and 21 deletions
Binary file not shown.
|
@ -1,24 +1,25 @@
|
||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <sdktools>
|
#include <sdktools>
|
||||||
#define PLUGIN_VERSION "1.4"
|
#define PLUGIN_VERSION "1.5"
|
||||||
#pragma newdecls required
|
#pragma newdecls required
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
|
|
||||||
static bool bEscapeReady = false;
|
static bool bEscapeReady = false;
|
||||||
static int TankClient;
|
static int TankClient, iAliveTanks;
|
||||||
//static ConVar hTankDangerDistance;
|
static bool bIsTank[MAXPLAYERS+1];
|
||||||
|
|
||||||
public Plugin myinfo =
|
public Plugin myinfo =
|
||||||
{
|
{
|
||||||
name = "Fly You Fools",
|
name = "Fly You Fools",
|
||||||
author = "ConnerRia & Jackzmc",
|
author = "ConnerRia & Jackzmc",
|
||||||
description = "Survivor bots will retreat from tank. ",
|
description = "Survivor bots will retreat from tank. Improved version.",
|
||||||
version = PLUGIN_VERSION,
|
version = PLUGIN_VERSION,
|
||||||
url = "N/A"
|
url = "N/A"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnPluginStart()
|
public void OnPluginStart()
|
||||||
{
|
{
|
||||||
EngineVersion g_Game = GetEngineVersion();
|
EngineVersion g_Game = GetEngineVersion();
|
||||||
|
@ -28,7 +29,6 @@ public void OnPluginStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateConVar("FlyYouFools_Version", PLUGIN_VERSION, "FlyYouFools Version", FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_DONTRECORD);
|
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_PostNoCopy);
|
HookEvent("map_transition", Event_RoundStart, EventHookMode_PostNoCopy);
|
||||||
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
|
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
|
||||||
|
@ -36,40 +36,72 @@ public void OnPluginStart()
|
||||||
HookEvent("tank_killed", Event_RoundStart, EventHookMode_PostNoCopy);
|
HookEvent("tank_killed", Event_RoundStart, EventHookMode_PostNoCopy);
|
||||||
HookEvent("finale_vehicle_incoming", Event_FinaleArriving, EventHookMode_PostNoCopy);
|
HookEvent("finale_vehicle_incoming", Event_FinaleArriving, EventHookMode_PostNoCopy);
|
||||||
|
|
||||||
AutoExecConfig(true, "200IQBots_FlyYouFools");
|
//debug
|
||||||
|
HookEvent("player_hurt", Event_PlayerHurt);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnMapStart() {
|
public void OnMapStart() {
|
||||||
TankClient = -1;
|
resetPlugin();
|
||||||
bEscapeReady = false;
|
|
||||||
|
|
||||||
FindExistingTank();
|
FindExistingTank();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
|
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
|
||||||
TankClient = -1;
|
resetPlugin();
|
||||||
bEscapeReady = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Event_TankSpawn(Event event, const char[] name, bool dontBroadcast) {
|
public void Event_TankSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
iAliveTanks++;
|
||||||
|
int userID = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||||
|
bIsTank[userID] = true;
|
||||||
|
if(iAliveTanks < 1) {
|
||||||
TankClient = GetClientOfUserId(GetEventInt(event, "userid"));
|
TankClient = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||||
CreateTimer(0.1, BotControlTimer, _, TIMER_REPEAT);
|
CreateTimer(0.1, BotControlTimerV2, _, TIMER_REPEAT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void Event_FinaleArriving(Event event, const char[] name, bool dontBroadcast) {
|
public void Event_FinaleArriving(Event event, const char[] name, bool dontBroadcast) {
|
||||||
bEscapeReady = true;
|
bEscapeReady = true;
|
||||||
}
|
}
|
||||||
|
public void Event_PlayerHurt(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
int targetPlayer = GetClientOfUserId(event.GetInt("userid"));
|
||||||
|
int attacker = GetClientOfUserId(event.GetInt("attacker"));
|
||||||
|
char attackerName[16];
|
||||||
|
GetClientName(attacker, attackerName, sizeof(attackerName));
|
||||||
|
if(StrContains(attackerName, "Tank", true) > -1) {
|
||||||
|
PrintToChatAll("%N (%d) was hit by tank %s (%d)", targetPlayer, targetPlayer, attackerName, attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Logic overview:
|
||||||
|
1. Check If there is a tank (will be last spawned tank)
|
||||||
|
2. Check that the tank has a target (not waiting)
|
||||||
|
3. Loop all valid players (bots, alive, survivors)
|
||||||
|
4. If they are being targetted by tank OR health < 40:
|
||||||
|
always run away
|
||||||
|
5. Else if less than 200 units away:
|
||||||
|
run away
|
||||||
|
else:
|
||||||
|
attack tank
|
||||||
|
*/
|
||||||
public Action BotControlTimer(Handle timer)
|
public Action BotControlTimer(Handle timer)
|
||||||
{
|
{
|
||||||
//remove timer once tank no longer exists, is dead, or finale escape vehicle arrived
|
//remove timer once tank no longer exists, is dead, or finale escape vehicle arrived
|
||||||
if(bEscapeReady || TankClient == -1 || !IsClientInGame(TankClient) || !IsPlayerAlive(TankClient)) {
|
//temp improvement: disable if more than one tank.
|
||||||
//incase any other tanks are available
|
|
||||||
FindExistingTank();
|
if(bEscapeReady || iAliveTanks == 0) {
|
||||||
|
//Check if there is any existing bots, if escape NOT ready
|
||||||
|
if(!bEscapeReady) FindExistingTank();
|
||||||
return Plugin_Stop;
|
return Plugin_Stop;
|
||||||
}
|
}
|
||||||
//Once an AI tank is awakened, m_lookatPlayer is set to a player ID
|
//Once an AI tank is awakened, m_lookatPlayer is set to a player ID
|
||||||
//Possible props: m_lookatPlayer, m_zombieState (if 1), m_hasVisibleThreats
|
//Possible props: m_lookatPlayer, m_zombieState (if 1), m_hasVisibleThreats
|
||||||
int tank_target = GetEntPropEnt(TankClient, Prop_Send, "m_lookatPlayer", 0);
|
int tank_target = GetEntPropEnt(TankClient, Prop_Send, "m_lookatPlayer", 0);
|
||||||
|
if(tank_target > -1) {
|
||||||
|
ShowHintToAll("TankClient#: %d | AliveTanks: %d | TankTarget: %N", TankClient, iAliveTanks, tank_target);
|
||||||
|
}else{
|
||||||
|
ShowHintToAll("TankClient#: %d | AliveTanks: %d | TankTarget: n/a", TankClient, iAliveTanks);
|
||||||
|
}
|
||||||
if(tank_target > -1) {
|
if(tank_target > -1) {
|
||||||
//grab tank position outside loop, only calculate bot
|
//grab tank position outside loop, only calculate bot
|
||||||
float TankPosition[3];
|
float TankPosition[3];
|
||||||
|
@ -87,7 +119,7 @@ public Action BotControlTimer(Handle timer)
|
||||||
|
|
||||||
float BotPosition[3];
|
float BotPosition[3];
|
||||||
GetClientAbsOrigin(i, BotPosition);
|
GetClientAbsOrigin(i, BotPosition);
|
||||||
|
//Compare the distance between tank and the survivor bot, attack if far, run if too close.
|
||||||
float distance = GetVectorDistance(BotPosition, TankPosition);
|
float distance = GetVectorDistance(BotPosition, TankPosition);
|
||||||
if(distance < 200) {
|
if(distance < 200) {
|
||||||
L4D2_RunScript("CommandABot({cmd=2,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(TankClient));
|
L4D2_RunScript("CommandABot({cmd=2,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(TankClient));
|
||||||
|
@ -102,17 +134,88 @@ public Action BotControlTimer(Handle timer)
|
||||||
}
|
}
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
New logic overview:
|
||||||
|
Either: Loop all tanks, check for any survivors.
|
||||||
|
Or: Loop any survivors, check for a nearby tank?
|
||||||
|
|
||||||
|
*/
|
||||||
|
public Action BotControlTimerV2(Handle timer)
|
||||||
|
{
|
||||||
|
//remove timer once tank no longer exists, is dead, or finale escape vehicle arrived
|
||||||
|
if(bEscapeReady || TankClient == -1 || !IsClientInGame(TankClient) || !IsPlayerAlive(TankClient)) {
|
||||||
|
//Check if there is any existing bots, if escape NOT ready
|
||||||
|
if(!bEscapeReady) FindExistingTank();
|
||||||
|
return Plugin_Stop;
|
||||||
|
}
|
||||||
|
if(iAliveTanks == 0) return Plugin_Continue;
|
||||||
|
//Loop all players, finding survivors. (survivor team, bots, not tank.)
|
||||||
|
for (int i = 1; i <= MaxClients; i++) {
|
||||||
|
if (IsClientInGame(i) && IsPlayerAlive(i) && IsFakeClient(i) && !bIsTank[i] && GetClientTeam(i) == 2) {
|
||||||
|
//Grab health of bot and current position
|
||||||
|
int botHealth = GetClientHealth(i);
|
||||||
|
float BotPosition[3];
|
||||||
|
GetClientAbsOrigin(i, BotPosition);
|
||||||
|
|
||||||
|
float smallestDistance = 0.0;
|
||||||
|
int closestTank = -1;
|
||||||
|
//Loop all players, finding tanks (alive, bot, tank)
|
||||||
|
for(int tankID = 1; tankID <= MaxClients; tankID++) {
|
||||||
|
if (IsClientInGame(tankID) && IsPlayerAlive(tankID) && IsFakeClient(tankID) && bIsTank[tankID]) {
|
||||||
|
//Check if tank has a target. tank_target will be -1 if not activated
|
||||||
|
int tank_target = GetEntPropEnt(tankID, Prop_Send, "m_lookatPlayer", 0);
|
||||||
|
if(tank_target > -1) {
|
||||||
|
|
||||||
|
//Fetch the tank's position
|
||||||
|
float TankPosition[3];
|
||||||
|
GetClientAbsOrigin(tankID, TankPosition);
|
||||||
|
//Get distance to survivor, and compare to get closest tank
|
||||||
|
float distanceFromSurvivor = GetVectorDistance(BotPosition, TankPosition);
|
||||||
|
PrintHintTextToAll("[Survivor: %N (%d)] | Tank: %d | Distance: %f", i, i, tankID, distanceFromSurvivor);
|
||||||
|
if(distanceFromSurvivor <= 1000 && smallestDistance > distanceFromSurvivor || smallestDistance == 0.0) {
|
||||||
|
smallestDistance = distanceFromSurvivor;
|
||||||
|
closestTank = tankID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If the closest tank exists (-1 means no tank.) and is close, avoid.
|
||||||
|
if(closestTank > -1 && smallestDistance <= 1000) {
|
||||||
|
if(smallestDistance <= 300) {
|
||||||
|
L4D2_RunScript("CommandABot({cmd=2,bot=GetPlayerFromUserID(%i),target=GetPlayerFromUserID(%i)})", GetClientUserId(i), GetClientUserId(closestTank));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
L4D2_RunScript("CommandABot({cmd=3,bot=GetPlayerFromUserID(%i)", GetClientUserId(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
void resetPlugin() {
|
||||||
|
TankClient = -1;
|
||||||
|
bEscapeReady = false;
|
||||||
|
iAliveTanks = 0;
|
||||||
|
for(int i = 0; i < sizeof(bIsTank); i++) {
|
||||||
|
bIsTank[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void FindExistingTank() {
|
public void FindExistingTank() {
|
||||||
|
//Loop all valid clients, check if they a BOT and an infected. Check for a name that contains "Tank"
|
||||||
|
iAliveTanks = 0;
|
||||||
for (int i = 1; i < MaxClients+1 ;i++) {
|
for (int i = 1; i < MaxClients+1 ;i++) {
|
||||||
if(IsClientInGame(i) && IsFakeClient(i) && IsPlayerAlive(i) && GetClientTeam(i) == 3) {
|
if(IsClientInGame(i) && IsFakeClient(i) && IsPlayerAlive(i) && GetClientTeam(i) == 3) {
|
||||||
char name[16];
|
char name[16];
|
||||||
GetClientName(i, name, sizeof(name));
|
GetClientName(i, name, sizeof(name));
|
||||||
if(StrContains(name, "Tank", true) > -1) {
|
if(StrContains(name, "Tank", true) > -1) {
|
||||||
|
bIsTank[i] = true;
|
||||||
|
PrintToChatAll("Found existing tank: %N (%i)", i, i);
|
||||||
|
if(iAliveTanks == 0) {
|
||||||
TankClient = i;
|
TankClient = i;
|
||||||
CreateTimer(0.1, BotControlTimer, _, TIMER_REPEAT);
|
CreateTimer(0.1, BotControlTimerV2, _, TIMER_REPEAT);
|
||||||
break;
|
}
|
||||||
|
iAliveTanks++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue