mirror of https://github.com/ENSL/NS.git
Commander chat request
This commit is contained in:
parent
2fef7b83ff
commit
567f34cbf7
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue