Commander chat request

This commit is contained in:
RGreenlees 2024-02-28 21:31:27 +00:00 committed by pierow
parent 2fef7b83ff
commit 567f34cbf7
15 changed files with 736 additions and 47 deletions

View File

@ -300,14 +300,14 @@ private:
dtOffMeshConnection* m_offMeshConnections; dtOffMeshConnection* m_offMeshConnections;
dtOffMeshConnection* m_nextFreeOffMeshConnection; dtOffMeshConnection* m_nextFreeOffMeshConnection;
static const int MAX_REQUESTS = 256; static const int MAX_REQUESTS = 512;
ObstacleRequest m_reqs[MAX_REQUESTS]; ObstacleRequest m_reqs[MAX_REQUESTS];
int m_nreqs; int m_nreqs;
OffMeshRequest m_OffMeshReqs[MAX_REQUESTS]; OffMeshRequest m_OffMeshReqs[MAX_REQUESTS];
int m_nOffMeshReqs; int m_nOffMeshReqs;
static const int MAX_UPDATE = 256; static const int MAX_UPDATE = 512;
dtCompressedTileRef m_update[MAX_UPDATE]; dtCompressedTileRef m_update[MAX_UPDATE];
int m_nupdate; int m_nupdate;
}; };

View File

@ -145,6 +145,7 @@
#include "../mod/AvHAlienAbilityConstants.h" #include "../mod/AvHAlienAbilityConstants.h"
#include "../mod/AvHNetworkMessages.h" #include "../mod/AvHNetworkMessages.h"
#include "../mod/AvHNexusServer.h" #include "../mod/AvHNexusServer.h"
#include "../mod/AIPlayers/AvHAIPlayerManager.h"
#include "../game_shared/voice_gamemgr.h" #include "../game_shared/voice_gamemgr.h"
extern CVoiceGameMgr g_VoiceGameMgr; extern CVoiceGameMgr g_VoiceGameMgr;
@ -394,10 +395,14 @@ void Host_Say( edict_t *pEntity, int teamonly )
if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) ) if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) )
{ {
if ( CMD_ARGC() >= 2 ) int NumArgs = CMD_ARGC();
if (NumArgs >= 2 )
{ {
p = (char *)CMD_ARGS(); p = (char *)CMD_ARGS();
bool bMessageParsed = false;
if(GetGameRules()->GetIsTournamentMode() && !GetGameRules()->GetGameStarted()) if(GetGameRules()->GetIsTournamentMode() && !GetGameRules()->GetGameStarted())
{ {
if(!strcmp(CMD_ARGV(1), kReadyNotification)) if(!strcmp(CMD_ARGV(1), kReadyNotification))
@ -408,6 +413,8 @@ void Host_Say( edict_t *pEntity, int teamonly )
{ {
theTeam->SetIsReady(); theTeam->SetIsReady();
} }
bMessageParsed = true;
} }
else if (!strcmp(CMD_ARGV(1), kNotReadyNotification)) else if (!strcmp(CMD_ARGV(1), kNotReadyNotification))
{ {
@ -417,8 +424,33 @@ void Host_Say( edict_t *pEntity, int teamonly )
{ {
theTeam->SetIsReady(false); theTeam->SetIsReady(false);
} }
bMessageParsed = true;
} }
} }
// Check to see if we are asking the AI commander for something
if (!bMessageParsed)
{
char shortenedMsg[32];
char* msg = (char*)CMD_ARGV(1);
strncpy(shortenedMsg, msg, 31);
char* pch;
pch = strtok(shortenedMsg, " ");
if (!stricmp(pch, kAICommanderRequest))
{
pch = strtok(NULL, " \n");
if (pch != NULL)
{
AIMGR_ReceiveCommanderRequest((AvHTeamNumber)pEntity->v.team, pEntity, pch);
}
}
}
} }
else else
{ {

View File

@ -868,10 +868,50 @@ bool AICOMM_IsRequestValid(ai_commander_request* Request)
{ {
if (Request->bResponded) { return false; } if (Request->bResponded) { return false; }
// We tried and failed to respond 5 times, give up so we don't block the queue of people needing help
if (Request->ResponseAttempts > 5) { return false; }
edict_t* Requestor = Request->Requestor;
if (FNullEnt(Requestor) || !IsPlayerActiveInGame(Requestor)) { return false; }
AvHPlayer* PlayerRef = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(Requestor));
if (!PlayerRef) { return false; }
AvHTeamNumber RequestorTeam = PlayerRef->GetTeam();
switch (Request->RequestType) switch (Request->RequestType)
{ {
case COMMANDER_NEXTHEALTH: case COMMANDER_NEXTHEALTH:
return Request->Requestor->v.health < Request->Requestor->v.max_health; return Requestor->v.health < Requestor->v.max_health;
case BUILD_SHOTGUN:
return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_SHOTGUN)
&& !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_SHOTGUN, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false)
&& AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)) ;
case BUILD_WELDER:
return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_WELDER)
&& !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_WELDER, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false)
&& AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
case BUILD_HMG:
return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_HMG)
&& !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_HMG, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false)
&& AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_ADVARMOURY, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
case BUILD_MINES:
return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_MINES)
&& !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_MINES, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false)
&& AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
case BUILD_CAT:
return !IsPlayerBuffed(Requestor)
&& !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_CATALYSTS, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false)
&& AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, 0.0f)
&& AITAC_ResearchIsComplete(RequestorTeam, TECH_RESEARCH_CATALYSTS);
case BUILD_PHASEGATE:
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_PHASEGATE, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
case BUILD_TURRET_FACTORY:
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
case BUILD_ARMORY:
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
default: default:
return true; return true;
} }
@ -2215,6 +2255,10 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
NextRequest->bResponded = true; NextRequest->bResponded = true;
} }
} }
else
{
NextRequest->ResponseAttempts++;
}
return true; return true;
} }
@ -2280,6 +2324,10 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
NextRequest->bResponded = true; NextRequest->bResponded = true;
} }
} }
else
{
NextRequest->ResponseAttempts++;
}
return true; return true;
} }
@ -2298,6 +2346,276 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
NextRequest->bResponded = true; NextRequest->bResponded = true;
} }
if (NextRequest->RequestType == BUILD_CAT)
{
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(2.0f));
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_AMMO, DeployLocation);
if (bSuccess)
{
NextRequest->bResponded = true;
}
else
{
NextRequest->ResponseAttempts++;
}
return true;
}
if (NextRequest->RequestType == BUILD_WELDER)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kWelderCost)) { return false; }
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
return false;
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_WELDER, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_SHOTGUN)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kShotgunCost)) { return false; }
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
return false;
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_SHOTGUN, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_MINES)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kMineCost)) { return false; }
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
return false;
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_MINES, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_HMG)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kHMGCost)) { return false; }
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = STRUCTURE_MARINE_ADVARMOURY;
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
return false;
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_HMG, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_PHASEGATE)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kPhaseGateCost)) { return false; }
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_TURRET_FACTORY)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kTurretFactoryCost)) { return false; }
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
if (NextRequest->RequestType == BUILD_TURRET)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kSentryCost)) { return false; }
DeployableSearchFilter TFFilter;
TFFilter.DeployableTeam = CommanderTeam;
TFFilter.DeployableTypes = (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY);
TFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
TFFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
AvHAIBuildableStructure* NearestTF = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &TFFilter);
if (!NearestTF)
{
NextRequest->bResponded = true;
return false;
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestTF->Location, UTIL_MetresToGoldSrcUnits(5.0f));
if (vIsZero(DeployLocation))
{
DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestTF->Location, UTIL_MetresToGoldSrcUnits(5.0f));
}
if (vIsZero(DeployLocation))
{
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, DeployLocation);
NextRequest->ResponseAttempts++;
NextRequest->bResponded = bSuccess;
return true;
}
return false; return false;
} }
@ -2446,6 +2764,8 @@ bool AICOMM_ShouldCommanderLeaveChair(AvHAIPlayer* pBot)
if (AIMGR_GetNumHumanPlayersOnTeam(pBot->Player->GetTeam()) > 0) { return true;} if (AIMGR_GetNumHumanPlayersOnTeam(pBot->Player->GetTeam()) > 0) { return true;}
} }
if (IsPlayerCommander(pBot->Edict) && AIMGR_GetCommanderAllowedTime(pBot->Player->GetTeam()) > gpGlobals->time) { return true; }
int NumAliveMarinesInBase = AITAC_GetNumPlayersOfTeamInArea(pBot->Player->GetTeam(), AITAC_GetCommChairLocation(pBot->Player->GetTeam()), UTIL_MetresToGoldSrcUnits(30.0f), true, pBot->Edict, AVH_USER3_NONE); int NumAliveMarinesInBase = AITAC_GetNumPlayersOfTeamInArea(pBot->Player->GetTeam(), AITAC_GetCommChairLocation(pBot->Player->GetTeam()), UTIL_MetresToGoldSrcUnits(30.0f), true, pBot->Edict, AVH_USER3_NONE);
if (NumAliveMarinesInBase > 0) { return false; } if (NumAliveMarinesInBase > 0) { return false; }
@ -2674,4 +2994,64 @@ bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot)
return false; return false;
}
void AICOMM_ReceiveChatRequest(AvHAIPlayer* Commander, edict_t* Requestor, const char* Request)
{
AvHMessageID NewRequestType = MESSAGE_NULL;
if (!stricmp(Request, "shotgun") || !stricmp(Request, "sg") || !stricmp(Request, "shotty"))
{
NewRequestType = BUILD_SHOTGUN;
}
else if (!stricmp(Request, "welder"))
{
NewRequestType = BUILD_WELDER;
}
else if (!stricmp(Request, "HMG"))
{
NewRequestType = BUILD_HMG;
}
else if (!stricmp(Request, "mines"))
{
NewRequestType = BUILD_MINES;
}
else if (!stricmp(Request, "cat") || !stricmp(Request, "cats") || !stricmp(Request, "catalysts"))
{
NewRequestType = BUILD_CAT;
}
else if (!stricmp(Request, "pg") || !stricmp(Request, "phase") || !stricmp(Request, "phasegate"))
{
NewRequestType = BUILD_PHASEGATE;
}
else if (!stricmp(Request, "TF") || !stricmp(Request, "turretfactory"))
{
NewRequestType = BUILD_TURRET_FACTORY;
}
else if (!stricmp(Request, "turret"))
{
NewRequestType = BUILD_TURRET;
}
else if (!stricmp(Request, "armory") || !stricmp(Request, "armoury"))
{
NewRequestType = BUILD_ARMORY;
}
if (NewRequestType == MESSAGE_NULL) { return; }
ai_commander_request* ExistingRequest = AICOMM_GetExistingRequestForPlayer(Commander, Requestor);
ai_commander_request NewRequest;
ai_commander_request* RequestRef = (ExistingRequest) ? ExistingRequest : &NewRequest;
RequestRef->bNewRequest = true;
RequestRef->bResponded = false;
RequestRef->RequestTime = gpGlobals->time;
RequestRef->RequestType = NewRequestType;
RequestRef->Requestor = Requestor;
if (!ExistingRequest)
{
Commander->ActiveRequests.push_back(NewRequest);
}
} }

