Files
firestorm/Gameleap/code/mw4/Code/MW4/AI_Condition.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

553 lines
13 KiB
C++

#include "MW4Headers.hpp"
#include "AI_Condition.hpp"
#include "AI_Weapons.hpp"
#include "MWPlayer.hpp"
#include "VehicleInterface.hpp"
#include "Torso.hpp"
#include "MWMission.hpp"
#include "JumpJet.hpp"
using namespace MW4AI;
using namespace MW4AI::Conditions;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::HittingSomethingElse(TacticInterface& i)
{
AILOGFUNC("Conditions::HittingSomethingElse");
if (i.GetUnableToFireDuration(4.0f) == true)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AnyWeaponReady
//
Fuzzy Conditions::AnyWeaponReady(TacticInterface& i)
{
AILOGFUNC("Conditions::AnyWeaponReady");
if (MW4AI::AnyWeaponReady(i.GetSelf()) == true)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::ProjectileApproaching(TacticInterface& i, Stuff::Scalar min_distance)
{
AILOGFUNC("Conditions::ProjectileApproaching");
AILOG1(min_distance);
if (i.ProjectileApproaching() == true)
{
Stuff::Point3D delta;
delta.Subtract(i.GetProjectileOrigin(),(Stuff::Point3D)i.GetSelf().GetLocalToWorld());
if (delta.GetLengthSquared() < min_distance * min_distance)
{
LOG_AND_RETURN(0);
}
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::Fired(TacticInterface& i, Stuff::Scalar within_when)
{
AILOGFUNC("Conditions::Fired");
AILOG1(within_when);
if (i.FiredWithin(within_when) == true)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::TargetedByEnemy(TacticInterface& i, Stuff::Scalar duration)
{
AILOGFUNC("Conditions::TargetedByEnemy");
AILOG1(duration);
if (i.GetTimeTargetedByEnemy() >= duration)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::Rammed(TacticInterface& i, Stuff::Scalar duration)
{
AILOGFUNC("Conditions::Rammed");
AILOG1(duration);
if (i.GetLastTimeRammedTarget() + duration > gos_GetElapsedTime())
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::InsideRadiusOfTarget(TacticInterface& i, Stuff::Scalar radius)
{
AILOGFUNC("Conditions::InsideRadiusOfTarget");
AILOG1(radius);
if (i.GetDistanceFromTargetSquared() <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::InsideRadiusOfTarget(TacticInterface&i, Stuff::Scalar radius, Stuff::Scalar when)
{
AILOGFUNC("Conditions::InsideRadiusOfTarget");
AILOG2(radius,when);
Stuff::Point3D my_pos(i.GetSelf().GetLocalToWorld());
Stuff::Point3D target_pos;
i.GetTarget().EstimateFuturePosition(&target_pos,(Scalar)when,true);
my_pos.y = 0;
target_pos.y = 0;
if (GetLengthSquared(my_pos,target_pos) <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::InsideRadiusOfRamTarget(TacticInterface& i, Stuff::Scalar radius)
{
AILOGFUNC("Conditions::InsideRadiusOfRamTarget");
AILOG(radius);
Verify(i.GetSelf_AsVehicle() != 0);
Stuff::Scalar time_to_reach = GetApproximateLength((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
(Stuff::Point3D)i.GetTarget().GetLocalToWorld()) / i.GetSelf_AsVehicle()->GetGameModel()->maxSpeed;
Stuff::Point3D target_pos;
i.GetTarget().EstimateFuturePosition(&target_pos,time_to_reach,false);
Stuff::Point3D my_pos((Stuff::Point3D)i.GetSelf().GetLocalToWorld());
my_pos.y = 0;
target_pos.y = 0;
if (GetLengthSquared(my_pos,target_pos) <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy MW4AI::Conditions::InsideWeaponsRadiusOfTarget(TacticInterface& i,
TacticInterface::WR_WHO who,
TacticInterface::WR_QUALIFIER type,
Stuff::Scalar multiplier)
{
AILOGFUNC("Conditions::InsideWeaponsRadiusOfTarget");
AILOG3(who,type,multiplier);
Stuff::Scalar radius = i.WeaponRange(who,type) * multiplier;
if (i.GetDistanceFromTargetSquared() <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy MW4AI::Conditions::InsidePercentileRangeOf(TacticInterface& i, Stuff::Scalar percentile_range, bool nearest_enemy)
{
AILOGFUNC("Conditions::InsidePercentileRangeOfTarget");
AILOG2(percentile_range,nearest_enemy);
Stuff::Scalar radius = i.GetCombatRadiusForRange(percentile_range);
if (nearest_enemy == true)
{
Adept::Entity* nearest = i.GetNearest(true);
if (nearest == 0)
{
nearest = &i.GetTarget();
}
if (GetLengthSquared((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
(Stuff::Point3D)nearest->GetLocalToWorld()) <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
if (i.GetDistanceFromTargetSquared() <= radius * radius)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::VehicleMoving(TacticInterface& i)
{
AILOGFUNC("Conditions::VehicleMoving");
if (i.Moving() == true)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// VehicleCrouching
//
Fuzzy Conditions::VehicleCrouching(TacticInterface& i)
{
AILOGFUNC("Conditions::VehicleCrouching");
if (i.Crouching() == true)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::FacingTarget(TacticInterface& i)
{
AILOGFUNC("Conditions::FacingTarget");
const Stuff::LinearMatrix4D& my_matrix = i.GetSelf().GetLocalToWorld();
Stuff::Point3D target_pos(i.GetTarget().GetLocalToWorld());
Stuff::UnitVector3D my_forward;
my_matrix.GetLocalForwardInWorld(&my_forward);
Stuff::Point3D forward(my_forward);
forward += (Stuff::Point3D)my_matrix;
Stuff::UnitVector3D my_backward;
my_matrix.GetLocalBackwardInWorld(&my_backward);
Stuff::Point3D backward(my_backward);
backward += (Stuff::Point3D)my_matrix;
if (GetLengthSquared(forward,target_pos) < GetLengthSquared(backward,target_pos))
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::InFrontOfTarget(TacticInterface& i, bool fUseTorso)
{
AILOGFUNC("Conditions::InFrontOfTarget");
AILOG1(fUseTorso);
LinearMatrix4D relative_to;
if ((fUseTorso == true) &&
(i.GetTarget().GetTorso() != 0) &&
(i.GetTarget().GetTorso()->twistJoint != 0))
{
Check_Object(i.GetTarget().GetTorso());
relative_to = i.GetTarget().GetTorso()->twistJoint->GetLocalToWorld();
}
else
{
relative_to = i.GetTarget().GetLocalToWorld();
}
Stuff::Point3D delta;
delta.Subtract((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),(Stuff::Point3D)relative_to);
Stuff::UnitVector3D delta_normalized(delta);
Stuff::UnitVector3D local_forward;
relative_to.GetLocalForwardInWorld(&local_forward);
Stuff::Scalar bearing = delta_normalized * local_forward;
bearing += 1;
bearing *= 0.5f;
if (bearing >= 0.5f)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0); // TODO: bearing is already a fuzzy; should return it as a Fuzzy!
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::JumpedWithin(TacticInterface& i, Stuff::Scalar duration)
{
AILOGFUNC("Conditions::JumpedWithin");
AILOG1(duration);
if (i.GetLastTimeJumped() + duration >= gos_GetElapsedTime())
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool Conditions::Jumping(TacticInterface& i)
{
AILOGFUNC("Conditions::Jumping");
if (i.GetSelf().IsDerivedFrom(Mech::DefaultData) == true)
{
Mech* mech = Cast_Object(Mech*,&(i.GetSelf()));
if ((mech->GetJumpJet() != 0) &&
(mech->GetJumpJet()->executionState->GetState() == JumpJet::ExecutionStateEngine::JumpingState))
{
LOG_AND_RETURN(true);
}
}
LOG_AND_RETURN(false);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::CanBeSeenByTarget(TacticInterface& i, Stuff::Scalar within_distance)
{
AILOGFUNC("Conditions::CanBeSeenByTarget");
const Stuff::Scalar distance = GetApproximateLength((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
(Stuff::Point3D)i.GetTarget().GetLocalToWorld());
if (distance > within_distance)
{
LOG_AND_RETURN(0);
}
if ((MWMission::GetInstance() != 0) &&
(MWMission::GetInstance()->GetGameModel() != 0))
{
const Adept::Mission::GameModel* game_model = MWMission::GetInstance()->GetGameModel();
if (distance > game_model->m_generalFogEnd)
{
LOG_AND_RETURN(0);
}
}
FireData fire_data(i.GetSelf(),
i.GetSelf().GetLineOfSight(),
i.GetTarget().GetLineOfSight());
fire_data.Project();
if (fire_data.GetHitResult(&i.GetTarget()) == FireData::HIT_TARGET)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::IsHighOffGround(TacticInterface& i)
{
AILOGFUNC("Conditions::IsHighOffGround");
const Stuff::Point3D my_pos(i.GetSelf().GetLocalToWorld());
BYTE tempmaterial;
if (my_pos.y - 10 > GetMapY(my_pos.x,my_pos.z,&i.GetSelf(),tempmaterial))
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::PlayerWillHitMe(TacticInterface& i,
Stuff::Scalar seconds,
Stuff::Scalar threshold)
{
AILOGFUNC("Conditions::PlayerWillHitMe");
AILOG2(seconds,threshold);
if ((Adept::Player::GetInstance() == 0) ||
(i.GetSelf_AsVehicle() == 0))
{
LOG_AND_RETURN(0);
}
MechWarrior4::MWPlayer* player = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
Check_Object(player);
if (player->GetInterface() == 0)
{
LOG_AND_RETURN(0);
}
Adept::Entity* player_entity = player->GetInterface()->vehicle;
if ((player_entity == 0) ||
(player_entity->GetAlignment() == i.GetSelf().GetAlignment()) ||
(player_entity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData) == false))
{
LOG_AND_RETURN(0);
}
threshold *= threshold;
MechWarrior4::Vehicle* player_vehicle = Cast_Object(MechWarrior4::Vehicle*,player_entity);
if (GetLengthSquared((Stuff::Point3D)player_vehicle->GetLocalToWorld(),
(Stuff::Point3D)i.GetSelf().GetLocalToWorld()) < threshold)
{
LOG_AND_RETURN(1);
}
Stuff::Point3D next_player_pos;
player_vehicle->EstimateFuturePosition(&next_player_pos, (Scalar)seconds);
Stuff::Point3D next_self_pos;
i.GetSelf_AsVehicle()->EstimateFuturePosition(&next_self_pos, (Scalar)seconds);
if (GetLengthSquared(next_self_pos,
next_player_pos) < threshold)
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::ClusterFuckingSomeone(TacticInterface& i,
Stuff::Scalar radius)
{
AILOGFUNC("Conditions::ClusterFuckingSomeone");
AILOG1(radius);
if (i.GetLastTimeRammedTarget() + 1.0f > gos_GetElapsedTime())
{
LOG_AND_RETURN(1);
}
Adept::Entity* entity = i.GetNearest();
if (entity != 0)
{
if (i.GetSelf().IsDerivedFrom(Mech::DefaultData) == false)
{
radius *= 0.8f; // this is to ensure that vehicles smaller than mechs have smaller dodge radii
}
if (GetLengthSquared((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
(Stuff::Point3D)entity->GetLocalToWorld()) < radius * radius)
{
LOG_AND_RETURN(1);
}
}
LOG_AND_RETURN(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::EliteLevelBetween(TacticInterface& i, UserConstants::ID min, UserConstants::ID max)
{
AILOGFUNC("Conditions::EliteLevelBetween");
AILOG2(min,max);
int int_min = (int)UserConstants::Instance()->Get(min);
int int_max = (int)UserConstants::Instance()->Get(max);
Verify(int_min <= int_max);
Verify(int_min >= 0);
Verify(int_max <= 100);
LOG_AND_RETURN((i.GetEliteLevel() >= int_min) && (i.GetEliteLevel() <= int_max));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Fuzzy Conditions::AttackThrottleBetween(TacticInterface& i, Stuff::Scalar min, Stuff::Scalar max)
{
AILOGFUNC("Conditions::AttackThrottleBetween");
AILOG2(min,max);
Verify(min >= 0);
Verify(max <= 100);
if ((i.GetAttackThrottle() >= min) &&
(i.GetAttackThrottle() <= max))
{
LOG_AND_RETURN(1);
}
LOG_AND_RETURN(0);
}