X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=4f86e9b0d3f14ddc3f21e097756080f4996e2e12;hb=836fd31457a6f741815605633f2fbfa157e37418;hp=8fa48d2735c4922cbd930d9a9c41b8abf22827dd;hpb=834fce43a6f96778d815cf0f8f858dfee0de9058;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 8fa48d2..4f86e9b 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -92,17 +92,23 @@ procedure g_Map_LoadState(Var Mem: TBinMemoryReader); procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: Integer); -// returns wall index in `gWalls` or -1 -function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil; log: Boolean=false): Boolean; +// returns panel or nil +// sets `ex` and `ey` to `x1` and `y1` when no hit was detected +function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel; + +// returns panel or nil +// sets `ex` and `ey` to `x1` and `y1` when no hit was detected +function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel; type TForEachPanelCB = function (pan: TPanel): Boolean; // return `true` to stop function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; +function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel; // trace liquid, stepping by `dx` and `dy` // return last seen liquid coords, and `false` if we're started outside of the liquid -function g_Map_TraceLiquid (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean; +function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean; procedure g_Map_ProfilersBegin (); @@ -184,9 +190,17 @@ 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()` + function panelTypeToTag (panelType: Word): Integer; // returns GridTagXXX +type + TPanelGrid = specialize TBodyGridBase; + +var + mapGrid: TPanelGrid = nil; // DO NOT USE! public for debugging only! + + implementation uses @@ -204,10 +218,6 @@ const FLAG_SIGNATURE = $47414C46; // 'FLAG' -type - TPanelGrid = specialize TBodyGridBase; - - function panelTypeToTag (panelType: Word): Integer; begin case panelType of @@ -255,7 +265,6 @@ var RespawnPoints: Array of TRespawnPoint; FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint; //DOMFlagPoints: Array of TFlagPoint; - mapGrid: TPanelGrid = nil; procedure g_Map_ProfilersBegin (); @@ -279,14 +288,30 @@ end; // wall index in `gWalls` or -1 -function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil; log: Boolean=false): Boolean; +function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel; +var + ex, ey: Integer; +begin + result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, (GridTagWall or GridTagDoor)); + if (result <> nil) then + begin + if (hitx <> nil) then hitx^ := ex; + if (hity <> nil) then hity^ := ey; + end + else + begin + if (hitx <> nil) then hitx^ := x1; + if (hity <> nil) then hity^ := y1; + end; +end; + +// returns panel or nil +function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel; var ex, ey: Integer; begin - mapGrid.dbgShowTraceLog := log; - result := (mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, (GridTagWall or GridTagDoor)) <> nil); - mapGrid.dbgShowTraceLog := false; - if result then + result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, tag); + if (result <> nil) then begin if (hitx <> nil) then hitx^ := ex; if (hity <> nil) then hity^ := ey; @@ -352,6 +377,14 @@ begin end; +function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel; +begin + result := nil; + if (tagmask = 0) then exit; + result := mapGrid.forEachAtPoint(x, y, nil, tagmask); +end; + + function g_Map_IsSpecialTexture(Texture: String): Boolean; begin Result := (Texture = TEXTURE_NAME_WATER) or @@ -1123,25 +1156,49 @@ var end; end; - procedure addPanelsToGrid (constref panels: TPanelArray; tag: Integer); + procedure addPanelsToGrid (constref panels: TPanelArray); var idx: Integer; pan: TPanel; + newtag: Integer; begin - tag := panelTypeToTag(tag); - for idx := High(panels) downto 0 do + //tag := panelTypeToTag(tag); + for idx := 0 to High(panels) do begin pan := panels[idx]; - pan.tag := tag; if not pan.visvalid then continue; - pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, tag); + if (pan.proxyId <> -1) then + begin + {$IF DEFINED(D2F_DEBUG)} + e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), MSG_NOTIFY); + {$ENDIF} + continue; + end; + case pan.PanelType of + PANEL_WALL: newtag := GridTagWall; + PANEL_OPENDOOR, PANEL_CLOSEDOOR: newtag := GridTagDoor; + PANEL_BACK: newtag := GridTagBack; + PANEL_FORE: newtag := GridTagFore; + PANEL_WATER: newtag := GridTagWater; + PANEL_ACID1: newtag := GridTagAcid1; + PANEL_ACID2: newtag := GridTagAcid2; + PANEL_STEP: newtag := GridTagStep; + PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: newtag := GridTagLift; + PANEL_BLOCKMON: newtag := GridTagBlockMon; + else continue; // oops + end; + pan.tag := newtag; + + pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, newtag); // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh... mapGrid.proxyEnabled[pan.proxyId] := pan.Enabled; {$IFDEF MAP_DEBUG_ENABLED_FLAG} + { if ((tag and (GridTagWall or GridTagDoor)) <> 0) then begin e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY); end; + } {$ENDIF} end; end; @@ -1160,21 +1217,26 @@ begin calcBoundingBox(gLifts); calcBoundingBox(gBlockMon); - e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING); + e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]); + + if (mapX0 > 0) then mapX0 := 0; + if (mapY0 > 0) then mapY0 := 0; - mapGrid := TPanelGrid.Create(mapX0-512, mapY0-512, mapX1-mapX0+1+512*2, mapY1-mapY0+1+512*2); + if (mapX1 < gMapInfo.Width-1) then mapX1 := gMapInfo.Width-1; + if (mapY1 < gMapInfo.Height-1) then mapY1 := gMapInfo.Height-1; - addPanelsToGrid(gWalls, PANEL_WALL); - addPanelsToGrid(gWalls, PANEL_CLOSEDOOR); - addPanelsToGrid(gWalls, PANEL_OPENDOOR); - addPanelsToGrid(gRenderBackgrounds, PANEL_BACK); - addPanelsToGrid(gRenderForegrounds, PANEL_FORE); - addPanelsToGrid(gWater, PANEL_WATER); - addPanelsToGrid(gAcid1, PANEL_ACID1); - addPanelsToGrid(gAcid2, PANEL_ACID2); - addPanelsToGrid(gSteps, PANEL_STEP); - addPanelsToGrid(gLifts, PANEL_LIFTUP); // it doesn't matter which LIFT type is used here - addPanelsToGrid(gBlockMon, PANEL_BLOCKMON); + mapGrid := TPanelGrid.Create(mapX0-128, mapY0-128, mapX1-mapX0+1+128*2, mapY1-mapY0+1+128*2); + //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height); + + addPanelsToGrid(gWalls); + addPanelsToGrid(gRenderBackgrounds); + addPanelsToGrid(gRenderForegrounds); + addPanelsToGrid(gWater); + addPanelsToGrid(gAcid1); + addPanelsToGrid(gAcid2); + addPanelsToGrid(gSteps); + addPanelsToGrid(gLifts); // it doesn't matter which LIFT type is used here + addPanelsToGrid(gBlockMon); mapGrid.dumpStats(); @@ -1269,6 +1331,22 @@ begin _textures := MapReader.GetTextures(); _texnummap := nil; + // Çàãðóçêà îïèñàíèÿ êàðòû: + e_WriteLog(' Reading map info...', MSG_NOTIFY); + g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False); + Header := MapReader.GetMapHeader(); + + 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; + end; + // Äîáàâëåíèå òåêñòóð â Textures[]: if _textures <> nil then begin @@ -1281,12 +1359,16 @@ 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; + {$IF DEFINED(D2F_DEBUG)} e_WriteLog(Format(' Loading texture #%d: %s', [a, s]), MSG_NOTIFY); + {$ENDIF} //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY); // Àíèìèðîâàííàÿ òåêñòóðà: if ByteBool(_textures[a].Anim) then @@ -1528,7 +1610,6 @@ begin e_WriteLog('Creating map grid', MSG_NOTIFY); mapCreateGrid(); - // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû: if (triggers <> nil) and not gLoadGameMode then begin @@ -1594,24 +1675,8 @@ begin CreateMonster(monsters[a]); end; - // Çàãðóçêà îïèñàíèÿ êàðòû: - e_WriteLog(' Reading map info...', MSG_NOTIFY); - g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False); - Header := MapReader.GetMapHeader(); - MapReader.Free(); - 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; - end; - // Çàãðóçêà íåáà: if gMapInfo.SkyName <> '' then begin @@ -2025,7 +2090,7 @@ begin end else} begin - mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask, true); + mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask); end; // list will be rendered in `g_game.DrawPlayer()` end; @@ -2046,7 +2111,7 @@ begin end else} begin - mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor), true); + mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor)); end; end; @@ -2382,7 +2447,7 @@ begin if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(gWalls[ID].PanelType, ID); {$IFDEF MAP_DEBUG_ENABLED_FLAG} - e_WriteLog(Format('wall #%d(%d) enabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); + //e_WriteLog(Format('ENABLE: wall #%d(%d) enabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); {$ENDIF} end; @@ -2400,7 +2465,7 @@ begin if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, ID); {$IFDEF MAP_DEBUG_ENABLED_FLAG} - e_WriteLog(Format('wall #%d(%d) disabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); + //e_WriteLog(Format('DISABLE: wall #%d(%d) disabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); {$ENDIF} end; @@ -2696,6 +2761,7 @@ var PAMem.LoadFromMemory(Mem); for i := 0 to Length(panels)-1 do + begin if panels[i].SaveIt then begin // ID ïàíåëè: @@ -2706,7 +2772,10 @@ var end; // Çàãðóæàåì ïàíåëü: panels[i].LoadState(PAMem); + if (panels[i].arrIdx <> i) then raise Exception.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel arrIdx'); + if (panels[i].proxyId >= 0) then mapGrid.proxyEnabled[panels[i].proxyId] := panels[i].Enabled; end; + end; // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí: PAMem.Free(); @@ -2759,7 +2828,7 @@ begin // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó: g_GFX_Init(); - mapCreateGrid(); + //mapCreateGrid(); ///// Çàãðóæàåì ìóçûêó: ///// // Ñèãíàòóðà ìóçûêè: @@ -2822,7 +2891,7 @@ end; // trace liquid, stepping by `dx` and `dy` // return last seen liquid coords, and `false` if we're started outside of the liquid -function g_Map_TraceLiquid (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean; +function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean; const MaskLiquid = GridTagWater or GridTagAcid1 or GridTagAcid2; begin