Lift improvements

* Bots avoid getting crushed under a lift when summoning it
* Bots are better at judging which stop a platform needs to be at
This commit is contained in:
RGreenlees 2023-11-25 23:35:24 +00:00 committed by pierow
parent 6ebe05483c
commit 39f183864c
4 changed files with 95 additions and 22 deletions

View file

@ -46,6 +46,18 @@ Vector UTIL_GetSurfaceNormal(const Vector v1, const Vector v2, const Vector v3)
return normal;
}
bool vPointOverlaps2D(const Vector Point, const Vector MinBB, const Vector MaxBB)
{
return (Point.x >= MinBB.x && Point.x <= MaxBB.x
&& Point.y >= MinBB.y && Point.y <= MaxBB.y);
}
bool vBBOverlaps2D(const Vector MinBBA, const Vector MaxBBA, const Vector MinBBB, const Vector MaxBBB)
{
return ( (MinBBA.x < MaxBBB.x && MaxBBA.x > MinBBB.x)
&& (MinBBA.y < MaxBBB.y && MaxBBA.y > MinBBB.y));
}
// Returns the 3D distance of point from a line defined between lineFrom and lineTo
float vDistanceFromLine3D(const Vector lineFrom, const Vector lineTo, const Vector CheckPoint)
{

View file

@ -115,6 +115,9 @@ Vector UTIL_GetCrossProduct(const Vector v1, const Vector v2);
// Returns the surface normal of a poly defined at points v1, v2 and v3 (clockwise)
Vector UTIL_GetSurfaceNormal(const Vector v1, const Vector v2, const Vector v3);
bool vPointOverlaps2D(const Vector Point, const Vector MinBB, const Vector MaxBB);
bool vBBOverlaps2D(const Vector MinBBA, const Vector MaxBBA, const Vector MinBBB, const Vector MaxBBB);
// WIP: Trying to get a working random unit vector in cone. Not currently used
Vector UTIL_GetRandomUnitVectorInCone(const Vector ConeDirection, const float HalfAngleRadians);
Vector random_unit_vector_within_cone(const Vector Direction, double HalfAngleRadians);

View file

@ -3506,7 +3506,6 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
return;
}
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, UTIL_GetCentreOfEntity(NearestLift->DoorEdict));
Vector LiftPosition = UTIL_GetCentreOfEntity(NearestLift->DoorEdict);
@ -3520,8 +3519,10 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
// Find the desired stop point for us to get onto the lift
for (auto it = NearestLift->StopPoints.begin(); it != NearestLift->StopPoints.end(); it++)
{
float thisStartDist = vDist3DSq(*it, StartPoint);
float thisEndDist = vDist3DSq(*it, EndPoint);
Vector LiftStopPoint = (*it) + Vector(0.0f, 0.0f, NearestLift->DoorEdict->v.size.z * 0.5f);
float thisStartDist = vDist3DSq(LiftStopPoint, StartPoint);
float thisEndDist = vDist3DSq(LiftStopPoint, EndPoint);
if (vIsZero(DesiredStartStop) || thisStartDist < minStartDist)
{
DesiredStartStop = *it;
@ -3569,11 +3570,27 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
return;
}
if (bIsLiftMoving)
{
AITASK_SetMoveTask(pBot, &pBot->BotNavInfo.MovementTask, StartPoint, true);
if (vDist2DSq(pBot->Edict->v.origin, StartPoint) > sqrf(50.0f))
{
AITASK_SetMoveTask(pBot, &pBot->BotNavInfo.MovementTask, StartPoint, true);
}
return;
}
if (bIsLiftAtOrNearStart && vEquals(DesiredStartStop, DesiredEndStop))
{
if (!bIsOnLift)
{
if (vDist2DSq(pBot->Edict->v.origin, StartPoint) > sqrf(50.0f))
{
AITASK_SetMoveTask(pBot, &pBot->BotNavInfo.MovementTask, StartPoint, true);
return;
}
pBot->desiredMovementDir = UTIL_GetVectorNormal2D(LiftPosition - pBot->CollisionHullBottomLocation);
}
return;
}
@ -3588,7 +3605,7 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
for (auto it = NearestLift->TriggerEnts.begin(); it != NearestLift->TriggerEnts.end(); it++)
{
if (!FNullEnt(it->Edict) && it->bIsActivated)
if (it->bIsActivated)
{
Vector CheckLocation = UTIL_GetCentreOfEntity(NearestLift->DoorEdict);
CheckLocation.z = pBot->Edict->v.origin.z;
@ -3622,9 +3639,21 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
{
if (gpGlobals->time < NearestLiftTrigger->NextActivationTime || !(NearestLift->DoorEdict->v.spawnflags & SF_TRAIN_WAIT_RETRIGGER) || (NearestLift->DoorEntity && NearestLift->DoorEntity->m_flWait > 0.0f))
{
if (!bIsOnLift && vDist2DSq(pBot->Edict->v.origin, StartPoint) > sqrf(50.0f) && !bIsLiftAtOrNearStart)
if (!bIsOnLift && !bIsLiftAtOrNearStart)
{
AITASK_SetMoveTask(pBot, &pBot->BotNavInfo.MovementTask, StartPoint, true);
// Make sure we won't be squashed by the lift coming down on us
if (vBBOverlaps2D(pBot->Edict->v.absmin, pBot->Edict->v.absmax, NearestLift->DoorEdict->v.absmin, NearestLift->DoorEdict->v.absmax))
{
pBot->desiredMovementDir = UTIL_GetVectorNormal2D(StartPoint - DesiredStartStop);
}
else
{
if (vDist2DSq(pBot->Edict->v.origin, StartPoint) > sqrf(32.0f))
{
AITASK_SetMoveTask(pBot, &pBot->BotNavInfo.MovementTask, StartPoint, true);
}
}
}
else
{
@ -3646,8 +3675,6 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
if (ButtonReachableFromLift)
{
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, ButtonFloorLocation, 255, 255, 0);
if (IsPlayerInUseRange(pBot->Edict, NearestLiftTrigger->Edict))
{
BotUseObject(pBot, NearestLiftTrigger->Edict, false);
@ -3657,11 +3684,13 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
if (!bIsOnLift)
{
pBot->desiredMovementDir = UTIL_GetVectorNormal2D(LiftPosition - pBot->Edict->v.origin);
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, ButtonFloorLocation, 255, 0, 0);
return;
}
else
{
pBot->desiredMovementDir = UTIL_GetVectorNormal2D(ButtonFloorLocation - pBot->Edict->v.origin);
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, ButtonFloorLocation, 255, 255, 0);
return;
}
}
@ -3672,9 +3701,6 @@ void LiftMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
Vector UseLocation = UTIL_GetButtonFloorLocation(pBot->Edict->v.origin, NearestLiftTrigger->Edict);
AITASK_SetUseTask(pBot, &pBot->BotNavInfo.MovementTask, NearestLiftTrigger->Edict, UseLocation, true);
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, UTIL_GetCentreOfEntity(NearestLiftTrigger->Edict), 10.0f, 255, 255, 0);
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, UseLocation, 10.0f, 255, 0, 0);
}
else if (NearestLiftTrigger->TriggerType == DOOR_TRIGGER)
{
@ -5823,6 +5849,8 @@ bool IsBotStuck(AvHAIPlayer* pBot, const Vector MoveDestination)
// If invalid move destination then bail out
if (vIsZero(MoveDestination) || vIsZero(pBot->desiredMovementDir)) { return false; }
if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_LIFT) { return false; }
// If moving to a new destination set a new distance baseline. We do not reset the stuck timer
if (MoveDestination != pBot->BotNavInfo.StuckCheckMoveLocation)
{
@ -6810,7 +6838,7 @@ bool UTIL_IsTriggerLinkedToDoor(CBaseEntity* TriggerEntity, CBaseEntity* Door)
CBaseEntity* TargetEntity = UTIL_FindEntityByTargetname(NULL, targetOnFinish);
if (TargetEntity && UTIL_IsTriggerLinkedToDoor(TargetEntity, Door)) { return true; }
if (TargetEntity && TargetEntity != TriggerEntity && UTIL_IsTriggerLinkedToDoor(TargetEntity, Door)) { return true; }
return false;
}
@ -6823,8 +6851,13 @@ bool UTIL_IsTriggerLinkedToDoor(CBaseEntity* TriggerEntity, CBaseEntity* Door)
{
CBaseEntity* MMTargetEntity = UTIL_FindEntityByTargetname(NULL, STRING(MMRef->m_iTargetName[i]));
if (!MMTargetEntity) { continue; }
if (MMTargetEntity == Door) { return true; }
// Don't check this if it's targeting us (circular reference)
if (FStrEq(STRING(MMTargetEntity->pev->target), STRING(TriggerEntity->pev->targetname))) { continue; }
if (MMTargetEntity && UTIL_IsTriggerLinkedToDoor(MMTargetEntity, Door)) { return true; }
}
@ -6891,7 +6924,11 @@ bool UTIL_IsTriggerLinkedToDoor(CBaseEntity* TriggerEntity, CBaseEntity* Door)
{
CBaseEntity* TargetEntity = UTIL_FindEntityByTargetname(NULL, STRING(ToggleRef->pev->target));
if (TargetEntity && UTIL_IsTriggerLinkedToDoor(TargetEntity, Door)) { return true; }
// Don't check this if it's targeting us (circular reference)
if (!FStrEq(STRING(TargetEntity->pev->target), STRING(TriggerEntity->pev->targetname)))
{
if (TargetEntity && UTIL_IsTriggerLinkedToDoor(TargetEntity, Door)) { return true; }
}
FOR_ALL_ENTITIES("trigger_changetarget", CTriggerChangeTarget*)
if (theEntity->GetNextTarget() && theEntity->GetNextTarget()->edict() == TriggerEntity->edict() && FStrEq(STRING(theEntity->GetNewTargetName()), STRING(Door->pev->targetname)))
@ -7665,8 +7702,17 @@ void UTIL_PopulateDoors()
}
else
{
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) + ToggleRef->m_vecPosition1);
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) + ToggleRef->m_vecPosition2);
if (NewDoor.DoorEdict->v.spawnflags & DOOR_START_OPEN)
{
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) + ToggleRef->m_vecPosition2);
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) - ToggleRef->m_vecPosition1);
}
else
{
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) + ToggleRef->m_vecPosition1);
NewDoor.StopPoints.push_back(UTIL_GetCentreOfEntity(NewDoor.DoorEdict) + ToggleRef->m_vecPosition2);
}
}

