library ToolBox;

{$mode delphi}{$H+}

{$R *.res}

uses
  Classes
  { you can add units after this }
  ,mainform,uHCDefines, uHCGCI, uHCGlobals, uHCTypeDefs, uHCEventHelpers,
  uHCDateTime, uHCAnnexHelpers, uHCAnnexDefs, uLazGUIGlobals, UHCUtils,
  Windows, Forms, ShellAPI, SysUtils, Types, Dialogs, Interfaces, Controls,
  runtimetypeinfocontrols, FileInfo, IniFiles;

const
  DLLVERN = 29;
  DLLVERINTN = 43;

var
  frmMain: TfrmMain;
  intGameTime, intGameTimeLeft: Long;
  dt_scen_start: PHCDateTimeRec;
  FileVersionInfo:TFileVersionInfo;
  strFileVersion, strTemp, gStrVerHC, strFileID, iniFileID: string;
  pGrpTemp: PHCGroup;
  RepFile: TIniFile;
  bAARDataRunning: Boolean;

{*** Return DLL internal version, i.e. revision 5 of my DLL ***}
function DLLVer():word;export;cdecl;
begin
  result := DLLVERN;
end;

{*** Return DLL interface version, i.e. revision 1 of HCE interface spec ***}
function DLLVerInt():word;export;cdecl;
begin
  result := DLLVERINTN;
end;

{*** Return DLL description, 255 characters max ***}
function DLLDesc():PAnsiChar;export;cdecl;
begin
  result := 'HCE Toolbox - export DLL by Don Thomas/Tony Eischens';
end;

{*** Free DLL ***}
procedure DLLFree();export;cdecl;
begin
  // Do any cleanup here, this is the end
  frmMain.Free;
end;

{*** Init DLL ***}
procedure DLLInit(hwndHC: HWND; pathHC: PAnsiChar; verHC: PAnsiChar;
  verSaveGame: LongWord; funcRefs: PHCDLL_FUNC_REF; PGEClosing: Pointer;
  PDLLBusy: Pointer; verInterface: LongWord; srandSeed: longword;        //  ddt update 020423
  harpoon_uuid_session: PAnsiChar; hclicense_dt_expire: Int64;
  hclicense_licensee: PAnsiChar; usblicense_desc: PAnsiChar;
  RESRSRStructureVersion: ulong;
  AnnexVersion: ushort; GameComponent: uchar);export;cdecl;
var
    funcTmp: PHCDLL_FUNC_REF;

begin
  // here we initialize globals and such for the life of the DLL
  Application.Initialize;
  uLazGUIGlobals.PDLLBusy:=PDLLBusy;
  uLazGUIGlobals.PGEClosing:=PGEClosing;
  uLazGUIGlobals.intVerInterface:=verInterface;
  uLazGUIGlobals.intVerSaveGame:=verSaveGame;
  frmMain := TfrmMain.Create(nil);
  frmMain.ParentWindow := hwndHC;
  FileVersionInfo:= TFileVersionInfo.Create(nil);
  FileVersionInfo.ReadFileInfo;
  strFileVersion:=  FileVersionInfo.VersionStrings.Values['FileVersion']
  + ' - ' + FileVersionInfo.VersionStrings.Values['Comments'] //20230110
  + ' - ' + FileVersionInfo.VersionStrings.Values['FileDescription'];    // 20230404
  FileVersionInfo.Free;
  if Length(strFileVersion)= 0 then
   strFileVersion := '2.5.0.0';
  frmMain.Caption := 'Toolbox ' + strFileVersion;           //  20230404 put required GE into project optins
// assign pointer location for 'stuff'
  funcTmp := funcRefs;
  while (funcTmp <> nil) do
  begin
    if (funcTmp^.funcName = 'NewPtr') then
      frmMain.NewPtr := funcTmp^.funcPtr
    else if (funcTmp^.funcName = 'DispPtr') then
      frmMain.DisposPtr := funcTmp^.funcPtr
    else if (funcTmp^.funcName = 'del_HarpoonEvent_list') then
      frmMain.del_HarpoonEvent_list :=  PHCDLL_FUNC_REF(PHCDLL_FUNC_REF(funcRefs^.next).next).funcPtr
    else if (funcTmp^.funcName = 'QueueHarpoonEvent') then
      frmMain.HCQueueHarpoonEvent := THCQueueHarpoonEvent(funcTmp^.funcPtr)
    else if (funcTmp^.funcName = 'dllCheckLatLonDepth') then
      frmMain.HCdllCheckLatLonDepth := THCdllCheckLatLonDepth(funcTmp^.funcPtr)
    else if (funcTmp^.funcName = 'annex_id_to_disk_id') then
      frmMain.HCannex_id_to_disk_id := THCannex_id_to_disk_id(funcTmp^.funcPtr)
    else if (funcTmp^.funcName = 'disk_id_to_annex_id') then
      frmMain.HCdisk_id_to_annex_id := THCdisk_id_to_annex_id(funcTmp^.funcPtr)
    else if (funcTmp^.funcName = 'ChangeActGroupPtr') then
        frmMain.HCChangeActGroupPtr := THCChangeActGroupPtr(funcTmp^.funcPtr)
    else if (funcTmp^.funcName = 'ChangeActUnitPtr') then
        frmMain.HCChangeActUnitPtr := THCChangeActUnitPtr(funcTmp^.funcPtr)
      ;

    funcTmp := funcTmp^.next;
  end;
  gStrVerHC:= verHC;
  frmMain.Show;
  frmMain.PageControl1.ActivePageIndex:= 2;
  frmMain.intPageActive:= 2;
  frmMain.SetSpinEditTop.Value:= frmMain.Top;    // position test             - frmMain.SetSpinEditTop.Value
  frmMain.Top:= StrToInt(frmMain.IniPropStorage1.StoredValue['frmTop']);  //  20230105  position test
  frmMain.WindowState:= wsNormal;           //  20250329
  frmMain.BringToFront;                     // 20230105  not needed I think  but influences top reading
end;

procedure ProcessVCList(PThisVicCondn: PHCVictoryConditions);
var
  strVT, strUC, strOS, strDam, strDT: string;
begin
   frmMain.StatVCLstbx.Clear;
   frmMain.StatVCLstbx.Items.Add('Import at Session Start');
   strVT:= 'No VCs met';
    while PThisVicCondn <> nil do
    begin
    if (PThisVicCondn^.gameTimeAchieved <> 0) then
    begin
      case PThisVicCondn^.VicType of
        0:  strVT:= 'Minimum';
        1:  strVT:= 'Total';
        else  strVT:= '';
      end;
      if PThisVicCondn^.AndOrFlag = 1
          then strVT:= strVT + '(and)'
          else strVT:= strVT + '(or)';  // set victory type
      case PThisVicCondn^.unitType of
      0: strUC:= 'Carrier';
      1: strUC:= 'Ship';
      2: strUC:= 'Sub';
      3: strUC:= 'Plane';
      4: strUC:= 'Helo';
      5: strUC:= 'Base';
      6: strUC:= 'Fixed AD';
      7: strUC:= 'Mobile AD';
      8: strUC:= 'Armoured';
      9: strUC:= 'UnArmred';
      else strUC:= 'Unknown';
      end;

      case PThisVicCondn^.itemType of
      0:  strDT:= '' ;
      1:  strDT:= Format('BroadType %s',[AnnexData^.PBSStrings^.BroadVicType[PThisVicCondn^.DetailType]]);
      2:  if  PThisVicCondn^.unitType = (3 or 4)
          then  strDT:= Format('DetailType %s',[AnnexData^.PBSStrings^.ACType[PThisVicCondn^.DetailType]])
          else  strDT:= Format('DetailType %s',[AnnexData^.PBSStrings^.ShipType[PThisVicCondn^.DetailType]]);
      else strDT := '';
      end;

      if PThisVicCondn^.TimeOnStation = 0
      then strOS:= 'Destroyed'
      else strOS:= format('OnStation for %d Mins',[(PThisVicCondn^.TimeOnStation) div 60]);
      if  PThisVicCondn^.numDamaged = 0
          then strDam:= ''
          else strDam:= Format('%d units %d %s damaged',
          [PThisVicCondn^.numDamaged, PThisVicCondn^.percentDamage, '%']);

      frmMain.StatVCLstbx.Items.Insert
      (0, Format('GT achieved: %8.8d, vc#%.1d %s; %s; Pertains to: %s; %s; Require: %d %s, %s',
      [PThisVicCondn^.gameTimeAchieved, PThisVicCondn^.id, frmMain.Side2String(PThisVicCondn^.WhichSide),
      strVT, strUC, strDT, PThisVicCondn^.numKilled, strOS, strDam]));
     end;        // end a met condition listing
      PThisVicCondn:= PThisVicCondn^.next;
    end;         // end all VCs
    if strVT = 'No VCs met' then frmMain.StatVCLstbx.Items.Insert(0,'No VCs are yet met');
    frmMain.StatVCLstbx.Items.Insert(0, 'Session Play Starts');
end;


procedure StartGroup(StartGroup: PHCGroup);export;cdecl;
begin
     frmMain.PStartGroup:=StartGroup;
     ProcessVCList(frmMain.PVCList);
end;

procedure ScenLoad(strHarpPath: PAnsiChar; intScenNum: SmallInt; strScenFPath: PAnsiChar; intBSNum: ShortInt;
  strBSFName: PAnsiChar; intSide: byte; intGameTimeIn: Long; intGameTimeLeftIn: Long;
   AnnexDataIn: PHCAnnexes_disk; DatabaseVersionDBIn: PHCDATABASE_VERSION;
    ScenDataIn: PHCSCENARIO_DATA; ScenSaveDataIn: PHCSCENARIO_SAVE_DATA;
   GlobalsIn: PHCGlobals);export;cdecl;      //dt_scen_start_in: PHCDateTimeRec;    deleted dllintver21

var
  strScenNum, strBatSetName: string;
  TimeNowTimeRec: THCDateTimeRec;

begin
  frmMain.strMySide:=format('%d',[intSide]);
  frmMain.MySide:= intSide;
  case intSide of
  0: frmMain.EnmySide:= uchar(1);
  1: frmMain.EnmySide:= 0;
  end;
  frmMain.MLtmemLog.Lines.Clear;
  AnnexData:= AnnexDataIn;
//  frmMain.PAnnexData:= AnnexDataIn;       not used
//  frmMain.dt_scen_start:= dt_scen_start_in;    no longer valid and not in use
  HCAnnexHelper := THCAnnexHelper.Create(AnnexDataIn, frmMain.HCannex_id_to_disk_id,
    uLazGUIGlobals.intVerInterface, uLazGUIGlobals.intVerSaveGame);
  DatabaseVersionDB := DatabaseVersionDBIn; // ALE 20170923 current database
  ScenData := ScenDataIn; // ALE 20170923 unique identifiers, lineage, etc.
  ScenSaveData := ScenSaveDataIn; // ALE 20170923 save UUIDs and Scenario Orders
  // write up scen data in session page
  if intScenNum <> -1
    then
      begin
        strScenFPath:= 'BattleSet Scenario ';
//        intScenNum:= intScenNum + 1;                 //  caused problems with getting storeconsumed tally
        strScenNum:= Format('#%d',[intScenNum +1]);          //  20230416 output tidy up
      end
    else strScenNum:= '';
    if intBSNum = 35 then strBatSetName:= 'Custom'
                             else strBatSetName:= strBSFName;

    frmMain.StatSessLstBx.Items.Clear;         //20230416  reset screen each scenload
    frmMain.StatSessLstBx.Items.Add('HC version: ' + gStrVerHC);
    frmMain.StatSessLstBx.Items.Add(Format('FileLoaded: %s, %s',[strScenFPath, strScenNum]));
    frmMain.StatSessLstBx.Items.Add('ScenarioDescription: %s',[ScenSaveDataIn^.OrdersShortDesc]);
    frmMain.StatSessLstBx.Items.Add(Format('BattleSet=%d, BattleSet=%s, PlayerSide=%s',
    [intBSNum, strBatSetName, AnnexData^.PBSStrings^.SideName[intSide]]));
    frmMain.StatSessLstBx.Items.Add(Format('SE Version= %s',[ScenDataIn^.Lineage.Top.SEVersion]));
    frmMain.StatSessLstBx.Items.Add(Format('Loaded Database %s',[DatabaseVersionDBIn.RESFile.flavor]));
    frmMain.StatSessLstBx.Items.Add(Format('Original Database %s',[ScenDataIn^.Lineage.Top.DatabaseVersion.RESFile.flavor]));
    frmMain.StatSessLstBx.Items.Add(Format('Last saved game Database %s',[ScenDataIn^.DatabaseVersion.RESFile.flavor]));
    frmMain.StatSessLstBx.Items.Add(Format('Scenario Start %4.4d-%2.2d-%2.2d, %2.2d:%2.2d:%2.2d',
    [ScenDataIn^.dt_scen_start.year, ScenDataIn^.dt_scen_start.month,
        ScenDataIn^.dt_scen_start.day, ScenDataIn^.dt_scen_start.hour,
        ScenDataIn^.dt_scen_start.minute, ScenDataIn^.dt_scen_start.second]));
    TimeNowTimeRec:= HCDateTimeInc(ScenDataIn^.dt_scen_start,intGameTimeIn);

    frmMain.StatSessLstBx.Items.Add('This Session Start %4.4d-%2.2d-%2.2d, %2.2d:%2.2d:%2.2d',
    [TimeNowTimeRec.year, TimeNowTimeRec.month, TimeNowTimeRec.day, TimeNowTimeRec.hour,
    TimeNowTimeRec.minute, TimeNowTimeRec.second]);

    //  stuff for reading storeconsumed   250320   //  maybe need to move so as to delay processing to let aardata in first?
                                                   //  could run in scenloaded
    strFileID:= strBSFName + IntToStr(intScenNum + 1);    //  for custom could use truncated strScenFPath
    iniFileID:= '\AARdata-' + strFileID + '.txt' ;
    If FileExists(Application.Location + iniFileID)
       then
         begin
       RepFile:= Tinifile.Create(Application.Location + iniFileID);  //  create for reading StorConsumed
       frmMain.MunGenTmen.Clear;                       // might need to move to enusre file exists at startup
       frmMain.MunACTmen.Clear;
       if intSide = 0
          then
            begin
            RepFile.ReadSectionValues('StoresConsumed - Blue', frmMain.MunGenTmen.Lines);
            RepFile.ReadSectionValues('AirCraft-StoresConsumed - Blue', frmMain.MunACTmen.Lines);
            end
           else
            begin
             RepFile.ReadSectionValues('StoresConsumed - Red', frmMain.MunGenTmen.Lines);
             RepFile.ReadSectionValues('AirCraft-StoresConsumed - Red', frmMain.MunACTmen.Lines);
            end;
       bAARDataRunning:= True;
         end
         else
         begin
          frmMain.MunGenTmen.Lines.Add('No AARData file');
          bAARDataRunning:= False;
         end;

end;

procedure MsgLog(MsgLine: PAnsiChar);export;cdecl;
begin
if Pos('ITER', MsgLine) = 0 then  //  250109  filter out iterative save note
begin
  while (frmMain.MLtmemLog.Lines.Count > frmMain.SETspnMLC.Value)  do
  begin
       frmMain.MLtmemLog.Lines.Delete(frmMain.SETspnMLC.Value); //  250114 change line count to be deleted
  end;
         frmMain.MLtmemLog.Lines.Insert(0,'');  //  Format('%s', [MsgLine]
         frmMain.MLtmemLog.Lines.Strings[0]:= MsgLine;
end;
if frmMain.AtkBtnAtkWarn.Checked = True
  then if Pos('Enemy', MsgLine) > 0 then
  begin
   frmMain.PostMessage('Sir, we have enemy fire');    //  250114 draft warn of enemy fire
//   frmMain.AGFBtnPause.Click;
   Byte(PDLLBusy^) := CTRUE;
  frmMain.AGFBtnPause.Caption:= 'Resume';
  frmMain.AtkBtnPause.Caption:= 'Resume';
  frmMain.RflBtnPause.Caption:= 'Resume';
//  250310 pause if enemy fire
  end;
  //  25015 reorded
end;

procedure GameTime(GameTime: Long; GameTimeLeft: Long);export;cdecl;

begin
  frmMain.intGameTime := GameTime;
  frmMain.intGameTimeLeft:= GameTimeLeft;
  frmMain.RflLblGameTime.Caption:= Format('%9.9d',[GameTime]);
end;

procedure HarpoonEventHead(HarpEventHead: PHCHarpoonEvent);export;cdecl;

var PThisRefuelEvent: PHCAirRefuelEvent;

begin
  If HarpEventHead <> nil then
     begin
      frmMain.PHCEventHead:= HarpEventHead;     // update for use in eg spliting groups
     if (HarpEventHead^.event_type = AIR_REFUEL_EVENT)      // ddt 20150720   have a refuel event    231003 [ and CommandMask)]
         and (PHCGroup(HarpEventHead^.ourGroup)^.side = frmMain.MySide)
     then
     begin
     PThisRefuelEvent:= HarpEventHead^.DataPtr;
      if ((frmMain.RflChkBPause.Checked = True) and (PThisRefuelEvent^.planestofuel[0] <> 205))
         or ((frmMain.RflChkBAutoPFinish.Checked = True) and  (PThisRefuelEvent^.planestofuel[0] = 255))
      then              //  so we list it if auto pause on and event due
      begin
      frmMain.RflLbxGroups.Clear;
      frmMain.RflLbxGroups.Items.Add(Format('%3.3s %d', [PHCGroup(HarpEventHead^.ourGroup)^.id,
                                                                            HarpEventHead^.Time]));
       //frmMain.RflChkBResume.Checked:= False;   }  DDT 210601 now use generic pause button
           //Byte(PDLLBusy^) := CTRUE;                }
       frmMain.RflChkBFind.Checked:= False;                //  240621 moved to before activate page
       frmMain.RflChkBTnkGrpSrch.Checked:= False;
       frmMain.intPageActive:= frmMain.PageControl1.ActivePageIndex;
       frmMain.WindowState:= wsNormal;
       frmMain.PageControl1.ActivePageIndex:=3;
       frmMain.RflLbxUnitFill(HarpEventHead^.ourGroup);
       frmMain.RflLbxDetailFill(HarpEventHead);
           if frmMain.RflBtnPause.Caption = 'Pause' then      // if not paused then click to pause (but should be)
             frmMain.RflBtnPause.Click;
           showmessage('Attention, refuel autopause!');         //  231007
       end;   // end an autoP box was ticked
      //  240621
     end;    //  end there was an our side refuel
     If  (HarpEventHead^.event_type = ATTACK_EVENT)          // start        230103 old change of data form
         then if (PHCGroup(HarpEventHead^.ourGroup)^.side = frmMain.MySide)    //20230607 switch green to enemy if attacked
            then if (HarpEventHead^.DataPtr <> nil)
              then if format('%s',[PHCAttackEvent(HarpEventHead^.DataPtr)^.TargetGroup[1]])= '0'    // simple test
               then
               begin
               strTemp:= format('Sir, from Fleet Command: your group %s has attacked a neutral and is stood down awaiting war crimes trial',
               [PHCGroup(HarpEventHead^.ourGroup)^.id]);
               frmMain.PostMessage(strTemp);
               pGrpTemp:= HCGroupID2GroupPtr(format('%s%s',
                 [PHCAttackEvent(HarpEventHead^.DataPtr)^.TargetGroup[1],
                 PHCAttackEvent(HarpEventHead^.DataPtr)^.TargetGroup[2]]), frmMain.PStartGroup);  //  202330622 moved function to hcutils
               if pGrpTemp <> nil then pGrpTemp^.side:= frmMain.EnmySide;     // attacked neutral group turns enemy
             if (PHCGroup(HarpEventHead^.ourGroup)^.gtype = MT_HELO)
               or  (PHCGroup(HarpEventHead^.ourGroup)^.gtype = MT_AC)
                 then PHCGroup(HarpEventHead^.ourGroup)^.side:= NEUTRALSIDE;
               end;
    end;
end;

procedure VictoryConditionsList(PVCList: PHCVictoryConditions);export;cdecl;

begin
  frmMain.PVCList:= PVCList;
end;

procedure VictoryConditionLevels(whichSide: uchar; enemySide: uchar; vicLevel: uchar);export; cdecl;
//  fired in game when a victory level (eg min, total) is met
begin
  frmMain.StatVCLstbx.Items.Insert(0, Format('GT achieved %8.8d: %s Victory Level %s',
    [frmMain.intGameTime, frmMain.Side2String(whichside), HCVictoryConditionLevel(vicLevel)]));  //  20230417
  end;                      //  AnnexData^.PBSStrings^.SideName[whichside]

procedure VictoryConditionAchieved(VictoryCondition: PHCVictoryConditions); export; cdecl;
//  fired in game when a victory condition is met, note for 'and' types it's when all are met
var
     strVT, strUC, strOS, strDam, strDT: string;
 begin
      case VictoryCondition^.VicType of
      0:  strVT:= 'Minimum';
      1:  strVT:= 'Total';
      else strVT:= '';
      end;
    if VictoryCondition^.AndOrFlag = 1
        then strVT:= strVT + '(and)'
        else strVT:= strVT + '(or)';  // set victory type
    case VictoryCondition^.unitType of
    0: strUC:= 'Carrier';
    1: strUC:= 'Ship';
    2: strUC:= 'Sub';
    3: strUC:= 'Plane';
    4: strUC:= 'Helo';
    5: strUC:= 'Base';
    6: strUC:= 'Fixed AD';
    7: strUC:= 'Mobile AD';
    8: strUC:= 'Armoured';
    9: strUC:= 'UnArmred';
    else strUC:= 'Unknown';
    end;

    case VictoryCondition^.itemType of
    0:  strDT:= '' ;
    1:  strDT:= Format('BroadType %s',[AnnexData^.PBSStrings^.BroadVicType[VictoryCondition^.DetailType]]);
    2:  if  VictoryCondition^.unitType = (3 or 4)
        then  strDT:= Format('DetailType %s',[AnnexData^.PBSStrings^.ACType[VictoryCondition^.DetailType]])
        else  strDT:= Format('DetailType %s',[AnnexData^.PBSStrings^.ShipType[VictoryCondition^.DetailType]]);
    else strDT := '';
    end;
    if VictoryCondition^.TimeOnStation = 0
    then strOS:= 'Destroyed'
    else strOS:= format('OnStation for %d Mins',[(VictoryCondition^.TimeOnStation) div 60]);
    if  VictoryCondition^.numDamaged = 0
        then strDam:= ''
        else strDam:= Format('%d units %d %s damaged',
        [VictoryCondition^.numDamaged, VictoryCondition^.percentDamage, '%']);

    frmMain.StatVCLstbx.Items.Insert
    (0, Format('GT achieved: %8.8d, vc#%.1d %s; %s; Pertains to: %s; %s; Require: %d %s, %s',
    [VictoryCondition^.gameTimeAchieved, VictoryCondition^.id,
     AnnexData^.PBSStrings^.SideName[VictoryCondition^.WhichSide],
     strVT, strUC, strDT, VictoryCondition^.numKilled, strOS, strDam]));  //  20230420 added ID
 end;

procedure ActGroupPtr(ActGroup: PHCGroup); export; cdecl;   //  240624
begin
  frmMain.gPActGroup:= ActGroup;
   if ActGroup <> nil then                //  if there is an active group and it is myside reset Surf/sub
   if ActGroup^.side = frmMain.MySide
    then
    case  frmMain.PageControl1.ActivePageIndex of
    4:    frmMain.SVSearchGroup();
    0:    frmMain.AGFgrpSrch();
    1:    frmMain.AtkGrpSrch();
    3:    frmMain.RefuelSheetUpdate();
    end
   else   // ActGroup is not friendly
   begin
   frmMain.PselectedEGroup:= ActGroup;
   if frmMain.PageControl1.ActivePageIndex = 1
     then frmMain.AtkEGroupSrch();
   end;
end;

procedure ActUnitPtr(ActUnit: PHCUnit); export; cdecl;      //  240624
  begin
    frmMain.gPActUnit:= ActUnit;
    if ActUnit <> nil then
    begin
    if PHCGroup(ActUnit^.Group)^.side = frmMain.MySide
      then
        case frmMain.PageControl1.ActivePageIndex of            //  240625
        4:   begin
             frmMain.gPActGroup := ActUnit^.Group;        //  get actunit listed and selected
             frmMain.SVSearchGroup();
             end;
        0:   frmMain.AGFgrpSrch();
        1:   frmMain.AtkGrpSrch();
        end
    else
    if (PHCGroup(ActUnit^.Group)^.side = frmMain.EnmySide) or  (PHCGroup(ActUnit^.Group)^.side = NEUTRALSIDE)
       then
       begin
        if frmMain.PageControl1.ActivePageIndex = 1
        then
        frmMain.AtkEGroupSrch();        //  240626  if there is a ActUnit = EUnit then should result in the group and unit selected
        frmMain.PselectedEGroup:= ActUnit^.Group;
        frmMain.PSelectedEUnit:= ActUnit;  //  240808 - if showing side not known then selctions weren't made by search
       end;
    end;    //  end actunit <> nil
  end;

procedure AllDeadUnitsPtr(AllDeadUnitsPtr: PHCDeadListItem);export;cdecl;
begin
    frmMain.PAllDeadUnit:= AllDeadUnitsPtr;
    frmMain.AtkEGroupSrch();       //  240808  reset atk e group and unit if any unit destroyed
end;

procedure UnitTop(topUnit: PHCUnit);export;cdecl;
begin
   frmMain.gPHCtopUnit:= topUnit;
end;

procedure TimeFactor(TimeFactor: longint); export; cdecl;
  begin
    if TimeFactor = 0 then
    begin
     frmMain.AtkEGroupSrch();
     frmMain.AtkGrpSrch();   // reset atk  groups when changing time compression to zero
    end;
  end;

procedure StoreConsumed(pLaunchUnit: PHCUNIT; pLaunchMount: PHCMntRec; ourMount: ushort;
  mountIndex: uchar; pQty: ushort; pWeapUnit: PHCUNIT; pTargetUnit: PHCUNIT; pTargetGroup: PHCGROUP); export; cdecl;
var
  lLaunchUnit, lWeaponUnit, lTargetUnit,lLaunchUnitClassName, lWeaponCLassName, lStrSide: String;
  lIntSide: Integer;
  PHCAnnexC1: PHCAnnexC1_disk;      // guns
  PHCAnnexD1: PHCAnnexD1_disk;      // missiles
  PHCAnnexE1: PHCAnnexE1_disk;      // asw dc mortar etc
  PHCAnnexF1: PHCAnnexF1_disk;      // torpedos
  PHCAnnexG1: PHCAnnexG1_disk;      //  ATOG
  lHCDTNow: THCDateTimeRec;

begin
    if (pLaunchUnit <> nil) then
      lLaunchUnit := Format('%2.2s%3.3d - %s', [pLaunchUnit^.Group^.id, pLaunchUnit^.id, pLaunchUnit^.name]);

