- les même objets que pour FC1
- les éclats et trajectoires obus !!!!
voici le film pour l'install
http://www.youtube.com/watch?v=gOYJ33oFbTo
en complément ci dessous le fichier tacview modifié :
-- Tacview ACMI - Universal Flight Analysis Tool 0.94
-- Export script for DCS: Black Shark
-- Copyright (C) 2006-2009 - Stra Software
-- See http://lomac.strasoftware.com/lomac-acmi.php for more info
-- ACMI text files are exported to [/Black Shark/Temp/] folder
-- TO ENABLE THIS SCRIPT:
-- Set [EnableExportScript = true] in [/Black Shark/Config/export/config.lua]
-- Add [dofile("./Config/Export/TacviewExportBlackShark.lua")] at the end of [/Black Shark/Config/Export/Export.lua]
-- Headers
dofile("./Config/World/World.lua") -- Required to get mission date
dofile("./Scripts/Database/wsTypes.lua") -- Required to get object types definitions
-- Debug tools
function table.val_to_str ( v )
if "string" == type( v ) then
v = string.gsub( v, "\n", "\\n" )
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
return "'" .. v .. "'"
end
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
else
return "table" == type( v ) and table.tostring( v ) or tostring( v )
end
end
function table.key_to_str ( k )
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
return k
else
return "[" .. table.val_to_str( k ) .. "]"
end
end
function table.tostring( tbl )
local result, done = {}, {}
for k, v in ipairs( tbl ) do
table.insert( result, table.val_to_str( v ) )
done[ k ] = true
end
for k, v in pairs( tbl ) do
if not done[ k ] then
table.insert( result,
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
end
end
return "{" .. table.concat( result, "," ) .. "}"
end
-- Terrain exporter
function ExportTerrain()
--[[
-- ge (Black Shark)
ExportSector(40,41);
ExportSector(40,42);
ExportSector(40,43);
ExportSector(40,44);
ExportSector(41,41);
ExportSector(41,42);
ExportSector(41,43);
ExportSector(41,44);
ExportSector(42,40);
ExportSector(42,41);
ExportSector(42,42);
ExportSector(42,43);
ExportSector(42,44);
-- ru (Black Shark)
ExportSector(43,39);
ExportSector(43,40);
ExportSector(43,41);
ExportSector(43,42);
ExportSector(43,43);
ExportSector(43,44);
ExportSector(44,37);
ExportSector(44,38);
ExportSector(44,39);
ExportSector(44,40);
ExportSector(44,41);
ExportSector(44,42);
ExportSector(44,43);
ExportSector(44,44);
ExportSector(45,37);
ExportSector(45,38);
ExportSector(45,39);
ExportSector(45,40);
-- ua (Flaming Cliffs)
ExportSector(44,33);
ExportSector(44,34);
ExportSector(44,35);
ExportSector(45,32);
ExportSector(45,33);
ExportSector(45,34);
ExportSector(45,35);
ExportSector(45,36);
--]]
end
function ExportSector(Latitude,Longitude)
local TerrainFile=io.open(string.format("./Temp/N%02uE%03u.hgt.txt",Latitude,Longitude),"wb");
for y=1200,0,-1 do
local CurrentLatitude=Latitude+y/1200;
for x=0,1200 do
local CurrentLongitude=Longitude+x/1200;
local DCSCoordinates=LoGeoCoordinatesToLoCoordinates(CurrentLongitude,CurrentLatitude);
TerrainFile:write(LoGetAltitude(DCSCoordinates.x,DCSCoordinates.z).."\n");
end
end
io.close(TerrainFile);
end
-- ACMI Log
AcmiData=
{
-- Log parameters
DefaultObjectsUpdatePeriod=1/10, -- Delay between two log updates (in seconds) for default objects, use [0] to force update at each frame
BallisticObjectsUpdatePeriod=1/2, -- Delay between two log updates (in seconds) for ballistic objects, use [0] to force update at each frame
LatitudeOffset=41, -- To improve log resolution
LongitudeOffset=36, -- To improve log resolution
-- Convert Lock-On Object_Type To Tacview Object_Type
ObjectTypeLookupTable=
{
[wsType_Destroyed] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Air]=
{
[-1] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Helicopter] = 0x18, -- Helicopters (including rotary-wing drones)
[wsType_Airplane]=
{
[-1] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Fighter] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_F_Bomber] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Intercepter] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Intruder] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Cruiser] = 0x10, -- Aeroplanes (including fixed-wing drones)
[wsType_Battleplane] = 0x10, -- Aeroplanes (including fixed-wing drones)
},
[wsType_Free_Fall]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Snars]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Chaff] = 0x50, -- Chaff (obviously a chaff cluster)
[wsType_Flare] = 0x54, -- Flare
},
[wsType_Parts]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[203] = 0x60, -- Minor object (e.g. cartridge)
},
[wsType_FuelTank] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
},
},
[wsType_Ground]=
{
[-1] = 0x28, -- Light/Unarmed vehicles
[wsType_Tank]=
{
[-1] = 0x24, -- Armored fighting vehicle
[wsType_NoWeapon]=
{
[-1] = 0x28, -- Light/Unarmed vehicles
[wsTypePredator_GCS] = 0x28, -- Light/Unarmed vehicles
[wsTypePredator_TrojanSpirit]=0x28, -- Light/Unarmed vehicles
},
[wsType_Gun]=
{
[-1] = 0x24, -- Armored fighting vehicle
[wsTypeSandbox] = 0x89, -- Building
[wsTypeBunker] = 0x89, -- Building
[wsTypeAutogun] = 0x2c, -- Infantry
[wsTypeSoldier_AK] = 0x2c, -- Infantry
},
[wsType_MissGun]=
{
[-1] = 0x24, -- Armored fighting vehicle
[wsTypeRPG] = 0x2c, -- Infantry
[wsTypeSoldier_RPG] = 0x2c, -- Infantry
},
},
[wsType_SAM] = 0x20, -- Anti-aircraft warfare (usually: SAM and AAA)
[wsType_Moving]=
{
[-1] = 0x28, -- Light/Unarmed vehicles
[wsType_NoWeapon] = 0x28, -- Light/Unarmed vehicles
[wsType_Gun] = 0x28, -- Light/Unarmed vehicles
[wsType_Miss] = 0x24, -- Armored fighting vehicle
[wsType_ChildMiss] = 0x24, -- Armored fighting vehicle
[wsType_MissGun] = 0x24, -- Armored fighting vehicle
[wsType_Civil] = 0x28, -- Light/Unarmed vehicles
},
[wsType_Standing]=
{
[-1] = 0x89, -- Building
[wsType_NoWeapon] = 0x89, -- Building
[wsType_Gun] = 0x89, -- Building
[wsType_Miss] = 0x20, -- Anti-aircraft warfare (usually: SAM and AAA)
[wsType_ChildMiss] = 0x20, -- Anti-aircraft warfare (usually: SAM and AAA)
[wsType_MissGun] = 0x20, -- Anti-aircraft warfare (usually: SAM and AAA)
[wsType_Civil] = 0x89, -- Building
},
},
[wsType_Navy]=
{
[-1] = 0x30, -- Armed Watercraft (including submarines)
[wsType_Ship]=
{
[-1] = 0x30, -- Armed Watercraft (including submarines)
[wsType_AirCarrier] = 0x34, -- Aircraft carrier (including Helicopter carrier)
[wsType_HCarrier] = 0x34, -- Aircraft carrier (including Helicopter carrier)
[wsType_ArmedShip] = 0x30, -- Armed Watercraft (including submarines)
[wsType_CivilShip] = 0x38, -- Light/Unarmed Watercraft
},
},
[wsType_Weapon]=
{
[-1] = 0x40, -- Missile (guided missiles)
[wsType_Missile]=
{
[-1] = 0x40, -- Missile (guided missiles)
[wsType_AA_Missile] = 0x40, -- Missile (guided missiles)
[wsType_AS_Missile] = 0x40, -- Missile (guided missiles)
[wsType_SA_Missile] = 0x40, -- Missile (guided missiles)
[wsType_SS_Missile] = 0x40, -- Missile (guided missiles)
[wsType_AA_TRAIN_Missile] = 0x40, -- Missile (guided missiles)
[wsType_AS_TRAIN_Missile] = 0x40, -- Missile (guided missiles)
},
[wsType_Bomb]=
{
[-1] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_A] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Guided] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_BetAB] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Cluster] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Antisubmarine] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_ODAB] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Fire] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Nuclear] = 0x4c, -- Bomb (guided and unguided)
[wsType_Bomb_Lighter] = 0x4c, -- Bomb (guided and unguided)
},
[wsType_Shell]=
{
[-1] = 0x48, -- Shell
[wsType_Shell_A] = 0x48, -- Shell
},
[wsType_NURS]=
{
[-1] = 0x44, -- Rocket (unguided missiles)
[wsType_Container] = 0x44, -- Rocket (unguided missiles)
[wsType_Rocket] = 0x44, -- Rocket (unguided missiles)
},
},
[wsType_Static]=
{
[-1] = 0x89, -- Building
[wsType_AirdromePart] = 0x89, -- Building
[wsType_WingPart] = 0x89, -- Building
[wsType_Free_Fall]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Parts]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[255] = -1, -- Particles (e.g. landing gear dust on runway)
},
},
[wsType_Airdrome]=
{
[-1] = 0x81, -- Aerodrome
[wsType_RW1] = 0x81, -- Aerodrome
[wsType_RW2] = 0x81, -- Aerodrome
[wsType_Heliport] = 0x81, -- Aerodrome
},
[wsType_Explosion]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_GroundExp] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
},
[wsType_GContainer]=
{
[-1] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Control_Cont] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Jam_Cont] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Cannon_Cont] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Support] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Snare_Cont] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
[wsType_Smoke_Cont] = 0x46, -- Shrapnel (e.g. Cluster-bomb fragments or exploded plane parts)
},
},
},
-- Convert Lock-On Coalition_ID To Tacview Coalition_ID
CoalitionLookupTable=
{
["Allies"] = 0,
["Enemies"] = 1,
},
-- Convert Lock-On Country_Name To ISO Country_Code
CountryCodeLookupTable=
{
[ 0] = "ru",
[ 1] = "ua",
[ 2] = "us",
[ 3] = "tr",
[ 4] = "uk",
[ 5] = "fr",
[ 6] = "de",
-- [ 7] = "",
[ 8] = "ca",
[ 9] = "es",
[10] = "nl",
[11] = "be",
[12] = "no",
[13] = "dk",
-- [14] = "",
[15] = "il",
[16] = "ge",
[17] = "xi", -- [Insurgents] (free for use ISO code)
},
-- Reduce ID size (to compact text log)
-- OptimizedID=ID^0x1000000 (free in C, hard to do with LUA...)
GetOptimizedID=function(ID)
if math.mod(math.floor(ID/0x1000000),2)==1 then
return ID-0x1000000; -- Clear bit
end
return ID+0x1000000; -- Set bit
end,
-- Trim Given String
Trim=function(StringToTrim)
return string.gsub(StringToTrim,"^%s*(.-)%s*$","%1");
end,
-- Add escape characters
DecorateName=function(Name)
if Name then
Name=string.gsub(Name,"\\","\\\\");
Name=string.gsub(Name,",","\\,");
Name=string.gsub(Name,"=","\\=");
return Name;
end
return "";
end,
-- Trim and decorate name for log output
CleanupName=function(Name)
return AcmiData.DecorateName(AcmiData.Trim(Name));
end,
-- Convert Lock-On unit type to Tacview unit type
ConvertObjectType=function(LockOnObjectType)
local TacviewObjectType;
TacviewObjectType=AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1];
if not TacviewObjectType then
return AcmiData.ObjectTypeLookupTable[-1];
end
if type(TacviewObjectType)~="table" then
return TacviewObjectType;
end
TacviewObjectType=AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][LockOnObjectType.level2];
if not TacviewObjectType then
return AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][-1];
end
if TacviewObjectType and type(TacviewObjectType)~="table" then
return TacviewObjectType;
end
TacviewObjectType=AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][LockOnObjectType.level2][LockOnObjectType.level3];
if not TacviewObjectType then
return AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][LockOnObjectType.level2][-1];
end
if TacviewObjectType and type(TacviewObjectType)~="table" then
return TacviewObjectType;
end
TacviewObjectType=AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][LockOnObjectType.level2][LockOnObjectType.level3][LockOnObjectType.level4];
if not TacviewObjectType then
return AcmiData.ObjectTypeLookupTable[LockOnObjectType.level1][LockOnObjectType.level2][LockOnObjectType.level3][-1];
end
return TacviewObjectType;
end,
-- Begin to log ACMI data
BeginLog=function(self)
-- Reset objects lists
self.LastObjectsStatus={}; -- Last frame object status
self.LoggedObjectsStatus={}; -- Last logged object status (usually older than LastObjectsStatus)
-- Reset tools
self.NextDefaultObjectsUpdateTime=0;
self.NextBallisticObjectsUpdateTime=0;
-- Create a new log file for each mission
self.AcmiFile=io.open("./Temp/Tacview-"..os.date("%Y%m%d-%H%M%S")..".txt.acmi","wb");
if not self.AcmiFile then
return;
end
-- UTF-8 BOM header
self.AcmiFile:write(string.char(0xEF,0xBB,0xBF));
-- Core Header
self.AcmiFile:write("FileType=text/acmi/tacview\n");
self.AcmiFile:write("FileVersion=1.2\n");
self.AcmiFile:write("Source=LOCK ON Flaming Cliff 2.0\n");
self.AcmiFile:write("Recorder=Tacview 0.94\n");
self.AcmiFile:write("RecordingTime="..os.date("!%Y-%m-%dT%H:%M:%SZ",now).."\n");
local PlayerName=LoGetPilotName();
if PlayerName then
self.AcmiFile:write("Author="..self.CleanupName(PlayerName).."\n");
end
-- Declarations
if MissionDate then
-- Crimea Time Zone: Winter(UTC+2) Summer(DST=UTC+3)
-- 3 hours time shift calculation (assume summer Crimea time shift)
local LocalRefTime=os.time{year=2004,month=6,day=22,hour=0};
local UTCRefTime=os.time{year=2004,month=6,day=21,hour=21};
local TimeShift=LocalRefTime-UTCRefTime;
-- Need to manualy apply DST bias because nothing is simple with LUA
local CurrentDate=os.date("*t",now);
local IsDst;
if CurrentDate and CurrentDate.isdst==true then
IsDst=true;
else
IsDst=false;
end
-- Substract 3 hours from the current mission time (not easy with lua)
local LocalMissionTime=os.time{year=MissionDate.Year,month=MissionDate.Month,day=MissionDate.Day,hour=0,isdst=IsDst};
local UTCMissionTime=LocalMissionTime-TimeShift+LoGetMissionStartTime();
local MissionTimeTable=os.date("*t",UTCMissionTime);
self.AcmiFile:write("MissionTime="..string.format("%04u-%02u-%02uT%02u:%02u:%02uZ",MissionTimeTable.year,MissionTimeTable.month,MissionTimeTable.day,MissionTimeTable.hour,MissionTimeTable.min,MissionTimeTable.sec).."\n");
end
self.AcmiFile:write("LatitudeOffset="..self.LatitudeOffset.."\n");
self.AcmiFile:write("LongitudeOffset="..self.LongitudeOffset.."\n");
self.AcmiFile:write("Coalition=Allies,Red\n");
self.AcmiFile:write("Coalition=Enemies,Blue\n");
self.AcmiFile:write("ProvidedEvents=Removed\n");
-- Additional Information
local PlayerID=LoGetPlayerPlaneId();
if PlayerID then
self.AcmiFile:write(string.format("MainAircraftID=%x\n",self.GetOptimizedID(PlayerID)));
end
end,
-- Update ACMI log
UpdateLog=function(self)
-- Check parameters
if not AcmiData.AcmiFile then
return;
end
-- Format current frame time
local CurrentTime=LoGetModelTime();
local FormatedTime=string.format("#%.2f\n",CurrentTime);
local ShouldUpdateLog=true;
-- Add/Update default objects
if CurrentTime>=self.NextDefaultObjectsUpdateTime then
ShouldUpdateLog=true;
self.NextDefaultObjectsUpdateTime=CurrentTime+self.DefaultObjectsUpdatePeriod;
end
local DefaultObjectsList=LoGetWorldObjects(); -- LoGetWorldObjects("units");
if self:AddUpdateObjects(DefaultObjectsList,FormatedTime,ShouldUpdateLog)==true then
FormatedTime=nil;
end
-- Add/Update ballistic objects
if CurrentTime>=self.NextBallisticObjectsUpdateTime then
ShouldUpdateLog=true;
self.NextBallisticObjectsUpdateTime=CurrentTime+self.BallisticObjectsUpdatePeriod;
end
local BallisticObjectsList=LoGetWorldObjects("ballistic");
if self:AddUpdateObjects(BallisticObjectsList,FormatedTime,ShouldUpdateLog)==true then
FormatedTime=nil;
end
-- Remove destroyed objects
self:RemoveObjects(DefaultObjectsList,BallisticObjectsList,FormatedTime);
end,
-- Add/Update objects
AddUpdateObjects=function(self,CurrentObjectsList,FormatedTime,ShouldUpdateLog)
-- Check parameters
if not CurrentObjectsList then
return false;
end
-- Dump objects
local LogWasUpdated=false;
for ID,Object in pairs(CurrentObjectsList) do
-- Check Object Type
local ObjectType=self.ConvertObjectType(Object.Type);
if ObjectType~=-1 then -- Ignore some objects (like particles clouds)
-- Reduce ID size (to compact text log)
local OptimizedID=self.GetOptimizedID(ID);
-- Add new object
if not self.LastObjectsStatus[ID] then
local LogLine;
-- Time prefix
if FormatedTime then
LogLine=FormatedTime;
FormatedTime=nil;
else
LogLine="";
end
-- Object/Pilot Name
local ObjectName=Object.Name;
local PilotName;
if Object.UnitName then
PilotName=Object.UnitName;
else
PilotName="";
end
-- Object Type
local ObjectTypeFormated;
if ObjectType and type(ObjectType)=="number" then
ObjectTypeFormated=string.format("%x",ObjectType);
else
-- This will help to track unknown types
ObjectTypeFormated=string.format("%s.%s.%s.%s",Object.Type.level1,Object.Type.level2,Object.Type.level3,Object.Type.level4);
end
-- Coalition
local CoalitionID;
if ObjectType==0x48 or ObjectType==0x50 or ObjectType==0x54 then
CoalitionID="?"; -- Chaff/Flare/Shell coalition is not reliable in DCS
else
if Object.Coalition then
CoalitionID=self.CoalitionLookupTable[Object.Coalition];
if not CoalitionID then
CoalitionID="?";
end
else
CoalitionID="?";
end
end
-- Country
local CountryCode;
if Object.Country then
CountryCode=self.CountryCodeLookupTable[Object.Country];
if not CountryCode then
CountryCode="?";
end
else
CountryCode="?";
end
-- Group Name
local GroupName;
if Object.GroupName then
GroupName=Object.GroupName;
else
GroupName="?";
end
-- modification yoann suppression des shrapnels
if ObjectType ~= 0x46 then
-- Declare new object
self.AcmiFile:write(LogLine..string.format("+%x,?,%s,%s,%s,%s,%s,%s,?\n",OptimizedID,ObjectTypeFormated,CoalitionID,CountryCode,self.CleanupName(ObjectName),self.CleanupName(PilotName),self.CleanupName(GroupName)));
-- Done
LogWasUpdated=true;
end
end
-- Update object data as required
--
-- modification yoann suppression des shrapnels
if ObjectType ~= 0x46 then
if self:UpdateObject(ID,Object,ObjectType,self.LoggedObjectsStatus[ID],FormatedTime,ShouldUpdateLog)==true then
FormatedTime=nil;
LogWasUpdated=true;
end
end
end
end
-- Completed
return LogWasUpdated;
end,
-- Fix Yaw (because FC/BS map is a 2D projection, not a true 3D sphere)
FixedYaw=function(Yaw,RefX,RefZ,Latitude,Longitude)
local ToNorthPos=LoGeoCoordinatesToLoCoordinates(Longitude,Latitude+.001);
local ToNorthX=ToNorthPos.z-RefZ;
local ToNorthY=ToNorthPos.x-RefX;
local ToNorthLength=math.sqrt(ToNorthX*ToNorthX+ToNorthY*ToNorthY);
if ToNorthLength>0 then
return Yaw-math.asin(ToNorthX/ToNorthLength);
end
return Yaw;
end,
-- Update one object
UpdateObject=function(self,ID,CurrentObjectData,ObjectType,PrevObjectData,FormatedTime,ShouldUpdateLog)
-- Log object dynamic properties
local ChangeDetected=false;
local LogWasUpdated=false;
local Log="";
-- Latitude
if not PrevObjectData or CurrentObjectData.LatLongAlt.Lat~=PrevObjectData.LatLongAlt.Lat then
Log=Log..string.format(",%.6f",CurrentObjectData.LatLongAlt.Lat-self.LatitudeOffset);
ChangeDetected=true;
else
Log=Log..",";
end
-- Longitude
if not PrevObjectData or CurrentObjectData.LatLongAlt.Long~=PrevObjectData.LatLongAlt.Long then
Log=Log..string.format(",%.6f",CurrentObjectData.LatLongAlt.Long-self.LongitudeOffset);
ChangeDetected=true;
else
Log=Log..",";
end
-- Altitude
if not PrevObjectData or CurrentObjectData.LatLongAlt.Alt~=PrevObjectData.LatLongAlt.Alt then
Log=Log..string.format(",%.2f",CurrentObjectData.LatLongAlt.Alt);
ChangeDetected=true;
else
Log=Log..",";
end
-- Roll/Pitch/Yaw
if ObjectType==0x48 or ObjectType==0x50 or ObjectType==0x54 then -- flare/chaff/shell
-- Do not log roll/pitch/yaw to reduce recording size
if not PrevObjectData then
Log=Log..",0,0,0\n";
else
Log=Log..",,,\n";
end
else
if ObjectType==0x4c and CurrentObjectData.Name=="" then
-- Emulate bomblets orientation
if not PrevObjectData then
Log=Log..",?,?,?\n";
else
Log=Log..",,,\n";
end
else
-- Roll
if not PrevObjectData or CurrentObjectData.Bank~=PrevObjectData.Bank then
local NewFormatedRoll=string.format(",%.1f",math.mod(math.deg(CurrentObjectData.Bank),360));
local RollIsDifferent=true;
if PrevObjectData then
local OldFormatedRoll=string.format(",%.1f",math.mod(math.deg(PrevObjectData.Bank),360));
if NewFormatedRoll==OldFormatedRoll then
RollIsDifferent=false;
end
end
if RollIsDifferent==true then
Log=Log..NewFormatedRoll;
ChangeDetected=true;
else
Log=Log..","; -- not different enougth to be dumped
end
else
Log=Log..",";
end
-- Pitch
if not PrevObjectData or CurrentObjectData.Pitch~=PrevObjectData.Pitch then
local NewFormatedPitch=string.format(",%.1f",-math.mod(math.deg(-CurrentObjectData.Pitch),360));
local PitchIsDifferent=true;
if PrevObjectData then
local OldFormatedPitch=string.format(",%.1f",-math.mod(math.deg(-PrevObjectData.Pitch),360));
if NewFormatedPitch==OldFormatedPitch then
PitchIsDifferent=false;
end
end
if PitchIsDifferent==true then
Log=Log..NewFormatedPitch;
ChangeDetected=true;
else
Log=Log..","; -- not different enougth to be dumped
end
else
Log=Log..",";
end
-- Yaw
if not PrevObjectData or CurrentObjectData.Heading~=PrevObjectData.Heading then
local NewFormatedYaw=string.format(",%.1f\n",math.mod(math.deg(AcmiData.FixedYaw(CurrentObjectData.Heading,CurrentObjectData.Position.x,CurrentObjectData.Position.z,CurrentObjectData.LatLongAlt.Lat,CurrentObjectData.LatLongAlt.Long)),360));
local YawIsDifferent=true;
if PrevObjectData then
local OldFormatedYaw=string.format(",%.1f\n",math.mod(math.deg(AcmiData.FixedYaw(PrevObjectData.Heading,PrevObjectData.Position.x,PrevObjectData.Position.z,PrevObjectData.LatLongAlt.Lat,PrevObjectData.LatLongAlt.Long)),360));
if NewFormatedYaw==OldFormatedYaw then
YawIsDifferent=false;
end
end
if YawIsDifferent==true then
Log=Log..NewFormatedYaw;
ChangeDetected=true;
else
Log=Log..",\n"; -- not different enougth to be dumped
end
else
Log=Log..",\n";
end
end
end
-- Log data
if not PrevObjectData or ( ChangeDetected==true and ShouldUpdateLog==true ) then
local OptimizedID=self.GetOptimizedID(ID);
if FormatedTime then
self.AcmiFile:write(FormatedTime..string.format("%x",OptimizedID)..Log);
else
self.AcmiFile:write(string.format("%x",OptimizedID)..Log);
end
LogWasUpdated=true;
-- Remember Last Logged Object Properties
self.LoggedObjectsStatus[ID]=CurrentObjectData;
end
-- Remember Current Frame Object Properties
self.LastObjectsStatus[ID]=CurrentObjectData;
-- Complete
return LogWasUpdated;
end,
-- Remove any destroyed objects
RemoveObjects=function(self,DefaultObjectsList,BallisticObjectsList,FormatedTime)
local Log;
for ID,Object in pairs(self.LastObjectsStatus) do
if (not DefaultObjectsList or not DefaultObjectsList[ID]) and (not BallisticObjectsList or not BallisticObjectsList[ID]) then
-- Log last position if required
local ObjectType=self.ConvertObjectType(Object.Type);
if self:UpdateObject(ID,Object,ObjectType,self.LoggedObjectsStatus[ID],FormatedTime,true)==true then
FormatedTime=nil;
end
-- Prefix event with time if required
if FormatedTime then
Log=FormatedTime;
FormatedTime=nil;
else
Log="";
end
-- Log Event
self.AcmiFile:write(Log..string.format("!20,%x\n",self.GetOptimizedID(ID)));
-- Remove object from lists
self.LoggedObjectsStatus[ID]=nil;
self.LastObjectsStatus[ID]=nil;
end
end
end,
-- Stop ACMI logging
EndLog=function(self)
if self.AcmiFile then
io.close(self.AcmiFile);
end
end,
}
-- (Hook) Works once right before mission start.
do
local PrevLuaExportStart=LuaExportStart;
LuaExportStart=function()
ExportTerrain();
AcmiData:BeginLog();
if PrevLuaExportStart then
PrevLuaExportStart();
end
end
end
-- (Hook) Works right after every simulation frame.
do
local PrevLuaExportAfterNextFrame=LuaExportAfterNextFrame;
LuaExportAfterNextFrame=function()
AcmiData:UpdateLog();
if PrevLuaExportAfterNextFrame then
PrevLuaExportAfterNextFrame();
end
end
end
-- (Hook) Works once right after mission stop.
do
local PrevLuaExportStop=LuaExportStop;
LuaExportStop=function()
AcmiData:EndLog();
if PrevLuaExportStop then
PrevLuaExportStop();
end
end
end
0 commentaires:
Enregistrer un commentaire