X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=33571b8bcd182fb5b61cbae55bfabfcd3c9f4a33;hb=db9e913bebcfba6251351e97118db8ee01c76cc0;hp=395a2ccbc4320a256545a286de9b34bb5e8e3137;hpb=d25ad51560a2159ff524fa9ef4ca37a81dcb528f;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 395a2cc..33571b8 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -109,7 +109,7 @@ function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; 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 + TForEachPanelCB = function (pan: TPanel): Boolean is nested; // 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; @@ -119,6 +119,12 @@ function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel; function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean; +// return `true` from `cb` to stop +function g_Map_ForEachPanel (cb: TForEachPanelCB): TPanel; + +procedure g_Map_NetSendInterestingPanels (); // yay! + + procedure g_Map_ProfilersBegin (); procedure g_Map_ProfilersEnd (); @@ -262,6 +268,34 @@ begin end; +// return `true` from `cb` to stop +function g_Map_ForEachPanel (cb: TForEachPanelCB): TPanel; +var + pan: TPanel; +begin + result := nil; + if not assigned(cb) then exit; + for pan in panByGUID do + begin + if cb(pan) then begin result := pan; exit; end; + end; +end; + + +procedure g_Map_NetSendInterestingPanels (); +var + pan: TPanel; +begin + if g_Game_IsServer and g_Game_IsNet then + begin + for pan in panByGUID do + begin + if pan.gncNeedSend then MH_SEND_PanelState(pan.guid); + end; + end; +end; + + // ////////////////////////////////////////////////////////////////////////// // function g_Map_MinX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0 else result := 0; end; function g_Map_MinY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0 else result := 0; end; @@ -273,6 +307,7 @@ function g_Map_MaxY (): Integer; inline; begin if (mapGrid <> nil) then result : var dfmapdef: TDynMapDef = nil; + procedure loadMapDefinition (); var pr: TTextParser = nil; @@ -280,13 +315,15 @@ var WAD: TWADFile = nil; begin if (dfmapdef <> nil) then exit; + try e_LogWritefln('parsing "mapdef.txt"...', []); st := openDiskFileRO(DataDir+'mapdef.txt'); + e_LogWritefln('found local "%smapdef.txt"', [DataDir]); except st := nil; - e_LogWritefln('local "%smapdef.txt" not found', [DataDir]); end; + if (st = nil) then begin WAD := TWADFile.Create(); @@ -301,15 +338,22 @@ begin end; end; - if (st = nil) then - begin - //raise Exception.Create('cannot open "mapdef.txt"'); - e_LogWritefln('using default "mapdef.txt"...', [], MSG_WARNING); - pr := TStrTextParser.Create(defaultMapDef); - end - else - begin - pr := TFileTextParser.Create(st); + try + if (st = nil) then + begin + //raise Exception.Create('cannot open "mapdef.txt"'); + e_LogWriteln('using default "mapdef.txt"...'); + pr := TStrTextParser.Create(defaultMapDef); + end + else + begin + pr := TFileTextParser.Create(st); + end; + except on e: Exception do + begin + e_LogWritefln('something is VERY wrong here! -- ', [e.message]); + raise; + end; end; try @@ -331,6 +375,8 @@ var begin result := nil; if (dataLen < 4) then exit; + + if (dfmapdef = nil) then writeln('need to load mapdef'); loadMapDefinition(); if (dfmapdef = nil) then raise Exception.Create('internal map loader error'); @@ -340,6 +386,7 @@ begin begin // binary map try + //e_LogWriteln('parsing binary map...'); result := dfmapdef.parseBinMap(wst); except on e: Exception do begin @@ -356,10 +403,11 @@ begin // text map pr := TFileTextParser.Create(wst); try + //e_LogWriteln('parsing text map...'); result := dfmapdef.parseMap(pr); except on e: Exception do begin - if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.line, pr.col, e.message]) + if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message]) else e_LogWritefln('ERROR: %s', [e.message]); pr.Free(); // will free `wst` result := nil; @@ -368,6 +416,7 @@ begin end; pr.Free(); // will free `wst` end; + //e_LogWriteln('map parsed.'); end; @@ -772,7 +821,7 @@ begin PanelArray := nil; end; -function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; sav: Boolean): Integer; +function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer): Integer; var len: Integer; panels: ^TPanelArray; @@ -807,7 +856,6 @@ begin pan.arrIdx := len; pan.proxyId := -1; pan.tag := panelTypeToTag(PanelRec.PanelType); - if sav then pan.SaveIt := True; PanelRec.user['panel_guid'] := pguid; @@ -1278,10 +1326,11 @@ begin end; end; -procedure CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word); +function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word): Integer; var _trigger: TTrigger; begin + result := -1; if g_Game_IsClient and not (Trigger.TriggerType in [TRIGGER_SOUND, TRIGGER_MUSIC]) then Exit; with _trigger do @@ -1313,11 +1362,11 @@ begin end else begin - trigData := Trigger.trigRec.clone(); + trigData := Trigger.trigRec.clone(nil); end; end; - g_Triggers_Create(_trigger); + result := Integer(g_Triggers_Create(_trigger)); end; procedure CreateMonster(monster: TDynRecord); @@ -1562,6 +1611,8 @@ type PTRec = ^TTRec; TTRec = record //TexturePanel: Integer; + tnum: Integer; + id: Integer; texPanIdx: Integer; LiftPanelIdx: Integer; DoorPanelIdx: Integer; @@ -1590,7 +1641,7 @@ var FileName, mapResName, s, TexName: String; Data: Pointer; Len: Integer; - ok, isAnim, trigRef: Boolean; + ok, isAnim: Boolean; CurTex, ntn: Integer; rec, texrec: TDynRecord; pttit: PTRec; @@ -1598,6 +1649,7 @@ var stt: UInt64; moveSpeed{, moveStart, moveEnd}: TDFPoint; //moveActive: Boolean; + pan: TPanel; begin mapGrid.Free(); mapGrid := nil; @@ -1662,6 +1714,12 @@ begin FreeMem(Data); + if (mapReader = nil) then + begin + e_LogWritefln('invalid map file: ''%s''', [mapResName]); + exit; + end; + generateExternalResourcesList(mapReader); mapTextureList := mapReader['texture']; // get all other lists here too @@ -1822,7 +1880,6 @@ begin //e_LogWritefln('PANSTART: pannum=%s', [pannum]); texrec := nil; SetLength(AddTextures, 0); - trigRef := False; CurTex := -1; ok := false; @@ -1839,21 +1896,9 @@ begin ok := false; 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 - begin - trigRef := True; - ok := True; - break; - end; - end; - } if rec.userPanelTrigRef then begin // e_LogWritefln('trigref for panel %s', [pannum]); - trigRef := True; ok := True; end; end; @@ -1981,7 +2026,7 @@ begin //e_LogWritefln('PANADD: pannum=%s', [pannum]); // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID - PanelID := CreatePanel(rec, AddTextures, CurTex, trigRef); + PanelID := CreatePanel(rec, AddTextures, CurTex); //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]); rec.userPanelId := PanelID; // remember game panel id, we'll fix triggers later @@ -2036,7 +2081,21 @@ begin else if (TriggersTable[trignum].MPlatPanelIdx <> -1) then tgpid := TriggersTable[trignum].MPlatPanelIdx else tgpid := -1; //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]); - CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c)); + TriggersTable[trignum].tnum := trignum; + TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c)); + end; + end; + + //FIXME: use hashtable! + for pan in panByGUID do + begin + if (pan.endPosTrigId >= 0) and (pan.endPosTrigId < Length(TriggersTable)) then + begin + pan.endPosTrigId := TriggersTable[pan.endPosTrigId].id; + end; + if (pan.endSizeTrigId >= 0) and (pan.endSizeTrigId < Length(TriggersTable)) then + begin + pan.endSizeTrigId := TriggersTable[pan.endSizeTrigId].id; end; end; @@ -2203,10 +2262,14 @@ begin mapReader := g_Map_ParseMap(Data, Len); except mapReader := nil; + FreeMem(Data); + exit; end; FreeMem(Data); + if (mapReader = nil) then exit; + if (mapReader.Width > 0) and (mapReader.Height > 0) then begin Result.Name := mapReader.MapName; @@ -2413,6 +2476,8 @@ var end; begin + if g_dbgpan_mplat_step then g_dbgpan_mplat_active := true; + UpdatePanelArray(gWalls); UpdatePanelArray(gRenderBackgrounds); UpdatePanelArray(gRenderForegrounds); @@ -2421,6 +2486,8 @@ begin UpdatePanelArray(gAcid2); UpdatePanelArray(gSteps); + if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end; + if gGameSettings.GameMode = GM_CTF then begin for a := FLAG_RED to FLAG_BLUE do @@ -2466,7 +2533,7 @@ begin if j > High(gPlayers) then j := 0; if gPlayers[j] <> nil then begin - if gPlayers[j].Live and g_Obj_Collide(@Obj, @gPlayers[j].Obj) then + if gPlayers[j].alive and g_Obj_Collide(@Obj, @gPlayers[j].Obj) then begin if gPlayers[j].GetFlag(a) then Break; end; @@ -2850,6 +2917,8 @@ begin //pan := gWalls[ID]; pan := g_Map_PanelByGUID(pguid); if (pan = nil) then exit; + if pan.Enabled and mapGrid.proxyEnabled[pan.proxyId] then exit; + pan.Enabled := True; g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, true); @@ -2857,7 +2926,9 @@ begin //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor); - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState({gWalls[ID]}pan.PanelType, pguid); + //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid); + // mark platform as interesting + pan.setDirty(); {$IFDEF MAP_DEBUG_ENABLED_FLAG} //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); @@ -2872,13 +2943,17 @@ begin //pan := gWalls[ID]; pan := g_Map_PanelByGUID(pguid); if (pan = nil) then exit; + if (not pan.Enabled) and (not mapGrid.proxyEnabled[pan.proxyId]) then exit; + pan.Enabled := False; g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, false); mapGrid.proxyEnabled[pan.proxyId] := false; //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end; - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, pguid); + //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid); + // mark platform as interesting + pan.setDirty(); {$IFDEF MAP_DEBUG_ENABLED_FLAG} //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); @@ -2906,7 +2981,7 @@ begin } tp.NextTexture(AnimLoop); - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelTexture(PanelType, pguid, AnimLoop); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelTexture(pguid, AnimLoop); end; @@ -2935,7 +3010,9 @@ begin 3: g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT); end; - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, pguid); + //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid); + // mark platform as interesting + pan.setDirty(); end; end; @@ -3056,20 +3133,15 @@ var var PAMem: TBinMemoryWriter; pan: TPanel; + count: Integer; begin // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé PAMem := TBinMemoryWriter.Create((Length(panByGUID)+1) * 40); - for pan in panByGUID do - begin - if true{pan.SaveIt} then - begin - // ID ïàíåëè - //PAMem.WriteInt(i); - // Ñîõðàíÿåì ïàíåëü - pan.SaveState(PAMem); - end; - end; + // Ñîõðàíÿåì ïàíåëè + count := Length(panByGUID); + Mem.WriteInt(count); + for pan in panByGUID do pan.SaveState(PAMem); // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé PAMem.SaveToMemory(Mem); @@ -3152,25 +3224,19 @@ var var PAMem: TBinMemoryReader; pan: TPanel; + count: LongInt; begin // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé PAMem := TBinMemoryReader.Create(); PAMem.LoadFromMemory(Mem); + // Çàãðóæàåì ïàíåëè + PAMem.ReadInt(count); + if (count <> Length(panByGUID)) then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: invalid number of panels'); for pan in panByGUID do begin - if true{pan.SaveIt} then - begin - // ID ïàíåëè: - //PAMem.ReadInt(id); - { - if id <> i then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel ID'); - } - // Çàãðóæàåì ïàíåëü - pan.LoadState(PAMem); - //if (panels[i].arrIdx <> i) then raise Exception.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel arrIdx'); - if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := pan.Enabled; - end; + pan.LoadState(PAMem); + if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := pan.Enabled; end; // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí