X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=9943dba6998a8a40944a89aa3d03346db8189293;hb=8cd33b294accd2d91e74720607bc8d7402ac2d6c;hp=4455ed9a66578a53b0e53cca9dec46c7ab79292c;hpb=0cf1438ff1766dc311fbebc45f6171d64f757cd4;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 4455ed9..9943dba 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -196,6 +196,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); @@ -252,8 +253,9 @@ var implementation uses + {$INCLUDE ../nogl/noGLuses.inc} 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, + 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, @@ -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(); @@ -600,10 +607,10 @@ 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 @@ -612,9 +619,8 @@ end; function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; var tagmask: Integer = 0; - pmark: PoolMark; - hitcount: Integer; - ppan: PPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin result := false; @@ -628,39 +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; - 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; @@ -1347,6 +1345,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; @@ -1365,6 +1364,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)); @@ -2256,7 +2261,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(); @@ -2510,6 +2515,7 @@ var a, d, j: Integer; m: Word; s: String; + b: Byte; procedure UpdatePanelArray(var panels: TPanelArray); var @@ -2560,6 +2566,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; @@ -2625,43 +2640,25 @@ end; // new algo procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; begin dplClear(); - 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 gDrawPanelList.insert(phit^); - 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); var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; begin - 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); + 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; @@ -2762,10 +2759,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 @@ -2841,10 +2838,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; @@ -2862,9 +2859,8 @@ const var tagmask: Integer = 0; - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; pan: TPanel; begin result := false; @@ -2881,22 +2877,20 @@ begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids'); if gdbg_map_use_accel_coldet then begin - pmark := framePool.mark(); if ((tagmask and SlowMask) <> 0) then begin // slow - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); + for mwit in it do begin - pan := phit^; + pan := mwit^; 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 + ((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 @@ -2909,17 +2903,15 @@ begin result := true; // i found her! end; if (result) then break; - Inc(phit); - Dec(hitcount); end; end else begin // fast - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit - result := (hitcount > 0); + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit + result := (it.length > 0); end; - framePool.release(pmark); + it.release(); end else begin @@ -2955,27 +2947,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 - 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 result := LongWord(TEXTURE_NONE); - 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); + 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 @@ -3071,10 +3052,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);