View File

@ -69,4 +69,6 @@ const AvHAIHiveDefinition* AICOMM_GetHiveSiegeOpportunityNearestLocation(AvHAIPl
bool AICOMM_ShouldCommanderPrioritiseNodes(AvHAIPlayer* pBot); bool AICOMM_ShouldCommanderPrioritiseNodes(AvHAIPlayer* pBot);
bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot); bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot);
void AICOMM_ReceiveChatRequest(AvHAIPlayer* Commander, edict_t* Requestor, const char* Request);
#endif // AVH_AI_COMMANDER_H #endif // AVH_AI_COMMANDER_H

View File

@ -677,6 +677,7 @@ typedef struct _AI_COMMANDER_REQUEST
AvHMessageID RequestType = MESSAGE_NULL; // What did they request? AvHMessageID RequestType = MESSAGE_NULL; // What did they request?
bool bResponded = false; // Have we already responded to this request? bool bResponded = false; // Have we already responded to this request?
float RequestTime = 0.0f; // When the request came in float RequestTime = 0.0f; // When the request came in
int ResponseAttempts = 0; // How many times have we tried to respond to this request?
} ai_commander_request; } ai_commander_request;
typedef struct AVH_AI_PLAYER typedef struct AVH_AI_PLAYER

View File

