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

272 lines
11 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 weapon_defs.txt
behavior engage_on_timeline
script_debug_writes off
script_variables
//**********************************************************************//
//** platform / agent specific shooting parameters **//
//**********************************************************************//
#bool mCoopEngageOne = false;
#bool mCoopEngageOneFlightOnly = false;
# double mDegradedFiringAngle = 55.0; //negative if not valid
# double mDegradedPercentRange = 0.50; //range constraint if past degraded firing angle
# //specify orientation limits for shooting
# double mMaxFiringRollAngle = 10.0; //dont shoot if rolled more/less than this
# double mMaxFiringPitchAngle = 15.0; //dont shoot if pitched more than this
# double mMinFiringPitchAngle = -10.0; //dont shoot if pitched less than this
//**********************************************************************//
//** threat specific shooting parameters **//
//**********************************************************************//
//require different track qualities to fire on different kinds of threats
# double DefaultRequiredTrackQuality = 0.49;
# Map<string, double> ThreatTypeRequiredTrackQuality = Map<string, double>();
# ThreatTypeRequiredTrackQuality["bomber"] = 0.49;
# ThreatTypeRequiredTrackQuality["fighter"] = 0.49;
//fire off different salvos at different types of threats
# int DefaultAirSalvo = 1;
# int DefaultGndSalvo = 1;
# Map<string, int> ThreatTypeSalvo = Map<string, int>();
# ThreatTypeSalvo["sam"] = 2;
# ThreatTypeSalvo["ship"] = 2;
# ThreatTypeSalvo["bomber"] = 2;
# ThreatTypeSalvo["fighter"] = 1;
# ThreatTypeSalvo["FIRE_CONTROL"] = 1;
# ThreatTypeSalvo["primary_target"] = 2;
# ThreatTypeSalvo["secondary_target"] = 2;
//**********************************************************************//
//** weapon + threat specific shooting parameters **//
//**********************************************************************//
//specify an Rmax based on which weapon used and which threat engaged
double DefaultPercentRangeMax = 0.80; // don't launch unless within this percent of Rmax
double DefaultPercentRangeMin = 1.20; // don't launch unless beyond this percent of Rmin
Map<string, Map<string, double>> WeaponThreatRmaxMap = Map<string, Map<string, double>>();
WeaponThreatRmaxMap["base_weapon"] = Map<string, double>();
WeaponThreatRmaxMap["base_weapon"].Set("fighter", 0.80);
end_script_variables
# script int GetSalvoForThreat(WsfTrack track)
# #writeln_d("checking salvo size for category: ", category);
# #WsfPlatform plat = WsfSimulation.FindPlatform( track.TargetIndex() );
# WsfPlatform plat = WsfSimulation.FindPlatform( track.TargetName() );
# if (plat.IsValid())
# {
# foreach( string aCategory : int salvo in ThreatTypeSalvo )
# {
# if( plat.CategoryMemberOf( aCategory ) )
# {
# writeln_d("salvo for type ", aCategory, " = ", salvo);
# return salvo;
# }
# }
# }
# #extern string GetTargetDomain(WsfTrack);
# string sTargetDomain = GetTargetDomain(track);
# if ( (sTargetDomain == "LAND") || (sTargetDomain == "SURFACE") )
# {
# return DefaultGndSalvo;
# }
# return DefaultAirSalvo;
# end_script
# script double GetRequiredTrackQualityForThreat(WsfTrack threat)
# writeln_d("checking required TQ for track: ", threat.TargetName());
# WsfPlatform plat = WsfSimulation.FindPlatform( threat.TargetName() );
# if (plat.IsValid())
# {
# foreach( string aCategory : double quality in ThreatTypeRequiredTrackQuality )
# {
# if( plat.CategoryMemberOf( aCategory ) )
# {
# writeln_d("TQ for type ", aCategory, " = ", quality);
# return quality;
# }
# }
# }
# return DefaultRequiredTrackQuality;
# end_script
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
#on_init
#end_on_init
precondition
#writeln_d("precondition engage-target");
if (!PROCESSOR.IsA_TypeOf("WSF_QUANTUM_TASKER_PROCESSOR"))
{
writeln_d("behavior engage... not on quantum tasker processor");
return Failure("behavior not attached to a quantum tasker processor!");
}
# todo - try using a state machine to setup the shot ??
# double pitch = PLATFORM.Pitch();
# if (MATH.Fabs(PLATFORM.Roll()) > mMaxFiringRollAngle ||
# pitch > mMaxFiringPitchAngle ||
# pitch < mMinFiringPitchAngle)
# {
# string msgStr = write_str(" ", PLATFORM.Name(), " orientation too far off to fire! (roll or pitch)");
# writeln_d(msgStr);
# //PLATFORM.Comment(msgStr);
# return Failure(msgStr);
# }
WsfQuantumTaskerProcessor proc = (WsfQuantumTaskerProcessor)PROCESSOR;
# WsfTaskList tasks = proc.TasksReceivedOfType("WEAPON");
# if (tasks.Count() > 0)
# {
# writeln_d("behavior engage precondition passes!");
# return true;
# }
# writeln_d("no weapon task target to shoot at!");
if (GetTimelineTask(proc).IsValid())
{
writeln_d("behavior engage precondition passes!");
return true;
}
writeln_d("no timeline task to engage!");
return Failure("no timeline task to engage!");
end_precondition
execute
writeln_d(PLATFORM.Name(), " executing engage-target, T=", TIME_NOW);
#extern WsfTrack GetTrackByName(WsfPlatform, string);
#check all possible targets on all channels
########################################################################
### fire on any pursue-target jobs we are assigned to
########################################################################
WsfQuantumTaskerProcessor proc = (WsfQuantumTaskerProcessor)PROCESSOR;
WsfTask timeline = GetTimelineTask(proc);
if (timeline.IsValid() && timeline.AuxDataExists("targets"))
{
Array<WsfTrack> targets = (Array<WsfTrack>)timeline.AuxDataObject("targets");
foreach (WsfTrack target in targets)
{
if (!target.IsValid())
{
continue;
}
#do we need master track?
WsfLocalTrack masterTarget = GetMasterTrackByName(PLATFORM, target.TargetName());
if (!masterTarget.IsValid())
{
continue;
}
# if (mCoopEngageOne == false)
# {
# WsfLocalTrack targetLocalTrack = (WsfLocalTrack)targetTrack;
# if (targetLocalTrack.IsValid())
# {
# if(!targetLocalTrack.ContributorOf(PLATFORM) &&
# !targetLocalTrack.IsPredefined())
# {
# writeln_d(" FAIL: Not able to coop engage! ", PLATFORM.Name(), " targeting ",targetTrack.TargetName(), ". NumContributors: ", targetLocalTrack.NumContributors() );
# return;
# }
# }
# }
#
# writeln_d (" targetTrack.TrackQuality == ", targetTrack.TrackQuality());
# if (targetTrack.TrackQuality() < GetRequiredTrackQualityForThreat(targetTrack))
# {
# writeln_d(" FAIL: track quality not good enough to fire on target");
# return;
# }
if ((PLATFORM.WeaponsPendingFor(masterTarget.TrackId()) + PLATFORM.WeaponsActiveFor(masterTarget.TrackId())) > 0)
{
writeln_d("already have weapons assigned for target: ", masterTarget.TargetName());
continue;
}
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, masterTarget) &&
InRangeToFire(PLATFORM, weapon, masterTarget, GetLaunchPercentRangeMaxOnThreat(weapon.Name(), masterTarget), DefaultPercentRangeMin))
{
weaponUsable = true;
break;
}
}
if (weaponUsable == false)
{
writeln_d("no usable weapon found!");
continue;
}
#int salvoCount = GetSalvoForThreat(targetTrack);
#writeln_d(" salvo count for ", targetTrack, " is: ", salvoCount);
int salvoCount = 1;
bool launched = false;
if (weapon.IsTurnedOn())
{
writeln_d(" Attempting launch at ", masterTarget.TargetName());
# if (salvoCount > 1)
# {
# writeln_d("FIRING SALVO AT ", masterTarget.TargetName());
# launched = weapon.FireSalvo(masterTarget, salvoCount);
# }
# else
# {
# writeln_d("FIRING AT ", masterTarget.TargetName());
# launched = weapon.Fire(masterTarget);
# }
launched = weapon.FireSalvo(masterTarget, salvoCount);
}
writeln_d(" launched == ", launched, ", weapon: ", weapon.Name());
if(launched == false)
{
writeln_d(" ", PLATFORM.Name(), " could NOT fire at track: ", masterTarget.TargetName(), " at time: ", TIME_NOW);
}
}
}
end_execute
end_behavior