Commander improvements, movement improvements

This commit is contained in:
RGreenlees 2024-03-15 16:14:53 +00:00 committed by pierow
parent 3217a5226e
commit b518693f5c
11 changed files with 332 additions and 166 deletions

View file

@ -2470,24 +2470,79 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
return true;
}
if (NextRequest->RequestType == BUILD_WELDER)
if (NextRequest->RequestType == BUILD_WELDER || NextRequest->RequestType == BUILD_SHOTGUN || NextRequest->RequestType == BUILD_MINES)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kWelderCost)) { return false; }
AvHAIDeployableItemType ItemToDrop = DEPLOYABLE_ITEM_NONE;
float Cost = 0.0f;
switch (NextRequest->RequestType)
{
case BUILD_WELDER:
ItemToDrop = DEPLOYABLE_ITEM_WELDER;
Cost = BALANCE_VAR(kWelderCost);
break;
case BUILD_SHOTGUN:
ItemToDrop = DEPLOYABLE_ITEM_SHOTGUN;
Cost = BALANCE_VAR(kShotgunCost);
break;
case BUILD_MINES:
ItemToDrop = DEPLOYABLE_ITEM_MINES;
Cost = BALANCE_VAR(kMineCost);
break;
default:
ItemToDrop = DEPLOYABLE_ITEM_WELDER;
Cost = BALANCE_VAR(kWelderCost);
break;
}
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
ArmouryFilter.MaxSearchRadius = BALANCE_VAR(kArmoryBuildDistance);
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
if (!NextRequest->bAcknowledged)
{
char msg[128];
sprintf(msg, "Get to an working armory %s, and ask again.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
NextRequest->bAcknowledged = true;
}
return false;
}
if (pBot->Player->GetResources() < Cost)
{
if (!NextRequest->bAcknowledged)
{
char msg[128];
sprintf(msg, "Wait for resources %s, I'll drop it soon.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
NextRequest->bAcknowledged = true;
}
return false;
}
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f);
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation);
if (vDist2DSq(ProjectedDeployLocation, NearestArmoury->Location) < BALANCE_VAR(kArmoryBuildDistance))
{
bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, ProjectedDeployLocation);
if (bSuccess)
{
NextRequest->bResponded = bSuccess;
return true;
}
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
@ -2497,11 +2552,14 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
if (vIsZero(DeployLocation))
{
char msg[128];
sprintf(msg, "I can't find a drop location, %s. Try asking again elsewhere.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
NextRequest->bResponded = true;
return false;
}
bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_WELDER, DeployLocation);
bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, DeployLocation);
NextRequest->ResponseAttempts++;
@ -2510,104 +2568,59 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
}
if (NextRequest->RequestType == BUILD_SHOTGUN)
if (NextRequest->RequestType == BUILD_HMG || NextRequest->RequestType == BUILD_GRENADE_GUN)
{
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; }
AvHAIDeployableItemType ItemToDrop = (NextRequest->RequestType == BUILD_HMG) ? DEPLOYABLE_ITEM_HMG : DEPLOYABLE_ITEM_GRENADELAUNCHER;
float Cost = (NextRequest->RequestType == BUILD_HMG) ? BALANCE_VAR(kHMGCost) : BALANCE_VAR(kGrenadeLauncherCost);
DeployableSearchFilter ArmouryFilter;
ArmouryFilter.DeployableTeam = CommanderTeam;
ArmouryFilter.DeployableTypes = STRUCTURE_MARINE_ADVARMOURY;
ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
ArmouryFilter.MaxSearchRadius = BALANCE_VAR(kArmoryBuildDistance);
AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter);
if (!NearestArmoury)
{
NextRequest->bResponded = true;
if (!NextRequest->bAcknowledged)
{
char msg[128];
sprintf(msg, "Get to an advanced armory %s, and I'll drop it for you.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
NextRequest->bAcknowledged = true;
}
return false;
}
if (pBot->Player->GetResources() < Cost)
{
if (!NextRequest->bAcknowledged)
{
char msg[128];
sprintf(msg, "Wait for resources %s, will drop asap.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
NextRequest->bAcknowledged = true;
}
return false;
}
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f);
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation);
if (vDist2DSq(ProjectedDeployLocation, NearestArmoury->Location) < BALANCE_VAR(kArmoryBuildDistance))
{
bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, ProjectedDeployLocation);
if (bSuccess)
{
NextRequest->bResponded = bSuccess;
return true;
}
}
Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f));
if (vIsZero(DeployLocation))
@ -2617,50 +2630,14 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
if (vIsZero(DeployLocation))
{
char msg[128];
sprintf(msg, "I can't find a drop location, %s. Try asking again elsewhere.", STRING(Requestor->v.netname));
BotSay(pBot, true, 0.5f, msg);
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_GRENADE_GUN)
{
if (pBot->Player->GetResources() < BALANCE_VAR(kGrenadeLauncherCost)) { 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_GRENADELAUNCHER, DeployLocation);
bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, DeployLocation);
NextRequest->ResponseAttempts++;
@ -3197,6 +3174,7 @@ void AICOMM_ReceiveChatRequest(AvHAIPlayer* Commander, edict_t* Requestor, const
RequestRef->RequestTime = gpGlobals->time;
RequestRef->RequestType = NewRequestType;
RequestRef->Requestor = Requestor;
RequestRef->RequestLocation = UTIL_GetFloorUnderEntity(Requestor) + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f);
if (!ExistingRequest)
{

View file

@ -690,9 +690,11 @@ typedef struct _AI_COMMANDER_REQUEST
bool bNewRequest = false; // Is this a new request just come in?
edict_t* Requestor = nullptr; // Who sent the request?
AvHMessageID RequestType = MESSAGE_NULL; // What did they request?
bool bAcknowledged = false; // If we can't satisfy the request right now, have we at least acknowledged it?
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?
Vector RequestLocation = g_vecZero; // Where was the request raised? Ideal drop location for stuff
} ai_commander_request;
typedef struct AVH_AI_PLAYER

View file

@ -276,7 +276,7 @@ Vector UTIL_GetVectorNormal(const Vector vec)
// Returns a 2D (Z axis is 0) normalized copy of the supplied Vector. Original value is unmodified
Vector UTIL_GetVectorNormal2D(const Vector vec)
{
if (vec == ZERO_VECTOR) { return ZERO_VECTOR; }
if (vec.x == 0.0f && vec.y == 0.0f) { return ZERO_VECTOR; }
Vector result;
float len = sqrt((vec.x * vec.x) + (vec.y * vec.y));

View file

@ -1495,6 +1495,37 @@ Vector AdjustPointForPathfinding(const Vector Point)
}
Vector AdjustPointForPathfinding(const Vector Point, const nav_profile& NavProfile)
{
Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(Point, Vector(400.0f, 100.0f, 400.0f), NavProfile);
int PointContents = UTIL_PointContents(ProjectedPoint);
if (PointContents == CONTENTS_SOLID)
{
int PointContents = UTIL_PointContents(ProjectedPoint + Vector(0.0f, 0.0f, 32.0f));
if (PointContents != CONTENTS_SOLID && PointContents != CONTENTS_LADDER)
{
Vector TraceStart = ProjectedPoint + Vector(0.0f, 0.0f, 32.0f);
Vector TraceEnd = TraceStart - Vector(0.0f, 0.0f, 50.0f);
Vector NewPoint = UTIL_GetHullTraceHitLocation(TraceStart, TraceEnd, point_hull);
if (!vIsZero(NewPoint)) { return NewPoint; }
}
}
else
{
Vector TraceStart = ProjectedPoint + Vector(0.0f, 0.0f, 5.0f);
Vector TraceEnd = TraceStart - Vector(0.0f, 0.0f, 32.0f);
Vector NewPoint = UTIL_GetHullTraceHitLocation(TraceStart, TraceEnd, point_hull);
if (!vIsZero(NewPoint)) { return NewPoint; }
}
return ProjectedPoint;
}
// Special path finding that takes flight movement into account
dtStatus FindFlightPathToPoint(const nav_profile &NavProfile, Vector FromLocation, Vector ToLocation, vector<bot_path_node>& path, float MaxAcceptableDistance)
{
@ -2220,7 +2251,7 @@ bool HasBotCompletedWalkMove(const AvHAIPlayer* pBot, Vector MoveStart, Vector M
if (NextMoveFlag != SAMPLE_POLYFLAGS_DISABLED)
{
bNextPointReachable = UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, NextMoveDestination);
bNextPointReachable = UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, NextMoveDestination);
}
return vPointOverlaps3D(MoveEnd, pBot->Edict->v.absmin, pBot->Edict->v.absmax) || (bNextPointReachable && vDist2DSq(pBot->Edict->v.origin, MoveEnd) < sqrf(GetPlayerRadius(pBot->Edict) * 2.0f));
@ -3410,9 +3441,13 @@ void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vect
void BlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
{
Vector vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint);
if (vIsZero(vForward))
{
vForward = UTIL_GetForwardVector2D(pBot->Edict->v.angles);
}
pBot->desiredMovementDir = vForward;
BotJump(pBot);
@ -4229,8 +4264,8 @@ bool IsBotOffWalkNode(const AvHAIPlayer* pBot, Vector MoveStart, Vector MoveEnd,
if (vDist2DSq(pBot->Edict->v.origin, NearestPointOnLine) > sqrf(GetPlayerRadius(pBot->Edict) * 3.0f)) { return true; }
if (vEquals2D(NearestPointOnLine, MoveStart) && !UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, MoveStart)) { return true; }
if (vEquals2D(NearestPointOnLine, MoveEnd) && !UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, MoveEnd)) { return true; }
if (vEquals2D(NearestPointOnLine, MoveStart) && !UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, MoveStart)) { return true; }
if (vEquals2D(NearestPointOnLine, MoveEnd) && !UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, MoveEnd)) { return true; }
return false;
@ -5838,7 +5873,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
Vector NavAdjustedDestination = AdjustPointForPathfinding(Destination);
if (vIsZero(NavAdjustedDestination)) { return false; }
PathFindingStatus = FindPathClosestToPoint(pBot, pBot->BotNavInfo.MoveStyle, pBot->CollisionHullBottomLocation, NavAdjustedDestination, BotNavInfo->CurrentPath, MaxAcceptableDist);
PathFindingStatus = FindPathClosestToPoint(pBot, pBot->BotNavInfo.MoveStyle, pBot->CurrentFloorPosition, NavAdjustedDestination, BotNavInfo->CurrentPath, MaxAcceptableDist);
}
pBot->BotNavInfo.NextForceRecalc = 0.0f;

