mirror of
https://github.com/l0k1/oprf_assets.git
synced 2026-08-23 10:29:19 +00:00
Shooting BUK-M2 (SA-11) released.
This commit is contained in:
@@ -130,7 +130,57 @@
|
||||
<menu n="100">
|
||||
<label>BUK-M2</label>
|
||||
<enabled type="bool">true</enabled>
|
||||
|
||||
<item>
|
||||
<label>Reload</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
fire_control.reload();
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Targets</label>
|
||||
<name>enemies</name>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>enemies</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Priority</label>
|
||||
<name>enemies</name>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>priority</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Relocate to cursor last click</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
setprop("position/latitude-deg",getprop("sim/input/click/latitude-deg"));
|
||||
setprop("position/longitude-deg",getprop("sim/input/click/longitude-deg"));
|
||||
setprop("position/altitude-ft",getprop("sim/input/click/elevation-ft"));
|
||||
var h = geo.elevation(getprop("sim/input/click/latitude-deg"),getprop("sim/input/click/longitude-deg"));
|
||||
if (h!=nil)
|
||||
setprop("position/altitude-ft",h*M2FT+0.010);
|
||||
fire_control.start_time = systime();
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Print log to console</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
setprop("payload/armament/msg",0);
|
||||
damage.printDamageLog();
|
||||
setprop("payload/armament/msg",1);
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Event Log</label>
|
||||
<binding>
|
||||
@@ -245,6 +295,48 @@
|
||||
<MAW-active type="bool">false</MAW-active>
|
||||
<spike type="bool">false</spike>
|
||||
<!-- speed: Mach 4 length: 5.5m -->
|
||||
<m317>
|
||||
<type-id type="int">62</type-id>
|
||||
<vol-search type="double">0.00</vol-search>
|
||||
<vol-track type="double">0.15</vol-track>
|
||||
<guidance type="string">radar</guidance>
|
||||
<navigation type="string">APN0506</navigation> <!-- horizontal APN, vertical aim 5 degrees above for 6 seconds -->
|
||||
<all-aspect type="bool">true</all-aspect>
|
||||
<max-fire-range-nm type="int">31</max-fire-range-nm> <!-- -->
|
||||
<FCS-field-deg type="int">360</FCS-field-deg>
|
||||
<seeker-field-deg type="int">170</seeker-field-deg>
|
||||
<max-g type="int">24</max-g> <!-- wikipedia -->
|
||||
<thrust-lbf-stage-1 type="double">11000</thrust-lbf-stage-1> <!-- changed -->
|
||||
<thrust-lbf-stage-2 type="double">0</thrust-lbf-stage-2> <!-- authentic -->
|
||||
<stage-1-duration-sec type="double">15</stage-1-duration-sec> <!-- http://www.whathappenedtoflightmh17.com/a-detailed-description-of-the-buk-sa-11-which-could-have-shot-down-mh17/#prettyPhoto -->
|
||||
<stage-2-duration-sec type="double">0</stage-2-duration-sec><!-- -->
|
||||
<weight-launch-lbs>1576</weight-launch-lbs> <!-- authentic -->
|
||||
<weight-warhead-lbs>145</weight-warhead-lbs> <!-- authentic -->
|
||||
<weight-fuel-lbm>900</weight-fuel-lbm> <!-- -->
|
||||
<drag-coeff type="double">0.20</drag-coeff> <!-- -->
|
||||
<cross-section-sqft type="double">1.312336</cross-section-sqft> <!-- authentic (0.4m diameter) -->
|
||||
<arming-time-sec type="double">2</arming-time-sec>
|
||||
<min-speed-for-guiding-mach type="double">0.5</min-speed-for-guiding-mach>
|
||||
<self-destruct-time-sec type="double">60</self-destruct-time-sec>
|
||||
<seeker-angular-speed-dps type="double">3000</seeker-angular-speed-dps>
|
||||
<loft-altitude type="int">0</loft-altitude>
|
||||
<min-fire-range-nm type="double">1.6</min-fire-range-nm> <!-- authentic -->
|
||||
<max-report-distance type="double">200</max-report-distance> <!-- -->
|
||||
<rail type="bool">true</rail> <!-- -->
|
||||
<rail-length-m type="double">5.5</rail-length-m> <!-- authentic length-->
|
||||
<rail-point-forward type="bool">false</rail-point-forward>
|
||||
<rail-pitch-deg type="double">24</rail-pitch-deg> <!-- matching mount -->
|
||||
<chaff-resistance type="double">0.92</chaff-resistance>
|
||||
<proportionality-constant type="double">3</proportionality-constant>
|
||||
<ready-time type="int">1</ready-time>
|
||||
<class type="string">A</class>
|
||||
<fire-msg>Bird away</fire-msg>
|
||||
<telemetry type="bool">true</telemetry>
|
||||
<FCS-at-origin type="bool">false</FCS-at-origin>
|
||||
<FCS-x type="double">0</FCS-x>
|
||||
<FCS-y type="double">0</FCS-y>
|
||||
<FCS-z type="double">3</FCS-z>
|
||||
</m317>
|
||||
</armament>
|
||||
</payload>
|
||||
|
||||
@@ -294,6 +386,17 @@
|
||||
|
||||
<priority type="int">0</priority>
|
||||
<priority0 type="int">1</priority0>
|
||||
|
||||
<instrumentation>
|
||||
<datalink>
|
||||
<data type="int">0</data>
|
||||
<power type="bool">true</power>
|
||||
<channel type="int">1212</channel>
|
||||
<power_prop type="string">/instrumentation/datalink/power</power_prop>
|
||||
<channel_prop type="string">instrumentation/datalink/channel</channel_prop>
|
||||
<receive_period type="double">1</receive_period>
|
||||
</datalink>
|
||||
</instrumentation>
|
||||
|
||||
<nasal>
|
||||
<notifications>
|
||||
@@ -315,7 +418,11 @@
|
||||
<armament>
|
||||
<file>Aircraft/BUK-M2/Nasal/guided-missiles.nas</file>
|
||||
</armament>
|
||||
<datalink>
|
||||
<file>Aircraft/BUK-M2/Nasal/datalink.nas</file>
|
||||
</datalink>
|
||||
<fire_control>
|
||||
<file>Aircraft/BUK-M2/Nasal/fire-control-custom.nas</file>
|
||||
<file>Aircraft/BUK-M2/Nasal/fire-control.nas</file>
|
||||
</fire_control>
|
||||
</nasal>
|
||||
|
||||
1544
BUK-M2/Models/Armament/Weapons/M317/9M317.ac
Normal file
1544
BUK-M2/Models/Armament/Weapons/M317/9M317.ac
Normal file
File diff suppressed because it is too large
Load Diff
BIN
BUK-M2/Models/Armament/Weapons/M317/BUK-M2.png
Normal file
BIN
BUK-M2/Models/Armament/Weapons/M317/BUK-M2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
176
BUK-M2/Models/Armament/Weapons/M317/explosion-0.xml
Normal file
176
BUK-M2/Models/Armament/Weapons/M317/explosion-0.xml
Normal file
@@ -0,0 +1,176 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-id-0</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>80</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>30</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 1.0 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>2</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.8 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>55</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.5</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion-smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">false</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-smoke-id-0</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>60</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.3 </value></red>
|
||||
<green><value> 0.3 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>10</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.4 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 0.04 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>60</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>40</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
176
BUK-M2/Models/Armament/Weapons/M317/explosion-1.xml
Normal file
176
BUK-M2/Models/Armament/Weapons/M317/explosion-1.xml
Normal file
@@ -0,0 +1,176 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-id-1</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>80</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>30</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 1.0 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>2</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.8 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>55</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.5</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion-smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">false</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-smoke-id-1</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>60</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.3 </value></red>
|
||||
<green><value> 0.3 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>10</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.4 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 0.04 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>60</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>40</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
176
BUK-M2/Models/Armament/Weapons/M317/explosion-2.xml
Normal file
176
BUK-M2/Models/Armament/Weapons/M317/explosion-2.xml
Normal file
@@ -0,0 +1,176 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-id-2</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>80</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>30</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 1.0 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>2</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.8 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>55</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.5</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion-smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">false</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-smoke-id-2</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>60</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.3 </value></red>
|
||||
<green><value> 0.3 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>10</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.4 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 0.04 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>60</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>40</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
176
BUK-M2/Models/Armament/Weapons/M317/explosion-3.xml
Normal file
176
BUK-M2/Models/Armament/Weapons/M317/explosion-3.xml
Normal file
@@ -0,0 +1,176 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-id-3</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>80</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>30</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 1.0 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>2</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.8 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>55</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.5</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
|
||||
<particlesystem>
|
||||
<name>explosion-smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">false</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/explode-smoke-id-3</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-180</theta-min-deg>
|
||||
<theta-max-deg>180</theta-max-deg>
|
||||
<phi-min-deg>-180</phi-min-deg>
|
||||
<phi-max-deg>180</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>500</value>
|
||||
<spread>60</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>10</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.3 </value></red>
|
||||
<green><value> 0.3 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>10</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.4 </value></green>
|
||||
<blue><value> 0.4 </value></blue>
|
||||
<alpha><value> 0.04 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>60</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>40</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 5 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> true </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
42
BUK-M2/Models/Armament/Weapons/M317/m317-0.xml
Normal file
42
BUK-M2/Models/Armament/Weapons/M317/m317-0.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
|
||||
<PropertyList>
|
||||
|
||||
<name>aim-120</name>
|
||||
<path>9M317.ac</path>
|
||||
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>missile1</object-name>
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/msl-id-0</property>
|
||||
</condition>
|
||||
</animation>
|
||||
|
||||
<model>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/motor-smoke-0.xml</path>
|
||||
<offsets>
|
||||
<x-m>1.83937</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<model>
|
||||
<name>explosion</name>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/explosion-0.xml</path>
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<animation>
|
||||
<object-name>missile1</object-name>
|
||||
<enable-hot type="bool">false</enable-hot>
|
||||
</animation>
|
||||
|
||||
</PropertyList>
|
||||
42
BUK-M2/Models/Armament/Weapons/M317/m317-1.xml
Normal file
42
BUK-M2/Models/Armament/Weapons/M317/m317-1.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
|
||||
<PropertyList>
|
||||
|
||||
<name>aim-120</name>
|
||||
<path>9M317.ac</path>
|
||||
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>missile1</object-name>
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/msl-id-1</property>
|
||||
</condition>
|
||||
</animation>
|
||||
|
||||
<model>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/motor-smoke-1.xml</path>
|
||||
<offsets>
|
||||
<x-m>1.83937</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<model>
|
||||
<name>explosion</name>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/explosion-1.xml</path>
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<animation>
|
||||
<object-name>missile1</object-name>
|
||||
<enable-hot type="bool">false</enable-hot>
|
||||
</animation>
|
||||
|
||||
</PropertyList>
|
||||
42
BUK-M2/Models/Armament/Weapons/M317/m317-2.xml
Normal file
42
BUK-M2/Models/Armament/Weapons/M317/m317-2.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
|
||||
<PropertyList>
|
||||
|
||||
<name>aim-120</name>
|
||||
<path>9M317.ac</path>
|
||||
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>missile1</object-name>
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/msl-id-2</property>
|
||||
</condition>
|
||||
</animation>
|
||||
|
||||
<model>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/motor-smoke-2.xml</path>
|
||||
<offsets>
|
||||
<x-m>1.83937</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<model>
|
||||
<name>explosion</name>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/explosion-2.xml</path>
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<animation>
|
||||
<object-name>missile1</object-name>
|
||||
<enable-hot type="bool">false</enable-hot>
|
||||
</animation>
|
||||
|
||||
</PropertyList>
|
||||
42
BUK-M2/Models/Armament/Weapons/M317/m317-3.xml
Normal file
42
BUK-M2/Models/Armament/Weapons/M317/m317-3.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
|
||||
<PropertyList>
|
||||
|
||||
<name>aim-120</name>
|
||||
<path>9M317.ac</path>
|
||||
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>missile1</object-name>
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/msl-id-3</property>
|
||||
</condition>
|
||||
</animation>
|
||||
|
||||
<model>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/motor-smoke-3.xml</path>
|
||||
<offsets>
|
||||
<x-m>1.83937</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<model>
|
||||
<name>explosion</name>
|
||||
<path>Aircraft/BUK-M2/Models/Armament/Weapons/M317/explosion-3.xml</path>
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
</model>
|
||||
|
||||
<animation>
|
||||
<object-name>missile1</object-name>
|
||||
<enable-hot type="bool">false</enable-hot>
|
||||
</animation>
|
||||
|
||||
</PropertyList>
|
||||
7
BUK-M2/Models/Armament/Weapons/M317/m317.xml
Normal file
7
BUK-M2/Models/Armament/Weapons/M317/m317.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<PropertyList>
|
||||
|
||||
<path>9M317.ac</path>
|
||||
|
||||
</PropertyList>
|
||||
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-0.xml
Normal file
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-0.xml
Normal file
@@ -0,0 +1,187 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-0</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>7</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>60</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
<particlesystem>
|
||||
<name>exhaust</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-0</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>100</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 0.7 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.7 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 0.6 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.15</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> false </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-1.xml
Normal file
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-1.xml
Normal file
@@ -0,0 +1,187 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-1</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>7</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>60</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
<particlesystem>
|
||||
<name>exhaust</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-1</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>100</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 0.7 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.7 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 0.6 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.15</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> false </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-2.xml
Normal file
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-2.xml
Normal file
@@ -0,0 +1,187 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-2</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>7</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>60</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
<particlesystem>
|
||||
<name>exhaust</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-2</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>100</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 0.7 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.7 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 0.6 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.15</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> false </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-3.xml
Normal file
187
BUK-M2/Models/Armament/Weapons/M317/motor-smoke-3.xml
Normal file
@@ -0,0 +1,187 @@
|
||||
<PropertyList>
|
||||
|
||||
<particlesystem>
|
||||
<name>smoke</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-3</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>7</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>50</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.25 </value></red>
|
||||
<green><value> 0.25 </value></green>
|
||||
<blue><value> 0.25 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>60</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> true </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
<particlesystem>
|
||||
<name>exhaust</name>
|
||||
<texture>smoke.png</texture>
|
||||
|
||||
<emissive type="bool">true</emissive>
|
||||
<lighting type="bool">false</lighting>
|
||||
|
||||
<condition>
|
||||
<property>payload/armament/m317/flags/smoke-id-3</property>
|
||||
</condition>
|
||||
|
||||
<attach>world</attach>
|
||||
|
||||
<placer>
|
||||
<type>point</type>
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
|
||||
<shooter>
|
||||
<theta-min-deg>-1.5</theta-min-deg>
|
||||
<theta-max-deg>1.5</theta-max-deg>
|
||||
<phi-min-deg>-1.5</phi-min-deg>
|
||||
<phi-max-deg>1.5</phi-max-deg>
|
||||
<speed-mps>
|
||||
<value>0</value>
|
||||
<spread>0</spread>
|
||||
</speed-mps>
|
||||
<rotation-speed>
|
||||
<x-min-deg-sec>0</x-min-deg-sec>
|
||||
<y-min-deg-sec>0</y-min-deg-sec>
|
||||
<z-min-deg-sec>0</z-min-deg-sec>
|
||||
<x-max-deg-sec>0</x-max-deg-sec>
|
||||
<y-max-deg-sec>0</y-max-deg-sec>
|
||||
<z-max-deg-sec>0</z-max-deg-sec>
|
||||
</rotation-speed>
|
||||
</shooter>
|
||||
|
||||
<counter>
|
||||
<particles-per-sec>
|
||||
<value>100</value>
|
||||
<spread>0</spread>
|
||||
</particles-per-sec>
|
||||
</counter>
|
||||
|
||||
<align>billboard</align>
|
||||
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 1.0 </value></red>
|
||||
<green><value> 0.7 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.7 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 0.6 </value></green>
|
||||
<blue><value> 0.2 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.5</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>0.15</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.001 </mass-kg>
|
||||
<radius-m> 0.5 </radius-m>
|
||||
</particle>
|
||||
|
||||
<program>
|
||||
<fluid> air </fluid>
|
||||
<gravity type="bool"> false </gravity>
|
||||
<wind typ="bool"> false </wind>
|
||||
</program>
|
||||
|
||||
</particlesystem>
|
||||
|
||||
</PropertyList>
|
||||
BIN
BUK-M2/Models/Armament/Weapons/M317/puff.png
Normal file
BIN
BUK-M2/Models/Armament/Weapons/M317/puff.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
BUK-M2/Models/Armament/Weapons/M317/smoke.png
Normal file
BIN
BUK-M2/Models/Armament/Weapons/M317/smoke.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
@@ -27,8 +27,6 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
var TRUE = 1;
|
||||
var FALSE = 0;
|
||||
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
@@ -164,7 +162,9 @@ var warheads = {
|
||||
"pilot": [93, 0.00,1,0],# ejected pilot
|
||||
"BETAB-500ShP": [94, 1160.00,1,0],
|
||||
"Flare": [95, 0.00,0,0],
|
||||
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@@ -189,7 +189,8 @@ var radar_signatures = {
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
"Mig-28": AIR_RADAR,
|
||||
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
|
||||
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
@@ -203,7 +204,7 @@ var radar_signatures = {
|
||||
var id2warhead = [];
|
||||
var launched = {};# callsign: elapsed-sec
|
||||
var approached = {};# callsign: uniqueID
|
||||
var heavy_smoke = [61,62,63,65,92,96];
|
||||
var heavy_smoke = [61,62,63,65,92,96,97];
|
||||
|
||||
var k = keys(warheads);
|
||||
|
||||
@@ -241,6 +242,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
|
||||
}
|
||||
}
|
||||
|
||||
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
|
||||
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
|
||||
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
|
||||
|
||||
#==================================================================
|
||||
# Notification processing
|
||||
#==================================================================
|
||||
@@ -281,6 +286,7 @@ var DamageRecipient =
|
||||
# " Flags=",notification.Flags,
|
||||
# " Radar=",bits.test(notification.Flags, 0),
|
||||
# " Thrust=",bits.test(notification.Flags, 1));
|
||||
# " CWI=",bits.test(notification.Flags, 2));
|
||||
#
|
||||
# todo:
|
||||
# animate missiles
|
||||
@@ -301,6 +307,7 @@ var DamageRecipient =
|
||||
var bearing = ownPos.course_to(notification.Position);
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var typ = id2warhead[index];
|
||||
|
||||
@@ -334,7 +341,7 @@ var DamageRecipient =
|
||||
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
|
||||
}
|
||||
|
||||
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
|
||||
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
if (tacview.starttime) {
|
||||
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
|
||||
if (notification.Kind == DESTROY) {
|
||||
@@ -348,7 +355,7 @@ var DamageRecipient =
|
||||
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
|
||||
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
|
||||
extra2 = typp=="Parachutist"?"":extra2;
|
||||
var color = radarOn?",Color=Red":",Color=Yellow";
|
||||
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
|
||||
thread.lock(tacview.mutexWrite);
|
||||
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
|
||||
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
|
||||
@@ -376,9 +383,10 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MLW-launcher", notification.Callsign);
|
||||
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
|
||||
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
|
||||
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
|
||||
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
|
||||
print(out);
|
||||
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
|
||||
if (m28_auto) mig28.missileLaunch();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -386,19 +394,29 @@ var DamageRecipient =
|
||||
# Missile approach warning:
|
||||
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
|
||||
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
|
||||
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
|
||||
var heading = getprop("orientation/heading-deg");
|
||||
var clock = geo.normdeg(bearing - heading);
|
||||
setprop("payload/armament/MAW-bearing", bearing);
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
|
||||
#var heading = getprop("orientation/heading-deg");
|
||||
#var clock = geo.normdeg(bearing - heading);
|
||||
if (radarOn) {
|
||||
setprop("payload/armament/MAW-bearing", bearing);
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
if (appr == nil or elapsed - appr > 450) {
|
||||
printf("Missile Approach Warning from %03d degrees.", bearing);
|
||||
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
|
||||
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
|
||||
if (radarOn) {
|
||||
#printf("Missile Approach Warning from %03d degrees.", bearing);
|
||||
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
|
||||
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
|
||||
} else {
|
||||
#printf("Missile Approach Warning");
|
||||
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
|
||||
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
|
||||
}
|
||||
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign);
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_OK;
|
||||
}
|
||||
@@ -415,7 +433,7 @@ var DamageRecipient =
|
||||
# debug.dump(notification);
|
||||
#
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
# its a warhead
|
||||
@@ -439,9 +457,10 @@ var DamageRecipient =
|
||||
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
|
||||
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
|
||||
#damage enabled and were getting hit
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign);
|
||||
|
||||
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
|
||||
# cannon hit
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
|
||||
var probability = id2shell[-1*notification.SecondaryKind-1][1];
|
||||
var typ = id2shell[-1*notification.SecondaryKind-1][2];
|
||||
var hit_count = notification.Distance;
|
||||
@@ -457,6 +476,7 @@ var DamageRecipient =
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var type = wh[4];#test code
|
||||
@@ -549,21 +569,18 @@ var DamageRecipient =
|
||||
}
|
||||
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
|
||||
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
|
||||
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
|
||||
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
if (static != nil) {
|
||||
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
|
||||
#static is a PropertyNode inside /models
|
||||
}
|
||||
} elsif (notification.SecondaryKind == 1) {
|
||||
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
|
||||
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
if (static != nil) {
|
||||
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
|
||||
}
|
||||
} elsif (notification.SecondaryKind == 2) {
|
||||
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
|
||||
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
|
||||
if (static != nil) {
|
||||
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
|
||||
}
|
||||
@@ -863,6 +880,7 @@ var flare_update_time = 0.4;
|
||||
var flare_duration = 8;
|
||||
var flare_terminal_speed = 50;#m/s
|
||||
var flares_max_process_per_loop = 4;
|
||||
var flare_sequencer = -120;
|
||||
|
||||
var flare_sorter = func(a, b) {
|
||||
if(a[0] < b[0]){
|
||||
@@ -945,7 +963,9 @@ var flare_released = func {
|
||||
getprop("orientation/heading-deg"),
|
||||
FT2M*getprop("velocities/speed-down-fps"),
|
||||
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
|
||||
int(rand()*240)-120];
|
||||
flare_sequencer];
|
||||
flare_sequencer += 1;
|
||||
if (flare_sequencer > 120) flare_sequencer = -120;
|
||||
append(flare_list, flare);
|
||||
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
|
||||
msg.Flags = 0;
|
||||
@@ -1233,7 +1253,7 @@ var processCallsigns = func () {
|
||||
var painted = 0;
|
||||
var paint_list = [];
|
||||
foreach (var player; players) {
|
||||
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
|
||||
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
|
||||
var callsign = player.getChild("callsign").getValue();
|
||||
callsign_struct[callsign] = player;
|
||||
var str6 = player.getNode("sim/multiplay/generic/string[6]");
|
||||
@@ -1247,6 +1267,7 @@ var processCallsigns = func () {
|
||||
}
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@@ -1293,16 +1314,16 @@ processCallsignsTimer.start();
|
||||
var code_ct = func () {
|
||||
#ANTIC
|
||||
if (getprop("payload/armament/msg")) {
|
||||
setprop("sim/rendering/redout/enabled", TRUE);
|
||||
setprop("sim/rendering/redout/enabled", 1);
|
||||
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
|
||||
call(func{multiplayer.dialog.del();},nil,var err= []);
|
||||
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
|
||||
if (!getprop("gear/gear[0]/wow")) {
|
||||
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
|
||||
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
|
||||
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
|
||||
}
|
||||
setprop("sim/freeze/fuel",0);
|
||||
setprop("/sim/speed-up", 1);
|
||||
if (!m28_auto) setprop("/sim/speed-up", 1);
|
||||
setprop("/gui/map/draw-traffic", 0);
|
||||
setprop("/sim/marker-pins/traffic", 0);
|
||||
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
|
||||
@@ -1317,7 +1338,7 @@ code_ctTimer.simulatedTime = 1;
|
||||
|
||||
|
||||
|
||||
setprop("/sim/failure-manager/display-on-screen", FALSE);
|
||||
setprop("/sim/failure-manager/display-on-screen", 0);
|
||||
|
||||
code_ctTimer.start();
|
||||
|
||||
@@ -1337,6 +1358,22 @@ var re_init = func (node) {
|
||||
}
|
||||
stopLaunch();
|
||||
damageLog.push("Aircraft was repaired due to re-init.");
|
||||
|
||||
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
|
||||
|
||||
foreach (var thekey ; keys(statics)) {
|
||||
var sta = statics[thekey];
|
||||
if (sta[0] != nil) {
|
||||
sta[0].remove();
|
||||
if (sta[5] == 0) {# TODO: make a hash with all the models
|
||||
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
|
||||
} elsif (sta[5] == 1) {
|
||||
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
|
||||
} elsif (sta[5] == 2) {
|
||||
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#==================================================================
|
||||
@@ -1405,6 +1442,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@@ -1412,6 +1450,8 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-air");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-20");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
|
||||
681
BUK-M2/Nasal/datalink.nas
Normal file
681
BUK-M2/Nasal/datalink.nas
Normal file
@@ -0,0 +1,681 @@
|
||||
#### Datalink
|
||||
|
||||
# Copyright 2020-2021 Colin Geniet.
|
||||
# Licensed under the GNU General Public License 2.0 or any later version.
|
||||
|
||||
|
||||
#### Usage
|
||||
|
||||
### Generalities
|
||||
#
|
||||
# The datalink protocol consists of a core protocol which implements a notion
|
||||
# of datalink channel, and extensions which allow transmitting actual data.
|
||||
|
||||
### Core protocol usage:
|
||||
#
|
||||
# Define the following properties (must be defined at nasal loading time).
|
||||
# * Mandatory
|
||||
# /instrumentation/datalink/power_prop path to property indicating if datalink is on
|
||||
# /instrumentation/datalink/channel_prop path to property containing datalink channel
|
||||
# (the channel property can contain anything, and is transmitted/compared as a string).
|
||||
# * Optional
|
||||
# /instrumentation/datalink/receive_period = 1 receiving loop update rate
|
||||
#
|
||||
# Optional: Re-define the function
|
||||
# datalink.can_transmit(callsign, mp_prop, mp_index)
|
||||
#
|
||||
# This function should return 'true' when the given aircraft is able to transmit over datalink to us.
|
||||
# For instance, it can be used to check line of sight and maximum range.
|
||||
# The default implementation always returns true (always able to transmit).
|
||||
# Arguments are callsign, property node /ai/models/multiplayer[i], index of the former node.
|
||||
#
|
||||
#
|
||||
# API:
|
||||
# - get_data(callsign)
|
||||
# Returns all datalink information about 'callsign' as an object, or nil if there is none.
|
||||
# This object must not be modified.
|
||||
# It contains the following methods:
|
||||
# callsign(): The aircraft callsign (same as the argument of get_data()).
|
||||
# index(): The aircraft index in /ai/models/multiplayer[i].
|
||||
# on_link(): Returns a bool indicating whether 'callsign' is connected to this aircraft through datalink.
|
||||
#
|
||||
# Extensions can define other methods in this object.
|
||||
#
|
||||
# - get_connected_callsigns() / get_connected_indices()
|
||||
# Returns a vector containing all callsigns, resp. indices
|
||||
# in /ai/models/multiplayer[i], of aircrafts connected on datalink.
|
||||
# Both vectors use the same order, i.e. get_connected_callsigns()[i]
|
||||
# and get_connected_indices()[i] correspond to the same aircraft.
|
||||
# Furthermore this order is stable (the relative order of two aircrafts
|
||||
# does not change as long as neither disconnects from multiplayer).
|
||||
#
|
||||
# - get_all_callsigns()
|
||||
# Returns a vector containing all callsigns of aircraft with any associated data.
|
||||
# There is no guarantee on the order of callsigns.
|
||||
#
|
||||
# - send_data(data, timeout=nil)
|
||||
# Send data on the datalink. 'data' is a hash of the form
|
||||
# {
|
||||
# <extension_name>: <extension_data>,
|
||||
# ...
|
||||
# }
|
||||
# If 'timeout' is set, clear_data() will be called after this delay.
|
||||
# Data sent with send_data() is deleted at the next call of send_data(), or by clear_data().
|
||||
#
|
||||
# - clear_data()
|
||||
# Clear data transmitted by this aircraft.
|
||||
#
|
||||
# Important note:
|
||||
# After a send_data(), and until the next send_data() or clear_data(),
|
||||
# the datalink behaves as if you are continuously sending the same data.
|
||||
# Thus, it is important to
|
||||
# 1. either call send_data() regularly
|
||||
# 2. or set the timeout argument of send_data()
|
||||
|
||||
### Extensions
|
||||
|
||||
### Aircraft contacts (extension name: "contacts")
|
||||
#
|
||||
# This extension allows to simulate an aircraft transmitting information about
|
||||
# another aircraft (typically one tracked on radar). The position data is not
|
||||
# actually transmitted (since everyone can access it from simulator internals).
|
||||
#
|
||||
## Receiving data
|
||||
# This extension adds the following methods to the result of get_data("A"):
|
||||
# tracked(): A bool indicating that some aircraft "B" connected on datalink
|
||||
# is transmitting information about aircraft "A".
|
||||
# iff(): One of IFF_UNKNOWN, IFF_HOSTILE, IFF_FRIENDLY, or nil if tracked() is false.
|
||||
# Indicates the result of IFF interrogation of "A" by "B"
|
||||
# IFF_UNKNOWN means that e.g. no IFF interrogation was performed.
|
||||
# tracked_by(): The callsign of the transmitting aircraft ("A"), or nil if tracked() is false.
|
||||
# tracked_by_index(): The index of the transmitting aircraft, or nil if tracked() is false.
|
||||
# The index refers to property nodes /ai/models/multiplayer[i].
|
||||
# is_known(): Equivalent to (on_link() or tracked()).
|
||||
# Indicates if the position of this aircraft is supposed to be known
|
||||
# (i.e. whether or not it should be displayed on a HSD or whatever).
|
||||
# is_friendly(): Equivalent to (on_link() or iff() == IFF_FRIENDLY).
|
||||
# is_hostile(): Equivalent to (!on_link() and iff() == IFF_HOSTILE).
|
||||
#
|
||||
## Sending data
|
||||
# usage: send_data({ contacts: <contacts>, ...}, ...)
|
||||
# where <contacts> is a vector of hashes of the form { callsign: <callsign>, [iff: <iff>,] }.
|
||||
# <callsign> is the multiplayer callsign of the tracked aircraft.
|
||||
# <iff> (optional) is one of IFF_UNKNOWN, IFF_HOSTILE, IFF_FRIENDLY
|
||||
|
||||
### Datalink identifier (extension name: "identifier")
|
||||
#
|
||||
# This extension allows each aircraft on datalink to transmit a personal
|
||||
# identifier, e.g. the number of the aircraft in a flight.
|
||||
#
|
||||
## Receiving data
|
||||
# This extension adds the method identifier() to the result of get_data(),
|
||||
# which returns the identifier, or nil if there is none).
|
||||
#
|
||||
## Sending data
|
||||
# Set the identifier with send_data({"identifier": <identifier>, ...});
|
||||
# The identifier must be a string. It must not contain '!'.
|
||||
|
||||
### Coordinate transmission (extension name: "point")
|
||||
#
|
||||
# This extension allows each aircraft to broadcast a coordinate (geo.Coord object).
|
||||
#
|
||||
## Receiving data
|
||||
# This extension adds the method point() to the result of get_data(),
|
||||
# which results the transmitted geo.Coord object, or nil if there is none.
|
||||
#
|
||||
## Sending data
|
||||
# Transmit a geo.Coord object <coord> with send_data({"point": <coord>, ...});
|
||||
|
||||
|
||||
#### Protocol:
|
||||
#
|
||||
# Data is transmitted on MP generic string[7], with the following format:
|
||||
# <channel>(!<data>)+
|
||||
#
|
||||
# <channel> is a hash of the datalink channel. See hash_channel() and check_channel_hash().
|
||||
# Each <data> block corresponds to data sent by an extension.
|
||||
# It starts with a prefix uniquely defining the extension.
|
||||
# The rest of the block can contain any character (including non-ascii) except '!'.
|
||||
#
|
||||
# Remark: '!' as separator is specifically chosen to allow encoding with emesary.Transfer<type>.
|
||||
#
|
||||
# The current extension prefixes are the following:
|
||||
# contacts: C
|
||||
# identifier: I
|
||||
# point: P
|
||||
|
||||
#### Extensions API
|
||||
#
|
||||
# Creating a new extension is done with
|
||||
# register_extension(name, prefix, object, encode, decode)
|
||||
# name the extension name, used as key in the 'data' argument of send_data().
|
||||
# prefix the protocol prefix.
|
||||
# class contact class parent.
|
||||
# A class from which all contact objects will inherit.
|
||||
# It must have an init() method, which is called whenever a contact is created.
|
||||
#
|
||||
# encode(data) extension encoding function.
|
||||
# Must return the encoding of the extension data (i.e. <data> when calling
|
||||
# send_data({name: <data>})) into a string, which may use any character except '!'.
|
||||
# The extension prefix must not be part of the encoded string.
|
||||
#
|
||||
# decode(aircrafts_data, callsign, index, string) extension decoding function.
|
||||
# 'aircrafts_data' is a hash from callsigns to contact objects (see below).
|
||||
# 'callsign' is the callsign of the aircraft which transmitted this data.
|
||||
# 'index' is the index of the aircraft which transmitted this data.
|
||||
# 'string' is the data encoded by encode() and transmitted through datalink.
|
||||
|
||||
# Each contact in 'data' inherits from the core 'Contact' class, and the extension 'class'.
|
||||
# decode() is expected to modify 'aircrafts_data', by possibly editing
|
||||
# existing contacts and adding new ones. It should be careful when
|
||||
# overwriting existing data in these contacts, including its own: decode()
|
||||
# will be called several time on the same 'aircrafts_data' (once for each
|
||||
# transmitting aircraft).
|
||||
# The modified 'aircrafts_data' hash must be returned.
|
||||
#
|
||||
# decode() may use the following helper functions:
|
||||
# add_if_missing(aircrafts_data, callsign):
|
||||
# Create a new contact object for 'callsign' and add it to 'aircrafts_data',
|
||||
# unless an entry for 'callsign' already exists. Returns the modified hash.
|
||||
|
||||
|
||||
|
||||
#### Version and changelog
|
||||
# current: v1.1.0, minimum compatible: v1.0.0
|
||||
#
|
||||
## v1.1.0:
|
||||
# Allow external transmission restrictions
|
||||
# Make transmitting contact IFF optional
|
||||
# Ensure personal identifier has no '!'
|
||||
# '\n' is redundant for printf()
|
||||
# Fix separator character in documentation
|
||||
# Fix error when sending unknown extension
|
||||
#
|
||||
## v1.0.1:
|
||||
# Add is_known(), is_friendly(), is_hostile() helpers to extension "contacts".
|
||||
#
|
||||
## v1.0.0: Initial version
|
||||
# - Core protocol for datalink channel.
|
||||
# - Extensions "contacts", "identifier", and "point".
|
||||
|
||||
|
||||
|
||||
### Parameters
|
||||
#
|
||||
# Remark: most parameters need to be the same on all aircrafts.
|
||||
|
||||
# Index of multiplayer string used to transmit datalink info.
|
||||
# Must be the same for all aircrafts.
|
||||
var mp_string = 7;
|
||||
var mp_path = "sim/multiplay/generic/string["~mp_string~"]";
|
||||
|
||||
var channel_hash_period = 600;
|
||||
|
||||
var receive_period = getprop("/instrumentation/datalink/receive_period") or 1;
|
||||
|
||||
# Should be overwitten to add transmission restrictions.
|
||||
var can_transmit = func(contact, mp_prop, mp_index) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
### Properties
|
||||
|
||||
var input = {
|
||||
power: getprop("/instrumentation/datalink/power_prop"),
|
||||
channel: getprop("/instrumentation/datalink/channel_prop"),
|
||||
ident: getprop("/instrumentation/datalink/identifier_prop"),
|
||||
mp: mp_path,
|
||||
models: "/ai/models",
|
||||
callsign: "/sim/multiplay/callsign",
|
||||
};
|
||||
|
||||
foreach (var name; keys(input)) {
|
||||
if (input[name] != nil) {
|
||||
input[name] = props.globals.getNode(input[name], 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#### Core protocol implementation
|
||||
|
||||
### Channel hash (based on iff.nas)
|
||||
#
|
||||
# Channel is hashed with current time (rounded to 10min) and own callsign.
|
||||
|
||||
var clean_callsign = func(callsign) {
|
||||
return damage.processCallsign(callsign);
|
||||
}
|
||||
|
||||
var my_callsign = func {
|
||||
return clean_callsign(input.callsign.getValue());
|
||||
}
|
||||
|
||||
# Time, rounded to 'channel_hash_period'. This is used to hash channel.
|
||||
var get_time = func {
|
||||
return int(math.floor(systime() / channel_hash_period) * channel_hash_period);
|
||||
}
|
||||
|
||||
# Previous / next time (with channel_hash_period interval).
|
||||
# This is used to give a bit of margin on the time check.
|
||||
# (will work if system clocks are coordinated within 10min).
|
||||
var get_prev_time = func { return get_time() - channel_hash_period; }
|
||||
var get_next_time = func { return get_time() + channel_hash_period; }
|
||||
|
||||
var parse_hexadecimal = func(str) {
|
||||
var res = 0;
|
||||
for (var i=0; i<size(str); i+=1) {
|
||||
res *= 10;
|
||||
var c = str[i];
|
||||
if (c >= 48 and c < 58) {
|
||||
# digit
|
||||
res += c - 48;
|
||||
} elsif (c >= 65 and c < 71) {
|
||||
# upper case letter
|
||||
res += c - 55;
|
||||
} elsif (c >= 97 and c < 103) {
|
||||
# lower case letter
|
||||
res += c - 87;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
var _hash_channel = func(time, callsign, channel) {
|
||||
# 5 hex digits (2^20) fit in 3 chars for emesary int encoding.
|
||||
var hash = parse_hexadecimal(left(md5(time ~ callsign ~ channel), 5));
|
||||
return emesary.TransferInt.encode(hash, 3);
|
||||
}
|
||||
|
||||
# Hash channel (when sending).
|
||||
var encode_channel = func(channel) {
|
||||
return _hash_channel(get_time(), my_callsign(), channel);
|
||||
}
|
||||
|
||||
# Check that the hash transmitted by aircraft 'callsign' is correct for 'channel'.
|
||||
var check_channel = func(hash, callsign, channel) {
|
||||
return hash == _hash_channel(get_time(), callsign, channel)
|
||||
or hash == _hash_channel(get_prev_time(), callsign, channel)
|
||||
or hash == _hash_channel(get_next_time(), callsign, channel);
|
||||
}
|
||||
|
||||
### Contact object
|
||||
var Contact = {
|
||||
new: func(callsign) {
|
||||
var c = {
|
||||
# contact_parents is the list of all classes from which contacts inherit (for extensions).
|
||||
parents: contact_parents,
|
||||
_callsign: callsign,
|
||||
};
|
||||
# Initialize all inherited classes.
|
||||
foreach (var class; contact_parents) {
|
||||
call(class.init, [], c, nil, nil);
|
||||
}
|
||||
return c;
|
||||
},
|
||||
init: func { me._on_link = 0; },
|
||||
|
||||
callsign: func { return me._callsign; },
|
||||
index: func { return callsign_to_index[me._callsign]; },
|
||||
on_link: func { return me._on_link; },
|
||||
set_on_link: func(b) { me._on_link = b; },
|
||||
};
|
||||
|
||||
### Extensions
|
||||
var extensions = {};
|
||||
var extension_prefixes = {};
|
||||
var max_prefix_length = 0;
|
||||
var contact_parents = [Contact];
|
||||
|
||||
var register_extension = func(name, prefix, class, encode, decode) {
|
||||
if (contains(extensions, name)) {
|
||||
printf("Datalink: double registration of extension '%s'. Skipping.", name);
|
||||
return -1;
|
||||
}
|
||||
if (contains(extension_prefixes, prefix)) {
|
||||
printf("Datalink: double registration of extension prefix '%s'. Skipping.", name);
|
||||
return -1;
|
||||
}
|
||||
extensions[name] = { prefix: prefix, encode: encode, decode: decode, };
|
||||
extension_prefixes[prefix] = name;
|
||||
max_prefix_length = math.max(max_prefix_length, size(prefix));
|
||||
append(contact_parents, class);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
var data_separator = "!";
|
||||
|
||||
|
||||
### Transmission
|
||||
|
||||
var clear_data = func {
|
||||
send_data({});
|
||||
}
|
||||
|
||||
var clear_timer = maketimer(1, clear_data);
|
||||
clear_timer.singleShot = 1;
|
||||
|
||||
# Send data through datalink.
|
||||
#
|
||||
# timeout: if set, sent data will be cleared after this time (other aircrafts
|
||||
# won't receive it anymore). Useful if 'send_data' is not called often.
|
||||
var send_data = func(data, timeout=nil) {
|
||||
if (!input.power.getBoolValue()) {
|
||||
last_data = {};
|
||||
input.mp.setValue("");
|
||||
return;
|
||||
}
|
||||
|
||||
# First encode channel
|
||||
var str = encode_channel(input.channel.getValue());
|
||||
|
||||
# Then all extensions
|
||||
last_data = data;
|
||||
foreach(var ext; keys(data)) {
|
||||
# Skip missing extensions with a warning
|
||||
if (!contains(extensions, ext)) {
|
||||
printf("Warning: unknown datalink extension %s in send_data().", ext);
|
||||
continue;
|
||||
}
|
||||
str = str ~ data_separator ~ extensions[ext].prefix ~ extensions[ext].encode(data[ext]);
|
||||
}
|
||||
|
||||
input.mp.setValue(str);
|
||||
|
||||
if (timeout != nil) {
|
||||
clear_timer.restart(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
# Used internally to update the channel/identifier while keeping the same data.
|
||||
# Does not touch timeout.
|
||||
var last_data = {};
|
||||
var resend_data = func {
|
||||
send_data(last_data);
|
||||
}
|
||||
|
||||
# Very slow timer to ensure the channel hash is updated regularly.
|
||||
# Only relevant if you never call send_data();
|
||||
var hash_update_timer = maketimer(channel_hash_period/2, resend_data);
|
||||
hash_update_timer.start();
|
||||
|
||||
|
||||
### Receiving
|
||||
|
||||
# callsign to data hash
|
||||
var aircrafts_data = {};
|
||||
# List of callsigns / indices connected on datalink (index is for /ai/models/multiplayer[i]).
|
||||
var connected_callsigns = [];
|
||||
var connected_indices = [];
|
||||
|
||||
# Maintain callsign to multiplayer index hash
|
||||
# (doesn't cost much since we already iterate over MP models).
|
||||
var callsign_to_index = {};
|
||||
|
||||
|
||||
var get_data = func(callsign) {
|
||||
return aircrafts_data[callsign];
|
||||
}
|
||||
|
||||
var get_connected_callsigns = func {
|
||||
return connected_callsigns;
|
||||
}
|
||||
|
||||
var get_connected_indices = func {
|
||||
return connected_indices;
|
||||
}
|
||||
|
||||
var get_all_callsigns = func {
|
||||
return keys(aircrafts_data);
|
||||
}
|
||||
|
||||
# Helper for modifying aircrafts_data.
|
||||
var add_if_missing = func(aircrafts_data, callsign) {
|
||||
if (!contains(aircrafts_data, callsign)) {
|
||||
aircrafts_data[callsign] = Contact.new(callsign);
|
||||
}
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
var receive_loop = func {
|
||||
var my_channel = input.channel.getValue();
|
||||
|
||||
aircrafts_data = {};
|
||||
connected_callsigns = [];
|
||||
connected_indices = [];
|
||||
|
||||
var mp_models = input.models.getChildren("multiplayer");
|
||||
foreach(var mp; mp_models) {
|
||||
var idx = mp.getIndex();
|
||||
if (!mp.getValue("valid")) continue;
|
||||
var callsign = mp.getValue("callsign");
|
||||
if (callsign == nil) continue;
|
||||
|
||||
callsign_to_index[callsign] = idx;
|
||||
|
||||
var data = mp.getValue(mp_path);
|
||||
if (data == nil) continue;
|
||||
|
||||
# Split channel part and data part
|
||||
var tokens = split(data_separator, data);
|
||||
|
||||
# Check channel
|
||||
if (!check_channel(tokens[0], callsign, my_channel)) continue;
|
||||
|
||||
# We check this _after_ the channel. Checking the channel is quite cheap,
|
||||
# and we don't know how slow this function is, it might have a get_cart_ground_intersection()
|
||||
if (!can_transmit(callsign, mp, idx)) continue;
|
||||
|
||||
# Add to list of connected aircrafts.
|
||||
append(connected_callsigns, callsign);
|
||||
append(connected_indices, idx);
|
||||
# Add to data
|
||||
aircrafts_data = add_if_missing(aircrafts_data, callsign);
|
||||
aircrafts_data[callsign].set_on_link(1);
|
||||
|
||||
# Parse extensions data
|
||||
for (var i=1; i<size(tokens); i+=1) {
|
||||
var extension = nil;
|
||||
# Identify extension prefix. This is not very clever code, but
|
||||
# realistically it doesn't matter since prefixes are very short.
|
||||
var len = 1;
|
||||
for (; len <= max_prefix_length; len += 1) {
|
||||
if (len > size(tokens)) break;
|
||||
var prefix = left(tokens[i], len);
|
||||
if (contains(extension_prefixes, prefix)) {
|
||||
extension = extension_prefixes[prefix];
|
||||
break;
|
||||
}
|
||||
}
|
||||
# Unknown extension, skip
|
||||
if (extension == nil) continue;
|
||||
# Remove prefix
|
||||
var data = substr(tokens[i], len);
|
||||
# Decode
|
||||
aircrafts_data = extensions[extension].decode(aircrafts_data, callsign, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var receive_timer = maketimer(receive_period, receive_loop);
|
||||
|
||||
|
||||
# Start / stop listener
|
||||
setlistener(input.power, func (node) {
|
||||
if (node.getBoolValue()) {
|
||||
receive_timer.start();
|
||||
resend_data(); # Sets channel/identifier
|
||||
} else {
|
||||
receive_timer.stop();
|
||||
aircrafts_data = {};
|
||||
clear_data();
|
||||
}
|
||||
}, 1, 0);
|
||||
|
||||
# Listener to resend data so as to update the channel.
|
||||
setlistener(input.channel, resend_data);
|
||||
|
||||
|
||||
|
||||
#### Extensions
|
||||
|
||||
## Identifier
|
||||
|
||||
var ContactIdentifier = {
|
||||
init: func {
|
||||
me._identifier = nil;
|
||||
},
|
||||
set_identifier: func(ident) {
|
||||
me._identifier = ident;
|
||||
},
|
||||
identifier: func {
|
||||
return me._identifier;
|
||||
},
|
||||
};
|
||||
|
||||
var encode_identifier = func(ident) {
|
||||
# Force string conversion
|
||||
ident = ""~ident;
|
||||
|
||||
if (find("!", ident) >= 0) {
|
||||
printf("Datalink: Identifier is not allowed to contain '!': %s.", ident);
|
||||
return "";
|
||||
} else {
|
||||
return ident;
|
||||
}
|
||||
}
|
||||
|
||||
var decode_identifier = func(aircrafts_data, callsign, str) {
|
||||
aircrafts_data = add_if_missing(aircrafts_data, callsign);
|
||||
aircrafts_data[callsign].set_identifier(str);
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("identifier", "I", ContactIdentifier, encode_identifier, decode_identifier);
|
||||
|
||||
|
||||
|
||||
## Contacts
|
||||
|
||||
# IFF status transmitted over datalink.
|
||||
var IFF_UNKNOWN = 0; # Unknown status
|
||||
var IFF_HOSTILE = 1; # Considered hostile (no response to IFF).
|
||||
var IFF_FRIENDLY = 2; # Friendly, because positive IFF identification.
|
||||
# This is also the priority order for IFF reports in case of conflicts:
|
||||
# e.g. a contact will be reported as friendly if anyone on datalink reports it as friendly.
|
||||
|
||||
var ContactTracked = {
|
||||
init: func {
|
||||
me._tracked_by = nil;
|
||||
me._iff = IFF_UNKNOWN;
|
||||
},
|
||||
set_tracked_by: func(callsign) {
|
||||
me._tracked_by = callsign;
|
||||
},
|
||||
set_iff: func(iff) {
|
||||
# Priority order on IFF values (friendly, then hostile, then no data).
|
||||
me._iff = math.max(me._iff, iff);
|
||||
},
|
||||
tracked: func {
|
||||
return me._tracked_by != nil;
|
||||
},
|
||||
tracked_by: func {
|
||||
return me._tracked_by;
|
||||
},
|
||||
tracked_by_index: func {
|
||||
return (me._tracked_by != nil) ? callsign_to_index[me._tracked_by] : nil;
|
||||
},
|
||||
iff: func {
|
||||
return me._iff;
|
||||
},
|
||||
is_known: func {
|
||||
return me.on_link() or me.tracked();
|
||||
},
|
||||
is_friendly: func {
|
||||
return me.on_link() or me.iff() == IFF_FRIENDLY;
|
||||
},
|
||||
is_hostile: func {
|
||||
return !me.on_link() and me.iff() == IFF_HOSTILE;
|
||||
},
|
||||
};
|
||||
|
||||
# Contact encoding: callsign + bits
|
||||
# callsign: the callsign encoded with emesary.TransferString
|
||||
# bits: bitfield |xxxxxxff| (left is most significant)
|
||||
# f: IFF, x: unused
|
||||
# encoded with emesary.TransferByte
|
||||
# Additional values may be appended for extensions.
|
||||
|
||||
var encode_contact = func(contact) {
|
||||
# Encode bitfield
|
||||
var bits = contact["iff"] != nil ? contact.iff : IFF_UNKNOWN;
|
||||
|
||||
return emesary.TransferString.encode(clean_callsign(contact.callsign))
|
||||
~ emesary.TransferByte.encode(bits);
|
||||
}
|
||||
|
||||
var decode_contact = func(str) {
|
||||
var res = {};
|
||||
var dv = emesary.TransferString.decode(str, 0);
|
||||
res.callsign = dv.value;
|
||||
dv = emesary.TransferByte.decode(str, dv.pos);
|
||||
var bits = dv.value;
|
||||
res.iff = math.mod(bits, 4);
|
||||
return res;
|
||||
}
|
||||
|
||||
# Special character, won't be used by emesary encoding.
|
||||
var contacts_separator = "#";
|
||||
|
||||
var encode_contacts = func(contacts) {
|
||||
var str = "";
|
||||
foreach (var contact; contacts) {
|
||||
str = str~encode_contact(contact)~contacts_separator;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var decode_contacts = func(aircrafts_data, callsign, str) {
|
||||
var contacts = split(contacts_separator, str);
|
||||
foreach (var contact; contacts) {
|
||||
if (contact == "") continue;
|
||||
var res = decode_contact(contact);
|
||||
aircrafts_data = add_if_missing(aircrafts_data, res.callsign);
|
||||
aircrafts_data[res.callsign].set_iff(res.iff);
|
||||
aircrafts_data[res.callsign].set_tracked_by(callsign);
|
||||
}
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("contacts", "C", ContactTracked, encode_contacts, decode_contacts);
|
||||
|
||||
|
||||
|
||||
## Coordinate
|
||||
|
||||
var ContactPoint = {
|
||||
init: func {
|
||||
me._point = nil;
|
||||
},
|
||||
set_point: func(point) {
|
||||
me._point = point;
|
||||
},
|
||||
point: func {
|
||||
return me._point;
|
||||
},
|
||||
};
|
||||
|
||||
var encode_point = func(coord) {
|
||||
return emesary.TransferCoord.encode(coord);
|
||||
}
|
||||
|
||||
var decode_point = func(aircrafts_data, callsign, str) {
|
||||
var coord = emesary.TransferCoord.decode(str, 0).value;
|
||||
aircrafts_data = add_if_missing(aircrafts_data, callsign);
|
||||
aircrafts_data[callsign].set_point(coord);
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
@@ -13,8 +13,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#io.include("Aircraft/ExpansionPack/Nasal/init.nas");
|
||||
srand();# seed the random generator with systime
|
||||
|
||||
#io.include("Aircraft/ExpansionPack/Nasal/init.nas");
|
||||
|
||||
#with("updateloop");
|
||||
|
||||
# Number of iterations per second
|
||||
|
||||
62
BUK-M2/Nasal/fire-control-custom.nas
Normal file
62
BUK-M2/Nasal/fire-control-custom.nas
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
################### SAM INFO
|
||||
|
||||
var setupTime = 300;#minimum 'launcher_tilt_time' secs no matter what, due to anim and stuff.
|
||||
var reload_time = 900;
|
||||
var launcher_final_tilt_deg = 24;
|
||||
var launcher_start_tilt_deg = 24;
|
||||
var launcher_tilt_time = 0;
|
||||
var sam_align_to_target = 1;
|
||||
var launcher_align_to_target = 0;
|
||||
var align_speed_dps = 20;
|
||||
var radar_elevation_above_terrain_m = 3;
|
||||
var radar_lowest_pitch = 0.5;# 0.5 degs = roughly 925 feet at 20 nm, 25 feet at half a nm. # 0.35 = roughly 925 feet at 20 nm, 25 feet at half a nm.
|
||||
var radar_off_time_min = 30;# When turning off to lure enemies into engagement zone, and to not make the SAM too easy to find, minimum turn off this duration.
|
||||
var radar_off_time_max = 90;# Bigger missile_max_distance give crew incentive to keep this a bit longer
|
||||
var radar_on_time = 45;# Minimum the time it would take to scan whole sky
|
||||
var radar_on_after_detect_time = 180;# Crew is alert after spotting an aircraft, how long should they stay that way?
|
||||
var can_detect_anti_rad = 0.35;# 0.5 very good, 0 not at all.
|
||||
|
||||
#reaction tme for s-300p is 28 secs acording to http://www.astronautix.com/s/s-300p.html
|
||||
# sounds a bit high, as its 4 secs for s-400
|
||||
|
||||
################### CIWS INFO
|
||||
|
||||
var ciws_installed = 0;
|
||||
var ciws_domain_nm = 1.50; #range where it can kill
|
||||
var ciws_chance = 0.20; #chance to get a kill at 0nm distance
|
||||
var ciws_burst_rounds = 60;#how many rounds in a burst
|
||||
var ciws_shell = 15;#from lookup table in damage.nas
|
||||
var ROUNDS_init = 30;
|
||||
var ROUNDS = ROUNDS_init;#CIWS bursts remaining
|
||||
|
||||
################### MISSILE INFO
|
||||
|
||||
var NUM_MISSILES = 3; # total carried minus 1
|
||||
var missile_name = "M317";
|
||||
var missile_brevity = damage.id2warhead[getprop("payload/armament/"~string.lc(missile_name)~"/type-id")][4];
|
||||
var missile_max_distance = getprop("payload/armament/"~string.lc(missile_name)~"/max-fire-range-nm"); #max distance of target in nm when it will fire
|
||||
var missile_min_distance = getprop("payload/armament/"~string.lc(missile_name)~"/min-fire-range-nm"); #minimum distance in nm when it will fire
|
||||
var lockon_time = 12; #time in seconds it takes to lock on and get a firing solution on a target
|
||||
var fire_minimum_interval = 7;# time since last track was initiated till a new can be initiated
|
||||
var same_target_max_missiles = 1;# max number of missiles in air against same target
|
||||
|
||||
var isInEngagementEnvelope = func (target_radial_airspeed, target_ground_distance, target_relative_altitude) {
|
||||
# is the plane within the engagement envelope?
|
||||
# the numbers after target_radial_airspeed are ( offset_of_engagement_envelope / speed_to_apply_that_offset )
|
||||
# larger offset means it wont fire until the plane is closer.
|
||||
# for visualization: https://www.desmos.com/calculator/gw570fa9km
|
||||
var vren = nil;
|
||||
if ( target_radial_airspeed < 0 ) {
|
||||
vren = 1 + target_radial_airspeed * ( 0.4 / 750 );
|
||||
} else {
|
||||
vren = 1 + target_radial_airspeed * ( -0.25 / 750 );
|
||||
}
|
||||
target_ground_distance = target_ground_distance * M2NM;
|
||||
var engagement_altitude = ((1 + vren) * (-.008 * math.pow(target_ground_distance,2)) + 0.5 * target_ground_distance + 5) * 6076.12;
|
||||
return target_relative_altitude <= engagement_altitude;
|
||||
}
|
||||
|
||||
var midflight = nil;
|
||||
|
||||
|
||||
646
BUK-M2/Nasal/fire-control.nas
Normal file
646
BUK-M2/Nasal/fire-control.nas
Normal file
@@ -0,0 +1,646 @@
|
||||
################### GLOBALS
|
||||
|
||||
var AIR = 0;
|
||||
var MARINE = 1;
|
||||
var SURFACE = 2;
|
||||
var ORDNANCE = 3;
|
||||
|
||||
var radar_update_time = 2;
|
||||
var launch_update_time = 0.3;
|
||||
var reloading = 0;
|
||||
var missile_delay_time = 0;#time when last track was initiated
|
||||
var missile_release_time = 0;#time when last missile was fired
|
||||
var ciws_delay_time = 0;#time when CIWS was last fired
|
||||
var launch_in_progress = 0;# if a firing solution is currently being calculated
|
||||
var reload_starting = 0;
|
||||
var ACTIVE_MISSILE = 0;
|
||||
var semi_active_track = nil;# with multiple missiles flying in semi-active-radar mode, this can change rather fast. Which means pilots wont get a steady tone, but disrupted tones. (tradeoff)
|
||||
var mutexLock = thread.newlock();
|
||||
var radarStatus = 0;# Current radar status.
|
||||
var radarOnTimestamp = -500;# Last timestamp of when the radar was online
|
||||
var radarOffTimestamp = -500;# Last timestamp of when the radar was offline
|
||||
var radarOffDuration = radar_off_time_min;
|
||||
var radarTrackTime = 0;# Last time stamp where any enemy aircraft has been spotted.
|
||||
|
||||
##########################################################################
|
||||
######################## Common SAM code ###########################
|
||||
##########################################################################
|
||||
|
||||
################### VARIOUS
|
||||
|
||||
setprop("sim/multiplay/generic/float[7]", 0);# tracking radar vert rotation
|
||||
setprop("sim/multiplay/generic/float[8]", 0);# tracking radar horiz rotation
|
||||
setprop("sim/multiplay/generic/float[5]", 0);# launcher vert rotation
|
||||
setprop("sim/multiplay/generic/float[6]", 0);# launcher horiz rotation
|
||||
var start_time = systime();
|
||||
|
||||
var opfor_switch = "enemies/opfor-switch";
|
||||
setprop(opfor_switch,0);
|
||||
var friend_switch = "enemies/friend-switch";
|
||||
setprop(friend_switch,0);
|
||||
|
||||
################### IFF
|
||||
|
||||
var target = {
|
||||
new: func (callsign) {
|
||||
var m = { parents: [target] };
|
||||
m.callsign = callsign;
|
||||
m.in_air = 0;
|
||||
m.tracking = 0;
|
||||
m.missiles = [];
|
||||
return m;
|
||||
},
|
||||
};
|
||||
|
||||
var base = props.globals.getNode("/");
|
||||
base.getNode("instrumentation/transponder/id-code",1).setIntValue(-9999);
|
||||
base.getNode("instrumentation/transponder/transmitted-id",1).setIntValue(-9999);# transponder off
|
||||
|
||||
###################################################################
|
||||
|
||||
var targetsV2 = nil;
|
||||
|
||||
var buildTargetList = func {
|
||||
# rather crappy code, but is not ran so often, so dont really matter.
|
||||
if (getprop(opfor_switch) == 0 and getprop(friend_switch) == 0) {
|
||||
for(var i = 1; i<=12;i+=1) {
|
||||
# add new callsign to list
|
||||
var sign = getprop("enemies/e"~i);
|
||||
var tgt = lookup(sign);
|
||||
if (tgt == nil) {
|
||||
targetsV2.append(target.new(sign));
|
||||
print("added callsign: "~sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
var removeList = [];
|
||||
foreach(tgt ; targetsV2.vector) {
|
||||
# schedule removed callsigns to be removed
|
||||
if (getprop(opfor_switch) == 0 and getprop(friend_switch) == 0) {
|
||||
if (tgt.callsign != getprop("enemies/e1") and tgt.callsign != getprop("enemies/e2") and tgt.callsign != getprop("enemies/e3") and tgt.callsign != getprop("enemies/e4") and tgt.callsign != getprop("enemies/e5") and tgt.callsign != getprop("enemies/e6") and tgt.callsign != getprop("enemies/e7") and tgt.callsign != getprop("enemies/e8") and tgt.callsign != getprop("enemies/e9") and tgt.callsign != getprop("enemies/e10") and tgt.callsign != getprop("enemies/e11") and tgt.callsign != getprop("enemies/e12")) {
|
||||
append(removeList, tgt);
|
||||
print("will remove callsign: "~tgt.callsign);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(tgt ; removeList) {
|
||||
# remove callsigns
|
||||
call(func {targetsV2.remove(tgt);}, nil, var err = []);
|
||||
}
|
||||
};
|
||||
|
||||
var lookup = func (sign) {
|
||||
|
||||
foreach (tgt ; targetsV2.vector) {
|
||||
if (tgt.callsign == sign) {
|
||||
return tgt;
|
||||
}
|
||||
}
|
||||
if ( getprop(opfor_switch) == 1 and (left(sign, 5) != "OPFOR" and left(sign,5) != "opfor")) {
|
||||
print("creating new target in: " ~ sign);
|
||||
tgt = target.new(sign);
|
||||
targetsV2.append(tgt);
|
||||
return tgt;
|
||||
}
|
||||
if ( getprop(friend_switch) == 1 and ( left(sign, 5) == "OPFOR" or left(sign,5) == "opfor" )) {
|
||||
print("creating new target in: " ~ sign);
|
||||
tgt = target.new(sign);
|
||||
targetsV2.append(tgt);
|
||||
return tgt;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
var PRIO_NORM = 0;
|
||||
var PRIO_HIGH = 1;
|
||||
var PRIO_LOW = 2;
|
||||
var PRIO_FAST = 3;
|
||||
var PRIO_SLOW = 4;
|
||||
var PRIO_CLOSE = 5;
|
||||
var PRIO_FAR = 6;
|
||||
|
||||
|
||||
################### MAIN LOOP
|
||||
|
||||
var scan = func() {
|
||||
setprop("sim/multiplay/visibility-range-nm", 250);
|
||||
buildTargetList();
|
||||
|
||||
if ( getprop("/carrier/sunk") == 1 or getprop("/carrier/disabled") == 1) {
|
||||
setprop("sim/multiplay/generic/string[6]", "");
|
||||
datalink.clear_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSetup() ) {
|
||||
printf("Seconds till activation: %.1f", setupTime - (systime() - start_time));
|
||||
setprop("sam/timeleft", setupTime - (systime() - start_time));
|
||||
setprop("sam/missiles",(NUM_MISSILES+1-ACTIVE_MISSILE));
|
||||
setprop("sam/bursts", ROUNDS);
|
||||
setprop("sam/info", "Preparing launch system");
|
||||
settimer(scan,radar_update_time);
|
||||
if (launcher_tilt_time > 0) {
|
||||
setprop("sim/multiplay/generic/float[5]", launcher_final_tilt_deg*math.max(0,(systime() - start_time)-(setupTime-launcher_tilt_time))/launcher_tilt_time);#raise the tubes in last 15 secs of activation
|
||||
} else {
|
||||
setprop("sim/multiplay/generic/float[5]", launcher_final_tilt_deg);
|
||||
}
|
||||
setprop("sim/multiplay/generic/float[6]", 0);
|
||||
setprop("sim/multiplay/generic/float[7]", 0);
|
||||
setprop("sim/multiplay/generic/float[8]", 0);
|
||||
setprop("sim/multiplay/generic/string[6]", "");
|
||||
setprop("/sim/multiplay/generic/int[2]", 1);
|
||||
datalink.clear_data();
|
||||
return;
|
||||
}
|
||||
setprop("sim/multiplay/generic/float[5]", launcher_final_tilt_deg);
|
||||
#### ITERATE THROUGH MP LIST ####
|
||||
if (radarStatus == 1) {
|
||||
var my_pos = geo.aircraft_position();
|
||||
var radarAlt = my_pos.alt()+radar_elevation_above_terrain_m;
|
||||
my_pos.set_alt(radarAlt);
|
||||
var mvec = props.globals.getNode("/ai/models").getChildren("multiplayer");
|
||||
var tvec = props.globals.getNode("/ai/models").getChildren("tanker");
|
||||
var avec = props.globals.getNode("/ai/models").getChildren("aircraft");
|
||||
if (mvec!=nil and tvec != nil) {
|
||||
mvec = mvec ~ tvec;
|
||||
}
|
||||
if (mvec!=nil and avec != nil) {
|
||||
mvec = mvec ~ avec;
|
||||
}
|
||||
var prio_vector = [];#0:node,1:trigger,2:prio value
|
||||
foreach(var mp; mvec){
|
||||
if (mp.getNode("valid") == nil or mp.getNode("valid").getValue() != 1) continue;
|
||||
var prio = fire_control(mp, my_pos);
|
||||
append(prio_vector, prio);
|
||||
if (prio[3] == 1) {
|
||||
radarTrackTime = systime();#this target is within envelope, we turn on radar.
|
||||
}
|
||||
}
|
||||
prio_vector = sort(prio_vector, func (a,b) {if (a[2]>b[2]){return -1;} elsif (a[2]<b[2]) {return 1;} else {return 0;}});
|
||||
foreach(var mp; prio_vector) {
|
||||
|
||||
#### DO WE HAVE FIRING SOLUTION... ####
|
||||
# is plane in range, do we still have missiles, and is a missile already inbound, and has it been 4 seconds since the last missile launch?
|
||||
var trigger = mp[1];
|
||||
#print("dist to target = " ~ dist_to_target);
|
||||
|
||||
var lu = lookup(mp[0].getNode("callsign").getValue());
|
||||
if ( launch_in_progress == 0 and trigger == 1 and lu != nil and lu.in_air < same_target_max_missiles and !lu.tracking and ACTIVE_MISSILE <= NUM_MISSILES and ( systime() - missile_delay_time > fire_minimum_interval ) ) { #
|
||||
#### ... FOR THE MISSILE ####
|
||||
#print("callsign " ~ cs ~ " found at " ~ dist_to_target);
|
||||
missile_delay_time = systime();
|
||||
mp[0].getNode("unique",1).setValue(rand());
|
||||
armament.contact = radar_logic.Contact.new(mp[0], AIR);
|
||||
launch_in_progress = 1;
|
||||
missile_launch(mp[0], systime(), my_pos);
|
||||
|
||||
} elsif ( ciws_installed and trigger == -1 and ROUNDS > 0 and ( systime() - ciws_delay_time > 1.0 ) and lu != nil) {
|
||||
#### ... FOR THE CIWS ####
|
||||
var contact = radar_logic.Contact.new(mp[0], AIR);
|
||||
var cord = contact.get_Coord();
|
||||
var dist_nm = my_pos.direct_distance_to(cord)*M2NM;
|
||||
var probabilityOfBurstKill = 0.50;
|
||||
if (mp[0].getNode("velocities/true-airspeed-kt").getValue() > 50) {
|
||||
probabilityOfBurstKill = extrapolate(dist_nm, 0, ciws_domain_nm, ciws_chance, 0);
|
||||
}
|
||||
var hits = math.max(0,int(extrapolate(rand(), 0, probabilityOfBurstKill, ciws_burst_rounds, 3)));#3 is a kill approx
|
||||
var target_bearing = my_pos.course_to(cord);
|
||||
setprop("sim/multiplay/generic/float[0]", -(target_bearing-getprop("orientation/heading-deg")));#CIWS horiz (inverted)
|
||||
setprop("sim/multiplay/generic/float[1]", vector.Math.getPitch(my_pos, cord));#CIWS vert
|
||||
setprop("sim/multiplay/generic/bool[0]",1);settimer(func {setprop("sim/multiplay/generic/bool[0]",0);}, 1);# for sound
|
||||
if (hits > 0) {
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, -1*(ciws_shell+1));
|
||||
msg.RelativeAltitude = 0;
|
||||
msg.Bearing = 0;
|
||||
msg.Distance = hits;
|
||||
msg.RemoteCallsign = mp[0].getNode("callsign").getValue();
|
||||
notifications.hitBridgedTransmitter.NotifyAll(msg);
|
||||
damage.damageLog.push("CIWS fired | rounds remaining: " ~ ROUNDS ~ " | hit on: " ~ mp[0].getNode("callsign").getValue());
|
||||
}
|
||||
print("CIWS fired | bursts remaining: " ~ ROUNDS ~ " | "~hits~" hits on: " ~ mp[0].getNode("callsign").getValue() ~ " @ "~ sprintf("%.1f",dist_nm) ~" nm");
|
||||
ciws_delay_time = systime();
|
||||
ROUNDS = ROUNDS - 1;
|
||||
setprop("sam/bursts", ROUNDS);
|
||||
if (ROUNDS == 0) {
|
||||
print("Launcher out of shell ammo.");
|
||||
settimer(autoreload, reload_time);
|
||||
reloading = 1;
|
||||
reload_starting = systime();
|
||||
}
|
||||
}
|
||||
if (lu != nil and lu.tracking) {
|
||||
radarTrackTime = systime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (launcher_align_to_target and ACTIVE_MISSILE > NUM_MISSILES and systime()-missile_release_time > 2) {
|
||||
# rotate launcher back to forward:
|
||||
var tgt_dir = 0;
|
||||
var cur_dir = getprop("sim/multiplay/generic/float[6]");
|
||||
var move_dir = geo.normdeg180(tgt_dir-cur_dir);
|
||||
var max_dir = radar_update_time*align_speed_dps*0.25;
|
||||
move_dir = math.clamp(move_dir, -max_dir, max_dir);
|
||||
setprop("sim/multiplay/generic/float[6]", cur_dir+move_dir);
|
||||
}
|
||||
if (launch_in_progress == 0) {
|
||||
if (reloading) {
|
||||
setprop("sam/info", "Reloading");
|
||||
setprop("sam/timeleft", reload_time - (systime() - reload_starting));
|
||||
} else {
|
||||
setprop("sam/info", "Search radar is "~(radarStatus==1?"ON":"OFF"));
|
||||
setprop("sam/timeleft", 0);
|
||||
}
|
||||
clearSingleLock();
|
||||
thread.lock(mutexLock);
|
||||
semi_active_track = nil;
|
||||
thread.unlock(mutexLock);
|
||||
} else {
|
||||
setprop("sam/timeleft", 0);
|
||||
}
|
||||
if (getprop(getprop("payload/armament/MP-alt-ft")) == 0.0) {
|
||||
# reset 'Follow view' to look at launcher
|
||||
setprop(getprop("payload/armament/MP-lat"),getprop("position/latitude-deg"));
|
||||
setprop(getprop("payload/armament/MP-lon"),getprop("position/longitude-deg"));
|
||||
setprop(getprop("payload/armament/MP-alt-ft"),getprop("position/altitude-ft"));
|
||||
}
|
||||
setprop("sam/missiles",(NUM_MISSILES+1-ACTIVE_MISSILE));
|
||||
settimer(scan,radar_update_time);
|
||||
}
|
||||
|
||||
var isSetup = func {
|
||||
return systime() - start_time < setupTime;
|
||||
}
|
||||
|
||||
var acquisitionRadarLoop = func {
|
||||
if (isSetup() or reloading or getprop("/carrier/sunk") == 1 or getprop("/carrier/disabled") == 1) return;
|
||||
var reason = "";
|
||||
var time = systime();
|
||||
if (time - radarTrackTime < radar_on_after_detect_time) {
|
||||
radarStatus = 1;
|
||||
reason = sprintf("Crew alert for %d seconds", radar_on_after_detect_time - (time - radarTrackTime));
|
||||
} elsif (radarStatus == 0 and time - radarOnTimestamp > radarOffDuration) {
|
||||
radarStatus = 1;
|
||||
reason = sprintf("Periodic check for %d seconds", radar_on_time);
|
||||
} elsif (radarStatus == 1 and time - radarOffTimestamp > radar_on_time) {
|
||||
radarStatus = 0;
|
||||
radarOffDuration = rand()*(radar_off_time_max - radar_off_time_min)+radar_off_time_min;
|
||||
reason = sprintf("Periodic pause for %d seconds", radarOffDuration);
|
||||
}
|
||||
|
||||
if (getprop("payload/armament/"~string.lc(missile_name)~"/guidance") == "tvm" and radarStatus == 0) {
|
||||
foreach(var tgt ; targetsV2.vector) {
|
||||
if (tgt.in_air > 0) {
|
||||
radarTrackTime = time;
|
||||
radarStatus = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setprop("/sim/multiplay/generic/int[2]", radarStatus != 1);
|
||||
if (radarStatus == 1) radarOnTimestamp = time;
|
||||
else radarOffTimestamp = time;
|
||||
#print("Search radar is "~(radarStatus==1?"ON":"OFF"));
|
||||
if (reason != "") print(reason);
|
||||
}
|
||||
|
||||
var radTimer = maketimer(0.5, acquisitionRadarLoop);
|
||||
radTimer.start();
|
||||
|
||||
var clearSingleLock = func () {
|
||||
thread.lock(mutexLock);
|
||||
if (semi_active_track == nil) {
|
||||
setprop("sim/multiplay/generic/string[6]", "");
|
||||
datalink.clear_data();
|
||||
} else {
|
||||
setprop("sim/multiplay/generic/string[6]", left(md5(semi_active_track), 4));
|
||||
datalink.send_data({"contacts":[{"callsign":semi_active_track,"iff":0}]});
|
||||
}
|
||||
thread.unlock(mutexLock);
|
||||
}
|
||||
|
||||
################## FIRE CONTROL
|
||||
################## ALL AI LOGIC RELATED TO FIGURING OUT IF A TARGET SHOULD BE SHOT AT SHOULD GO HERE.
|
||||
|
||||
var fire_control = func(mp, my_pos) {
|
||||
# gather some data about the target
|
||||
|
||||
if ( mp.getNode("valid").getValue() == 0 ) { return [mp,0,0,0]; }
|
||||
|
||||
var ufo_pos = geo.Coord.new().set_latlon(mp.getNode("position/latitude-deg").getValue(),mp.getNode("position/longitude-deg").getValue(),(mp.getNode("position/altitude-ft").getValue() * FT2M));
|
||||
var target_distance = my_pos.direct_distance_to(ufo_pos);
|
||||
var target_altitude = mp.getNode("position/altitude-ft").getValue();
|
||||
|
||||
# is this plane a friend or foe?
|
||||
var lu = lookup(mp.getNode("callsign").getValue());
|
||||
if ( lu == nil ) { return [mp,0,0,0]; }
|
||||
|
||||
var target_airspeed = mp.getNode("velocities/true-airspeed-kt").getValue();
|
||||
var target_ground_distance = my_pos.distance_to(ufo_pos);
|
||||
var target_heading = mp.getNode("orientation/true-heading-deg").getValue();
|
||||
var relative_bearing = math.abs(geo.normdeg180(ufo_pos.course_to(my_pos) - target_heading));
|
||||
|
||||
var target_relative_altitude = target_altitude - my_pos.alt()*M2FT;
|
||||
var target_radial_airspeed = math.abs(math.abs(((relative_bearing / 90 ) - 1) * target_airspeed));#200kt against us = 200kt, 200kt at angle of us = 0kt, 200kt away from us = 200kt
|
||||
var target_relative_pitch = vector.Math.getPitch(my_pos, ufo_pos);
|
||||
|
||||
|
||||
# can the radar see it?
|
||||
var data_link_match = 0;
|
||||
# foreach(var cx; gci.data_receive_callsigns) {
|
||||
# if (cx[0] == callsign) {
|
||||
# data_link_match = true;
|
||||
# #print('tgt confirmed via datalink');
|
||||
# }
|
||||
# }
|
||||
|
||||
var visible = radar_logic.isNotBehindTerrain(mp);
|
||||
|
||||
|
||||
if (ciws_installed and ROUNDS > 0 and target_distance*M2NM < ciws_domain_nm) {
|
||||
#CIWS
|
||||
var radarSeeTarget = 1;
|
||||
if ( data_link_match == 0 ) {
|
||||
if ( visible[0] == 0 ) {radarSeeTarget = 0 }
|
||||
if ( target_relative_pitch < radar_lowest_pitch ) { radarSeeTarget = 0 } #
|
||||
if ( target_distance*M2NM > 1.0 and visible[1] and math.abs(target_radial_airspeed) < 20 ) {radarSeeTarget = 0 } # i.e. notching with terrain behind
|
||||
}
|
||||
|
||||
if (radarSeeTarget and rand() > target_distance*M2NM / ciws_domain_nm) {
|
||||
var score = 0;
|
||||
var priority = getprop("priority");
|
||||
if (priority==PRIO_NORM) {
|
||||
score = rand()-0.5;
|
||||
} elsif (priority==PRIO_HIGH) {
|
||||
score = target_altitude;
|
||||
} elsif (priority==PRIO_LOW) {
|
||||
score = -target_altitude;
|
||||
} elsif (priority==PRIO_FAST) {
|
||||
score = target_radial_airspeed;
|
||||
} elsif (priority==PRIO_SLOW) {
|
||||
score = -target_radial_airspeed;
|
||||
} elsif (priority==PRIO_CLOSE) {
|
||||
score = -target_distance;
|
||||
} elsif (priority==PRIO_FAR) {
|
||||
score = target_distance;
|
||||
}
|
||||
return [mp,-1,score,1];
|
||||
}
|
||||
}
|
||||
|
||||
if ( data_link_match == 0 ) {
|
||||
if (target_airspeed < 60) {return [mp,0,0,0];}
|
||||
if ( visible[0] == 0 ) { return [mp,0,0,0]; }
|
||||
if ( target_relative_pitch < radar_lowest_pitch ) { return [mp,0,0,0]; } #
|
||||
if ( visible[1] and math.abs(target_radial_airspeed) < 20 ) { return [mp,0,0,0]; } # i.e. notching, landed aircraft
|
||||
}
|
||||
|
||||
if ( target_distance * M2NM > missile_max_distance ) { return [mp,0,0,0]; }
|
||||
if ( target_distance * M2NM < missile_min_distance ) { return [mp,0,0,0]; }
|
||||
|
||||
|
||||
|
||||
|
||||
# is the plane within the engagement envelope?
|
||||
# the numbers after target_radial_airspeed are ( offset_of_engagement_envelope / speed_to_apply_that_offset )
|
||||
# larger offset means it wont fire until the plane is closer.
|
||||
# for visualization: https://www.desmos.com/calculator/gw570fa9km
|
||||
|
||||
if (!isInEngagementEnvelope(target_radial_airspeed, target_ground_distance, target_relative_altitude) ) { return [mp,0,0,0]; }
|
||||
|
||||
|
||||
|
||||
var the_dice = rand();
|
||||
|
||||
if ( the_dice > 0.20 ) {
|
||||
var score = 0;
|
||||
var priority = getprop("priority");
|
||||
if (priority==PRIO_NORM) {
|
||||
score = rand()-0.5;
|
||||
} elsif (priority==PRIO_HIGH) {
|
||||
score = target_altitude;
|
||||
} elsif (priority==PRIO_LOW) {
|
||||
score = -target_altitude;
|
||||
} elsif (priority==PRIO_FAST) {
|
||||
score = target_radial_airspeed;
|
||||
} elsif (priority==PRIO_SLOW) {
|
||||
score = -target_radial_airspeed;
|
||||
} elsif (priority==PRIO_CLOSE) {
|
||||
score = -target_distance;
|
||||
} elsif (priority==PRIO_FAR) {
|
||||
score = target_distance;
|
||||
}
|
||||
return [mp,1,score,1];
|
||||
} else {
|
||||
return [mp,0,0,1];
|
||||
}
|
||||
}
|
||||
|
||||
################### MISSILE CONTROL
|
||||
|
||||
|
||||
### missile reload
|
||||
|
||||
var reload = func(force = 1) {
|
||||
#figure out how many to add
|
||||
if (ACTIVE_MISSILE > NUM_MISSILES or force == 1) {
|
||||
for ( var i = 0; i <= NUM_MISSILES; i = i + 1 ) {
|
||||
|
||||
if (armament.AIM.new(i,missile_name,missile_brevity, midflight) != -1) {
|
||||
#if statement just in case reload was called before all missiles were fired. Cause avoid calling search() on same missile twice.
|
||||
armament.AIM.active[i].radarZ = radar_elevation_above_terrain_m;
|
||||
armament.AIM.active[i].start();
|
||||
}
|
||||
}
|
||||
ACTIVE_MISSILE = 0;setprop("active", 0);
|
||||
print("Launcher reloaded with "~(NUM_MISSILES+1)~" missiles.");
|
||||
setprop("/sim/messages/copilot", "Launcher reloaded with "~(NUM_MISSILES+1)~" missiles.");
|
||||
}
|
||||
if (ROUNDS == 0 or force == 1) {
|
||||
ROUNDS = ROUNDS_init;
|
||||
print("Reloaded with "~(ROUNDS)~" bursts.");
|
||||
}
|
||||
setprop("sam/missiles",(NUM_MISSILES+1-ACTIVE_MISSILE));
|
||||
setprop("sam/bursts", ROUNDS);
|
||||
reloading = 0;
|
||||
}
|
||||
|
||||
var autoreload = func() {
|
||||
if ( getprop("/carrier/sunk") == 1 or getprop("/carrier/disabled") == 1) {
|
||||
return;
|
||||
}
|
||||
if (reloading) {
|
||||
reloading = 0;
|
||||
if (ACTIVE_MISSILE > NUM_MISSILES or ROUNDS == 0) {
|
||||
reload(0);
|
||||
print("Auto reloading completed.")
|
||||
}
|
||||
} else {
|
||||
print("Auto reloading cancelled due to manual reload.")
|
||||
}
|
||||
}
|
||||
|
||||
### missile launch
|
||||
|
||||
var missile_launch = func(mp, launchtime, my_pos) {
|
||||
if ( getprop("/carrier/sunk") == 1 or getprop("/carrier/disabled") == 1) {
|
||||
var lu = lookup(mp.getNode("callsign").getValue());
|
||||
if (lu != nil) {
|
||||
lu.tracking = 0;
|
||||
}
|
||||
launch_in_progress = 0;
|
||||
clearSingleLock();
|
||||
return;
|
||||
}
|
||||
var ufo_pos = geo.Coord.new().set_latlon(mp.getNode("position/latitude-deg").getValue(),mp.getNode("position/longitude-deg").getValue(),(mp.getNode("position/altitude-ft").getValue() * 0.3048));
|
||||
var target_bearing = my_pos.course_to(ufo_pos);
|
||||
var target_pitch = vector.Math.getPitch(my_pos, ufo_pos);
|
||||
var info = mp.getNode("callsign").getValue();
|
||||
var lu = lookup(mp.getNode("callsign").getValue());
|
||||
if (getprop("sam/timeleft") != 0) {
|
||||
launch_in_progress = 0;
|
||||
if (lu != nil) {
|
||||
lu.tracking = 0;
|
||||
}
|
||||
return;
|
||||
} elsif ( armament.AIM.active[ACTIVE_MISSILE].status == 1 and systime() - launchtime > lockon_time and radar_logic.isNotBehindTerrain(mp)[0] == 1 ) {
|
||||
var theMissile = armament.AIM.active[ACTIVE_MISSILE];
|
||||
var brevity = theMissile.brevity;
|
||||
#armament.defeatSpamFilter(brevity ~ " at: " ~ mp.getNode("callsign").getValue());
|
||||
damage.damageLog.push(brevity ~ " at: " ~ mp.getNode("callsign").getValue());
|
||||
if (launcher_align_to_target) {
|
||||
setprop("sim/multiplay/generic/float[6]", target_bearing-getprop("orientation/heading-deg"));
|
||||
theMissile.rail_head_deg = getprop("sim/multiplay/generic/float[6]");
|
||||
}
|
||||
setprop("sim/multiplay/generic/float[7]", target_pitch);
|
||||
setprop("sim/multiplay/generic/float[8]", target_bearing-getprop("orientation/heading-deg"));
|
||||
if (sam_align_to_target) {
|
||||
setprop("/orientation/heading-deg",target_bearing);
|
||||
}
|
||||
theMissile.release();
|
||||
missile_release_time = systime();
|
||||
ACTIVE_MISSILE = ACTIVE_MISSILE + 1;setprop("active", ACTIVE_MISSILE);
|
||||
print("Fired "~missile_name~" #" ~ ACTIVE_MISSILE ~ " at: " ~ mp.getNode("callsign").getValue());
|
||||
setprop("/sim/messages/copilot", "Launch at "~mp.getNode("callsign").getValue());
|
||||
if (ACTIVE_MISSILE > NUM_MISSILES) {
|
||||
setprop("/sim/messages/copilot", "Launcher out of ammo");
|
||||
print("Launcher out of missile ammo.");
|
||||
settimer(autoreload, reload_time);
|
||||
reloading = 1;
|
||||
reload_starting = systime();
|
||||
}
|
||||
if (lu != nil) {
|
||||
append(lu.missiles, theMissile);
|
||||
lu.in_air += 1;
|
||||
lu.tracking = 0;
|
||||
}
|
||||
launch_in_progress = 0;
|
||||
info = info~" (launched)";
|
||||
setprop("sam/info", info);
|
||||
setprop("sam/missiles",(NUM_MISSILES+1-ACTIVE_MISSILE));
|
||||
clearSingleLock();
|
||||
return;
|
||||
} elsif ((systime() - launchtime) > (lockon_time*1.5) or radar_logic.isNotBehindTerrain(mp)[0] == 0) {
|
||||
# launch cancelled so it dont forever goes in this loop and dont allow for other firings.
|
||||
if (lu != nil) {
|
||||
lu.tracking = 0;
|
||||
}
|
||||
setprop("/sim/messages/copilot", "SAM Canceled launch at "~mp.getNode("callsign").getValue());
|
||||
launch_in_progress = 0;
|
||||
info = info~" (cancelled)";
|
||||
setprop("sam/info", info);
|
||||
setprop("sam/missiles",(NUM_MISSILES+1-ACTIVE_MISSILE));
|
||||
clearSingleLock();
|
||||
return;
|
||||
} else {
|
||||
info = sprintf("%s (tracking %d nm at %d ft)", info, armament.contact.get_range(), armament.contact.get_altitude());
|
||||
if (systime()-missile_release_time > 1.5) {
|
||||
var tgt_dir = target_bearing-getprop("orientation/heading-deg");
|
||||
var max_dir = launch_update_time*align_speed_dps;
|
||||
if (launcher_align_to_target) {
|
||||
# now smoothly rotate launcher:
|
||||
var cur_dir = getprop("sim/multiplay/generic/float[6]");
|
||||
var move_dir = geo.normdeg180(tgt_dir-cur_dir);
|
||||
move_dir = math.clamp(move_dir, -max_dir, max_dir);
|
||||
setprop("sim/multiplay/generic/float[6]", cur_dir+move_dir);
|
||||
}
|
||||
var cur_dir2 = getprop("sim/multiplay/generic/float[8]");
|
||||
var move_dir2 = geo.normdeg180(tgt_dir-cur_dir2);
|
||||
move_dir2 = math.clamp(move_dir2, -max_dir, max_dir);
|
||||
setprop("sim/multiplay/generic/float[8]", cur_dir2+move_dir2);
|
||||
if (sam_align_to_target) {
|
||||
var tgt_dir = target_bearing;
|
||||
var cur_dir = getprop("orientation/heading-deg");
|
||||
var move_dir = geo.normdeg180(tgt_dir-cur_dir);
|
||||
var max_dir = launch_update_time*align_speed_dps;
|
||||
move_dir = math.clamp(move_dir, -max_dir, max_dir);
|
||||
setprop("orientation/heading-deg", cur_dir+move_dir);
|
||||
}
|
||||
}
|
||||
|
||||
setprop("sam/info", info);
|
||||
if (mp.getNode("callsign") != nil and mp.getNode("callsign").getValue() != nil and mp.getNode("callsign").getValue() != "") {
|
||||
if (getprop("payload/armament/"~string.lc(missile_name)~"/guidance") != "tvm") setprop("sim/multiplay/generic/string[6]", left(md5(mp.getNode("callsign").getValue()), 4));
|
||||
datalink.send_data({"contacts":[{"callsign":mp.getNode("callsign").getValue(),"iff":0}]});
|
||||
} else {
|
||||
clearSingleLock();
|
||||
}
|
||||
if (lu != nil) {
|
||||
lu.tracking = 1;
|
||||
radarTrackTime = systime();
|
||||
}
|
||||
}
|
||||
|
||||
settimer( func { missile_launch(mp, launchtime, my_pos); },launch_update_time);
|
||||
}
|
||||
|
||||
### missile set launched to false for target
|
||||
|
||||
var missile_listener = func {
|
||||
foreach(var tgt ; targetsV2.vector) {
|
||||
var missilesNew = [];
|
||||
foreach(var missile ; tgt.missiles) {
|
||||
if (missile != nil) {
|
||||
if (missile.deleted) {
|
||||
tgt.in_air -= 1;
|
||||
} else {
|
||||
append(missilesNew, missile);
|
||||
}
|
||||
}
|
||||
}
|
||||
tgt.missiles = missilesNew;
|
||||
}
|
||||
settimer(missile_listener, 2.5);
|
||||
}
|
||||
|
||||
var extrapolate = func (x, x1, x2, y1, y2) {
|
||||
return y1 + ((x - x1) / (x2 - x1)) * (y2 - y1);
|
||||
}
|
||||
|
||||
################### MISC
|
||||
|
||||
var main_init_listener = setlistener("sim/signals/fdm-initialized", func {
|
||||
print("fdm-initialized");
|
||||
targetsV2 = std.Vector.new();# OO vector (to make removing item easier)
|
||||
reload();
|
||||
scan();
|
||||
aircraft.data.save(0.5);# save the target list every 30 seconds
|
||||
removelistener(main_init_listener);
|
||||
setlistener(opfor_switch, func {
|
||||
targetsV2 = std.Vector.new();# OO vector (to make removing item easier)
|
||||
}, 0, 0);
|
||||
setlistener(friend_switch, func {
|
||||
targetsV2 = std.Vector.new();# OO vector (to make removing item easier)
|
||||
}, 0, 0);
|
||||
missile_listener();
|
||||
setprop(getprop("payload/armament/MP-lat"),getprop("position/latitude-deg"));
|
||||
setprop(getprop("payload/armament/MP-lon"),getprop("position/longitude-deg"));
|
||||
setprop(getprop("payload/armament/MP-alt-ft"),getprop("position/altitude-ft"));
|
||||
view.setViewByIndex(200);#follow view
|
||||
}, 0, 0);
|
||||
|
||||
setlistener("sim/signals/reinit", func {
|
||||
print("reinit");
|
||||
start_time = systime();
|
||||
});
|
||||
5930
BUK-M2/Nasal/guided-missiles.nas
Normal file
5930
BUK-M2/Nasal/guided-missiles.nas
Normal file
File diff suppressed because it is too large
Load Diff
427
BUK-M2/Nasal/radar-logic.nas
Normal file
427
BUK-M2/Nasal/radar-logic.nas
Normal file
@@ -0,0 +1,427 @@
|
||||
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
||||
var encode3bits = func(first, second, third) {
|
||||
var integer = first;
|
||||
integer = integer + 2 * second;
|
||||
integer = integer + 4 * third;
|
||||
return integer;
|
||||
}
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
|
||||
var AIR = 0;
|
||||
var MARINE = 1;
|
||||
var SURFACE = 2;
|
||||
var ORDNANCE = 3;
|
||||
|
||||
var Contact = {
|
||||
# For now only used in guided missiles, to make it compatible with Mirage 2000-5.
|
||||
new: func(c, class) {
|
||||
var obj = { parents : [Contact]};
|
||||
#debug.benchmark("radar process1", func {
|
||||
obj.rdrProp = c.getNode("radar");
|
||||
obj.oriProp = c.getNode("orientation");
|
||||
obj.velProp = c.getNode("velocities");
|
||||
obj.posProp = c.getNode("position");
|
||||
obj.heading = obj.oriProp.getNode("true-heading-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process2", func {
|
||||
obj.alt = obj.posProp.getNode("altitude-ft");
|
||||
obj.lat = obj.posProp.getNode("latitude-deg");
|
||||
obj.lon = obj.posProp.getNode("longitude-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process3", func {
|
||||
#As it is a geo.Coord object, we have to update lat/lon/alt ->and alt is in meters
|
||||
obj.coord = geo.Coord.new();
|
||||
obj.coord.set_latlon(obj.lat.getValue(), obj.lon.getValue(), obj.alt.getValue() * FT2M);
|
||||
#});
|
||||
#debug.benchmark("radar process4", func {
|
||||
obj.pitch = obj.oriProp.getNode("pitch-deg");
|
||||
obj.roll = obj.oriProp.getNode("roll-deg");
|
||||
obj.speed = obj.velProp.getNode("true-airspeed-kt");
|
||||
obj.vSpeed = obj.velProp.getNode("vertical-speed-fps");
|
||||
obj.callsign = c.getNode("callsign", 1);
|
||||
obj.shorter = c.getNode("model-shorter");
|
||||
obj.orig_callsign = obj.callsign.getValue();
|
||||
obj.name = c.getNode("name");
|
||||
obj.sign = c.getNode("sign",1);
|
||||
obj.valid = c.getNode("valid");
|
||||
obj.painted = c.getNode("painted");
|
||||
obj.unique = c.getNode("unique");
|
||||
obj.validTree = 0;
|
||||
#});
|
||||
#debug.benchmark("radar process5", func {
|
||||
#obj.transponderID = c.getNode("instrumentation/transponder/transmitted-id");
|
||||
#});
|
||||
#debug.benchmark("radar process6", func {
|
||||
obj.acType = c.getNode("sim/model/ac-type");
|
||||
obj.type = c.getName();
|
||||
obj.index = c.getIndex();
|
||||
obj.string = "ai/models/" ~ obj.type ~ "[" ~ obj.index ~ "]";
|
||||
obj.shortString = obj.type ~ "[" ~ obj.index ~ "]";
|
||||
#});
|
||||
#debug.benchmark("radar process7", func {
|
||||
obj.range = obj.rdrProp.getNode("range-nm");
|
||||
obj.bearing = obj.rdrProp.getNode("bearing-deg");
|
||||
obj.elevation = obj.rdrProp.getNode("elevation-deg");
|
||||
obj.ubody = obj.rdrProp.getNode("velocities/uBody-fps");
|
||||
obj.vbody = obj.rdrProp.getNode("velocities/vBody-fps");
|
||||
obj.wbody = obj.rdrProp.getNode("velocities/wBody-fps");
|
||||
#});
|
||||
obj.deviation = nil;
|
||||
|
||||
obj.node = c;
|
||||
obj.class = class;
|
||||
|
||||
obj.polar = [0,0];
|
||||
obj.cartesian = [0,0];
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
get_uBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.ubody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = me.get_Speed()*KT2FPS;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_vBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.vbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_wBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.wbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
isValid: func () {
|
||||
var valid = me.valid.getValue();
|
||||
if (valid == nil) {
|
||||
valid = 0;
|
||||
}
|
||||
if (me.callsign.getValue() != me.orig_callsign) {
|
||||
valid = 0;
|
||||
}
|
||||
return valid;
|
||||
},
|
||||
|
||||
isPainted: func () {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
isCommandActive: func {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
getUnique: func () {
|
||||
if (me.unique == nil) {
|
||||
me.unique = me.node.getNode("unique");
|
||||
}
|
||||
if (me.unique == nil) {
|
||||
return nil;
|
||||
}
|
||||
var u = me.unique.getValue();
|
||||
return u;
|
||||
},
|
||||
|
||||
getElevation: func() {
|
||||
var e = 0;
|
||||
e = me.elevation.getValue();
|
||||
if(e == nil or e == 0) {
|
||||
# AI/MP has no radar properties
|
||||
var self = geo.aircraft_position();
|
||||
self.set_alt(self.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
me.get_Coord();
|
||||
var angleInv = clamp(self.distance_to(me.coord)/self.direct_distance_to(me.coord), -1, 1);
|
||||
e = (self.alt()>me.coord.alt()?-1:1)*math.acos(angleInv)*R2D;
|
||||
}
|
||||
return e;
|
||||
},
|
||||
|
||||
getNode: func () {
|
||||
return me.node;
|
||||
},
|
||||
|
||||
getFlareNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/flap-deg");
|
||||
},
|
||||
|
||||
getChaffNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/position-deg");
|
||||
},
|
||||
|
||||
setPolar: func(dist, angle) {
|
||||
me.polar = [dist,angle];
|
||||
},
|
||||
|
||||
setCartesian: func(x, y) {
|
||||
me.cartesian = [x,y];
|
||||
},
|
||||
|
||||
remove: func(){
|
||||
if(me.validTree != 0){
|
||||
me.validTree.setValue(0);
|
||||
}
|
||||
},
|
||||
|
||||
get_Coord: func(){
|
||||
me.coord.set_latlon(me.lat.getValue(), me.lon.getValue(), me.alt.getValue() * FT2M);
|
||||
var TgTCoord = geo.Coord.new(me.coord);
|
||||
return TgTCoord;
|
||||
},
|
||||
|
||||
get_Callsign: func(){
|
||||
var n = me.callsign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return "UFO";
|
||||
},
|
||||
|
||||
get_model: func(){
|
||||
var n = "";
|
||||
if (me.shorter == nil) {
|
||||
me.shorter = me.node.getNode("model-shorter");
|
||||
}
|
||||
if (me.shorter != nil) {
|
||||
n = me.shorter.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return me.get_Callsign();
|
||||
},
|
||||
|
||||
get_Speed: func(){
|
||||
# return true airspeed
|
||||
var n = me.speed.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Longitude: func(){
|
||||
var n = me.lon.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Latitude: func(){
|
||||
var n = me.lat.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Pitch: func(){
|
||||
var n = me.pitch.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
isVirtual: func(){
|
||||
return 0;
|
||||
},
|
||||
|
||||
get_Roll: func(){
|
||||
var n = me.roll.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_heading : func(){
|
||||
var n = me.heading.getValue();
|
||||
if(n == nil)
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing: func(){
|
||||
var n = 0;
|
||||
n = me.bearing.getValue();
|
||||
if(n == nil or n == 0) {
|
||||
# AI/MP has no radar properties
|
||||
n = me.get_bearing_from_Coord(geo.aircraft_position());
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing_from_Coord: func(MyAircraftCoord){
|
||||
me.get_Coord();
|
||||
var myBearing = 0;
|
||||
if(me.coord.is_defined()) {
|
||||
myBearing = MyAircraftCoord.course_to(me.coord);
|
||||
}
|
||||
return myBearing;
|
||||
},
|
||||
|
||||
get_reciprocal_bearing: func(){
|
||||
return geo.normdeg(me.get_bearing() + 180);
|
||||
},
|
||||
|
||||
get_deviation: func(true_heading_ref, coord){
|
||||
me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing_from_Coord(coord));
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_altitude: func(){
|
||||
#Return Alt in feet
|
||||
return me.alt.getValue();
|
||||
},
|
||||
|
||||
get_Elevation_from_Coord: func(MyAircraftCoord) {
|
||||
me.get_Coord();
|
||||
var value = (me.coord.alt() - MyAircraftCoord.alt()) / me.coord.direct_distance_to(MyAircraftCoord);
|
||||
if (math.abs(value) > 1) {
|
||||
# warning this else will fail if logged in as observer and see aircraft on other side of globe
|
||||
return 0;
|
||||
}
|
||||
var myPitch = math.asin(value) * R2D;
|
||||
return myPitch;
|
||||
},
|
||||
|
||||
get_total_elevation_from_Coord: func(own_pitch, MyAircraftCoord){
|
||||
var myTotalElevation = - deviation_normdeg(own_pitch, me.get_Elevation_from_Coord(MyAircraftCoord));
|
||||
return myTotalElevation;
|
||||
},
|
||||
|
||||
get_total_elevation: func(own_pitch) {
|
||||
me.deviation = - deviation_normdeg(own_pitch, me.getElevation());
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_range: func() {
|
||||
var r = 0;
|
||||
if(me.range == nil or me.range.getValue() == nil or me.range.getValue() == 0) {
|
||||
# AI/MP has no radar properties
|
||||
me.get_Coord();
|
||||
r = me.coord.direct_distance_to(geo.aircraft_position()) * M2NM;
|
||||
} else {
|
||||
r = me.range.getValue();
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
get_range_from_Coord: func(MyAircraftCoord) {
|
||||
var myCoord = me.get_Coord();
|
||||
var myDistance = 0;
|
||||
if(myCoord.is_defined()) {
|
||||
myDistance = MyAircraftCoord.direct_distance_to(myCoord) * M2NM;
|
||||
}
|
||||
return myDistance;
|
||||
},
|
||||
|
||||
get_type: func () {
|
||||
return me.class;
|
||||
},
|
||||
|
||||
get_cartesian: func() {
|
||||
return me.cartesian;
|
||||
},
|
||||
|
||||
get_polar: func() {
|
||||
return me.polar;
|
||||
},
|
||||
};
|
||||
|
||||
var isNotBehindTerrain = func( mp ) {
|
||||
var pos = mp.getNode("position");
|
||||
var alt = pos.getNode("altitude-ft").getValue();
|
||||
var lat = pos.getNode("latitude-deg").getValue();
|
||||
var lon = pos.getNode("longitude-deg").getValue();
|
||||
if(alt == nil or lat == nil or lon == nil) {
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
var aircraftPos = geo.Coord.new().set_latlon(lat, lon, alt*FT2M);
|
||||
|
||||
var myPos = geo.aircraft_position();
|
||||
|
||||
myPos.set_alt(myPos.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
|
||||
var target_distance = myPos.direct_distance_to(aircraftPos);
|
||||
|
||||
call(func {
|
||||
if (target_distance*0.001 > 3.57*(math.sqrt(myPos.alt())+math.sqrt(alt*FT2M))) {
|
||||
# behind earth curvature
|
||||
#print("behind earth curvature");
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
},nil,nil,var err =[]);
|
||||
|
||||
var xyz = {"x":myPos.x(), "y":myPos.y(), "z":myPos.z()};
|
||||
var dir = {"x":aircraftPos.x()-myPos.x(), "y":aircraftPos.y()-myPos.y(), "z":aircraftPos.z()-myPos.z()};
|
||||
|
||||
# Check for terrain between own aircraft and other:
|
||||
v = get_cart_ground_intersection(xyz, dir);
|
||||
if (v == nil) {
|
||||
return [1,0]; # visible and not in front of terrain
|
||||
#printf("No terrain, planes has clear view of each other");
|
||||
} else {
|
||||
var terrain = geo.Coord.new();
|
||||
terrain.set_latlon(v.lat, v.lon, v.elevation);
|
||||
var maxDist = myPos.direct_distance_to(aircraftPos);
|
||||
var terrainDist = myPos.direct_distance_to(terrain);
|
||||
if (terrainDist < maxDist-1) {
|
||||
#printf("terrain found between me and aircraft %.1f meter away.", terrainDist);
|
||||
return [0,0]; # visible and not in front of terrain
|
||||
} else {
|
||||
#print("The planes has clear view of each other");
|
||||
return [1,1]; # visible and in front of terrain
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
BUK-M2/Sounds/launch.wav
Normal file
BIN
BUK-M2/Sounds/launch.wav
Normal file
Binary file not shown.
25
BUK-M2/Sounds/sound.xml
Normal file
25
BUK-M2/Sounds/sound.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<PropertyList>
|
||||
<fx>
|
||||
<launch>
|
||||
<name>missile</name>
|
||||
<path>Aircraft/BUK-M2/Sounds/launch.wav</path>
|
||||
<mode>once</mode>
|
||||
<condition>
|
||||
<property>payload/armament/m317/sound-fire-on-off</property>
|
||||
</condition>
|
||||
<reference-dist>50</reference-dist>
|
||||
<max-dist>15000</max-dist>
|
||||
<position>
|
||||
<x> 0.01 </x>
|
||||
<y> 0.01 </y>
|
||||
<z> 0.01 </z>
|
||||
</position>
|
||||
<volume>
|
||||
<factor>1</factor>
|
||||
<max>1</max>
|
||||
</volume>
|
||||
</launch>
|
||||
</fx>
|
||||
</PropertyList>
|
||||
348
BUK-M2/gui/dialogs/enemies.xml
Normal file
348
BUK-M2/gui/dialogs/enemies.xml
Normal file
@@ -0,0 +1,348 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList>
|
||||
<name>enemies</name>
|
||||
<modal>false</modal>
|
||||
<layout>vbox</layout>
|
||||
<draggable>true</draggable>
|
||||
<resizable>true</resizable>
|
||||
<width>250</width>
|
||||
<height>550</height>
|
||||
|
||||
<group>
|
||||
<layout>hbox</layout>
|
||||
<empty><stretch>1</stretch></empty>
|
||||
|
||||
<text>
|
||||
<label>Targets</label>
|
||||
</text>
|
||||
|
||||
<empty><stretch>1</stretch></empty>
|
||||
|
||||
<button>
|
||||
<pref-width>16</pref-width>
|
||||
<pref-height>16</pref-height>
|
||||
<legend></legend>
|
||||
<default>1</default>
|
||||
<keynum>27</keynum>
|
||||
<border>2</border>
|
||||
<binding>
|
||||
<command>dialog-close</command>
|
||||
</binding>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</button>
|
||||
</group>
|
||||
|
||||
<text>
|
||||
<label>Callsigns:</label>
|
||||
<height>25</height>
|
||||
</text>
|
||||
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>1</label>
|
||||
<property>enemies/e1</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>2</label>
|
||||
<property>enemies/e2</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>3</label>
|
||||
<property>enemies/e3</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>4</label>
|
||||
<property>enemies/e4</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>5</label>
|
||||
<property>enemies/e5</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>6</label>
|
||||
<property>enemies/e6</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>7</label>
|
||||
<property>enemies/e7</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>8</label>
|
||||
<property>enemies/e8</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>9</label>
|
||||
<property>enemies/e9</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>10</label>
|
||||
<property>enemies/e10</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>11</label>
|
||||
<property>enemies/e11</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<input>
|
||||
<width>250</width>
|
||||
<height>25</height>
|
||||
<label>12</label>
|
||||
<property>enemies/e12</property>
|
||||
<live>true</live>
|
||||
<halign>left</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>1</red>
|
||||
<green>0.5</green>
|
||||
<blue>0.5</blue>
|
||||
</color>
|
||||
<enable>
|
||||
<not>
|
||||
<property>enemies/opfor-switch</property>
|
||||
</not>
|
||||
<not>
|
||||
<property>enemies/friend-switch</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<checkbox>
|
||||
<width>12</width>
|
||||
<height>12</height>
|
||||
<property>/enemies/opfor-switch</property>
|
||||
<label>Target all non-OPFOR</label>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
<checkbox>
|
||||
<width>12</width>
|
||||
<height>12</height>
|
||||
<property>/enemies/friend-switch</property>
|
||||
<label>Target all OPFOR</label>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
</PropertyList>
|
||||
166
BUK-M2/gui/dialogs/prio.xml
Normal file
166
BUK-M2/gui/dialogs/prio.xml
Normal file
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList>
|
||||
<name>priority</name>
|
||||
<modal>false</modal>
|
||||
<layout>vbox</layout>
|
||||
<draggable>true</draggable>
|
||||
<resizable>false</resizable>
|
||||
<width>150</width>
|
||||
<height>250</height>
|
||||
|
||||
<group>
|
||||
<empty><stretch>1</stretch></empty>
|
||||
<layout>hbox</layout>
|
||||
<text>
|
||||
<label>Priority</label>
|
||||
</text>
|
||||
<empty><stretch>1</stretch></empty>
|
||||
<button>
|
||||
<pref-width>16</pref-width>
|
||||
<pref-height>16</pref-height>
|
||||
<legend></legend>
|
||||
<default>1</default>
|
||||
<keynum>27</keynum>
|
||||
<border>2</border>
|
||||
<binding>
|
||||
<command>dialog-close</command>
|
||||
</binding>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</button>
|
||||
</group>
|
||||
<group>
|
||||
<layout>table</layout>
|
||||
<text>
|
||||
<label>Random</label>
|
||||
<halign>right</halign>
|
||||
<row>0</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>0</row>
|
||||
<col>1</col>
|
||||
<property>priority0</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",0);setprop("priority0",1);setprop("priority6",0);setprop("priority1",0);setprop("priority2",0);setprop("priority3",0);setprop("priority4",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Highest</label>
|
||||
<halign>right</halign>
|
||||
<row>1</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>1</row>
|
||||
<col>1</col>
|
||||
<property>priority1</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",1);setprop("priority1",1);setprop("priority0",0);setprop("priority6",0);setprop("priority2",0);setprop("priority3",0);setprop("priority4",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Lowest</label>
|
||||
<halign>right</halign>
|
||||
<row>2</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>2</row>
|
||||
<col>1</col>
|
||||
<property>priority2</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",2);setprop("priority2",1);setprop("priority0",0);setprop("priority1",0);setprop("priority6",0);setprop("priority3",0);setprop("priority4",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Fastest</label>
|
||||
<halign>right</halign>
|
||||
<row>3</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>3</row>
|
||||
<col>1</col>
|
||||
<property>priority3</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",3);setprop("priority3",1);setprop("priority0",0);setprop("priority1",0);setprop("priority2",0);setprop("priority6",0);setprop("priority4",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Slowest</label>
|
||||
<halign>right</halign>
|
||||
<row>4</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>4</row>
|
||||
<col>1</col>
|
||||
<property>priority4</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",4);setprop("priority4",1);setprop("priority0",0);setprop("priority1",0);setprop("priority2",0);setprop("priority3",0);setprop("priority6",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Closest</label>
|
||||
<halign>right</halign>
|
||||
<row>5</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>5</row>
|
||||
<col>1</col>
|
||||
<property>priority5</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",5);setprop("priority5",1);setprop("priority0",0);setprop("priority1",0);setprop("priority2",0);setprop("priority3",0);setprop("priority4",0);setprop("priority6",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<text>
|
||||
<label>Farthest</label>
|
||||
<halign>right</halign>
|
||||
<row>6</row>
|
||||
<col>0</col>
|
||||
</text>
|
||||
<radio>
|
||||
<row>6</row>
|
||||
<col>1</col>
|
||||
<property>priority6</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("priority",6);setprop("priority6",1);setprop("priority0",0);setprop("priority1",0);setprop("priority2",0);setprop("priority3",0);setprop("priority4",0);setprop("priority5",0);</script>
|
||||
</binding>
|
||||
</radio>
|
||||
<input>
|
||||
<row>7</row>
|
||||
<col>0</col>
|
||||
<width>75</width>
|
||||
<height>25</height>
|
||||
<label>DLNK</label>
|
||||
<property>instrumentation/datalink/channel</property>
|
||||
<live>true</live>
|
||||
<halign>right</halign>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
<color>
|
||||
<red>0.75</red>
|
||||
<green>0.75</green>
|
||||
<blue>1.0</blue>
|
||||
</color>
|
||||
</input>
|
||||
</group>
|
||||
</PropertyList>
|
||||
Reference in New Issue
Block a user