View file

@ -1500,6 +1500,18 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd )
if (Door)
{
Vector CurrPoint = ZERO_VECTOR;
for (auto stop = Door->StopPoints.begin(); stop != Door->StopPoints.end(); stop++)
{
Vector Point = (*stop);
Point.z += Door->DoorEdict->v.size.z * 0.5f;
UTIL_DrawLine(INDEXENT(1), INDEXENT(1)->v.origin, Point, 10.0f);
}
const dtOffMeshConnection* NearestCon = DEBUG_FindNearestOffMeshConnectionToPoint(theAvHPlayer->pev->origin, SAMPLE_POLYFLAGS_LIFT);
if (NearestCon)
@ -1508,17 +1520,17 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd )
Vector ConnectionStart = Vector(NearestCon->pos[0], -NearestCon->pos[2], NearestCon->pos[1]);
Vector ConnectionEnd = Vector(NearestCon->pos[3], -NearestCon->pos[5], NearestCon->pos[4]);
UTIL_DrawLine(INDEXENT(1), ConnectionStart, ConnectionEnd, 10.0f);
//UTIL_DrawLine(INDEXENT(1), ConnectionStart, ConnectionEnd, 10.0f);
for (auto stop = Door->StopPoints.begin(); stop != Door->StopPoints.end(); stop++)
{
UTIL_DrawLine(INDEXENT(1), ConnectionStart, *stop, 10.0f, 255, 0, 0);
//UTIL_DrawLine(INDEXENT(1), ConnectionStart, *stop, 10.0f, 255, 0, 0);
Vector NearestPointStart = UTIL_GetClosestPointOnEntityToLocation(ConnectionStart, Door->DoorEdict, *stop);
Vector NearestPointEnd = UTIL_GetClosestPointOnEntityToLocation(ConnectionEnd, Door->DoorEdict, *stop);
UTIL_DrawLine(INDEXENT(1), ConnectionStart, NearestPointStart, 10.0f, 255, 255, 0);
UTIL_DrawLine(INDEXENT(1), ConnectionEnd, NearestPointEnd, 10.0f, 0, 0, 255);
//UTIL_DrawLine(INDEXENT(1), ConnectionStart, NearestPointStart, 10.0f, 255, 255, 0);
//UTIL_DrawLine(INDEXENT(1), ConnectionEnd, NearestPointEnd, 10.0f, 0, 0, 255);
}
}