diff --git a/src/shared/MAPDEF.pas b/src/shared/MAPDEF.pas
index 3f843872a2f3cdd8825b9268e254232d35a251a5..ceedbe3f5aaf6d36b6e98c9b011b2af261f25bc8 100644 (file)
--- a/src/shared/MAPDEF.pas
+++ b/src/shared/MAPDEF.pas
-(* Copyright (C) DooM 2D:Forever Developers
+(* Copyright (C) Doom 2D: Forever Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 3 of the License ONLY.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
-{$MODE DELPHI}
+{$INCLUDE a_modes.inc}
+{$M+}
unit MAPDEF;
-{
------------------------------------
-MAPDEF.PAS ÂÅÐÑÈß ÎÒ 22.03.09
-
-Ïîääåðæêà êàðò âåðñèè 1
------------------------------------
-}
-
interface
uses
- MAPSTRUCT;
+ xdynrec;
+
const
- PANEL_NONE = 0;
- PANEL_WALL = 1;
- PANEL_BACK = 2;
- PANEL_FORE = 4;
- PANEL_WATER = 8;
- PANEL_ACID1 = 16;
- PANEL_ACID2 = 32;
- PANEL_STEP = 64;
- PANEL_LIFTUP = 128;
- PANEL_LIFTDOWN = 256;
- PANEL_OPENDOOR = 512;
- PANEL_CLOSEDOOR = 1024;
- PANEL_BLOCKMON = 2048;
- PANEL_LIFTLEFT = 4096;
- PANEL_LIFTRIGHT = 8192;
-
- PANEL_FLAG_BLENDING = 1;
- PANEL_FLAG_HIDE = 2;
- PANEL_FLAG_WATERTEXTURES = 4;
-
- EFFECT_NONE = 0;
- EFFECT_TELEPORT = 1;
- EFFECT_RESPAWN = 2;
- EFFECT_FIRE = 3;
-
- ITEM_NONE = 0;
- ITEM_MEDKIT_SMALL = 1;
- ITEM_MEDKIT_LARGE = 2;
- ITEM_MEDKIT_BLACK = 3;
- ITEM_ARMOR_GREEN = 4;
- ITEM_ARMOR_BLUE = 5;
- ITEM_SPHERE_BLUE = 6;
- ITEM_SPHERE_WHITE = 7;
- ITEM_SUIT = 8;
- ITEM_OXYGEN = 9;
- ITEM_INVUL = 10;
- ITEM_WEAPON_SAW = 11;
- ITEM_WEAPON_SHOTGUN1 = 12;
- ITEM_WEAPON_SHOTGUN2 = 13;
- ITEM_WEAPON_CHAINGUN = 14;
- ITEM_WEAPON_ROCKETLAUNCHER = 15;
- ITEM_WEAPON_PLASMA = 16;
- ITEM_WEAPON_BFG = 17;
- ITEM_WEAPON_SUPERPULEMET = 18;
- ITEM_AMMO_BULLETS = 19;
- ITEM_AMMO_BULLETS_BOX = 20;
- ITEM_AMMO_SHELLS = 21;
- ITEM_AMMO_SHELLS_BOX = 22;
- ITEM_AMMO_ROCKET = 23;
- ITEM_AMMO_ROCKET_BOX = 24;
- ITEM_AMMO_CELL = 25;
- ITEM_AMMO_CELL_BIG = 26;
- ITEM_AMMO_BACKPACK = 27;
- ITEM_KEY_RED = 28;
- ITEM_KEY_GREEN = 29;
- ITEM_KEY_BLUE = 30;
- ITEM_WEAPON_KASTET = 31;
- ITEM_WEAPON_PISTOL = 32;
- ITEM_BOTTLE = 33;
- ITEM_HELMET = 34;
- ITEM_JETPACK = 35;
- ITEM_INVIS = 36;
-
- ITEM_MAX = 36; // store the last item's id in here
- // use this in for loops
-
- ITEM_OPTION_ONLYDM = 1;
- ITEM_OPTION_FALL = 2;
-
- AREA_NONE = 0;
- AREA_PLAYERPOINT1 = 1;
- AREA_PLAYERPOINT2 = 2;
- AREA_DMPOINT = 3;
- AREA_REDFLAG = 4;
- AREA_BLUEFLAG = 5;
- AREA_DOMFLAG = 6;
- AREA_REDTEAMPOINT = 7;
- AREA_BLUETEAMPOINT = 8;
-
- MONSTER_NONE = 0;
- MONSTER_DEMON = 1;
- MONSTER_IMP = 2;
- MONSTER_ZOMBY = 3;
- MONSTER_SERG = 4;
- MONSTER_CYBER = 5;
- MONSTER_CGUN = 6;
- MONSTER_BARON = 7;
- MONSTER_KNIGHT = 8;
- MONSTER_CACO = 9;
- MONSTER_SOUL = 10;
- MONSTER_PAIN = 11;
- MONSTER_SPIDER = 12;
- MONSTER_BSP = 13;
- MONSTER_MANCUB = 14;
- MONSTER_SKEL = 15;
- MONSTER_VILE = 16;
- MONSTER_FISH = 17;
- MONSTER_BARREL = 18;
- MONSTER_ROBO = 19;
- MONSTER_MAN = 20;
-
- TRIGGER_NONE = 0;
- TRIGGER_EXIT = 1;
- TRIGGER_TELEPORT = 2;
- TRIGGER_OPENDOOR = 3;
- TRIGGER_CLOSEDOOR = 4;
- TRIGGER_DOOR = 5;
- TRIGGER_DOOR5 = 6;
- TRIGGER_CLOSETRAP = 7;
- TRIGGER_TRAP = 8;
- TRIGGER_PRESS = 9;
- TRIGGER_SECRET = 10;
- TRIGGER_LIFTUP = 11;
- TRIGGER_LIFTDOWN = 12;
- TRIGGER_LIFT = 13;
- TRIGGER_TEXTURE = 14;
- TRIGGER_ON = 15;
- TRIGGER_OFF = 16;
- TRIGGER_ONOFF = 17;
- TRIGGER_SOUND = 18;
- TRIGGER_SPAWNMONSTER = 19;
- TRIGGER_SPAWNITEM = 20;
- TRIGGER_MUSIC = 21;
- TRIGGER_PUSH = 22;
- TRIGGER_SCORE = 23;
- TRIGGER_MESSAGE = 24;
- TRIGGER_DAMAGE = 25;
- TRIGGER_HEALTH = 26;
- TRIGGER_SHOT = 27;
- TRIGGER_EFFECT = 28;
- TRIGGER_SCRIPT = 29;
- TRIGGER_MAX = 29;
-
- TRIGGER_SHOT_PISTOL = 0;
- TRIGGER_SHOT_BULLET = 1;
- TRIGGER_SHOT_SHOTGUN = 2;
- TRIGGER_SHOT_SSG = 3;
- TRIGGER_SHOT_IMP = 4;
- TRIGGER_SHOT_PLASMA = 5;
- TRIGGER_SHOT_SPIDER = 6;
- TRIGGER_SHOT_CACO = 7;
- TRIGGER_SHOT_BARON = 8;
- TRIGGER_SHOT_MANCUB = 9;
- TRIGGER_SHOT_REV = 10;
- TRIGGER_SHOT_ROCKET = 11;
- TRIGGER_SHOT_BFG = 12;
- TRIGGER_SHOT_EXPL = 13;
- TRIGGER_SHOT_BFGEXPL = 14;
- TRIGGER_SHOT_MAX = 14;
-
- TRIGGER_SHOT_TARGET_NONE = 0;
- TRIGGER_SHOT_TARGET_MON = 1;
- TRIGGER_SHOT_TARGET_PLR = 2;
- TRIGGER_SHOT_TARGET_RED = 3;
- TRIGGER_SHOT_TARGET_BLUE = 4;
- TRIGGER_SHOT_TARGET_MONPLR = 5;
- TRIGGER_SHOT_TARGET_PLRMON = 6;
-
- TRIGGER_EFFECT_PARTICLE = 0;
- TRIGGER_EFFECT_ANIMATION = 1;
-
- TRIGGER_EFFECT_SLIQUID = 0;
- TRIGGER_EFFECT_LLIQUID = 1;
- TRIGGER_EFFECT_DLIQUID = 2;
- TRIGGER_EFFECT_BLOOD = 3;
- TRIGGER_EFFECT_SPARK = 4;
- TRIGGER_EFFECT_BUBBLE = 5;
- TRIGGER_EFFECT_MAX = 5;
-
- TRIGGER_EFFECT_POS_CENTER = 0;
- TRIGGER_EFFECT_POS_AREA = 1;
-
- ACTIVATE_PLAYERCOLLIDE = 1;
- ACTIVATE_MONSTERCOLLIDE = 2;
- ACTIVATE_PLAYERPRESS = 4;
- ACTIVATE_MONSTERPRESS = 8;
- ACTIVATE_SHOT = 16;
- ACTIVATE_NOMONSTER = 32;
- ACTIVATE_CUSTOM = 255;
-
- KEY_RED = 1;
- KEY_GREEN = 2;
- KEY_BLUE = 4;
- KEY_REDTEAM = 8;
- KEY_BLUETEAM = 16;
+ MAP_SIGNATURE = 'MAP';
+
+const
TEXTURE_NAME_WATER = '_water_0';
TEXTURE_NAME_ACID1 = '_water_1';
TEXTURE_NAME_ACID2 = '_water_2';
- TEXTURE_SPECIAL_WATER = DWORD(-1);
- TEXTURE_SPECIAL_ACID1 = DWORD(-2);
- TEXTURE_SPECIAL_ACID2 = DWORD(-3);
- TEXTURE_NONE = DWORD(-4);
type
- TPoint = packed record
+ TDFPoint = packed record
+ public
X, Y: LongInt;
+
+ public
+ constructor Create (ax, ay: LongInt);
+
+ 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;
- TTriggerData = record
- case Byte of
- 0: (Default: Byte128);
- TRIGGER_EXIT: (MapName: Char16);
- TRIGGER_TELEPORT: (TargetPoint: TPoint;
- d2d_teleport: Boolean;
- silent_teleport: Boolean;
- TlpDir: Byte);
- TRIGGER_OPENDOOR,
- TRIGGER_CLOSEDOOR,
- TRIGGER_DOOR,
- TRIGGER_DOOR5,
- TRIGGER_CLOSETRAP,
- TRIGGER_TRAP,
- TRIGGER_LIFTUP,
- TRIGGER_LIFTDOWN,
- TRIGGER_LIFT: (PanelID: Integer;
- NoSound: Boolean;
- d2d_doors: Boolean);
- TRIGGER_PRESS,
- TRIGGER_ON,
- TRIGGER_OFF,
- TRIGGER_ONOFF: (tX, tY: Integer;
- tWidth, tHeight: Word;
- Wait: Word;
- Count: Word;
- MonsterID: Integer;
- ExtRandom: Boolean);
- TRIGGER_SECRET: ();
- TRIGGER_TEXTURE: (ActivateOnce: Boolean;
- AnimOnce: Boolean);
- TRIGGER_SOUND: (SoundName: Char64;
- Volume: Byte;
- Pan: Byte;
- Local: Boolean;
- PlayCount: Byte;
- SoundSwitch: Boolean);
- TRIGGER_SPAWNMONSTER: (MonPos: TPoint;
- MonType: Byte;
- MonHealth: Integer;
- MonDir: Byte;
- MonActive: Boolean;
- MonCount: Integer;
- MonEffect: Byte;
- MonMax: Word;
- MonDelay: Word;
- MonBehav: Byte);
- TRIGGER_SPAWNITEM: (ItemPos: TPoint;
- ItemType: Byte;
- ItemFalls: Boolean;
- ItemOnlyDM: Boolean;
- ItemCount: Integer;
- ItemEffect: Byte;
- ItemMax: Word;
- ItemDelay: Word);
- TRIGGER_MUSIC: (MusicName: Char64;
- MusicAction: Byte);
- TRIGGER_PUSH: (PushAngle: Word;
- PushForce: Byte;
- ResetVel: Boolean);
- TRIGGER_SCORE: (ScoreAction: Byte;
- ScoreCount: Byte;
- ScoreTeam: Byte;
- ScoreCon,
- ScoreMsg: Boolean);
- TRIGGER_MESSAGE: (MessageKind: Byte;
- MessageSendTo: Byte;
- MessageText: Char100;
- MessageTime: Word);
- TRIGGER_DAMAGE: (DamageValue: Word;
- DamageInterval: Word);
- TRIGGER_HEALTH: (HealValue: Word;
- HealInterval: Word;
- HealMax: Boolean;
- HealSilent: Boolean);
- TRIGGER_SHOT: (ShotPos: TPoint;
- ShotType: Byte;
- ShotTarget: Byte;
- ShotSound: Boolean;
- ShotAllMap: Boolean;
- ShotPanelID: Integer;
- ShotIntSight: Word;
- ShotAngle: Word;
- ShotWait: Word;
- ShotAccuracy: Word;
- ShotAmmo: Word;
- ShotIntReload: Word);
- TRIGGER_EFFECT: (FXCount: Byte;
- FXType: Byte;
- FXSubType: Byte;
- FXColorR: Byte;
- FXColorG: Byte;
- FXColorB: Byte;
- FXPos: Byte;
- FXWait: Word;
- FXVelX: ShortInt;
- FXVelY: ShortInt;
- FXSpreadL: Byte;
- FXSpreadR: Byte;
- FXSpreadU: Byte;
- FXSpreadD: Byte);
- TRIGGER_SCRIPT: (SCRProc: Char64;
- SCRArg: Integer);
+ TDFColor = packed record
+ public
+ r, g, b, a: Byte; // a: 0 is transparent, 255 is opaque
+
+ public
+ constructor Create (ar, ag, ab: LongInt; aa: LongInt=0);
+
+ function isTransparent (): Boolean; inline;
+ function isOpaque (): Boolean; inline;
+ function isBlack (): Boolean; inline;
+ function isWhite (): Boolean; inline;
end;
-{$INCLUDE mapstructsizes.inc}
+{$INCLUDE mapdef.inc}
+
+// various helpers to access map structures
+type
+ TDynFieldHelper = class helper for TDynField
+ public
+ function getRGBA (): TDFColor; inline;
+ procedure setRGBA (const v: TDFColor); inline;
+
+ public
+ property rgba: TDFColor read getRGBA write setRGBA; // for `TColor`
+ end;
+
+ TDynRecordHelper = class helper for TDynRecord
+ private
+ function getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline;
+
+ function getPanelByIdx (idx: Integer): TDynRecord; inline;
+
+ function getTexturePanel (): Integer; inline;
+ function getTexturePanelRec (): TDynRecord; inline;
+
+ function getPanelIndex (pan: TDynRecord): Integer;
+
+ function getPointField (const aname: AnsiString): TDFPoint; inline;
+ function getSizeField (const aname: AnsiString): TDFSize; inline;
+
+ public
+ function panelCount (): Integer; inline;
+
+ // header
+ function mapName (): AnsiString; inline;
+ function mapAuthor (): AnsiString; inline;
+ function mapDesc (): AnsiString; inline;
+ function musicName (): AnsiString; inline;
+ function skyName (): AnsiString; inline;
+
+ // panel
+ function X (): Integer; inline;
+ function Y (): Integer; inline;
+ function Width (): Word; inline;
+ function Height (): Word; inline;
+ function TextureNum (): Word; inline;
+ function TextureRec (): TDynRecord; inline;
+ function PanelType (): Word; inline;
+ function Alpha (): Byte; inline;
+ function Flags (): Byte; inline;
+
+ function moveSpeed (): TDFPoint; 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;
+
+ // item
+ function ItemType (): Byte; inline;
+ function Options (): Byte; inline;
+
+ // monster
+ function MonsterType (): Byte; inline; // type, ubyte
+ function Direction (): Byte; inline; // direction, ubyte
+
+ // area
+ function AreaType (): Byte; inline; // type, ubyte
+ //function Direction (): Byte; inline; // direction, ubyte
+
+ // trigger
+ function trigRec (): TDynRecord; inline;
+ function Enabled (): Boolean; inline; // enabled, bool
+ function TriggerType (): Byte; inline; // type, ubyte
+ function ActivateType (): Byte; inline; // activatetype, ubyte
+ function Keys (): Byte; inline; // keys, ubyte
+ //function DATA (): Byte128; inline; // triggerdata, trigdata[128]; // the only special nested structure
+
+ {$INCLUDE mapdef_help.inc}
+ function trigMonsterId (): Integer; inline;
+ function trigPanelId (): Integer; inline; // panel index in list
+ function trigPanelRec (): TDynRecord; inline;
+
+ private
+ // user fields
+ function getUserPanelId (): Integer; inline;
+ procedure setUserPanelId (v: Integer); inline;
+
+ function getUserTrigRef (): Boolean; inline;
+ procedure setUserTrigRef (v: Boolean); inline;
+
+ public
+ property panel[idx: Integer]: TDynRecord read getPanelByIdx;
+ property panelIndex[pan: TDynRecord]: Integer read getPanelIndex;
+ // triggers
+ property tgPanelId: Integer read trigPanelId;
+ property tgPanelRec: TDynRecord read trigPanelRec;
+ property TexturePanelId: Integer read getTexturePanel; // texturepanel, int
+ property TexturePanelRec: TDynRecord read getTexturePanelRec;
+ // user fields
+ property userPanelId: Integer read getUserPanelId write setUserPanelId;
+ property userPanelTrigRef: Boolean read getUserTrigRef write setUserTrigRef;
+ end;
implementation
-uses SysUtils;
+uses
+ SysUtils, {e_log,} utils, xparser, xstreams;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TDFPoint.Create (ax, ay: LongInt); begin X := ax; Y := ay; end;
+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;
+
+constructor TDFColor.Create (ar, ag, ab: LongInt; aa: LongInt=0);
+begin
+ if (ar < 0) then r := 0 else if (ar > 255) then r := 255 else r := Byte(ar);
+ if (ag < 0) then g := 0 else if (ag > 255) then g := 255 else g := Byte(ag);
+ if (ab < 0) then b := 0 else if (ab > 255) then b := 255 else b := Byte(ab);
+ if (aa < 0) then a := 0 else if (aa > 255) then a := 255 else a := Byte(aa);
+end;
+function TDFColor.isTransparent (): Boolean; inline; begin result := (a = 0); end;
+function TDFColor.isOpaque (): Boolean; inline; begin result := (a = 255); end;
+function TDFColor.isBlack (): Boolean; inline; begin result := (r = 0) and (g = 0) and (b = 0); end;
+function TDFColor.isWhite (): Boolean; inline; begin result := (r = 255) and (g = 255) and (b = 255); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TDynFieldHelper.getRGBA (): TDFColor; inline; begin result := TDFColor.Create(red, green, blue, alpha); end;
+procedure TDynFieldHelper.setRGBA (const v: TDFColor); inline; begin red := v.r; green := v.g; blue := v.b; alpha := v.a; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TDynRecordHelper.getUserPanelId (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ fld := field['userPanelId'];
+ //if (fld = nil) or (fld.baseType <> TDynField.TType.TInt) then result := -1 else result := fld.ival;
+ if (fld = nil) then result := -1 else result := Integer(fld.value);
+end;
+
+
+procedure TDynRecordHelper.setUserPanelId (v: Integer); inline;
+begin
+ user['userPanelId'] := v;
+end;
+
+
+function TDynRecordHelper.getUserTrigRef (): Boolean; inline;
+var
+ fld: TDynField;
+begin
+ fld := field['userPanelTrigRef'];
+ if (fld = nil) then result := false else result := Boolean(fld.value);
+ //if (fld = nil) or (fld.baseType <> TDynField.TType.TBool) then result := false else result := (fld.ival <> 0);
+end;
+
+
+procedure TDynRecordHelper.setUserTrigRef (v: Boolean); inline;
+begin
+ user['userPanelTrigRef'] := v;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TDynRecordHelper.moveSpeed (): TDFPoint; inline; begin result := getPointField('move_speed'); end;
+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;
+begin
+ result := field[aname];
+ if (result = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, typeName, id]));
+ if (result.baseType <> atype) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, typeName, id]));
+end;
+
+
+function TDynRecordHelper.getPointField (const aname: AnsiString): TDFPoint; 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, typeName, id]));
+ if (fld.baseType <> fld.TType.TPoint) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, typeName, id]));
+ result := TDFPoint.Create(fld.ival, fld.ival2);
+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, typeName, id]));
+ if (fld.baseType <> fld.TType.TSize) and (fld.baseType <> fld.TType.TPoint) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, typeName, id]));
+ result := TDFSize.Create(fld.ival, fld.ival2);
+end;
+
+
+function TDynRecordHelper.getPanelByIdx (idx: Integer): TDynRecord; inline;
+var
+ fld: TDynField;
+begin
+ fld := headerRec['panel'];
+ if (fld <> nil) then result := fld.itemAt[idx] else result := nil;
+end;
+
+
+function TDynRecordHelper.getPanelIndex (pan: TDynRecord): Integer;
+var
+ fld: TDynField;
+ f: Integer;
+begin
+ result := -1;
+ if (pan <> nil) then
+ begin
+ fld := headerRec['panel'];
+ if (fld <> nil) then
+ begin
+ for f := 0 to fld.count-1 do if (fld.itemAt[f] = pan) then begin result := f; exit; end;
+ end;
+ end;
+end;
+
+
+function TDynRecordHelper.panelCount (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ fld := headerRec['panel'];
+ if (fld <> nil) then result := fld.count else result := 0;
+end;
+
+
+function TDynRecordHelper.TextureNum (): Word; inline;
+var
+ idx: Integer;
+ fld: TDynField;
+begin
+ fld := getFieldWithType('texture', TDynField.TType.TUShort);
+ idx := fld.recrefIndex;
+ if (idx < 0) then result := Word(TEXTURE_NONE) else result := Word(idx);
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+// trigger
+function TDynRecordHelper.trigRec (): TDynRecord; inline;
+var
+ fld: TDynField;
+begin
+ fld := getFieldWithType('triggerdata', TDynField.TType.TTrigData);
+ if (fld <> nil) then result := fld.recref else result := nil;
+end;
+
+function TDynRecordHelper.trigMonsterId (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ result := -1;
+ fld := field['monsterid'];
+ if (fld = nil) then exit;
+ if (fld.baseType <> TDynField.TType.TInt) then exit;
+ if (fld.recref = nil) then exit;
+ result := fld.recrefIndex;
+end;
+
+function TDynRecordHelper.trigPanelRec (): TDynRecord; inline;
+var
+ fld: TDynField;
+begin
+ result := nil;
+ fld := field['panelid'];
+ if (fld = nil) then exit;
+ if (fld.baseType <> TDynField.TType.TInt) then exit;
+ result := fld.recref;
+ if (result <> nil) and (result.typeName <> 'panel') then result := nil;
+end;
+
+// panel index in list
+function TDynRecordHelper.trigPanelId (): Integer; inline;
+var
+ fld: TDynField;
+begin
+ result := -1;
+ fld := field['panelid'];
+ if (fld = nil) then exit;
+ if (fld.baseType <> TDynField.TType.TInt) then exit;
+ if (fld.recref = nil) then exit;
+ if (fld.recref.typeName <> 'panel') then exit;
+ result := fld.recrefIndex;
+end;
+
+function TDynRecordHelper.getTexturePanelRec (): TDynRecord;
+var
+ fld: TDynField;
+begin
+ result := nil;
+ fld := field['texture_panel'];
+ if (fld = nil) then exit;
+ if (fld.baseType <> TDynField.TType.TInt) then exit;
+ result := fld.recref;
+ if (result <> nil) and (result.typeName <> 'panel') then result := nil;
+end;
+
+function TDynRecordHelper.getTexturePanel (): Integer;
+var
+ fld: TDynField;
+begin
+ result := -1;
+ fld := field['texture_panel'];
+ if (fld = nil) then exit;
+ if (fld.baseType <> TDynField.TType.TInt) then exit;
+ if (fld.recref = nil) then exit;
+ if (fld.recref.typeName <> 'panel') then exit;
+ result := fld.recrefIndex;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TDynRecordHelper.mapName (): AnsiString; inline; begin result := utf2win(getFieldWithType('name', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.mapAuthor (): AnsiString; inline; begin result := utf2win(getFieldWithType('author', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.mapDesc (): AnsiString; inline; begin result := utf2win(getFieldWithType('description', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.musicName (): AnsiString; inline; begin result := utf2win(getFieldWithType('music', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.skyName (): AnsiString; inline; begin result := utf2win(getFieldWithType('sky', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.X (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival; end;
+function TDynRecordHelper.Y (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival2; end;
+function TDynRecordHelper.Width (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival); end;
+function TDynRecordHelper.Height (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival2); end;
+function TDynRecordHelper.PanelType (): Word; inline; begin result := Word(getFieldWithType('type', TDynField.TType.TUShort).ival); end;
+function TDynRecordHelper.TextureRec (): TDynRecord; inline; begin result := getFieldWithType('texture', TDynField.TType.TUShort).recref; end;
+function TDynRecordHelper.Alpha (): Byte; inline; begin result := Byte(getFieldWithType('alpha', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Flags (): Byte; inline; begin result := Byte(getFieldWithType('flags', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Resource (): AnsiString; inline; begin result := utf2win(getFieldWithType('path', TDynField.TType.TChar).sval); end;
+function TDynRecordHelper.Anim (): Boolean; inline; begin result := (getFieldWithType('animated', TDynField.TType.TBool).ival <> 0); end;
+function TDynRecordHelper.ItemType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Options (): Byte; inline; begin result := Byte(getFieldWithType('options', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.MonsterType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Direction (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.AreaType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Enabled (): Boolean; inline; begin result := (getFieldWithType('enabled', TDynField.TType.TBool).ival <> 0); end;
+function TDynRecordHelper.TriggerType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.ActivateType (): Byte; inline; begin result := Byte(getFieldWithType('activate_type', TDynField.TType.TUByte).ival); end;
+function TDynRecordHelper.Keys (): Byte; inline; begin result := Byte(getFieldWithType('keys', TDynField.TType.TUByte).ival); end;
+
+{$INCLUDE mapdef_impl.inc}
-{$INCLUDE mapstructio.inc}
end.