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_nextFreeOffMeshConnection;
static const int MAX_REQUESTS = 256;
static const int MAX_REQUESTS = 512;
ObstacleRequest m_reqs[MAX_REQUESTS];
int m_nreqs;
OffMeshRequest m_OffMeshReqs[MAX_REQUESTS];
int m_nOffMeshReqs;
static const int MAX_UPDATE = 256;
static const int MAX_UPDATE = 512;
dtCompressedTileRef m_update[MAX_UPDATE];
int m_nupdate;
};

View File

@ -145,6 +145,7 @@
#include "../mod/AvHAlienAbilityConstants.h"
#include "../mod/AvHNetworkMessages.h"
#include "../mod/AvHNexusServer.h"
#include "../mod/AIPlayers/AvHAIPlayerManager.h"
#include "../game_shared/voice_gamemgr.h"
extern CVoiceGameMgr g_VoiceGameMgr;
@ -394,10 +395,14 @@ void Host_Say( edict_t *pEntity, int teamonly )
if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) )
{
if ( CMD_ARGC() >= 2 )
int NumArgs = CMD_ARGC();
if (NumArgs >= 2 )
{
p = (char *)CMD_ARGS();
bool bMessageParsed = false;
if(GetGameRules()->GetIsTournamentMode() && !GetGameRules()->GetGameStarted())
{
if(!strcmp(CMD_ARGV(1), kReadyNotification))
@ -408,6 +413,8 @@ void Host_Say( edict_t *pEntity, int teamonly )
{
theTeam->SetIsReady();
}
bMessageParsed = true;
}
else if (!strcmp(CMD_ARGV(1), kNotReadyNotification))
{
@ -417,8 +424,33 @@ void Host_Say( edict_t *pEntity, int teamonly )
{
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
{

View File

@ -868,10 +868,50 @@ bool AICOMM_IsRequestValid(ai_commander_request* Request)
{
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)
{
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:
return true;
}
@ -2215,6 +2255,10 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
NextRequest->bResponded = true;
}
}
else
{
NextRequest->ResponseAttempts++;
}
return true;
}
@ -2280,6 +2324,10 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
NextRequest->bResponded = true;
}
}
else
{
NextRequest->ResponseAttempts++;
}
return true;
}
@ -2298,6 +2346,276 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
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;
}
@ -2446,6 +2764,8 @@ bool AICOMM_ShouldCommanderLeaveChair(AvHAIPlayer* pBot)
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);
if (NumAliveMarinesInBase > 0) { return false; }
@ -2674,4 +2994,64 @@ bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot)
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_ShouldBeacon(AvHAIPlayer* pBot);
void AICOMM_ReceiveChatRequest(AvHAIPlayer* Commander, edict_t* Requestor, const char* Request);
#endif // AVH_AI_COMMANDER_H

View File

@ -677,6 +677,7 @@ typedef struct _AI_COMMANDER_REQUEST
AvHMessageID RequestType = MESSAGE_NULL; // What did they request?
bool bResponded = false; // Have we already responded to this request?
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;
typedef struct AVH_AI_PLAYER

View File

@ -2965,28 +2965,19 @@ void NewMove(AvHAIPlayer* pBot)
break;
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
{
BlinkClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
WallClimbMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ);
}
}
break;
case SAMPLE_POLYFLAGS_LADDER:
{
if (IsPlayerSkulk(pBot->Edict))
{
LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
}
else
{
LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
}
}
break;
LadderMove(pBot, MoveFrom, MoveTo, pBot->BotNavInfo.CurrentPathPoint->requiredZ, NextArea);
break;
case SAMPLE_POLYFLAGS_TEAM1PHASEGATE:
case SAMPLE_POLYFLAGS_TEAM2PHASEGATE:
PhaseGateMove(pBot, MoveFrom, MoveTo);
@ -3247,25 +3238,27 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin
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))
{
// We're on the ladder and actively climbing
Vector CurrentLadderNormal = UTIL_GetNearestLadderNormal(pBot->Edict);
CurrentLadderNormal = UTIL_GetVectorNormal2D(CurrentLadderNormal);
Vector CurrentLadderNormal = UTIL_GetNearestLadderNormal(pBot->CollisionHullBottomLocation + Vector(0.0f, 0.0f, 5.0f));
//CurrentLadderNormal = UTIL_GetVectorNormal2D(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));
// 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;
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 bClimbIntoVent = (NextArea == SAMPLE_POLYAREA_CROUCH);
if (bHittingHead || bClimbIntoVent)
if (!IsPlayerSkulk(pBot->Edict) && (bHittingHead || bClimbIntoVent))
{
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);
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);
@ -4111,7 +4104,7 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
}
else
{
if (ZDiff > 32.0f)
if (ZDiff > 16.0f)
{
ClimbSurfaceNormal = ClimbSurfaceNormal;
LookLocation = pBot->CurrentEyePosition + (ClimbSurfaceNormal * 100.0f);
@ -5069,7 +5062,15 @@ bool AbortCurrentMove(AvHAIPlayer* pBot, const Vector NewDestination)
}
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 "AvHAIWeaponHelper.h"
#include "AvHAIHelper.h"
#include "AvHAICommander.h"
#include "../AvHGamerules.h"
#include "../dlls/client.h"
#include <time.h>
@ -33,6 +34,9 @@ bool bMapDataInitialised = false;
bool bTestNavigation = false;
bool bDroneMode = false;
float NextCommanderAllowedTimeTeamA = 0.0f;
float NextCommanderAllowedTimeTeamB = 0.0f;
extern int m_spriteTexture;
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()
{
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();)
@ -597,6 +606,8 @@ void AIMGR_UpdateAIPlayers()
float FrameDelta = CurrTime - PrevTime;
float ThinkDelta = CurrTime - LastThinkTime;
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 (bot->bIsInactive)
@ -877,6 +913,41 @@ void AIMGR_ResetRound()
void AIMGR_RoundStarted()
{
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()
@ -944,7 +1015,7 @@ AvHAIPlayer* AIMGR_GetAICommander(AvHTeamNumber Team)
{
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++)
{
@ -1113,4 +1184,21 @@ bool AIMGR_GetTestNavMode()
bool AIMGR_GetDroneMode()
{
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();
void AIMGR_SetCommanderAllowedTime(AvHTeamNumber Team, float NewValue);
float AIMGR_GetCommanderAllowedTime(AvHTeamNumber Team);
Vector AIDEBUG_GetDebugVector1();
Vector AIDEBUG_GetDebugVector2();
void AIDEBUG_SetDebugVector1(const Vector NewVector);
@ -93,4 +96,6 @@ bool AIMGR_GetTestNavMode();
void AIMGR_SetDroneMode(bool bNewValue);
bool AIMGR_GetDroneMode();
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request);
#endif

View File

@ -848,21 +848,161 @@ Vector UTIL_GetNearestLadderNormal(Vector SearchLocation)
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))
{
CentrePoint = SearchLocation;
CentrePoint.z = closestLadderRef->pev->absmin.z;
Vector Trace1End, Trace2End, Trace3End, Trace4End, Trace5End, Trace6End, Trace7End, Trace8End;
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;
}
trace_t TraceResult;
NS_TraceLine(SearchLocation, CentrePoint, 1, PM_WORLD_ONLY, -1, true, TraceResult);
if (TraceResult.fraction < 1.0f)
else
{
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;
}
}
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);
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

View File

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

View File

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

View File

@ -146,6 +146,8 @@
#include "AvHSiegeTurret.h"
#include "AvHHulls.h"
#include "AIPlayers/AvHAIPlayerManager.h"
//LINK_ENTITY_TO_CLASS(kwMine, AvHMine);
//LINK_ENTITY_TO_CLASS(kwDeployedTurret, AvHDeployedTurret);
//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
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);
}
}

View File

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