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, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE a_modes.inc}
27 MAP_SIGNATURE
= 'MAP';
31 TEXTURE_NAME_WATER
= '_water_0';
32 TEXTURE_NAME_ACID1
= '_water_1';
33 TEXTURE_NAME_ACID2
= '_water_2';
37 TDFPoint
= packed record
42 constructor Create (ax
, ay
: LongInt);
44 function isZero (): Boolean; inline;
47 TDFSize
= packed record
52 constructor Create (aw
, ah
: LongInt);
54 function isZero (): Boolean; inline;
55 function isValid (): Boolean; inline;
58 TDFColor
= packed record
60 r
, g
, b
, a
: Byte; // a: 0 is transparent, 255 is opaque
63 constructor Create (ar
, ag
, ab
: LongInt; aa
: LongInt=0);
65 function isTransparent (): Boolean; inline;
66 function isOpaque (): Boolean; inline;
67 function isBlack (): Boolean; inline;
68 function isWhite (): Boolean; inline;
73 // various helpers to access map structures
75 TDynFieldHelper
= class helper
for TDynField
77 function getRGBA (): TDFColor
; inline;
78 procedure setRGBA (const v
: TDFColor
); inline;
81 property rgba
: TDFColor read getRGBA write setRGBA
; // for `TColor`
84 TDynRecordHelper
= class helper
for TDynRecord
86 function getFieldWithType (const aname
: AnsiString; atype
: TDynField
.TType
): TDynField
; inline;
88 function getPanelByIdx (idx
: Integer): TDynRecord
; inline;
90 function getTexturePanel (): Integer; inline;
91 function getTexturePanelRec (): TDynRecord
; inline;
93 function getPanelIndex (pan
: TDynRecord
): Integer;
95 function getPointField (const aname
: AnsiString): TDFPoint
; inline;
96 function getSizeField (const aname
: AnsiString): TDFSize
; inline;
99 function panelCount (): Integer; inline;
102 function mapName (): AnsiString; inline;
103 function mapAuthor (): AnsiString; inline;
104 function mapDesc (): AnsiString; inline;
105 function musicName (): AnsiString; inline;
106 function skyName (): AnsiString; inline;
109 function X (): Integer; inline;
110 function Y (): Integer; inline;
111 function Width (): Word; inline;
112 function Height (): Word; inline;
113 function TextureNum (): Word; inline;
114 function TextureRec (): TDynRecord
; inline;
115 function PanelType (): Word; inline;
116 function Alpha (): Byte; inline;
117 function Flags (): Byte; inline;
119 function moveSpeed (): TDFPoint
; inline;
120 function moveStart (): TDFPoint
; inline;
121 function moveEnd (): TDFPoint
; inline;
123 function moveOnce (): Boolean; inline;
125 function sizeSpeed (): TDFSize
; inline;
126 function sizeEnd (): TDFSize
; inline;
128 function endPosTrig (): Integer; inline;
129 function endSizeTrig (): Integer; inline;
132 function Resource (): AnsiString; inline;
133 function Anim (): Boolean; inline;
136 function ItemType (): Byte; inline;
137 function Options (): Byte; inline;
140 function MonsterType (): Byte; inline; // type, ubyte
141 function Direction (): Byte; inline; // direction, ubyte
144 function AreaType (): Byte; inline; // type, ubyte
145 //function Direction (): Byte; inline; // direction, ubyte
148 function trigRec (): TDynRecord
; inline;
149 function Enabled (): Boolean; inline; // enabled, bool
150 function TriggerType (): Byte; inline; // type, ubyte
151 function ActivateType (): Byte; inline; // activatetype, ubyte
152 function Keys (): Byte; inline; // keys, ubyte
153 //function DATA (): Byte128; inline; // triggerdata, trigdata[128]; // the only special nested structure
155 {$INCLUDE mapdef_help.inc}
156 function trigMonsterId (): Integer; inline;
157 function trigPanelId (): Integer; inline; // panel index in list
158 function trigPanelRec (): TDynRecord
; inline;
162 function getUserPanelId (): Integer; inline;
163 procedure setUserPanelId (v
: Integer); inline;
165 function getUserTrigRef (): Boolean; inline;
166 procedure setUserTrigRef (v
: Boolean); inline;
169 property panel
[idx
: Integer]: TDynRecord read getPanelByIdx
;
170 property panelIndex
[pan
: TDynRecord
]: Integer read getPanelIndex
;
172 property tgPanelId
: Integer read trigPanelId
;
173 property tgPanelRec
: TDynRecord read trigPanelRec
;
174 property TexturePanelId
: Integer read getTexturePanel
; // texturepanel, int
175 property TexturePanelRec
: TDynRecord read getTexturePanelRec
;
177 property userPanelId
: Integer read getUserPanelId write setUserPanelId
;
178 property userPanelTrigRef
: Boolean read getUserTrigRef write setUserTrigRef
;
184 SysUtils
, {e_log,} utils
, xparser
, xstreams
;
187 // ////////////////////////////////////////////////////////////////////////// //
188 constructor TDFPoint
.Create (ax
, ay
: LongInt); begin X
:= ax
; Y
:= ay
; end;
189 function TDFPoint
.isZero (): Boolean; inline; begin result
:= (X
= 0) and (Y
= 0); end;
192 constructor TDFSize
.Create (aw
, ah
: LongInt); begin w
:= aw
; h
:= ah
; end;
193 function TDFSize
.isZero (): Boolean; inline; begin result
:= (w
= 0) and (h
= 0); end;
194 function TDFSize
.isValid (): Boolean; inline; begin result
:= (w
> 0) and (h
> 0); end;
196 constructor TDFColor
.Create (ar
, ag
, ab
: LongInt; aa
: LongInt=0);
198 if (ar
< 0) then r
:= 0 else if (ar
> 255) then r
:= 255 else r
:= Byte(ar
);
199 if (ag
< 0) then g
:= 0 else if (ag
> 255) then g
:= 255 else g
:= Byte(ag
);
200 if (ab
< 0) then b
:= 0 else if (ab
> 255) then b
:= 255 else b
:= Byte(ab
);
201 if (aa
< 0) then a
:= 0 else if (aa
> 255) then a
:= 255 else a
:= Byte(aa
);
203 function TDFColor
.isTransparent (): Boolean; inline; begin result
:= (a
= 0); end;
204 function TDFColor
.isOpaque (): Boolean; inline; begin result
:= (a
= 255); end;
205 function TDFColor
.isBlack (): Boolean; inline; begin result
:= (r
= 0) and (g
= 0) and (b
= 0); end;
206 function TDFColor
.isWhite (): Boolean; inline; begin result
:= (r
= 255) and (g
= 255) and (b
= 255); end;
209 // ////////////////////////////////////////////////////////////////////////// //
210 function TDynFieldHelper
.getRGBA (): TDFColor
; inline; begin result
:= TDFColor
.Create(red
, green
, blue
, alpha
); end;
211 procedure TDynFieldHelper
.setRGBA (const v
: TDFColor
); inline; begin red
:= v
.r
; green
:= v
.g
; blue
:= v
.b
; alpha
:= v
.a
; end;
214 // ////////////////////////////////////////////////////////////////////////// //
215 function TDynRecordHelper
.getUserPanelId (): Integer; inline;
219 fld
:= field
['userPanelId'];
220 //if (fld = nil) or (fld.baseType <> TDynField.TType.TInt) then result := -1 else result := fld.ival;
221 if (fld
= nil) then result
:= -1 else result
:= Integer(fld
.value
);
225 procedure TDynRecordHelper
.setUserPanelId (v
: Integer); inline;
227 user
['userPanelId'] := v
;
231 function TDynRecordHelper
.getUserTrigRef (): Boolean; inline;
235 fld
:= field
['userPanelTrigRef'];
236 if (fld
= nil) then result
:= false else result
:= Boolean(fld
.value
);
237 //if (fld = nil) or (fld.baseType <> TDynField.TType.TBool) then result := false else result := (fld.ival <> 0);
241 procedure TDynRecordHelper
.setUserTrigRef (v
: Boolean); inline;
243 user
['userPanelTrigRef'] := v
;
247 // ////////////////////////////////////////////////////////////////////////// //
248 function TDynRecordHelper
.moveSpeed (): TDFPoint
; inline; begin result
:= getPointField('move_speed'); end;
249 function TDynRecordHelper
.moveStart (): TDFPoint
; inline; begin result
:= getPointField('move_start'); end;
250 function TDynRecordHelper
.moveEnd (): TDFPoint
; inline; begin result
:= getPointField('move_end'); end;
252 function TDynRecordHelper
.sizeSpeed (): TDFSize
; inline; begin result
:= getSizeField('size_speed'); end;
253 function TDynRecordHelper
.sizeEnd (): TDFSize
; inline; begin result
:= getSizeField('size_end'); end;
255 function TDynRecordHelper
.moveOnce (): Boolean; inline; begin result
:= (getFieldWithType('move_once', TDynField
.TType
.TBool
).ival
<> 0); end;
258 function TDynRecordHelper
.endPosTrig (): Integer; inline;
262 fld
:= getFieldWithType('end_pos_trigger', TDynField
.TType
.TInt
);
263 result
:= fld
.recrefIndex
;
266 function TDynRecordHelper
.endSizeTrig (): Integer; inline;
270 fld
:= getFieldWithType('end_size_trigger', TDynField
.TType
.TInt
);
271 result
:= fld
.recrefIndex
;
275 // ////////////////////////////////////////////////////////////////////////// //
276 function TDynRecordHelper
.getFieldWithType (const aname
: AnsiString; atype
: TDynField
.TType
): TDynField
; inline;
278 result
:= field
[aname
];
279 if (result
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
280 if (result
.baseType
<> atype
) then raise Exception
.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname
, typeName
, id
]));
284 function TDynRecordHelper
.getPointField (const aname
: AnsiString): TDFPoint
; inline;
289 if (fld
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
290 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
]));
291 result
:= TDFPoint
.Create(fld
.ival
, fld
.ival2
);
295 function TDynRecordHelper
.getSizeField (const aname
: AnsiString): TDFSize
; inline;
300 if (fld
= nil) then raise Exception
.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname
, typeName
, id
]));
301 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
]));
302 result
:= TDFSize
.Create(fld
.ival
, fld
.ival2
);
306 function TDynRecordHelper
.getPanelByIdx (idx
: Integer): TDynRecord
; inline;
310 fld
:= headerRec
['panel'];
311 if (fld
<> nil) then result
:= fld
.itemAt
[idx
] else result
:= nil;
315 function TDynRecordHelper
.getPanelIndex (pan
: TDynRecord
): Integer;
323 fld
:= headerRec
['panel'];
326 for f
:= 0 to fld
.count
-1 do if (fld
.itemAt
[f
] = pan
) then begin result
:= f
; exit
; end;
332 function TDynRecordHelper
.panelCount (): Integer; inline;
336 fld
:= headerRec
['panel'];
337 if (fld
<> nil) then result
:= fld
.count
else result
:= 0;
341 function TDynRecordHelper
.TextureNum (): Word; inline;
346 fld
:= getFieldWithType('texture', TDynField
.TType
.TUShort
);
347 idx
:= fld
.recrefIndex
;
348 if (idx
< 0) then result
:= Word(TEXTURE_NONE
) else result
:= Word(idx
);
352 // ////////////////////////////////////////////////////////////////////////// //
354 function TDynRecordHelper
.trigRec (): TDynRecord
; inline;
358 fld
:= getFieldWithType('triggerdata', TDynField
.TType
.TTrigData
);
359 if (fld
<> nil) then result
:= fld
.recref
else result
:= nil;
362 function TDynRecordHelper
.trigMonsterId (): Integer; inline;
367 fld
:= field
['monsterid'];
368 if (fld
= nil) then exit
;
369 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
370 if (fld
.recref
= nil) then exit
;
371 result
:= fld
.recrefIndex
;
374 function TDynRecordHelper
.trigPanelRec (): TDynRecord
; inline;
379 fld
:= field
['panelid'];
380 if (fld
= nil) then exit
;
381 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
382 result
:= fld
.recref
;
383 if (result
<> nil) and (result
.typeName
<> 'panel') then result
:= nil;
386 // panel index in list
387 function TDynRecordHelper
.trigPanelId (): Integer; inline;
392 fld
:= field
['panelid'];
393 if (fld
= nil) then exit
;
394 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
395 if (fld
.recref
= nil) then exit
;
396 if (fld
.recref
.typeName
<> 'panel') then exit
;
397 result
:= fld
.recrefIndex
;
400 function TDynRecordHelper
.getTexturePanelRec (): TDynRecord
;
405 fld
:= field
['texture_panel'];
406 if (fld
= nil) then exit
;
407 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
408 result
:= fld
.recref
;
409 if (result
<> nil) and (result
.typeName
<> 'panel') then result
:= nil;
412 function TDynRecordHelper
.getTexturePanel (): Integer;
417 fld
:= field
['texture_panel'];
418 if (fld
= nil) then exit
;
419 if (fld
.baseType
<> TDynField
.TType
.TInt
) then exit
;
420 if (fld
.recref
= nil) then exit
;
421 if (fld
.recref
.typeName
<> 'panel') then exit
;
422 result
:= fld
.recrefIndex
;
426 // ////////////////////////////////////////////////////////////////////////// //
427 function TDynRecordHelper
.mapName (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('name', TDynField
.TType
.TChar
).sval
); end;
428 function TDynRecordHelper
.mapAuthor (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('author', TDynField
.TType
.TChar
).sval
); end;
429 function TDynRecordHelper
.mapDesc (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('description', TDynField
.TType
.TChar
).sval
); end;
430 function TDynRecordHelper
.musicName (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('music', TDynField
.TType
.TChar
).sval
); end;
431 function TDynRecordHelper
.skyName (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('sky', TDynField
.TType
.TChar
).sval
); end;
432 function TDynRecordHelper
.X (): Integer; inline; begin result
:= getFieldWithType('position', TDynField
.TType
.TPoint
).ival
; end;
433 function TDynRecordHelper
.Y (): Integer; inline; begin result
:= getFieldWithType('position', TDynField
.TType
.TPoint
).ival2
; end;
434 function TDynRecordHelper
.Width (): Word; inline; begin result
:= Word(getFieldWithType('size', TDynField
.TType
.TSize
).ival
); end;
435 function TDynRecordHelper
.Height (): Word; inline; begin result
:= Word(getFieldWithType('size', TDynField
.TType
.TSize
).ival2
); end;
436 function TDynRecordHelper
.PanelType (): Word; inline; begin result
:= Word(getFieldWithType('type', TDynField
.TType
.TUShort
).ival
); end;
437 function TDynRecordHelper
.TextureRec (): TDynRecord
; inline; begin result
:= getFieldWithType('texture', TDynField
.TType
.TUShort
).recref
; end;
438 function TDynRecordHelper
.Alpha (): Byte; inline; begin result
:= Byte(getFieldWithType('alpha', TDynField
.TType
.TUByte
).ival
); end;
439 function TDynRecordHelper
.Flags (): Byte; inline; begin result
:= Byte(getFieldWithType('flags', TDynField
.TType
.TUByte
).ival
); end;
440 function TDynRecordHelper
.Resource (): AnsiString; inline; begin result
:= utf2win(getFieldWithType('path', TDynField
.TType
.TChar
).sval
); end;
441 function TDynRecordHelper
.Anim (): Boolean; inline; begin result
:= (getFieldWithType('animated', TDynField
.TType
.TBool
).ival
<> 0); end;
442 function TDynRecordHelper
.ItemType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
443 function TDynRecordHelper
.Options (): Byte; inline; begin result
:= Byte(getFieldWithType('options', TDynField
.TType
.TUByte
).ival
); end;
444 function TDynRecordHelper
.MonsterType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
445 function TDynRecordHelper
.Direction (): Byte; inline; begin result
:= Byte(getFieldWithType('direction', TDynField
.TType
.TUByte
).ival
); end;
446 function TDynRecordHelper
.AreaType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
447 function TDynRecordHelper
.Enabled (): Boolean; inline; begin result
:= (getFieldWithType('enabled', TDynField
.TType
.TBool
).ival
<> 0); end;
448 function TDynRecordHelper
.TriggerType (): Byte; inline; begin result
:= Byte(getFieldWithType('type', TDynField
.TType
.TUByte
).ival
); end;
449 function TDynRecordHelper
.ActivateType (): Byte; inline; begin result
:= Byte(getFieldWithType('activate_type', TDynField
.TType
.TUByte
).ival
); end;
450 function TDynRecordHelper
.Keys (): Byte; inline; begin result
:= Byte(getFieldWithType('keys', TDynField
.TType
.TUByte
).ival
); end;
452 {$INCLUDE mapdef_impl.inc}