330 lines
11 KiB
Plaintext
330 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.
|
||
|
|
# ****************************************************************************
|
||
|
|
|
||
|
|
// converted BRAWLER v7.5 aslct7.f and akshn7.f
|
||
|
|
// Replicates the gun fire 7,3,7,x alternative behavior
|
||
|
|
|
||
|
|
include_once BrawlerScriptUtil.txt
|
||
|
|
|
||
|
|
behavior weapon_decision_gun
|
||
|
|
|
||
|
|
script_debug_writes off
|
||
|
|
|
||
|
|
script_variables
|
||
|
|
|
||
|
|
double RNGWPN = 3000.0; #feet (from MIND file)
|
||
|
|
|
||
|
|
WsfQuantumTaskerProcessor processor;
|
||
|
|
WsfBrawlerPlatform brawlerPlatform;
|
||
|
|
|
||
|
|
//**********************************************************************//
|
||
|
|
//** debugging parameters **//
|
||
|
|
//**********************************************************************//
|
||
|
|
bool mDrawGuns = true;
|
||
|
|
WsfDraw mDraw = WsfDraw();
|
||
|
|
|
||
|
|
//**********************************************************************//
|
||
|
|
//** alternative parameters **//
|
||
|
|
//**********************************************************************//
|
||
|
|
// Flag used to enable/disable this alternative
|
||
|
|
// Takes the place of production rules
|
||
|
|
bool mAlternative7371Enabled = true;
|
||
|
|
|
||
|
|
// Alternative ID
|
||
|
|
int ilevel = 7;
|
||
|
|
int kalt = 3;
|
||
|
|
int icall = 7; // Always 7 for gun
|
||
|
|
int lcall = 1;
|
||
|
|
|
||
|
|
|
||
|
|
end_script_variables
|
||
|
|
|
||
|
|
on_init
|
||
|
|
if (PROCESSOR.IsA_TypeOf("WSF_QUANTUM_TASKER_PROCESSOR"))
|
||
|
|
{
|
||
|
|
processor = (WsfQuantumTaskerProcessor)PROCESSOR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Needed?
|
||
|
|
brawlerPlatform = (WsfBrawlerPlatform)PLATFORM;
|
||
|
|
end_on_init
|
||
|
|
|
||
|
|
// Replicates the checks done in canfirg.f
|
||
|
|
// Return true if the gun can be fired ("hard" checks)
|
||
|
|
// Sets the string to the fail reason
|
||
|
|
script bool canfirg(string failMsg)
|
||
|
|
/*
|
||
|
|
cnfire = .false.
|
||
|
|
C --NOTE THAT WE ARE RECALCULATING PILOT POSTURE VARIABLES HERE
|
||
|
|
C --ppmrmx WILL BE NEEDED IN shldfrg, SO PERFORM THIS CALCULATION
|
||
|
|
C --UNCONDITIONALLY.
|
||
|
|
call gunenv(xp(1,me),vp(1,me),xp(1,ppmiac),vp(1,ppmiac),
|
||
|
|
1 ppmptr,ppmrmn,ppmrmx,ppmapt,ppmse,ppmaof,ppmenv,ppmtrk,ppmohr,
|
||
|
|
2 rbep )
|
||
|
|
C --If temp midway in a 0.5 second burst exceeds maximum (1.0 by
|
||
|
|
C --definition) then you can't shoot. Rate of temperature rise
|
||
|
|
C --is 1.0/t_to_heat, so that firing for t_to_heat seconds reaches
|
||
|
|
C --the limit.
|
||
|
|
overheat = (gun_temp+0.25/t_to_heat .gt. 1.0)
|
||
|
|
if (overheat) then
|
||
|
|
rsfail = 'GUN OVERHEAT'
|
||
|
|
return
|
||
|
|
endif
|
||
|
|
C
|
||
|
|
C --CHECK IF TARGET IS IN ENVELOPE
|
||
|
|
if (.not.ppmenv) then
|
||
|
|
rsfail = 'NOT IN ENVELOPE '
|
||
|
|
return
|
||
|
|
endif
|
||
|
|
C
|
||
|
|
C --CHECK ON PROBABILITY IN RANGE
|
||
|
|
pinrng = prmax2(ppmiac,ppmrmx,1.0,0.2)
|
||
|
|
pbinrg = pinrng.ge.pr2lim
|
||
|
|
if (.not.pbinrg) then
|
||
|
|
rsfail = 'LOW PROB IN RANGE'
|
||
|
|
return
|
||
|
|
endif
|
||
|
|
C
|
||
|
|
visacq = inform(ppmiac).eq.1 .and. time.le.seet(ppmiac)+0.5
|
||
|
|
C --If pilot has not had a recent visual (or does not have a
|
||
|
|
C --radar lock if rdrgun is set), then gun can't be fired.
|
||
|
|
if(.not.rdrgun) then
|
||
|
|
C --DO I HAVE A RECENT VISUAL?
|
||
|
|
if(.not.visacq) then
|
||
|
|
rsfail = 'NO RECENT VISUAL'
|
||
|
|
return
|
||
|
|
endif
|
||
|
|
else
|
||
|
|
C --AN ESTABLISHED RADAR TRACK MAY SUBSTITUTE FOR A VISUAL
|
||
|
|
C --IF RDRGUN=.TRUE.
|
||
|
|
call lockid(iacid,ppmjid,locked)
|
||
|
|
gunacq = visacq .or. locked.eq.2
|
||
|
|
if(.not.gunacq) then
|
||
|
|
rsfail = 'NO RECENT VISUAL OR LOCK'
|
||
|
|
return
|
||
|
|
endif
|
||
|
|
endif
|
||
|
|
C
|
||
|
|
cnfire = .true.
|
||
|
|
*/
|
||
|
|
#bool canFire = false;
|
||
|
|
bool canFire = true; #LBM - temporary
|
||
|
|
|
||
|
|
return canFire;
|
||
|
|
end_script
|
||
|
|
|
||
|
|
// Replicates the checks done in shldfrg.f
|
||
|
|
// Return true if the should should be fired ("soft" checks)
|
||
|
|
// Sets the string to the fail reason if any
|
||
|
|
script bool shldfrg(string failMsg)
|
||
|
|
/*
|
||
|
|
C --If target is inside Rmax2, don't need the following
|
||
|
|
C --tests(target is inside no-escape range).
|
||
|
|
C --CHECK THAT PILOT BELIEVES RANGE IS OK FOR TARGETING
|
||
|
|
pinrng = prmax2(ppmiac,ppmrmx,ppm_rpeak,0.2)
|
||
|
|
pbinrg = pinrng.ge.pr2lim
|
||
|
|
call pdset('PROB_IN_RANGE',pbinrg)
|
||
|
|
C
|
||
|
|
C --CALCULATE CURRENT ENVELOPE LEVEL; ppmrmx WAS RECALCULATED IN canfirg
|
||
|
|
elevnow = envlvg(rngnow(me,ppmiac),rdotme(ppmiac),ppmse,ppmrmx,
|
||
|
|
1 'SHOOT')
|
||
|
|
C --CALCULATE PROJECTED ENVELOPE, CONSTANT VELOCITY PROJECTION FOR
|
||
|
|
C --ME AND CURRENT ACCELERATION PROJECTION FOR TARGET.
|
||
|
|
C --call vecinc(xp(1,me),tproj3,vp(1,me),xme)
|
||
|
|
C --Full projection for target, fixed velocity projection
|
||
|
|
C --for attacker.
|
||
|
|
C --call gunenv(xme,vp(1,me),xeut(1,ppmiac),veut(1,ppmiac),
|
||
|
|
call gunenv(xeuan,veuan,xeut(1,ppmiac),veut(1,ppmiac),
|
||
|
|
1 ppmptr,rmin,rmax,aimp,se,aof,inenvp,trkbl,ovrhoz,rbep)
|
||
|
|
elevprj = envlvg(rngun(ppmiac),rngrun(ppmiac),se,rmax,'SHOOT')
|
||
|
|
if(lprnt) write(ioutp,2000) rmin,rmax,rng(ppmiac),aimp,se,aof,
|
||
|
|
1 elevprj
|
||
|
|
C
|
||
|
|
C --CHECK PROJECTION -- IS LEVEL DECREASING?
|
||
|
|
worse = (elevnow.ge.elevprj)
|
||
|
|
call pdset('SHOT_WORSENING',worse)
|
||
|
|
C
|
||
|
|
needid = (irel(ppmiac).eq.0) .and. (id_mode.ne.bvr_id_md)
|
||
|
|
call pdset('SURE_BAD_GUY',.not.needid)
|
||
|
|
C
|
||
|
|
if (needid)then
|
||
|
|
lfire = .false.
|
||
|
|
rsfail = 'NEED ID'
|
||
|
|
elseif(.not.(pbinrg.or.worse))then
|
||
|
|
rsfail = '!(IN RPEAK OR WORSE)'
|
||
|
|
lfire = .false.
|
||
|
|
else
|
||
|
|
lfire = .true.
|
||
|
|
endif
|
||
|
|
*/
|
||
|
|
# bool lfire = false;
|
||
|
|
bool lfire = true; #LBM - temporary
|
||
|
|
|
||
|
|
|
||
|
|
return lfire;
|
||
|
|
end_script
|
||
|
|
|
||
|
|
precondition
|
||
|
|
#writeln_d(PLATFORM.Name(), " precondition weapon_decision_gun, T=", TIME_NOW);
|
||
|
|
|
||
|
|
### Evaluate conditions that would prevent behavior alternative from running
|
||
|
|
|
||
|
|
if (!PROCESSOR.IsA_TypeOf("WSF_QUANTUM_TASKER_PROCESSOR"))
|
||
|
|
{
|
||
|
|
writeln_d("not a quantum tasker!");
|
||
|
|
return Failure("behavior not attached to a WSF_QUANTUM_TASKER_PROCESSOR");
|
||
|
|
}
|
||
|
|
|
||
|
|
// aslct7.f line 123 - 132
|
||
|
|
# --CHECK IF TARGET SELECTED
|
||
|
|
# if (ppmiac .eq. 0 .and. .not.dewvmsl)then
|
||
|
|
# rsfail = 'NO TARGET SELECTED'
|
||
|
|
# goto 800
|
||
|
|
# endif
|
||
|
|
# --CHECK IF WEAPON SELECTED
|
||
|
|
# if (ppmptr .eq. 0)then
|
||
|
|
# rsfail = 'NO WEAPON SELECTED'
|
||
|
|
# goto 800
|
||
|
|
# endif
|
||
|
|
WsfTaskList tasks = processor.TasksReceivedOfType("WEAPON");
|
||
|
|
if(tasks.Count() <= 0)
|
||
|
|
{
|
||
|
|
return Failure("no target selected");
|
||
|
|
}
|
||
|
|
|
||
|
|
WsfTrack targetTrack = PLATFORM.MasterTrackList().FindTrack(tasks.Entry(0).LocalTrackId());
|
||
|
|
if (!targetTrack.IsValid())
|
||
|
|
{
|
||
|
|
return Failure("no valid target track");
|
||
|
|
}
|
||
|
|
|
||
|
|
#LBM - temporary
|
||
|
|
# // Weapon selection done in selwpn.f (called from aslct2.f)
|
||
|
|
# // checks weapon inventory. Use a similar check here as a replacement
|
||
|
|
# if (!HaveWeapon(PLATFORM))
|
||
|
|
# {
|
||
|
|
# // TODO Account for weapon type gun/missile
|
||
|
|
# return Failure("no weapon selected");
|
||
|
|
# }
|
||
|
|
|
||
|
|
if (!PLATFORM.Weapon("gun").IsValid() || PLATFORM.Weapon("gun").QuantityRemaining() <= 0)
|
||
|
|
{
|
||
|
|
writeln_d(" ", PLATFORM.Name(), " no weapon selected at time: ", TIME_NOW);
|
||
|
|
return Failure("no weapon selected");
|
||
|
|
}
|
||
|
|
|
||
|
|
# // aslct7() calls canfir().
|
||
|
|
# // canfir.f checks production rules and GCI inhibit
|
||
|
|
# // just doing a simple flag for now
|
||
|
|
# if (!mAlternative7371Enabled)
|
||
|
|
# {
|
||
|
|
# writeln_d("behavior not enabled!");
|
||
|
|
# return Failure("behavior alternative not enabled");
|
||
|
|
# }
|
||
|
|
#
|
||
|
|
# //canfir.f calls canfirg()
|
||
|
|
# string msg = "";
|
||
|
|
# if (!canfirg(msg))
|
||
|
|
# {
|
||
|
|
# return Failure(msg);
|
||
|
|
# }
|
||
|
|
#
|
||
|
|
# // aslct7 line 199 - 205
|
||
|
|
# // if undamaged calls shldfr().
|
||
|
|
# // if we are damaged skip checks and fire now
|
||
|
|
# if (PLATFORM.DamageFactor() <= 0.0)
|
||
|
|
# {
|
||
|
|
# // shldfr.f just calls the specific weapon type
|
||
|
|
# if (!shldfrg(msg))
|
||
|
|
# {
|
||
|
|
# return Failure(msg);
|
||
|
|
# }
|
||
|
|
# }
|
||
|
|
#
|
||
|
|
# // aslct7 creates and alternative to evaluate.
|
||
|
|
# // The alternative has no projection and always
|
||
|
|
# // evaluates to 1, so skip that processing
|
||
|
|
|
||
|
|
WsfWeapon gun = PLATFORM.Weapon("gun");
|
||
|
|
if (gun.LaunchComputer().CanIntercept(targetTrack, 0.1)) #see "firing_delay" for BULLET weapon
|
||
|
|
{
|
||
|
|
WsfGeoPoint pt = gun.LaunchComputer().InterceptPoint();
|
||
|
|
|
||
|
|
#TODO - move slant range check to gun's launch computer???
|
||
|
|
|
||
|
|
if (PLATFORM.SlantRangeTo(pt) <= (RNGWPN * MATH.M_PER_FT()))
|
||
|
|
{
|
||
|
|
# #draw line to intercept point
|
||
|
|
# if (mDrawGuns)
|
||
|
|
# {
|
||
|
|
# double delta = ((WsfBrawlerPlatform)PLATFORM).ProjectedTimeDelta();
|
||
|
|
# mDraw.SetLayer("behavior_weapon_decision_gun");
|
||
|
|
# mDraw.SetDuration(delta);
|
||
|
|
# mDraw.SetColor(0.5, 0.5, 0.5); #gray
|
||
|
|
# mDraw.SetLineSize(1);
|
||
|
|
# mDraw.SetLineStyle("solid");
|
||
|
|
# mDraw.BeginLines();
|
||
|
|
# mDraw.Vertex(PLATFORM.Location());
|
||
|
|
# mDraw.Vertex(pt);
|
||
|
|
# mDraw.End();
|
||
|
|
# }
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
writeln_d("no gun fire, too far away");
|
||
|
|
return Failure("no gun fire, too far away");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
writeln_d("gun cannot intercept target yet");
|
||
|
|
return Failure("gun cannot intercept target yet");
|
||
|
|
}
|
||
|
|
|
||
|
|
// All conditions pass, weapon can fire
|
||
|
|
return true;
|
||
|
|
end_precondition
|
||
|
|
|
||
|
|
execute
|
||
|
|
// Replicates akshn7.f
|
||
|
|
// We don't need to do all the bookeeping that BRAWLER
|
||
|
|
// does. Just launch the weapon.
|
||
|
|
// TODO Fill in gun fire
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
#LBM - temporary
|
||
|
|
WsfTrack targetTrack = PLATFORM.MasterTrackList().FindTrack(processor.TasksReceivedOfType("WEAPON").Entry(0).LocalTrackId());
|
||
|
|
WsfWeapon weapon = PLATFORM.Weapon("gun");
|
||
|
|
bool launched = weapon.FireSalvo(targetTrack, 1); // Always firing one for now
|
||
|
|
if (!launched)
|
||
|
|
{
|
||
|
|
writeln_d(" ", PLATFORM.Name(), " could NOT fire at track: ", targetTrack.TargetName(), " at time: ", TIME_NOW);
|
||
|
|
}
|
||
|
|
else if (mDrawGuns)
|
||
|
|
{
|
||
|
|
double delta = ((WsfBrawlerPlatform)PLATFORM).ProjectedTimeDelta();
|
||
|
|
|
||
|
|
mDraw.SetLayer("behavior_weapon_decision_gun");
|
||
|
|
mDraw.SetDuration(delta);
|
||
|
|
mDraw.SetColor(1.0, 1.0, 1.0); #white
|
||
|
|
mDraw.SetLineSize(2);
|
||
|
|
mDraw.SetLineStyle("dotted2");
|
||
|
|
mDraw.BeginLines();
|
||
|
|
mDraw.Vertex(PLATFORM.Location());
|
||
|
|
mDraw.Vertex(targetTrack.CurrentLocation());
|
||
|
|
mDraw.End();
|
||
|
|
}
|
||
|
|
|
||
|
|
end_execute
|
||
|
|
|
||
|
|
end_behavior
|
||
|
|
|