View file

@ -344,6 +344,7 @@ void MoveToWithoutNav(AvHAIPlayer* pBot, const Vector Destination);
void HandlePlayerAvoidance(AvHAIPlayer* pBot, const Vector MoveDestination);
Vector AdjustPointForPathfinding(const Vector Point);
Vector AdjustPointForPathfinding(const Vector Point, const nav_profile& NavProfile);
// Special path finding that takes the presence of phase gates into account
dtStatus FindFlightPathToPoint(const nav_profile& NavProfile, Vector FromLocation, Vector ToLocation, vector<bot_path_node>& path, float MaxAcceptableDistance);

View file

@ -1032,11 +1032,16 @@ void BotEvolveLifeform(AvHAIPlayer* pBot, Vector DesiredEvolveLocation, AvHMessa
// We're already the target lifeform, don't do anything
if (TargetUser3 == pBot->Player->GetUser3()) { return; }
Vector EvolvePoint = UTIL_ProjectPointToNavmesh(DesiredEvolveLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
Vector EvolvePoint = AdjustPointForPathfinding(DesiredEvolveLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
if (vIsZero(EvolvePoint))
{
EvolvePoint = DesiredEvolveLocation;
EvolvePoint = UTIL_ProjectPointToNavmesh(DesiredEvolveLocation, Vector(400.0f, 400.0f, 400.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
}
if (vIsZero(EvolvePoint))
{
EvolvePoint = UTIL_ProjectPointToNavmesh(DesiredEvolveLocation, Vector(400.0f, 400.0f, 400.0f), GetBaseNavProfile(GORGE_BASE_NAV_PROFILE));
}
if (vDist2DSq(pBot->Edict->v.origin, EvolvePoint) > sqrf(32.0f))
@ -1592,11 +1597,13 @@ void UpdateBotChat(AvHAIPlayer* pBot)
{
if (pBot->ChatMessages[i].bIsTeamSay)
{
CLIENT_COMMAND(pBot->Edict, "say_team %s", pBot->ChatMessages[i].msg);
//CLIENT_COMMAND(pBot->Edict, "say_team %s", pBot->ChatMessages[i].msg);
AIPlayer_Say(pBot->Edict, 1, pBot->ChatMessages[i].msg);
}
else
{
CLIENT_COMMAND(pBot->Edict, "say %s", pBot->ChatMessages[i].msg);
//CLIENT_COMMAND(pBot->Edict, "say %s", pBot->ChatMessages[i].msg);
AIPlayer_Say(pBot->Edict, 0, pBot->ChatMessages[i].msg);
}
pBot->ChatMessages[i].bIsPending = false;
break;
@ -1837,7 +1844,7 @@ void CustomThink(AvHAIPlayer* pBot)
pBot->Player->GiveResources(70.0f);
}
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_FIVE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_FIVE);
return;
}
@ -4061,19 +4068,19 @@ void AIPlayerNSAlienThink(AvHAIPlayer* pBot)
{
if (!PlayerHasAlienUpgradeOfType(pBot->Edict, HIVE_TECH_DEFENCE) && AITAC_IsAlienUpgradeAvailableForTeam(pBot->Player->GetTeam(), HIVE_TECH_DEFENCE))
{
BotEvolveUpgrade(pBot, pBot->Edict->v.origin, AlienGetDesiredUpgrade(pBot, HIVE_TECH_DEFENCE));
BotEvolveUpgrade(pBot, pBot->CurrentFloorPosition, AlienGetDesiredUpgrade(pBot, HIVE_TECH_DEFENCE));
return;
}
if (!PlayerHasAlienUpgradeOfType(pBot->Edict, HIVE_TECH_MOVEMENT) && AITAC_IsAlienUpgradeAvailableForTeam(pBot->Player->GetTeam(), HIVE_TECH_MOVEMENT))
{
BotEvolveUpgrade(pBot, pBot->Edict->v.origin, AlienGetDesiredUpgrade(pBot, HIVE_TECH_MOVEMENT));
BotEvolveUpgrade(pBot, pBot->CurrentFloorPosition, AlienGetDesiredUpgrade(pBot, HIVE_TECH_MOVEMENT));
return;
}
if (!PlayerHasAlienUpgradeOfType(pBot->Edict, HIVE_TECH_SENSORY) && AITAC_IsAlienUpgradeAvailableForTeam(pBot->Player->GetTeam(), HIVE_TECH_SENSORY))
{
BotEvolveUpgrade(pBot, pBot->Edict->v.origin, AlienGetDesiredUpgrade(pBot, HIVE_TECH_SENSORY));
BotEvolveUpgrade(pBot, pBot->CurrentFloorPosition, AlienGetDesiredUpgrade(pBot, HIVE_TECH_SENSORY));
return;
}
}
@ -4945,7 +4952,7 @@ void TestNavThink(AvHAIPlayer* pBot)
{
if (pBot->Player->GetResources() >= BALANCE_VAR(kGorgeCost))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_TWO);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_TWO);
return;
}
}
@ -4954,7 +4961,7 @@ void TestNavThink(AvHAIPlayer* pBot)
{
if (pBot->Player->GetResources() >= BALANCE_VAR(kLerkCost))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_THREE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_THREE);
return;
}
else
@ -4967,7 +4974,7 @@ void TestNavThink(AvHAIPlayer* pBot)
{
if (pBot->Player->GetResources() >= BALANCE_VAR(kFadeCost))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_FOUR);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_FOUR);
return;
}
else
@ -4980,7 +4987,7 @@ void TestNavThink(AvHAIPlayer* pBot)
{
if (pBot->Player->GetResources() >= BALANCE_VAR(kOnosCost))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_FIVE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_FIVE);
return;
}
else
@ -5084,6 +5091,7 @@ void AIPlayerReceiveBuildOrder(AvHAIPlayer* pBot, edict_t* BuildTarget)
void AIPlayerReceiveMoveOrder(AvHAIPlayer* pBot, Vector Destination)
{
Vector NavMoveLocation = AdjustPointForPathfinding(Destination);
Vector ActualMoveLocation = FindClosestNavigablePointToDestination(pBot->BotNavInfo.NavProfile, pBot->CurrentFloorPosition, NavMoveLocation, UTIL_MetresToGoldSrcUnits(5.0f));
@ -5610,7 +5618,7 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
if (IsPlayerGorge(pBot->Edict) && gpGlobals->time - pBot->LastCombatTime > 5.0f)
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_ONE);
AITASK_SetEvolveTask(pBot, Task, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_ONE, true);
return;
}
@ -6075,14 +6083,14 @@ void AIPlayerSetAlienHarasserPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas
}
else
{
AITASK_SetEvolveTask(pBot, Task, pBot->Edict->v.origin, ALIEN_LIFEFORM_THREE, true);
AITASK_SetEvolveTask(pBot, Task, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_THREE, true);
return;
}
}
if (IsPlayerGorge(pBot->Edict))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_ONE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_ONE);
return;
}

View file

@ -660,6 +660,19 @@ void AIMGR_UpdateAIPlayers()
UTIL_DrawLine(INDEXENT(1), bot->Edict->v.origin, CurrentPathNode.FromLocation, 255, 0, 0);
UTIL_DrawLine(INDEXENT(1), bot->Edict->v.origin, CurrentPathNode.Location, 0, 128, 0);
}
if (bot->CurrentTask && bot->CurrentTask->TaskType != TASK_NONE)
{
if (!FNullEnt(bot->CurrentTask->TaskTarget))
{
UTIL_DrawLine(INDEXENT(1), bot->Edict->v.origin, bot->CurrentTask->TaskTarget->v.origin, 255, 0, 0);
}
if (!vIsZero(bot->CurrentTask->TaskLocation))
{
UTIL_DrawLine(INDEXENT(1), bot->Edict->v.origin, bot->CurrentTask->TaskLocation, 255, 0, 0);
}
}
}
if (bHasRoundStarted)

View file

@ -1144,4 +1144,118 @@ Vector UTIL_GetNearestLadderCentrePoint(const Vector SearchLocation)
}
return SearchLocation;
}
void AIPlayer_Say(edict_t* pEntity, int teamonly, const char* Msg)
{
AvHPlayer* client;
AvHPlayer* theTalkingPlayer = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(pEntity));
int j;
char* p;
char text[256];
char szTemp[256];
bool theTalkerInReadyRoom = theTalkingPlayer->GetInReadyRoom();
// We can get a raw string now, without the "say " prepended
if (!Msg)
return;
//Not yet.
if (theTalkingPlayer->m_flNextChatTime > gpGlobals->time)
return;
p = (char*)Msg;
// remove quotes if present
if (*p == '"')
{
p++;
p[strlen(p) - 1] = 0;
}
// make sure the text has content
char* pc = p;
for (pc = p; pc != NULL && *pc != 0; pc++)
{
if (isprint(*pc) && !isspace(*pc))
{
pc = NULL; // we've found an alphanumeric character, so text is valid
break;
}
}
if (pc != NULL)
return; // no character found, so say nothing
// turn on color set 2 (color on, no sound)
if (teamonly)
sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname));
else
sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname));
j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator
if ((int)strlen(p) > j)
p[j] = 0;
strcat(text, p);
strcat(text, "\n");
theTalkingPlayer->m_flNextChatTime = gpGlobals->time + CHAT_INTERVAL;
// loop through all players
// Start with the first player.
// This may return the world in single player if the client types something between levels or during spawn
// so check it, or it will infinite loop
client = NULL;
while (((client = (AvHPlayer*)UTIL_FindEntityByClassname(client, "player")) != NULL) && (!FNullEnt(client->edict())))
{
if (!client->pev)
continue;
if (client->edict() == pEntity)
continue;
if (!(client->IsNetClient())) // Not a client ? (should never be true)
continue;
// Don't differentiate between team and non-team when not playing
bool theTalkingPlayerIsPlaying = ((theTalkingPlayer->GetPlayMode() == PLAYMODE_PLAYING) || (theTalkingPlayer->GetPlayMode() == PLAYMODE_AWAITINGREINFORCEMENT) || (theTalkingPlayer->GetPlayMode() == PLAYMODE_REINFORCING));
bool theClientIsPlaying = ((client->GetPlayMode() == PLAYMODE_PLAYING) || (client->GetPlayMode() == PLAYMODE_AWAITINGREINFORCEMENT) || (client->GetPlayMode() == PLAYMODE_REINFORCING));
bool theTalkerIsObserver = theTalkingPlayer->IsObserver();
bool theClientIsObserver = client->IsObserver();
bool theClientIsHLTV = (client->pev->flags & FL_PROXY);
bool theClientInReadyRoom = client->GetInReadyRoom();
if (theClientInReadyRoom != theTalkerInReadyRoom && !theClientIsHLTV)
{
continue;
}
if (!theClientIsObserver || theClientIsPlaying) // Non-playing Observers hear everything.
{
if (theTalkingPlayerIsPlaying && teamonly && g_pGameRules->PlayerRelationship(client, CBaseEntity::Instance(pEntity)) != GR_TEAMMATE)
continue;
// chat can never go between play area and non-play area
if (theTalkingPlayerIsPlaying != theClientIsPlaying && !theClientIsHLTV)
continue;
// chat of any kind doesn't go from ready room to play area in tournament mode
if (theTalkerInReadyRoom && GetGameRules()->GetIsTournamentMode() && theClientIsPlaying && !theClientIsHLTV)
continue;
}
UTIL_SayText(text, client, ENTINDEX(pEntity));
}
// print to the sending client
UTIL_SayText(text, CBaseEntity::Instance(ENT(pEntity)));
// echo to server console
g_engfuncs.pfnServerPrint(text);
// UTIL_LogPrintf( "%s %s \"%s\"\n", GetLogStringForPlayer( pEntity ).c_str(), temp, p );
}

