From 923fa980434e55419f35422119af2faae2bf68d7 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Thu, 31 Aug 2017 22:28:08 +0300 Subject: [PATCH] no more old-styled map structured; sadly, most triggers aren't working; also, save/load is completely broken --- src/game/g_game.pas | 14 +- src/game/g_gui.pas | 60 ++- src/game/g_main.pas | 3 +- src/game/g_map.pas | 738 +++++++++++++++++++++---------------- src/game/g_netmsg.pas | 6 +- src/game/g_panel.pas | 6 +- src/game/g_triggers.pas | 541 ++++++++++++++------------- src/shared/MAPDEF.pas | 326 ++++++++-------- src/shared/mapdef.inc | 186 ---------- src/shared/mapdef_help.inc | 88 +++++ src/shared/mapdef_impl.inc | 123 +++++++ src/shared/xdynrec.pas | 166 ++++++++- src/tools/mapgen.dpr | 157 +++++++- 13 files changed, 1399 insertions(+), 1015 deletions(-) create mode 100644 src/shared/mapdef_help.inc create mode 100644 src/shared/mapdef_impl.inc diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 03be57d..302b952 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -5198,7 +5198,8 @@ begin begin g_Console_Add('player left the map'); gExitByTrigger := True; - g_Game_ExitLevel(gTriggers[a].Data.MapName); + //g_Game_ExitLevel(gTriggers[a].Data.MapName); + g_Game_ExitLevel(gTriggers[a].trigData.trigMapName); break; end; end; @@ -6067,7 +6068,8 @@ begin if gTriggers[a].TriggerType = TRIGGER_EXIT then begin gExitByTrigger := True; - gNextMap := gTriggers[a].Data.MapName; + //gNextMap := gTriggers[a].Data.MapName; + gNextMap := gTriggers[a].trigData.trigMapName; Break; end; // Èùåì ñëåäóþùóþ êàðòó â WAD ôàéëå @@ -6458,17 +6460,17 @@ begin with gTriggers[i] do if (TriggerType = TRIGGER_SOUND) and (Sound <> nil) and - (Data.Local) and + (trigData.trigLocal) and Sound.IsPlaying() then begin if ((gPlayer1 <> nil) and g_CollidePoint(gPlayer1.GameX, gPlayer1.GameY, X, Y, Width, Height)) or ((gPlayer2 <> nil) and g_CollidePoint(gPlayer2.GameX, gPlayer2.GameY, X, Y, Width, Height)) then begin - Sound.SetPan(0.5 - Data.Pan/255.0); - Sound.SetVolume(Data.Volume/255.0); + Sound.SetPan(0.5 - trigData.trigPan/255.0); + Sound.SetVolume(trigData.trigVolume/255.0); end else - Sound.SetCoords(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0); + Sound.SetCoords(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0); end; end; diff --git a/src/game/g_gui.pas b/src/game/g_gui.pas index 45b2364..d7735ab 100644 --- a/src/game/g_gui.pas +++ b/src/game/g_gui.pas @@ -2775,10 +2775,9 @@ end; procedure TGUIMapPreview.SetMap(Res: string); var WAD: TWADFile; - //MapReader: TMapReader_1; - panels: TPanelsRec1Array; - header: TMapHeaderRec_1; - a: Integer; + panlist: TDynField; + pan: TDynRecord; + //header: TMapHeaderRec_1; FileName: string; Data: Pointer; Len: Integer; @@ -2815,48 +2814,36 @@ begin raise; end; - { - MapReader := TMapReader_1.Create(); - if not MapReader.LoadMap(Data) then - begin - FreeMem(Data); - MapReader.Free(); - FMapSize.X := 0; - FMapSize.Y := 0; - FScale := 0.0; - FMapData := nil; - Exit; - end; - } - FreeMem(Data); - panels := GetPanels(map); - header := GetMapHeader(map); + panlist := map.field['panel']; + //header := GetMapHeader(map); - FMapSize.X := header.Width div 16; - FMapSize.Y := header.Height div 16; + FMapSize.X := map.Width div 16; + FMapSize.Y := map.Height div 16; - rX := Ceil(header.Width / (MAPPREVIEW_WIDTH*256.0)); - rY := Ceil(header.Height / (MAPPREVIEW_HEIGHT*256.0)); + rX := Ceil(map.Width / (MAPPREVIEW_WIDTH*256.0)); + rY := Ceil(map.Height / (MAPPREVIEW_HEIGHT*256.0)); FScale := max(rX, rY); FMapData := nil; - if panels <> nil then - for a := 0 to High(panels) do - if WordBool(panels[a].PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or + if (panlist <> nil) then + begin + for pan in panlist do + begin + if (pan.PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP or PANEL_WATER or - PANEL_ACID1 or PANEL_ACID2)) then + PANEL_ACID1 or PANEL_ACID2)) <> 0 then begin SetLength(FMapData, Length(FMapData)+1); with FMapData[High(FMapData)] do begin - X1 := panels[a].X div 16; - Y1 := panels[a].Y div 16; + X1 := pan.X div 16; + Y1 := pan.Y div 16; - X2 := (panels[a].X + panels[a].Width) div 16; - Y2 := (panels[a].Y + panels[a].Height) div 16; + X2 := (pan.X + pan.Width) div 16; + Y2 := (pan.Y + pan.Height) div 16; X1 := Trunc(X1/FScale + 0.5); Y1 := Trunc(Y1/FScale + 0.5); @@ -2871,13 +2858,12 @@ begin Y2 := Y2 + 1; end; - PanelType := panels[a].PanelType; + PanelType := pan.PanelType; + end; end; - end; - - panels := nil; + end; + end; - //MapReader.Free(); map.Free(); end; diff --git a/src/game/g_main.pas b/src/game/g_main.pas index 1b131f1..06e5ace 100644 --- a/src/game/g_main.pas +++ b/src/game/g_main.pas @@ -302,7 +302,8 @@ begin if gTriggers[a].TriggerType = TRIGGER_EXIT then begin gExitByTrigger := True; - g_Game_ExitLevel(gTriggers[a].Data.MapName); + //g_Game_ExitLevel(gTriggers[a].Data.MapName); + g_Game_ExitLevel(gTriggers[a].trigData.trigMapName); Break; end; goto Cheated; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 66d4e56..1695460 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -201,6 +201,8 @@ var profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY! gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()` + gCurrentMap: TDynRecord = nil; + function panelTypeToTag (panelType: Word): Integer; // returns GridTagXXX @@ -219,7 +221,7 @@ uses GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG, g_options, g_triggers, g_player, Math, g_monsters, g_saveload, g_language, g_netmsg, - utils, sfs, xstreams, + utils, sfs, xstreams, hashtable, ImagingTypes, Imaging, ImagingUtility, ImagingGif, ImagingNetworkGraphics; @@ -232,7 +234,6 @@ const var dfmapdef: TDynMapDef = nil; - procedure loadMapDefinition (); var pr: TTextParser = nil; @@ -734,7 +735,7 @@ begin PanelArray := nil; end; -function CreatePanel(PanelRec: TPanelRec_1; AddTextures: TAddTextureArray; +function CreatePanel(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; sav: Boolean): Integer; var len: Integer; @@ -1107,7 +1108,7 @@ begin end; end; -procedure CreateItem(Item: TItemRec_1); +procedure CreateItem(Item: TDynRecord); begin if g_Game_IsClient then Exit; @@ -1119,7 +1120,7 @@ begin gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF, GM_COOP]); end; -procedure CreateArea(Area: TAreaRec_1); +procedure CreateArea(Area: TDynRecord); var a: Integer; id: DWORD = 0; @@ -1189,7 +1190,7 @@ begin end; end; -procedure CreateTrigger(Trigger: TTriggerRec_1; fTexturePanel1Type, fTexturePanel2Type: Word); +procedure CreateTrigger(Trigger: TDynRecord; atpanid, ashotpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word); var _trigger: TTrigger; begin @@ -1208,13 +1209,16 @@ begin TriggerType := Trigger.TriggerType; ActivateType := Trigger.ActivateType; Keys := Trigger.Keys; - Data.Default := Trigger.DATA; + trigPanelId := atpanid; + trigShotPanelId := ashotpanid; + //Data.Default := Trigger.DATA; + trigData := Trigger.trigRec.clone(); end; g_Triggers_Create(_trigger); end; -procedure CreateMonster(monster: TMonsterRec_1); +procedure CreateMonster(monster: TDynRecord); var a: Integer; mon: TMonster; @@ -1232,7 +1236,8 @@ begin begin if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then begin - if (gTriggers[a].Data.MonsterID-1) = mon.StartID then mon.AddTrigger(a); + //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a); + if (gTriggers[a].trigData.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a); end; end; end; @@ -1253,7 +1258,8 @@ procedure g_Map_ReAdd_DieTriggers(); begin if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then begin - if (gTriggers[a].Data.MonsterID-1) = mon.StartID then mon.AddTrigger(a); + //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a); + if (gTriggers[a].trigData.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a); end; end; end; @@ -1283,28 +1289,44 @@ begin end; procedure generateExternalResourcesList({mapReader: TMapReader_1}map: TDynRecord); -var - textures: TTexturesRec1Array; - mapHeader: TMapHeaderRec_1; - i: integer; - resFile: String = ''; +//var + //textures: TTexturesRec1Array; + //textures: TDynField; + //trec: TDynRecord; + //mapHeader: TMapHeaderRec_1; + //i: integer; + //resFile: String = ''; begin if gExternalResources = nil then gExternalResources := TStringList.Create; gExternalResources.Clear; + + (* + { textures := GetTextures(map); for i := 0 to High(textures) do begin addResToExternalResList(resFile); end; + } + + textures := map['texture']; + if (textures <> nil) then + begin + for trec in textures do + begin + addResToExternalResList(resFile); + end; + end; textures := nil; + *) - mapHeader := GetMapHeader(map); + //mapHeader := GetMapHeader(map); - addResToExternalResList(mapHeader.MusicName); - addResToExternalResList(mapHeader.SkyName); + addResToExternalResList(map.MusicName); + addResToExternalResList(map.SkyName); end; @@ -1424,45 +1446,66 @@ function g_Map_Load(Res: String): Boolean; const DefaultMusRes = 'Standart.wad:STDMUS\MUS1'; DefaultSkyRes = 'Standart.wad:STDSKY\SKY0'; +type + PTRec = ^TTRec; + TTRec = record + //TexturePanel: Integer; + texPanIdx: Integer; + LiftPanelIdx: Integer; + DoorPanelIdx: Integer; + ShotPanelIdx: Integer; + trigrec: TDynRecord; + texPan: TDynRecord; + liftPan: TDynRecord; + doorPan: TDynRecord; + shotPan: TDynRecord; + end; var WAD: TWADFile; //MapReader: TMapReader_1; mapReader: TDynRecord = nil; - Header: TMapHeaderRec_1; - _textures: TTexturesRec1Array; - _texnummap: array of Integer; // `_textures` -> `Textures` - panels: TPanelsRec1Array; - items: TItemsRec1Array; - monsters: TMonsterRec1Array; - areas: TAreasRec1Array; - triggers: TTriggersRec1Array; - a, b, c, k: Integer; + //Header: TMapHeaderRec_1; + _textures: TDynField = nil; //TTexturesRec1Array; tagInt: texture index + //_texnummap: array of Integer = nil; // `_textures` -> `Textures` + panels: TDynField = nil; //TPanelsRec1Array; + items: TDynField = nil; //TItemsRec1Array; + monsters: TDynField = nil; //TMonsterRec1Array; + areas: TDynField = nil; //TAreasRec1Array; + triggers: TDynField = nil; //TTriggersRec1Array; + b, c, k: Integer; PanelID: DWORD; AddTextures: TAddTextureArray; - texture: TTextureRec_1; - TriggersTable: Array of record - TexturePanel: Integer; - LiftPanel: Integer; - DoorPanel: Integer; - ShotPanel: Integer; - end; + //texture: TTextureRec_1; + TriggersTable: array of TTRec; FileName, mapResName, s, TexName: String; Data: Pointer; Len: Integer; ok, isAnim, trigRef: Boolean; CurTex, ntn: Integer; + rec, texrec: TDynRecord; + pttit: PTRec; + pannum, trignum, cnt: Integer; + // key: panel index; value: `TriggersTable` index + hashTextPan: THashIntInt = nil; + hashLiftPan: THashIntInt = nil; + hashDoorPan: THashIntInt = nil; + hashShotPan: THashIntInt = nil; begin mapGrid.Free(); mapGrid := nil; + gCurrentMap.Free(); + gCurrentMap := nil; + Result := False; gMapInfo.Map := Res; TriggersTable := nil; - FillChar(texture, SizeOf(texture), 0); + mapReader := nil; + //FillChar(texture, SizeOf(texture), 0); sfsGCDisable(); // temporary disable removing of temporary volumes try - // Çàãðóçêà WAD: + // Çàãðóçêà WAD: FileName := g_ExtractWadName(Res); e_WriteLog('Loading map WAD: '+FileName, MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False); @@ -1497,443 +1540,473 @@ begin e_LogWritefln('Loading map: %s', [mapResName], MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False); - { - if (PChar(Data)[0] = 'M') and (PChar(Data)[1] = 'A') and (PChar(Data)[2] = 'P') and (PByte(Data)[3] = 1) then - begin - // nothing - end - else - begin - e_LogWritefln('Loading text map: %s', [mapResName]); - loadMapDefinition(); - if (dfmapdef = nil) then raise Exception.Create('internal map loader error'); - //e_LogWritefln('***'#10'%s'#10'***', [dfmapdef.headerType.definition]); - wst := TSFSMemoryChunkStream.Create(Data, Len); - try - pr := TFileTextParser.Create(wst); - e_LogWritefln('parsing text map: %s', [mapResName]); - rec := dfmapdef.parseMap(pr); - except on e: Exception do - begin - if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.line, pr.col, e.message]) - else e_LogWritefln('ERROR: %s', [e.message]); - pr.Free(); - wst.Free(); - FreeMem(Data); - exit; - end; - end; - pr.Free(); - //wst.Free(); // pr will do it - e_LogWritefln('writing text map to temporary bin storage...', []); - st := TMemoryStream.Create(); - try - rec.writeBinTo(st); - Len := Integer(st.position); - st.position := 0; - FreeMem(Data); - GetMem(Data, Len); - st.ReadBuffer(Data^, Len); - except on e: Exception do - begin - rec.Free(); - st.Free(); - e_LogWritefln('ERROR: %s', [e.message]); - FreeMem(Data); - exit; - end; - end; - st.Free(); - end; - } try mapReader := g_Map_ParseMap(Data, Len); except mapReader.Free(); g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res])); FreeMem(Data); - MapReader.Free(); - Exit; - end; - - { - MapReader := TMapReader_1.Create(); - if not MapReader.LoadMap(Data) then - begin - g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res])); - FreeMem(Data); - MapReader.Free(); Exit; end; - } FreeMem(Data); - generateExternalResourcesList(MapReader); - // Çàãðóçêà òåêñòóð: - g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False); - _textures := GetTextures(mapReader); - _texnummap := nil; - // Çàãðóçêà îïèñàíèÿ êàðòû: + hashTextPan := hashNewIntInt(); + hashLiftPan := hashNewIntInt(); + hashDoorPan := hashNewIntInt(); + hashShotPan := hashNewIntInt(); + + generateExternalResourcesList(MapReader); + //_textures := GetTextures(mapReader); + _textures := mapReader['texture']; + //_texnummap := nil; + // get all other lists here too + //panels := GetPanels(mapReader); + panels := mapReader['panel']; + //triggers := GetTriggers(mapReader); + triggers := mapReader['trigger']; + //items := GetItems(mapReader); + items := mapReader['item']; + //areas := GetAreas(mapReader); + areas := mapReader['area']; + //monsters := GetMonsters(mapReader); + monsters := mapReader['monster']; + + // Çàãðóçêà îïèñàíèÿ êàðòû: e_WriteLog(' Reading map info...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False); - Header := GetMapHeader(mapReader); + //Header := GetMapHeader(mapReader); with gMapInfo do begin - Name := Header.MapName; - Description := Header.MapDescription; - Author := Header.MapAuthor; - MusicName := Header.MusicName; - SkyName := Header.SkyName; - Height := Header.Height; - Width := Header.Width; + Name := mapReader.MapName; + Description := mapReader.MapDesc; + Author := mapReader.MapAuthor; + MusicName := mapReader.MusicName; + SkyName := mapReader.SkyName; + Height := mapReader.Height; + Width := mapReader.Width; end; - // Äîáàâëåíèå òåêñòóð â Textures[]: - if _textures <> nil then + // Çàãðóçêà òåêñòóð: + g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False); + // Äîáàâëåíèå òåêñòóð â Textures[]: + if (_textures <> nil) and (_textures.count > 0) then begin e_WriteLog(' Loading textures:', MSG_NOTIFY); - g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], High(_textures), False); - SetLength(_texnummap, length(_textures)); + g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], _textures.count-1, False); + //SetLength(_texnummap, _textures.count); - for a := 0 to High(_textures) do + cnt := -1; + for rec in _textures do begin - SetLength(s, 64); - CopyMemory(@s[1], @_textures[a].Resource[0], 64); - for b := 1 to Length(s) do - begin - if s[b] = #0 then - begin - SetLength(s, b-1); - Break; - end; - end; + Inc(cnt); + s := rec.Resource; {$IF DEFINED(D2F_DEBUG_TXLOAD)} - e_WriteLog(Format(' Loading texture #%d: %s', [a, s]), MSG_NOTIFY); + e_WriteLog(Format(' Loading texture #%d: %s', [cnt, s]), MSG_NOTIFY); {$ENDIF} //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY); - // Àíèìèðîâàííàÿ òåêñòóðà: - if ByteBool(_textures[a].Anim) then - begin - ntn := CreateAnimTexture(_textures[a].Resource, FileName, True); - if ntn < 0 then - begin - g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s])); - ntn := CreateNullTexture(_textures[a].Resource); - end; - end - else // Îáû÷íàÿ òåêñòóðà: - ntn := CreateTexture(_textures[a].Resource, FileName, True); - if ntn < 0 then - begin - g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s])); - ntn := CreateNullTexture(_textures[a].Resource); - end; + if rec.Anim then + begin + // Àíèìèðîâàííàÿ òåêñòóðà + ntn := CreateAnimTexture(rec.Resource, FileName, True); + if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s])); + end + else + begin + // Îáû÷íàÿ òåêñòóðà + ntn := CreateTexture(rec.Resource, FileName, True); + if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s])); + end; + if (ntn < 0) then ntn := CreateNullTexture(rec.Resource); - _texnummap[a] := ntn; // fix texture number + //_texnummap[a] := ntn; // fix texture number + rec.tagInt := ntn; g_Game_StepLoading(); end; + + // set panel tagInt to texture index + if (panels <> nil) then + begin + for rec in panels do + begin + texrec := rec.TextureRec; + if (texrec = nil) then rec.tagInt := -1 else rec.tagInt := texrec.tagInt; + end; + end; end; - // Çàãðóçêà òðèããåðîâ: + // Çàãðóçêà òðèããåðîâ gTriggerClientID := 0; e_WriteLog(' Loading triggers...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS], 0, False); - triggers := GetTriggers(mapReader); - // Çàãðóçêà ïàíåëåé: + // Çàãðóçêà ïàíåëåé e_WriteLog(' Loading panels...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_PANELS], 0, False); - panels := GetPanels(mapReader); // check texture numbers for panels - for a := 0 to High(panels) do + if (panels <> nil) and (panels.count > 0) then begin - if panels[a].TextureNum > High(_textures) then + for rec in panels do begin - e_WriteLog('error loading map: invalid texture index for panel', MSG_FATALERROR); - result := false; - exit; + if (rec.tagInt < 0) then + begin + e_WriteLog('error loading map: invalid texture index for panel', MSG_FATALERROR); + result := false; + exit; + end; end; - panels[a].TextureNum := _texnummap[panels[a].TextureNum]; end; - // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì): - if triggers <> nil then + // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì) + if (triggers <> nil) and (triggers.count > 0) then begin e_WriteLog(' Setting up trigger table...', MSG_NOTIFY); - SetLength(TriggersTable, Length(triggers)); - g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], High(TriggersTable), False); + //SetLength(TriggersTable, triggers.count); + g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], triggers.count-1, False); - for a := 0 to High(TriggersTable) do + for rec in triggers do begin - // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè): - TriggersTable[a].TexturePanel := triggers[a].TexturePanel; - // Ëèôòû: - if triggers[a].TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then - TriggersTable[a].LiftPanel := TTriggerData(triggers[a].DATA).PanelID - else - TriggersTable[a].LiftPanel := -1; - // Äâåðè: - if triggers[a].TriggerType in [TRIGGER_OPENDOOR, - TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, - TRIGGER_CLOSETRAP, TRIGGER_TRAP] then - TriggersTable[a].DoorPanel := TTriggerData(triggers[a].DATA).PanelID - else - TriggersTable[a].DoorPanel := -1; - // Òóðåëü: - if triggers[a].TriggerType = TRIGGER_SHOT then - TriggersTable[a].ShotPanel := TTriggerData(triggers[a].DATA).ShotPanelID - else - TriggersTable[a].ShotPanel := -1; + SetLength(TriggersTable, Length(TriggersTable)+1); + pttit := @TriggersTable[High(TriggersTable)]; + pttit.trigrec := rec; + pttit.texPan := mapReader.panel[rec.TexturePanel]; + pttit.liftPan := nil; + pttit.doorPan := nil; + pttit.shotPan := nil; + pttit.texPanIdx := -1; + pttit.LiftPanelIdx := -1; + pttit.DoorPanelIdx := -1; + pttit.ShotPanelIdx := -1; + // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè) + //if (rec.TexturePanel >= 0) and (pttit.texPan = nil) then e_WriteLog('error loading map: invalid texture panel index for trigger', MSG_WARNING); + // Ëèôòû + if rec.TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then + begin + //pttit.LiftPanel := TTriggerData(rec.DATA).PanelID + pttit.liftPan := mapReader.panel[rec.trigRec.tgPanelID]; + //if (rec.trigRec.trigPanelID >= 0) and (pttit.liftPan = nil) then e_WriteLog('error loading map: invalid lift panel index for trigger', MSG_WARNING); + end; + // Äâåðè + if rec.TriggerType in [TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP] then + begin + //pttit.DoorPanel := TTriggerData(rec.DATA).PanelID + pttit.doorPan := mapReader.panel[rec.trigRec.tgPanelID]; + end; + // Òóðåëü + if (rec.TriggerType = TRIGGER_SHOT) then + begin + //pttit.ShotPanel := TTriggerData(rec.DATA).ShotPanelID + pttit.shotPan := mapReader.panel[rec.trigRec.tgShotPanelID]; + end; + + // update hashes + if (pttit.texPan <> nil) then hashTextPan.put(rec.TexturePanel, High(TriggersTable)); + if (pttit.liftPan <> nil) then hashLiftPan.put(rec.trigRec.tgPanelID, High(TriggersTable)); + if (pttit.doorPan <> nil) then hashDoorPan.put(rec.trigRec.tgPanelID, High(TriggersTable)); + if (pttit.shotPan <> nil) then hashShotPan.put(rec.trigRec.tgShotPanelID, High(TriggersTable)); g_Game_StepLoading(); end; end; - // Ñîçäàåì ïàíåëè: - if panels <> nil then + // Ñîçäàåì ïàíåëè + if (panels <> nil) and (panels.count > 0) then begin e_WriteLog(' Setting up trigger links...', MSG_NOTIFY); - g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], High(panels), False); + g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], panels.count-1, False); - for a := 0 to High(panels) do + pannum := -1; + for rec in panels do begin + Inc(pannum); + texrec := nil; SetLength(AddTextures, 0); trigRef := False; CurTex := -1; - if _textures <> nil then - begin - texture := _textures[panels[a].TextureNum]; - ok := True; - end - else - ok := False; + ok := false; + + if (_textures <> nil) then + begin + texrec := rec.TextureRec; + ok := (texrec <> nil); + end; if ok then begin - // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû. - // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð: - ok := False; + // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû. + // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð + ok := false; if (TriggersTable <> nil) and (_textures <> nil) then + begin for b := 0 to High(TriggersTable) do - if (TriggersTable[b].TexturePanel = a) - or (TriggersTable[b].ShotPanel = a) then + begin + if (TriggersTable[b].texPan = rec) or (TriggersTable[b].shotPan = rec) then begin trigRef := True; ok := True; - Break; + break; end; + end; + end; end; if ok then - begin // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü - SetLength(s, 64); - CopyMemory(@s[1], @texture.Resource[0], 64); - // Èçìåðÿåì äëèíó: - Len := Length(s); - for c := Len downto 1 do - if s[c] <> #0 then - begin - Len := c; - Break; - end; - SetLength(s, Len); + begin + // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü + s := texrec.Resource; - // Ñïåö-òåêñòóðû çàïðåùåíû: + // Ñïåö-òåêñòóðû çàïðåùåíû if g_Map_IsSpecialTexture(s) then - ok := False + begin + ok := false + end else - // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè: + begin + // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè ok := g_Texture_NumNameFindStart(s); + end; - // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå. - // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #: + // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå. + // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè # if ok then begin k := NNF_NAME_BEFORE; - // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû: - while ok or (k = NNF_NAME_BEFORE) or - (k = NNF_NAME_EQUALS) do + // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû + while ok or (k = NNF_NAME_BEFORE) or (k = NNF_NAME_EQUALS) do begin k := g_Texture_NumNameFindNext(TexName); - if (k = NNF_NAME_BEFORE) or - (k = NNF_NAME_AFTER) then + if (k = NNF_NAME_BEFORE) or (k = NNF_NAME_AFTER) then + begin + // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó + if texrec.Anim then begin - // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó: - if ByteBool(texture.Anim) then - begin // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ - isAnim := True; - ok := CreateAnimTexture(TexName, FileName, False) >= 0; - if not ok then - begin // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ - isAnim := False; - ok := CreateTexture(TexName, FileName, False) >= 0; - end; - end - else - begin // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ - isAnim := False; - ok := CreateTexture(TexName, FileName, False) >= 0; - if not ok then - begin // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ - isAnim := True; - ok := CreateAnimTexture(TexName, FileName, False) >= 0; - end; - end; - - // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè: - if ok then + // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ + isAnim := True; + ok := CreateAnimTexture(TexName, FileName, False) >= 0; + if not ok then begin - for c := 0 to High(Textures) do - if Textures[c].TextureName = TexName then - begin - SetLength(AddTextures, Length(AddTextures)+1); - AddTextures[High(AddTextures)].Texture := c; - AddTextures[High(AddTextures)].Anim := isAnim; - Break; - end; + // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ + isAnim := False; + ok := CreateTexture(TexName, FileName, False) >= 0; end; end + else + begin + // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ + isAnim := False; + ok := CreateTexture(TexName, FileName, False) >= 0; + if not ok then + begin + // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ + isAnim := True; + ok := CreateAnimTexture(TexName, FileName, False) >= 0; + end; + end; + + // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè + if ok then + begin + for c := 0 to High(Textures) do + begin + if (Textures[c].TextureName = TexName) then + begin + SetLength(AddTextures, Length(AddTextures)+1); + AddTextures[High(AddTextures)].Texture := c; + AddTextures[High(AddTextures)].Anim := isAnim; + break; + end; + end; + end; + end else + begin if k = NNF_NAME_EQUALS then - begin - // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî: - SetLength(AddTextures, Length(AddTextures)+1); - AddTextures[High(AddTextures)].Texture := panels[a].TextureNum; - AddTextures[High(AddTextures)].Anim := ByteBool(texture.Anim); - CurTex := High(AddTextures); - ok := True; - end + begin + // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî + SetLength(AddTextures, Length(AddTextures)+1); + //AddTextures[High(AddTextures)].Texture := _texnummap[rec.TextureNum]; //panels[a].TextureNum; + AddTextures[High(AddTextures)].Texture := rec.tagInt; //panels[a].TextureNum; + AddTextures[High(AddTextures)].Anim := texrec.Anim; + CurTex := High(AddTextures); + ok := true; + end else // NNF_NO_NAME - ok := False; + begin + ok := false; + end; + end; end; // while ok... - ok := True; + ok := true; end; // if ok - åñòü ñìåæíûå òåêñòóðû end; // if ok - ññûëàþòñÿ òðèããåðû if not ok then begin - // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó: + // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó SetLength(AddTextures, 1); - AddTextures[0].Texture := panels[a].TextureNum; - AddTextures[0].Anim := ByteBool(texture.Anim); + AddTextures[0].Texture := rec.tagInt; //panels[a].TextureNum; + AddTextures[0].Anim := false; + if (texrec <> nil) then AddTextures[0].Anim := texrec.Anim; CurTex := 0; end; //e_WriteLog(Format('panel #%d: TextureNum=%d; ht=%d; ht1=%d; atl=%d', [a, panels[a].TextureNum, High(_textures), High(Textures), High(AddTextures)]), MSG_NOTIFY); - // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð: - PanelID := CreatePanel(panels[a], AddTextures, CurTex, trigRef); + // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð + PanelID := CreatePanel(rec, AddTextures, CurTex, trigRef); + //e_LogWritefln('panel #%s of type %s got id #%s', [pannum, rec.PanelType, PanelID]); - // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID: - if TriggersTable <> nil then + // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID + if hashTextPan.get(pannum, b) then TriggersTable[b].texPanIdx := PanelID; + if hashLiftPan.get(pannum, b) then TriggersTable[b].LiftPanelIdx := PanelID; + if hashDoorPan.get(pannum, b) then TriggersTable[b].DoorPanelIdx := PanelID; + if hashShotPan.get(pannum, b) then TriggersTable[b].ShotPanelIdx := PanelID; + + (* + if (TriggersTable <> nil) then + begin for b := 0 to High(TriggersTable) do begin - // Òðèããåð äâåðè/ëèôòà: - if (TriggersTable[b].LiftPanel = a) or - (TriggersTable[b].DoorPanel = a) then - TTriggerData(triggers[b].DATA).PanelID := PanelID; - // Òðèããåð ñìåíû òåêñòóðû: - if TriggersTable[b].TexturePanel = a then - triggers[b].TexturePanel := PanelID; - // Òðèããåð "Òóðåëü": - if TriggersTable[b].ShotPanel = a then - TTriggerData(triggers[b].DATA).ShotPanelID := PanelID; + if (TriggersTable[b].texPan = rec) then TriggersTable[b].texPanIdx := PanelID; + if (TriggersTable[b].liftPan = rec) then TriggersTable[b].LiftPanelIdx := PanelID; + if (TriggersTable[b].doorPan = rec) then TriggersTable[b].DoorPanelIdx := PanelID; + if (TriggersTable[b].shotPan = rec) then TriggersTable[b].ShotPanelIdx := PanelID; + { + // Òðèããåð äâåðè/ëèôòà + if (TriggersTable[b].LiftPanel = pannum) or + (TriggersTable[b].DoorPanel = pannum) then + //TTriggerData(TriggersTable[b].trigrec.DATA).PanelID := PanelID; + TriggersTable[b].trigrec.trigRec.trigPanelID := PanelID; + // Òðèããåð ñìåíû òåêñòóðû + if TriggersTable[b].texPanIdx = pannum then + TriggersTable[b].trigrec.TexturePanel := PanelID; + // Òðèããåð "Òóðåëü" + if TriggersTable[b].ShotPanel = pannum then + TriggersTable[b].trigrec.trigRec.trigShotPanelID := PanelID; + } end; + end; + *) g_Game_StepLoading(); end; end; + (* + begin + for b := 0 to High(TriggersTable) do + begin + // Òðèããåð äâåðè/ëèôòà + if (TriggersTable[b].texPan <> nil) then e_LogWritefln('trigger #%s: textPan=%s; panidx=%s', [b, TriggersTable[b].texPanIdx, mapReader.panelIndex[TriggersTable[b].texPan]]); + if (TriggersTable[b].liftPan <> nil) then e_LogWritefln('trigger #%s: liftPan=%s; panidx=%s', [b, TriggersTable[b].LiftPanelIdx, mapReader.panelIndex[TriggersTable[b].liftPan]]); + if (TriggersTable[b].doorPan <> nil) then e_LogWritefln('trigger #%s: doorPan=%s; panidx=%s', [b, TriggersTable[b].DoorPanelIdx, mapReader.panelIndex[TriggersTable[b].doorPan]]); + if (TriggersTable[b].shotPan <> nil) then e_LogWritefln('trigger #%s: shotPan=%s; panidx=%s', [b, TriggersTable[b].ShotPanelIdx, mapReader.panelIndex[TriggersTable[b].shotPan]]); + end; + end; + *) + // create map grid, init other grids (for monsters, for example) e_WriteLog('Creating map grid', MSG_NOTIFY); mapCreateGrid(); - // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû: - if (triggers <> nil) and not gLoadGameMode then + // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû + if (triggers <> nil) and (panels <> nil) and (not gLoadGameMode) then begin - e_LogWritefln(' Creating triggers (%d)...', [Length(triggers)]); + e_LogWritefln(' Creating triggers (%d)...', [triggers.count]); g_Game_SetLoadingText(_lc[I_LOAD_CREATE_TRIGGERS], 0, False); - // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü: - for a := 0 to High(triggers) do + // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü + trignum := -1; + for rec in triggers do begin - if (triggers[a].TexturePanel <> -1) then + Inc(trignum); + if (TriggersTable[trignum].texPan <> nil) then b := TriggersTable[trignum].texPan.PanelType else b := 0; + if (TriggersTable[trignum].shotPan <> nil) then c := TriggersTable[trignum].shotPan.PanelType else c := 0; + (* + if (rec.TexturePanel <> -1) then begin - if (TriggersTable[a].TexturePanel < 0) or (TriggersTable[a].TexturePanel > High(panels)) then + { + if (TriggersTable[trignum].TexturePanel < 0) or (TriggersTable[trignum].TexturePanel >= panels.count) then begin e_WriteLog('error loading map: invalid panel index for trigger', MSG_FATALERROR); result := false; exit; end; - b := panels[TriggersTable[a].TexturePanel].PanelType; + } + //b := panels[TriggersTable[a].TexturePanel].PanelType; + //b := mapReader.panel[TriggersTable[trignum].texPanIdx].PanelType; + assert(TriggersTable[trignum].texPanIdx >= 0); + b := TriggersTable[trignum].texPanIdx; end else begin b := 0; end; - if (triggers[a].TriggerType = TRIGGER_SHOT) and (TTriggerData(triggers[a].DATA).ShotPanelID <> -1) then + e_LogWritefln('trigger #%s: type=%s; texPanIdx=%s; b=%s', [trignum, rec.TriggerType, TriggersTable[trignum].texPanIdx, b]); + if (rec.TriggerType = TRIGGER_SHOT) then e_LogWritefln(' SHOT: shotpanidx=%s', [rec.trigRec.trigShotPanelID]); + if (rec.TriggerType = TRIGGER_SHOT) and {(rec.trigRec.trigShotPanelID <> -1)} (TriggersTable[trignum].shotPan <> nil) then begin - c := panels[TriggersTable[a].ShotPanel].PanelType + //c := panels[TriggersTable[a].ShotPanel].PanelType; + //c := mapReader.panel[TriggersTable[trignum].ShotPanel].PanelType; + assert(TriggersTable[trignum].ShotPanelIdx >= 0); + c := TriggersTable[trignum].ShotPanelIdx; end else begin c := 0; end; - CreateTrigger(triggers[a], b, c); + *) + //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]); + CreateTrigger(rec, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx, Word(b), Word(c)); end; end; - // Çàãðóçêà ïðåäìåòîâ: + // Çàãðóçêà ïðåäìåòîâ e_WriteLog(' Loading items...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_ITEMS], 0, False); - items := GetItems(mapReader); - // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû: + // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû if (items <> nil) and not gLoadGameMode then begin e_WriteLog(' Spawning items...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_CREATE_ITEMS], 0, False); - for a := 0 to High(items) do - CreateItem(Items[a]); + for rec in items do CreateItem(rec); end; - // Çàãðóçêà îáëàñòåé: + // Çàãðóçêà îáëàñòåé e_WriteLog(' Loading areas...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_AREAS], 0, False); - areas := GetAreas(mapReader); - // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè: + // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè if areas <> nil then begin e_WriteLog(' Creating areas...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_CREATE_AREAS], 0, False); - for a := 0 to High(areas) do - CreateArea(areas[a]); + for rec in areas do CreateArea(rec); end; - // Çàãðóçêà ìîíñòðîâ: + // Çàãðóçêà ìîíñòðîâ e_WriteLog(' Loading monsters...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_MONSTERS], 0, False); - monsters := GetMonsters(mapReader); gTotalMonsters := 0; - // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ: + // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ if (monsters <> nil) and not gLoadGameMode then begin e_WriteLog(' Spawning monsters...', MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_CREATE_MONSTERS], 0, False); - for a := 0 to High(monsters) do - CreateMonster(monsters[a]); + for rec in monsters do CreateMonster(rec); end; - MapReader.Free(); + //MapReader.Free(); + gCurrentMap := mapReader; + mapReader := nil; - // Çàãðóçêà íåáà: + // Çàãðóçêà íåáà if gMapInfo.SkyName <> '' then begin e_WriteLog(' Loading sky: ' + gMapInfo.SkyName, MSG_NOTIFY); @@ -1956,7 +2029,7 @@ begin g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s])); end; - // Çàãðóçêà ìóçûêè: + // Çàãðóçêà ìóçûêè ok := False; if gMapInfo.MusicName <> '' then begin @@ -1978,7 +2051,7 @@ begin g_FatalError(Format(_lc[I_GAME_ERROR_MUSIC], [s])); end; - // Îñòàëüíûå óñòàíâêè: + // Îñòàëüíûå óñòàíâêè CreateDoorMap(); CreateLiftMap(); @@ -1986,11 +2059,10 @@ begin g_Weapon_Init(); g_Monsters_Init(); - // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé: - if not gLoadGameMode then - g_GFX_Init(); + // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé: + if not gLoadGameMode then g_GFX_Init(); - // Ñáðîñ ëîêàëüíûõ ìàññèâîâ: + // Ñáðîñ ëîêàëüíûõ ìàññèâîâ: _textures := nil; panels := nil; items := nil; @@ -1999,16 +2071,23 @@ begin TriggersTable := nil; AddTextures := nil; - // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà: + // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà: if ok and (not gLoadGameMode) then - begin - gMusic.SetByName(gMapInfo.MusicName); - gMusic.Play(); - end + begin + gMusic.SetByName(gMapInfo.MusicName); + gMusic.Play(); + end else + begin gMusic.SetByName(''); + end; finally sfsGCEnable(); // enable releasing unused volumes + mapReader.Free(); + hashTextPan.Free(); + hashLiftPan.Free(); + hashDoorPan.Free(); + hashShotPan.Free(); end; e_WriteLog('Done loading map.', MSG_NOTIFY); @@ -2019,7 +2098,7 @@ function g_Map_GetMapInfo(Res: String): TMapInfo; var WAD: TWADFile; MapReader: TDynRecord; - Header: TMapHeaderRec_1; + //Header: TMapHeaderRec_1; FileName: String; Data: Pointer; Len: Integer; @@ -2068,26 +2147,31 @@ begin FreeMem(Data); //MapReader.Free(); - if (mapReader <> nil) then Header := GetMapHeader(mapReader) else FillChar(Header, sizeof(Header), 0); - MapReader.Free(); + //if (mapReader <> nil) then Header := GetMapHeader(mapReader) else FillChar(Header, sizeof(Header), 0); + //MapReader.Free(); - if (Header.Width > 0) and (Header.Height > 0) then + if (mapReader.Width > 0) and (mapReader.Height > 0) then begin - Result.Name := Header.MapName; - Result.Description := Header.MapDescription; + Result.Name := mapReader.MapName; + Result.Description := mapReader.MapDesc; + Result.Map := Res; + Result.Author := mapReader.MapAuthor; + Result.Height := mapReader.Height; + Result.Width := mapReader.Width; end else begin g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True); - ZeroMemory(@Header, SizeOf(Header)); + //ZeroMemory(@Header, SizeOf(Header)); Result.Name := _lc[I_GAME_ERROR_MAP_SELECT]; Result.Description := _lc[I_GAME_ERROR_MAP_SELECT]; + Result.Map := Res; + Result.Author := ''; + Result.Height := 0; + Result.Width := 0; end; - Result.Map := Res; - Result.Author := Header.MapAuthor; - Result.Height := Header.Height; - Result.Width := Header.Width; + mapReader.Free(); end; function g_Map_GetMapsList(WADName: string): SArray; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 936141a..f77bdca 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -2517,10 +2517,10 @@ begin begin if SPlaying then begin - if Data.Local then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0) + if trigData.trigLocal then + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0) else - Sound.PlayPanVolume((Data.Pan-127.0)/128.0, Data.Volume/255.0); + Sound.PlayPanVolume((trigData.trigPan-127.0)/128.0, trigData.trigVolume/255.0); Sound.SetPosition(SPos); end else diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index c46cf8c..5eec8e7 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -19,7 +19,7 @@ unit g_panel; interface uses - MAPDEF, BinEditor, g_textures; + MAPDEF, BinEditor, g_textures, xdynrec; type TAddTextureArray = Array of @@ -63,7 +63,7 @@ type tag: Integer; // used in coldets and such; sorry proxyId: Integer; // proxy id in map grid (DO NOT USE!) - constructor Create(PanelRec: TPanelRec_1; + constructor Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; var Textures: TLevelTextureArray); @@ -102,7 +102,7 @@ const { T P a n e l : } -constructor TPanel.Create(PanelRec: TPanelRec_1; +constructor TPanel.Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; var Textures: TLevelTextureArray); diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index c327fdb..be680ec 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -20,7 +20,7 @@ interface uses MAPDEF, e_graphics, g_basic, g_sound, - BinEditor; + BinEditor, xdynrec; type TActivator = record @@ -60,7 +60,11 @@ type ShotAmmoCount: Word; ShotReloadTime: Integer; - Data: TTriggerData; + trigShotPanelId: Integer; + trigPanelId: Integer; + + //TrigData: TTriggerData; + trigData: TDynRecord; // triggerdata; owned by trigger end; function g_Triggers_Create(Trigger: TTrigger): DWORD; @@ -631,28 +635,28 @@ end; procedure MakeShot(var Trigger: TTrigger; wx, wy, dx, dy: Integer; TargetUID: Word); begin with Trigger do - if (Data.ShotAmmo = 0) or - ((Data.ShotAmmo > 0) and (ShotAmmoCount > 0)) then + if (trigData.trigShotAmmo = 0) or + ((trigData.trigShotAmmo > 0) and (ShotAmmoCount > 0)) then begin - if (Data.ShotPanelID <> -1) and (ShotPanelTime = 0) then + if (trigShotPanelID <> -1) and (ShotPanelTime = 0) then begin - g_Map_SwitchTexture(ShotPanelType, Data.ShotPanelID); + g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); ShotPanelTime := 4; // òèêîâ íà âñïûøêó âûñòðåëà end; - if Data.ShotIntSight > 0 then + if trigData.trigShotIntSight > 0 then ShotSightTimeout := 180; // ~= 5 ñåêóíä if ShotAmmoCount > 0 then Dec(ShotAmmoCount); - dx := dx + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy); - dy := dy + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy); + dx := dx + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); + dy := dy + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); - tr_SpawnShot(Data.ShotType, wx, wy, dx, dy, Data.ShotSound, TargetUID); + tr_SpawnShot(trigData.trigShotType, wx, wy, dx, dy, trigData.trigShotSound, TargetUID); end else - if (Data.ShotIntReload > 0) and (ShotReloadTime = 0) then - ShotReloadTime := Data.ShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè + if (trigData.trigShotIntReload > 0) and (ShotReloadTime = 0) then + ShotReloadTime := trigData.trigShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè end; procedure tr_MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean); @@ -959,11 +963,11 @@ begin begin if TriggerType <> TRIGGER_SHOT then Exit; - Result := (Data.ShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0) + Result := (trigData.trigShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0) or g_Obj_Collide(X, Y, Width, Height, Obj); - if Result and (Data.ShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then - Result := g_TraceVector(Data.ShotPos.X, - Data.ShotPos.Y, + if Result and (trigData.trigShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then + Result := g_TraceVector(trigData.trigShotPos.X, + trigData.trigShotPos.Y, Obj^.X + Obj^.Rect.X + (Obj^.Rect.Width div 2), Obj^.Y + Obj^.Rect.Y + (Obj^.Rect.Height div 2)); end; @@ -1045,7 +1049,7 @@ begin g_Sound_PlayEx('SOUND_GAME_SWITCH0'); if g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH0'); gExitByTrigger := True; - g_Game_ExitLevel(Data.MapName); + g_Game_ExitLevel(trigData.trigMapName); TimeOut := 18; Result := True; @@ -1055,37 +1059,37 @@ begin TRIGGER_TELEPORT: begin Result := tr_Teleport(ActivateUID, - Data.TargetPoint.X, Data.TargetPoint.Y, - Data.TlpDir, Data.silent_teleport, - Data.d2d_teleport); + trigData.trigTargetPoint.X, trigData.trigTargetPoint.Y, + trigData.trigTlpDir, trigData.trigsilent_teleport, + trigData.trigd2d_teleport); TimeOut := 0; end; TRIGGER_OPENDOOR: begin - Result := tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_CLOSEDOOR: begin - Result := tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_DOOR, TRIGGER_DOOR5: begin - if Data.PanelID <> -1 then + if trigPanelID <> -1 then begin - if gWalls[Data.PanelID].Enabled then + if gWalls[trigPanelID].Enabled then begin - Result := tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if TriggerType = TRIGGER_DOOR5 then DoorTime := 180; end else - Result := tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if Result then TimeOut := 18; @@ -1094,7 +1098,7 @@ begin TRIGGER_CLOSETRAP, TRIGGER_TRAP: begin - tr_CloseTrap(Data.PanelID, Data.NoSound, Data.d2d_doors); + tr_CloseTrap(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if TriggerType = TRIGGER_TRAP then begin @@ -1115,7 +1119,7 @@ begin PressCount := PressCount + 1; if PressTime = -1 then - PressTime := Data.Wait; + PressTime := trigData.trigWait; if coolDown then TimeOut := 18 @@ -1139,10 +1143,10 @@ begin TRIGGER_LIFTUP: begin - Result := tr_SetLift(Data.PanelID, 0, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 0, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -1155,10 +1159,10 @@ begin TRIGGER_LIFTDOWN: begin - Result := tr_SetLift(Data.PanelID, 1, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 1, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -1171,13 +1175,13 @@ begin TRIGGER_LIFT: begin - Result := tr_SetLift(Data.PanelID, 3, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 3, trigData.trigNoSound, trigData.trigd2d_doors); if Result then begin TimeOut := 18; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -1191,7 +1195,7 @@ begin TRIGGER_TEXTURE: begin - if ByteBool(Data.ActivateOnce) then + if ByteBool(trigData.trigActivateOnce) then begin Enabled := False; TriggerType := TRIGGER_NONE; @@ -1202,7 +1206,7 @@ begin else TimeOut := 0; - animonce := Data.AnimOnce; + animonce := trigData.trigAnimOnce; Result := True; end; @@ -1210,17 +1214,17 @@ begin begin if Sound <> nil then begin - if Data.SoundSwitch and Sound.IsPlaying() then + if trigData.trigSoundSwitch and Sound.IsPlaying() then begin // Íóæíî âûêëþ÷èòü, åñëè èãðàë Sound.Stop(); SoundPlayCount := 0; Result := True; end else // (not Data.SoundSwitch) or (not Sound.IsPlaying()) - if (Data.PlayCount > 0) or (not Sound.IsPlaying()) then + if (trigData.trigPlayCount > 0) or (not Sound.IsPlaying()) then begin - if Data.PlayCount > 0 then - SoundPlayCount := Data.PlayCount + if trigData.trigPlayCount > 0 then + SoundPlayCount := trigData.trigPlayCount else // 0 - èãðàåì áåñêîíå÷íî SoundPlayCount := 1; Result := True; @@ -1230,10 +1234,10 @@ begin end; TRIGGER_SPAWNMONSTER: - if (Data.MonType in [MONSTER_DEMON..MONSTER_MAN]) then + if (trigData.trigMonType in [MONSTER_DEMON..MONSTER_MAN]) then begin Result := False; - if (Data.MonDelay > 0) and (actType <> ACTIVATE_CUSTOM) then + if (trigData.trigMonDelay > 0) and (actType <> ACTIVATE_CUSTOM) then begin AutoSpawn := not AutoSpawn; SpawnCooldown := 0; @@ -1241,34 +1245,34 @@ begin Result := True; end; - if ((Data.MonDelay = 0) and (actType <> ACTIVATE_CUSTOM)) - or ((Data.MonDelay > 0) and (actType = ACTIVATE_CUSTOM)) then - for k := 1 to Data.MonCount do + if ((trigData.trigMonDelay = 0) and (actType <> ACTIVATE_CUSTOM)) + or ((trigData.trigMonDelay > 0) and (actType = ACTIVATE_CUSTOM)) then + for k := 1 to trigData.trigMonCount do begin - if (actType = ACTIVATE_CUSTOM) and (Data.MonDelay > 0) then - SpawnCooldown := Data.MonDelay; - if (Data.MonMax > 0) and (SpawnedCount >= Data.MonMax) then + if (actType = ACTIVATE_CUSTOM) and (trigData.trigMonDelay > 0) then + SpawnCooldown := trigData.trigMonDelay; + if (trigData.trigMonMax > 0) and (SpawnedCount >= trigData.trigMonMax) then Break; - mon := g_Monsters_Create(Data.MonType, - Data.MonPos.X, Data.MonPos.Y, - TDirection(Data.MonDir), True); + mon := g_Monsters_Create(trigData.trigMonType, + trigData.trigMonPos.X, trigData.trigMonPos.Y, + TDirection(trigData.trigMonDir), True); Result := True; // Çäîðîâüå: - if (Data.MonHealth > 0) then - mon.SetHealth(Data.MonHealth); + if (trigData.trigMonHealth > 0) then + mon.SetHealth(trigData.trigMonHealth); // Óñòàíàâëèâàåì ïîâåäåíèå: - mon.MonsterBehaviour := Data.MonBehav; + mon.MonsterBehaviour := trigData.trigMonBehav; mon.FNoRespawn := True; if g_Game_IsNet then MH_SEND_MonsterSpawn(mon.UID); // Èäåì èñêàòü öåëü, åñëè íàäî: - if Data.MonActive then + if trigData.trigMonActive then mon.WakeUp(); - if Data.MonType <> MONSTER_BARREL then Inc(gTotalMonsters); + if trigData.trigMonType <> MONSTER_BARREL then Inc(gTotalMonsters); if g_Game_IsNet then begin @@ -1276,18 +1280,18 @@ begin gMonstersSpawned[High(gMonstersSpawned)] := mon.UID; end; - if Data.MonMax > 0 then + if trigData.trigMonMax > 0 then begin mon.SpawnTrigger := ID; Inc(SpawnedCount); end; - case Data.MonEffect of + case trigData.trigMonEffect of EFFECT_TELEPORT: begin if g_Frames_Get(FramesID, 'FRAMES_TELEPORT') then begin Anim := TAnimation.Create(FramesID, False, 3); - g_Sound_PlayExAt('SOUND_GAME_TELEPORT', Data.MonPos.X, Data.MonPos.Y); + g_Sound_PlayExAt('SOUND_GAME_TELEPORT', trigData.trigMonPos.X, trigData.trigMonPos.Y); g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32, mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-32, Anim); Anim.Free(); @@ -1301,7 +1305,7 @@ begin if g_Frames_Get(FramesID, 'FRAMES_ITEM_RESPAWN') then begin Anim := TAnimation.Create(FramesID, False, 4); - g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', Data.MonPos.X, Data.MonPos.Y); + g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', trigData.trigMonPos.X, trigData.trigMonPos.Y); g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-16, mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-16, Anim); Anim.Free(); @@ -1315,7 +1319,7 @@ begin if g_Frames_Get(FramesID, 'FRAMES_FIRE') then begin Anim := TAnimation.Create(FramesID, False, 4); - g_Sound_PlayExAt('SOUND_FIRE', Data.MonPos.X, Data.MonPos.Y); + g_Sound_PlayExAt('SOUND_FIRE', trigData.trigMonPos.X, trigData.trigMonPos.Y); g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32, mon.Obj.Y+mon.Obj.Rect.Y+mon.Obj.Rect.Height-128, Anim); Anim.Free(); @@ -1343,10 +1347,10 @@ begin end; TRIGGER_SPAWNITEM: - if (Data.ItemType in [ITEM_MEDKIT_SMALL..ITEM_MAX]) then + if (trigData.trigItemType in [ITEM_MEDKIT_SMALL..ITEM_MAX]) then begin Result := False; - if (Data.ItemDelay > 0) and (actType <> ACTIVATE_CUSTOM) then + if (trigData.trigItemDelay > 0) and (actType <> ACTIVATE_CUSTOM) then begin AutoSpawn := not AutoSpawn; SpawnCooldown := 0; @@ -1354,36 +1358,36 @@ begin Result := True; end; - if ((Data.ItemDelay = 0) and (actType <> ACTIVATE_CUSTOM)) - or ((Data.ItemDelay > 0) and (actType = ACTIVATE_CUSTOM)) then - if (not Data.ItemOnlyDM) or + if ((trigData.trigItemDelay = 0) and (actType <> ACTIVATE_CUSTOM)) + or ((trigData.trigItemDelay > 0) and (actType = ACTIVATE_CUSTOM)) then + if (not trigData.trigItemOnlyDM) or (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF]) then - for k := 1 to Data.ItemCount do + for k := 1 to trigData.trigItemCount do begin - if (actType = ACTIVATE_CUSTOM) and (Data.ItemDelay > 0) then - SpawnCooldown := Data.ItemDelay; - if (Data.ItemMax > 0) and (SpawnedCount >= Data.ItemMax) then + if (actType = ACTIVATE_CUSTOM) and (trigData.trigItemDelay > 0) then + SpawnCooldown := trigData.trigItemDelay; + if (trigData.trigItemMax > 0) and (SpawnedCount >= trigData.trigItemMax) then Break; - iid := g_Items_Create(Data.ItemPos.X, Data.ItemPos.Y, - Data.ItemType, Data.ItemFalls, False, True); + iid := g_Items_Create(trigData.trigItemPos.X, trigData.trigItemPos.Y, + trigData.trigItemType, trigData.trigItemFalls, False, True); Result := True; - if Data.ItemMax > 0 then + if trigData.trigItemMax > 0 then begin it := g_Items_ByIdx(iid); it.SpawnTrigger := ID; Inc(SpawnedCount); end; - case Data.ItemEffect of + case trigData.trigItemEffect of EFFECT_TELEPORT: begin it := g_Items_ByIdx(iid); if g_Frames_Get(FramesID, 'FRAMES_TELEPORT') then begin Anim := TAnimation.Create(FramesID, False, 3); - g_Sound_PlayExAt('SOUND_GAME_TELEPORT', Data.ItemPos.X, Data.ItemPos.Y); + g_Sound_PlayExAt('SOUND_GAME_TELEPORT', trigData.trigItemPos.X, trigData.trigItemPos.Y); g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32, it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-32, Anim); Anim.Free(); @@ -1398,7 +1402,7 @@ begin if g_Frames_Get(FramesID, 'FRAMES_ITEM_RESPAWN') then begin Anim := TAnimation.Create(FramesID, False, 4); - g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', Data.ItemPos.X, Data.ItemPos.Y); + g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', trigData.trigItemPos.X, trigData.trigItemPos.Y); g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-16, it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-16, Anim); Anim.Free(); @@ -1413,7 +1417,7 @@ begin if g_Frames_Get(FramesID, 'FRAMES_FIRE') then begin Anim := TAnimation.Create(FramesID, False, 4); - g_Sound_PlayExAt('SOUND_FIRE', Data.ItemPos.X, Data.ItemPos.Y); + g_Sound_PlayExAt('SOUND_FIRE', trigData.trigItemPos.X, trigData.trigItemPos.Y); g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32, it.Obj.Y+it.Obj.Rect.Y+it.Obj.Rect.Height-128, Anim); Anim.Free(); @@ -1441,14 +1445,14 @@ begin TRIGGER_MUSIC: begin // Ìåíÿåì ìóçûêó, åñëè åñòü íà ÷òî: - if (Trigger.Data.MusicName <> '') then + if (Trigger.trigData.trigMusicName <> '') then begin - gMusic.SetByName(Trigger.Data.MusicName); + gMusic.SetByName(Trigger.trigData.trigMusicName); gMusic.SpecPause := True; gMusic.Play(); end; - if Trigger.Data.MusicAction = 1 then + if Trigger.trigData.trigMusicAction = 1 then begin // Âêëþ÷èòü if gMusic.SpecPause then // Áûëà íà ïàóçå => èãðàòü gMusic.SpecPause := False @@ -1471,11 +1475,11 @@ begin TRIGGER_PUSH: begin - pAngle := -DegToRad(Data.PushAngle); + pAngle := -DegToRad(trigData.trigPushAngle); Result := tr_Push(ActivateUID, - Floor(Cos(pAngle)*Data.PushForce), - Floor(Sin(pAngle)*Data.PushForce), - Data.ResetVel); + Floor(Cos(pAngle)*trigData.trigPushForce), + Floor(Sin(pAngle)*trigData.trigPushForce), + trigData.trigResetVel); TimeOut := 0; end; @@ -1483,106 +1487,106 @@ begin begin Result := False; // Ïðèáàâèòü èëè îòíÿòü î÷êî - if (Data.ScoreAction in [0..1]) and (Data.ScoreCount > 0) then + if (trigData.trigScoreAction in [0..1]) and (trigData.trigScoreCount > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäå - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreAction = 0) and (Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) - or ((Data.ScoreAction = 0) and (Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) + or ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then begin - Inc(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Scores + Inc(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Scores - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+r'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+r'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+re'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+re'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_RED); end; end; - if ((Data.ScoreAction = 1) and (Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) - or ((Data.ScoreAction = 1) and (Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) + or ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then begin - Dec(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Fouls + Dec(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Fouls - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-r'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-r'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-re'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-re'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, -TEAM_RED); end; end; - if ((Data.ScoreAction = 0) and (Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) - or ((Data.ScoreAction = 0) and (Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) + or ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then begin - Inc(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Scores + Inc(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Scores - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+b'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+b'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+be'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+be'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_BLUE); end; end; - if ((Data.ScoreAction = 1) and (Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) - or ((Data.ScoreAction = 1) and (Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) + or ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then begin - Dec(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Fouls + Dec(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Fouls - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-b'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-b'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-be'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-be'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then @@ -1592,74 +1596,74 @@ begin Result := (p.Team = TEAM_RED) or (p.Team = TEAM_BLUE); end; // Êàêîé-òî êîíêðåòíîé êîìàíäå - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if (Data.ScoreAction = 0) and (Data.ScoreTeam = 2) then + if (trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 2) then begin - Inc(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Scores + Inc(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Scores - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_RED], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_RED], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '+tr'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '+tr'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_RED); end; end; - if (Data.ScoreAction = 1) and (Data.ScoreTeam = 2) then + if (trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 2) then begin - Dec(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Fouls + Dec(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Fouls - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_RED], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_RED], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '-tr'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '-tr'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, -TEAM_RED); end; end; - if (Data.ScoreAction = 0) and (Data.ScoreTeam = 3) then + if (trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 3) then begin - Inc(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Scores + Inc(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Scores - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_BLUE], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_BLUE], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '+tb'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '+tb'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_BLUE); end; end; - if (Data.ScoreAction = 1) and (Data.ScoreTeam = 3) then + if (trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 3) then begin - Dec(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Fouls + Dec(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Fouls - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_BLUE], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_BLUE], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '-tb'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '-tb'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then @@ -1670,20 +1674,20 @@ begin end; end; // Âûèãðûø - if (Data.ScoreAction = 2) and (gGameSettings.GoalLimit > 0) then + if (trigData.trigScoreAction = 2) and (gGameSettings.GoalLimit > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäû - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) // Red Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) // Red Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_OWN], [p.Name, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1697,14 +1701,14 @@ begin Result := True; end; - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Blue Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Blue Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_OWN], [p.Name, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1720,15 +1724,15 @@ begin end; end; // Êàêîé-òî êîíêðåòíîé êîìàíäû - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if Data.ScoreTeam = 2 then // Red Wins + if trigData.trigScoreTeam = 2 then // Red Wins if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; Result := True; end; - if Data.ScoreTeam = 3 then // Blue Wins + if trigData.trigScoreTeam = 3 then // Blue Wins if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; @@ -1737,20 +1741,20 @@ begin end; end; // Ïðîèãðûø - if (Data.ScoreAction = 3) and (gGameSettings.GoalLimit > 0) then + if (trigData.trigScoreAction = 3) and (gGameSettings.GoalLimit > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäû - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Red Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Red Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_ENEMY], [p.Name, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1764,14 +1768,14 @@ begin Result := True; end; - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) // Blue Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) // Blue Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_ENEMY], [p.Name, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1787,15 +1791,15 @@ begin end; end; // Êàêîé-òî êîíêðåòíîé êîìàíäû - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if Data.ScoreTeam = 3 then // Red Wins + if trigData.trigScoreTeam = 3 then // Red Wins if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; Result := True; end; - if Data.ScoreTeam = 2 then // Blue Wins + if trigData.trigScoreTeam = 2 then // Blue Wins if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; @@ -1815,8 +1819,8 @@ begin TRIGGER_MESSAGE: begin - Result := tr_Message(Data.MessageKind, Data.MessageText, - Data.MessageSendTo, Data.MessageTime, + Result := tr_Message(trigData.trigMessageKind, trigData.trigMessageText, + trigData.trigMessageSendTo, trigData.trigMessageTime, ActivateUID); TimeOut := 18; end; @@ -1847,7 +1851,7 @@ begin end else begin // Óæå âèäåëè åãî // Åñëè èíòåðâàë îòêëþ÷¸í, íî îí âñ¸ åù¸ â çîíå ïîðàæåíèÿ, äà¸ì åìó âðåìÿ - if (Data.DamageInterval = 0) and (Activators[k].TimeOut > 0) then + if (trigData.trigDamageInterval = 0) and (Activators[k].TimeOut > 0) then Activators[k].TimeOut := 65535; // Òàéìàóò ïðîø¸ë - ðàáîòàåì Result := Activators[k].TimeOut = 0; @@ -1864,12 +1868,12 @@ begin Exit; // Íàíîñèì óðîí èãðîêó - if (TriggerType = TRIGGER_DAMAGE) and (Data.DamageValue > 0) then - p.Damage(Data.DamageValue, 0, 0, 0, HIT_SOME); + if (TriggerType = TRIGGER_DAMAGE) and (trigData.trigDamageValue > 0) then + p.Damage(trigData.trigDamageValue, 0, 0, 0, HIT_SOME); // Ëå÷èì èãðîêà - if (TriggerType = TRIGGER_HEALTH) and (Data.HealValue > 0) then - if p.Heal(Data.HealValue, not Data.HealMax) and (not Data.HealSilent) then + if (TriggerType = TRIGGER_HEALTH) and (trigData.trigHealValue > 0) then + if p.Heal(trigData.trigHealValue, not trigData.trigHealMax) and (not trigData.trigHealSilent) then begin g_Sound_PlayExAt('SOUND_ITEM_GETITEM', p.Obj.X, p.Obj.Y); if g_Game_IsServer and g_Game_IsNet then @@ -1884,12 +1888,12 @@ begin Exit; // Íàíîñèì óðîí ìîíñòðó - if (TriggerType = TRIGGER_DAMAGE) and (Data.DamageValue > 0) then - m.Damage(Data.DamageValue, 0, 0, 0, HIT_SOME); + if (TriggerType = TRIGGER_DAMAGE) and (trigData.trigDamageValue > 0) then + m.Damage(trigData.trigDamageValue, 0, 0, 0, HIT_SOME); // Ëå÷èì ìîíñòðà - if (TriggerType = TRIGGER_HEALTH) and (Data.HealValue > 0) then - if m.Heal(Data.HealValue) and (not Data.HealSilent) then + if (TriggerType = TRIGGER_HEALTH) and (trigData.trigHealValue > 0) then + if m.Heal(trigData.trigHealValue) and (not trigData.trigHealSilent) then begin g_Sound_PlayExAt('SOUND_ITEM_GETITEM', m.Obj.X, m.Obj.Y); if g_Game_IsServer and g_Game_IsNet then @@ -1899,9 +1903,9 @@ begin end; // Íàçíà÷àåì âðåìÿ ñëåäóþùåãî âîçäåéñòâèÿ if TriggerType = TRIGGER_DAMAGE then - idx := Data.DamageInterval + idx := trigData.trigDamageInterval else - idx := Data.HealInterval; + idx := trigData.trigHealInterval; if coolDown then if idx > 0 then Activators[k].TimeOut := idx @@ -1918,16 +1922,16 @@ begin Exit; // put this at the beginning so it doesn't trigger itself - TimeOut := Data.ShotWait + 1; + TimeOut := trigData.trigShotWait + 1; - wx := Data.ShotPos.X; - wy := Data.ShotPos.Y; - pAngle := -DegToRad(Data.ShotAngle); + wx := trigData.trigShotPos.X; + wy := trigData.trigShotPos.Y; + pAngle := -DegToRad(trigData.trigShotAngle); xd := wx + Round(Cos(pAngle) * 32.0); yd := wy + Round(Sin(pAngle) * 32.0); TargetUID := 0; - case Data.ShotTarget of + case trigData.trigShotTarget of TRIGGER_SHOT_TARGET_MON: // monsters //TODO: accelerate this! g_Mons_ForEachAlive(monsShotTarget); @@ -2007,25 +2011,25 @@ begin end; else begin - if (Data.ShotTarget <> TRIGGER_SHOT_TARGET_NONE) or - (Data.ShotType <> TRIGGER_SHOT_REV) then + if (trigData.trigShotTarget <> TRIGGER_SHOT_TARGET_NONE) or + (trigData.trigShotType <> TRIGGER_SHOT_REV) then TargetUID := ActivateUID; end; end; - if (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) or - ((Data.ShotTarget > TRIGGER_SHOT_TARGET_NONE) and (TargetUID = 0)) then + if (trigData.trigShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) or + ((trigData.trigShotTarget > TRIGGER_SHOT_TARGET_NONE) and (TargetUID = 0)) then begin Result := True; - if (Data.ShotIntSight = 0) or - (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or + if (trigData.trigShotIntSight = 0) or + (trigData.trigShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID = ShotSightTarget) then MakeShot(Trigger, wx, wy, xd, yd, TargetUID) else begin - ShotSightTime := Data.ShotIntSight; + ShotSightTime := trigData.trigShotIntSight; ShotSightTargetN := TargetUID; - if Data.ShotType = TRIGGER_SHOT_BFG then + if trigData.trigShotType = TRIGGER_SHOT_BFG then begin g_Sound_PlayExAt('SOUND_WEAPON_STARTFIREBFG', wx, wy); if g_Game_IsNet and g_Game_IsServer then @@ -2037,11 +2041,11 @@ begin TRIGGER_EFFECT: begin - idx := Data.FXCount; + idx := trigData.trigFXCount; while idx > 0 do begin - case Data.FXPos of + case trigData.trigFXPos of TRIGGER_EFFECT_POS_CENTER: begin wx := X + Width div 2; @@ -2057,18 +2061,18 @@ begin wy := Y + Height div 2; end; end; - xd := Data.FXVelX; - yd := Data.FXVelY; - if Data.FXSpreadL > 0 then xd := xd - Random(Data.FXSpreadL + 1); - if Data.FXSpreadR > 0 then xd := xd + Random(Data.FXSpreadR + 1); - if Data.FXSpreadU > 0 then yd := yd - Random(Data.FXSpreadU + 1); - if Data.FXSpreadD > 0 then yd := yd + Random(Data.FXSpreadD + 1); + xd := trigData.trigFXVelX; + yd := trigData.trigFXVelY; + if trigData.trigFXSpreadL > 0 then xd := xd - Random(trigData.trigFXSpreadL + 1); + if trigData.trigFXSpreadR > 0 then xd := xd + Random(trigData.trigFXSpreadR + 1); + if trigData.trigFXSpreadU > 0 then yd := yd - Random(trigData.trigFXSpreadU + 1); + if trigData.trigFXSpreadD > 0 then yd := yd + Random(trigData.trigFXSpreadD + 1); tr_MakeEffect(wx, wy, xd, yd, - Data.FXType, Data.FXSubType, - Data.FXColorR, Data.FXColorG, Data.FXColorB, True, False); + trigData.trigFXType, trigData.trigFXSubType, + trigData.trigFXColorR, trigData.trigFXColorG, trigData.trigFXColorB, True, False); Dec(idx); end; - TimeOut := Data.FXWait; + TimeOut := trigData.trigFXWait; end; end; end; @@ -2127,30 +2131,30 @@ begin // Çàãðóæàåì çâóê, åñëè ýòî òðèããåð "Çâóê": if (Trigger.TriggerType = TRIGGER_SOUND) and - (Trigger.Data.SoundName <> '') then + (Trigger.trigData.trigSoundName <> '') then begin // Åùå íåò òàêîãî çâóêà: - if not g_Sound_Exists(Trigger.Data.SoundName) then + if not g_Sound_Exists(Trigger.trigData.trigSoundName) then begin - fn := g_ExtractWadName(Trigger.Data.SoundName); + fn := g_ExtractWadName(Trigger.trigData.trigSoundName); if fn = '' then begin // Çâóê â ôàéëå ñ êàðòîé mapw := g_ExtractWadName(gMapInfo.Map); - fn := mapw+':'+g_ExtractFilePathName(Trigger.Data.SoundName); + fn := mapw+':'+g_ExtractFilePathName(Trigger.trigData.trigSoundName); end else // Çâóê â îòäåëüíîì ôàéëå - fn := GameDir + '/wads/' + Trigger.Data.SoundName; + fn := GameDir + '/wads/' + Trigger.trigData.trigSoundName; - if not g_Sound_CreateWADEx(Trigger.Data.SoundName, fn) then - g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.Data.SoundName])); + if not g_Sound_CreateWADEx(Trigger.trigData.trigSoundName, fn) then + g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.trigData.trigSoundName])); end; // Ñîçäàåì îáúåêò çâóêà: with gTriggers[find_id] do begin Sound := TPlayableSound.Create(); - if not Sound.SetByName(Trigger.Data.SoundName) then + if not Sound.SetByName(Trigger.trigData.trigSoundName) then begin Sound.Free(); Sound := nil; @@ -2160,23 +2164,23 @@ begin // Çàãðóæàåì ìóçûêó, åñëè ýòî òðèããåð "Ìóçûêà": if (Trigger.TriggerType = TRIGGER_MUSIC) and - (Trigger.Data.MusicName <> '') then + (Trigger.trigData.trigMusicName <> '') then begin // Åùå íåò òàêîé ìóçûêè: - if not g_Sound_Exists(Trigger.Data.MusicName) then + if not g_Sound_Exists(Trigger.trigData.trigMusicName) then begin - fn := g_ExtractWadName(Trigger.Data.MusicName); + fn := g_ExtractWadName(Trigger.trigData.trigMusicName); if fn = '' then begin // Ìóçûêà â ôàéëå ñ êàðòîé mapw := g_ExtractWadName(gMapInfo.Map); - fn := mapw+':'+g_ExtractFilePathName(Trigger.Data.MusicName); + fn := mapw+':'+g_ExtractFilePathName(Trigger.trigData.trigMusicName); end else // Ìóçûêà â ôàéëå ñ êàðòîé - fn := GameDir+'/wads/'+Trigger.Data.MusicName; + fn := GameDir+'/wads/'+Trigger.trigData.trigMusicName; - if not g_Sound_CreateWADEx(Trigger.Data.MusicName, fn, True) then - g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.Data.MusicName])); + if not g_Sound_CreateWADEx(Trigger.trigData.trigMusicName, fn, True) then + g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.trigData.trigMusicName])); end; end; @@ -2189,7 +2193,7 @@ begin ShotSightTimeout := 0; ShotSightTarget := 0; ShotSightTargetN := 0; - ShotAmmoCount := Trigger.Data.ShotAmmo; + ShotAmmoCount := Trigger.trigData.trigShotAmmo; ShotReloadTime := 0; end; @@ -2249,7 +2253,7 @@ begin else Continue; // Ñ÷èòàåì, ÷òî îáúåêò ïîêèíóë çîíó äåéñòâèÿ òðèããåðà - if (Data.DamageInterval = 0) and (Activators[b].TimeOut < 65530) then + if (trigData.trigDamageInterval = 0) and (Activators[b].TimeOut < 65530) then Activators[b].TimeOut := 0; end; @@ -2258,13 +2262,13 @@ begin if SpawnCooldown = 0 then begin // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ìîíñòðà: - if (TriggerType = TRIGGER_SPAWNMONSTER) and (Data.MonDelay > 0) then + if (TriggerType = TRIGGER_SPAWNMONSTER) and (trigData.trigMonDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); end; // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ïðåäìåò: - if (TriggerType = TRIGGER_SPAWNITEM) and (Data.ItemDelay > 0) then + if (TriggerType = TRIGGER_SPAWNITEM) and (trigData.trigItemDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); @@ -2279,7 +2283,7 @@ begin begin Dec(ShotPanelTime); if ShotPanelTime = 0 then - g_Map_SwitchTexture(ShotPanelType, Data.ShotPanelID); + g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); end; if ShotSightTime > 0 then begin @@ -2297,7 +2301,7 @@ begin begin Dec(ShotReloadTime); if ShotReloadTime = 0 then - ShotAmmoCount := Data.ShotAmmo; + ShotAmmoCount := trigData.trigShotAmmo; end; end; @@ -2305,60 +2309,60 @@ begin if Enabled and (TriggerType = TRIGGER_SOUND) and (Sound <> nil) then if (SoundPlayCount > 0) and (not Sound.IsPlaying()) then begin - if Data.PlayCount > 0 then // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî + if trigData.trigPlayCount > 0 then // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî SoundPlayCount := SoundPlayCount - 1; - if Data.Local then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0) + if trigData.trigLocal then + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0) else - Sound.PlayPanVolume((Data.Pan-127.0)/128.0, Data.Volume/255.0); + Sound.PlayPanVolume((trigData.trigPan-127.0)/128.0, trigData.trigVolume/255.0); if Sound.IsPlaying() and g_Game_IsNet and g_Game_IsServer then MH_SEND_TriggerSound(gTriggers[a]); end; // Òðèããåð "Ëîâóøêà" - ïîðà îòêðûâàòü: - if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (Data.PanelID <> -1) then + if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (trigPanelID <> -1) then begin - tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); DoorTime := -1; end; // Òðèããåð "Äâåðü 5 ñåê" - ïîðà çàêðûâàòü: - if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (Data.PanelID <> -1) then + if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (trigPanelID <> -1) then begin // Óæå çàêðûòà: - if gWalls[Data.PanelID].Enabled then + if gWalls[trigPanelID].Enabled then DoorTime := -1 else // Ïîêà îòêðûòà - çàêðûâàåì - if tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors) then + if tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors) then DoorTime := -1; end; // Òðèããåð - ðàñøèðèòåëü èëè ïåðåêëþ÷àòåëü, è ïðîøëà çàäåðæêà, è íàæàëè íóæíîå ÷èñëî ðàç: if (TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF]) and - (PressTime = 0) and (PressCount >= Data.Count) then + (PressTime = 0) and (PressCount >= trigData.trigCount) then begin // Ñáðàñûâàåì çàäåðæêó àêòèâàöèè: PressTime := -1; // Ñáðàñûâàåì ñ÷åò÷èê íàæàòèé: - if Data.Count > 0 then - PressCount := PressCount - Data.Count + if trigData.trigCount > 0 then + PressCount := PressCount - trigData.trigCount else PressCount := 0; // Îïðåäåëÿåì èçìåíÿåìûå èì òðèããåðû: for b := 0 to High(gTriggers) do - if g_Collide(Data.tX, Data.tY, Data.tWidth, Data.tHeight, gTriggers[b].X, gTriggers[b].Y, + if g_Collide(trigData.trigtX, trigData.trigtY, trigData.trigtWidth, trigData.trigtHeight, gTriggers[b].X, gTriggers[b].Y, gTriggers[b].Width, gTriggers[b].Height) and - ((b <> a) or (Data.Wait > 0)) then + ((b <> a) or (trigData.trigWait > 0)) then begin // Can be self-activated, if there is Data.Wait - if (not Data.ExtRandom) or gTriggers[b].Enabled then + if (not trigData.trigExtRandom) or gTriggers[b].Enabled then begin SetLength(Affected, Length(Affected) + 1); Affected[High(Affected)] := b; end; end; // Âûáèðàåì îäèí èç òðèããåðîâ äëÿ ðàñøèðèòåëÿ, åñëè âêëþ÷åí ðàíäîì: - if (TriggerType = TRIGGER_PRESS) and Data.ExtRandom then + if (TriggerType = TRIGGER_PRESS) and trigData.trigExtRandom then begin if (Length(Affected) > 0) then begin @@ -2628,7 +2632,7 @@ begin (TriggerType = TRIGGER_DOOR5) or (TriggerType = TRIGGER_DOOR) then begin - tr_OpenDoor(Data.PanelID, True, Data.d2d_doors); + tr_OpenDoor(trigPanelID, True, trigData.trigd2d_doors); if TriggerType = TRIGGER_DOOR5 then DoorTime := 180; b := True; end; @@ -2647,19 +2651,22 @@ procedure g_Triggers_Free(); var a: Integer; begin - if gTriggers <> nil then - for a := 0 to High(gTriggers) do + for a := 0 to High(gTriggers) do + begin + gTriggers[a].trigData.Free(); + if (gTriggers[a].TriggerType = TRIGGER_SOUND) then begin - if gTriggers[a].TriggerType = TRIGGER_SOUND then + if g_Sound_Exists(gTriggers[a].trigData.trigSoundName) then begin - if g_Sound_Exists(gTriggers[a].Data.SoundName) then - g_Sound_Delete(gTriggers[a].Data.SoundName); - - gTriggers[a].Sound.Free(); + g_Sound_Delete(gTriggers[a].trigData.trigSoundName); end; - if gTriggers[a].Activators <> nil then - SetLength(gTriggers[a].Activators, 0); + gTriggers[a].Sound.Free(); end; + if (gTriggers[a].Activators <> nil) then + begin + SetLength(gTriggers[a].Activators, 0); + end; + end; gTriggers := nil; gSecretsCount := 0; @@ -2672,7 +2679,7 @@ var dw: DWORD; sg: Single; b: Boolean; - p: Pointer; + //p: Pointer; begin // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ òðèããåðîâ: count := 0; @@ -2696,8 +2703,9 @@ begin // Òèï òðèããåðà: Mem.WriteByte(gTriggers[i].TriggerType); // Ñïåöèàëüíûå äàííûå òðèããåðà: - p := @gTriggers[i].Data; - Mem.WriteMemory(p, SizeOf(TTriggerData)); + //!!!FIXME!!! + //p := @gTriggers[i].Data; + //Mem.WriteMemory(p, SizeOf(TTriggerData)); // Êîîðäèíàòû ëåâîãî âåðõíåãî óãëà: Mem.WriteInt(gTriggers[i].X); Mem.WriteInt(gTriggers[i].Y); @@ -2772,7 +2780,7 @@ var dw: DWORD; vol, pan: Single; b: Boolean; - p: Pointer; + //p: Pointer; Trig: TTrigger; begin if Mem = nil then @@ -2797,12 +2805,15 @@ begin // Òèï òðèããåðà: Mem.ReadByte(Trig.TriggerType); // Ñïåöèàëüíûå äàííûå òðèããåðà: + //!!!FIXME!!! + { Mem.ReadMemory(p, dw); if dw <> SizeOf(TTriggerData) then begin raise EBinSizeError.Create('g_Triggers_LoadState: Wrong TriggerData Size'); end; Trig.Data := TTriggerData(p^); + } // Ñîçäàåì òðèããåð: i := g_Triggers_Create(Trig); // Êîîðäèíàòû ëåâîãî âåðõíåãî óãëà: diff --git a/src/shared/MAPDEF.pas b/src/shared/MAPDEF.pas index 37f9f00..a713716 100644 --- a/src/shared/MAPDEF.pas +++ b/src/shared/MAPDEF.pas @@ -17,14 +17,6 @@ {$M+} unit MAPDEF; -{ ------------------------------------ -MAPDEF.PAS ÂÅÐÑÈß ÎÒ 22.03.09 - -Ïîääåðæêà êàðò âåðñèè 1 ------------------------------------ -} - interface uses @@ -43,7 +35,11 @@ const type TDFPoint = packed record + public X, Y: LongInt; + + public + constructor Create (ax, ay: LongInt); end; Char16 = packed array[0..15] of Char; @@ -55,221 +51,207 @@ type {$INCLUDE mapdef.inc} +// various helpers to access map structures type - TTexturesRec1Array = array of TTextureRec_1; - TPanelsRec1Array = array of TPanelRec_1; - TItemsRec1Array = array of TItemRec_1; - TMonsterRec1Array = array of TMonsterRec_1; - TAreasRec1Array = array of TAreaRec_1; - TTriggersRec1Array = array of TTriggerRec_1; + TDynRecordHelper = class helper for TDynRecord + private + function getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline; + + function getPanelByIdx (idx: Integer): TDynRecord; inline; + + function getPanelId (): Integer; inline; + //procedure setPanelId (v: Integer); inline; + + function getTexturePanel (): Integer; inline; + //procedure setTexturePanel (v: Integer); inline; + + function getPanelIndex (pan: TDynRecord): Integer; + + function getPointField (const aname: AnsiString): TDFPoint; inline; + + public + function panelCount (): Integer; inline; + + // header + function mapName (): AnsiString; inline; + function mapAuthor (): AnsiString; inline; + function mapDesc (): AnsiString; inline; + function musicName (): AnsiString; inline; + function skyName (): AnsiString; inline; + + // panel + function X (): Integer; inline; + function Y (): Integer; inline; + function Width (): Word; inline; + function Height (): Word; inline; + function TextureNum (): Word; inline; + function TextureRec (): TDynRecord; inline; + function PanelType (): Word; inline; + function Alpha (): Byte; inline; + function Flags (): Byte; inline; + + // texture + function Resource (): AnsiString; inline; + function Anim (): Boolean; inline; + + // item + function ItemType (): Byte; inline; + function Options (): Byte; inline; + + // monster + function MonsterType (): Byte; inline; // type, ubyte + function Direction (): Byte; inline; // direction, ubyte + + // area + function AreaType (): Byte; inline; // type, ubyte + //function Direction (): Byte; inline; // direction, ubyte + + // trigger + function trigRec (): TDynRecord; inline; + function Enabled (): Boolean; inline; // enabled, bool + function TriggerType (): Byte; inline; // type, ubyte + function ActivateType (): Byte; inline; // activatetype, ubyte + function Keys (): Byte; inline; // keys, ubyte + //function DATA (): Byte128; inline; // triggerdata, trigdata[128]; // the only special nested structure + + {$INCLUDE mapdef_help.inc} + function trigMonsterId (): Integer; inline; + + public + property panel[idx: Integer]: TDynRecord read getPanelByIdx; + property panelIndex[pan: TDynRecord]: Integer read getPanelIndex; + // triggers + property tgPanelID: Integer read getPanelId {write setPanelId}; + property tgShotPanelID: Integer read getPanelId {write setPanelId}; + property TexturePanel: Integer read getTexturePanel {write setTexturePanel}; // texturepanel, int + end; +implementation -function GetMapHeader (rec: TDynRecord): TMapHeaderRec_1; -function GetTextures (rec: TDynRecord): TTexturesRec1Array; -function GetPanels (rec: TDynRecord): TPanelsRec1Array; -function GetItems (rec: TDynRecord): TItemsRec1Array; -function GetAreas (rec: TDynRecord): TAreasRec1Array; -function GetMonsters (rec: TDynRecord): TMonsterRec1Array; -function GetTriggers (rec: TDynRecord): TTriggersRec1Array; +uses + SysUtils, {e_log,} utils, xparser, xstreams; -implementation +// ////////////////////////////////////////////////////////////////////////// // +constructor TDFPoint.Create (ax, ay: LongInt); begin X := ax; Y := ay; end; -uses - {e_log,} xparser, xstreams; + +// ////////////////////////////////////////////////////////////////////////// // +function TDynRecordHelper.getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline; +begin + result := field[aname]; + if (result = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, name, id])); + if (result.baseType <> atype) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, name, id])); +end; -function GetMapHeader (rec: TDynRecord): TMapHeaderRec_1; +function TDynRecordHelper.getPointField (const aname: AnsiString): TDFPoint; inline; var - ws: TSFSMemoryChunkStream = nil; + fld: TDynField; begin - FillChar(result, sizeof(result), 0); - if (rec = nil) then exit; - try - ws := TSFSMemoryChunkStream.Create(@result, sizeof(result)); - rec.writeBinTo(ws, -1, true); // only fields - except // sorry - FillChar(result, sizeof(result), 0); - end; - ws.Free(); + fld := field[aname]; + if (fld = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, name, id])); + if (fld.baseType <> TPoint) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, name, id])); + result := TDFPoint.Create(fld.ival, fld.ival2); end; -function GetTextures (rec: TDynRecord): TTexturesRec1Array; +function TDynRecordHelper.getPanelByIdx (idx: Integer): TDynRecord; inline; var - ws: TSFSMemoryChunkStream = nil; fld: TDynField; - f: Integer; begin - result := nil; - fld := rec.field['texture']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - SetLength(result, fld.count); - for f := 0 to fld.count-1 do - begin - FillChar(result[f], sizeof(result[f]), 0); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields - end; - except - result := nil; - end; - ws.Free(); + fld := headerRec['panel']; + if (fld <> nil) then result := fld.item[idx] else result := nil; end; -function GetPanels (rec: TDynRecord): TPanelsRec1Array; +function TDynRecordHelper.getPanelIndex (pan: TDynRecord): Integer; var - ws: TSFSMemoryChunkStream = nil; fld: TDynField; f: Integer; begin - result := nil; - fld := rec.field['panel']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - SetLength(result, fld.count); - for f := 0 to fld.count-1 do + result := -1; + if (pan <> nil) then + begin + fld := headerRec['panel']; + if (fld <> nil) then begin - FillChar(result[f], sizeof(result[f]), 0); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields + for f := 0 to fld.count-1 do if (fld.item[f] = pan) then begin result := f; exit; end; end; - except - result := nil; end; - ws.Free(); end; -function GetItems (rec: TDynRecord): TItemsRec1Array; +function TDynRecordHelper.panelCount (): Integer; inline; var - ws: TSFSMemoryChunkStream = nil; fld: TDynField; - f: Integer; begin - result := nil; - fld := rec.field['item']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - SetLength(result, fld.count); - for f := 0 to fld.count-1 do - begin - FillChar(result[f], sizeof(result[f]), 0); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields - end; - except - result := nil; - end; - ws.Free(); + fld := headerRec['panel']; + if (fld <> nil) then result := fld.count else result := 0; end; -function GetAreas (rec: TDynRecord): TAreasRec1Array; +function TDynRecordHelper.TextureNum (): Word; inline; var - ws: TSFSMemoryChunkStream = nil; + idx: Integer; fld: TDynField; - f: Integer; begin - result := nil; - fld := rec.field['area']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - SetLength(result, fld.count); - for f := 0 to fld.count-1 do - begin - FillChar(result[f], sizeof(result[f]), 0); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields - end; - except - result := nil; - end; - ws.Free(); + fld := getFieldWithType('texture', TDynField.TType.TUShort); + idx := fld.recrefIndex; + if (idx < 0) then result := Word(TEXTURE_NONE) else result := Word(idx); end; -function GetMonsters (rec: TDynRecord): TMonsterRec1Array; +// ////////////////////////////////////////////////////////////////////////// // +// trigger +function TDynRecordHelper.trigRec (): TDynRecord; inline; var - ws: TSFSMemoryChunkStream = nil; fld: TDynField; - f: Integer; begin - result := nil; - fld := rec.field['monster']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - SetLength(result, fld.count); - for f := 0 to fld.count-1 do - begin - FillChar(result[f], sizeof(result[f]), 0); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields - end; - except - result := nil; - end; - ws.Free(); + fld := getFieldWithType('triggerdata', TDynField.TType.TTrigData); + if (fld <> nil) then result := fld.recref else result := nil; end; -function GetTriggers (rec: TDynRecord): TTriggersRec1Array; +function TDynRecordHelper.trigMonsterId (): Integer; inline; var - ws: TSFSMemoryChunkStream = nil; fld: TDynField; - f: Integer; - //wr: TTextWriter; - //fo: File; begin - result := nil; - fld := rec.field['trigger']; - if (fld = nil) or (fld.baseType <> fld.TType.TList) or (fld.count = 0) then exit; - ws := TSFSMemoryChunkStream.Create(nil, 0); - try - //wr := TFileTextWriter.Create('z00.txt'); - SetLength(result, fld.count); - for f := 0 to fld.count-1 do - begin - FillChar(result[f], sizeof(result[f]), 0); - //e_LogWritefln(': trigger #%s; TexturePanel=%s', [f, result[f].TexturePanel]); - ws.setup(@result[f], sizeof(result[f])); - fld.item[f].writeBinTo(ws, -1, true); // only fields - { - e_LogWritefln(': trigger #%s; X=%s; Y=%s; Width=%s; Height=%s; Enabled=%s; TexturePanel=%s; TriggerType=%s; ActivateType=%s; Keys=%s', [f, - result[f].X, - result[f].Y, - result[f].Width, - result[f].Height, - result[f].Enabled, - result[f].TexturePanel, - result[f].TriggerType, - result[f].ActivateType, - result[f].Keys - ]); - //e_LogWritefln('***'#10'%s'#10'***', [); - fld.item[f].writeTo(wr); - if (f = 0) then - begin - AssignFile(fo, 'z00.bin'); - Rewrite(fo, 1); - BlockWrite(fo, result[f], sizeof(result[f])); - CloseFile(fo); - end; - } - end; - //wr.Free(); - except - result := nil; - end; - ws.Free(); + fld := getFieldWithType('monsterid', TDynField.TType.TInt); + result := fld.recrefIndex; end; +// ////////////////////////////////////////////////////////////////////////// // +function TDynRecordHelper.mapName (): AnsiString; inline; begin result := utf2win(getFieldWithType('name', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.mapAuthor (): AnsiString; inline; begin result := utf2win(getFieldWithType('author', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.mapDesc (): AnsiString; inline; begin result := utf2win(getFieldWithType('description', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.musicName (): AnsiString; inline; begin result := utf2win(getFieldWithType('music', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.skyName (): AnsiString; inline; begin result := utf2win(getFieldWithType('sky', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.X (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival; end; +function TDynRecordHelper.Y (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival2; end; +function TDynRecordHelper.Width (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival); end; +function TDynRecordHelper.Height (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival2); end; +function TDynRecordHelper.PanelType (): Word; inline; begin result := Word(getFieldWithType('type', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.TextureRec (): TDynRecord; inline; begin result := getFieldWithType('texture', TDynField.TType.TUShort).recref; end; +function TDynRecordHelper.Alpha (): Byte; inline; begin result := Byte(getFieldWithType('alpha', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Flags (): Byte; inline; begin result := Byte(getFieldWithType('flags', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Resource (): AnsiString; inline; begin result := utf2win(getFieldWithType('path', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.Anim (): Boolean; inline; begin result := (getFieldWithType('animated', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.ItemType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Options (): Byte; inline; begin result := Byte(getFieldWithType('options', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.MonsterType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Direction (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.AreaType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Enabled (): Boolean; inline; begin result := (getFieldWithType('enabled', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.TriggerType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.ActivateType (): Byte; inline; begin result := Byte(getFieldWithType('activatetype', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.Keys (): Byte; inline; begin result := Byte(getFieldWithType('keys', TDynField.TType.TUByte).ival); end; + +function TDynRecordHelper.getPanelId (): Integer; inline; begin result := getFieldWithType('panelid', TDynField.TType.TInt).recrefIndex; end; +function TDynRecordHelper.getTexturePanel (): Integer; begin result := getFieldWithType('texturepanel', TDynField.TType.TInt).recrefIndex; end; + +{$INCLUDE mapdef_impl.inc} + + end. diff --git a/src/shared/mapdef.inc b/src/shared/mapdef.inc index 3ebc917..d744d93 100644 --- a/src/shared/mapdef.inc +++ b/src/shared/mapdef.inc @@ -246,192 +246,6 @@ const KEY_BLUETEAM = 16; -// ////////////////////////////////////////////////////////////////////////// // -// records -type - TMapHeaderRec_1 = packed record - MapName: Char32; - MapAuthor: Char32; - MapDescription: Char256; - MusicName: Char64; - SkyName: Char64; - Width, Height: Word; - end; - - TTextureRec_1 = packed record - Resource: Char64; - Anim: Boolean; - end; - - TPanelRec_1 = packed record - X, Y: Integer; - Width, Height: Word; - TextureNum: Word; - PanelType: Word; - Alpha: Byte; - Flags: Byte; - end; - - TItemRec_1 = packed record - X, Y: Integer; - ItemType: Byte; - Options: Byte; - end; - - TMonsterRec_1 = packed record - X, Y: Integer; - MonsterType: Byte; - Direction: Byte; - end; - - TAreaRec_1 = packed record - X, Y: Integer; - AreaType: Byte; - Direction: Byte; - end; - - TTriggerRec_1 = packed record - X, Y: Integer; - Width, Height: Word; - Enabled: Boolean; - TexturePanel: LongInt; - TriggerType: Byte; - ActivateType: Byte; - Keys: Byte; - DATA: Byte128; - end; - - - -// ////////////////////////////////////////////////////////////////////////// // -// triggerdata -type - TTriggerData = record - case Byte of - 0: (Default: Byte128); - TRIGGER_EXIT: ( - MapName: Char16; - ); - TRIGGER_TELEPORT: ( - TargetPoint: TDFPoint; - d2d_teleport: Boolean; - silent_teleport: Boolean; - TlpDir: Byte; - ); - TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP, TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT: ( - PanelID: LongInt; - NoSound: Boolean; - d2d_doors: Boolean; - ); - TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF: ( - tX, tY: Integer; - tWidth, tHeight: Word; - Wait: Word; - Count: Word; - MonsterID: LongInt; - ExtRandom: Boolean; - ); - TRIGGER_SECRET: ( - ); - TRIGGER_TEXTURE: ( - ActivateOnce: Boolean; - AnimOnce: Boolean; - ); - TRIGGER_SOUND: ( - SoundName: Char64; - Volume: Byte; - Pan: Byte; - Local: Boolean; - PlayCount: Byte; - SoundSwitch: Boolean; - ); - TRIGGER_SPAWNMONSTER: ( - MonPos: TDFPoint; - MonType: Byte; - MonHealth: LongInt; - MonDir: Byte; - MonActive: Boolean; - MonCount: LongInt; - MonEffect: Byte; - MonMax: Word; - MonDelay: Word; - MonBehav: Byte; - ); - TRIGGER_SPAWNITEM: ( - ItemPos: TDFPoint; - ItemType: Byte; - ItemFalls: Boolean; - ItemOnlyDM: Boolean; - ItemCount: LongInt; - ItemEffect: Byte; - ItemMax: Word; - ItemDelay: Word; - ); - TRIGGER_MUSIC: ( - MusicName: Char64; - MusicAction: Byte; - ); - TRIGGER_PUSH: ( - PushAngle: Word; - PushForce: Byte; - ResetVel: Boolean; - ); - TRIGGER_SCORE: ( - ScoreAction: Byte; - ScoreCount: Byte; - ScoreTeam: Byte; - ScoreCon: Boolean; - ScoreMsg: Boolean; - ); - TRIGGER_MESSAGE: ( - MessageKind: Byte; - MessageSendTo: Byte; - MessageText: Char100; - MessageTime: Word; - ); - TRIGGER_DAMAGE: ( - DamageValue: Word; - DamageInterval: Word; - ); - TRIGGER_HEALTH: ( - HealValue: Word; - HealInterval: Word; - HealMax: Boolean; - HealSilent: Boolean; - ); - TRIGGER_SHOT: ( - ShotPos: TDFPoint; - ShotType: Byte; - ShotTarget: Byte; - ShotSound: Boolean; - ShotAim: ShortInt; - ShotPanelID: LongInt; - ShotIntSight: Word; - ShotAngle: Word; - ShotWait: Word; - ShotAccuracy: Word; - ShotAmmo: Word; - ShotIntReload: Word; - ); - TRIGGER_EFFECT: ( - FXCount: Byte; - FXType: Byte; - FXSubType: Byte; - FXColorR: Byte; - FXColorG: Byte; - FXColorB: Byte; - FXPos: Byte; - FXWait: Word; - FXVelX: ShortInt; - FXVelY: ShortInt; - FXSpreadL: Byte; - FXSpreadR: Byte; - FXSpreadU: Byte; - FXSpreadD: Byte; - ); - end; - - const defaultMapDef: AnsiString = ''+ #47#47#32#121#101#115#44#32#116#104#105#115#32#102#105#108#101#32#115#101+ #114#118#101#115#32#98#111#116#104#32#97#115#32#102#111#114#109#97#116#32+ diff --git a/src/shared/mapdef_help.inc b/src/shared/mapdef_help.inc new file mode 100644 index 0000000..efd7623 --- /dev/null +++ b/src/shared/mapdef_help.inc @@ -0,0 +1,88 @@ +// *** WARNING! *** +// regenerate this part directly from "mapdef.txt" with 'mapgen', NEVER manually change anything here! + +function trigMapName (): AnsiString; inline; +function trigTargetPoint (): TDFPoint; inline; +function trigd2d_teleport (): Boolean; inline; +function trigsilent_teleport (): Boolean; inline; +function trigTlpDir (): Byte; inline; +function trigNoSound (): Boolean; inline; +function trigd2d_doors (): Boolean; inline; +function trigTX (): LongInt; inline; +function trigTY (): LongInt; inline; +function trigTWidth (): Word; inline; +function trigTHeight (): Word; inline; +function trigWait (): Word; inline; +function trigCount (): Word; inline; +function trigExtRandom (): Boolean; inline; +function trigActivateOnce (): Boolean; inline; +function trigAnimOnce (): Boolean; inline; +function trigSoundName (): AnsiString; inline; +function trigVolume (): Byte; inline; +function trigPan (): Byte; inline; +function trigLocal (): Boolean; inline; +function trigPlayCount (): Byte; inline; +function trigSoundSwitch (): Boolean; inline; +function trigMonPos (): TDFPoint; inline; +function trigMonType (): Byte; inline; +function trigMonHealth (): LongInt; inline; +function trigMonDir (): Byte; inline; +function trigMonActive (): Boolean; inline; +function trigMonCount (): LongInt; inline; +function trigMonEffect (): Byte; inline; +function trigMonMax (): Word; inline; +function trigMonDelay (): Word; inline; +function trigMonBehav (): Byte; inline; +function trigItemPos (): TDFPoint; inline; +function trigItemType (): Byte; inline; +function trigItemFalls (): Boolean; inline; +function trigItemOnlyDM (): Boolean; inline; +function trigItemCount (): LongInt; inline; +function trigItemEffect (): Byte; inline; +function trigItemMax (): Word; inline; +function trigItemDelay (): Word; inline; +function trigMusicName (): AnsiString; inline; +function trigMusicAction (): Byte; inline; +function trigPushAngle (): Word; inline; +function trigPushForce (): Byte; inline; +function trigResetVel (): Boolean; inline; +function trigScoreAction (): Byte; inline; +function trigScoreCount (): Byte; inline; +function trigScoreTeam (): Byte; inline; +function trigScoreCon (): Boolean; inline; +function trigScoreMsg (): Boolean; inline; +function trigMessageKind (): Byte; inline; +function trigMessageSendTo (): Byte; inline; +function trigMessageText (): AnsiString; inline; +function trigMessageTime (): Word; inline; +function trigDamageValue (): Word; inline; +function trigDamageInterval (): Word; inline; +function trigHealValue (): Word; inline; +function trigHealInterval (): Word; inline; +function trigHealMax (): Boolean; inline; +function trigHealSilent (): Boolean; inline; +function trigShotPos (): TDFPoint; inline; +function trigShotType (): Byte; inline; +function trigShotTarget (): Byte; inline; +function trigShotSound (): Boolean; inline; +function trigShotAim (): SmallInt; inline; +function trigShotIntSight (): Word; inline; +function trigShotAngle (): Word; inline; +function trigShotWait (): Word; inline; +function trigShotAccuracy (): Word; inline; +function trigShotAmmo (): Word; inline; +function trigShotIntReload (): Word; inline; +function trigFXCount (): Byte; inline; +function trigFXType (): Byte; inline; +function trigFXSubType (): Byte; inline; +function trigFXColorR (): Byte; inline; +function trigFXColorG (): Byte; inline; +function trigFXColorB (): Byte; inline; +function trigFXPos (): Byte; inline; +function trigFXWait (): Word; inline; +function trigFXVelX (): SmallInt; inline; +function trigFXVelY (): SmallInt; inline; +function trigFXSpreadL (): Byte; inline; +function trigFXSpreadR (): Byte; inline; +function trigFXSpreadU (): Byte; inline; +function trigFXSpreadD (): Byte; inline; diff --git a/src/shared/mapdef_impl.inc b/src/shared/mapdef_impl.inc new file mode 100644 index 0000000..f491dbf --- /dev/null +++ b/src/shared/mapdef_impl.inc @@ -0,0 +1,123 @@ + + +// ////////////////////////////////////////////////////////////////////////// // +// trigger helpers + +// TRIGGER_EXIT +function TDynRecordHelper.trigMapName (): AnsiString; inline; begin result := utf2win(getFieldWithType('map', TDynField.TType.TChar).sval); end; + +// TRIGGER_TELEPORT +function TDynRecordHelper.trigTargetPoint (): TDFPoint; inline; begin result := getPointField('target'); end; +function TDynRecordHelper.trigd2d_teleport (): Boolean; inline; begin result := (getFieldWithType('d2d', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigsilent_teleport (): Boolean; inline; begin result := (getFieldWithType('silent', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigTlpDir (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end; + +// TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP, TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT +function TDynRecordHelper.trigNoSound (): Boolean; inline; begin result := (getFieldWithType('silent', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigd2d_doors (): Boolean; inline; begin result := (getFieldWithType('d2d', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF +function TDynRecordHelper.trigTX (): LongInt; inline; begin result := LongInt(getFieldWithType('position', TDynField.TType.TPoint).ival); end; +function TDynRecordHelper.trigTY (): LongInt; inline; begin result := LongInt(getFieldWithType('position', TDynField.TType.TPoint).ival2); end; +function TDynRecordHelper.trigTWidth (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival); end; +function TDynRecordHelper.trigTHeight (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival2); end; +function TDynRecordHelper.trigWait (): Word; inline; begin result := Word(getFieldWithType('wait', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigCount (): Word; inline; begin result := Word(getFieldWithType('count', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigExtRandom (): Boolean; inline; begin result := (getFieldWithType('extrandom', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_SECRET + +// TRIGGER_TEXTURE +function TDynRecordHelper.trigActivateOnce (): Boolean; inline; begin result := (getFieldWithType('activateonce', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigAnimOnce (): Boolean; inline; begin result := (getFieldWithType('animateonce', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_SOUND +function TDynRecordHelper.trigSoundName (): AnsiString; inline; begin result := utf2win(getFieldWithType('soundname', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.trigVolume (): Byte; inline; begin result := Byte(getFieldWithType('volume', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigPan (): Byte; inline; begin result := Byte(getFieldWithType('pan', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigLocal (): Boolean; inline; begin result := (getFieldWithType('local', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigPlayCount (): Byte; inline; begin result := Byte(getFieldWithType('playcount', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigSoundSwitch (): Boolean; inline; begin result := (getFieldWithType('soundswitch', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_SPAWNMONSTER +function TDynRecordHelper.trigMonPos (): TDFPoint; inline; begin result := getPointField('position'); end; +function TDynRecordHelper.trigMonType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigMonHealth (): LongInt; inline; begin result := LongInt(getFieldWithType('health', TDynField.TType.TInt).ival); end; +function TDynRecordHelper.trigMonDir (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigMonActive (): Boolean; inline; begin result := (getFieldWithType('active', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigMonCount (): LongInt; inline; begin result := LongInt(getFieldWithType('count', TDynField.TType.TInt).ival); end; +function TDynRecordHelper.trigMonEffect (): Byte; inline; begin result := Byte(getFieldWithType('effect', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigMonMax (): Word; inline; begin result := Word(getFieldWithType('max', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigMonDelay (): Word; inline; begin result := Word(getFieldWithType('delay', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigMonBehav (): Byte; inline; begin result := Byte(getFieldWithType('behaviour', TDynField.TType.TUByte).ival); end; + +// TRIGGER_SPAWNITEM +function TDynRecordHelper.trigItemPos (): TDFPoint; inline; begin result := getPointField('position'); end; +function TDynRecordHelper.trigItemType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigItemFalls (): Boolean; inline; begin result := (getFieldWithType('gravity', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigItemOnlyDM (): Boolean; inline; begin result := (getFieldWithType('dmonly', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigItemCount (): LongInt; inline; begin result := LongInt(getFieldWithType('count', TDynField.TType.TInt).ival); end; +function TDynRecordHelper.trigItemEffect (): Byte; inline; begin result := Byte(getFieldWithType('effect', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigItemMax (): Word; inline; begin result := Word(getFieldWithType('max', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigItemDelay (): Word; inline; begin result := Word(getFieldWithType('delay', TDynField.TType.TUShort).ival); end; + +// TRIGGER_MUSIC +function TDynRecordHelper.trigMusicName (): AnsiString; inline; begin result := utf2win(getFieldWithType('name', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.trigMusicAction (): Byte; inline; begin result := Byte(getFieldWithType('action', TDynField.TType.TUByte).ival); end; + +// TRIGGER_PUSH +function TDynRecordHelper.trigPushAngle (): Word; inline; begin result := Word(getFieldWithType('angle', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigPushForce (): Byte; inline; begin result := Byte(getFieldWithType('force', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigResetVel (): Boolean; inline; begin result := (getFieldWithType('resetvelocity', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_SCORE +function TDynRecordHelper.trigScoreAction (): Byte; inline; begin result := Byte(getFieldWithType('action', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigScoreCount (): Byte; inline; begin result := Byte(getFieldWithType('count', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigScoreTeam (): Byte; inline; begin result := Byte(getFieldWithType('team', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigScoreCon (): Boolean; inline; begin result := (getFieldWithType('console', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigScoreMsg (): Boolean; inline; begin result := (getFieldWithType('message', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_MESSAGE +function TDynRecordHelper.trigMessageKind (): Byte; inline; begin result := Byte(getFieldWithType('kind', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigMessageSendTo (): Byte; inline; begin result := Byte(getFieldWithType('sendto', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigMessageText (): AnsiString; inline; begin result := utf2win(getFieldWithType('text', TDynField.TType.TChar).sval); end; +function TDynRecordHelper.trigMessageTime (): Word; inline; begin result := Word(getFieldWithType('time', TDynField.TType.TUShort).ival); end; + +// TRIGGER_DAMAGE +function TDynRecordHelper.trigDamageValue (): Word; inline; begin result := Word(getFieldWithType('amount', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigDamageInterval (): Word; inline; begin result := Word(getFieldWithType('interval', TDynField.TType.TUShort).ival); end; + +// TRIGGER_HEALTH +function TDynRecordHelper.trigHealValue (): Word; inline; begin result := Word(getFieldWithType('amount', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigHealInterval (): Word; inline; begin result := Word(getFieldWithType('interval', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigHealMax (): Boolean; inline; begin result := (getFieldWithType('max', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigHealSilent (): Boolean; inline; begin result := (getFieldWithType('silent', TDynField.TType.TBool).ival <> 0); end; + +// TRIGGER_SHOT +function TDynRecordHelper.trigShotPos (): TDFPoint; inline; begin result := getPointField('position'); end; +function TDynRecordHelper.trigShotType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigShotTarget (): Byte; inline; begin result := Byte(getFieldWithType('target', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigShotSound (): Boolean; inline; begin result := (getFieldWithType('silent', TDynField.TType.TBool).ival = 0); end; +function TDynRecordHelper.trigShotAim (): SmallInt; inline; begin result := ShortInt(getFieldWithType('aim', TDynField.TType.TByte).ival); end; +function TDynRecordHelper.trigShotIntSight (): Word; inline; begin result := Word(getFieldWithType('sight', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigShotAngle (): Word; inline; begin result := Word(getFieldWithType('angle', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigShotWait (): Word; inline; begin result := Word(getFieldWithType('wait', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigShotAccuracy (): Word; inline; begin result := Word(getFieldWithType('accuracy', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigShotAmmo (): Word; inline; begin result := Word(getFieldWithType('ammo', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigShotIntReload (): Word; inline; begin result := Word(getFieldWithType('reload', TDynField.TType.TUShort).ival); end; + +// TRIGGER_EFFECT +function TDynRecordHelper.trigFXCount (): Byte; inline; begin result := Byte(getFieldWithType('count', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXSubType (): Byte; inline; begin result := Byte(getFieldWithType('subtype', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXColorR (): Byte; inline; begin result := Byte(getFieldWithType('colorr', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXColorG (): Byte; inline; begin result := Byte(getFieldWithType('colorg', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXColorB (): Byte; inline; begin result := Byte(getFieldWithType('colorb', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXPos (): Byte; inline; begin result := Byte(getFieldWithType('position', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXWait (): Word; inline; begin result := Word(getFieldWithType('wait', TDynField.TType.TUShort).ival); end; +function TDynRecordHelper.trigFXVelX (): SmallInt; inline; begin result := ShortInt(getFieldWithType('velx', TDynField.TType.TByte).ival); end; +function TDynRecordHelper.trigFXVelY (): SmallInt; inline; begin result := ShortInt(getFieldWithType('vely', TDynField.TType.TByte).ival); end; +function TDynRecordHelper.trigFXSpreadL (): Byte; inline; begin result := Byte(getFieldWithType('spreadl', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXSpreadR (): Byte; inline; begin result := Byte(getFieldWithType('spreadr', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXSpreadU (): Byte; inline; begin result := Byte(getFieldWithType('spreadu', TDynField.TType.TUByte).ival); end; +function TDynRecordHelper.trigFXSpreadD (): Byte; inline; begin result := Byte(getFieldWithType('spreadd', TDynField.TType.TUByte).ival); end; diff --git a/src/shared/xdynrec.pas b/src/shared/xdynrec.pas index 37d27df..8ebac36 100644 --- a/src/shared/xdynrec.pas +++ b/src/shared/xdynrec.pas @@ -63,7 +63,6 @@ type mRecRef: TDynRecord; // for TEBS.TRec mMaxDim: Integer; // for byte and char arrays; <0: not an array; 0: impossible value mBinOfs: Integer; // offset in binary; <0 - none - mRecOfs: Integer; // offset in record; <0 - none mSepPosSize: Boolean; // for points and sizes, use separate fields mAsT: Boolean; // for points and sizes, use separate fields, names starts with `t` mDefined: Boolean; @@ -85,6 +84,10 @@ type // for binary parser mRecRefId: AnsiString; + // for userdata + mTagInt: Integer; + mTagPtr: Pointer; + private procedure cleanup (); @@ -98,10 +101,27 @@ type function getListItem (idx: Integer): TDynRecord; inline; overload; function getListItem (const aname: AnsiString): TDynRecord; inline; overload; + function getRecRefIndex (): Integer; + + procedure setIVal (v: Integer); inline; + protected // returns `true` for duplicate record id function addListItem (rec: TDynRecord): Boolean; inline; + public + type + TListEnumerator = record + private + mList: TDynRecList; + mCurIdx: Integer; + public + constructor Create (alist: TDynRecList); + function MoveNext (): Boolean; inline; + function getCurrent (): TDynRecord; inline; + property Current: TDynRecord read getCurrent; + end; + public constructor Create (const aname: AnsiString; atype: TType); constructor Create (pr: TTextParser); @@ -125,28 +145,35 @@ type procedure setValue (const s: AnsiString); + function GetEnumerator (): TListEnumerator; + public property pasname: AnsiString read mPasName; property name: AnsiString read mName; property baseType: TType read mType; + property negbool: Boolean read mNegBool; property defined: Boolean read mDefined write mDefined; property internal: Boolean read mInternal write mInternal; - property ival: Integer read mIVal; + property hasTPrefix: Boolean read mAsT; + property separatePasFields: Boolean read mSepPosSize; + property binOfs: Integer read mBinOfs; + property ival: Integer read mIVal write setIVal; + property ival2: Integer read mIVal2; property sval: AnsiString read mSVal; property hasDefault: Boolean read mHasDefault; property defsval: AnsiString read mDefSVal; property ebs: TEBS read mEBS; property ebstype: TObject read mEBSType; property ebstypename: AnsiString read mEBSTypeName; // enum/bitset name + property recref: TDynRecord read mRecRef write mRecRef; //FIXME: writing is a hack! + property recrefIndex: Integer read getRecRefIndex; // search for this record in header; -1: not found // for lists property count: Integer read getListCount; property item[idx: Integer]: TDynRecord read getListItem; property items[const aname: AnsiString]: TDynRecord read getListItem; default; // alas, FPC 3+ lost property overloading feature - - property x: Integer read mIVal; - property w: Integer read mIVal; - property y: Integer read mIVal2; - property h: Integer read mIVal2; + // userdata + property tagInt: Integer read mTagInt write mTagInt; + property tagPtr: Pointer read mTagPtr write mTagPtr; end; @@ -167,16 +194,25 @@ type mBinBlock: Integer; // -1: none mHeaderRec: TDynRecord; // for "value" records this is header record with data, for "type" records this is header type record + // for userdata + mTagInt: Integer; + mTagPtr: Pointer; + private procedure parseDef (pr: TTextParser); // parse definition function findByName (const aname: AnsiString): Integer; inline; function hasByName (const aname: AnsiString): Boolean; inline; function getFieldByName (const aname: AnsiString): TDynField; inline; + function getFieldAt (idx: Integer): TDynField; inline; + function getCount (): Integer; inline; function getIsTrigData (): Boolean; inline; function getIsForTrig (const aname: AnsiString): Boolean; inline; + function getForTrigCount (): Integer; inline; + function getForTrigAt (idx: Integer): AnsiString; inline; + protected function findRecordByTypeId (const atypename, aid: AnsiString): TDynRecord; function findRecordNumByType (const atypename: AnsiString; rc: TDynRecord): Integer; @@ -216,11 +252,18 @@ type property size: Integer read mSize; // size in bytes //property fields: TDynFieldList read mFields; property has[const aname: AnsiString]: Boolean read hasByName; - property field[const aname: AnsiString]: TDynField read getFieldByName; + property count: Integer read getCount; + property field[const aname: AnsiString]: TDynField read getFieldByName; default; + property fieldAt[idx: Integer]: TDynField read getFieldAt; property isTrigData: Boolean read getIsTrigData; property isForTrig[const aname: AnsiString]: Boolean read getIsForTrig; - property headerType: TDynRecord read mHeaderRec; + property forTrigCount: Integer read getForTrigCount; + property forTrigAt[idx: Integer]: AnsiString read getForTrigAt; + property headerRec: TDynRecord read mHeaderRec; property isHeader: Boolean read mHeader; + // userdata + property tagInt: Integer read mTagInt write mTagInt; + property tagPtr: Pointer read mTagPtr write mTagPtr; end; TDynEBS = class @@ -271,6 +314,9 @@ type function getHeaderRecType (): TDynRecord; inline; + function getTrigTypeCount (): Integer; inline; + function getTrigTypeAt (idx: Integer): TDynRecord; inline; + public constructor Create (pr: TTextParser); // parses data definition destructor Destroy (); override; @@ -280,6 +326,7 @@ type function findEBSType (const aname: AnsiString): TDynEBS; function pasdef (): AnsiString; + function pasdefconst (): AnsiString; // creates new header record function parseMap (pr: TTextParser): TDynRecord; @@ -289,6 +336,8 @@ type public property headerType: TDynRecord read getHeaderRecType; + property trigTypeCount: Integer read getTrigTypeCount; + property trigType[idx: Integer]: TDynRecord read getTrigTypeAt; end; @@ -308,6 +357,33 @@ uses function StrEqu (const a, b: AnsiString): Boolean; inline; begin result := (a = b); end; +// ////////////////////////////////////////////////////////////////////////// // +constructor TDynField.TListEnumerator.Create (alist: TDynRecList); +begin + mList := alist; + mCurIdx := -1; +end; + + +function TDynField.TListEnumerator.MoveNext (): Boolean; inline; +begin + Inc(mCurIdx); + result := (mList <> nil) and (mCurIdx < mList.count); +end; + + +function TDynField.TListEnumerator.getCurrent (): TDynRecord; inline; +begin + result := mList[mCurIdx]; +end; + + +function TDynField.GetEnumerator (): TListEnumerator; +begin + result := TListEnumerator.Create(mRVal); +end; + + // ////////////////////////////////////////////////////////////////////////// // constructor TDynField.Create (const aname: AnsiString; atype: TType); begin @@ -353,7 +429,6 @@ begin mRecRef := nil; mMaxDim := -1; mBinOfs := -1; - mRecOfs := -1; mSepPosSize := false; mAsT := false; mHasDefault := false; @@ -372,6 +447,8 @@ begin mAsMonsterId := false; mNegBool := false; mRecRefId := ''; + mTagInt := 0; + mTagPtr := nil; end; @@ -397,7 +474,6 @@ begin result.mRecRef := mRecRef; result.mMaxDim := mMaxDim; result.mBinOfs := mBinOfs; - result.mRecOfs := mRecOfs; result.mSepPosSize := mSepPosSize; result.mAsT := mAsT; result.mDefined := mDefined; @@ -416,6 +492,16 @@ begin result.mEBSTypeName := mEBSTypeName; result.mEBSType := mEBSType; result.mRecRefId := mRecRefId; + result.mTagInt := mTagInt; + result.mTagPtr := mTagPtr; +end; + + +procedure TDynField.setIVal (v: Integer); inline; +begin + //FIXME: check type + mIVal := v; + mDefined := true; end; @@ -590,7 +676,7 @@ begin result := mPasName+' is '+quoteStr(mName)+' type '; result += getTypeName(mType); if (mMaxDim >= 0) then result += Format('[%d]', [mMaxDim]); - if (mRecOfs >= 0) then result += Format(' offset %d', [mRecOfs]); + if (mBinOfs >= 0) then result += Format(' offset %d', [mBinOfs]); case mEBS of TEBS.TNone: begin end; TEBS.TRec: result += ' '+mEBSTypeName; @@ -814,7 +900,6 @@ begin self.mAsMonsterId := asmonid; self.mMaxDim := lmaxdim; self.mBinOfs := fldofs; - self.mRecOfs := fldofs; self.mSepPosSize := (asxy or aswh); self.mAsT := ast; self.mOmitDef := omitdef; @@ -822,6 +907,13 @@ begin end; +function TDynField.getRecRefIndex (): Integer; +begin + if (mRecRef = nil) then begin result := -1; exit; end; + result := mOwner.findRecordNumByType(mEBSTypeName, mRecRef); +end; + + procedure TDynField.writeBinTo (st: TStream); var s: AnsiString; @@ -1122,6 +1214,7 @@ begin raise Exception.Create(Format('cannot parse field ''%s'' yet', [mName])); end; + procedure TDynField.parseBinValue (st: TStream); var rec, rc: TDynRecord; @@ -1564,6 +1657,8 @@ begin mHeader := false; mHeaderRec := nil; mBinBlock := -1; + mTagInt := 0; + mTagPtr := nil; parseDef(pr); end; @@ -1579,6 +1674,8 @@ begin mTrigTypes := nil; mHeader := false; mHeaderRec := nil; + mTagInt := 0; + mTagPtr := nil; end; @@ -1593,6 +1690,8 @@ begin {$ENDIF} mTrigTypes := nil; mHeaderRec := nil; + mTagInt := 0; + mTagPtr := nil; inherited; end; @@ -1652,6 +1751,18 @@ begin end; +function TDynRecord.getFieldAt (idx: Integer): TDynField; inline; +begin + if (idx >= 0) and (idx < mFields.count) then result := mFields[idx] else result := nil; +end; + + +function TDynRecord.getCount (): Integer; inline; +begin + result := mFields.count; +end; + + function TDynRecord.getIsTrigData (): Boolean; inline; begin result := (Length(mTrigTypes) > 0); @@ -1668,6 +1779,18 @@ begin end; +function TDynRecord.getForTrigCount (): Integer; inline; +begin + result := Length(mTrigTypes); +end; + + +function TDynRecord.getForTrigAt (idx: Integer): AnsiString; inline; +begin + if (idx >= 0) and (idx < Length(mTrigTypes)) then result := mTrigTypes[idx] else result := ''; +end; + + function TDynRecord.clone (): TDynRecord; var fld: TDynField; @@ -1689,6 +1812,8 @@ begin result.mHeader := mHeader; result.mBinBlock := mBinBlock; result.mHeaderRec := mHeaderRec; + result.mTagInt := mTagInt; + result.mTagPtr := mTagPtr; end; @@ -2815,4 +2940,19 @@ begin end; +function TDynMapDef.pasdefconst (): AnsiString; +var + ebs: TDynEBS; +begin + result := ''; + result += '// ////////////////////////////////////////////////////////////////////////// //'#10; + result += '// enums and bitsets'#10; + for ebs in ebsTypes do result += #10+ebs.pasdef(); +end; + + +function TDynMapDef.getTrigTypeCount (): Integer; inline; begin result := trigTypes.count; end; +function TDynMapDef.getTrigTypeAt (idx: Integer): TDynRecord; inline; begin if (idx >= 0) and (idx < trigTypes.count) then result := trigTypes[idx] else result := nil; end; + + end. diff --git a/src/tools/mapgen.dpr b/src/tools/mapgen.dpr index 9a98f71..c53aa4e 100644 --- a/src/tools/mapgen.dpr +++ b/src/tools/mapgen.dpr @@ -19,11 +19,15 @@ uses var pr: TTextParser; dfmapdef: TDynMapDef; - fo: TextFile; + fo, fohlp, foimpl: TextFile; st: TStream = nil; ch: AnsiChar; wdt: Integer; s: AnsiString; + tidx, nidx, fidx: Integer; + needComma: Boolean; + trec: TDynRecord; + fld: TDynField; begin //writeln(getFilenamePath(ParamStr(0)), '|'); @@ -60,9 +64,156 @@ begin writeln('writing "mapdef.inc"...'); AssignFile(fo, 'mapdef.inc'); Rewrite(fo); + + AssignFile(fohlp, 'mapdef_help.inc'); + Rewrite(fohlp); + + AssignFile(foimpl, 'mapdef_impl.inc'); + Rewrite(foimpl); + write(fo, '// *** WARNING! ***'#10); write(fo, '// regenerate this part directly from "mapdef.txt" with ''mapgen'', NEVER manually change anything here!'#10#10#10); - write(fo, dfmapdef.pasdef); + write(fo, dfmapdef.pasdefconst); + + write(fohlp, '// *** WARNING! ***'#10); + write(fohlp, '// regenerate this part directly from "mapdef.txt" with ''mapgen'', NEVER manually change anything here!'#10#10); + + // generate trigger helpers +{ +function TDynRecordHelper.trigTargetPoint (): TDFPoint; inline; begin result := getPointField('target'); end; +function TDynRecordHelper.trigD2DTeleport (): Boolean; inline; begin result := (getFieldWithType('d2d', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigSilentTeleport (): Boolean; inline; begin result := (getFieldWithType('silent', TDynField.TType.TBool).ival <> 0); end; +function TDynRecordHelper.trigTlpDir (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end; +} + + write(foimpl, #10#10'// ////////////////////////////////////////////////////////////////////////// //'#10); + write(foimpl, '// trigger helpers'#10); + for tidx := 0 to dfmapdef.trigTypeCount-1 do + begin + // header comment + write(foimpl, #10'// '); + needComma := false; + trec := dfmapdef.trigType[tidx]; + for nidx := 0 to trec.forTrigCount-1 do + begin + if needComma then write(foimpl, ', ') else needComma := true; + write(foimpl, trec.forTrigAt[nidx]); + end; + write(foimpl, #10); + // fields + for fidx := 0 to trec.count-1 do + begin + fld := trec.fieldAt[fidx]; + if fld.internal then continue; + if (fld.binOfs < 0) then continue; + // HACK! + if (fld.name = 'panelid') or (fld.name = 'monsterid') then + begin + writeln('skipping ', fld.pasname, ' <', fld.name, '>'); + continue; + end; + if (fld.baseType <> TDynField.TType.TPoint) and (fld.baseType <> TDynField.TType.TSize) then + begin + write(foimpl, 'function TDynRecordHelper.trig', fld.pasname, ' (): '); + write(fohlp, 'function trig', fld.pasname, ' (): '); + end; + case fld.baseType of + TDynField.TType.TBool: + begin + write(fohlp, 'Boolean; inline;'#10); + write(foimpl, 'Boolean; inline; begin result := (getFieldWithType(''', fld.name, ''', TDynField.TType.TBool).ival '); + if fld.negbool then write(foimpl, '=') else write(foimpl, '<>'); + write(foimpl, ' 0); end;'#10); + end; + TDynField.TType.TChar: + begin + write(fohlp, 'AnsiString; inline;'#10); + write(foimpl, 'AnsiString; inline; begin result := utf2win(getFieldWithType(''', fld.name, ''', TDynField.TType.TChar).sval); end;'#10); + end; + TDynField.TType.TByte: + begin + write(fohlp, 'SmallInt; inline;'#10); + write(foimpl, 'SmallInt; inline; begin result := ShortInt(getFieldWithType(''', fld.name, ''', TDynField.TType.TByte).ival); end;'#10); + end; + TDynField.TType.TUByte: + begin + write(fohlp, 'Byte; inline;'#10); + write(foimpl, 'Byte; inline; begin result := Byte(getFieldWithType(''', fld.name, ''', TDynField.TType.TUByte).ival); end;'#10); + end; + TDynField.TType.TShort: + begin + write(fohlp, 'ShortInt; inline;'#10); + write(foimpl, 'ShortInt; inline; begin result := SmallInt(getFieldWithType(''', fld.name, ''', TDynField.TType.TShort).ival); end;'#10); + end; + TDynField.TType.TUShort: + begin + write(fohlp, 'Word; inline;'#10); + write(foimpl, 'Word; inline; begin result := Word(getFieldWithType(''', fld.name, ''', TDynField.TType.TUShort).ival); end;'#10); + end; + TDynField.TType.TInt: + begin + write(fohlp, 'LongInt; inline;'#10); + write(foimpl, 'LongInt; inline; begin result := LongInt(getFieldWithType(''', fld.name, ''', TDynField.TType.TInt).ival); end;'#10); + end; + TDynField.TType.TUInt: + begin + write(fohlp, 'LongWord; inline;'#10); + write(foimpl, 'LongWord; inline; begin result := LongWord(getFieldWithType(''', fld.name, ''', TDynField.TType.TUInt).ival); end;'#10); + end; + TDynField.TType.TString: + begin + write(fohlp, 'AnsiString; inline;'#10); + write(foimpl, 'AnsiString; inline; begin result := utf2win(getFieldWithType(''', fld.name, ''', TDynField.TType.TChar).sval); end;'#10); + end; + TDynField.TType.TPoint: + begin + if fld.hasTPrefix or fld.separatePasFields then + begin + write(fohlp, 'function trig'); if fld.hasTPrefix then write(fohlp, 'T'); write(fohlp, 'X (): LongInt; inline;'#10); + write(fohlp, 'function trig'); if fld.hasTPrefix then write(fohlp, 'T'); write(fohlp, 'Y (): LongInt; inline;'#10); + // [T]X + write(foimpl, 'function TDynRecordHelper.trig'); + if fld.hasTPrefix then write(foimpl, 'T'); + write(foimpl, 'X (): LongInt; inline; begin result := LongInt(getFieldWithType(''', fld.name, ''', TDynField.TType.TPoint).ival); end;'#10); + // [T]Y + write(foimpl, 'function TDynRecordHelper.trig'); + if fld.hasTPrefix then write(foimpl, 'T'); + write(foimpl, 'Y (): LongInt; inline; begin result := LongInt(getFieldWithType(''', fld.name, ''', TDynField.TType.TPoint).ival2); end;'#10); + end + else + begin + write(fohlp, 'function trig', fld.pasname, ' (): TDFPoint; inline;'#10); + write(foimpl, 'function TDynRecordHelper.trig', fld.pasname, ' (): TDFPoint; inline; begin result := getPointField(''', fld.name, '''); end;'#10); + end; + end; + TDynField.TType.TSize: + begin + if fld.hasTPrefix or fld.separatePasFields then + begin + write(fohlp, 'function trig'); if fld.hasTPrefix then write(fohlp, 'T'); write(fohlp, 'Width (): Word; inline;'#10); + write(fohlp, 'function trig'); if fld.hasTPrefix then write(fohlp, 'T'); write(fohlp, 'Height (): Word; inline;'#10); + // [T]X + write(foimpl, 'function TDynRecordHelper.trig'); + if fld.hasTPrefix then write(foimpl, 'T'); + write(foimpl, 'Width (): Word; inline; begin result := Word(getFieldWithType(''', fld.name, ''', TDynField.TType.TSize).ival); end;'#10); + // [T]Y + write(foimpl, 'function TDynRecordHelper.trig'); + if fld.hasTPrefix then write(foimpl, 'T'); + write(foimpl, 'Height (): Word; inline; begin result := Word(getFieldWithType(''', fld.name, ''', TDynField.TType.TSize).ival2); end;'#10); + end + else + begin + raise Exception.Create('no non-separate sizes in triggers, pelase'); + end; + end; + TDynField.TType.TList: + raise Exception.Create('no lists in triggers, pelase'); + TDynField.TType.TTrigData: + raise Exception.Create('no triggers in triggers, pelase'); + end; + end; + end; + //st := openDiskFileRO('mapdef.txt'); st.position := 0; @@ -79,4 +230,6 @@ begin write(fo, #10';'); CloseFile(fo); + CloseFile(fohlp); + CloseFile(foimpl); end. -- 2.29.2