mirror of
https://github.com/ENSL/NS.git
synced 2024-11-14 00:40:57 +00:00
Commander Placements Tweaks
* Commander won't get stuck trying to build base structures if using nav hints that are placed in bad spots (i.e. can't deploy structures where the nav hint is) * Commander can now deploy prototype labs, arms labs and infantry portals on request
This commit is contained in:
parent
9452b8a0c3
commit
9a4a6b3660
5 changed files with 290 additions and 79 deletions
Binary file not shown.
|
@ -993,6 +993,10 @@ bool AICOMM_IsRequestValid(ai_commander_request* Request)
|
||||||
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_COMMCHAIR, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_COMMCHAIR, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
case BUILD_SCAN:
|
case BUILD_SCAN:
|
||||||
return !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_SCAN, RequestorTeam, AI_REACHABILITY_NONE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false);
|
return !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_SCAN, RequestorTeam, AI_REACHABILITY_NONE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false);
|
||||||
|
case BUILD_ARMSLAB:
|
||||||
|
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_ARMSLAB, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
|
case BUILD_PROTOTYPE_LAB:
|
||||||
|
return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_PROTOTYPELAB, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2330,69 +2334,72 @@ bool AICOMM_BuildInfantryPortal(AvHAIPlayer* pBot, edict_t* CommChair)
|
||||||
|
|
||||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_INFANTRYPORTAL, CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_INFANTRYPORTAL, CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
||||||
|
|
||||||
if (vIsZero(BuildLocation))
|
if (!vIsZero(BuildLocation))
|
||||||
{
|
{
|
||||||
|
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
||||||
|
|
||||||
DeployableSearchFilter ExistingPortalFilter;
|
if (bSuccess) { return true; }
|
||||||
ExistingPortalFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
|
||||||
ExistingPortalFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
|
||||||
ExistingPortalFilter.DeployableTeam = pBot->Player->GetTeam();
|
|
||||||
ExistingPortalFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
ExistingPortalFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
|
||||||
|
|
||||||
AvHAIBuildableStructure ExistingInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &ExistingPortalFilter);
|
|
||||||
|
|
||||||
// First see if we can place the next infantry portal next to the first one
|
|
||||||
if (ExistingInfantryPortal.IsValid())
|
|
||||||
{
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingInfantryPortal.edict->v.origin, UTIL_MetresToGoldSrcUnits(2.0f), UTIL_MetresToGoldSrcUnits(3.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (bSuccess) { return true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector SearchPoint = ZERO_VECTOR;
|
|
||||||
|
|
||||||
DeployableSearchFilter ResNodeFilter;
|
|
||||||
ResNodeFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
ResNodeFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
|
||||||
|
|
||||||
const AvHAIResourceNode* ResNode = AITAC_FindNearestResourceNodeToLocation(CommChair->v.origin, &ResNodeFilter);
|
|
||||||
|
|
||||||
if (ResNode)
|
|
||||||
{
|
|
||||||
SearchPoint = ResNode->Location;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector NearestPointToChair = FindClosestNavigablePointToDestination(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), SearchPoint, CommChair->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NearestPointToChair))
|
|
||||||
{
|
|
||||||
float Distance = vDist2D(NearestPointToChair, CommChair->v.origin);
|
|
||||||
float RandomDist = UTIL_MetresToGoldSrcUnits(5.0f) - Distance;
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPointToChair, RandomDist);
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (bSuccess) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeployableSearchFilter ExistingPortalFilter;
|
||||||
|
ExistingPortalFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
||||||
|
ExistingPortalFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||||
|
ExistingPortalFilter.DeployableTeam = pBot->Player->GetTeam();
|
||||||
|
ExistingPortalFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
||||||
|
ExistingPortalFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
||||||
|
|
||||||
|
AvHAIBuildableStructure ExistingInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &ExistingPortalFilter);
|
||||||
|
|
||||||
|
// First see if we can place the next infantry portal next to the first one
|
||||||
|
if (ExistingInfantryPortal.IsValid())
|
||||||
|
{
|
||||||
|
BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingInfantryPortal.edict->v.origin, UTIL_MetresToGoldSrcUnits(2.0f), UTIL_MetresToGoldSrcUnits(3.0f));
|
||||||
|
|
||||||
|
if (!vIsZero(BuildLocation))
|
||||||
|
{
|
||||||
|
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
||||||
|
|
||||||
|
if (bSuccess) { return true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector SearchPoint = ZERO_VECTOR;
|
||||||
|
|
||||||
|
DeployableSearchFilter ResNodeFilter;
|
||||||
|
ResNodeFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
||||||
|
ResNodeFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
||||||
|
|
||||||
|
const AvHAIResourceNode* ResNode = AITAC_FindNearestResourceNodeToLocation(CommChair->v.origin, &ResNodeFilter);
|
||||||
|
|
||||||
|
if (ResNode)
|
||||||
|
{
|
||||||
|
SearchPoint = ResNode->Location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector NearestPointToChair = FindClosestNavigablePointToDestination(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), SearchPoint, CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
||||||
|
|
||||||
|
if (!vIsZero(NearestPointToChair))
|
||||||
|
{
|
||||||
|
float Distance = vDist2D(NearestPointToChair, CommChair->v.origin);
|
||||||
|
float RandomDist = UTIL_MetresToGoldSrcUnits(5.0f) - Distance;
|
||||||
|
|
||||||
|
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPointToChair, RandomDist);
|
||||||
|
|
||||||
|
if (!vIsZero(BuildLocation))
|
||||||
|
{
|
||||||
|
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
||||||
|
|
||||||
|
if (bSuccess) { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
||||||
|
|
||||||
if (vIsZero(BuildLocation)) { return false; }
|
if (vIsZero(BuildLocation)) { return false; }
|
||||||
|
|
||||||
return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
||||||
|
@ -3055,7 +3062,6 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (NextRequest->RequestType == BUILD_PHASEGATE && !AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_PHASETECH))
|
if (NextRequest->RequestType == BUILD_PHASEGATE && !AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_PHASETECH))
|
||||||
{
|
{
|
||||||
char msg[128];
|
char msg[128];
|
||||||
|
@ -3065,7 +3071,7 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NextRequest->RequestType == BUILD_OBSERVATORY && !AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_PHASETECH))
|
if (NextRequest->RequestType == BUILD_OBSERVATORY || NextRequest->RequestType == BUILD_ARMSLAB)
|
||||||
{
|
{
|
||||||
DeployableSearchFilter ArmouryFilter;
|
DeployableSearchFilter ArmouryFilter;
|
||||||
ArmouryFilter.DeployableTeam = CommanderTeam;
|
ArmouryFilter.DeployableTeam = CommanderTeam;
|
||||||
|
@ -3085,6 +3091,39 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NextRequest->RequestType == BUILD_PROTOTYPE_LAB)
|
||||||
|
{
|
||||||
|
DeployableSearchFilter RequiredFilter;
|
||||||
|
RequiredFilter.DeployableTeam = CommanderTeam;
|
||||||
|
RequiredFilter.DeployableTypes = STRUCTURE_MARINE_ADVARMOURY;
|
||||||
|
RequiredFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||||
|
RequiredFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||||
|
|
||||||
|
bool bHasArmoury = AITAC_DeployableExistsAtLocation(ZERO_VECTOR, &RequiredFilter);
|
||||||
|
|
||||||
|
if (!bHasArmoury)
|
||||||
|
{
|
||||||
|
char msg[128];
|
||||||
|
sprintf(msg, "We haven't got an advanced armory yet, %s. Ask again later.", STRING(Requestor->v.netname));
|
||||||
|
BotSay(pBot, true, 0.5f, msg);
|
||||||
|
NextRequest->bResponded = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequiredFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB;
|
||||||
|
|
||||||
|
bool bHasArmsLab = AITAC_DeployableExistsAtLocation(ZERO_VECTOR, &RequiredFilter);
|
||||||
|
|
||||||
|
if (!bHasArmsLab)
|
||||||
|
{
|
||||||
|
char msg[128];
|
||||||
|
sprintf(msg, "We haven't got an arms lab yet, %s. Ask again later.", STRING(Requestor->v.netname));
|
||||||
|
BotSay(pBot, true, 0.5f, msg);
|
||||||
|
NextRequest->bResponded = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
float RequiredRes = 0.0f;
|
float RequiredRes = 0.0f;
|
||||||
AvHAIDeployableStructureType StructureToDeploy = STRUCTURE_NONE;
|
AvHAIDeployableStructureType StructureToDeploy = STRUCTURE_NONE;
|
||||||
|
@ -3115,6 +3154,18 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
RequiredRes = BALANCE_VAR(kPhaseGateCost);
|
RequiredRes = BALANCE_VAR(kPhaseGateCost);
|
||||||
StructureToDeploy = STRUCTURE_MARINE_PHASEGATE;
|
StructureToDeploy = STRUCTURE_MARINE_PHASEGATE;
|
||||||
break;
|
break;
|
||||||
|
case BUILD_INFANTRYPORTAL:
|
||||||
|
RequiredRes = BALANCE_VAR(kInfantryPortalCost);
|
||||||
|
StructureToDeploy = STRUCTURE_MARINE_INFANTRYPORTAL;
|
||||||
|
break;
|
||||||
|
case BUILD_PROTOTYPE_LAB:
|
||||||
|
RequiredRes = BALANCE_VAR(kPrototypeLabCost);
|
||||||
|
StructureToDeploy = STRUCTURE_MARINE_PROTOTYPELAB;
|
||||||
|
break;
|
||||||
|
case BUILD_ARMSLAB:
|
||||||
|
RequiredRes = BALANCE_VAR(kArmsLabCost);
|
||||||
|
StructureToDeploy = STRUCTURE_MARINE_ARMSLAB;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3139,11 +3190,55 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f);
|
float ProjectDistance = (NextRequest->RequestType == BUILD_INFANTRYPORTAL || NextRequest->RequestType == BUILD_SIEGE) ? 32.0f : 75.0f;
|
||||||
|
|
||||||
|
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * ProjectDistance);
|
||||||
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
||||||
|
|
||||||
if (!vIsZero(ProjectedDeployLocation))
|
if (!vIsZero(ProjectedDeployLocation))
|
||||||
{
|
{
|
||||||
|
if (NextRequest->RequestType == BUILD_INFANTRYPORTAL)
|
||||||
|
{
|
||||||
|
DeployableSearchFilter CCFilter;
|
||||||
|
CCFilter.DeployableTeam = CommanderTeam;
|
||||||
|
CCFilter.DeployableTypes = STRUCTURE_MARINE_COMMCHAIR;
|
||||||
|
CCFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||||
|
CCFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||||
|
CCFilter.MaxSearchRadius = BALANCE_VAR(kCommandStationBuildDistance);
|
||||||
|
|
||||||
|
bool bHasChair = AITAC_DeployableExistsAtLocation(ProjectedDeployLocation, &CCFilter);
|
||||||
|
|
||||||
|
if (!bHasChair)
|
||||||
|
{
|
||||||
|
char msg[128];
|
||||||
|
sprintf(msg, "There isn't a comm chair there, %s. Ask again next to the CC", STRING(Requestor->v.netname));
|
||||||
|
BotSay(pBot, true, 0.5f, msg);
|
||||||
|
NextRequest->bResponded = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NextRequest->RequestType == BUILD_SIEGE)
|
||||||
|
{
|
||||||
|
DeployableSearchFilter TFFilter;
|
||||||
|
TFFilter.DeployableTeam = CommanderTeam;
|
||||||
|
TFFilter.DeployableTypes = STRUCTURE_MARINE_ADVTURRETFACTORY;
|
||||||
|
TFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||||
|
TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||||
|
TFFilter.MaxSearchRadius = BALANCE_VAR(kTurretFactoryBuildDistance);
|
||||||
|
|
||||||
|
bool bHasChair = AITAC_DeployableExistsAtLocation(ProjectedDeployLocation, &TFFilter);
|
||||||
|
|
||||||
|
if (!bHasChair)
|
||||||
|
{
|
||||||
|
char msg[128];
|
||||||
|
sprintf(msg, "There isn't a an advanced armory there, %s. Ask again next to one", STRING(Requestor->v.netname));
|
||||||
|
BotSay(pBot, true, 0.5f, msg);
|
||||||
|
NextRequest->bResponded = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool bSuccess = AICOMM_DeployStructure(pBot, StructureToDeploy, ProjectedDeployLocation, STRUCTURE_PURPOSE_NONE);
|
bool bSuccess = AICOMM_DeployStructure(pBot, StructureToDeploy, ProjectedDeployLocation, STRUCTURE_PURPOSE_NONE);
|
||||||
|
|
||||||
if (bSuccess)
|
if (bSuccess)
|
||||||
|
@ -3712,6 +3807,22 @@ void AICOMM_ReceiveChatRequest(AvHAIPlayer* Commander, edict_t* Requestor, const
|
||||||
{
|
{
|
||||||
NewRequestType = BUILD_OBSERVATORY;
|
NewRequestType = BUILD_OBSERVATORY;
|
||||||
}
|
}
|
||||||
|
else if (!stricmp(Request, "pl") || !stricmp(Request, "protolab") || !stricmp(Request, "proto lab") || !stricmp(Request, "prototype lab"))
|
||||||
|
{
|
||||||
|
NewRequestType = BUILD_PROTOTYPE_LAB;
|
||||||
|
}
|
||||||
|
else if (!stricmp(Request, "ip") || !stricmp(Request, "portal") || !stricmp(Request, "inf portal") || !stricmp(Request, "infantry portal"))
|
||||||
|
{
|
||||||
|
NewRequestType = BUILD_INFANTRYPORTAL;
|
||||||
|
}
|
||||||
|
else if (!stricmp(Request, "al") || !stricmp(Request, "armslab") || !stricmp(Request, "arms lab"))
|
||||||
|
{
|
||||||
|
NewRequestType = BUILD_ARMSLAB;
|
||||||
|
}
|
||||||
|
else if (!stricmp(Request, "sc") || !stricmp(Request, "st") || !stricmp(Request, "siegeturret") || !stricmp(Request, "siege turret") || !stricmp(Request, "siegecannon") || !stricmp(Request, "siege cannon"))
|
||||||
|
{
|
||||||
|
NewRequestType = BUILD_SIEGE;
|
||||||
|
}
|
||||||
|
|
||||||
if (NewRequestType == MESSAGE_NULL) { return; }
|
if (NewRequestType == MESSAGE_NULL) { return; }
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ typedef enum
|
||||||
STRUCTURE_ALIEN_OFFENCECHAMBER = 1u << 19,
|
STRUCTURE_ALIEN_OFFENCECHAMBER = 1u << 19,
|
||||||
|
|
||||||
SEARCH_ALL_MARINE_STRUCTURES = 0xFFF,
|
SEARCH_ALL_MARINE_STRUCTURES = 0xFFF,
|
||||||
SEARCH_ALL_ALIEN_STRUCTURES = 0xFC000,
|
SEARCH_ALL_ALIEN_STRUCTURES = (STRUCTURE_ALIEN_HIVE | STRUCTURE_ALIEN_RESTOWER | STRUCTURE_ALIEN_DEFENCECHAMBER | STRUCTURE_ALIEN_SENSORYCHAMBER | STRUCTURE_ALIEN_MOVEMENTCHAMBER | STRUCTURE_ALIEN_OFFENCECHAMBER),
|
||||||
SEARCH_ANY_RES_TOWER = (STRUCTURE_MARINE_RESTOWER | STRUCTURE_ALIEN_RESTOWER),
|
SEARCH_ANY_RES_TOWER = (STRUCTURE_MARINE_RESTOWER | STRUCTURE_ALIEN_RESTOWER),
|
||||||
|
|
||||||
SEARCH_ALL_STRUCTURES = ((unsigned int)-1 & ~(STRUCTURE_MARINE_DEPLOYEDMINE))
|
SEARCH_ALL_STRUCTURES = ((unsigned int)-1 & ~(STRUCTURE_MARINE_DEPLOYEDMINE))
|
||||||
|
|
|
@ -1887,17 +1887,116 @@ void EndBotFrame(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
void CustomThink(AvHAIPlayer* pBot)
|
void CustomThink(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
if (pBot->Player->GetResources() < 80.0f)
|
||||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
|
||||||
|
|
||||||
if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE)
|
|
||||||
{
|
{
|
||||||
AITASK_SetAssaultMarineBaseTask(pBot, &pBot->PrimaryBotTask, AITAC_GetTeamStartingLocation(EnemyTeam), true);
|
pBot->Player->GiveResources(10.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pBot->CurrentTask = &pBot->PrimaryBotTask;
|
pBot->CurrentTask = &pBot->PrimaryBotTask;
|
||||||
|
|
||||||
BotProgressTask(pBot, pBot->CurrentTask);
|
AITASK_BotUpdateAndClearTasks(pBot);
|
||||||
|
|
||||||
|
if (pBot->CurrentTask->TaskType == TASK_REINFORCE_STRUCTURE)
|
||||||
|
{
|
||||||
|
BotProgressTask(pBot, pBot->CurrentTask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No missing upgrade chambers to drop, let's look for empty hives we can start staking a claim to, to deny to the enemy
|
||||||
|
vector<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
|
||||||
|
|
||||||
|
AvHAIHiveDefinition* HiveToSecure = nullptr;
|
||||||
|
|
||||||
|
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||||
|
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||||
|
|
||||||
|
float MinDist = 0.0f;
|
||||||
|
|
||||||
|
for (auto it = AllHives.begin(); it != AllHives.end(); it++)
|
||||||
|
{
|
||||||
|
AvHAIHiveDefinition* ThisHive = (*it);
|
||||||
|
|
||||||
|
if (ThisHive->Status == HIVE_STATUS_UNBUILT)
|
||||||
|
{
|
||||||
|
unsigned int StructureTypes = (STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY);
|
||||||
|
|
||||||
|
if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_ALIEN)
|
||||||
|
{
|
||||||
|
StructureTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeployableSearchFilter EnemyStructureFilter;
|
||||||
|
EnemyStructureFilter.DeployableTeam = EnemyTeam;
|
||||||
|
EnemyStructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||||
|
EnemyStructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||||
|
EnemyStructureFilter.DeployableTypes = StructureTypes;
|
||||||
|
EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||||
|
|
||||||
|
bool bEnemyHaveFoothold = AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStructureFilter);
|
||||||
|
|
||||||
|
if (bEnemyHaveFoothold) { continue; }
|
||||||
|
|
||||||
|
if (AITAC_GetNumPlayersOfTeamInArea(EnemyTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_COMMANDER_PLAYER) > 1) { continue; }
|
||||||
|
|
||||||
|
int OtherBuilders = AITAC_GetNumPlayersOfTeamAndClassInArea(EnemyTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_ALIEN_PLAYER2);
|
||||||
|
|
||||||
|
if (OtherBuilders >= 2) { continue; }
|
||||||
|
|
||||||
|
DeployableSearchFilter ExistingReinforcementFilter;
|
||||||
|
ExistingReinforcementFilter.DeployableTeam = BotTeam;
|
||||||
|
ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||||
|
ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||||
|
|
||||||
|
vector<AvHAIBuildableStructure> AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter);
|
||||||
|
|
||||||
|
int NumOCs = 0;
|
||||||
|
int NumDCs = 0;
|
||||||
|
int NumMCs = 0;
|
||||||
|
int NumSCs = 0;
|
||||||
|
|
||||||
|
for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++)
|
||||||
|
{
|
||||||
|
switch ((*it).StructureType)
|
||||||
|
{
|
||||||
|
case STRUCTURE_ALIEN_OFFENCECHAMBER:
|
||||||
|
NumOCs++;
|
||||||
|
break;
|
||||||
|
case STRUCTURE_ALIEN_DEFENCECHAMBER:
|
||||||
|
NumDCs++;
|
||||||
|
break;
|
||||||
|
case STRUCTURE_ALIEN_MOVEMENTCHAMBER:
|
||||||
|
NumMCs++;
|
||||||
|
break;
|
||||||
|
case STRUCTURE_ALIEN_SENSORYCHAMBER:
|
||||||
|
NumSCs++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumOCs < 3
|
||||||
|
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_DEFENSE_CHAMBER) && NumDCs < 2)
|
||||||
|
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_MOVEMENT_CHAMBER) && NumMCs < 1)
|
||||||
|
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_SENSORY_CHAMBER) && NumSCs < 1))
|
||||||
|
{
|
||||||
|
float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisHive->FloorLocation);
|
||||||
|
|
||||||
|
if (!HiveToSecure || ThisDist < MinDist)
|
||||||
|
{
|
||||||
|
HiveToSecure = ThisHive;
|
||||||
|
MinDist = ThisDist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HiveToSecure)
|
||||||
|
{
|
||||||
|
AITASK_SetReinforceStructureTask(pBot, &pBot->PrimaryBotTask, HiveToSecure->HiveEdict, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DroneThink(AvHAIPlayer* pBot)
|
void DroneThink(AvHAIPlayer* pBot)
|
||||||
|
@ -5615,14 +5714,12 @@ void AIPlayerEndMatchThink(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
if (IsPlayerMarine(pBot->Player))
|
if (IsPlayerMarine(pBot->Player))
|
||||||
{
|
{
|
||||||
MarineCombatThink(pBot);
|
if (MarineCombatThink(pBot)) { return; }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AlienCombatThink(pBot);
|
if (AlienCombatThink(pBot)) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||||
|
@ -5667,16 +5764,16 @@ void AIPlayerDMThink(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
if (IsPlayerMarine(pBot->Player))
|
if (IsPlayerMarine(pBot->Player))
|
||||||
{
|
{
|
||||||
MarineCombatThink(pBot);
|
if (MarineCombatThink(pBot)) { return; }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AlienCombatThink(pBot);
|
if (AlienCombatThink(pBot)) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pBot->CurrentTask = &pBot->PrimaryBotTask;
|
||||||
|
|
||||||
AITASK_BotUpdateAndClearTasks(pBot);
|
AITASK_BotUpdateAndClearTasks(pBot);
|
||||||
|
|
||||||
if (pBot->CurrentTask->TaskType == TASK_NONE)
|
if (pBot->CurrentTask->TaskType == TASK_NONE)
|
||||||
|
|
|
@ -876,9 +876,9 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
||||||
if (bActiveHiveWithoutTechExists) { return true; }
|
if (bActiveHiveWithoutTechExists) { return true; }
|
||||||
|
|
||||||
DeployableSearchFilter StructureFilter;
|
DeployableSearchFilter StructureFilter;
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER | ALIEN_BUILD_DEFENSE_CHAMBER | ALIEN_BUILD_MOVEMENT_CHAMBER | ALIEN_BUILD_SENSORY_CHAMBER;
|
StructureFilter.DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES;
|
||||||
StructureFilter.MaxSearchRadius = (IsEdictHive(Task->TaskTarget)) ? UTIL_MetresToGoldSrcUnits(10.0f) : UTIL_MetresToGoldSrcUnits(5.0f);
|
StructureFilter.MaxSearchRadius = (IsEdictHive(Task->TaskTarget)) ? UTIL_MetresToGoldSrcUnits(10.0f) : UTIL_MetresToGoldSrcUnits(5.0f);
|
||||||
StructureFilter.DeployableTeam = pBot->Player->GetTeam();
|
StructureFilter.DeployableTeam = BotTeam;
|
||||||
|
|
||||||
vector<AvHAIBuildableStructure> AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter);
|
vector<AvHAIBuildableStructure> AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter);
|
||||||
|
|
||||||
|
@ -1356,10 +1356,13 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||||
// We had a go, whether it succeeded or not we should try a new location
|
// We had a go, whether it succeeded or not we should try a new location
|
||||||
if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS)
|
if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS)
|
||||||
{
|
{
|
||||||
|
Task->TaskStartedTime = gpGlobals->time;
|
||||||
Task->TaskLocation = ZERO_VECTOR;
|
Task->TaskLocation = ZERO_VECTOR;
|
||||||
Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
|
Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gpGlobals->time - Task->TaskStartedTime < 1.0f) { return; }
|
||||||
|
|
||||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||||
|
|
||||||
Vector ReinforceLocation = UTIL_ProjectPointToNavmesh(UTIL_GetEntityGroundLocation(Task->TaskTarget), pBot->BotNavInfo.NavProfile);
|
Vector ReinforceLocation = UTIL_ProjectPointToNavmesh(UTIL_GetEntityGroundLocation(Task->TaskTarget), pBot->BotNavInfo.NavProfile);
|
||||||
|
|
Loading…
Reference in a new issue