@ -2965,28 +2965,19 @@ void NewMove(AvHAIPlayer* pBot)
break; break;
case SAMPLE_POLYFLAGS_WALLCLIMB: case SAMPLE_POLYFLAGS_WALLCLIMB:
{ {
if (IsPlayerSkulk(pBot->Edict)) if (PlayerHasWeapon(pBot->Player, WEAPON_FADE_BLINK))
{ {
WallClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ); BlinkClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
} }
else else
{ {
BlinkClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ); WallClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
} }
} }
break; break;
case SAMPLE_POLYFLAGS_LADDER: case SAMPLE_POLYFLAGS_LADDER:
{ LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
if (IsPlayerSkulk(pBot->Edict)) break;
{
LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
}
else
{
LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
}
}
break;
case SAMPLE_POLYFLAGS_TEAM1PHASEGATE: case SAMPLE_POLYFLAGS_TEAM1PHASEGATE:
case SAMPLE_POLYFLAGS_TEAM2PHASEGATE: case SAMPLE_POLYFLAGS_TEAM2PHASEGATE:
PhaseGateMove(pBot, MoveFrom, MoveTo); PhaseGateMove(pBot, MoveFrom, MoveTo);
@ -3247,25 +3238,27 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin
bool bIsGoingUpLadder = (EndPoint.z > StartPoint.z); bool bIsGoingUpLadder = (EndPoint.z > StartPoint.z);
// Stop holding crouch if we're a skulk so we can climb up/down
if (IsPlayerSkulk(pBot->Edict))
{
pBot->Button &= ~IN_DUCK;
}
if (IsPlayerOnLadder(pBot->Edict)) if (IsPlayerOnLadder(pBot->Edict))
{ {
// We're on the ladder and actively climbing // We're on the ladder and actively climbing
Vector CurrentLadderNormal = UTIL_GetNearestLadderNormal(pBot->Edict); Vector CurrentLadderNormal = UTIL_GetNearestLadderNormal(pBot->CollisionHullBottomLocation + Vector(0.0f, 0.0f, 5.0f));
CurrentLadderNormal = UTIL_GetVectorNormal2D(CurrentLadderNormal); //CurrentLadderNormal = UTIL_GetVectorNormal2D(CurrentLadderNormal);
if (vIsZero(CurrentLadderNormal)) if (vIsZero(CurrentLadderNormal))
{ {
CurrentLadderNormal = UTIL_GetVectorNormal2D(EndPoint - StartPoint); CurrentLadderNormal = UTIL_GetVectorNormal2D(EndPoint - pBot->Edict->v.origin);
} }
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->Edict->v.origin + (CurrentLadderNormal * 100.0f), 0.5f);
const Vector LadderRightNormal = UTIL_GetVectorNormal(UTIL_GetCrossProduct(CurrentLadderNormal, UP_VECTOR)); const Vector LadderRightNormal = UTIL_GetVectorNormal(UTIL_GetCrossProduct(CurrentLadderNormal, UP_VECTOR));
// Stop holding crouch if we're a skulk so we can climb up/down
if (IsPlayerSkulk(pBot->Edict))
{
pBot->Button &= ~IN_DUCK;
}
Vector ClimbRightNormal = LadderRightNormal; Vector ClimbRightNormal = LadderRightNormal;
if (bIsGoingUpLadder) if (bIsGoingUpLadder)
@ -3312,7 +3305,7 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin
bool bHittingHead = !UTIL_QuickTrace(pBot->Edict, HeadTraceLocation, HeadTraceLocation + Vector(0.0f, 0.0f, 10.0f)); bool bHittingHead = !UTIL_QuickTrace(pBot->Edict, HeadTraceLocation, HeadTraceLocation + Vector(0.0f, 0.0f, 10.0f));
bool bClimbIntoVent = (NextArea == SAMPLE_POLYAREA_CROUCH); bool bClimbIntoVent = (NextArea == SAMPLE_POLYAREA_CROUCH);
if (bHittingHead || bClimbIntoVent) if (!IsPlayerSkulk(pBot->Edict) && (bHittingHead || bClimbIntoVent))
{ {
pBot->Button |= IN_DUCK; pBot->Button |= IN_DUCK;
} }
@ -4083,7 +4076,7 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
float ZDiff = fabs(pEdict->v.origin.z - RequiredClimbHeight); float ZDiff = fabs(pEdict->v.origin.z - RequiredClimbHeight);
Vector AdjustedTargetLocation = EndPoint + (UTIL_GetVectorNormal2D(EndPoint - StartPoint) * 1000.0f); Vector AdjustedTargetLocation = EndPoint + (UTIL_GetVectorNormal2D(EndPoint - StartPoint) * 1000.0f);
Vector DirectAheadView = pBot->CurrentEyePosition + (UTIL_GetVectorNormal2D(AdjustedTargetLocation - pEdict->v.origin) * 10.0f); Vector DirectAheadView = pBot->CurrentEyePosition + (UTIL_GetVectorNormal2D(AdjustedTargetLocation - pBot->CurrentEyePosition) * 100.0f);
Vector ClimbSurfaceNormal = UTIL_GetVectorNormal(EndPoint - StartPoint); Vector ClimbSurfaceNormal = UTIL_GetVectorNormal(EndPoint - StartPoint);
@ -4111,7 +4104,7 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
} }
else else
{ {
if (ZDiff > 32.0f) if (ZDiff > 16.0f)
{ {
ClimbSurfaceNormal = ClimbSurfaceNormal; ClimbSurfaceNormal = ClimbSurfaceNormal;
LookLocation = pBot->CurrentEyePosition + (ClimbSurfaceNormal * 100.0f); LookLocation = pBot->CurrentEyePosition + (ClimbSurfaceNormal * 100.0f);
@ -5069,7 +5062,15 @@ bool AbortCurrentMove(AvHAIPlayer* pBot, const Vector NewDestination)
} }
else else
{ {
WallClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ); if (PlayerHasWeapon(pBot->Player, WEAPON_FADE_BLINK))
{
BlinkClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
}
else
{
WallClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
}
} }
} }

View File

@ -6,6 +6,7 @@
#include "AvHAIConfig.h" #include "AvHAIConfig.h"
#include "AvHAIWeaponHelper.h" #include "AvHAIWeaponHelper.h"
#include "AvHAIHelper.h" #include "AvHAIHelper.h"
#include "AvHAICommander.h"
#include "../AvHGamerules.h" #include "../AvHGamerules.h"
#include "../dlls/client.h" #include "../dlls/client.h"
#include <time.h> #include <time.h>
@ -33,6 +34,9 @@ bool bMapDataInitialised = false;
bool bTestNavigation = false; bool bTestNavigation = false;
bool bDroneMode = false; bool bDroneMode = false;
float NextCommanderAllowedTimeTeamA = 0.0f;
float NextCommanderAllowedTimeTeamB = 0.0f;
extern int m_spriteTexture; extern int m_spriteTexture;
Vector DebugVector1 = ZERO_VECTOR; Vector DebugVector1 = ZERO_VECTOR;
@ -92,6 +96,11 @@ AvHAICommanderMode AIMGR_GetCommanderMode()
} }
float AIMGR_GetCommanderAllowedTime(AvHTeamNumber Team)
{
return (Team == GetGameRules()->GetTeamANumber()) ? NextCommanderAllowedTimeTeamA : NextCommanderAllowedTimeTeamB;
}
void AIMGR_UpdateAIPlayerCounts() void AIMGR_UpdateAIPlayerCounts()
{ {
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();) for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();)
@ -597,6 +606,8 @@ void AIMGR_UpdateAIPlayers()
float FrameDelta = CurrTime - PrevTime; float FrameDelta = CurrTime - PrevTime;
float ThinkDelta = CurrTime - LastThinkTime; float ThinkDelta = CurrTime - LastThinkTime;
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();) for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();)
{ {
@ -627,6 +638,31 @@ void AIMGR_UpdateAIPlayers()
} }
} }
if (bHasRoundStarted)
{
AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber();
AvHTeamNumber TeamBNumber = GetGameRules()->GetTeamBNumber();
AvHTeam* TeamA = GetGameRules()->GetTeam(TeamANumber);
AvHTeam* TeamB = GetGameRules()->GetTeam(TeamBNumber);
if (TeamA->GetTeamType() == AVH_CLASS_TYPE_MARINE)
{
if (TeamA->GetCommanderPlayer() && !(TeamA->GetCommanderPlayer()->pev->flags & FL_FAKECLIENT))
{
AIMGR_SetCommanderAllowedTime(TeamANumber, gpGlobals->time + 15.0f);
}
}
if (TeamB->GetTeamType() == AVH_CLASS_TYPE_MARINE)
{
if (TeamB->GetCommanderPlayer() && !(TeamB->GetCommanderPlayer()->pev->flags & FL_FAKECLIENT))
{
AIMGR_SetCommanderAllowedTime(TeamBNumber, gpGlobals->time + 15.0f);
}
}
}
if (bHasRoundStarted && ShouldBotThink(bot)) if (bHasRoundStarted && ShouldBotThink(bot))
{ {
if (bot->bIsInactive) if (bot->bIsInactive)
@ -877,6 +913,41 @@ void AIMGR_ResetRound()
void AIMGR_RoundStarted() void AIMGR_RoundStarted()
{ {
bHasRoundStarted = true; bHasRoundStarted = true;
AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber();
AvHTeamNumber TeamBNumber = GetGameRules()->GetTeamANumber();
// If our team has no humans on it, then we can take command right away. Otherwise, wait the allotted grace period to allow the human to take command
if (AIMGR_GetNumHumanPlayersOnTeam(TeamANumber) > 0)
{
AIMGR_SetCommanderAllowedTime(TeamANumber, gpGlobals->time + CONFIG_GetCommanderWaitTime());
}
else
{
AIMGR_SetCommanderAllowedTime(TeamANumber, 0.0f);
}
if (AIMGR_GetNumHumanPlayersOnTeam(TeamBNumber) > 0)
{
AIMGR_SetCommanderAllowedTime(TeamBNumber, gpGlobals->time + CONFIG_GetCommanderWaitTime());
}
else
{
AIMGR_SetCommanderAllowedTime(TeamBNumber, 0.0f);
}
}
void AIMGR_SetCommanderAllowedTime(AvHTeamNumber Team, float NewValue)
{
if (Team == GetGameRules()->GetTeamANumber())
{
NextCommanderAllowedTimeTeamA = NewValue;
}
else
{
NextCommanderAllowedTimeTeamB = NewValue;
}
} }
void AIMGR_ClearBotData() void AIMGR_ClearBotData()
@ -944,7 +1015,7 @@ AvHAIPlayer* AIMGR_GetAICommander(AvHTeamNumber Team)
{ {
AvHPlayer* ActiveCommander = GetGameRules()->GetTeam(Team)->GetCommanderPlayer(); AvHPlayer* ActiveCommander = GetGameRules()->GetTeam(Team)->GetCommanderPlayer();
if (!ActiveCommander) { return nullptr; } if (!ActiveCommander || !(ActiveCommander->pev->flags & FL_FAKECLIENT)) { return nullptr; }
for (auto it = ActiveAIPlayers.begin(); it != ActiveAIPlayers.end(); it++) for (auto it = ActiveAIPlayers.begin(); it != ActiveAIPlayers.end(); it++)
{ {
@ -1113,4 +1184,21 @@ bool AIMGR_GetTestNavMode()
bool AIMGR_GetDroneMode() bool AIMGR_GetDroneMode()
{ {
return bTestNavigation; return bTestNavigation;
}
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request)
{
AvHTeam* TeamRef = GetGameRules()->GetTeam(Team);
if (!TeamRef || TeamRef->GetTeamType() != AVH_CLASS_TYPE_MARINE)
{
return;
}
AvHAIPlayer* BotCommander = AIMGR_GetAICommander(Team);
if (BotCommander)
{
AICOMM_ReceiveChatRequest(BotCommander, Requestor, Request);
}
} }

View File

@ -49,6 +49,9 @@ void AIMGR_UpdateAIMapData();
AvHAICommanderMode AIMGR_GetCommanderMode(); AvHAICommanderMode AIMGR_GetCommanderMode();
void AIMGR_SetCommanderAllowedTime(AvHTeamNumber Team, float NewValue);
float AIMGR_GetCommanderAllowedTime(AvHTeamNumber Team);
Vector AIDEBUG_GetDebugVector1(); Vector AIDEBUG_GetDebugVector1();
Vector AIDEBUG_GetDebugVector2(); Vector AIDEBUG_GetDebugVector2();
void AIDEBUG_SetDebugVector1(const Vector NewVector); void AIDEBUG_SetDebugVector1(const Vector NewVector);
@ -93,4 +96,6 @@ bool AIMGR_GetTestNavMode();
void AIMGR_SetDroneMode(bool bNewValue); void AIMGR_SetDroneMode(bool bNewValue);
bool AIMGR_GetDroneMode(); bool AIMGR_GetDroneMode();
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request);
#endif #endif

View File

@ -848,21 +848,161 @@ Vector UTIL_GetNearestLadderNormal(Vector SearchLocation)
if (closestLadderRef) if (closestLadderRef)
{ {
Vector CentrePoint = closestLadderRef->pev->absmin + ((closestLadderRef->pev->absmax - closestLadderRef->pev->absmin) * 0.5f);
CentrePoint.z = SearchLocation.z;
if (vPointOverlaps3D(SearchLocation, closestLadderRef->pev->absmin, closestLadderRef->pev->absmax)) if (vPointOverlaps3D(SearchLocation, closestLadderRef->pev->absmin, closestLadderRef->pev->absmax))
{ {
CentrePoint = SearchLocation; Vector Trace1End, Trace2End, Trace3End, Trace4End, Trace5End, Trace6End, Trace7End, Trace8End;
CentrePoint.z = closestLadderRef->pev->absmin.z; Trace1End = Trace2End = Trace3End = Trace4End = Trace5End = Trace6End = Trace7End = Trace8End = SearchLocation;
Trace1End.x += 32.0f;
Trace1End.y += 32.0f;
Trace2End.x += 32.0f;
Trace2End.y -= 32.0f;
Trace3End.x -= 32.0f;
Trace3End.y -= 32.0f;
Trace4End.x -= 32.0f;
Trace4End.y += 32.0f;
Trace5End.x += 32.0f;
Trace6End.x -= 32.0f;
Trace7End.y -= 32.0f;
Trace8End.y += 32.0f;
Vector ClosestNormal = ZERO_VECTOR;
float MinDist = 0.0f;
trace_t TraceResult;
NS_TraceLine(SearchLocation, Trace1End, 1, PM_NORMAL, -1, true, TraceResult);
UTIL_DrawLine(INDEXENT(1), SearchLocation, Trace1End, 0.5f, 255, 0, 0);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
UTIL_DrawLine(INDEXENT(1), SearchLocation, Trace2End, 0.5f, 0, 128, 0);
NS_TraceLine(SearchLocation, Trace2End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
UTIL_DrawLine(INDEXENT(1), SearchLocation, Trace3End, 0.5f, 0, 0, 255);
NS_TraceLine(SearchLocation, Trace3End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
UTIL_DrawLine(INDEXENT(1), SearchLocation, Trace4End, 0.5f, 255, 255, 0);
NS_TraceLine(SearchLocation, Trace4End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
NS_TraceLine(SearchLocation, Trace5End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
NS_TraceLine(SearchLocation, Trace6End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
NS_TraceLine(SearchLocation, Trace7End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
NS_TraceLine(SearchLocation, Trace8End, 1, PM_NORMAL, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
int PointContents = UTIL_PointContents(TraceResult.endpos);
if (vIsZero(ClosestNormal) || TraceResult.fraction < MinDist)
{
ClosestNormal = TraceResult.plane.normal;
MinDist = TraceResult.fraction;
}
}
return ClosestNormal;
} }
else
trace_t TraceResult;
NS_TraceLine(SearchLocation, CentrePoint, 1, PM_WORLD_ONLY, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{ {
return TraceResult.plane.normal; Vector CentrePoint = closestLadderRef->pev->absmin + (closestLadderRef->pev->size * 0.5f);
CentrePoint.z = SearchLocation.z;
trace_t TraceResult;
NS_TraceLine(SearchLocation, CentrePoint, 1, PM_WORLD_ONLY, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
{
return TraceResult.plane.normal;
}
} }
} }

View File

@ -4721,3 +4721,26 @@ edict_t* AITAC_GetLastSeenLerkForTeam(AvHTeamNumber Team, float& LastSeenTime)
return LastSeenLerkTeamB; return LastSeenLerkTeamB;
} }
} }
bool AITAC_IsCompletedStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius)
{
DeployableSearchFilter SearchFilter;
SearchFilter.DeployableTeam = Team;
SearchFilter.DeployableTypes = StructureType;
SearchFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
SearchFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
SearchFilter.MaxSearchRadius = SearchRadius;
return AITAC_DeployableExistsAtLocation(SearchLocation, &SearchFilter);
}
bool AITAC_IsStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius)
{
DeployableSearchFilter SearchFilter;
SearchFilter.DeployableTeam = Team;
SearchFilter.DeployableTypes = StructureType;
SearchFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
SearchFilter.MaxSearchRadius = SearchRadius;
return AITAC_DeployableExistsAtLocation(SearchLocation, &SearchFilter);
}

View File

@ -189,4 +189,7 @@ int AITAC_GetNumWeaponsInPlay(AvHTeamNumber Team, AvHAIWeapon WeaponType);
edict_t* AITAC_GetLastSeenLerkForTeam(AvHTeamNumber Team, float& LastSeenTime); edict_t* AITAC_GetLastSeenLerkForTeam(AvHTeamNumber Team, float& LastSeenTime);
bool AITAC_IsCompletedStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius);
bool AITAC_IsStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius);
#endif #endif

View File

@ -1752,9 +1752,7 @@ void BotProgressTakeCommandTask(AvHAIPlayer* pBot)
} }
else else
{ {
float CommanderWaitTime = CONFIG_GetCommanderWaitTime(); if (gpGlobals->time > AIMGR_GetCommanderAllowedTime(pBot->Player->GetTeam()))
if ((gpGlobals->time - GetGameRules()->GetTimeGameStarted()) > CommanderWaitTime)
{ {
BotUseObject(pBot, CommChair, false); BotUseObject(pBot, CommChair, false);
} }
@ -1764,7 +1762,7 @@ void BotProgressTakeCommandTask(AvHAIPlayer* pBot)
if (FNullEnt(NearestHuman)) if (FNullEnt(NearestHuman))
{ {
BotUseObject(pBot, CommChair, false); BotGuardLocation(pBot, CommChair->v.origin);
} }
else else
{ {

View File

@ -942,6 +942,8 @@ const float kCommanderHierarchyScaleFactor = .0002f;
#define kReadyNotification "ready" #define kReadyNotification "ready"
#define kNotReadyNotification "notready" #define kNotReadyNotification "notready"
#define kAICommanderRequest "comm"
const int kOverwatchBreakingVelocity = 5; const int kOverwatchBreakingVelocity = 5;
const float kOverwatchAcquireTime = 6.0f; const float kOverwatchAcquireTime = 6.0f;
const float kOverwatchLostTargetTime = 4.0f; const float kOverwatchLostTargetTime = 4.0f;

View File

@ -146,6 +146,8 @@
#include "AvHSiegeTurret.h" #include "AvHSiegeTurret.h"
#include "AvHHulls.h" #include "AvHHulls.h"
#include "AIPlayers/AvHAIPlayerManager.h"
//LINK_ENTITY_TO_CLASS(kwMine, AvHMine); //LINK_ENTITY_TO_CLASS(kwMine, AvHMine);
//LINK_ENTITY_TO_CLASS(kwDeployedTurret, AvHDeployedTurret); //LINK_ENTITY_TO_CLASS(kwDeployedTurret, AvHDeployedTurret);
//LINK_ENTITY_TO_CLASS(kwTurret, AvHTurret); //LINK_ENTITY_TO_CLASS(kwTurret, AvHTurret);
@ -1991,6 +1993,12 @@ void AvHCommandStation::CommandUse( CBaseEntity* pActivator, CBaseEntity* pCalle
// The player somehow touches the command station while still a commander // The player somehow touches the command station while still a commander
if(thePlayer->GetUser3() != AVH_USER3_COMMANDER_PLAYER) if(thePlayer->GetUser3() != AVH_USER3_COMMANDER_PLAYER)
{ {
// A human used the comm chair, kick the AI commander out if they're in there and don't let them re-enter for 20 seconds
if (!(thePlayer->pev->flags & FL_FAKECLIENT))
{
AIMGR_SetCommanderAllowedTime(theStationTeamNumber, gpGlobals->time + 20.0f);
}
thePlayer->SendMessage(kCommandStationInUse, TOOLTIP); thePlayer->SendMessage(kCommandStationInUse, TOOLTIP);
} }
} }

View File

@ -158,6 +158,8 @@
#include "AvHNetworkMessages.h" #include "AvHNetworkMessages.h"
#include "AvHNexusServer.h" #include "AvHNexusServer.h"
#include "AIPlayers/AvHAIPlayerManager.h"
extern int gPhaseInEventID; extern int gPhaseInEventID;
extern cvar_t avh_votecasttime; extern cvar_t avh_votecasttime;
extern cvar_t avh_votedowntime; extern cvar_t avh_votedowntime;
@ -721,6 +723,10 @@ bool AvHTeam::PlayerVote(int inPlayerIndex, string& outPlayerMessage)
if(theCommander) if(theCommander)
{ {
theCommander->LogPlayerActionPlayer(theVotingPlayer, "votedown"); theCommander->LogPlayerActionPlayer(theVotingPlayer, "votedown");
if (theCommander->pev->flags & FL_FAKECLIENT)
{
AIMGR_SetCommanderAllowedTime(theVotingPlayer->GetTeam(), gpGlobals->time + 60.0f);
}
} }
} }
} }