library ActUnitReport; {$mode delphi}{$H+} uses Classes { you can add units after this } ,uHCDefines, mainform, uActUnitReportGlobals, uHCGCI, uHCGlobals, uHCTypeDefs, uHCEventHelpers, uHCDateTime, uHCAnnexDefs, uHCAnnexHelpers, Windows, Forms, ShellAPI, SysUtils, Types, Dialogs, Interfaces, Controls; const DLLVERN = 3; DLLVERINTN = 34; var frmMain: TfrmMain; {*** 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 := 'ActUnitReport DLL by 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; harpoon_uuid_session: PAnsiChar; hclicense_dt_expire: Int64; hclicense_licensee: PAnsiChar; usblicense_desc: PAnsiChar; RESRSRStructureVersion: ulong; AnnexVersion: ushort); 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; uActUnitReportGlobals.PGEClosing:=PGEClosing; uActUnitReportGlobals.PDLLBusy:=PDLLBusy; uActUnitReportGlobals.intVerSaveGame:=verSaveGame; uActUnitReportGlobals.intVerInterface:=verInterface; frmMain := TfrmMain.Create(nil); // ALE 20160405 let it float outside of HC frmMain.ParentWindow := hwndHC; frmMain.Caption := 'ActUnitReport Export DLL v' + IntToStr(DLLVERN) + ', ExportDLL Interface v' + IntToStr(DLLVERINTN); frmMain.memDLLInit.Lines.Add('ActUnitReport 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 = '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); funcTmp := funcTmp^.next; end; frmMain.Show; 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; 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 := @ScenDataIn^.dt_scen_start; // ALE 20150712 Scenario Starting date and time AnnexData := AnnexDataIn; // ALE 20150813 Database/Platform information HCAnnexHelper := THCAnnexHelper.Create(AnnexDataIn, frmMain.HCannex_id_to_disk_id, uActUnitReportGlobals.intVerInterface, uActUnitReportGlobals.intVerSaveGame); end; procedure GameTime(GameTime: Long; GameTimeLeft: Long);export;cdecl; begin intGameTime := GameTime; intGameTimeLeft := GameTimeLeft; // ALE 20150712 store remaining time frmMain.UpdateActUnitReport(); frmMain.UpdateHarpoonEvents(); // 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. // Byte(PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE end; procedure HarpoonEventHead(HarpEventHead: PHCHarpoonEvent);export;cdecl; begin frmMain.PHarpEventHead:=HarpEventHead; end; procedure ActUnitPtr(ActUnit: PHCUnit);export;cdecl; begin PActUnit := ActUnit; frmMain.UpdateActUnitReport(); end; procedure StartGroup(StartGroup: PHCGroup);export;cdecl; begin frmMain.PStartGroup:=StartGroup; end; exports DLLVer, DLLVerInt, DLLDesc, DLLFree, DLLInit, ScenLoad, GameTime ,StartGroup // ALE 20130205 Sends updated GroupPtr whenever that changes ,HarpoonEventHead // ALE 20130805 Sends updated soonest HarpoonEvent pointer whenever it changes ,ActUnitPtr // ALE 20160305 Sends pointer to the Unit the player just selected or NULL ; end.