1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE a_modes.inc}
26 MAP_SIGNATURE
= 'MAP';
30 TEXTURE_NAME_WATER
= '_water_0';
31 TEXTURE_NAME_ACID1
= '_water_1';
32 TEXTURE_NAME_ACID2
= '_water_2';
36 TDFPoint
= packed record
41 constructor Create (ax
, ay
: LongInt);
43 function isZero (): Boolean; inline;
46 TDFSize
= packed record
51 constructor Create (aw
, ah
: LongInt);
53 function isZero (): Boolean; inline;
54 function isValid (): Boolean; inline;
57 TDFColor
= packed record
59 r
, g
, b
, a
: Byte; // a: 0 is transparent, 255 is opaque
62 constructor Create (ar
, ag
, ab
: LongInt; aa
: LongInt=0);
64 function isTransparent (): Boolean; inline;
65 function isOpaque (): Boolean; inline;
66 function isBlack (): Boolean; inline;
67 function isWhite (): Boolean; inline;
72 // various helpers to access map structures
74 TDynFieldHelper
= class helper
for TDynField
76 function getRGBA (): TDFColor
; inline;
77 procedure setRGBA (const v
: TDFColor
); inline;
80 property rgba
: TDFColor read getRGBA write setRGBA
; // for `TColor`
83 TDynRecordHelper
= class helper
for TDynRecord
85 function getFieldWithType (const aname
: AnsiString
; atype
: TDynField
.TType
): TDynField
; inline;
87 function getPanelByIdx (idx
: Integer): TDynRecord
; inline;
89 function getTexturePanel (): Integer; inline;
90 function getTexturePanelRec (): TDynRecord
; inline;
92 function getPanelIndex (pan
: TDynRecord
): Integer;
94 function getPointField (const aname
: AnsiString
): TDFPoint
; inline;
95 function getSizeField (const aname
: AnsiString
): TDFSize
; inline;
98 function panelCount (): Integer; inline;
101 function mapName (): AnsiString
; inline;
102 function mapAuthor (): AnsiString
; inline;
103 function mapDesc (): AnsiString
; inline;
104 function musicName (): AnsiString
; inline;
105 function skyName (): AnsiString
; inline;
108 function X (): Integer; inline;
109 function Y (): Integer; inline;
110 function Width (): Word; inline;
111 function Height (): Word; inline;
112 function TextureNum (): Word; inline;
113 function TextureRec (): TDynRecord
; inline;
114 function PanelType (): Word; inline;
115 function Alpha (): Byte; inline;
116 function Flags (): Byte; inline;
118 function moveSpeed (): TDFPoint
; inline;
119 function moveStart (): TDFPoint
; inline;
120 function moveEnd (): TDFPoint
; inline;
122 function moveOnce (): Boolean; inline;
124 function sizeSpeed (): TDFSize
; inline;
125 function sizeEnd (): TDFSize
; inline;
127 function endPosTrig (): Integer; inline;
128 function endSizeTrig (): Integer; inline;
131 function Resource (): AnsiString
; inline;
132 function Anim (): Boolean; inline;
135 function ItemType (): Byte; inline;
136 function Options (): Byte; inline;
139 function MonsterType (): Byte; inline; // type, ubyte
140 function Direction (): Byte; inline; // direction, ubyte
143 function AreaType (): Byte; inline; // type, ubyte
144 //function Direction (): Byte; inline; // direction, ubyte
147 function trigRec (): TDynRecord
; {inline;}
148 function Enabled (): Boolean; inline; // enabled, bool
149 function TriggerType (): Byte; inline; // type, ubyte
150 function ActivateType (): Byte; inline; // activatetype, ubyte
151 function Keys (): Byte; inline; // keys, ubyte
152 //function DATA (): Byte128; inline; // triggerdata, trigdata[128]; // the only special nested structure
154 {$INCLUDE mapdef_help.inc}
155 function trigMonsterId (): Integer; inline;
156 function trigPanelId (): Integer; inline; // panel index in list
157 function trigPanelRec (): TDynRecord
; inline;
161 function getUserPanelId (): Integer; inline;
162 procedure setUserPanelId (v
: Integer); inline;
164 function getUserTrigRef (): Boolean; inline;
165 procedure setUserTrigRef (v
: Boolean); inline;
168 property panel
[idx
: Integer]: TDynRecord read getPanelByIdx
;
169 property panelIndex
[pan
: TDynRecord
]: Integer read getPanelIndex
;
171 property tgPanelId
: Integer read trigPanelId
;
172 property tgPanelRec
: TDynRecord read trigPanelRec
;
173 property TexturePanelId
: Integer read getTexturePanel
; // texturepanel, int
174 property TexturePanelRec
: TDynRecord read getTexturePanelRec
;
176 property userPanelId
: Integer read getUserPanelId write setUserPanelId
;
177 property userPanelTrigRef
: Boolean read getUserTrigRef write setUserTrigRef
;
183 SysUtils
, {e_log,} utils
, xparser
, xstreams
;
186 // ////////////////////////////////////////////////////////////////////////// //
187 constructor TDFPoint
.Create (ax
, ay
: LongInt); begin X
:= ax
; Y
:= ay
; end;
188 function TDFPoint
.isZero (): Boolean; inline; begin result
:= (X
= 0) and (Y
= 0); end;
191 constructor TDFSize
.Create (aw
, ah
: LongInt); begin w
:= aw
; h
:= ah
; end;
192 function TDFSize
.isZero (): Boolean; inline; begin result
:= (w
= 0) and (h
= 0); end;
193 function TDFSize
.isValid (): Boolean; inline; begin result
:= (w
> 0) and (h
> 0); end;
195 constructor TDFColor
.Create (ar
, ag
, ab
: LongInt; aa
: LongInt=0);
197 if (ar
< 0) then r
:= 0 else if (ar
> 255) then r
:= 255 else r
:= Byte(ar
);
198 if (ag
< 0) then g
:= 0 else if (ag
> 255) then g
:= 255 else g
:= Byte(ag
);
199 if (ab
< 0) then b
:= 0 else if (ab
> 255) then b
:= 255 else b
:= Byte(ab
);
200 if (aa
< 0) then a
:= 0 else if (aa
> 255) then a
:= 255 else a
:= Byte(aa
);
202 function TDFColor
.isTransparent (): Boolean; inline; begin result
:= (a
= 0); end;
203 function TDFColor
.isOpaque (): Boolean; inline; begin result
:= (a
= 255); end;
204 function TDFColor
.isBlack (): Boolean; inline; begin result
:= (r
= 0) and (g
= 0) and (b
= 0); end;
205 function TDFColor
.isWhite (): Boolean; inline; begin result
:= (r
= 255) and (g
= 255) and (b
= 255); end;
208 // ////////////////////////////////////////////////////////////////////////// //
209 function TDynFieldHelper
.getRGBA (): TDFColor
; inline; begin result
:= TDFColor
.Create(red
, green
, blue
, alpha
); end;
210 procedure TDynFieldHelper
.setRGBA (const v
: TDFColor
); inline; begin red
:= v
.r
; green
:= v
.g
; blue
:= v
.b
; alpha
:= v
.a
; end;
213 // ////////////////////////////////////////////////////////////////////////// //
214 function TDynRecordHelper
.getUserPanelId (): Integer; inline;
218 fld
:= field
['userPanelId'];
219 //if (fld = nil) or (fld.baseType <> TDynField.TType.TInt) then result := -1 else result := fld.ival;
220 if (fld
= nil) then result
:= -1 else result
:= Integer(fld
.value
);
224 procedure TDynRecordHelper
.setUserPanelId (v
: Integer); inline;
226 user
['userPanelId'] := v
;
230 function TDynRecordHelper
.getUserTrigRef (): Boolean; inline;
234 fld
:= field
['userPanelTrigRef'];
235 if (fld
= nil) then result
:= false else result
:= Boolean(fld
.value
);
236 //if (fld = nil) or (fld.baseType <> TDynField.TType.TBool) then result := false else result := (fld.ival <> 0);
240 procedure TDynRecordHelper
.setUserTrigRef (v
: Boolean); inline;
242 user
['userPanelTrigRef'] := v
;
246 // ////////////////////////////////////////////////////////////////////////// //
247 function TDynRecordHelper
.moveSpeed (): TDFPoint
; inline; begin result
:= getPointField('move_speed'); end;
248 function TDynRecordHelper
.moveStart (): TDFPoint
; inline; begin result
:= getPointField('move_start'); end;
249 function TDynRecordHelper
.moveEnd (): TDFPoint
; inline; begin result
:= getPointField('move_end'); end;
251 function TDynRecordHelper
.sizeSpeed (): TDFSize
; inline; begin result
:= getSizeField('size_speed'); end;
252 function TDynRecordHelper
.sizeEnd (): TDFSize
; inline; begin result
:= getSizeField('size_end'); end;
254 function TDynRecordHelper
.moveOnce (): Boolean; inline; begin result
:= (getFieldWithType('move_once', TDynField
.TType
.TBool
).ival
<> 0); end;
257 function TDynRecordHelper
.endPosTrig (): Integer; inline;
261 fld
:= getFieldWithType('end_pos_trigger', TDynField
.TType
.TInt
);
262 result
:= fld
.recrefIndex
;
265 function TDynRecordHelper
.endSizeTrig (): Integer; inline;
269 fld
:= getFieldWithType('end_size_trigger', TDynField
.TType
.TInt
);
270 result
:= fld
.recrefIndex
;
274 // ////////////////////////////////////////////////////////////////////////// //
275 function TDynRecordHelper
.getFieldWithType (const aname
: AnsiString
; atype
: TDynField
.TType
): TDynField
; inline;
277 result
:= field
[aname
];
278 if (result
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
279 if (result
.baseType
<> atype
) then raise Exception
.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname
, typeName
, id
]));
283 function TDynRecordHelper
.getPointField (const aname
: AnsiString
): TDFPoint
; inline;
288 if (fld
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
289 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
]));
290 result
:= TDFPoint
.Create(fld
.ival
, fld
.ival2
);
294 function TDynRecordHelper
.getSizeField (const aname
: AnsiString
): TDFSize
; inline;
299 if (fld
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
300 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
]));
301 result
:= TDFSize
.Create(fld
.ival
, fld
.ival2
);
305 function TDynRecordHelper
.getPanelByIdx (idx
: Integer): TDynRecord
; inline;
309 fld
:= headerRec
['panel'];
310 if (fld
<> nil) then result
:= fld
.itemAt
[idx
] else result
:= nil;
314 function TDynRecordHelper
.getPanelIndex (pan
: TDynRecord
): Integer;
322 fld
:= headerRec
['panel'];
325 for f
:= 0 to fld
.count
-1 do if (fld
.itemAt
[f
] = pan
) then begin result
:= f
; exit
; end;
331 function TDynRecordHelper
.panelCount (): Integer; inline;
335 fld
:= headerRec
['panel'];
336 if (fld
<> nil) then result
:= fld
.count
else result
:= 0;
340 function TDynRecordHelper
.TextureNum (): Word; inline;
345 fld
:= getFieldWithType('texture', TDynField
.TType
.TUShort
);
346 idx
:= fld
.recrefIndex
;
347 if (idx
< 0) then result
:= Word(TEXTURE_NONE
) else result
:= Word(idx
);
351 // ////////////////////////////////////////////////////////////////////////// //
353 function TDynRecordHelper
.trigRec (): TDynRecord
; {inline;}
357 fld
:= getFieldWithType('triggerdata', TDynField
.TType
.TTrigData
);
358 if (fld
<> nil) then result
:= fld
.recref
else result
:= nil;
361 function TDynRecordHelper
.trigMonsterId (): Integer; inline;
366 fld
:= field
['monsterid'];
367 if (fld
= nil) then exit
;
368 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
369 if (fld
.recref
= nil) then exit
;
370 result
:= fld
.recrefIndex
;
373 function TDynRecordHelper
.trigPanelRec (): TDynRecord
; inline;
378 fld
:= field
['panelid'];
379 if (fld
= nil) then exit
;
380 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
381 result
:= fld
.recref
;
382 if (result
<> nil) and (result
.typeName
<> 'panel') then result
:= nil;
385 // panel index in list
386 function TDynRecordHelper
.trigPanelId (): Integer; inline;
391 fld
:= field
['panelid'];
392 if (fld
= nil) then exit
;
393 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
394 if (fld
.recref
= nil) then exit
;
395 if (fld
.recref
.typeName
<> 'panel') then exit
;
396 result
:= fld
.recrefIndex
;
399 function TDynRecordHelper
.getTexturePanelRec (): TDynRecord
;
404 fld
:= field
['texture_panel'];
405 if (fld
= nil) then exit
;
406 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
407 result
:= fld
.recref
;
408 if (result
<> nil) and (result
.typeName
<> 'panel') then result
:= nil;
411 function TDynRecordHelper
.getTexturePanel (): Integer;
416 fld
:= field
['texture_panel'];
417 if (fld
= nil) then exit
;
418 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
419 if (fld
.recref
= nil) then exit
;
420 if (fld
.recref
.typeName
<> 'panel') then exit
;
421 result
:= fld
.recrefIndex
;
425 // ////////////////////////////////////////////////////////////////////////// //
426 function TDynRecordHelper
.mapName (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('name', TDynField
.TType
.TChar
).sval
); end;
427 function TDynRecordHelper
.mapAuthor (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('author', TDynField
.TType
.TChar
).sval
); end;
428 function TDynRecordHelper
.mapDesc (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('description', TDynField
.TType
.TChar
).sval
); end;
429 function TDynRecordHelper
.musicName (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('music', TDynField
.TType
.TChar
).sval
); end;
430 function TDynRecordHelper
.skyName (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('sky', TDynField
.TType
.TChar
).sval
); end;
431 function TDynRecordHelper
.X (): Integer; inline; begin result
:= getFieldWithType('position', TDynField
.TType
.TPoint
).ival
; end;
432 function TDynRecordHelper
.Y (): Integer; inline; begin result
:= getFieldWithType('position', TDynField
.TType
.TPoint
).ival2
; end;
433 function TDynRecordHelper
.Width (): Word; inline; begin result
:= Word(getFieldWithType('size', TDynField
.TType
.TSize
).ival
); end;
434 function TDynRecordHelper
.Height (): Word; inline; begin result
:= Word(getFieldWithType('size', TDynField
.TType
.TSize
).ival2
); end;
435 function TDynRecordHelper
.PanelType (): Word; inline; begin result
:= Word(getFieldWithType('type', TDynField
.TType
.TUShort
).ival
); end;
436 function TDynRecordHelper
.TextureRec (): TDynRecord
; inline; begin result
:= getFieldWithType('texture', TDynField
.TType
.TUShort
).recref
; end;
437 function TDynRecordHelper
.Alpha (): Byte; inline; begin result
:= Byte(getFieldWithType('alpha', TDynField
.TType
.TUByte
).ival
); end;
438 function TDynRecordHelper
.Flags (): Byte; inline; begin result
:= Byte(getFieldWithType('flags', TDynField
.TType
.TUByte
).ival
); end;
439 function TDynRecordHelper
.Resource (): AnsiString
; inline; begin result
:= utf2win(getFieldWithType('path', TDynField
.TType
.TChar
).sval
); end;
440 function TDynRecordHelper
.Anim (): Boolean; inline; begin result
:= (getFieldWithType('animated', TDynField
.TType
.TBool
).ival
<> 0); end;
441 function TDynRecordHelper
.ItemType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
442 function TDynRecordHelper
.Options (): Byte; inline; begin result
:= Byte(getFieldWithType('options', TDynField
.TType
.TUByte
).ival
); end;
443 function TDynRecordHelper
.MonsterType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
444 function TDynRecordHelper
.Direction (): Byte; inline; begin result
:= Byte(getFieldWithType('direction', TDynField
.TType
.TUByte
).ival
); end;
445 function TDynRecordHelper
.AreaType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
446 function TDynRecordHelper
.Enabled (): Boolean; inline; begin result
:= (getFieldWithType('enabled', TDynField
.TType
.TBool
).ival
<> 0); end;
447 function TDynRecordHelper
.TriggerType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
448 function TDynRecordHelper
.ActivateType (): Byte; inline; begin result
:= Byte(getFieldWithType('activate_type', TDynField
.TType
.TUByte
).ival
); end;
449 function TDynRecordHelper
.Keys (): Byte; inline; begin result
:= Byte(getFieldWithType('keys', TDynField
.TType
.TUByte
).ival
); end;
451 {$INCLUDE mapdef_impl.inc}