X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fgame%2Fg_map.pas;h=b79c972159203bd65018e370b88a54088893508e;hb=3bfb3c21b8428a30bcd430263499b64522b6e1d5;hp=85d551047d36f4b5d0bb2980e4e18f91f5a7da72;hpb=31fadda69508ddb1f225a2a471c1be888148ffac;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 85d5510..b79c972 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -189,6 +189,25 @@ const FLAG_SIGNATURE = $47414C46; // 'FLAG' +type + TPanelGrid = specialize TBodyGridBase; + + TDynAABBTreePanelBase = specialize TDynAABBTreeBase; + + TDynAABBTreeMap = class(TDynAABBTreePanelBase) + function getFleshAABB (out aabb: AABB2D; pan: TPanel; tag: Integer): Boolean; override; + end; + +function TDynAABBTreeMap.getFleshAABB (out aabb: AABB2D; pan: TPanel; tag: Integer): Boolean; +begin + result := false; + if (pan = nil) then begin aabb := AABB2D.Create(0, 0, 0, 0); exit; end; + aabb := AABB2D.Create(pan.X, pan.Y, pan.X+pan.Width-1, pan.Y+pan.Height-1); + if (pan.Width < 1) or (pan.Height < 1) then exit; + if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!'); + result := true; +end; + function panelTypeToTag (panelType: Word): Integer; begin @@ -232,49 +251,26 @@ type PArrID: Integer; end; -type - TDynAABBTreeMap = class(TDynAABBTree) - function getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh): Boolean; override; - end; - -function TDynAABBTreeMap.getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh): Boolean; -var - pan: TPanel; -begin - result := false; - if (flesh = nil) then begin aabb := AABB2D.Create(0, 0, 0, 0); exit; end; - //pan := (flesh as TPanel); - pan := TPanel(flesh); - aabb := AABB2D.Create(pan.X, pan.Y, pan.X+pan.Width, pan.Y+pan.Height); - if (pan.Width < 1) or (pan.Height < 1) then exit; - //if (pan.Width = 1) then aabb.maxX += 1; - //if (pan.Height = 1) then aabb.maxY += 1; - //if (pan.Width < 3) or (pan.Height < 3) then exit; - //aabb := AABB2D.Create(pan.X, pan.Y, pan.X+pan.Width-2, pan.Y+pan.Height-2); - if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!'); - result := aabb.valid; -end; - var PanelById: array of TPanelID; Textures: TLevelTextureArray; RespawnPoints: Array of TRespawnPoint; FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint; //DOMFlagPoints: Array of TFlagPoint; - gMapGrid: TBodyGrid = nil; - mapTree: TDynAABBTree = nil; + gMapGrid: TPanelGrid = nil; + mapTree: TDynAABBTreeMap = nil; procedure g_Map_ProfilersBegin (); begin - if (profMapCollision = nil) then profMapCollision := TProfiler.Create('MAP COLLISION', g_profile_history_size); + if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size); profMapCollision.mainBegin(g_profile_collision); // create sections if g_profile_collision then begin - profMapCollision.sectionBegin('wall coldet'); + profMapCollision.sectionBegin('*solids'); profMapCollision.sectionEnd(); - profMapCollision.sectionBegin('liquid coldet'); + profMapCollision.sectionBegin('liquids'); profMapCollision.sectionEnd(); end; end; @@ -939,45 +935,52 @@ end; procedure CreateMonster(monster: TMonsterRec_1); var - a, i: Integer; + a: Integer; + mon: TMonster; begin if g_Game_IsClient then Exit; if (gGameSettings.GameType = GT_SINGLE) or LongBool(gGameSettings.Options and GAME_OPTION_MONSTERS) then begin - i := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, - TDirection(monster.Direction)); + mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction)); if gTriggers <> nil then + begin for a := 0 to High(gTriggers) do - if gTriggers[a].TriggerType in [TRIGGER_PRESS, - TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then - if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then - gMonsters[i].AddTrigger(a); + 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); + end; + end; + end; - if monster.MonsterType <> MONSTER_BARREL then - Inc(gTotalMonsters); + if monster.MonsterType <> MONSTER_BARREL then Inc(gTotalMonsters); end; end; procedure g_Map_ReAdd_DieTriggers(); -var - i, a: Integer; -begin - if g_Game_IsClient then Exit; - for i := 0 to High(gMonsters) do - if gMonsters[i] <> nil then + function monsDieTrig (monidx: Integer; mon: TMonster): Boolean; + var + a: Integer; + begin + result := false; // don't stop + mon.ClearTriggers(); + for a := 0 to High(gTriggers) do + begin + if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then begin - gMonsters[i].ClearTriggers(); - - for a := 0 to High(gTriggers) do - if gTriggers[a].TriggerType in [TRIGGER_PRESS, - TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then - if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then - gMonsters[i].AddTrigger(a); + if (gTriggers[a].Data.MonsterID-1) = mon.StartID then mon.AddTrigger(a); end; + end; + end; + +begin + if g_Game_IsClient then Exit; + + g_Mons_ForEach(monsDieTrig); end; function extractWadName(resourceName: string): string; @@ -1081,7 +1084,7 @@ begin e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING); - gMapGrid := TBodyGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1); + gMapGrid := TPanelGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1); mapTree := TDynAABBTreeMap.Create(); addPanelsToGrid(gWalls, PANEL_WALL); @@ -1924,16 +1927,10 @@ end; // new algo procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); - function checker (obj: TObject; objx, objy, objw, objh: Integer; tag: Integer): Boolean; - var - pan: TPanel; + function checker (pan: TPanel; tag: Integer): Boolean; begin result := false; // don't stop, ever - //pan := (obj as TPanel); - pan := TPanel(obj); - //if (PanelType = PANEL_CLOSEDOOR) then begin if not pan.Door then exit; end else begin if pan.Door then exit; end; if ((tag and GridTagDoor) <> 0) <> pan.Door then exit; - //dplAddPanel(pan); gDrawPanelList.insert(pan); end; @@ -1950,26 +1947,13 @@ begin gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore)); end; // list will be rendered in `g_game.DrawPlayer()` - (* - while (gDrawPanelList.count > 0) do - begin - //(gDrawPanelList.front() as TPanel).Draw(); - TPanel(gDrawPanelList.front()).Draw(); - gDrawPanelList.popFront(); - end; - *) end; procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: Integer); - function checker (obj: TObject; objx, objy, objw, objh: Integer; tag: Integer): Boolean; - var - pan: TPanel; + function checker (pan: TPanel; tag: Integer): Boolean; begin result := false; // don't stop, ever - //if (tag <> GridTagWall) and (tag <> GridTagDoor) then exit; // only walls - //pan := (obj as TPanel); - pan := TPanel(obj); pan.DrawShadowVolume(lightX, lightY, radius); end; @@ -2145,45 +2129,40 @@ end; function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean; - - function checker (obj: TObject; objx, objy, objwidth, objheight: Integer; tag: Integer): Boolean; - var - pan: TPanel; + function checker (pan: TPanel; tag: Integer): Boolean; begin result := false; // don't stop, ever + if ((tag and (GridTagWall or GridTagDoor)) <> 0) then + begin + if not pan.Enabled then exit; + end; + if ((tag and GridTagLift) <> 0) then begin - pan := TPanel(obj); - if ((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, objx, objy, objwidth, objheight) then - begin - result := true; - exit; - end; + 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); + exit; end; if ((tag and GridTagBlockMon) <> 0) then begin - if ((not b1x3) or (objwidth+objheight >= 64)) and g_Collide(X, Y, Width, Height, objx, objy, objwidth, objheight) then - begin - result := True; - exit; - end; + result := ((not b1x3) or (pan.Width+pan.Height >= 64)) and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); + exit; end; // other shit - result := g_Collide(X, Y, Width, Height, objx, objy, objwidth, objheight); + result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); end; var tagmask: Integer = 0; begin - //TODO: detailed profile - if WordBool(PanelType and PANEL_WALL) then tagmask := tagmask or GridTagWall or GridTagDoor; + if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor); if WordBool(PanelType and PANEL_WATER) then tagmask := tagmask or GridTagWater; if WordBool(PanelType and PANEL_ACID1) then tagmask := tagmask or GridTagAcid1; if WordBool(PanelType and PANEL_ACID2) then tagmask := tagmask or GridTagAcid2; @@ -2193,7 +2172,7 @@ begin if (tagmask = 0) then begin result := false; exit; end; // just in case - if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('wall coldet'); + if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids'); if gdbg_map_use_accel_coldet then begin if gdbg_map_use_tree_coldet then @@ -2221,37 +2200,34 @@ end; function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD; var - cctype: Integer = 3; // priority: 0: water, 1: acid1, 2: acid2; 3: others (nothing) + 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 (obj: TObject; objx, objy, objwidth, objheight: Integer; tag: Integer): Boolean; - //var pan: TPanel; + 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; + //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit; // check priorities case cctype of - 0: if ((tag and GridTagWater) = 0) then exit; // only water - 1: if ((tag and (GridTagWater or GridTagAcid1)) = 0) then exit; // water, acid1 - //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // water, acid1, acid2 + 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, objx, objy, objwidth, objheight) then exit; + if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit; // yeah - //pan := (obj as TPanel); - texid := TPanel(obj).GetTextureID(); + 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 + // acid2? if ((tag and GridTagAcid2) <> 0) then cctype := 2; - // acid1 + // acid1? if ((tag and GridTagAcid1) <> 0) then cctype := 1; end; begin - //TODO: detailed profile? - if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquid coldet'); + if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquids'); if gdbg_map_use_accel_coldet then begin texid := TEXTURE_NONE;