diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index bbf39cb5efb7bad44613c76d9352e0cb2655b37b..e976be49c616045a92b12fd0b2c4844fd9227be2 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
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;
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 ();
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;
try
dfmapdef := TDynMapDef.Create(pr);
- except on e: Exception do
- raise Exception.Create(Format('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.line, pr.col, e.message]));
+ except
+ on e: TDynParseException do
+ raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [e.tokLine, e.tokCol, e.message]);
+ on e: Exception do
+ raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message]);
end;
st.Free();
function g_Map_ParseMap (data: Pointer; dataLen: Integer): TDynRecord;
var
wst: TSFSMemoryChunkStream = nil;
- pr: TTextParser = nil;
begin
result := nil;
if (dataLen < 4) then exit;
if (dfmapdef = nil) then raise Exception.Create('internal map loader error');
wst := TSFSMemoryChunkStream.Create(data, dataLen);
-
- if (PAnsiChar(data)[0] = 'M') and (PAnsiChar(data)[1] = 'A') and (PAnsiChar(data)[2] = 'P') and (PByte(data)[3] = 1) then
- begin
- // binary map
- try
- //e_LogWriteln('parsing binary map...');
- result := dfmapdef.parseBinMap(wst);
- except on e: Exception do
+ try
+ result := dfmapdef.parseMap(wst);
+ except
+ on e: TDynParseException do
begin
- e_LogWritefln('ERROR: %s', [e.message]);
+ e_LogWritefln('ERROR at (%s,%s): %s', [e.tokLine, e.tokCol, e.message]);
wst.Free();
result := nil;
exit;
end;
- end;
- wst.Free();
- end
- else
- begin
- // text map
- pr := TFileTextParser.Create(wst);
- try
- //e_LogWriteln('parsing text map...');
- result := dfmapdef.parseMap(pr);
- except on e: Exception do
+ on e: Exception do
begin
- 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`
+ e_LogWritefln('ERROR: %s', [e.message]);
+ wst.Free();
result := nil;
exit;
end;
- end;
- pr.Free(); // will free `wst`
end;
+
//e_LogWriteln('map parsed.');
end;
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;
pan.arrIdx := len;
pan.proxyId := -1;
pan.tag := panelTypeToTag(PanelRec.PanelType);
- if sav then pan.SaveIt := True;
PanelRec.user['panel_guid'] := pguid;
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
//Data.Default := Trigger.DATA;
if (Trigger.trigRec = nil) then
begin
- trigData := nil;
+ trigDataRec := nil;
+ //HACK!
if (TriggerType <> TRIGGER_SECRET) then
begin
e_LogWritefln('trigger of type %s has no triggerdata; wtf?!', [TriggerType], MSG_WARNING);
end
else
begin
- trigData := Trigger.trigRec.clone(nil);
+ trigDataRec := Trigger.trigRec.clone(nil);
end;
end;
- g_Triggers_Create(_trigger);
+ result := Integer(g_Triggers_Create(_trigger));
end;
procedure CreateMonster(monster: TDynRecord);
if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
begin
//if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
- if (gTriggers[a].trigData.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a);
+ if (gTriggers[a].trigDataRec.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a);
end;
end;
end;
tw.Free();
end;
}
- if (gTriggers[a].trigData.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a);
+ if (gTriggers[a].trigDataRec.trigMonsterId) = Integer(mon.StartID) then mon.AddTrigger(a);
end;
end;
end;
PTRec = ^TTRec;
TTRec = record
//TexturePanel: Integer;
+ tnum: Integer;
+ id: Integer;
texPanIdx: Integer;
LiftPanelIdx: Integer;
DoorPanelIdx: Integer;
FileName, mapResName, s, TexName: String;
Data: Pointer;
Len: Integer;
- ok, isAnim, trigRef: Boolean;
+ ok, isAnim: Boolean;
CurTex, ntn: Integer;
rec, texrec: TDynRecord;
pttit: PTRec;
stt: UInt64;
moveSpeed{, moveStart, moveEnd}: TDFPoint;
//moveActive: Boolean;
+ pan: TPanel;
begin
mapGrid.Free();
mapGrid := nil;
//e_LogWritefln('PANSTART: pannum=%s', [pannum]);
texrec := nil;
SetLength(AddTextures, 0);
- trigRef := False;
CurTex := -1;
ok := false;
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;
//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
moveSpeed := rec.moveSpeed;
//moveStart := rec.moveStart;
//moveEnd := rec.moveEnd;
- //moveActive := rec['move_active'].varvalue;
+ //moveActive := rec['move_active'].value;
if not moveSpeed.isZero then
begin
SetLength(gMovingWallIds, Length(gMovingWallIds)+1);
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;
//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);
//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);
//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);
}
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;
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;
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);
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;
// Ýòîò ñïèñîê ïàíåëåé çàãðóæåí