diff --git a/main/source/mod/AIPlayers/AvHAIMath.cpp b/main/source/mod/AIPlayers/AvHAIMath.cpp index 619e5990..8aa0b351 100644 --- a/main/source/mod/AIPlayers/AvHAIMath.cpp +++ b/main/source/mod/AIPlayers/AvHAIMath.cpp @@ -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) { diff --git a/main/source/mod/AIPlayers/AvHAIMath.h b/main/source/mod/AIPlayers/AvHAIMath.h index 532482d2..e1fcbfc7 100644 --- a/main/source/mod/AIPlayers/AvHAIMath.h +++ b/main/source/mod/AIPlayers/AvHAIMath.h @@ -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); diff --git a/main/source/mod/AIPlayers/AvHAINavigation.cpp b/main/source/mod/AIPlayers/AvHAINavigation.cpp index 81c7296e..0a430190 100644 --- a/main/source/mod/AIPlayers/AvHAINavigation.cpp +++ b/main/source/mod/AIPlayers/AvHAINavigation.cpp @@ -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); + } + } diff --git a/main/source/mod/AvHConsoleCommands.cpp b/main/source/mod/AvHConsoleCommands.cpp index a5785e75..6d400c22 100644 --- a/main/source/mod/AvHConsoleCommands.cpp +++ b/main/source/mod/AvHConsoleCommands.cpp @@ -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); } }