Files
lab1/processors/timeline_agents/behavior_timeline_engage.txt
2025-09-12 15:20:28 +08:00

276 lines
9.7 KiB
Plaintext

# ****************************************************************************
# CUI
#
# The Advanced Framework for Simulation, Integration, and Modeling (AFSIM)
#
# The use, dissemination or disclosure of data in this file is subject to
# limitation or restriction. See accompanying README and LICENSE for details.
# ****************************************************************************
include_once common_timeline_scripts.txt
include_once air_combat_maneuvers.txt
include_once weapon_defs.txt
behavior timeline_engage
script_debug_writes off
script_variables
WsfQuantumTaskerProcessor processor;
bool mWaitForLatestShot = false; #if false: shoots asap once at %rmax
bool mDontShootIfCantSupport = false; #if true: doesn't shoot unless there is time to support the shot
WsfLocalTrack mEngageTarget;
end_script_variables
on_init
if (PROCESSOR.IsA_TypeOf("WSF_QUANTUM_TASKER_PROCESSOR"))
{
processor = (WsfQuantumTaskerProcessor)PROCESSOR;
}
end_on_init
precondition
writeln_d(PLATFORM.Name(), " precondition timeline_engage, T=", TIME_NOW);
if (!processor.IsValid())
{
return Failure("behavior not attached to a WSF_QUANTUM_TASKER_PROCESSOR");
}
WsfTask timeline = GetTimeLineTask(processor);
if (!timeline.IsValid())
{
return Failure("not assigned a TIMELINE task");
}
string RISK = timeline.AuxDataString("RISK");
extern WsfLocalTrack mNearestTimeLineTarget;
extern bool mConsiderPeersWeapons;
#look for the soonest intercepting target that we don't already have a weapon active or pending against
extern Array<WsfLocalTrack> mTimeLineLocalTargets; #sorted list of local track timeline targets
#check for no active or pending weapons
#pursue something, hopefully a shootable guy
extern Array<WsfLocalTrack> mTimeLineLocalTargetsToShoot;
if (mTimeLineLocalTargetsToShoot.Size() > 0)
{
mEngageTarget = mTimeLineLocalTargetsToShoot.Front();
return true;
}
foreach(WsfLocalTrack target in mTimeLineLocalTargets)
{
if (FiredOn(PLATFORM, target, mConsiderPeersWeapons))
{
continue;
}
extern double mGeesToTurnWith;
extern double mEngageSpeed;
# extern bool mRequiredToSupportWeapons;
# if (mRequiredToSupportWeapons == true && RISK != "HIGH") #can support any shot when risk is high (won't be dragging)
# {
# double gate = timeline.AuxDataDouble("DOR"); #range (meters)
# if (RISK == "MEDIUM")
# {
# gate = timeline.AuxDataDouble("MAR"); #range (meters)
# }
#
# #calculate if we have time to support a shot to this target:
# extern double mOffsetAngle;
# extern double mDelaySpeed;
#
# #figure out weapon range & time of flight
# double weaponMaxRange = 0.0;
# WsfWeapon maxRangeWeapon;
# for (int i=0; i < PLATFORM.WeaponCount(); i+=1)
# {
# WsfWeapon weapon = PLATFORM.WeaponEntry(i);
# if (WeaponCapableAvailableAgainstThreat(weapon, target))
# {
# double weaponRange = MaxRange(PLATFORM,weapon,target);
# if (weaponRange > weaponMaxRange)
# {
# weaponMaxRange = weaponRange;
# maxRangeWeapon = weapon;
# }
# }
# }
# if (!maxRangeWeapon.IsValid())
# {
# continue; #no weapon for this target
# }
# #estimate time before we can shoot
# #hypothetical shot
# #estimate time cranking (based on weapon travel time)
# #does this leave us enough time to turn to drag?
# double range = PLATFORM.GroundRangeTo(mNearestTimeLineTarget.CurrentLocation());
#
# double weaponTOF = TimeToHit(PLATFORM, maxRangeWeapon, target);
# if (weaponTOF <= 0)
# {
# #good weapon data no found
# continue;
# }
# double firingRange = DefaultPercentRangeMax * weaponMaxRange;
# double targetRange = PLATFORM.GroundRangeTo(target.CurrentLocation());
# double rangeToGo = targetRange - firingRange;
# double timeTilShot = 0.0;
# double closingSpeed = 0.0;
# if (rangeToGo > 0)
# {
# #subtract off closing distance to nearest target during the time before shot
# timeTilShot = rangeToGo / PLATFORM.ClosingSpeedOf(target);
# closingSpeed = PLATFORM.Speed() + mNearestTimeLineTarget.Speed();
# range -= (timeTilShot * closingSpeed);
# }
#
# #subtract off closing distance to nearest target during the time of weapon's flight
# closingSpeed = (mDelaySpeed * MATH.Cos(mOffsetAngle)) + mNearestTimeLineTarget.Speed();
# range -= (weaponTOF * closingSpeed);
#
# #calculate time to turn to drag (after cranking)
# Array<double> vals = Array<double>();
# double turnAngle = 180 - mOffsetAngle;
# TurnAngleTimeAndDistance(turnAngle, mEngageSpeed, mGeesToTurnWith, vals);
# double turnTime = vals[0];
# double distSep = vals[1];
# #subtract off closing distance to nearest target during the time of turning to drag
# range += distSep;
# range -= (turnTime*mNearestTimeLineTarget.Speed());
#
# if (range >= gate)
# {
# mEngageTarget = target;
# return true;
# }
# }
# else
{
mEngageTarget = target;
return true;
}
}
return Failure("no timeline targets left to engage");
end_precondition
# script double GetLaunchPercentRangeMaxOnThreat(string weaponName, WsfTrack threat)
# WsfPlatform plat = WsfSimulation.FindPlatform( threat.TargetName() );
# if (plat.IsValid())
# {
# if (WeaponThreatRmaxMap.Exists(weaponName))
# {
# Map<string, double> categoryRangeMap = WeaponThreatRmaxMap.Get(weaponName);
# foreach (string aCategory : double percent in categoryRangeMap)
# {
# if( plat.CategoryMemberOf( aCategory ) )
# {
# return percent;
# }
# }
# }
# }
# return DefaultPercentRangeMax;
# end_script
script bool TryToFireOn(WsfLocalTrack target)
extern double DefaultPercentRangeMax;
extern double DefaultPercentRangeMin;
WsfWeapon weapon;
bool weaponUsable = false;
#first weapon found will be used
for (int i=0; i < PLATFORM.WeaponCount(); i+=1)
{
weapon = PLATFORM.WeaponEntry(i);
writeln_d("checking if weapon ", weapon.Name(), " is usable.");
if (WeaponCapableAvailableAgainstThreat(weapon, target) &&
#InRangeToFire(PLATFORM, weapon, target, GetLaunchPercentRangeMaxOnThreat(weapon.Name(), target), DefaultPercentRangeMin))
InRangeToFire(PLATFORM, weapon, target, DefaultPercentRangeMax, DefaultPercentRangeMin))
{
weaponUsable = true;
break;
}
}
if (weaponUsable == false)
{
writeln_d("no usable weapon found!");
return false;
}
bool launched = false;
if (weapon.IsTurnedOn())
{
writeln_d(" Attempting launch at ", target.TargetName());
launched = weapon.Fire(target);
}
writeln_d(" launched == ", launched, ", weapon: ", weapon.Name());
if(launched == false)
{
writeln_d(" ", PLATFORM.Name(), " could NOT fire at track: ", target.TargetName(), " at time: ", TIME_NOW);
}
return launched;
end_script
on_new_execute
PLATFORM.Comment("engage");
end_on_new_execute
execute
#mEngageTarget;
extern double mDefaultAltitude;
#check if we need to fly offset to get on proper side of engagement separation line
extern double mEngageSpeed;
extern double mGeesToTurnWith;
extern bool mSeparateEngagement;
if (mSeparateEngagement == true)
{
extern string mSeparateSide; # "LEFT" or "RIGHT"
extern double mEngagementTrueBearing;
extern double mOffsetAngle;
double delta = PLATFORM.TrueBearingTo(mEngageTarget) - mEngagementTrueBearing;
if (delta < 0 && mSeparateSide == "LEFT")
{
#we're out of position, crank left
Offset(PLATFORM, mEngageTarget.CurrentLocation(), -mOffsetAngle, mDefaultAltitude, mEngageSpeed, mGeesToTurnWith);
}
else if (delta > 0 && mSeparateSide == "RIGHT")
{
#we're out of position, crank right
Offset(PLATFORM, mEngageTarget.CurrentLocation(), mOffsetAngle, mDefaultAltitude, mEngageSpeed, mGeesToTurnWith);
}
else
{
#engage straight way - intercept the target
Engage(PLATFORM, mEngageTarget, "lead", mEngageSpeed, mDefaultAltitude, mGeesToTurnWith);
}
}
else
{
#engage straight way - intercept the target
Engage(PLATFORM, mEngageTarget, "lead", mEngageSpeed, mDefaultAltitude, mGeesToTurnWith);
}
#TODO - check for shot range, prep for shot if appropriate?
# #if possible, fire a weapon at the target
# TryToFireOn(mEngageTarget);
#try for shots on all shootable targets
foreach (WsfLocalTrack target in mTimeLineLocalTargetsToShoot)
{
TryToFireOn(target);
}
end_execute
end_behavior