View file

@ -71,6 +71,8 @@ bool IsPlayerCharging(const edict_t* Player);
// Is the player buffed by catalysts (for marines) or primal scream (for aliens)?
bool IsPlayerBuffed(const edict_t* Player);
void AIPlayer_Say(edict_t* pEntity, int teamonly, const char* Msg);
// Returns the player's max armour, based on armour research levels (marines) or class and carapace level (aliens)
int GetPlayerMaxArmour(const edict_t* Player);

View file

@ -692,10 +692,18 @@ Vector AITAC_GetFloorLocationForHive(const AvHAIHiveDefinition* Hive)
if (!vIsZero(NearestNavigableLoc))
{
Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(NearestNavigableLoc, Vector(500.0f, 500.0f, 500.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
if (!vIsZero(ProjectedPoint)) { return ProjectedPoint; }
return NearestNavigableLoc;
}
else
{
Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(HiveFloorLoc, Vector(500.0f, 500.0f, 500.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
if (!vIsZero(ProjectedPoint)) { return ProjectedPoint; }
return HiveFloorLoc;
}
@ -811,7 +819,7 @@ void AITAC_RefreshHiveData()
it->NextFloorLocationCheck = gpGlobals->time + (5.0f + (0.1f * NextRefresh));
//AITAC_RefreshReachabilityForHive(&(*it));
AITAC_RefreshReachabilityForHive(&(*it));
}
NextRefresh++;

View file

@ -1228,7 +1228,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
Vector ReinforceLocation = Task->TaskTarget->v.origin;
Vector ReinforceLocation = UTIL_ProjectPointToNavmesh(UTIL_GetEntityGroundLocation(Task->TaskTarget), pBot->BotNavInfo.NavProfile);
float SearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
if (Task->StructureType == STRUCTURE_ALIEN_HIVE)
@ -1615,7 +1615,7 @@ void BotProgressAttackTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
if (IsPlayerGorge(pBot->Edict) && !PlayerHasWeapon(pBot->Player, WEAPON_GORGE_BILEBOMB))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_ONE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_ONE);
return;
}
@ -2062,7 +2062,7 @@ void BotAlienPlaceChamber(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, AvHAIDeploya
if (!IsPlayerGorge(pBot->Edict))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_TWO);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_TWO);
return;
}
@ -2117,7 +2117,7 @@ void BotAlienBuildResTower(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAI
if (!IsPlayerGorge(pBot->Edict))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_TWO);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_TWO);
return;
}
@ -2170,7 +2170,7 @@ void BotAlienBuildHive(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIHive
if (!IsPlayerGorge(pBot->Edict))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_TWO);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_TWO);
return;
}
@ -2195,7 +2195,7 @@ void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget)
}
else
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_TWO);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_TWO);
return;
}
}
@ -2274,7 +2274,7 @@ void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
}
else
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_ONE);
BotEvolveLifeform(pBot, pBot->CurrentFloorPosition, ALIEN_LIFEFORM_ONE);
return;
}
}
@ -2446,12 +2446,19 @@ void BotProgressWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
// so instead aim at the closest point on the func_weldable to us.
if (!IsEdictPlayer(Task->TaskTarget) && !IsEdictStructure(Task->TaskTarget))
{
Vector BBMin = Task->TaskTarget->v.absmin + Vector(5.0f, 5.0f, 5.0f);
Vector BBMax = Task->TaskTarget->v.absmax - Vector(5.0f, 5.0f, 5.0f);
if (Task->TaskTarget->v.size.Length2D() < 100.0f)
{
AimLocation = UTIL_GetCentreOfEntity(Task->TaskTarget);
}
else
{
Vector BBMin = Task->TaskTarget->v.absmin + Vector(5.0f, 5.0f, 5.0f);
Vector BBMax = Task->TaskTarget->v.absmax - Vector(5.0f, 5.0f, 5.0f);
vScaleBB(BBMin, BBMax, 0.75f);
vScaleBB(BBMin, BBMax, 0.75f);
AimLocation = vClosestPointOnBB(pBot->Edict->v.origin, BBMin, BBMax);
AimLocation = vClosestPointOnBB(pBot->Edict->v.origin, BBMin, BBMax);
}
}
@ -2690,12 +2697,8 @@ void BotGuardLocation(AvHAIPlayer* pBot, const Vector GuardLocation)
if (DistFromGuardLocation > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
{
pBot->GuardInfo.GuardLocation = g_vecZero;
pBot->GuardInfo.GuardStartLookTime = 0.0f;
pBot->GuardInfo.ThisGuardLookTime = 0.0f;
pBot->GuardInfo.GuardStartStandTime = 0.0f;
pBot->GuardInfo.ThisGuardStandTime = 0.0f;
MoveTo(pBot, GuardLocation, MOVESTYLE_NORMAL);
memset(&pBot->GuardInfo, 0, sizeof(AvHAIGuardInfo));
MoveTo(pBot, GuardLocation, MOVESTYLE_NORMAL, UTIL_MetresToGoldSrcUnits(10.0f));
return;
}
@ -3157,6 +3160,8 @@ void AITASK_SetMoveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const Vector L
if (vIsZero(Location)) { return; }
UpdateBotMoveProfile(pBot, MOVESTYLE_NORMAL);
Vector MoveStart = AdjustPointForPathfinding(pBot->CurrentFloorPosition);
Vector MoveEnd = AdjustPointForPathfinding(Location);