DEADSOFTWARE

53bedb79b1c329fa632fee6755cd1a82312133e6
[d2df-sdl.git] / src / shared / MAPDEF.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
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.
7 *
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.
12 *
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/>.
15 *)
16 {$INCLUDE a_modes.inc}
17 {$M+}
18 unit MAPDEF;
20 interface
22 uses
23 xdynrec;
26 const
27 MAP_SIGNATURE = 'MAP';
30 const
31 TEXTURE_NAME_WATER = '_water_0';
32 TEXTURE_NAME_ACID1 = '_water_1';
33 TEXTURE_NAME_ACID2 = '_water_2';
36 type
37 TDFPoint = packed record
38 public
39 X, Y: LongInt;
41 public
42 constructor Create (ax, ay: LongInt);
44 function isZero (): Boolean; inline;
45 end;
47 TDFSize = packed record
48 public
49 w, h: LongInt;
51 public
52 constructor Create (aw, ah: LongInt);
54 function isZero (): Boolean; inline;
55 function isValid (): Boolean; inline;
56 end;
58 Char16 = packed array[0..15] of Char;
59 Char32 = packed array[0..31] of Char;
60 Char64 = packed array[0..63] of Char;
61 Char100 = packed array[0..99] of Char;
62 Char256 = packed array[0..255] of Char;
63 Byte128 = packed array[0..127] of Byte;
65 {$INCLUDE mapdef.inc}
67 // various helpers to access map structures
68 type
69 TDynRecordHelper = class helper for TDynRecord
70 private
71 function getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline;
73 function getPanelByIdx (idx: Integer): TDynRecord; inline;
75 function getTexturePanel (): Integer; inline;
76 function getTexturePanelRec (): TDynRecord; inline;
78 function getPanelIndex (pan: TDynRecord): Integer;
80 function getPointField (const aname: AnsiString): TDFPoint; inline;
81 function getSizeField (const aname: AnsiString): TDFSize; inline;
83 public
84 function panelCount (): Integer; inline;
86 // header
87 function mapName (): AnsiString; inline;
88 function mapAuthor (): AnsiString; inline;
89 function mapDesc (): AnsiString; inline;
90 function musicName (): AnsiString; inline;
91 function skyName (): AnsiString; inline;
93 // panel
94 function X (): Integer; inline;
95 function Y (): Integer; inline;
96 function Width (): Word; inline;
97 function Height (): Word; inline;
98 function TextureNum (): Word; inline;
99 function TextureRec (): TDynRecord; inline;
100 function PanelType (): Word; inline;
101 function Alpha (): Byte; inline;
102 function Flags (): Byte; inline;
104 function moveSpeed (): TDFPoint; inline;
105 function moveStart (): TDFPoint; inline;
106 function moveEnd (): TDFPoint; inline;
108 function moveOnce (): Boolean; inline;
110 function sizeSpeed (): TDFSize; inline;
111 function sizeEnd (): TDFSize; inline;
113 function endPosTrig (): Integer; inline;
114 function endSizeTrig (): Integer; inline;
116 // texture
117 function Resource (): AnsiString; inline;
118 function Anim (): Boolean; inline;
120 // item
121 function ItemType (): Byte; inline;
122 function Options (): Byte; inline;
124 // monster
125 function MonsterType (): Byte; inline; // type, ubyte
126 function Direction (): Byte; inline; // direction, ubyte
128 // area
129 function AreaType (): Byte; inline; // type, ubyte
130 //function Direction (): Byte; inline; // direction, ubyte
132 // trigger
133 function trigRec (): TDynRecord; inline;
134 function Enabled (): Boolean; inline; // enabled, bool
135 function TriggerType (): Byte; inline; // type, ubyte
136 function ActivateType (): Byte; inline; // activatetype, ubyte
137 function Keys (): Byte; inline; // keys, ubyte
138 //function DATA (): Byte128; inline; // triggerdata, trigdata[128]; // the only special nested structure
140 {$INCLUDE mapdef_help.inc}
141 function trigMonsterId (): Integer; inline;
142 function trigPanelId (): Integer; inline; // panel index in list
143 function trigPanelRec (): TDynRecord; inline;
145 private
146 // user fields
147 function getUserPanelId (): Integer; inline;
148 procedure setUserPanelId (v: Integer); inline;
150 function getUserTrigRef (): Boolean; inline;
151 procedure setUserTrigRef (v: Boolean); inline;
153 public
154 property panel[idx: Integer]: TDynRecord read getPanelByIdx;
155 property panelIndex[pan: TDynRecord]: Integer read getPanelIndex;
156 // triggers
157 property tgPanelId: Integer read trigPanelId;
158 property tgPanelRec: TDynRecord read trigPanelRec;
159 property TexturePanelId: Integer read getTexturePanel; // texturepanel, int
160 property TexturePanelRec: TDynRecord read getTexturePanelRec;
161 // user fields
162 property userPanelId: Integer read getUserPanelId write setUserPanelId;
163 property userPanelTrigRef: Boolean read getUserTrigRef write setUserTrigRef;
164 end;
166 implementation
168 uses
169 SysUtils, {e_log,} utils, xparser, xstreams;
172 // ////////////////////////////////////////////////////////////////////////// //
173 constructor TDFPoint.Create (ax, ay: LongInt); begin X := ax; Y := ay; end;
174 function TDFPoint.isZero (): Boolean; inline; begin result := (X = 0) and (Y = 0); end;
177 constructor TDFSize.Create (aw, ah: LongInt); begin w := aw; h := ah; end;
178 function TDFSize.isZero (): Boolean; inline; begin result := (w = 0) and (h = 0); end;
179 function TDFSize.isValid (): Boolean; inline; begin result := (w > 0) and (h > 0); end;
182 // ////////////////////////////////////////////////////////////////////////// //
183 function TDynRecordHelper.getUserPanelId (): Integer; inline;
184 var
185 fld: TDynField;
186 begin
187 fld := field['userPanelId'];
188 //if (fld = nil) or (fld.baseType <> TDynField.TType.TInt) then result := -1 else result := fld.ival;
189 if (fld = nil) then result := -1 else result := Integer(fld.value);
190 end;
193 procedure TDynRecordHelper.setUserPanelId (v: Integer); inline;
194 begin
195 user['userPanelId'] := v;
196 end;
199 function TDynRecordHelper.getUserTrigRef (): Boolean; inline;
200 var
201 fld: TDynField;
202 begin
203 fld := field['userPanelTrigRef'];
204 if (fld = nil) then result := false else result := Boolean(fld.value);
205 //if (fld = nil) or (fld.baseType <> TDynField.TType.TBool) then result := false else result := (fld.ival <> 0);
206 end;
209 procedure TDynRecordHelper.setUserTrigRef (v: Boolean); inline;
210 begin
211 user['userPanelTrigRef'] := v;
212 end;
215 // ////////////////////////////////////////////////////////////////////////// //
216 function TDynRecordHelper.moveSpeed (): TDFPoint; inline; begin result := getPointField('move_speed'); end;
217 function TDynRecordHelper.moveStart (): TDFPoint; inline; begin result := getPointField('move_start'); end;
218 function TDynRecordHelper.moveEnd (): TDFPoint; inline; begin result := getPointField('move_end'); end;
220 function TDynRecordHelper.sizeSpeed (): TDFSize; inline; begin result := getSizeField('size_speed'); end;
221 function TDynRecordHelper.sizeEnd (): TDFSize; inline; begin result := getSizeField('size_end'); end;
223 function TDynRecordHelper.moveOnce (): Boolean; inline; begin result := (getFieldWithType('move_once', TDynField.TType.TBool).ival <> 0); end;
226 function TDynRecordHelper.endPosTrig (): Integer; inline;
227 var
228 fld: TDynField;
229 begin
230 fld := getFieldWithType('end_pos_trigger', TDynField.TType.TInt);
231 result := fld.recrefIndex;
232 end;
234 function TDynRecordHelper.endSizeTrig (): Integer; inline;
235 var
236 fld: TDynField;
237 begin
238 fld := getFieldWithType('end_size_trigger', TDynField.TType.TInt);
239 result := fld.recrefIndex;
240 end;
243 // ////////////////////////////////////////////////////////////////////////// //
244 function TDynRecordHelper.getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline;
245 begin
246 result := field[aname];
247 if (result = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, typeName, id]));
248 if (result.baseType <> atype) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, typeName, id]));
249 end;
252 function TDynRecordHelper.getPointField (const aname: AnsiString): TDFPoint; inline;
253 var
254 fld: TDynField;
255 begin
256 fld := field[aname];
257 if (fld = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, typeName, id]));
258 if (fld.baseType <> TPoint) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of type ''%s'' has invalid data type', [aname, typeName, id]));
259 result := TDFPoint.Create(fld.ival, fld.ival2);
260 end;
263 function TDynRecordHelper.getSizeField (const aname: AnsiString): TDFSize; inline;
264 var
265 fld: TDynField;
266 begin
267 fld := field[aname];
268 if (fld = nil) then raise Exception.Create(Format('field ''%s'' not found in record ''%s'' of type ''%s''', [aname, typeName, id]));
269 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, typeName, id]));
270 result := TDFSize.Create(fld.ival, fld.ival2);
271 end;
274 function TDynRecordHelper.getPanelByIdx (idx: Integer): TDynRecord; inline;
275 var
276 fld: TDynField;
277 begin
278 fld := headerRec['panel'];
279 if (fld <> nil) then result := fld.itemAt[idx] else result := nil;
280 end;
283 function TDynRecordHelper.getPanelIndex (pan: TDynRecord): Integer;
284 var
285 fld: TDynField;
286 f: Integer;
287 begin
288 result := -1;
289 if (pan <> nil) then
290 begin
291 fld := headerRec['panel'];
292 if (fld <> nil) then
293 begin
294 for f := 0 to fld.count-1 do if (fld.itemAt[f] = pan) then begin result := f; exit; end;
295 end;
296 end;
297 end;
300 function TDynRecordHelper.panelCount (): Integer; inline;
301 var
302 fld: TDynField;
303 begin
304 fld := headerRec['panel'];
305 if (fld <> nil) then result := fld.count else result := 0;
306 end;
309 function TDynRecordHelper.TextureNum (): Word; inline;
310 var
311 idx: Integer;
312 fld: TDynField;
313 begin
314 fld := getFieldWithType('texture', TDynField.TType.TUShort);
315 idx := fld.recrefIndex;
316 if (idx < 0) then result := Word(TEXTURE_NONE) else result := Word(idx);
317 end;
320 // ////////////////////////////////////////////////////////////////////////// //
321 // trigger
322 function TDynRecordHelper.trigRec (): TDynRecord; inline;
323 var
324 fld: TDynField;
325 begin
326 fld := getFieldWithType('triggerdata', TDynField.TType.TTrigData);
327 if (fld <> nil) then result := fld.recref else result := nil;
328 end;
330 function TDynRecordHelper.trigMonsterId (): Integer; inline;
331 var
332 fld: TDynField;
333 begin
334 result := -1;
335 fld := field['monsterid'];
336 if (fld = nil) then exit;
337 if (fld.baseType <> TDynField.TType.TInt) then exit;
338 if (fld.recref = nil) then exit;
339 result := fld.recrefIndex;
340 end;
342 function TDynRecordHelper.trigPanelRec (): TDynRecord; inline;
343 var
344 fld: TDynField;
345 begin
346 result := nil;
347 fld := field['panelid'];
348 if (fld = nil) then exit;
349 if (fld.baseType <> TDynField.TType.TInt) then exit;
350 result := fld.recref;
351 if (result <> nil) and (result.typeName <> 'panel') then result := nil;
352 end;
354 // panel index in list
355 function TDynRecordHelper.trigPanelId (): Integer; inline;
356 var
357 fld: TDynField;
358 begin
359 result := -1;
360 fld := field['panelid'];
361 if (fld = nil) then exit;
362 if (fld.baseType <> TDynField.TType.TInt) then exit;
363 if (fld.recref = nil) then exit;
364 if (fld.recref.typeName <> 'panel') then exit;
365 result := fld.recrefIndex;
366 end;
368 function TDynRecordHelper.getTexturePanelRec (): TDynRecord;
369 var
370 fld: TDynField;
371 begin
372 result := nil;
373 fld := field['texture_panel'];
374 if (fld = nil) then exit;
375 if (fld.baseType <> TDynField.TType.TInt) then exit;
376 result := fld.recref;
377 if (result <> nil) and (result.typeName <> 'panel') then result := nil;
378 end;
380 function TDynRecordHelper.getTexturePanel (): Integer;
381 var
382 fld: TDynField;
383 begin
384 result := -1;
385 fld := field['texture_panel'];
386 if (fld = nil) then exit;
387 if (fld.baseType <> TDynField.TType.TInt) then exit;
388 if (fld.recref = nil) then exit;
389 if (fld.recref.typeName <> 'panel') then exit;
390 result := fld.recrefIndex;
391 end;
394 // ////////////////////////////////////////////////////////////////////////// //
395 function TDynRecordHelper.mapName (): AnsiString; inline; begin result := utf2win(getFieldWithType('name', TDynField.TType.TChar).sval); end;
396 function TDynRecordHelper.mapAuthor (): AnsiString; inline; begin result := utf2win(getFieldWithType('author', TDynField.TType.TChar).sval); end;
397 function TDynRecordHelper.mapDesc (): AnsiString; inline; begin result := utf2win(getFieldWithType('description', TDynField.TType.TChar).sval); end;
398 function TDynRecordHelper.musicName (): AnsiString; inline; begin result := utf2win(getFieldWithType('music', TDynField.TType.TChar).sval); end;
399 function TDynRecordHelper.skyName (): AnsiString; inline; begin result := utf2win(getFieldWithType('sky', TDynField.TType.TChar).sval); end;
400 function TDynRecordHelper.X (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival; end;
401 function TDynRecordHelper.Y (): Integer; inline; begin result := getFieldWithType('position', TDynField.TType.TPoint).ival2; end;
402 function TDynRecordHelper.Width (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival); end;
403 function TDynRecordHelper.Height (): Word; inline; begin result := Word(getFieldWithType('size', TDynField.TType.TSize).ival2); end;
404 function TDynRecordHelper.PanelType (): Word; inline; begin result := Word(getFieldWithType('type', TDynField.TType.TUShort).ival); end;
405 function TDynRecordHelper.TextureRec (): TDynRecord; inline; begin result := getFieldWithType('texture', TDynField.TType.TUShort).recref; end;
406 function TDynRecordHelper.Alpha (): Byte; inline; begin result := Byte(getFieldWithType('alpha', TDynField.TType.TUByte).ival); end;
407 function TDynRecordHelper.Flags (): Byte; inline; begin result := Byte(getFieldWithType('flags', TDynField.TType.TUByte).ival); end;
408 function TDynRecordHelper.Resource (): AnsiString; inline; begin result := utf2win(getFieldWithType('path', TDynField.TType.TChar).sval); end;
409 function TDynRecordHelper.Anim (): Boolean; inline; begin result := (getFieldWithType('animated', TDynField.TType.TBool).ival <> 0); end;
410 function TDynRecordHelper.ItemType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
411 function TDynRecordHelper.Options (): Byte; inline; begin result := Byte(getFieldWithType('options', TDynField.TType.TUByte).ival); end;
412 function TDynRecordHelper.MonsterType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
413 function TDynRecordHelper.Direction (): Byte; inline; begin result := Byte(getFieldWithType('direction', TDynField.TType.TUByte).ival); end;
414 function TDynRecordHelper.AreaType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
415 function TDynRecordHelper.Enabled (): Boolean; inline; begin result := (getFieldWithType('enabled', TDynField.TType.TBool).ival <> 0); end;
416 function TDynRecordHelper.TriggerType (): Byte; inline; begin result := Byte(getFieldWithType('type', TDynField.TType.TUByte).ival); end;
417 function TDynRecordHelper.ActivateType (): Byte; inline; begin result := Byte(getFieldWithType('activate_type', TDynField.TType.TUByte).ival); end;
418 function TDynRecordHelper.Keys (): Byte; inline; begin result := Byte(getFieldWithType('keys', TDynField.TType.TUByte).ival); end;
420 {$INCLUDE mapdef_impl.inc}
423 end.