summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 768ae6d)
raw | patch | inline | side by side (parent: 768ae6d)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Tue, 5 Sep 2017 01:48:59 +0000 (04:48 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Tue, 5 Sep 2017 01:49:09 +0000 (04:49 +0300) |
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 58abd6ef2ef281d0b7ee2b0d471708ff8ced7143..c83fb8e455e06decf3ce5a07a13f94a8aa06a33c 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
{$IF DEFINED(D2F_DEBUG)}
if gPlayer1 <> nil then gPlayer1.NoTarget := True;
- gAimLine := true;
+ gAimLine := g_dbg_aimline_on;
{$ENDIF}
end;
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index bbf39cb5efb7bad44613c76d9352e0cb2655b37b..101c3c544d06658454afb94777d730c333832545 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
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
end;
end;
- g_Triggers_Create(_trigger);
+ result := Integer(g_Triggers_Create(_trigger));
end;
procedure CreateMonster(monster: TDynRecord);
PTRec = ^TTRec;
TTRec = record
//TexturePanel: Integer;
+ tnum: Integer;
+ id: Integer;
texPanIdx: Integer;
LiftPanelIdx: Integer;
DoorPanelIdx: Integer;
stt: UInt64;
moveSpeed{, moveStart, moveEnd}: TDFPoint;
//moveActive: Boolean;
+ pan: TPanel;
begin
mapGrid.Free();
mapGrid := nil;
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;
diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 7ea056dc25f97fef599dfaa48539367915558137..2f54116f98da1fcf96782ba70d2035e2e335553d 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
mMovingStart: TDFPoint;
mMovingEnd: TDFPoint;
mMovingActive: Boolean;
+ mMoveOnce: Boolean;
+
+ mSizeSpeed: TDFSize;
+ mSizeEnd: TDFSize;
+
+ mEndPosTrig: Integer;
+ mEndSizeTrig: Integer;
private
function getx1 (): Integer; inline;
property movingEndX: Integer read getMovingEndX write setMovingEndX;
property movingEndY: Integer read getMovingEndY write setMovingEndY;
property movingActive: Boolean read mMovingActive write mMovingActive;
+ property moveOnce: Boolean read mMoveOnce write mMoveOnce;
property isGBack: Boolean read getIsGBack;
property isGStep: Boolean read getIsGStep;
property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed;
property movingStart: TDFPoint read mMovingStart write mMovingStart;
property movingEnd: TDFPoint read mMovingEnd write mMovingEnd;
+
+ property endPosTrigId: Integer read mEndPosTrig write mEndPosTrig;
+ property endSizeTrigId: Integer read mEndSizeTrig write mEndSizeTrig;
end;
TPanelArray = Array of TPanel;
implementation
uses
- SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons,
+ SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons, g_triggers,
g_console, g_language, g_monsters, g_player, g_grid, e_log, GL, utils;
const
mMovingStart := PanelRec.moveStart;
mMovingEnd := PanelRec.moveEnd;
mMovingActive := PanelRec['move_active'].varvalue;
+ mMoveOnce := PanelRec.moveOnce;
+
+ mSizeSpeed := PanelRec.sizeSpeed;
+ mSizeEnd := PanelRec.sizeEnd;
+
+ mEndPosTrig := PanelRec.endPosTrig;
+ mEndSizeTrig := PanelRec.endSizeTrig;
// Òèï ïàíåëè:
PanelType := PanelRec.PanelType;
[arrIdx, mGUID, proxyId, px, py, pw, ph, x, y, width, height]);
}
g_Mark(px, py, pw, ph, MARK_WALL, false);
- if (pw <> Width) or (ph <> Height) then mapGrid.moveResizeBody(proxyId, X, Y, Width, Height)
- else mapGrid.moveBody(proxyId, X, Y);
- g_Mark(X, Y, Width, Height, MARK_WALL);
+ if (Width < 1) or (Height < 1) then
+ begin
+ mapGrid.proxyEnabled[proxyId] := false;
+ end
+ else
+ begin
+ mapGrid.proxyEnabled[proxyId] := Enabled;
+ if (pw <> Width) or (ph <> Height) then mapGrid.moveResizeBody(proxyId, X, Y, Width, Height)
+ else mapGrid.moveBody(proxyId, X, Y);
+ g_Mark(X, Y, Width, Height, MARK_WALL);
+ end;
end;
end;
end;
pdx, pdy: Integer;
pan: TPanel;
trtag: Integer;
+ hedge: Integer;
begin
squash := false;
tex := px;
begin
//e_LogWritefln('entity on the platform; tracing=(%s,%s); endpoint=(%s,%s); mustbe=(%s,%s)', [px, py, tex, tey, px+pdx, py+pdy]);
// if we cannot move, only walls should squash the entity
+ {
if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
begin
if (tex = px) and (tey = py) then squash := true;
end;
+ }
end;
end
else
e_LogWritefln('entity is embedded: plr=(%s,%s)-(%s,%s); mpl=(%s,%s)-(%s,%s)', [px, py, px+pw-1, py+ph-1, ox, oy, ox+mpw-1, oy+mph-1]);
end;
}
- if sweepAABB(ox, oy, mpw, mph, pdx, pdy, px, py, pw, ph, @u0, nil, @u1) then
+ if sweepAABB(ox, oy, mpw, mph, pdx, pdy, px, py, pw, ph, @u0, @hedge, @u1) then
begin
//e_LogWritefln('T: platsweep; u0=%s; u1=%s; hedge=%s; sweepAABB(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', [u0, u1, hedge, ox, oy, mpw, mph, pdx, pdy, px-1, py-1, pw+2, ph+2]);
// yes, platform hits the entity, push the entity in the direction of the platform
pan := mapGrid.traceBox(tex, tey, px, py, pw, ph, pdx, pdy, nil, trtag);
//e_LogWritefln(' tracebox: te=(%s,%s)', [tex, tey]);
// if we cannot move, only walls should squash the entity
+ {
if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
begin
if (pan <> nil) and (tex = px) and (tey = py) then squash := true;
end;
+ }
end;
end
else
begin
// no collistion, but may be embedded
//e_LogWritefln('F: platsweep; u0=%s; u1=%s; sweepAABB(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', [u0, u1, ox, oy, mpw, mph, pdx, pdy, px-1, py-1, pw+2, ph+2]);
- squash := (u1 >= 0.0);
+ //squash := (u1 >= 0.0);
end;
end;
dx := tex-px;
dy := tey-py;
result := (dx <> 0) or (dy <> 0);
- if result and (not squash) and ((tag and (GridTagWall or GridTagDoor)) <> 0) then
+ if (not squash) and ((tag and (GridTagWall or GridTagDoor)) <> 0) then
begin
squash := g_Collide(tex, tey, pw, ph, nx, ny, mpw, mph); // still in platform?
- if not squash then squash := g_Map_CollidePanel(tex, tey, pw, ph, (PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR));
+ //if not squash then squash := g_Map_CollidePanel(tex, tey, pw, ph, (PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR));
end;
end;
mon: TMonster;
mpfrid: LongWord;
ontop: Boolean;
+ actMoveTrig: Boolean;
+ actSizeTrig: Boolean;
begin
if (not Enabled) or (Width < 1) or (Height < 1) then exit;
FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
end;
+ if not g_dbgpan_mplat_active then exit;
+
+ if not mMovingActive then exit;
+ if mMovingSpeed.isZero and mSizeSpeed.isZero then exit;
+
+ //TODO: write wall size change processing
+
// moving platform?
- if mMovingActive and (not mMovingSpeed.isZero) and g_dbgpan_mplat_active then
begin
(*
* collect all monsters and players (aka entities) along the possible platform path
cw := cx1-cx0+1;
ch := cy1-cy0+1;
- // temporarily turn off this panel, so it won't interfere with collision checks
- mapGrid.proxyEnabled[proxyId] := false;
-
- // process players
- for f := 0 to High(gPlayers) do
+ // process "obstacle" panels
+ if ((tag and GridTagObstacle) <> 0) then
begin
- plr := gPlayers[f];
- if (plr = nil) or (not plr.alive) then continue;
- plr.getMapBox(px, py, pw, ph);
- if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
- if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then
+ // temporarily turn off this panel, so it won't interfere with collision checks
+ mapGrid.proxyEnabled[proxyId] := false;
+
+ // process players
+ for f := 0 to High(gPlayers) do
begin
- // set new position
- plr.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ plr := gPlayers[f];
+ if (plr = nil) or (not plr.alive) then continue;
+ plr.getMapBox(px, py, pw, ph);
+ if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
+ if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then
+ begin
+ // set new position
+ plr.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ end;
// squash player, if necessary
if squash then plr.Damage(15000, 0, 0, 0, HIT_TRAP);
end;
- end;
- // process gibs
- for f := 0 to High(gGibs) do
- begin
- gib := @gGibs[f];
- if not gib.alive then continue;
- gib.getMapBox(px, py, pw, ph);
- if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
- if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then
+ // process gibs
+ for f := 0 to High(gGibs) do
begin
- // set new position
- gib.moveBy(pdx, pdy); // this will call `positionChanged()` for us
- {
- if ontop then
+ gib := @gGibs[f];
+ if not gib.alive then continue;
+ gib.getMapBox(px, py, pw, ph);
+ if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
+ if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then
begin
- gib.Obj.Vel.X += pdx;
- gib.Obj.Vel.Y += pdy;
+ // set new position
+ gib.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ {
+ if ontop then
+ begin
+ gib.Obj.Vel.X += pdx;
+ gib.Obj.Vel.Y += pdy;
+ end;
+ }
end;
- }
end;
- end;
- // move and push corpses
- for f := 0 to High(gCorpses) do
- begin
- cor := gCorpses[f];
- if (cor = nil) then continue;
- cor.getMapBox(px, py, pw, ph);
- if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
- if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then
+ // move and push corpses
+ for f := 0 to High(gCorpses) do
begin
- // set new position
- cor.moveBy(pdx, pdy); // this will call `positionChanged()` for us
- {
- if ontop then
+ cor := gCorpses[f];
+ if (cor = nil) then continue;
+ cor.getMapBox(px, py, pw, ph);
+ if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
+ if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then
begin
- cor.ObjPtr.Vel.X += pdx;
- cor.ObjPtr.Vel.Y += pdy;
+ // set new position
+ cor.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ {
+ if ontop then
+ begin
+ cor.ObjPtr.Vel.X += pdx;
+ cor.ObjPtr.Vel.Y += pdy;
+ end;
+ }
end;
- }
end;
- end;
- // collect monsters
- monCheckListUsed := 0;
- g_Mons_ForEachAt(cx0, cy0, cw, ch, monCollect);
+ // collect monsters
+ monCheckListUsed := 0;
+ g_Mons_ForEachAt(cx0, cy0, cw, ch, monCollect);
- // process collected monsters
- if (monCheckListUsed > 0) then
- begin
- mpfrid := g_Mons_getNewMPlatFrameId();
- for f := 0 to monCheckListUsed do
+ // process collected monsters
+ if (monCheckListUsed > 0) then
begin
- mon := monCheckList[f];
- if (mon = nil) or (not mon.alive) or (mon.mplatCheckFrameId = mpfrid) then continue;
- mon.mplatCheckFrameId := mpfrid;
- mon.getMapBox(px, py, pw, ph);
- //if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
- if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then
+ mpfrid := g_Mons_getNewMPlatFrameId();
+ for f := 0 to monCheckListUsed do
begin
- // set new position
- mon.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ mon := monCheckList[f];
+ if (mon = nil) or (not mon.alive) or (mon.mplatCheckFrameId = mpfrid) then continue;
+ mon.mplatCheckFrameId := mpfrid;
+ mon.getMapBox(px, py, pw, ph);
+ //if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue;
+ if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then
+ begin
+ // set new position
+ mon.moveBy(pdx, pdy); // this will call `positionChanged()` for us
+ end;
// squash player, if necessary
if squash then mon.Damage(15000, 0, 0, 0, HIT_TRAP);
end;
end;
+
+ // restore panel state
+ mapGrid.proxyEnabled[proxyId] := true;
end;
- // restore panel state
- mapGrid.proxyEnabled[proxyId] := true;
- // and really move it
+ // move panel
X := nx;
Y := ny;
+ FWidth += mSizeSpeed.w;
+ FHeight += mSizeSpeed.h;
positionChanged();
+ actMoveTrig := false;
+ actSizeTrig := false;
+
+ {
+ if not mSizeSpeed.isZero then
+ begin
+ e_LogWritefln('ss: size_speed=(%s,%s); size=(%s,%s); move_speed=(%s,%s); oy=%s; ny=%s; etp:%s; ets:%s', [mSizeSpeed.w, mSizeSpeed.h, FWidth, FHeight, mMovingSpeed.X, mMovingSpeed.Y, oy, ny, mEndPosTrig, mEndSizeTrig]);
+ end;
+ }
+
// reverse moving direction, if necessary
- if (mMovingSpeed.X < 0) and (nx <= mMovingStart.X) then mMovingSpeed.X := -mMovingSpeed.X
- else if (mMovingSpeed.X > 0) and (nx >= mMovingEnd.X) then mMovingSpeed.X := -mMovingSpeed.X;
- if (mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y) then mMovingSpeed.Y := -mMovingSpeed.Y
- else if (mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y) then mMovingSpeed.Y := -mMovingSpeed.Y;
+ if ((mMovingSpeed.X < 0) and (nx <= mMovingStart.X)) or ((mMovingSpeed.X > 0) and (nx >= mMovingEnd.X)) then
+ begin
+ if mMoveOnce then mMovingActive := false else mMovingSpeed.X := -mMovingSpeed.X;
+ actMoveTrig := true;
+ end;
+
+ if ((mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y)) or ((mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y)) then
+ begin
+ if mMoveOnce then mMovingActive := false else mMovingSpeed.Y := -mMovingSpeed.Y;
+ actMoveTrig := true;
+ end;
+
+ // check "size stop"
+ if not mSizeSpeed.isZero and (Width = mSizeEnd.w) and (Height = mSizeEnd.h) then
+ begin
+ mSizeSpeed.w := 0;
+ mSizeSpeed.h := 0;
+ actSizeTrig := true;
+ if (Width < 1) or (Height < 1) then mMovingActive := false; //HACK!
+ //e_LogWritefln('FUUUUUUUUUUUUUU', []);
+ end;
+
+
+ if actMoveTrig then
+ begin
+ g_Triggers_Press(mEndPosTrig, ACTIVATE_CUSTOM);
+ end;
+
+ if actSizeTrig then
+ begin
+ g_Triggers_Press(mEndSizeTrig, ACTIVATE_CUSTOM);
+ end;
end;
end;
index 2da3a1e8dcdb267c264d22ef5fbd916845927085..97648af9e91d01cbbf3bdec3123aa363864d80fc 100644 (file)
--- a/src/game/g_triggers.pas
+++ b/src/game/g_triggers.pas
procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte; ActivateUID: Word = 0);
begin
+ if (ID >= Length(gTriggers)) then exit;
gTriggers[ID].ActivateUID := ActivateUID;
ActivateTrigger(gTriggers[ID], ActivateType);
end;
diff --git a/src/game/g_window.pas b/src/game/g_window.pas
index e77934cbb8892120c7fa6e93b5dbf7ececb619c1..0cf15d68e7496a62fe4389700811d9bd2dec47b1 100644 (file)
--- a/src/game/g_window.pas
+++ b/src/game/g_window.pas
gwin_dump_extensions: Boolean = false;
gwin_has_stencil: Boolean = false;
gwin_k8_enable_light_experiments: Boolean = false;
+ g_dbg_aimline_on: Boolean = false;
implementation
if arg = '--no-particle-phys' then gpart_dbg_phys_enabled := false;
if arg = '--no-particle-physics' then gpart_dbg_phys_enabled := false;
+ {$IF DEFINED(D2F_DEBUG)}
+ if arg = '--aimline' then g_dbg_aimline_on := false;
+ {$ENDIF}
+
if arg = '--holmes' then begin g_holmes_enabled := true; g_Game_SetDebugMode(); end;
if (arg = '--holmes-ui-scale') or (arg = '-holmes-ui-scale') then
begin
diff --git a/src/mapdef/mapdef.txt b/src/mapdef/mapdef.txt
index 4a27ccfa1b675d8820166afd52c231f3ef7325b1..591eadbc4ec71a5754428347ccd1940cda449d15 100644 (file)
--- a/src/mapdef/mapdef.txt
+++ b/src/mapdef/mapdef.txt
Flags is "flags" type ubyte offset 17 bitset PanelFlag default PANEL_FLAG_NONE omitdefault;
// moving platform options, not in binary
MoveSpeed is "move_speed" type point default (0 0) omitdefault;
+ SizeSpeed is "size_speed" type point default (0 0) omitdefault; // alas, `size` cannot be negative
MoveStart is "move_start" type point default (0 0) omitdefault;
MoveEnd is "move_end" type point default (0 0) omitdefault;
+ SizeEnd is "size_end" type size default (0 0) omitdefault;
MoveActive is "move_active" type bool default false omitdefault;
+ MoveOnce is "move_once" type bool default false omitdefault;
+ EndPosTrigger is "end_pos_trigger" type int trigger default null omitdefault;
+ EndSizeTrigger is "end_size_trigger" type int trigger default null omitdefault;
// not in binary
//Id is "id" type string default "" omitdefault;
// internals
diff --git a/src/shared/MAPDEF.pas b/src/shared/MAPDEF.pas
index ad160252dcc5877460d99f413785999aa8df791f..2e7ec96e8310ed7c6aa719e8729e5828068246ea 100644 (file)
--- a/src/shared/MAPDEF.pas
+++ b/src/shared/MAPDEF.pas
function isZero (): Boolean; inline;
end;
+ TDFSize = packed record
+ public
+ w, h: LongInt;
+
+ public
+ constructor Create (aw, ah: LongInt);
+
+ function isZero (): Boolean; inline;
+ function isValid (): Boolean; inline;
+ end;
+
Char16 = packed array[0..15] of Char;
Char32 = packed array[0..31] of Char;
Char64 = packed array[0..63] of Char;
function getPanelIndex (pan: TDynRecord): Integer;
function getPointField (const aname: AnsiString): TDFPoint; inline;
+ function getSizeField (const aname: AnsiString): TDFSize; inline;
public
function panelCount (): Integer; inline;
function moveStart (): TDFPoint; inline;
function moveEnd (): TDFPoint; inline;
+ function moveOnce (): Boolean; inline;
+
+ function sizeSpeed (): TDFSize; inline;
+ function sizeEnd (): TDFSize; inline;
+
+ function endPosTrig (): Integer; inline;
+ function endSizeTrig (): Integer; inline;
+
// texture
function Resource (): AnsiString; inline;
function Anim (): Boolean; inline;
function TDFPoint.isZero (): Boolean; inline; begin result := (X = 0) and (Y = 0); end;
+constructor TDFSize.Create (aw, ah: LongInt); begin w := aw; h := ah; end;
+function TDFSize.isZero (): Boolean; inline; begin result := (w = 0) and (h = 0); end;
+function TDFSize.isValid (): Boolean; inline; begin result := (w > 0) and (h > 0); end;
+
+
// ////////////////////////////////////////////////////////////////////////// //
function TDynRecordHelper.getUserPanelId (): Integer; inline;
var
@@ -193,6 +218,28 @@ function TDynRecordHelper.moveSpeed (): TDFPoint; inline; begin result := getPoi
function TDynRecordHelper.moveStart (): TDFPoint; inline; begin result := getPointField('move_start'); end;
function TDynRecordHelper.moveEnd (): TDFPoint; inline; begin result := getPointField('move_end'); end;
+function TDynRecordHelper.sizeSpeed (): TDFSize; inline; begin result := getSizeField('size_speed'); end;
+function TDynRecordHelper.sizeEnd (): TDFSize; inline; begin result := getSizeField('size_end'); end;
+
+function TDynRecordHelper.moveOnce (): Boolean; inline; begin result := (getFieldWithType('move_once', TDynField.TType.TBool).ival <> 0); end;
+
+
+function TDynRecordHelper.endPosTrig (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ fld := getFieldWithType('end_pos_trigger', TDynField.TType.TInt);
+ result := fld.recrefIndex;
+end;
+
+function TDynRecordHelper.endSizeTrig (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ fld := getFieldWithType('end_size_trigger', TDynField.TType.TInt);
+ result := fld.recrefIndex;
+end;
+
// ////////////////////////////////////////////////////////////////////////// //
function TDynRecordHelper.getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline;
end;
+function TDynRecordHelper.getSizeField (const aname: AnsiString): TDFSize; inline;
+var
+ fld: TDynField;
+begin
+ fld := field[aname];
+ if (fld = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, name, id]));
+ if (fld.baseType <> TSize) and (fld.baseType <> TPoint) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, name, id]));
+ result := TDFSize.Create(fld.ival, fld.ival2);
+end;
+
+
function TDynRecordHelper.getPanelByIdx (idx: Integer): TDynRecord; inline;
var
fld: TDynField;
diff --git a/src/shared/mapdef.inc b/src/shared/mapdef.inc
index b74ebfc9dcb93ab110655d97cd365a27c2e75a36..c4ab9848657502190c5eb86bd968c83c52efcde6 100644 (file)
--- a/src/shared/mapdef.inc
+++ b/src/shared/mapdef.inc
#10#32#32#77#111#118#101#83#112#101#101#100#32#105#115#32#34#109#111#118#101+
#95#115#112#101#101#100#34#32#116#121#112#101#32#112#111#105#110#116#32#100+
#101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116#100#101#102#97+
- #117#108#116#59#10#32#32#77#111#118#101#83#116#97#114#116#32#105#115#32#34+
- #109#111#118#101#95#115#116#97#114#116#34#32#116#121#112#101#32#112#111#105+
+ #117#108#116#59#10#32#32#83#105#122#101#83#112#101#101#100#32#105#115#32#34+
+ #115#105#122#101#95#115#112#101#101#100#34#32#116#121#112#101#32#112#111#105+
#110#116#32#100#101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116+
- #100#101#102#97#117#108#116#59#10#32#32#77#111#118#101#69#110#100#32#105#115+
- #32#34#109#111#118#101#95#101#110#100#34#32#116#121#112#101#32#112#111#105+
- #110#116#32#100#101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116+
- #100#101#102#97#117#108#116#59#10#32#32#77#111#118#101#65#99#116#105#118#101+
- #32#105#115#32#34#109#111#118#101#95#97#99#116#105#118#101#34#32#116#121#112+
- #101#32#98#111#111#108#32#100#101#102#97#117#108#116#32#102#97#108#115#101+
- #32#111#109#105#116#100#101#102#97#117#108#116#59#10#32#32#47#47#32#110#111+
- #116#32#105#110#32#98#105#110#97#114#121#10#32#32#47#47#73#100#32#105#115#32+
- #34#105#100#34#32#116#121#112#101#32#115#116#114#105#110#103#32#100#101#102+
- #97#117#108#116#32#34#34#32#111#109#105#116#100#101#102#97#117#108#116#59#10+
- #32#32#47#47#32#105#110#116#101#114#110#97#108#115#10#32#32#80#97#110#73#100+
- #120#32#105#115#32#34#112#97#110#105#100#120#34#32#116#121#112#101#32#117+
- #105#110#116#32#105#110#116#101#114#110#97#108#59#10#125#10#10#84#73#116#101+
- #109#82#101#99#95#49#32#105#115#32#34#105#116#101#109#34#32#115#105#122#101+
- #32#49#48#32#98#121#116#101#115#32#98#105#110#98#108#111#99#107#32#51#32#123+
- #10#32#32#47#47#88#32#105#115#32#34#120#34#32#116#121#112#101#32#105#110#116+
- #32#111#102#102#115#101#116#32#48#59#10#32#32#47#47#89#32#105#115#32#34#121+
- #34#32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#52#59#10+
- #32#32#80#111#115#32#105#115#32#34#112#111#115#105#116#105#111#110#34#32#116+
+ #100#101#102#97#117#108#116#59#32#47#47#32#97#108#97#115#44#32#96#115#105+
+ #122#101#96#32#99#97#110#110#111#116#32#98#101#32#110#101#103#97#116#105#118+
+ #101#10#32#32#77#111#118#101#83#116#97#114#116#32#105#115#32#34#109#111#118+
+ #101#95#115#116#97#114#116#34#32#116#121#112#101#32#112#111#105#110#116#32+
+ #100#101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116#100#101#102+
+ #97#117#108#116#59#10#32#32#77#111#118#101#69#110#100#32#105#115#32#34#109+
+ #111#118#101#95#101#110#100#34#32#116#121#112#101#32#112#111#105#110#116#32+
+ #100#101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116#100#101#102+
+ #97#117#108#116#59#10#32#32#83#105#122#101#69#110#100#32#105#115#32#34#115+
+ #105#122#101#95#101#110#100#34#32#116#121#112#101#32#115#105#122#101#32#100+
+ #101#102#97#117#108#116#32#40#48#32#48#41#32#111#109#105#116#100#101#102#97+
+ #117#108#116#59#10#32#32#77#111#118#101#65#99#116#105#118#101#32#105#115#32+
+ #34#109#111#118#101#95#97#99#116#105#118#101#34#32#116#121#112#101#32#98#111+
+ #111#108#32#100#101#102#97#117#108#116#32#102#97#108#115#101#32#111#109#105+
+ #116#100#101#102#97#117#108#116#59#10#32#32#77#111#118#101#79#110#99#101#32+
+ #105#115#32#34#109#111#118#101#95#111#110#99#101#34#32#116#121#112#101#32#98+
+ #111#111#108#32#100#101#102#97#117#108#116#32#102#97#108#115#101#32#111#109+
+ #105#116#100#101#102#97#117#108#116#59#10#32#32#69#110#100#80#111#115#84#114+
+ #105#103#103#101#114#32#105#115#32#34#101#110#100#95#112#111#115#95#116#114+
+ #105#103#103#101#114#34#32#116#121#112#101#32#105#110#116#32#116#114#105#103+
+ #103#101#114#32#100#101#102#97#117#108#116#32#110#117#108#108#32#111#109#105+
+ #116#100#101#102#97#117#108#116#59#10#32#32#69#110#100#83#105#122#101#84#114+
+ #105#103#103#101#114#32#105#115#32#34#101#110#100#95#115#105#122#101#95#116+
+ #114#105#103#103#101#114#34#32#116#121#112#101#32#105#110#116#32#116#114#105+
+ #103#103#101#114#32#100#101#102#97#117#108#116#32#110#117#108#108#32#111#109+
+ #105#116#100#101#102#97#117#108#116#59#10#32#32#47#47#32#110#111#116#32#105+
+ #110#32#98#105#110#97#114#121#10#32#32#47#47#73#100#32#105#115#32#34#105#100+
+ #34#32#116#121#112#101#32#115#116#114#105#110#103#32#100#101#102#97#117#108+
+ #116#32#34#34#32#111#109#105#116#100#101#102#97#117#108#116#59#10#32#32#47+
+ #47#32#105#110#116#101#114#110#97#108#115#10#32#32#80#97#110#73#100#120#32+
+ #105#115#32#34#112#97#110#105#100#120#34#32#116#121#112#101#32#117#105#110+
+ #116#32#105#110#116#101#114#110#97#108#59#10#125#10#10#84#73#116#101#109#82+
+ #101#99#95#49#32#105#115#32#34#105#116#101#109#34#32#115#105#122#101#32#49+
+ #48#32#98#121#116#101#115#32#98#105#110#98#108#111#99#107#32#51#32#123#10#32+
+ #32#47#47#88#32#105#115#32#34#120#34#32#116#121#112#101#32#105#110#116#32+
+ #111#102#102#115#101#116#32#48#59#10#32#32#47#47#89#32#105#115#32#34#121#34+
+ #32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#52#59#10#32+
+ #32#80#111#115#32#105#115#32#34#112#111#115#105#116#105#111#110#34#32#116+
#121#112#101#32#112#111#105#110#116#32#111#102#102#115#101#116#32#48#32#97+
#115#32#120#121#59#10#32#32#73#116#101#109#84#121#112#101#32#105#115#32#34+
#116#121#112#101#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
diff --git a/src/shared/xdynrec.pas b/src/shared/xdynrec.pas
index d82867e7d504dd34ad0d1a152a9ffe7a872069d6..15040f8acc1d0dfa984a40de623192043617c9a9 100644 (file)
--- a/src/shared/xdynrec.pas
+++ b/src/shared/xdynrec.pas
else
begin
rec := mOwner.findRecordByTypeId(mEBSTypeName, pr.tokStr);
- if (rec = nil) then raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSTypeName, mName]));
+ if (rec = nil) then
+ begin
+ //raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSTypeName, mName]));
+ mRecRefId := pr.tokStr;
+ end
+ else
+ begin
+ mRecRef := rec;
+ mRecRefId := '';
+ end;
pr.expectId();
- mRecRef := rec;
end;
mDefined := true;
pr.expectTT(pr.TTSemi);
{$IF DEFINED(D2D_DYNREC_PROFILER)}
stt, stall: UInt64;
{$ENDIF}
+
+ procedure linkNames (rec: TDynRecord);
+ var
+ fld: TDynField;
+ rt: TDynRecord;
+ begin
+ //writeln('*** rec: ', rec.mName, '.', rec.mId, ' (', rec.mFields.count, ')');
+ for fld in rec.mFields do
+ begin
+ if (fld.mType = TDynField.TType.TTrigData) then
+ begin
+ if (fld.mRecRef <> nil) then linkNames(fld.mRecRef);
+ continue;
+ end;
+ if (Length(fld.mRecRefId) = 0) then continue;
+ assert(fld.mEBSType <> nil);
+ rt := findRecordByTypeId(fld.mEBSTypeName, fld.mRecRefId);
+ if (rt = nil) then
+ begin
+ e_LogWritefln('record of type ''%s'' with id ''%s'' links to inexistant record of type ''%s'' with id ''%s''', [rec.mName, rec.mId, fld.mEBSTypeName, fld.mRecRefId], MSG_WARNING);
+ //raise Exception.Create(Format('record of type ''%s'' with id ''%s'' links to inexistant record of type ''%s'' with id ''%s''', [rec.mName, rec.mId, fld.mEBSTypeName, fld.mRecRefId]));
+ end;
+ //writeln(' ', rec.mName, '.', rec.mId, ':', fld.mName, ' -> ', rt.mName, '.', rt.mId, ' (', fld.mEBSTypeName, '.', fld.mRecRefId, ')');
+ fld.mRecRefId := '';
+ fld.mRecRef := rt;
+ fld.mDefined := true;
+ end;
+ for fld in rec.mFields do
+ begin
+ //writeln(' ', fld.mName);
+ fld.fixDefaultValue(); // just in case
+ end;
+ end;
+
begin
if (mOwner = nil) then raise Exception.Create(Format('can''t parse record ''%s'' value without owner', [mName]));
raise Exception.Create(Format('unknown field ''%s'' in record ''%s''', [pr.tokStr, mName]));
end;
pr.expectTT(pr.TTEnd);
+
+ if mHeader then
+ begin
+ // link fields
+ for fld in mFields do
+ begin
+ if (fld.mType <> TDynField.TType.TList) then continue;
+ for rec in fld.mRVal do linkNames(rec);
+ end;
+ end;
+
// fix field defaults
{$IF DEFINED(D2D_DYNREC_PROFILER)}stt := curTimeMicro();{$ENDIF}
for fld in mFields do fld.fixDefaultValue();
result := res;
res := nil;
finally
- res.Free();
+ //TMP:segfaults! res.Free();
end;
end;