//  ****

    case (HCAnnexHelper.HCAnnexShift(pLaunchMount^.WepId)) of
      MISSILE_FLAG:
      begin
        PHCAnnexD1:= HCAnnexHelper.HCGetAnnexD1(pLaunchMount^.WepId);
        lWeaponClassName:= PHCAnnexD1^.ClassName;
      end;
      TORP_FLAG:
      begin
        PHCAnnexF1:= HCAnnexHelper.HCGetAnnexF1(pLaunchMount^.WepId);
        lWeaponClassName:= PHCAnnexF1^.ClassName;
      end;
      ASW_FLAG:
      begin
        PHCAnnexE1:= HCAnnexHelper.HCGetAnnexE1(pLaunchMount^.WepId);
        lWeaponClassName:= PHCAnnexE1^.ClassName;
      end;
       GUN_FLAG:
      begin
        PHCAnnexC1:= HCAnnexHelper.HCGetAnnexC1(pLaunchMount^.WepId);
        lWeaponClassName:= PHCAnnexC1^.ClassName;
      end;
       ATOG_FLAG:
       begin
         PHCAnnexG1:= HCAnnexHelper.HCGetAnnexG1(pLaunchMount^.WepId);
        lWeaponClassName:= PHCAnnexG1^.ClassName;
       end;
        MULTI_FLAG:
        case (HCAnnexHelper.HCAnnexShift(ourMount)) of
      MISSILE_FLAG:
      begin
        PHCAnnexD1:= HCAnnexHelper.HCGetAnnexD1(ourMount);
        lWeaponClassName:= PHCAnnexD1^.ClassName;
      end;
      TORP_FLAG:
      begin
        PHCAnnexF1:= HCAnnexHelper.HCGetAnnexF1(ourMount);
        lWeaponClassName:= PHCAnnexF1^.ClassName;
      end;
      ASW_FLAG:
      begin
        PHCAnnexE1:= HCAnnexHelper.HCGetAnnexE1(ourMount);
        lWeaponClassName:= PHCAnnexE1^.ClassName;
      end;
       GUN_FLAG:
      begin
        PHCAnnexC1:= HCAnnexHelper.HCGetAnnexC1(ourMount);
        lWeaponClassName:= PHCAnnexC1^.ClassName;
      end;
       ATOG_FLAG:
       begin
         PHCAnnexG1:= HCAnnexHelper.HCGetAnnexG1(ourMount);
        lWeaponClassName:= PHCAnnexG1^.ClassName;
       end;
    end      //  end multimount
      else
       lWeaponClassName:= 'NotAudited';
    end;   //  there was a mount
//  ******

//  250329  need to filter by our side
    if bAARDataRunning = True
      then
        begin
        RepFile:= Tinifile.Create(Application.Location + iniFileID);
        if frmMain.MySide = 0
          then
          begin
          RepFile.ReadSectionValues('StoresConsumed - Blue', frmMain.MunGenTmen.Lines);
          if HCMTIsAir(pLaunchUnit^.utype)
            then
              RepFile.ReadSectionValues('AirCraft-StoresConsumed - Blue', frmMain.MunACTmen.Lines);
          end
          else     //  my side is red
          begin
            RepFile.ReadSectionValues('StoresConsumed - Red', frmMain.MunGenTmen.Lines);
            if HCMTIsAir(pLaunchUnit^.utype)
              then
              RepFile.ReadSectionValues('AirCraft-StoresConsumed - Red', frmMain.MunACTmen.Lines);
          end;
        end;     //  end aardata is running
    //  250303
end;

exports
  DLLVer,
  DLLVerInt,
  DLLDesc,
  DLLFree,
  DLLInit,
  ScenLoad,
  MsgLog,
  HarpoonEventHead,
  GameTime,
  VictoryConditionsList,
  VictoryConditionLevels,
  VictoryConditionAchieved,
  AllDeadUnitsPtr,
  ActGroupPtr,
  ActUnitPtr,
  UnitTop,
  TimeFactor,
  StartGroup, // ALE 20130205 Sends updated GroupPtr whenever that changes
  StoreConsumed;
end.

