X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=22a9aee280e1d2d8295ea8191655dd3645a10936;hb=2fa77a7c9667395ef6d4141cde69ff6349bf301e;hp=6ae077b111553f4193f959550e7ac90774e1b670;hpb=ebca2a974a49e96c507d87dcb3c320f5bb104d12;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 6ae077b..22a9aee 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -60,7 +60,7 @@ function g_Map_Load(Res: String): Boolean; function g_Map_GetMapInfo(Res: String): TMapInfo; function g_Map_GetMapsList(WADName: String): SArray; function g_Map_Exist(Res: String): Boolean; -procedure g_Map_Free(); +procedure g_Map_Free(freeTextures: Boolean=true); procedure g_Map_Update(); procedure g_Map_DrawPanels (PanelType: Word); // unaccelerated @@ -202,6 +202,7 @@ var gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()` gCurrentMap: TDynRecord = nil; + gCurrentMapFileName: AnsiString = ''; // so we can skip texture reloading function panelTypeToTag (panelType: Word): Integer; // returns GridTagXXX @@ -438,7 +439,9 @@ type var PanelById: array of TPanelID; - Textures: TLevelTextureArray; + Textures: TLevelTextureArray = nil; + TextNameHash: THashStrInt = nil; // key: texture name; value: index in `Textures` + BadTextNameHash: THashStrInt = nil; // set; so we won't spam with non-existing texture messages RespawnPoints: Array of TRespawnPoint; FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint; //DOMFlagPoints: Array of TFlagPoint; @@ -784,8 +787,13 @@ begin PanelByID[len].PArrID := Result; end; + function CreateNullTexture(RecName: String): Integer; begin + RecName := toLowerCase1251(RecName); + if (TextNameHash = nil) then TextNameHash := hashNewStrInt(); + if TextNameHash.get(RecName, result) then exit; // i found her! + SetLength(Textures, Length(Textures)+1); result := High(Textures); @@ -797,26 +805,47 @@ begin Anim := False; TextureID := LongWord(TEXTURE_NONE); end; + + TextNameHash.put(RecName, result); end; -function CreateTexture(RecName: String; Map: string; log: Boolean): Integer; + +function CreateTexture(RecName: AnsiString; Map: string; log: Boolean): Integer; var WAD: TWADFile; TextureData: Pointer; - WADName, txname: String; + WADName: String; a, ResLength: Integer; begin + RecName := toLowerCase1251(RecName); + if (TextNameHash = nil) then TextNameHash := hashNewStrInt(); + if TextNameHash.get(RecName, result) then + begin + // i found her! + //e_LogWritefln('texture ''%s'' already loaded', [RecName]); + exit; + end; + Result := -1; + if (BadTextNameHash <> nil) and BadTextNameHash.has(RecName) then exit; // don't do it again and again + + { if Textures <> nil then + begin for a := 0 to High(Textures) do - if Textures[a].TextureName = RecName then + begin + if (Textures[a].TextureName = RecName) then begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü + e_LogWritefln('texture ''%s'' already loaded', [RecName]); Result := a; Exit; end; + end; + end; + } -// Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà): + // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà): if (RecName = TEXTURE_NAME_WATER) or (RecName = TEXTURE_NAME_ACID1) or (RecName = TEXTURE_NAME_ACID2) then @@ -826,36 +855,28 @@ begin with Textures[High(Textures)] do begin TextureName := RecName; - - if TextureName = TEXTURE_NAME_WATER then - TextureID := LongWord(TEXTURE_SPECIAL_WATER) - else - if TextureName = TEXTURE_NAME_ACID1 then - TextureID := LongWord(TEXTURE_SPECIAL_ACID1) - else - if TextureName = TEXTURE_NAME_ACID2 then - TextureID := LongWord(TEXTURE_SPECIAL_ACID2); + if (TextureName = TEXTURE_NAME_WATER) then TextureID := LongWord(TEXTURE_SPECIAL_WATER) + else if (TextureName = TEXTURE_NAME_ACID1) then TextureID := LongWord(TEXTURE_SPECIAL_ACID1) + else if (TextureName = TEXTURE_NAME_ACID2) then TextureID := LongWord(TEXTURE_SPECIAL_ACID2); Anim := False; end; result := High(Textures); + TextNameHash.put(RecName, result); Exit; end; -// Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à: + // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à: WADName := g_ExtractWadName(RecName); WAD := TWADFile.Create(); - if WADName <> '' then - WADName := GameDir+'/wads/'+WADName - else - WADName := Map; + if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map; WAD.ReadFile(WADName); - txname := RecName; + //txname := RecName; { if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then begin @@ -864,33 +885,38 @@ begin end; } - if WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then + if WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength, log) then + begin + SetLength(Textures, Length(Textures)+1); + if not e_CreateTextureMem(TextureData, ResLength, Textures[High(Textures)].TextureID) then begin - SetLength(Textures, Length(Textures)+1); - if not e_CreateTextureMem(TextureData, ResLength, Textures[High(Textures)].TextureID) then - Exit; - e_GetTextureSize(Textures[High(Textures)].TextureID, - @Textures[High(Textures)].Width, - @Textures[High(Textures)].Height); - FreeMem(TextureData); - Textures[High(Textures)].TextureName := {RecName}txname; - Textures[High(Textures)].Anim := False; - - result := High(Textures); - end + SetLength(Textures, Length(Textures)-1); + Exit; + end; + e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height); + FreeMem(TextureData); + Textures[High(Textures)].TextureName := RecName; + Textures[High(Textures)].Anim := False; + + result := High(Textures); + TextNameHash.put(RecName, result); + end else // Íåò òàêîãî ðåóñðñà â WAD'å begin - //e_WriteLog(Format('SHIT! Error loading texture %s : %s : %s', [RecName, txname, g_ExtractFilePathName(RecName)]), MSG_WARNING); - if log then - begin - e_WriteLog(Format('Error loading texture %s', [RecName]), MSG_WARNING); - //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING); - end; + //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING); + if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt(); + if log and (not BadTextNameHash.get(RecName, a)) then + begin + e_WriteLog(Format('Error loading texture %s', [RecName]), MSG_WARNING); + //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING); + end; + BadTextNameHash.put(RecName, -1); end; WAD.Free(); end; + function CreateAnimTexture(RecName: String; Map: string; log: Boolean): Integer; var WAD: TWADFile; @@ -907,29 +933,44 @@ var ia: TDynImageDataArray = nil; f, c, frdelay, frloop: Integer; begin + RecName := toLowerCase1251(RecName); + if (TextNameHash = nil) then TextNameHash := hashNewStrInt(); + if TextNameHash.get(RecName, result) then + begin + // i found her! + //e_LogWritefln('animated texture ''%s'' already loaded', [RecName]); + exit; + end; + result := -1; - //e_WriteLog(Format('*** Loading animated texture "%s"', [RecName]), MSG_NOTIFY); + //e_LogWritefln('*** Loading animated texture "%s"', [RecName]); + + if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt(); + if BadTextNameHash.get(RecName, f) then + begin + //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY); + exit; + end; // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü: WADName := g_ExtractWadName(RecName); WAD := TWADFile.Create(); try - if WADName <> '' then - WADName := GameDir+'/wads/'+WADName - else - WADName := Map; + if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map; WAD.ReadFile(WADName); - if not WAD.GetResource(g_ExtractFilePathName(RecName), TextureWAD, ResLength) then + if not WAD.GetResource(g_ExtractFilePathName(RecName), TextureWAD, ResLength, log) then begin - if log then + if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt(); + if log and (not BadTextNameHash.get(RecName, f)) then begin e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING); //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING); end; + BadTextNameHash.put(RecName, -1); exit; end; @@ -946,6 +987,7 @@ begin if ResLength < 6 then begin e_WriteLog(Format('Animated texture file "%s" too short', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -957,6 +999,7 @@ begin if not WAD.ReadMemory(TextureWAD, ResLength) then begin e_WriteLog(Format('Animated texture WAD file "%s" is invalid', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -964,6 +1007,7 @@ begin if not WAD.GetResource('TEXT/ANIM', TextData, ResLength) then begin e_WriteLog(Format('Animated texture file "%s" has invalid INI', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -973,6 +1017,7 @@ begin if TextureResource = '' then begin e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -989,6 +1034,7 @@ begin if not WAD.GetResource('TEXTURES/'+TextureResource, TextureData, ResLength) then begin e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -1008,10 +1054,16 @@ begin FramesCount := _framecount; Speed := _speed; result := High(Textures); + TextNameHash.put(RecName, result); end else begin - if log then e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING); + if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt(); + if log and (not BadTextNameHash.get(RecName, f)) then + begin + e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING); + end; + BadTextNameHash.put(RecName, -1); end; end; end @@ -1031,11 +1083,13 @@ begin if not LoadMultiImageFromMemory(TextureWAD, ResLength, ia) then begin e_WriteLog(Format('Animated texture file "%s" cannot be loaded', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; if length(ia) = 0 then begin e_WriteLog(Format('Animated texture file "%s" has no frames', [RecName]), MSG_WARNING); + BadTextNameHash.put(RecName, -1); exit; end; @@ -1091,20 +1145,26 @@ begin Textures[High(Textures)].FramesCount := length(ia); Textures[High(Textures)].Speed := _speed; result := High(Textures); + TextNameHash.put(RecName, result); //writeln(' CREATED!'); end else begin - if log then e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), MSG_WARNING); + if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt(); + if log and (not BadTextNameHash.get(RecName, f)) then + begin + e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), MSG_WARNING); + end; + BadTextNameHash.put(RecName, -1); end; end; finally for f := 0 to High(ia) do FreeImage(ia[f]); WAD.Free(); cfg.Free(); - if TextureWAD <> nil then FreeMem(TextureWAD); - if TextData <> nil then FreeMem(TextData); - if TextureData <> nil then FreeMem(TextureData); + if (TextureWAD <> nil) then FreeMem(TextureWAD); + if (TextData <> nil) then FreeMem(TextData); + if (TextureData <> nil) then FreeMem(TextureData); end; end; @@ -1190,7 +1250,7 @@ begin end; end; -procedure CreateTrigger(Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word); +procedure CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word); var _trigger: TTrigger; begin @@ -1198,11 +1258,13 @@ begin with _trigger do begin + mapId := Trigger.id; + mapIndex := amapIdx; X := Trigger.X; Y := Trigger.Y; Width := Trigger.Width; Height := Trigger.Height; - Enabled := ByteBool(Trigger.Enabled); + Enabled := Trigger.Enabled; //TexturePanel := Trigger.TexturePanel; TexturePanel := atpanid; TexturePanelType := fTexturePanel1Type; @@ -1213,7 +1275,18 @@ begin trigPanelId := atrigpanid; //trigShotPanelId := ashotpanid; //Data.Default := Trigger.DATA; - trigData := Trigger.trigRec.clone(); + if (Trigger.trigRec = nil) then + begin + trigData := nil; + if (TriggerType <> TRIGGER_SECRET) then + begin + e_LogWritefln('trigger of type %s has no triggerdata; wtf?!', [TriggerType], MSG_WARNING); + end; + end + else + begin + trigData := Trigger.trigRec.clone(); + end; end; g_Triggers_Create(_trigger); @@ -1252,6 +1325,7 @@ procedure g_Map_ReAdd_DieTriggers(); function monsDieTrig (mon: TMonster): Boolean; var a: Integer; + //tw: TStrTextWriter; begin result := false; // don't stop mon.ClearTriggers(); @@ -1260,6 +1334,15 @@ procedure g_Map_ReAdd_DieTriggers(); if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then begin //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a); + { + tw := TStrTextWriter.Create(); + try + gTriggers[a].trigData.writeTo(tw); + e_LogWritefln('=== trigger #%s ==='#10'%s'#10'---', [a, tw.str]); + finally + tw.Free(); + end; + } if (gTriggers[a].trigData.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a); end; end; @@ -1463,11 +1546,8 @@ type end; var WAD: TWADFile; - //MapReader: TMapReader_1; mapReader: TDynRecord = nil; - //Header: TMapHeaderRec_1; - _textures: TDynField = nil; //TTexturesRec1Array; tagInt: texture index - //_texnummap: array of Integer = nil; // `_textures` -> `Textures` + mapTextureList: TDynField = nil; //TTexturesRec1Array; tagInt: texture index panels: TDynField = nil; //TPanelsRec1Array; items: TDynField = nil; //TItemsRec1Array; monsters: TDynField = nil; //TMonsterRec1Array; @@ -1476,7 +1556,6 @@ var b, c, k: Integer; PanelID: DWORD; AddTextures: TAddTextureArray; - //texture: TTextureRec_1; TriggersTable: array of TTRec; FileName, mapResName, s, TexName: String; Data: Pointer; @@ -1486,11 +1565,7 @@ var rec, texrec: TDynRecord; pttit: PTRec; pannum, trignum, cnt, tgpid: Integer; - // key: panel index; value: `TriggersTable` index - hashTextPan: THashIntInt = nil; - hashLiftPan: THashIntInt = nil; - hashDoorPan: THashIntInt = nil; - hashShotPan: THashIntInt = nil; + stt: UInt64; begin mapGrid.Free(); mapGrid := nil; @@ -1502,7 +1577,6 @@ begin gMapInfo.Map := Res; TriggersTable := nil; mapReader := nil; - //FillChar(texture, SizeOf(texture), 0); sfsGCDisable(); // temporary disable removing of temporary volumes try @@ -1541,6 +1615,8 @@ begin e_LogWritefln('Loading map: %s', [mapResName], MSG_NOTIFY); g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False); + stt := curTimeMicro(); + try mapReader := g_Map_ParseMap(Data, Len); except @@ -1552,31 +1628,18 @@ begin FreeMem(Data); - hashTextPan := hashNewIntInt(); - hashLiftPan := hashNewIntInt(); - hashDoorPan := hashNewIntInt(); - hashShotPan := hashNewIntInt(); - - generateExternalResourcesList(MapReader); - //_textures := GetTextures(mapReader); - _textures := mapReader['texture']; - //_texnummap := nil; + generateExternalResourcesList(mapReader); + mapTextureList := mapReader['texture']; // 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); with gMapInfo do begin @@ -1592,14 +1655,13 @@ begin // Çàãðóçêà òåêñòóð: g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False); // Äîáàâëåíèå òåêñòóð â Textures[]: - if (_textures <> nil) and (_textures.count > 0) then + if (mapTextureList <> nil) and (mapTextureList.count > 0) then begin e_WriteLog(' Loading textures:', MSG_NOTIFY); - g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], _textures.count-1, False); - //SetLength(_texnummap, _textures.count); + g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], mapTextureList.count-1, False); cnt := -1; - for rec in _textures do + for rec in mapTextureList do begin Inc(cnt); s := rec.Resource; @@ -1621,8 +1683,7 @@ begin end; if (ntn < 0) then ntn := CreateNullTexture(rec.Resource); - //_texnummap[a] := ntn; // fix texture number - rec.tagInt := ntn; + rec.tagInt := ntn; // remember texture number g_Game_StepLoading(); end; @@ -1672,6 +1733,7 @@ begin SetLength(TriggersTable, Length(TriggersTable)+1); pttit := @TriggersTable[High(TriggersTable)]; pttit.trigrec := rec; + // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè) pttit.texPan := mapReader.panel[rec.TexturePanel]; pttit.liftPan := nil; pttit.doorPan := nil; @@ -1680,33 +1742,26 @@ begin 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)); + if (pttit.texPan <> nil) then pttit.texPan.userPanelTrigRef := true; + if (pttit.liftPan <> nil) then pttit.liftPan.userPanelTrigRef := true; + if (pttit.doorPan <> nil) then pttit.doorPan.userPanelTrigRef := true; + if (pttit.shotPan <> nil) then pttit.shotPan.userPanelTrigRef := true; g_Game_StepLoading(); end; @@ -1722,13 +1777,14 @@ begin for rec in panels do begin Inc(pannum); + //e_LogWritefln('PANSTART: pannum=%s', [pannum]); texrec := nil; SetLength(AddTextures, 0); trigRef := False; CurTex := -1; ok := false; - if (_textures <> nil) then + if (mapTextureList <> nil) then begin texrec := rec.TextureRec; ok := (texrec <> nil); @@ -1739,8 +1795,9 @@ begin // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû. // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð ok := false; - if (TriggersTable <> nil) and (_textures <> nil) then + if (TriggersTable <> nil) and (mapTextureList <> nil) then begin + { for b := 0 to High(TriggersTable) do begin if (TriggersTable[b].texPan = rec) or (TriggersTable[b].shotPan = rec) then @@ -1750,6 +1807,13 @@ begin break; end; end; + } + if rec.userPanelTrigRef then + begin + // e_LogWritefln('trigref for panel %s', [pannum]); + trigRef := True; + ok := True; + end; end; end; @@ -1786,30 +1850,39 @@ begin begin // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ isAnim := True; + //e_LogWritefln('000: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); ok := CreateAnimTexture(TexName, FileName, False) >= 0; + //e_LogWritefln('001: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); if not ok then begin // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ isAnim := False; + //e_LogWritefln('002: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); ok := CreateTexture(TexName, FileName, False) >= 0; + //e_LogWritefln('003: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); end; end else begin // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ isAnim := False; + //e_LogWritefln('004: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); ok := CreateTexture(TexName, FileName, False) >= 0; + //e_LogWritefln('005: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); if not ok then begin // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ isAnim := True; + //e_LogWritefln('006: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); ok := CreateAnimTexture(TexName, FileName, False) >= 0; + //e_LogWritefln('007: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]); end; end; // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè if ok then begin + { for c := 0 to High(Textures) do begin if (Textures[c].TextureName = TexName) then @@ -1820,6 +1893,13 @@ begin break; end; end; + } + if (TextNameHash <> nil) and TextNameHash.get(toLowerCase1251(TexName), c) then + begin + SetLength(AddTextures, Length(AddTextures)+1); + AddTextures[High(AddTextures)].Texture := c; + AddTextures[High(AddTextures)].Anim := isAnim; + end; end; end else @@ -1828,8 +1908,7 @@ begin 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)].Texture := rec.tagInt; // internal texture number, not map index AddTextures[High(AddTextures)].Anim := texrec.Anim; CurTex := High(AddTextures); ok := true; @@ -1849,66 +1928,36 @@ begin begin // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó SetLength(AddTextures, 1); - AddTextures[0].Texture := rec.tagInt; //panels[a].TextureNum; + AddTextures[0].Texture := rec.tagInt; // internal texture number, not map index 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); + //e_WriteLog(Format('panel #%d: TextureNum=%d; ht=%d; ht1=%d; atl=%d', [a, panels[a].TextureNum, High(mapTextureList), High(Textures), High(AddTextures)]), MSG_NOTIFY); + + //e_LogWritefln('PANADD: pannum=%s', [pannum]); // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð PanelID := CreatePanel(rec, AddTextures, CurTex, trigRef); //e_LogWritefln('panel #%s of type %s got id #%s', [pannum, rec.PanelType, PanelID]); + // set 'gamePanelId' field to panel id + rec.userPanelId := PanelID; // remember game panel id, we'll fix triggers later - // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé 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].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; - *) + //e_LogWritefln('PANEND: pannum=%s', [pannum]); g_Game_StepLoading(); end; end; - (* + // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ + for b := 0 to High(TriggersTable) do 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; + if (TriggersTable[b].texPan <> nil) then TriggersTable[b].texPanIdx := TriggersTable[b].texPan.userPanelId; + if (TriggersTable[b].liftPan <> nil) then TriggersTable[b].LiftPanelIdx := TriggersTable[b].liftPan.userPanelId; + if (TriggersTable[b].doorPan <> nil) then TriggersTable[b].DoorPanelIdx := TriggersTable[b].doorPan.userPanelId; + if (TriggersTable[b].shotPan <> nil) then TriggersTable[b].ShotPanelIdx := TriggersTable[b].shotPan.userPanelId; end; - *) // create map grid, init other grids (for monsters, for example) e_WriteLog('Creating map grid', MSG_NOTIFY); @@ -1926,47 +1975,13 @@ begin 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; - tgpid := -1; + // we can have only one of those if (TriggersTable[trignum].LiftPanelIdx <> -1) then tgpid := TriggersTable[trignum].LiftPanelIdx else if (TriggersTable[trignum].DoorPanelIdx <> -1) then tgpid := TriggersTable[trignum].DoorPanelIdx else if (TriggersTable[trignum].ShotPanelIdx <> -1) then tgpid := TriggersTable[trignum].ShotPanelIdx else tgpid := -1; - (* - if (rec.TexturePanel <> -1) then - begin - { - 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 := mapReader.panel[TriggersTable[trignum].texPanIdx].PanelType; - assert(TriggersTable[trignum].texPanIdx >= 0); - b := TriggersTable[trignum].texPanIdx; - end - else - begin - b := 0; - end; - 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 := mapReader.panel[TriggersTable[trignum].ShotPanel].PanelType; - assert(TriggersTable[trignum].ShotPanelIdx >= 0); - c := TriggersTable[trignum].ShotPanelIdx; - end - else - begin - c := 0; - end; - *) //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, tgpid, Word(b), Word(c)); + CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c)); end; end; @@ -2008,8 +2023,8 @@ begin for rec in monsters do CreateMonster(rec); end; - //MapReader.Free(); - gCurrentMap := mapReader; + gCurrentMap := mapReader; // this will be our current map now + gCurrentMapFileName := Res; mapReader := nil; // Çàãðóçêà íåáà @@ -2069,7 +2084,7 @@ begin if not gLoadGameMode then g_GFX_Init(); // Ñáðîñ ëîêàëüíûõ ìàññèâîâ: - _textures := nil; + mapTextureList := nil; panels := nil; items := nil; areas := nil; @@ -2087,23 +2102,23 @@ begin begin gMusic.SetByName(''); end; + + stt := curTimeMicro()-stt; + e_LogWritefln('map loaded in %s.%s milliseconds', [Integer(stt div 1000), Integer(stt mod 1000)]); finally sfsGCEnable(); // enable releasing unused volumes mapReader.Free(); - hashTextPan.Free(); - hashLiftPan.Free(); - hashDoorPan.Free(); - hashShotPan.Free(); end; e_WriteLog('Done loading map.', MSG_NOTIFY); Result := True; end; + function g_Map_GetMapInfo(Res: String): TMapInfo; var WAD: TWADFile; - MapReader: TDynRecord; + mapReader: TDynRecord; //Header: TMapHeaderRec_1; FileName: String; Data: Pointer; @@ -2128,22 +2143,6 @@ begin WAD.Free(); - { - MapReader := TMapReader_1.Create(); - if not MapReader.LoadMap(Data) then - begin - g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True); - ZeroMemory(@Header, SizeOf(Header)); - Result.Name := _lc[I_GAME_ERROR_MAP_SELECT]; - Result.Description := _lc[I_GAME_ERROR_MAP_SELECT]; - end - else - begin - Header := MapReader.GetMapHeader(); - Result.Name := Header.MapName; - Result.Description := Header.MapDescription; - end; - } try mapReader := g_Map_ParseMap(Data, Len); except @@ -2151,10 +2150,6 @@ begin end; FreeMem(Data); - //MapReader.Free(); - - //if (mapReader <> nil) then Header := GetMapHeader(mapReader) else FillChar(Header, sizeof(Header), 0); - //MapReader.Free(); if (mapReader.Width > 0) and (mapReader.Height > 0) then begin @@ -2235,7 +2230,7 @@ begin end; end; -procedure g_Map_Free(); +procedure g_Map_Free(freeTextures: Boolean=true); var a: Integer; @@ -2274,17 +2269,42 @@ begin //gDOMFlags := nil; - if Textures <> nil then + if (Length(gCurrentMapFileName) <> 0) then begin - for a := 0 to High(Textures) do - if not g_Map_IsSpecialTexture(Textures[a].TextureName) then - if Textures[a].Anim then - g_Frames_DeleteByID(Textures[a].FramesID) - else - if Textures[a].TextureID <> LongWord(TEXTURE_NONE) then - e_DeleteTexture(Textures[a].TextureID); - - Textures := nil; + e_LogWritefln('g_Map_Free: previous map was ''%s''...', [gCurrentMapFileName]); + end + else + begin + e_LogWritefln('g_Map_Free: no previous map.', []); + end; + if freeTextures then + begin + e_LogWritefln('g_Map_Free: clearing textures...', []); + if (Textures <> nil) then + begin + for a := 0 to High(Textures) do + begin + if not g_Map_IsSpecialTexture(Textures[a].TextureName) then + begin + if Textures[a].Anim then + begin + g_Frames_DeleteByID(Textures[a].FramesID) + end + else + begin + if (Textures[a].TextureID <> LongWord(TEXTURE_NONE)) then + begin + e_DeleteTexture(Textures[a].TextureID); + end; + end; + end; + end; + Textures := nil; + end; + TextNameHash.Free(); + TextNameHash := nil; + BadTextNameHash.Free(); + BadTextNameHash := nil; end; FreePanelArray(gWalls);