X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=95bb1a02fd813f82536e759ee6a2b0cfa1f86f8c;hb=414f2873efa0cce84499f64774db7000e6268971;hp=29ece6fafd845f590715a7502689b9fc1dc2630a;hpb=200614b5c22e6bdd6a7919b6acc9c1cf74ecfb6b;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 29ece6f..95bb1a0 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -196,6 +195,7 @@ const GridTagLift = 1 shl 8; // gLifts GridTagBlockMon = 1 shl 9; // gBlockMon + GridTagSolid = (GridTagWall or GridTagDoor); GridTagObstacle = (GridTagStep or GridTagWall or GridTagDoor); GridTagLiquid = (GridTagAcid1 or GridTagAcid2 or GridTagWater); @@ -226,7 +226,7 @@ var gLiftMap: array of array of DWORD; gWADHash: TMD5Digest; BackID: DWORD = DWORD(-1); - gExternalResources: TStringList; + gExternalResources: array of TDiskFileInfo = nil; gMovingWallIds: array of Integer = nil; gdbg_map_use_accel_render: Boolean = true; @@ -252,13 +252,15 @@ var implementation uses - e_input, g_main, e_log, e_texture, g_items, g_gfx, g_console, - GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG, + {$INCLUDE ../nogl/noGLuses.inc} + e_input, g_main, e_log, e_texture, e_res, g_items, g_gfx, g_console, + g_weapons, g_game, g_sound, e_sound, CONFIG, g_options, g_triggers, g_player, Math, g_monsters, g_saveload, g_language, g_netmsg, sfs, xstreams, hashtable, wadreader, ImagingTypes, Imaging, ImagingUtility, - ImagingGif, ImagingNetworkGraphics; + ImagingGif, ImagingNetworkGraphics, + g_res_downloader; const FLAGRECT: TRectWH = (X:15; Y:12; Width:33; Height:52); @@ -343,8 +345,8 @@ begin try e_LogWritefln('parsing "mapdef.txt"...', []); - st := openDiskFileRO(DataDir+'mapdef.txt'); - e_LogWritefln('found local "%smapdef.txt"', [DataDir]); + st := e_OpenResourceRO(DataDirs, 'mapdef.txt'); + e_LogWritefln('found local "mapdef.txt"', []); except st := nil; end; @@ -434,17 +436,19 @@ end; // ////////////////////////////////////////////////////////////////////////// // var NNF_PureName: String; // Èìÿ òåêñòóðû áåç öèôð â êîíöå + NNF_PureExt: String; // extension postfix NNF_FirstNum: Integer; // ×èñëî ó íà÷àëüíîé òåêñòóðû NNF_CurrentNum: Integer; // Ñëåäóþùåå ÷èñëî ó òåêñòóðû function g_Texture_NumNameFindStart(name: String): Boolean; var - i: Integer; + i, j: Integer; begin Result := False; NNF_PureName := ''; + NNF_PureExt := ''; NNF_FirstNum := -1; NNF_CurrentNum := -1; @@ -457,8 +461,11 @@ begin end else begin + j := i + 1; + while (j <= Length(name)) and (name[j] <> '.') do inc(j); NNF_PureName := Copy(name, 1, i); - Delete(name, 1, i); + NNF_PureExt := Copy(name, j); + name := Copy(name, i + 1, j - i - 1); Break; end; end; @@ -482,7 +489,7 @@ begin Exit; end; - newName := NNF_PureName + IntToStr(NNF_CurrentNum); + newName := NNF_PureName + IntToStr(NNF_CurrentNum) + NNF_PureExt; if NNF_CurrentNum < NNF_FirstNum then Result := NNF_NAME_BEFORE @@ -540,9 +547,9 @@ var procedure g_Map_ProfilersBegin (); begin if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size); - profMapCollision.mainBegin(g_profile_collision); + if (profMapCollision <> nil) then profMapCollision.mainBegin(g_profile_collision); // create sections - if g_profile_collision then + if g_profile_collision and (profMapCollision <> nil) then begin profMapCollision.sectionBegin('*solids'); profMapCollision.sectionEnd(); @@ -562,7 +569,7 @@ function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; var ex, ey: Integer; begin - result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, (GridTagWall or GridTagDoor)); + result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, (GridTagWall or GridTagDoor)); if (result <> nil) then begin if (hitx <> nil) then hitx^ := ex; @@ -580,7 +587,7 @@ function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInt var ex, ey: Integer; begin - result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, tag); + result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, tag); if (result <> nil) then begin if (hitx <> nil) then hitx^ := ex; @@ -600,46 +607,20 @@ begin begin // stop if the lift of the right type result := - ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = 0)) or - (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = 1)) or - (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = 2)) or - (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))); + ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = LIFTTYPE_UP)) or + (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = LIFTTYPE_DOWN)) or + (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = LIFTTYPE_LEFT)) or + (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = LIFTTYPE_RIGHT))); exit; end; result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels end; function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; - - function checker (pan: TPanel; tag: Integer): Boolean; - begin - { - if ((tag and (GridTagWall or GridTagDoor)) <> 0) then - begin - result := pan.Enabled; // stop if wall is enabled - exit; - end; - } - - if ((tag and GridTagLift) <> 0) then - begin - // stop if the lift of the right type - result := - ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = 0)) or - (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = 1)) or - (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = 2)) or - (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))); - exit; - end; - - result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels - end; - var tagmask: Integer = 0; - pmark: PoolMark; - hitcount: Integer; - ppan: PPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin result := false; @@ -653,40 +634,31 @@ begin if (tagmask = 0) then exit;// just in case - pmark := framePool.mark(); if ((tagmask and GridTagLift) <> 0) then begin // slow - hitcount := mapGrid.forEachAtPoint(x, y, tagmask); - ppan := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - if (xxPanAtPointChecker(ppan^, PanelType)) then begin result := true; break; end; - Inc(ppan); - Dec(hitcount); - end; + it := mapGrid.forEachAtPoint(x, y, tagmask); + for mwit in it do if (xxPanAtPointChecker(mwit^, PanelType)) then begin result := true; break; end; end else begin // fast - result := (mapGrid.forEachAtPoint(x, y, tagmask, false, true) <> 0); // firsthit + it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); + result := (it.length <> 0); // firsthit end; - framePool.release(pmark); + it.release(); end; function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel; var - pmark: PoolMark; - hitcount: Integer; + it: TPanelGrid.Iter; begin result := nil; if (tagmask = 0) then exit; - //result := mapGrid.forEachAtPoint(x, y, nil, tagmask); - pmark := framePool.mark(); - hitcount := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit - if (hitcount <> 0) then result := PPanel(framePool.getPtr(pmark))^; - framePool.release(pmark); + it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit + if (it.length <> 0) then result := it.first^; + it.release(); end; @@ -928,6 +900,20 @@ begin end; +function GetReplacementWad (WadName: AnsiString): AnsiString; +begin + result := ''; + if WadName <> '' then + begin + result := WadName; + if g_Game_IsClient then + result := g_Res_FindReplacementWad(WadName); + if (result = WadName) then + result := e_FindWad(WadDirs, result) + end; +end; + + function CreateTexture(RecName: AnsiString; Map: string; log: Boolean): Integer; var WAD: TWADFile; @@ -986,12 +972,10 @@ begin end; // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à: - WADName := g_ExtractWadName(RecName); + WADName := GetReplacementWad(g_ExtractWadName(RecName)); + if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else WAD := TWADFile.Create(); - - if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map; - WAD.ReadFile(WADName); //txname := RecName; @@ -1074,11 +1058,12 @@ begin end; // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü: - WADName := g_ExtractWadName(RecName); + WADName := GetReplacementWad(g_ExtractWadName(RecName)); + if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else 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); @@ -1112,8 +1097,7 @@ begin end; // ýòî ïòèöà? ýòî ñàìîë¸ò? - if (TextureWAD[0] = 'D') and (TextureWAD[1] = 'F') and - (TextureWAD[2] = 'W') and (TextureWAD[3] = 'A') and (TextureWAD[4] = 'D') then + if isWadData(TextureWAD, ResLength) then begin // íåò, ýòî ñóïåðìåí! if not WAD.ReadMemory(TextureWAD, ResLength) then @@ -1373,6 +1357,7 @@ end; function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer): Integer; var _trigger: TTrigger; + tp: TPanel; begin result := -1; if g_Game_IsClient and not (Trigger.TriggerType in [TRIGGER_SOUND, TRIGGER_MUSIC]) then Exit; @@ -1391,6 +1376,12 @@ begin ActivateType := Trigger.ActivateType; Keys := Trigger.Keys; trigPanelGUID := atrigpanid; + // HACK: used in TPanel.CanChangeTexture. maybe there's a better way? + if TexturePanelGUID <> -1 then + begin + tp := g_Map_PanelByGUID(TexturePanelGUID); + if (tp <> nil) then tp.hasTexTrigger := True; + end; end; result := Integer(g_Triggers_Create(_trigger, Trigger)); @@ -1469,50 +1460,66 @@ begin Result := ''; end; -procedure addResToExternalResList(res: string); -begin - res := extractWadName(res); - if (res <> '') and (gExternalResources.IndexOf(res) = -1) then - gExternalResources.Add(res); -end; -procedure generateExternalResourcesList({mapReader: TMapReader_1}map: TDynRecord); -//var - //textures: TTexturesRec1Array; - //textures: TDynField; - //trec: TDynRecord; - //mapHeader: TMapHeaderRec_1; - //i: integer; - //resFile: String = ''; +procedure addResToExternalResList (res: AnsiString); +var + uname: AnsiString; + f: Integer; + fi: TDiskFileInfo; begin - if gExternalResources = nil then - gExternalResources := TStringList.Create; - - gExternalResources.Clear; - - (* - { - textures := GetTextures(map); - for i := 0 to High(textures) do + if g_Game_IsClient or not g_Game_IsNet then exit; + if (length(res) = 0) then exit; // map wad + res := extractWadName(res); + if (length(res) = 0) then exit; // map wad + uname := toLowerCase1251(res); + // do not add duplicates + for f := 0 to High(gExternalResources) do begin - addResToExternalResList(resFile); + if (gExternalResources[f].userName = uname) then exit; end; - } + // add new resource + fi.userName := uname; + if (not GetDiskFileInfo(GameDir+'/wads/'+res, fi)) then + begin + fi.tag := -1; + end + else + begin + fi.tag := 0; // non-zero means "cannot caclucate hash" + try + fi.hash := MD5File(fi.diskName); + except + fi.tag := -1; + end; + end; + //e_LogWritefln('addext: res=[%s]; uname=[%s]; diskName=[%s]', [res, fi.userName, fi.diskName]); + SetLength(gExternalResources, length(gExternalResources)+1); + gExternalResources[High(gExternalResources)] := fi; +end; + - textures := map['texture']; - if (textures <> nil) then +procedure compactExtResList (); +var + src, dest: Integer; +begin + src := 0; + dest := 0; + for src := 0 to High(gExternalResources) do begin - for trec in textures do + if (gExternalResources[src].tag = 0) then begin - addResToExternalResList(resFile); + // copy it + if (dest <> src) then gExternalResources[dest] := gExternalResources[src]; + Inc(dest); end; end; + if (dest <> length(gExternalResources)) then SetLength(gExternalResources, dest); +end; - textures := nil; - *) - - //mapHeader := GetMapHeader(map); +procedure generateExternalResourcesList (map: TDynRecord); +begin + SetLength(gExternalResources, 0); addResToExternalResList(map.MusicName); addResToExternalResList(map.SkyName); end; @@ -1697,7 +1704,7 @@ begin if (gCurrentMap = nil) then begin FileName := g_ExtractWadName(Res); - e_WriteLog('Loading map WAD: '+FileName, TMsgType.Notify); + e_LogWritefln('Loading map WAD [%s] (res=[%s])', [FileName, Res], TMsgType.Notify); g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False); WAD := TWADFile.Create(); @@ -1857,7 +1864,14 @@ begin ntn := CreateTexture(rec.Resource, FileName, True); if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [rec.Resource])); end; - if (ntn < 0) then ntn := CreateNullTexture(rec.Resource); + if (ntn < 0) then + begin + ntn := CreateNullTexture(rec.Resource); + end + else + begin + addResToExternalResList(rec.Resource); + end; rec.tagInt := ntn; // remember texture number end; @@ -2203,21 +2217,13 @@ begin begin e_WriteLog(' Loading sky: ' + gMapInfo.SkyName, TMsgType.Notify); g_Game_SetLoadingText(_lc[I_LOAD_SKY], 0, False); - FileName := g_ExtractWadName(gMapInfo.SkyName); - - if (FileName <> '') then FileName := GameDir+'/wads/'+FileName else FileName := g_ExtractWadName(Res); - if gTextureFilter then TEXTUREFILTER := GL_LINEAR else TEXTUREFILTER := GL_NEAREST; try - s := FileName+':'+g_ExtractFilePathName(gMapInfo.SkyName); + s := e_GetResourcePath(WadDirs, gMapInfo.SkyName, g_ExtractWadName(Res)); if g_Texture_CreateWAD(BackID, s) then - begin - g_Game_SetupScreenSize(); - end + g_Game_SetupScreenSize else - begin - g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s])); - end; + g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s])) finally TEXTUREFILTER := GL_NEAREST; end; @@ -2229,16 +2235,8 @@ begin begin e_WriteLog(' Loading music: ' + gMapInfo.MusicName, TMsgType.Notify); g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False); - FileName := g_ExtractWadName(gMapInfo.MusicName); - - if FileName <> '' then - FileName := GameDir+'/wads/'+FileName - else - begin - FileName := g_ExtractWadName(Res); - end; - s := FileName+':'+g_ExtractFilePathName(gMapInfo.MusicName); + s := e_GetResourcePath(WadDirs, gMapInfo.MusicName, g_ExtractWadName(Res)); if g_Sound_CreateWADEx(gMapInfo.MusicName, s, True) then ok := True else @@ -2282,7 +2280,7 @@ begin finally sfsGCEnable(); // enable releasing unused volumes //mapReader.Free(); - e_ClearInputBuffer(); // why not? + e_UnpressAllKeys; // why not? if not mapOk then begin gCurrentMap.Free(); @@ -2291,6 +2289,7 @@ begin end; end; + compactExtResList(); e_WriteLog('Done loading map.', TMsgType.Notify); Result := True; end; @@ -2536,6 +2535,7 @@ var a, d, j: Integer; m: Word; s: String; + b: Byte; procedure UpdatePanelArray(var panels: TPanelArray); var @@ -2586,6 +2586,15 @@ begin s := _lc[I_PLAYER_FLAG_BLUE]; g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144); + if (((gPlayer1 <> nil) and (((gPlayer1.Team = TEAM_RED) and (a = FLAG_RED)) or ((gPlayer1.Team = TEAM_BLUE) and (a = FLAG_BLUE)))) + or ((gPlayer2 <> nil) and (((gPlayer2.Team = TEAM_RED) and (a = FLAG_RED)) or ((gPlayer2.Team = TEAM_BLUE) and (a = FLAG_BLUE))))) then + b := 0 + else + b := 1; + + if not sound_ret_flag[b].IsPlaying() then + sound_ret_flag[b].Play(); + if g_Game_IsNet then MH_SEND_FlagEvent(FLAG_STATE_RETURNED, a, 0); Continue; @@ -2650,68 +2659,26 @@ end; // new algo procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); - (* - function checker (pan: TPanel; tag: Integer): Boolean; - begin - result := false; // don't stop, ever - if ((tag and GridTagDoor) <> 0) <> pan.Door then exit; - gDrawPanelList.insert(pan); - end; - *) var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; begin dplClear(); - //tagmask := panelTypeToTag(PanelType); - //mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask); - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - if ((phit^.tag and GridTagDoor) <> 0) <> phit^.Door then - begin - end - else - begin - gDrawPanelList.insert(phit^); - end; - Inc(phit); - Dec(hitcount); - end; - framePool.release(pmark); + it := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask); + for mwit in it do if (((mwit^.tag and GridTagDoor) <> 0) = mwit^.Door) then gDrawPanelList.insert(mwit^); + it.release(); // list will be rendered in `g_game.DrawPlayer()` end; procedure g_Map_DrawPanelShadowVolumes (lightX: Integer; lightY: Integer; radius: Integer); - (* - function checker (pan: TPanel; tag: Integer): Boolean; - begin - result := false; // don't stop, ever - pan.DrawShadowVolume(lightX, lightY, radius); - end; - *) var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; -begin - //mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor)); - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor)); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - phit^.DrawShadowVolume(lightX, lightY, radius); - Inc(phit); - Dec(hitcount); - end; - framePool.release(pmark); + mwit: PPanel; + it: TPanelGrid.Iter; +begin + it := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor)); + for mwit in it do mwit^.DrawShadowVolume(lightX, lightY, radius); + it.release(); end; @@ -2812,10 +2779,10 @@ begin h := High(gLifts); for a := 0 to h do - if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = 0)) or - (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = 1)) or - (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = 2)) or - (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = 3))) and + if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = LIFTTYPE_UP)) or + (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = LIFTTYPE_DOWN)) or + (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = LIFTTYPE_LEFT)) or + (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = LIFTTYPE_RIGHT))) and g_Collide(X, Y, Width, Height, gLifts[a].X, gLifts[a].Y, gLifts[a].Width, gLifts[a].Height) then @@ -2891,10 +2858,10 @@ const if ((tag and GridTagLift) <> 0) then begin result := - ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = 0)) or - (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = 1)) or - (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = 2)) or - (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))) {and + ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = LIFTTYPE_UP)) or + (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = LIFTTYPE_DOWN)) or + (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = LIFTTYPE_LEFT)) or + (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = LIFTTYPE_RIGHT))) {and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height)}; exit; end; @@ -2912,9 +2879,8 @@ const var tagmask: Integer = 0; - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; pan: TPanel; begin result := false; @@ -2931,64 +2897,41 @@ begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids'); if gdbg_map_use_accel_coldet then begin - {if (Width = 1) and (Height = 1) then - begin - if ((tagmask and SlowMask) <> 0) then - begin - // slow - result := (mapGrid.forEachAtPoint(X, Y, checker, tagmask) <> nil); - end - else - begin - // fast - result := (mapGrid.forEachAtPoint(X, Y, nil, tagmask) <> nil); - end; - end - else} + if ((tagmask and SlowMask) <> 0) then begin - pmark := framePool.mark(); - if ((tagmask and SlowMask) <> 0) then + // slow + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); + for mwit in it do begin - // slow - //result := (mapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask) <> nil); - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); - //if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do + pan := mwit^; + if ((pan.tag and GridTagLift) <> 0) then begin - pan := phit^; - if ((pan.tag and GridTagLift) <> 0) then - begin - result := - ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = 0)) or - (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = 1)) or - (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = 2)) or - (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))) {and - g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height)}; - end - else if ((pan.tag and GridTagBlockMon) <> 0) then - begin - result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); - end - else - begin - // other shit - result := true; // i found her! - end; - if (result) then break; - Inc(phit); - Dec(hitcount); + result := + ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = LIFTTYPE_UP)) or + (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = LIFTTYPE_DOWN)) or + (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = LIFTTYPE_LEFT)) or + (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = LIFTTYPE_RIGHT))) {and + g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height)}; + end + else if ((pan.tag and GridTagBlockMon) <> 0) then + begin + result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); + end + else + begin + // other shit + result := true; // i found her! end; - end - else - begin - // fast - //result := (mapGrid.forEachInAABB(X, Y, Width, Height, nil, tagmask) <> nil); - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit - result := (hitcount > 0); + if (result) then break; end; - framePool.release(pmark); + end + else + begin + // fast + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit + result := (it.length > 0); end; + it.release(); end else begin @@ -3024,65 +2967,16 @@ end; function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD; var cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit - //texid: DWORD; - - (* - // slightly different from the old code, but meh... - function checker (pan: TPanel; tag: Integer): Boolean; - begin - result := false; // don't stop, ever - //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit; - // check priorities - case cctype of - 0: if ((tag and GridTagWater) = 0) then exit; // allowed: water - 1: if ((tag and (GridTagWater or GridTagAcid1)) = 0) then exit; // allowed: water, acid1 - //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2 - end; - // collision? - //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit; - // yeah - texid := pan.GetTextureID(); - // water? water has the highest priority, so stop right here - if ((tag and GridTagWater) <> 0) then begin cctype := 0; result := true; exit; end; - // acid2? - if ((tag and GridTagAcid2) <> 0) then cctype := 2; - // acid1? - if ((tag and GridTagAcid1) <> 0) then cctype := 1; - end; - *) -var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; - pan: TPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquids'); if gdbg_map_use_accel_coldet then begin - {texid}result := LongWord(TEXTURE_NONE); - { - if (Width = 1) and (Height = 1) then - begin - mapGrid.forEachAtPoint(X, Y, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); - end - else - begin - mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); - end; - } - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2)); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - pan := phit^; - Inc(phit); - Dec(hitcount); - if (liquidChecker(pan, result, cctype)) then break; - end; - framePool.release(pmark); - //result := texid; + result := LongWord(TEXTURE_NONE); + it := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2)); + for mwit in it do if (liquidChecker(mwit^, result, cctype)) then break; + it.release(); end else begin @@ -3178,10 +3072,10 @@ begin //TODO: make separate lift tags, and change tag here case LiftType of - 0: g_Mark(X, Y, Width, Height, MARK_LIFTUP); - 1: g_Mark(X, Y, Width, Height, MARK_LIFTDOWN); - 2: g_Mark(X, Y, Width, Height, MARK_LIFTLEFT); - 3: g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT); + LIFTTYPE_UP: g_Mark(X, Y, Width, Height, MARK_LIFTUP); + LIFTTYPE_DOWN: g_Mark(X, Y, Width, Height, MARK_LIFTDOWN); + LIFTTYPE_LEFT: g_Mark(X, Y, Width, Height, MARK_LIFTLEFT); + LIFTTYPE_RIGHT: g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT); end; //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);