1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef GAME_MAPITEMS_H
4#define GAME_MAPITEMS_H
5
6#include <base/color.h>
7#include <base/vmath.h>
8
9// layer types
10enum
11{
12 LAYERTYPE_INVALID = 0,
13 LAYERTYPE_GAME, // unused
14 LAYERTYPE_TILES,
15 LAYERTYPE_QUADS,
16 LAYERTYPE_FRONT,
17 LAYERTYPE_TELE,
18 LAYERTYPE_SPEEDUP,
19 LAYERTYPE_SWITCH,
20 LAYERTYPE_TUNE,
21 LAYERTYPE_SOUNDS_DEPRECATED, // deprecated! do not use this, this is just for compatibility reasons
22 LAYERTYPE_SOUNDS,
23};
24
25enum
26{
27 MAPITEMTYPE_VERSION = 0,
28 MAPITEMTYPE_INFO,
29 MAPITEMTYPE_IMAGE,
30 MAPITEMTYPE_ENVELOPE,
31 MAPITEMTYPE_GROUP,
32 MAPITEMTYPE_LAYER,
33 MAPITEMTYPE_ENVPOINTS,
34 MAPITEMTYPE_SOUND,
35 // High map item type numbers suggest that they use the alternate
36 // format with UUIDs. See src/engine/shared/datafile.cpp for some of
37 // the implementation.
38};
39
40enum
41{
42 CURVETYPE_STEP = 0,
43 CURVETYPE_LINEAR,
44 CURVETYPE_SLOW,
45 CURVETYPE_FAST,
46 CURVETYPE_SMOOTH,
47 CURVETYPE_BEZIER,
48 NUM_CURVETYPES,
49};
50
51enum
52{
53 // game layer tiles
54 // TODO define which Layer uses which tiles (needed for mapeditor)
55 ENTITY_NULL = 0,
56 ENTITY_SPAWN = 1,
57 ENTITY_SPAWN_RED = 2,
58 ENTITY_SPAWN_BLUE = 3,
59 ENTITY_FLAGSTAND_RED = 4,
60 ENTITY_FLAGSTAND_BLUE = 5,
61 ENTITY_ARMOR_1 = 6,
62 ENTITY_HEALTH_1 = 7,
63 ENTITY_WEAPON_SHOTGUN = 8,
64 ENTITY_WEAPON_GRENADE = 9,
65 ENTITY_POWERUP_NINJA = 10,
66 ENTITY_WEAPON_LASER = 11,
67
68 // DDRace - Main Lasers
69 ENTITY_LASER_FAST_CCW = 12,
70 ENTITY_LASER_NORMAL_CCW = 13,
71 ENTITY_LASER_SLOW_CCW = 14,
72 ENTITY_LASER_STOP = 15,
73 ENTITY_LASER_SLOW_CW = 16,
74 ENTITY_LASER_NORMAL_CW = 17,
75 ENTITY_LASER_FAST_CW = 18,
76
77 // DDRace - Laser Modifiers
78 ENTITY_LASER_SHORT = 19,
79 ENTITY_LASER_MEDIUM = 20,
80 ENTITY_LASER_LONG = 21,
81 ENTITY_LASER_C_SLOW = 22,
82 ENTITY_LASER_C_NORMAL = 23,
83 ENTITY_LASER_C_FAST = 24,
84 ENTITY_LASER_O_SLOW = 25,
85 ENTITY_LASER_O_NORMAL = 26,
86 ENTITY_LASER_O_FAST = 27,
87
88 // DDRace - Plasma
89 ENTITY_PLASMAE = 29,
90 ENTITY_PLASMAF = 30,
91 ENTITY_PLASMA = 31,
92 ENTITY_PLASMAU = 32,
93
94 // DDRace - Shotgun
95 ENTITY_CRAZY_SHOTGUN_EX = 33,
96 ENTITY_CRAZY_SHOTGUN = 34,
97
98 // DDNet - Removing specific weapon
99 ENTITY_ARMOR_SHOTGUN = 35,
100 ENTITY_ARMOR_GRENADE = 36,
101 ENTITY_ARMOR_NINJA = 37,
102 ENTITY_ARMOR_LASER = 38,
103
104 // DDRace - Draggers
105 ENTITY_DRAGGER_WEAK = 42,
106 ENTITY_DRAGGER_NORMAL = 43,
107 ENTITY_DRAGGER_STRONG = 44,
108 // Draggers Behind Walls
109 ENTITY_DRAGGER_WEAK_NW = 45,
110 ENTITY_DRAGGER_NORMAL_NW = 46,
111 ENTITY_DRAGGER_STRONG_NW = 47,
112
113 // Doors
114 ENTITY_DOOR = 49,
115 // End Of Lower Tiles
116
117 ENTITY_OFFSET = 255 - 16 * 4,
118};
119
120enum
121{
122 // Start From Top Left
123 // Tile Controllers
124 TILE_AIR = 0,
125 TILE_SOLID = 1,
126 TILE_DEATH = 2,
127 TILE_NOHOOK = 3,
128 TILE_NOLASER = 4,
129 TILE_THROUGH_CUT = 5,
130 TILE_THROUGH = 6,
131 TILE_JUMP = 7,
132 TILE_FREEZE = 9,
133 TILE_TELEINEVIL = 10,
134 TILE_UNFREEZE = 11,
135 TILE_DFREEZE = 12,
136 TILE_DUNFREEZE = 13,
137 TILE_TELEINWEAPON = 14,
138 TILE_TELEINHOOK = 15,
139 TILE_WALLJUMP = 16,
140 TILE_EHOOK_ENABLE = 17,
141 TILE_EHOOK_DISABLE = 18,
142 TILE_HIT_ENABLE = 19,
143 TILE_HIT_DISABLE = 20,
144 TILE_SOLO_ENABLE = 21,
145 TILE_SOLO_DISABLE = 22,
146 // Switches
147 TILE_SWITCHTIMEDOPEN = 22,
148 TILE_SWITCHTIMEDCLOSE = 23,
149 TILE_SWITCHOPEN = 24,
150 TILE_SWITCHCLOSE = 25,
151 TILE_TELEIN = 26,
152 TILE_TELEOUT = 27,
153 TILE_SPEED_BOOST_OLD = 28,
154 TILE_SPEED_BOOST = 29,
155 TILE_TELECHECK = 29,
156 TILE_TELECHECKOUT = 30,
157 TILE_TELECHECKIN = 31,
158 TILE_REFILL_JUMPS = 32,
159 TILE_START = 33,
160 TILE_FINISH = 34,
161 TILE_TIME_CHECKPOINT_FIRST = 35,
162 TILE_TIME_CHECKPOINT_LAST = 59,
163 TILE_STOP = 60,
164 TILE_STOPS = 61,
165 TILE_STOPA = 62,
166 TILE_TELECHECKINEVIL = 63,
167 TILE_CP = 64,
168 TILE_CP_F = 65,
169 TILE_THROUGH_ALL = 66,
170 TILE_THROUGH_DIR = 67,
171 TILE_TUNE = 68,
172 TILE_OLDLASER = 71,
173 TILE_NPC = 72,
174 TILE_EHOOK = 73,
175 TILE_NOHIT = 74,
176 TILE_NPH = 75,
177 TILE_UNLOCK_TEAM = 76,
178 TILE_ADD_TIME = 79,
179 TILE_NPC_DISABLE = 88,
180 TILE_UNLIMITED_JUMPS_DISABLE = 89,
181 TILE_JETPACK_DISABLE = 90,
182 TILE_NPH_DISABLE = 91,
183 TILE_SUBTRACT_TIME = 95,
184 TILE_TELE_GUN_ENABLE = 96,
185 TILE_TELE_GUN_DISABLE = 97,
186 TILE_ALLOW_TELE_GUN = 98,
187 TILE_ALLOW_BLUE_TELE_GUN = 99,
188 TILE_NPC_ENABLE = 104,
189 TILE_UNLIMITED_JUMPS_ENABLE = 105,
190 TILE_JETPACK_ENABLE = 106,
191 TILE_NPH_ENABLE = 107,
192 TILE_TELE_GRENADE_ENABLE = 112,
193 TILE_TELE_GRENADE_DISABLE = 113,
194 TILE_TELE_LASER_ENABLE = 128,
195 TILE_TELE_LASER_DISABLE = 129,
196 TILE_CREDITS_1 = 140,
197 TILE_CREDITS_2 = 141,
198 TILE_CREDITS_3 = 142,
199 TILE_CREDITS_4 = 143,
200 TILE_LFREEZE = 144,
201 TILE_LUNFREEZE = 145,
202 TILE_CREDITS_5 = 156,
203 TILE_CREDITS_6 = 157,
204 TILE_CREDITS_7 = 158,
205 TILE_CREDITS_8 = 159,
206 TILE_ENTITIES_OFF_1 = 190,
207 TILE_ENTITIES_OFF_2 = 191,
208 // End of higher tiles
209};
210
211enum
212{
213 // Layers
214 LAYER_GAME = 0,
215 LAYER_FRONT,
216 LAYER_TELE,
217 LAYER_SPEEDUP,
218 LAYER_SWITCH,
219 LAYER_TUNE,
220 NUM_LAYERS,
221};
222
223enum
224{
225 // Flags
226 TILEFLAG_XFLIP = 1 << 0,
227 TILEFLAG_YFLIP = 1 << 1,
228 TILEFLAG_OPAQUE = 1 << 2,
229 TILEFLAG_ROTATE = 1 << 3,
230};
231
232enum
233{
234 // Rotation
235 ROTATION_0 = 0,
236 ROTATION_90 = TILEFLAG_ROTATE,
237 ROTATION_180 = (TILEFLAG_XFLIP | TILEFLAG_YFLIP),
238 ROTATION_270 = (TILEFLAG_XFLIP | TILEFLAG_YFLIP | TILEFLAG_ROTATE),
239};
240
241enum
242{
243 LAYERFLAG_DETAIL = 1,
244 TILESLAYERFLAG_GAME = 1 << 0,
245 TILESLAYERFLAG_TELE = 1 << 1,
246 TILESLAYERFLAG_SPEEDUP = 1 << 2,
247 TILESLAYERFLAG_FRONT = 1 << 3,
248 TILESLAYERFLAG_SWITCH = 1 << 4,
249 TILESLAYERFLAG_TUNE = 1 << 5,
250};
251
252static constexpr size_t MAX_MAPIMAGES = 64;
253static constexpr size_t MAX_MAPSOUNDS = 64;
254
255typedef ivec2 CPoint; // 22.10 fixed point
256typedef ivec4 CColor;
257
258class CFixedTime
259{
260 int m_FixedPoint;
261
262public:
263 constexpr CFixedTime() :
264 m_FixedPoint(0) {}
265 constexpr explicit CFixedTime(int FixedPoint) :
266 m_FixedPoint(FixedPoint) {}
267
268 constexpr int GetInternal() const
269 {
270 return m_FixedPoint;
271 }
272
273 constexpr float AsSeconds() const
274 {
275 return m_FixedPoint / 1000.0f;
276 }
277
278 constexpr static CFixedTime FromSeconds(float Seconds)
279 {
280 return CFixedTime((int)std::round(x: Seconds * 1000.0f));
281 }
282
283 constexpr bool operator<(const CFixedTime &Other) const
284 {
285 return m_FixedPoint < Other.m_FixedPoint;
286 }
287
288 constexpr bool operator<=(const CFixedTime &Other) const
289 {
290 return m_FixedPoint <= Other.m_FixedPoint;
291 }
292
293 constexpr bool operator>(const CFixedTime &Other) const
294 {
295 return m_FixedPoint > Other.m_FixedPoint;
296 }
297
298 constexpr bool operator>=(const CFixedTime &Other) const
299 {
300 return m_FixedPoint >= Other.m_FixedPoint;
301 }
302
303 constexpr bool operator==(const CFixedTime &Other) const
304 {
305 return m_FixedPoint == Other.m_FixedPoint;
306 }
307
308 constexpr bool operator!=(const CFixedTime &Other) const
309 {
310 return m_FixedPoint != Other.m_FixedPoint;
311 }
312
313 constexpr CFixedTime operator+(const CFixedTime &Other) const
314 {
315 return CFixedTime(m_FixedPoint + Other.m_FixedPoint);
316 }
317
318 constexpr CFixedTime operator-(const CFixedTime &Other) const
319 {
320 return CFixedTime(m_FixedPoint - Other.m_FixedPoint);
321 }
322
323 constexpr CFixedTime &operator+=(const CFixedTime &Other)
324 {
325 m_FixedPoint += Other.m_FixedPoint;
326 return *this;
327 }
328
329 constexpr CFixedTime &operator-=(const CFixedTime &Other)
330 {
331 m_FixedPoint -= Other.m_FixedPoint;
332 return *this;
333 }
334};
335
336class CQuad
337{
338public:
339 CPoint m_aPoints[5];
340 CColor m_aColors[4];
341 CPoint m_aTexcoords[4];
342
343 int m_PosEnv;
344 int m_PosEnvOffset;
345
346 int m_ColorEnv;
347 int m_ColorEnvOffset;
348};
349
350class CTile
351{
352public:
353 unsigned char m_Index;
354 unsigned char m_Flags;
355 unsigned char m_Skip;
356 unsigned char m_Reserved;
357};
358
359class CMapItemInfo
360{
361public:
362 int m_Version;
363 int m_Author;
364 int m_MapVersion;
365 int m_Credits;
366 int m_License;
367};
368
369class CMapItemInfoSettings : public CMapItemInfo
370{
371public:
372 int m_Settings;
373};
374
375class CMapItemImage_v1
376{
377public:
378 int m_Version;
379 int m_Width;
380 int m_Height;
381 int m_External;
382 int m_ImageName;
383 int m_ImageData;
384};
385
386class CMapItemImage_v2 : public CMapItemImage_v1
387{
388public:
389 int m_MustBe1;
390};
391
392typedef CMapItemImage_v1 CMapItemImage;
393
394class CMapItemGroup_v1
395{
396public:
397 int m_Version;
398 int m_OffsetX;
399 int m_OffsetY;
400 int m_ParallaxX;
401 int m_ParallaxY;
402
403 int m_StartLayer;
404 int m_NumLayers;
405};
406
407class CMapItemGroup : public CMapItemGroup_v1
408{
409public:
410 int m_UseClipping;
411 int m_ClipX;
412 int m_ClipY;
413 int m_ClipW;
414 int m_ClipH;
415
416 int m_aName[3];
417};
418
419class CMapItemLayer
420{
421public:
422 int m_Version;
423 int m_Type;
424 int m_Flags;
425};
426
427class CMapItemLayerTilemap
428{
429public:
430 /**
431 * @link CMapItemLayerTilemap @endlink with this version are only written to maps in upstream Teeworlds.
432 * The tile data of tilemaps using this version must be unpacked by repeating tiles according to the
433 * @link CTile::m_Skip @endlink values of the packed tile data.
434 *
435 * @see CMap::ExtractTiles
436 */
437 static constexpr int VERSION_TEEWORLDS_TILESKIP = 4;
438
439 CMapItemLayer m_Layer;
440 int m_Version;
441
442 int m_Width;
443 int m_Height;
444 int m_Flags;
445
446 CColor m_Color;
447 int m_ColorEnv;
448 int m_ColorEnvOffset;
449
450 int m_Image;
451 int m_Data;
452
453 int m_aName[3];
454
455 // DDRace
456
457 int m_Tele;
458 int m_Speedup;
459 int m_Front;
460 int m_Switch;
461 int m_Tune;
462};
463
464class CMapItemLayerQuads
465{
466public:
467 CMapItemLayer m_Layer;
468 int m_Version;
469
470 int m_NumQuads;
471 int m_Data;
472 int m_Image;
473
474 int m_aName[3];
475};
476
477class CMapItemVersion
478{
479public:
480 int m_Version;
481};
482
483// Represents basic information about envelope points.
484// In upstream Teeworlds, this is only used if all CMapItemEnvelope are version 1 or 2.
485class CEnvPoint
486{
487public:
488 enum
489 {
490 MAX_CHANNELS = 4,
491 };
492
493 CFixedTime m_Time;
494 int m_Curvetype; // CURVETYPE_* constants, any unknown value behaves like CURVETYPE_LINEAR
495 int m_aValues[MAX_CHANNELS]; // 1-4 depending on envelope (22.10 fixed point)
496
497 bool operator<(const CEnvPoint &Other) const { return m_Time < Other.m_Time; }
498
499 ColorRGBA ColorValue() const;
500 void SetColorValue(const ColorRGBA &Color);
501};
502
503// Represents additional envelope point information for CURVETYPE_BEZIER.
504// In DDNet, these are stored separately in an UUID-based map item.
505// In upstream Teeworlds, CEnvPointBezier_upstream is used instead.
506class CEnvPointBezier
507{
508public:
509 CFixedTime m_aInTangentDeltaX[CEnvPoint::MAX_CHANNELS];
510 int m_aInTangentDeltaY[CEnvPoint::MAX_CHANNELS]; // 22.10 fxp
511 CFixedTime m_aOutTangentDeltaX[CEnvPoint::MAX_CHANNELS];
512 int m_aOutTangentDeltaY[CEnvPoint::MAX_CHANNELS]; // 22.10 fxp
513};
514
515// Written to maps on upstream Teeworlds for envelope points including bezier information instead of the basic
516// CEnvPoint items, if at least one CMapItemEnvelope with version 3 or higher exists in the map.
517class CEnvPointBezier_upstream : public CEnvPoint
518{
519public:
520 CEnvPointBezier m_Bezier;
521};
522
523// Used to represent all envelope point information at runtime in editor.
524// (Can eventually be different than CEnvPointBezier_upstream)
525class CEnvPoint_runtime : public CEnvPoint
526{
527public:
528 CEnvPointBezier m_Bezier;
529};
530
531class CMapItemEnvelope_v1
532{
533public:
534 /**
535 * @link CMapItemEnvelope @endlink with this version are only written to maps in upstream Teeworlds.
536 * If at least one of these exists in a map, then the envelope points are represented
537 * by @link CEnvPointBezier_upstream @endlink instead of @link CEnvPoint @endlink.
538 */
539 static constexpr int VERSION_TEEWORLDS_BEZIER = 3;
540
541 int m_Version;
542 int m_Channels;
543 int m_StartPoint;
544 int m_NumPoints;
545 int m_aName[8];
546};
547
548class CMapItemEnvelope_v2 : public CMapItemEnvelope_v1
549{
550public:
551 int m_Synchronized;
552};
553
554typedef CMapItemEnvelope_v2 CMapItemEnvelope;
555
556class CSoundShape
557{
558public:
559 enum
560 {
561 SHAPE_RECTANGLE = 0,
562 SHAPE_CIRCLE,
563 NUM_SHAPES,
564 };
565
566 class CRectangle
567 {
568 public:
569 int m_Width, m_Height; // fxp 22.10
570 };
571
572 class CCircle
573 {
574 public:
575 int m_Radius;
576 };
577
578 int m_Type;
579
580 union
581 {
582 CRectangle m_Rectangle;
583 CCircle m_Circle;
584 };
585};
586
587class CSoundSource
588{
589public:
590 CPoint m_Position;
591 int m_Loop;
592 int m_Pan; // 0 - no panning, 1 - panning
593 int m_TimeDelay; // in s
594 int m_Falloff; // [0,255] // 0 - No falloff, 255 - full
595
596 int m_PosEnv;
597 int m_PosEnvOffset;
598 int m_SoundEnv;
599 int m_SoundEnvOffset;
600
601 CSoundShape m_Shape;
602};
603
604class CMapItemLayerSounds
605{
606public:
607 CMapItemLayer m_Layer;
608 int m_Version;
609
610 int m_NumSources;
611 int m_Data;
612 int m_Sound;
613
614 int m_aName[3];
615};
616
617class CMapItemSound
618{
619public:
620 int m_Version;
621
622 int m_External;
623
624 int m_SoundName;
625 int m_SoundData;
626 // Deprecated. Do not read this value, it could be wrong.
627 // Use GetDataSize instead, which returns the de facto size.
628 // Value must still be written for compatibility.
629 int m_SoundDataSize;
630};
631
632// DDRace
633
634class CTeleTile
635{
636public:
637 unsigned char m_Number;
638 unsigned char m_Type;
639};
640
641class CSpeedupTile
642{
643public:
644 unsigned char m_Force;
645 unsigned char m_MaxSpeed;
646 unsigned char m_Type;
647 short m_Angle;
648};
649
650class CSwitchTile
651{
652public:
653 unsigned char m_Number;
654 unsigned char m_Type;
655 unsigned char m_Flags;
656 unsigned char m_Delay;
657};
658
659class CDoorTile
660{
661public:
662 unsigned char m_Index;
663 unsigned char m_Flags;
664 int m_Number;
665};
666
667class CTuneTile
668{
669public:
670 unsigned char m_Number;
671 unsigned char m_Type;
672};
673
674bool IsValidGameTile(int Index);
675bool IsValidFrontTile(int Index);
676bool IsValidTeleTile(int Index);
677bool IsTeleTileCheckpoint(int Index); // Assumes that Index is a valid tele tile index
678bool IsTeleTileNumberUsed(int Index, bool Checkpoint); // Assumes that Index is a valid tele tile index
679bool IsTeleTileNumberUsedAny(int Index); // Does not check for checkpoint only
680bool IsValidSpeedupTile(int Index);
681bool IsValidSwitchTile(int Index);
682bool IsSwitchTileFlagsUsed(int Index); // Assumes that Index is a valid switch tile index
683bool IsSwitchTileNumberUsed(int Index); // Assumes that Index is a valid switch tile index
684bool IsSwitchTileDelayUsed(int Index); // Assumes that Index is a valid switch tile index
685bool IsValidTuneTile(int Index);
686bool IsValidEntity(int Index);
687bool IsRotatableTile(int Index);
688bool IsCreditsTile(int TileIndex);
689
690int PackColor(const CColor &Color);
691CColor UnpackColor(int PackedColor);
692
693#endif
694