library lazGUI_extn; {$mode delphi}{$H+} {$R *.res} uses Classes { you can add units after this } , Mainform, uHCDefines , uHCGCI, uHCGlobals, uHCTypeDefs, uHCEventHelpers, uHCDateTime , uHCAnnexDefs, uHCAnnexHelpers, uLazGUIGlobals, uHCUtils , Windows, Forms, ShellAPI, SysUtils ,Types ,Dialogs, Interfaces, Controls, FileInfo , IniFiles; const DLLVERN = 10; DLLVERINTN = 43; var frmMain: TfrmMain; intGameTime, intGameTimeLeft: Long; // dt_scen_start: PHCDateTimeRec; no longer used new scen load structure FileVersionInfo: TFileVersionInfo; strFileVers, strGEVers, strFileID, iniFileID: String; PCurrentStartGroup: PHCGroup; gHCDTStart: THCDateTimeRec; 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 my 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 := 'lazarus GUI test DLL by Tony Eischens extensions by Don Thomas'; end; {*** Free DLL ***} procedure DLLFree();export;cdecl; begin // Do any cleanup here, this is the end // frmMain.GTmemDLLcalls.Lines.Add('DLLFree'); frmMain.WindowState:= wsMinimized; // 240906 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; harpoon_uuid_session: PAnsiChar; hclicense_dt_expire: Int64; hclicense_licensee: PAnsiChar; usblicense_desc: PAnsiChar; RESRSRStructureVersion: ulong; AnnexVersion: ushort; GameComponent: uchar; pLosTable: PHCLosTable );export;cdecl; var funcTmp: PHCDLL_FUNC_REF; begin // here we initialize globals and such for the life of the DLL // Application.Scaled:= False; // ddt 2022/09/25 trying to fix scaling issue Application.Initialize; // ALE 20120410 Freezes HC Application.Run; uLazGUIGlobals.PGEClosing:=PGEClosing; uLazGUIGlobals.PDLLBusy:=PDLLBusy; uLazGUIGlobals.hwndHC:=hwndHC; // 20230405 version update uLazGUIGlobals.intVerInterface:=verInterface; uLazGUIGlobals.intVerSaveGame:=verSaveGame; FileVersionInfo:= TFileVersionInfo.Create(nil); FileVersionInfo.ReadFileInfo; frmMain := TfrmMain.Create(nil); frmMain.ParentWindow := hwndHC; // 230407 reside in harpwindow // ShowWindow(hwndHC, SW_MAXIMIZE); // test max HC 20230414 not good result strFileVers:= FileVersionInfo.VersionStrings.Values['FileVersion']; FileVersionInfo.Free; if Length(strFileVers) = 0 then strFileVers := '1.4.3'; frmMain.Caption := 'AI Window v ' + strFileVers //IntToStr(DLLVERN) + ', ExportDLL Interface v ' + IntToStr(DLLVERINTN) + 'for GE v 2023.003+'; frmMain.memDLLInit.Lines.Add('lazarus GUI Export DLL v' + IntToStr(DLLVERN)); frmMain.memDLLInit.Lines.Add('ExportDLL Interface v' + IntToStr(DLLVERINTN)); frmMain.memDLLInit.Lines.Add('hwndHC = 0x' + IntToHex(hwndHC, 8)); frmMain.memDLLInit.Lines.Add('pathHC = ' + pathHC); frmMain.memDLLInit.Lines.Add('verHC = ' + verHC); frmMain.memDLLInit.Lines.Add('verSaveGame = 0x' + IntToHex(verSaveGame, 8)); frmMain.memDLLInit.Lines.Add(Format('funcRefs = 0x%p', [funcRefs])); frmMain.memDLLInit.Lines.Add(Format('GE ExportDLL Interface Version = %d', [verInterface])); frmMain.memDLLInit.Lines.add('harpoon_uuid_session = ' + harpoon_uuid_session); // 20230405 vers upgrade // ALE 20130908 List the function pointers sent over by the GE // then capture one of them for example usage funcTmp := funcRefs; while (funcTmp <> nil) do begin frmMain.memDLLInit.Lines.Add(#9 + Format('funcRef: 0x%p %s', [funcTmp^.funcPtr, funcTmp^.funcName])); if (funcTmp^.funcName = 'NewPtr') then frmMain.NewPtr := funcTmp^.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 = 'free_Unit') then frmMain.HCfree_Unit := THCfree_Unit(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'free_Group') then frmMain.HCfree_Group := THCfree_Group(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'ChangeActGroupPtr') then frmMain.HCChangeActGroupPtr := THCChangeActGroupPtr(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'ChangeActUnitPtr') then frmMain.HCChangeActUnitPtr := THCChangeActUnitPtr(funcTmp^.funcPtr) // 250303 ; funcTmp := funcTmp^.next; end; frmMain.PageControl1.ActivePage:= frmMain.tshScenLoad; // 20230414 tshStartGroup frmMain.Show; frmMain.WindowState:= wsNormal; strGEVers:= verHC; end; procedure UnitShowing(UnitID: Byte; GroupID: PAnsiChar; Showing: Byte);export;cdecl; begin //if (frmMain.USckbEnabled.Checked = True) then //begin // frmMain.USmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Showing=%d', [intGameTime, GroupID, UnitID, Showing])); // if (frmMain.USmemMsgLog.Lines.Count > frmMain.USedtLines.Value) then // begin // frmMain.USmemMsgLog.Lines.Delete(frmMain.USedtLines.Value); // end; //end; end; // procedure UnitNew(UnitID: Byte; GroupID: PAnsiChar; utype: shortint; side: byte; annexID: word; name: PAnsiChar);export;cdecl; var strUSide: string; begin if (frmMain.UNckbEnabled.Checked = True) then begin case side of 0: strUSide:= 'Blue'; 1: strUSide:= 'Red'; 2: strUside:= 'Green'; end; frmMain.UNmemMsgLog.Lines.Insert(0, Format('GT: %8.8d: %s:%2.2d, %s %s %s, AnnexID=%d', [intGameTime, GroupID, UnitID, strUSide, frmMain.HCMT2String(utype), name, annexID])); if (frmMain.UNmemMsgLog.Lines.Count > frmMain.UNedtLines.Value) then // begin frmMain.UNmemMsgLog.Lines.Delete(frmMain.UNedtLines.Value); end; // Byte(PDLLBusy^) := CTRUE; frmMain.PageControl1.ActivePage:= frmMain.tshUN; frmMain.WindowState:= wsNormal; // frmMain.UNbtnResume.Enabled:= False; // frmMain.UNbtnResume.Enabled:= True; end; end; procedure ScenLoad(strHarpPath: PAnsiChar; intScenNum: SmallInt; strScenFPath: PAnsiChar; intBSNum: ShortInt; strBSFName: PAnsiChar; intSide: byte; intGameTimeIn: Long; intGameTimeLeftIn: Long; // 20230405 dt_scen_start_in: PHCDateTimeRec; AnnexDataIn: PHCAnnexes_disk; DatabaseVersionDBIn: PHCDATABASE_VERSION; ScenDataIn: PHCSCENARIO_DATA; ScenSaveDataIn: PHCSCENARIO_SAVE_DATA; GlobalsIn: PHCGlobals);export;cdecl; var intIdx: NativeUInt; pLoadout: PHCAnnexY1_disk; pShip: PHCAnnexA1_disk; pSub: PHCAnnexA2_disk; pAir: PHCAnnexB1_disk; pBase: PHCAnnexP1_disk; pGun: PHCAnnexC1_disk; pMissile: PHCAnnexD1_disk; pBomb: PHCAnnexG1_disk; pECM: PHCAnnexG2_disk; pNuke: PHCAnnexI1_disk; pRadar: PHCAnnexJ1_disk; pSonar: PHCAnnexM1_disk; pMount: PHCAnnexZ1_disk; pMulti: PHCAnnexZ2_disk; strScenNum, strBatSetName: string; TimeNowTimeRec: THCDateTimeRec; begin intGameTime := intGameTimeIn; // ALE 20150712 Now that we receive the game time here, store it intGameTimeLeft := intGameTimeLeftIn; // ALE 20150712 Now that we receive the game time left here, store it // dt_scen_start := ScenData^.dt_scen_start;// 20230405 vers update /dt_scen_start_in; // ALE 20150712 Scenario Starting date and time AnnexData := AnnexDataIn; // ALE 20150813 Database/Platform information HCAnnexHelper := THCAnnexHelper.Create(AnnexDataIn, frmMain.HCannex_id_to_disk_id, uLazGUIGlobals.intVerInterface, uLazGUIGlobals.intVerSaveGame); // frmMain.GTmemDLLcalls.Lines.Add('scenarioload'); gHCDTStart:= ScenDataIn.dt_scen_start; // 250303 // if (frmMain.SLckbEnabled.Checked = True) then // removed 20230408 frmMain.intPSide:= intSide; if intSide = 0 then frmMain.intESide := 1 else frmMain.intESide := 0; if intScenNum <> -1 then begin strScenFPath:= 'BattleSet Scenario '; // intScenNum:= intScenNum + 1; 250405 played havoc with streconsumed strScenNum:= Format('#%d',[intScenNum + 1]); // 20230416 output tidy up end else strScenNum:= ''; if intBSNum = 35 then strBatSetName:= 'Custom' else strBatSetName:= strBSFName; frmMain.SLmemMsgLog.Lines.Clear; //20230416 reset screen each scenload frmMain.SLmemMsgLog.Lines.Add(Format('ScenLoad: %s, %s',[strScenFPath, strScenNum])); frmMain.SLmemMsgLog.Lines.Add('ShortOrders: %s',[ScenSaveDataIn^.OrdersShortDesc]); frmMain.SLmemMsgLog.Lines.Add(Format('BattleSet=%d, BattleSet=%s, PlayerSide=%s', [intBSNum, strBatSetName, AnnexData^.PBSStrings^.SideName[intSide]])); // 20230417 frmMain.Side2String(intSide) frmMain.SLmemMsgLog.Lines.Add(Format('Loaded Database %s',[DatabaseVersionDBIn.RESFile.flavor])); frmMain.SLmemMsgLog.Lines.Add(Format('Original Database %s',[ScenDataIn^.Lineage.Top.DatabaseVersion.RESFile.flavor])); frmMain.SLmemMsgLog.Lines.Add(Format('Last saved Database %s',[ScenDataIn^.DatabaseVersion.RESFile.flavor])); frmMain.SLmemMsgLog.Lines.Add(Format('SE Version=%s',[ScenDataIn^.Lineage.Top.SEVersion])); frmMain.SLmemMsgLog.Lines.Add(Format('GE version=%s, HC Path=%s, ',[strGEVers, strHarpPath])); frmMain.SLmemMsgLog.Lines.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.SLmemMsgLog.Lines.Add('This Game 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]); frmMain.SLmemMsgLog.Lines.Add('RawTimeIn: ' + IntToStr(intGameTimeIn)); // 250310 if (ScenSaveDataIn^.uuid_prev = frmMain.SLTLblThisUUID.Caption) or (ScenSaveDataIn^.uuid = frmMain.SLTLblThisUUID.Caption) then ShowMessage('AIWindow has detected: follow on from session save') else begin frmMain.StoreExpLst.Clear; if (ScenSaveDataIn^.uuid_prev = '') then ShowMessage('AIWindow has detected: New Scenario') else ShowMessage('AIWindow has detected: out of sequence saved game'); end; frmMain.SLTLblThisUUID.Caption:= (ScenSaveDataIn^.uuid); frmMain.SLTLblLastUUID.Caption:= (ScenSaveDataIn^.uuid_prev); //250311 frmMain.SLmemMsgLog.Lines.Add('Scenario Edit # %d',[ScenDataIn^.Lineage.Count]); // 250206 frmMain.SLmemMsgLog.Lines.Add('frmTop: ' + IntToStr(frmMain.Top)); frmMain.SLmemMsgLog.Lines.Add('frmWidth: ' + IntToStr(frmmain.Width)); frmMain.SLmemMsgLog.Lines.Add('frmLeft: ' + IntToStr(frmMain.Left)); // ^^^ 240618 // stuff for reading storeconsumed 250320 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.StoreExpAccumLst.Clear; // might need to move to enusre file exists at startup RepFile.ReadSectionValues('StoresConsumed - Blue', frmMain.StoreExpAccumLst.Lines); RepFile.ReadSectionValues('StoresConsumed - Red', frmMain.StoreExpRedLst.Lines); RepFile.ReadSectionValues('AirCraft-StoresConsumed - Blue', frmMain.StrExpAirBlTally.Lines); RepFile.ReadSectionValues('AirCraft-StoresConsumed - Red', frmMain.StrExpAirRdTally.Lines); bAARDataRunning:= True; end else begin frmMain.StoreExpAccumLst.Lines.Add('No AARData file'); bAARDataRunning:= False; end; end; procedure SaveGame(FileNameIn: PAnsiChar; ScenSaveDataIn: PHCSCENARIO_SAVE_DATA; AutoSave: CBOOL); export; cdecl; begin frmMain.SLTLblThisUUID.Caption:= ScenSaveDataIn.uuid; frmMain.SLTLblLastUUID.Caption:= ScenSaveDataIn.uuid_prev; end; procedure TimeFactor(TimeFactor: longint);export;cdecl; begin // frmMain.GTmemDLLcalls.Lines.Add('timefactor'); if (frmMain.TFckbEnabled.Checked = True) then begin frmMain.TFmemMsgLog.Lines.Insert(0, Format('%8.8d: TimeFactor=%d', [intGameTime, TimeFactor])); if (frmMain.TFmemMsgLog.Lines.Count > frmMain.TFedtLines.Value) then begin frmMain.TFmemMsgLog.Lines.Delete(frmMain.TFedtLines.Value); end; end; end; procedure MsgLog(MsgLine: PAnsiChar);export;cdecl; begin if (frmMain.MLckbEnabled.Checked = True) then begin frmMain.MLmemMsgLog.Lines.Insert(0, Format('%8.8d: %s', [intGameTime, MsgLine])); if (frmMain.MLmemMsgLog.Lines.Count > frmMain.MLedtLines.Value) then begin frmMain.MLmemMsgLog.Lines.Delete(frmMain.MLedtLines.Value); end; end; end; procedure GameTime(GameTime: Long; GameTimeLeft: Long);export;cdecl; var PEvent: PHCHarpoonEvent; EventType: uchar; strGroupID: String; // dtNow: THCDateTimeRec; 20230426 no longer used begin intGameTime := GameTime; frmMain.intGTNow:= GameTime; intGameTimeLeft := GameTimeLeft; // ALE 20150712 store remaining time frmMain.GTlblGameTime.Caption := 'GameTime: ' + Format('%8.8d', [intGameTime]); frmMain.GTlblGameTimeLeft.Caption := 'GameTimeLeft: ' + Format('%8.8d', [intGameTimeLeft]); // ALE 20130812 If the user wants to look at data structures // then make sure the GE doesn't keep processing until the // user is done. You would use this mechanism to manipulate // the data structures so that they maintain a consistent state. // ALE 20130816 You don't have to make use of PDLLBusy if you don't // mind the UI freezing during your processing. Freezing is a fine // approach for things like moving units or firing missiles that // don't require immediate user feedback. // ALE 20130816 Note also that GameTime is called at the beginning of the // game second. Any of the enabled stock GE effects will run after this function // or if using PDLLBusy then once you unbusy any DLLs. if (frmMain.GTckbPause.Checked) then begin Byte(PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE frmMain.GTbtnResume.Enabled:=True; frmMain.SGButtonResume.Enabled:= True; // 240906 // frmMain.GTckbPause.Enabled:=False; testtonight 231117 trying to get every second analysis frmMain.PageControl1.ActivePage:= frmMain.tshGT; //ActivePageIndex:=7; // GameTime/InvestigateStructures // 20230410 // ALE 20130816 this would be a good place to start your thread that does the long processing PEvent := frmMain.PHarpEventHead; frmMain.GTHEEventList.Clear; frmMain.GEHEmemDetail.Clear; while (PEvent <> nil) do begin EventType := PEvent^.event_type; // 202304045 vers update /flag AND CommandMask; strGroupID := 'No Group'; // strEUnitID := 'No Unit'; // don't need this info if (PEvent^.ourGroup <> nil) then begin strGroupID := PHCGroup(PEvent^.ourGroup)^.id; //if PEvent^.unit_uuid <> '' then // strEUnitID := Format(' %0.3d', // [PHCUnit(HCuuid2UnitPtr(PEvent^.unit_uuid,pCurrentStartGroup, PEvent^.ourGroup))^.id]); end; frmMain.GTHEEventList.Items.Add(Format('ExT:%8.5d %s %s uuid:%s', [PEvent^.Time, strGroupID, HCEventType2String(EventType), PEvent^.uuid ])); // ddt 20230410 trimmed // frmMain.GTHEEventList.Items.Add(Format('%8.5d 0x%p %s %3.3d %3.3d %1.1d %s', // [PEvent^.Time, PEvent, strGroupID, PEvent^.UnitID, EventType, PEvent^.in_scroll_flag, // HCEventType2String(EventType)])); / 20230405 vers update PEvent := PEvent^.next; end; end; // end gametime pause // 240613 set up real time update of unit info if (frmMain.SGChkBxRTU.Checked = True) and (frmMain.tshStartGroup.Showing = True) // 240906 // and (frmMain.SGlbxUnits.ItemIndex <> -1) // 240907 expanding test into UnitKtsFill then begin if (HCIsValidUnit(frmMain.PSelectedUnit, frmMain.PStartGroup^.Units) = CTRUE) or (frmMain.PSelectedUnit = nil) then frmMain.SGlblUnitKtsFill(); end; end; procedure ProcessVCList(PThisVicCondn: PHCVictoryConditions); var strVT, strUC, strOS, strDam, strDT: string; begin frmMain.VClstbxItems.Clear; frmMain.VClstbxItems.Items.Add('Import at Session Start'); while PThisVicCondn <> nil do begin if PThisVicCondn^.VicType = 0 then strVT:= 'Minimum' else strVT:= 'Total'; 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.VClstbxItems.Items.Add (Format('GT achieved: %8.8d, vc#%.1d %s; %s; Pertains to: %s; %s; Require: %d %s, %s', [PThisVicCondn^.gameTimeAchieved, PThisVicCondn^.id, AnnexData^.PBSStrings^.SideName[PThisVicCondn^.WhichSide], strVT, strUC, strDT, PThisVicCondn^.numKilled, strOS, strDam])); // 20230420 added ID // // chase crash PThisVicCondn:= PThisVicCondn^.next; end; frmMain.VClstbxItems.Items.Add('Session Play Starts'); end; procedure StartGroup(StartGroup: PHCGroup);export;cdecl; var PHCGThis: PHCGroup; begin PCurrentStartGroup:= StartGroup; begin // ALE 20130317 Fill up the SGlbxGroups frmMain.PStartGroup:=StartGroup; frmMain.SGlbxGroups.Items.Clear; frmMain.SGlbxGroups.Sorted := True; PHCGThis := StartGroup; while (PHCGThis <> nil) do begin frmMain.SGlbxGroups.Items.Add(PHCGThis^.id); PHCGThis := PHCGThis^.toSouth; end; end; frmMain.PStartGroup:=StartGroup; ProcessVCList(frmMain.PVCList); end; procedure HarpoonEventHead(HarpEventHead: PHCHarpoonEvent);export;cdecl; var strEventType: string; EventType, strUid: uchar; pTEventUnit: PHCUnit; lIntExT: Integer; lThisHarpEvent: PHCHarpoonEvent; begin frmMain.PHarpEventHead:= HarpEventHead; if (HarpEventHead <> nil) then begin // insert code for auto pause to investigate events check a new event - frmMain.PE <> eventhead if (frmMain.GTckbAutoP.Checked = true) and (frmMain.PEvent <> HarpEventHead) then begin EventType:=(HarpEventHead^.event_type); // vers update / flag and CommandMask); strEventType:= HCEventType2String(EventType); if ((frmMain.GTcklbAutoP.Checked[0]) and (EventType = ENEMY_AI_EVENT)) or ((frmMain.GTcklbAutoP.Checked[1]) and (EventType = INTERCEPT_EVENT)) or ((frmMain.GTcklbAutoP.Checked[2]) and (EventType = AIR_REFUEL_EVENT)) or ((frmMain.GTcklbAutoP.Checked[3]) and (EventType = LAUNCH_EVENT)) or ((frmMain.GTcklbAutoP.Checked[4]) and (EventType = ALT_SPEED_EVENT)) or ((frmMain.GTcklbAutoP.Checked[5]) and (EventType = ALT_COURSE_EVENT)) or ((frmMain.GTcklbAutoP.Checked[6]) and (EventType = ATTACK_EVENT)) or ((frmMain.GTcklbAutoP.Checked[7]) and (EventType = AIR_ATTACK_EVENT)) or ((frmMain.GTcklbAutoP.Checked[8]) and (EventType = AIR_PATROL_EVENT)) or ((frmMain.GTcklbAutoP.Checked[9]) and (EventType = LAUNCHLAND_EVENT)) or ((frmMain.GTcklbAutoP.Checked[10]) and (EventType = READY_EVENT)) or ((frmMain.GTcklbAutoP.Checked[11]) and (EventType = LANDING_EVENT)) or ((frmMain.GTcklbAutoP.Checked[12]) and (EventType = JOIN_EVENT)) or ((frmMain.GTcklbAutoP.Checked[13]) and (EventType = SPLIT_EVENT)) or ((frmMain.GTcklbAutoP.Checked[14]) and (EventType = SINK_EVENT)) or ((frmMain.GTcklbAutoP.Checked[15]) and (EventType = RELOAD_EVENT)) or ((frmMain.GTcklbAutoP.Checked[16]) and (EventType = FORMATION_EVENT)) then begin Byte(PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE frmMain.WindowState:= wsNormal; // want to wake up frmMain.BringToFront; // frmMain.PageControl1.ActivePage:= frmMain.tshGT; // wake up to last active window CHECKWORKS frmMain.GTbtnResume.Enabled:=True; frmMain.SGButtonResume.Enabled:=True; // frmMain.GTckbPause.Enabled:=False; 20231117 getting every second frmMain.PageControl1.ActivePageIndex:=7; // GameTime/InvestigateStructures use tabsheet name if that works frmMain.GTHEEventList.Clear; frmMain.GEHEmemDetail.Clear; // test that there is a Unit UUID and have default nuls if HarpEventHead^.unit_uuid <> '' then begin // event unit exists PTEventUnit:= HCuuid2UnitPtr(HarpEventHead^.unit_uuid, PCurrentStartGroup, HarpEventHead^.ourGroup); strUid := PTEventUnit^.id; // frmMain.GTHEEventList.Items.Add(Format('event type - %s, ExT:%8.5d',[strEventType, HarpEventHead^.Time])); // 20230409 frmMain.GTHEEventList.Items.Add(Format('Group:Unit %2.2s:%0.3d - %s', [PHCGroup(HarpEventHead^.ourGroup)^.id, strUid, PTEventUnit^.name])); // """" end else begin // no event unit PTEventUnit:= nil; frmMain.GTHEEventList.Items.Add(Format('Group %2.2s: %s - %s', [PHCGroup(HarpEventHead^.ourGroup)^.id, frmMain.HCMT2String(PHCGroup(HarpEventHead^.ourGroup)^.gtype), strEventType])); // 20230409 end; // 20230410 added MT // lIntExT:= HarpEventHead^.Time; // 240908 want to list events of same time but doesn't work frmMain.PEvent:= HarpEventHead; // 240908 moved code from line + 6 frmMain.PEventUnit:= pTEventUnit; frmMain.EventmemDetailWrite; end; //there was a ticked event end; // autoP checked and it was a new event end; // end check eventhead <> nil end; procedure VictoryConditionsList(PVCList: PHCVictoryConditions);export;cdecl; begin frmMain.PVCList := PVCList; end; procedure VictoryConditionLevels(whichSide: uchar; enemySide: uchar; vicLevel: uchar);export; cdecl; begin frmMain.VClstbxItems.Items.Add(Format('GT%8.8d: %s Victory Level %s achieved', [intGameTime, AnnexData^.PBSStrings^.SideName[whichSide], HCVictoryConditionLevel(vicLevel)])); // 20230417 end; procedure VictoryConditionAchieved(VictoryCondition: PHCVictoryConditions); export; cdecl; var strVT, strUC, strOS, strDam, strDT: string; begin if VictoryCondition^.VicType = 0 then strVT:= 'Minimum' else strVT:= 'Total'; 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.VClstbxItems.Items.Add (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 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]); // **** if pLaunchMount <> nil then begin if ourMount <> 0 // 250415 valid outMount then 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; else lWeaponClassName:= 'unknown MultiMntWep'; end else // either arkward mulitmount or simple mount or legacy a2a cannon 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; // end single mount no valid ourMount MULTI_FLAG: // multiflag with no valid ourMount begin if pWeapUnit <> nil then begin case HCAnnexHelper.HCAnnexShift(pWeapUnit^.Annex) of MISSILE_FLAG: begin PHCAnnexD1:= HCAnnexHelper.HCGetAnnexD1(pWeapUnit^.Annex); lWeaponClassName:= PHCAnnexD1^.ClassName; end; TORP_FLAG: begin PHCAnnexF1:= HCAnnexHelper.HCGetAnnexF1(pWeapUnit^.Annex); lWeaponClassName:= PHCAnnexF1^.ClassName; end; ASW_FLAG: begin PHCAnnexE1:= HCAnnexHelper.HCGetAnnexE1(pWeapUnit^.Annex); lWeaponClassName:= PHCAnnexE1^.ClassName; end; GUN_FLAG: begin PHCAnnexC1:= HCAnnexHelper.HCGetAnnexC1(pWeapUnit^.Annex); lWeaponClassName:= PHCAnnexC1^.ClassName; end; ATOG_FLAG: begin PHCAnnexG1:= HCAnnexHelper.HCGetAnnexG1(pWeapUnit^.Annex); lWeaponClassName:= PHCAnnexG1^.ClassName; end; end; // case of look at weapunit end; end; // multimount no valid our Mount // else // no known weapon // begin // lWeaponClassName:= 'NotAudited'; //ShowMessage(IntToStr(ourMount) + '; ' + IntToStr(mountIndex) + '; ' + IntToStr(pLaunchMount^.WepId)); // debug // end; end; // case of mount.wepID end else lWeaponClassName := 'Unknown Weapon'; // 250914 // ****** if (pTargetUnit <> nil) then if HCIsValidUnit(pTargetUnit, frmMain.PStartGroup^.Units) =CTRUE then lTargetUnit := Format('%2.2s%3.3d - %s', [pTargetUnit^.Group^.id, pTargetUnit^.id, pTargetUnit^.name]) else lTargetUnit:= 'Target Destroyed' else lTargetUnit:= 'BOL'; lIntSide:= PHCGroup(pLaunchUnit^.Group)^.side; case lINtSide of 0: lStrSide:= 'Blue'; 1: lStrSide:= 'Red'; 2: lStrSide:= 'Neutral'; end; lHCDTNow:= HCDateTImeInc(gHCDTStart, intGameTIme); frmMain.StoreExpLst.Lines.Insert(0, Format('%d:%d:%d %s %s, Targeting %s, %d x %s, ourMount %d, MntIdx %d', [lHCDTNow.hour, lHCDTNow.minute, lHCDTNow.second, lStrSide, lLaunchUnit, lTargetUnit, pQty, lWeaponClassName, ourMount, mountIndex])); // 250320 250914, pLaunchMount^.WepId, pLaunchMount^.MntId if bAARDataRunning = True then begin RepFile:= Tinifile.Create(Application.Location + iniFileID); RepFile.ReadSectionValues('StoresConsumed - Blue', frmMain.StoreExpAccumLst.Lines); RepFile.ReadSectionValues('StoresConsumed - Red', frmMain.StoreExpRedLst.Lines); if HCMTIsAir(pLaunchUnit^.utype) then begin RepFile.ReadSectionValues('AirCraft-StoresConsumed - Blue', frmMain.StrExpAirBlTally.Lines); RepFile.ReadSectionValues('AirCraft-StoresConsumed - Red', frmMain.StrExpAirRdTally.Lines); end; end; // 250303 end; procedure UnitTop(topUnit: PHCUnit);export;cdecl; begin frmMain.gPHCtopUnit:= topUnit; end; procedure ScenLoaded(intWhichRound: Long); export; cdecl; begin if intWhichRound = SCENLOADED_EXPORTDLLS_DONE then begin frmMain.GTbtnCheck.Click; frmMain.PageControl1.ActivePage:= frmMain.tshGT; end; end; exports DLLVer, DLLVerInt, DLLDesc, DLLFree, DLLInit, // UnitLatLon, UnitShowing, UnitNew, ScenLoad, TimeFactor, MsgLog, GameTime ,StartGroup // ALE 20130205 Sends updated GroupPtr whenever that changes ,HarpoonEventHead // ALE 20130805 Sends updated soonest HarpoonEvent pointer whenever it changes ,VictoryConditionsList // ALE 20130812 Sends a pointer to the list of victory conditions when a scenario is loaded ,VictoryConditionLevels // 20230417 new for ver34 interface fires when a vic cond level achieved ,VictoryConditionAchieved // 20230419 fires when a vict cond list item is met ,StoreConsumed ,SaveGame ,UnitTop ,ScenLoaded ; end.