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 , Windows, Forms, ShellAPI, SysUtils ,Types ,Dialogs, Interfaces, Controls; const DLLVERN = 7; DLLVERINTN = 17; SIDES = 3; SLIVER360 = 134217728; var frmMain: TfrmMain; intGameTime: Long; intGameTimeLeft: Long; dt_scen_start: PHCDateTimeRec; {*** 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.Free; end; {*** Init DLL ***} procedure DLLInit(hwndHC: HWND; pathHC: PAnsiChar; verHC: PAnsiChar; verSaveGame: LongWord; funcRefs: PHCDLL_FUNC_REF; PGEClosing: Pointer; PDLLBusy: Pointer; verInterface: LongWord);export;cdecl; var funcTmp: PHCDLL_FUNC_REF; begin // here we initialize globals and such for the life of the DLL Application.Initialize; // ALE 20120410 Freezes HC Application.Run; uLazGUIGlobals.PGEClosing:=PGEClosing; uLazGUIGlobals.PDLLBusy:=PDLLBusy; uLazGUIGlobals.intVerInterface:=verInterface; uLazGUIGlobals.intVerSaveGame:=verSaveGame; frmMain := TfrmMain.Create(nil); frmMain.ParentWindow := hwndHC; frmMain.Caption := 'lazarus GUI Export DLL extension v' + IntToStr(DLLVERN) + ', ExportDLL Interface v' + IntToStr(DLLVERINTN) + 'for GE v 2017.005+'; 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])); // 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) ; funcTmp := funcTmp^.next; end; frmMain.Show; end; procedure UnitLatLon(UnitID: Byte; GroupID: PAnsiChar; Lat: Double; Lon: Double);export;cdecl; begin if (frmMain.ULLckbEnabled.Checked = True) then begin frmMain.ULLmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Lat=%3.2f, Lon=%3.2f, Depth/Altitude=%d', [intGameTime, GroupID, UnitID, Lat, Lon, frmMain.HCdllCheckLatLonDepth(Lat, Lon)])); if (frmMain.ULLmemMsgLog.Lines.Count > frmMain.ULLedtLines.Value) then begin frmMain.ULLmemMsgLog.Lines.Delete(frmMain.ULLedtLines.Value); end; end; 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 UnitURegion(UnitID: Byte; GroupID: PAnsiChar; pUR: PTURegion);export;cdecl; var intC1, intC2: integer; strText: string; begin if (frmMain.UURckbEnabled.Checked = True) then begin strText := Format('%8.8d: GroupID=%s, UnitID=%2.2d, UnitURegion', [intGameTime, GroupID, UnitID]); for intC1 := 0 to SIDES-1 do begin for intC2 := 0 to 3 do // Four corners of uncertainty region begin // Dump data to text file // (double)((sLon*360.0)/SLIVER360)) // (double)(90-(sLat*360.0/SLIVER360)) strText := strText + Format(', %8.8f, %8.8f', [(90-(pUR^[intC1]^.sLat[intC2]*360.0/SLIVER360)), ((pUR^[intC1]^.sLon[intC2]*360.0)/SLIVER360)]); end; end; frmMain.UURmemMsgLog.Lines.Insert(0, strText); if (frmMain.UURmemMsgLog.Lines.Count > frmMain.UURedtLines.Value) then begin frmMain.UURmemMsgLog.Lines.Delete(frmMain.UURedtLines.Value); end; end; end; procedure UnitCourse(UnitID: Byte; GroupID: PAnsiChar; course: smallint);export;cdecl; begin if (frmMain.UCckbEnabled.Checked = True) then begin frmMain.UCmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Course (deg)=%d', [intGameTime, GroupID, UnitID, course])); if (frmMain.UCmemMsgLog.Lines.Count > frmMain.UCedtLines.Value) then begin frmMain.UCmemMsgLog.Lines.Delete(frmMain.UCedtLines.Value); end; end; end; procedure UnitSpeed(UnitID: Byte; GroupID: PAnsiChar; speed: smallint);export;cdecl; begin if (frmMain.USPckbEnabled.Checked = True) then begin frmMain.USPmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Speed (kts)=%d', [intGameTime, GroupID, UnitID, speed])); if (frmMain.USPmemMsgLog.Lines.Count > frmMain.USPedtLines.Value) then begin frmMain.USPmemMsgLog.Lines.Delete(frmMain.USPedtLines.Value); end; end; end; procedure UnitAlt(UnitID: Byte; GroupID: PAnsiChar; alt: byte);export;cdecl; begin if (frmMain.UAckbEnabled.Checked = True) then begin frmMain.UAmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Altitude Band=%d', [intGameTime, GroupID, UnitID, alt])); if (frmMain.UAmemMsgLog.Lines.Count > frmMain.UAedtLines.Value) then begin frmMain.UAmemMsgLog.Lines.Delete(frmMain.UAedtLines.Value); end; end; end; procedure UnitShowingSide(UnitID: Byte; GroupID: PAnsiChar; showing: PTSidesUChar);export;cdecl; var intC: integer; strText: string; begin if (frmMain.USSckbEnabled.Checked = True) then begin strText := ''; for intC := 0 to SIDES-1 do begin // Dump data to text file strText := strText + Format('%3.3d ', [showing^[intC]]); end; frmMain.USSmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Showing=%s', [intGameTime, GroupID, UnitID, strText])); if (frmMain.USSmemMsgLog.Lines.Count > frmMain.USSedtLines.Value) then begin frmMain.USSmemMsgLog.Lines.Delete(frmMain.USSedtLines.Value); end; end; end; procedure UnitSink(UnitID: Byte; GroupID: PAnsiChar);export;cdecl; begin frmMain.GTmemDLLcalls.Lines.Add('UnitSink'); if (frmMain.USKckbEnabled.Checked = True) then begin frmMain.USKmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, Sinking', [intGameTime, GroupID, UnitID])); if (frmMain.USKmemMsgLog.Lines.Count > frmMain.USKedtLines.Value) then begin frmMain.USKmemMsgLog.Lines.Delete(frmMain.USKedtLines.Value); end; end; end; procedure UnitToGroup(UnitID: Byte; GroupID, GroupIDold: PAnsiChar);export;cdecl; begin if (frmMain.UGckbEnabled.Checked = True) then begin frmMain.UGmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, UnitToGroup OldGroup=%s', [intGameTime, GroupID, UnitID, GroupIDold])); if (frmMain.UGmemMsgLog.Lines.Count > frmMain.UGedtLines.Value) then begin frmMain.UGmemMsgLog.Lines.Delete(frmMain.UGedtLines.Value); end; end; end; procedure UnitNew(UnitID: Byte; GroupID: PAnsiChar; utype: shortint; side: byte; annexID: word; name: PAnsiChar);export;cdecl; begin if (frmMain.UNckbEnabled.Checked = True) then begin frmMain.UNmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, UnitNew Type=%d, Side=%d, AnnexID=%d, Name=%s', [intGameTime, GroupID, UnitID, utype, side, annexID, name])); if (frmMain.UNmemMsgLog.Lines.Count > frmMain.UNedtLines.Value) then begin frmMain.UNmemMsgLog.Lines.Delete(frmMain.UNedtLines.Value); end; if (frmMain.UNckbPause.Checked = True) then begin Byte(PDLLBusy^) := CTRUE; frmMain.PageControl1.ActivePageIndex:= 11; frmMain.WindowState:= wsNormal; frmMain.UNbtnResume.Enabled:= False; frmMain.UNbtnResume.Enabled:= True; end; end; end; procedure UnitFree(UnitID: Byte; GroupID: PAnsiChar);export;cdecl; begin frmMain.GTmemDLLcalls.Lines.Add('UnitFree'); frmMain.DUbtnUpdate.Click; if (frmMain.UFckbEnabled.Checked = True) then begin frmMain.UFmemMsgLog.Lines.Insert(0, Format('%8.8d: GroupID=%s, UnitID=%2.2d, UnitFree', [intGameTime, GroupID, UnitID])); if (frmMain.UFmemMsgLog.Lines.Count > frmMain.UFedtLines.Value) then begin frmMain.UFmemMsgLog.Lines.Delete(frmMain.UFedtLines.Value); end; end; end; procedure ScenLoad(strHarpPath: PAnsiChar; intScenNum: SmallInt; strScenFPath: PAnsiChar; intBSNum: ShortInt; strBSFName: PAnsiChar; intSide: byte; intGameTimeIn: Long; intGameTimeLeftIn: Long; dt_scen_start_in: PHCDateTimeRec; AnnexDataIn: PHCAnnexes_disk);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; 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 := 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'); if (frmMain.SLckbEnabled.Checked = True) then begin frmMain.SLmemMsgLog.Lines.Insert(0, Format('ScenLoad HC Path=%s, Scen#=%d, ScenFNP=%s, BattleSet=%d, BattleSet=%s, PlayerSide=%d', [strHarpPath, intScenNum, strScenFPath, intBSNum, strBSFName, intSide])); if (frmMain.SLmemMsgLog.Lines.Count > frmMain.SLedtLines.Value) then begin frmMain.SLmemMsgLog.Lines.Delete(frmMain.SLedtLines.Value); end; end; // in lazgui tony dumps annex data to mainform page 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; begin intGameTime := 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.GTckbPause.Enabled:=False; frmMain.PageControl1.ActivePageIndex:=21; // GameTime/InvestigateStructures // 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^.flag AND CommandMask; strGroupID := ' '; if (PEvent^.ourGroup <> nil) then strGroupID := PHCGroup(PEvent^.ourGroup)^.id; 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)])); PEvent := PEvent^.next; end; end; end; procedure StartGroup(StartGroup: PHCGroup);export;cdecl; var PHCGThis: PHCGroup; begin frmMain.GTmemDLLcalls.Lines.Add('startgroup'); if (frmMain.SGckbEnabled.Checked = True) then begin if (StartGroup <> nil) then begin if (StartGroup^.Units <> nil) then begin frmMain.SGmemMsgLog.Lines.Insert(0, Format('%8.8d: %s %s', [intGameTime, StartGroup^.id, StartGroup^.Units^.name])); end else begin frmMain.SGmemMsgLog.Lines.Insert(0, Format('%8.8d: %s', [intGameTime, StartGroup^.id])); end end else begin frmMain.SGmemMsgLog.Lines.Insert(0, Format('%8.8d: StartGroup is NULL', [intGameTime])); end; if (frmMain.SGmemMsgLog.Lines.Count > frmMain.SGedtLines.Value) then begin frmMain.SGmemMsgLog.Lines.Delete(frmMain.SGedtLines.Value); end; // 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; end; procedure HarpoonEventHead(HarpEventHead: PHCHarpoonEvent);export;cdecl; var strEventType: string; EventType: uchar; begin frmMain.GTmemDLLcalls.Lines.Add('HarpEventHead'); // ddt clocking procedure/function calls frmMain.PHarpEventHead:= HarpEventHead; if (HarpEventHead <> nil) then begin if (frmMain.HHckbEnabled.Checked = True) then begin frmMain.HHmemMsgLog.Lines.Insert(0, Format('%8.8d: 0x%p', [intGameTime, HarpEventHead])); end; if (frmMain.HHmemMsgLog.Lines.Count > frmMain.HHedtLines.Value) then begin frmMain.HHmemMsgLog.Lines.Delete(frmMain.HHedtLines.Value); end; // insert code for auto pause to investigate events if (frmMain.GTckbAutoP.Checked = true) and (frmMain.PEvent <> HarpEventHead) then begin EventType:= (HarpEventHead^.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)) then begin Byte(PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE frmMain.GTbtnResume.Enabled:=True; frmMain.GTckbPause.Enabled:=False; frmMain.PageControl1.ActivePageIndex:=21; // GameTime/InvestigateStructures frmMain.GTHEEventList.Clear; frmMain.GEHEmemDetail.Clear; frmMain.GTHEEventList.Items.Add(Format('%8.5d 0x%p %3.3s %3.3d %1.1d %s', [HarpEventHead^.Time, HarpEventHead, PHCGroup(HarpEventHead^.ourGroup)^.id , HarpEventHead^.UnitID, HarpEventHead^.in_scroll_flag, strEventType])); frmMain.PEvent:= HarpEventHead; frmMain.EventmemDetailWrite; end; end; end else begin frmMain.HHmemMsgLog.Lines.Insert(0, Format('%8.8d: HarpoonEventHead is NULL', [intGameTime])); end; end; procedure SonobuoyRegionHead(SonobuoyRegionHead: PHCSonobuoyRegion);export;cdecl; begin if (frmMain.SHckbEnabled.Checked = True) then begin if (SonobuoyRegionHead <> nil) then begin frmMain.SHmemMsgLog.Lines.Insert(0, Format('%8.8d: 0x%p', [intGameTime, SonobuoyRegionHead])); end else begin frmMain.SHmemMsgLog.Lines.Insert(0, Format('%8.8d: SonobuoyRegionHead is NULL', [intGameTime])); end; if (frmMain.SHmemMsgLog.Lines.Count > frmMain.SHedtLines.Value) then begin frmMain.SHmemMsgLog.Lines.Delete(frmMain.SHedtLines.Value); end; end; frmMain.PSonobuoyRegionHead := SonobuoyRegionHead; end; procedure AllDeadUnitsPtr(AllDeadUnitsPtr: PHCDeadListItem);export;cdecl; var strClass, strSide: string; intDead: Integer; begin frmMain.GTmemDLLcalls.Lines.Add('deadunitptr'); if (frmMain.DUckbEnabled.Checked = True) then begin if (AllDeadUnitsPtr <> nil) then frmMain.DUmemMsgLog.Lines.Insert(0, Format('%8.8d: 0x%p', [intGameTime, AllDeadUnitsPtr])) else frmMain.DUmemMsgLog.Lines.Insert(0, Format('%8.8d: AllDeadUnitsPtr is NULL', [intGameTime])); if (frmMain.DUmemMsgLog.Lines.Count > frmMain.DUedtLines.Value) then begin frmMain.DUmemMsgLog.Lines.Delete(frmMain.DUedtLines.Value); end; end; frmMain.PAllDeadUnitsPtr := AllDeadUnitsPtr; end; procedure WeatherGroups(WeatherGroups: PHCGroup);export;cdecl; begin if (frmMain.WGckbEnabled.Checked = True) then begin if (WeatherGroups <> nil) then begin frmMain.WGmemMsgLog.Lines.Insert(0, Format('%8.8d: 0x%p', [intGameTime, WeatherGroups])); end else begin frmMain.WGmemMsgLog.Lines.Insert(0, Format('%8.8d: WeatherGroups is NULL', [intGameTime])); end; if (frmMain.WGmemMsgLog.Lines.Count > frmMain.WGedtLines.Value) then begin frmMain.WGmemMsgLog.Lines.Delete(frmMain.WGedtLines.Value); end; end; frmMain.PWeatherGroups := WeatherGroups; end; procedure VictoryConditionsList(VictoryConditionsList: PHCVictoryConditions);export;cdecl; var PThisVicCondn: PHCVictoryConditions; begin if (frmMain.VCckbEnabled.Checked = True) then begin if (VictoryConditionsList <> nil) then begin frmMain.VCmemMsgLog.Lines.Insert(0, Format('%8.8d: 0x%p', [intGameTime, VictoryConditionsList])); PThisVicCondn:= VictoryConditionsList; frmMain.VClstbxItems.Clear; while PThisVicCondn <> nil do begin frmMain.VClstbxItems.Items.Add(Format('side: %d; UnitType: %d; VicType: %d; ItemType: %d; DetailType: %d; id: %d',[PThisVicCondn^.WhichSide, PThisVicCondn^.unitType, PThisVicCondn^.VicType, PThisVicCondn^.itemType, PThisVicCondn^.DetailType, PThisVicCondn^.numKilled])); // PThisVicCondn:= PThisVicCondn^.next; end; end else begin frmMain.VCmemMsgLog.Lines.Insert(0, Format('%8.8d: VictoryConditionsList is NULL', [intGameTime])); end; if (frmMain.VCmemMsgLog.Lines.Count > frmMain.VCedtLines.Value) then begin frmMain.VCmemMsgLog.Lines.Delete(frmMain.VCedtLines.Value); end; end; frmMain.PVictoryConditionsList := VictoryConditionsList; end; exports DLLVer, DLLVerInt, DLLDesc, DLLFree, DLLInit, UnitLatLon, UnitShowing, UnitURegion, UnitCourse, UnitSpeed, UnitAlt, UnitShowingSide, UnitSink, UnitToGroup, UnitNew, UnitFree, ScenLoad, TimeFactor, MsgLog, GameTime ,StartGroup // ALE 20130205 Sends updated GroupPtr whenever that changes ,HarpoonEventHead // ALE 20130805 Sends updated soonest HarpoonEvent pointer whenever it changes ,SonobuoyRegionHead // ALE 20130812 Sends updated pointer to all sonobuoys when it changes ,AllDeadUnitsPtr // ALE 20130812 Sends updated pointer to the list of killed units used for victory condition evaluation ,WeatherGroups // ALE 20130812 Sends update GroupPtr whenever the top weather group changes ,VictoryConditionsList // ALE 20130812 Sends a pointer to the list of victory conditions when a scenario is loaded ; end.