1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name unittype.h - The unit-types headerfile. */
12 //
13 //      (c) Copyright 1998-2015 by Lutz Sammer, Jimmy Salmon and Andrettin
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 #ifndef __UNITTYPE_H__
31 #define __UNITTYPE_H__
32 
33 //@{
34 
35 /*----------------------------------------------------------------------------
36 --  Includes
37 ----------------------------------------------------------------------------*/
38 
39 #ifndef __UPGRADE_STRUCTS_H__
40 #include "upgrade_structs.h"
41 #endif
42 
43 #ifndef __UNITSOUND_H__
44 #include "unitsound.h"
45 #endif
46 
47 #ifndef __ICONS_H__
48 #include "icons.h"
49 #endif
50 
51 #include "color.h"
52 #include "missileconfig.h"
53 #include "vec2i.h"
54 
55 #include <climits>
56 #include <vector>
57 #include <algorithm>
58 #include <map>
59 
60 /*----------------------------------------------------------------------------
61 --  Declarations
62 ----------------------------------------------------------------------------*/
63 
64 class CAnimations;
65 class CPlayerColorGraphic;
66 class CConstruction;
67 class MissileType;
68 class CFile;
69 struct lua_State;
70 #ifdef USE_MNG
71 class Mng;
72 #endif
73 class LuaCallback;
74 
75 #define UnitSides 8
76 #define MaxAttackPos 5
77 
78 CUnitType *UnitTypeByIdent(const std::string &ident);
79 
80 enum GroupSelectionMode {
81 	SELECTABLE_BY_RECTANGLE_ONLY = 0,
82 	NON_SELECTABLE_BY_RECTANGLE_ONLY,
83 	SELECT_ALL
84 };
85 
86 class ResourceInfo
87 {
88 public:
ResourceInfo()89 	ResourceInfo() : WaitAtResource(0), ResourceStep(0),
90 		ResourceCapacity(0), WaitAtDepot(0), ResourceId(0), FinalResource(0),
91 		TerrainHarvester(0), LoseResources(0), HarvestFromOutside(0),
92 		SpriteWhenLoaded(NULL), SpriteWhenEmpty(NULL)
93 	{}
94 
95 	std::string FileWhenLoaded;     /// Change the graphic when the unit is loaded.
96 	std::string FileWhenEmpty;      /// Change the graphic when the unit is empty.
97 	unsigned WaitAtResource;        /// Cycles the unit waits while mining.
98 	unsigned ResourceStep;          /// Resources the unit gains per mining cycle.
99 	int      ResourceCapacity;      /// Max amount of resources to carry.
100 	unsigned WaitAtDepot;           /// Cycles the unit waits while returning.
101 	unsigned ResourceId;            /// Id of the resource harvested. Redundant.
102 	unsigned FinalResource;         /// Convert resource when delivered.
103 	unsigned char TerrainHarvester;    /// Unit will harvest terrain(wood only for now).
104 	unsigned char LoseResources;       /// The unit will lose it's resource when distracted.
105 	unsigned char HarvestFromOutside;  /// Unit harvests without entering the building.
106 	unsigned char RefineryHarvester;   /// Unit have to build Refinery buildings for harvesting.
107 	//  Runtime info:
108 	CPlayerColorGraphic *SpriteWhenLoaded; /// The graphic corresponding to FileWhenLoaded.
109 	CPlayerColorGraphic *SpriteWhenEmpty;  /// The graphic corresponding to FileWhenEmpty
110 };
111 
112 /**
113 **  User defined variable type.
114 **
115 **  It is used to define variables and use it after
116 **  to manage magic, energy, shield or other stuff.
117 */
118 class CVariable
119 {
120 public:
CVariable()121 	CVariable() : Max(0), Value(0), Increase(0), IncreaseFrequency(0), Enable(0) {}
122 
123 	bool operator ==(const CVariable &rhs) const
124 	{
125 		return this->Max == rhs.Max
126 			   && this->Value == rhs.Value
127 			   && this->Increase == rhs.Increase
128 			   && this->IncreaseFrequency == rhs.IncreaseFrequency
129 			   && this->Enable == rhs.Enable;
130 	}
131 	bool operator !=(const CVariable &rhs) const { return !(*this == rhs); }
132 
133 public:
134 	int Max;        /// Maximum for the variable. (Assume min is 0.)
135 	int Value;      /// Current (or initial) value of the variable (or initial value).
136 	char Increase;  /// Number to increase(decrease) Value by second.
137 	unsigned char IncreaseFrequency:7;    /// Every how many seconds we should apply the increase
138 	unsigned char Enable:1;    /// True if the unit doesn't have this variable. (f.e shield)
139 };
140 
141 // Index for boolflag already defined
142 enum {
143 	COWARD_INDEX = 0,				/// Unit will only attack if instructed.
144 	BUILDING_INDEX,
145 	FLIP_INDEX,
146 	REVEALER_INDEX,					/// reveal the fog of war
147 	LANDUNIT_INDEX,
148 	AIRUNIT_INDEX,
149 	SEAUNIT_INDEX,
150 	EXPLODEWHENKILLED_INDEX,
151 	VISIBLEUNDERFOG_INDEX,			/// Unit is visible under fog of war.
152 	PERMANENTCLOAK_INDEX,			/// Is only visible by CloakDetectors.
153 	DETECTCLOAK_INDEX,				/// Can see Cloaked units.
154 	ATTACKFROMTRANSPORTER_INDEX,	/// Can attack from transporter
155 	VANISHES_INDEX,					/// Corpses & destroyed places.
156 	GROUNDATTACK_INDEX,				/// Can do ground attack command.
157 	SHOREBUILDING_INDEX,			/// Building must be built on coast.
158 	CANATTACK_INDEX,
159 	BUILDEROUTSIDE_INDEX,			/// The builder stays outside during the construction.
160 	BUILDERLOST_INDEX,				/// The builder is lost after the construction.
161 	CANHARVEST_INDEX,				/// Resource can be harvested.
162 	HARVESTER_INDEX,				/// Unit is a resource harvester.
163 	SELECTABLEBYRECTANGLE_INDEX,	/// Selectable with mouse rectangle.
164 	ISNOTSELECTABLE_INDEX,
165 	DECORATION_INDEX,				/// Unit is a decoration (act as tile).
166 	INDESTRUCTIBLE_INDEX,			/// Unit is indestructible (take no damage).
167 	TELEPORTER_INDEX,				/// Can teleport other units.
168 	SHIELDPIERCE_INDEX,
169 	SAVECARGO_INDEX,				/// Unit unloads his passengers after death.
170 	NONSOLID_INDEX,					/// Unit can be entered by other units.
171 	WALL_INDEX,						/// Use special logic for Direction field.
172 	NORANDOMPLACING_INDEX,			/// Don't use random frame rotation
173 	ORGANIC_INDEX,					/// Organic unit (used for death coil spell)
174 	SIDEATTACK_INDEX,
175 	SKIRMISHER_INDEX,
176 	ALWAYSTHREAT_INDEX,				/// Unit always considered as threat for auto targeting algorihm, useful for unit without main attack ability, but which can cast spells (f.e. defiler in SC:BW)
177 	ELEVATED_INDEX,					/// Unit is elevated and can see over opaque tiles placed in the same ground level with the unit.
178 	NOFRIENDLYFIRE_INDEX,           /// Unit accepts friendly fire for splash attacks
179 	MAINFACILITY_INDEX,				/// Unit is a main building (Town Hall f. ex.)
180 	NBARALREADYDEFINED
181 };
182 
183 // Index for variable already defined.
184 enum {
185 	HP_INDEX = 0,
186 	BUILD_INDEX,
187 	MANA_INDEX,
188 	TRANSPORT_INDEX,
189 	RESEARCH_INDEX,
190 	TRAINING_INDEX,
191 	UPGRADINGTO_INDEX,
192 	GIVERESOURCE_INDEX,
193 	CARRYRESOURCE_INDEX,
194 	XP_INDEX,
195 	KILL_INDEX,
196 	SUPPLY_INDEX,					/// Food supply
197 	DEMAND_INDEX,					/// Food demand
198 	ARMOR_INDEX,
199 	SIGHTRANGE_INDEX,
200 	ATTACKRANGE_INDEX,
201 	PIERCINGDAMAGE_INDEX,
202 	BASICDAMAGE_INDEX,
203 	POSX_INDEX,
204 	POSY_INDEX,
205 	TARGETPOSX_INDEX,
206 	TARGETPOSY_INDEX,
207 	RADAR_INDEX,
208 	RADARJAMMER_INDEX,
209 	AUTOREPAIRRANGE_INDEX,
210 	BLOODLUST_INDEX,
211 	HASTE_INDEX,
212 	SLOW_INDEX,
213 	INVISIBLE_INDEX,
214 	UNHOLYARMOR_INDEX,
215 	SLOT_INDEX,
216 	SHIELD_INDEX,
217 	POINTS_INDEX,
218 	MAXHARVESTERS_INDEX,
219 	POISON_INDEX,
220 	SHIELDPERMEABILITY_INDEX,
221 	SHIELDPIERCING_INDEX,
222 	ISALIVE_INDEX,
223 	PLAYER_INDEX,
224 	PRIORITY_INDEX,
225 	NVARALREADYDEFINED
226 };
227 
228 class CUnit;
229 class CUnitType;
230 class CFont;
231 
232 /**
233 **  Decoration for user defined variable.
234 **
235 **  It is used to show variables graphicly.
236 **  @todo add more stuff in this struct.
237 */
238 class CDecoVar
239 {
240 public:
241 
CDecoVar()242 	CDecoVar() {};
~CDecoVar()243 	virtual ~CDecoVar()
244 	{
245 	};
246 
247 	/// function to draw the decorations.
248 	virtual void Draw(int x, int y, const CUnitType &type, const CVariable &var) const = 0;
249 
250 	unsigned int Index;     /// Index of the variable. @see DefineVariables
251 
252 	int OffsetX;            /// Offset in X coord.
253 	int OffsetY;            /// Offset in Y coord.
254 
255 	int OffsetXPercent;     /// Percent offset (TileWidth) in X coord.
256 	int OffsetYPercent;     /// Percent offset (TileHeight) in Y coord.
257 
258 	bool IsCenteredInX;     /// if true, use center of deco instead of left border
259 	bool IsCenteredInY;     /// if true, use center of deco instead of upper border
260 
261 	bool ShowIfNotEnable;   /// if false, Show only if var is enable
262 	bool ShowWhenNull;      /// if false, don't show if var is null (F.E poison)
263 	bool HideHalf;          /// if true, don't show when 0 < var < max.
264 	bool ShowWhenMax;       /// if false, don't show if var is to max. (Like mana)
265 	bool ShowOnlySelected;  /// if true, show only for selected units.
266 
267 	bool HideNeutral;       /// if true, don't show for neutral unit.
268 	bool HideAllied;        /// if true, don't show for allied unit. (but show own units)
269 	bool ShowOpponent;      /// if true, show for opponent unit.
270 };
271 
272 class CDecoVarBar : public CDecoVar
273 {
274 public:
275 	/// function to draw the decorations.
276 	virtual void Draw(int x, int y, const CUnitType &type, const CVariable &var) const;
277 
278 	bool IsVertical;            /// if true, vertical bar, else horizontal.
279 	bool SEToNW;                /// (SouthEastToNorthWest), if false value 0 is on the left or up of the bar.
280 	int Height;                 /// Height of the bar.
281 	int Width;                  /// Width of the bar.
282 	bool ShowFullBackground;    /// if true, show background like value equal to max.
283 	char BorderSize;            /// Size of the border, 0 for no border.
284 	// FIXME color depend of percent (red, Orange, Yellow, Green...)
285 	IntColor Color;             /// Color of bar.
286 	IntColor BColor;            /// Color of background.
287 };
288 
289 class CDecoVarFrame : public CDecoVar
290 {
291 public:
CDecoVarFrame()292 	CDecoVarFrame() : Thickness(0), ColorIndex(-1) {};
293 	virtual void Draw(int x, int y, const CUnitType &type, const CVariable &var) const;
294 
295 	int Thickness;
296 	int ColorIndex;
297 };
298 
299 class CDecoVarText : public CDecoVar
300 {
301 public:
CDecoVarText()302 	CDecoVarText() : Font(NULL) {};
303 	/// function to draw the decorations.
304 	virtual void Draw(int x, int y, const CUnitType &type, const CVariable &var) const;
305 
306 	CFont *Font;  /// Font to use to display value.
307 	// FIXME : Add Color, format
308 };
309 
310 /// Sprite contains frame from full (left)to empty state (right).
311 class CDecoVarSpriteBar : public CDecoVar
312 {
313 public:
CDecoVarSpriteBar()314 	CDecoVarSpriteBar() : NSprite(-1) {};
315 	/// function to draw the decorations.
316 	virtual void Draw(int x, int y,
317 					  const CUnitType &type, const CVariable &var) const;
318 
319 	char NSprite; /// Index of number. (@see DefineSprites and @see GetSpriteIndex)
320 	// FIXME Sprite info. better way ?
321 };
322 
323 /// use to show specific frame in a sprite.
324 class CDecoVarStaticSprite : public CDecoVar
325 {
326 public:
CDecoVarStaticSprite()327 	CDecoVarStaticSprite() : NSprite(-1), n(0), FadeValue(0) {}
328 	/// function to draw the decorations.
329 	virtual void Draw(int x, int y, const CUnitType &type, const CVariable &var) const;
330 
331 	// FIXME Sprite info. and Replace n with more appropriate var.
332 	char NSprite;  /// Index of sprite. (@see DefineSprites and @see GetSpriteIndex)
333 	int n;         /// identifiant in SpellSprite
334 	int FadeValue; /// if variable's value is below than FadeValue, it drawn transparent.
335 };
336 
337 enum UnitTypeType {
338 	UnitTypeLand,  /// Unit lives on land
339 	UnitTypeFly,   /// Unit lives in air
340 	UnitTypeNaval  /// Unit lives on water
341 };
342 
343 enum DistanceTypeType {
344 	Equal,
345 	NotEqual,
346 	LessThan,
347 	LessThanEqual,
348 	GreaterThan,
349 	GreaterThanEqual
350 };
351 
352 class CBuildRestriction
353 {
354 public:
~CBuildRestriction()355 	virtual ~CBuildRestriction() {}
Init()356 	virtual void Init() {};
357 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const = 0;
358 };
359 
360 class CBuildRestrictionAnd : public CBuildRestriction
361 {
362 public:
~CBuildRestrictionAnd()363 	virtual ~CBuildRestrictionAnd()
364 	{
365 		for (std::vector<CBuildRestriction *>::const_iterator i = _or_list.begin();
366 			 i != _or_list.end(); ++i) {
367 			delete *i;
368 		}
369 		_or_list.clear();
370 	}
Init()371 	virtual void Init()
372 	{
373 		for (std::vector<CBuildRestriction *>::const_iterator i = _or_list.begin();
374 			 i != _or_list.end(); ++i) {
375 			(*i)->Init();
376 		}
377 	}
378 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
379 
push_back(CBuildRestriction * restriction)380 	void push_back(CBuildRestriction *restriction) { _or_list.push_back(restriction); }
381 public:
382 	std::vector<CBuildRestriction *> _or_list;
383 };
384 
385 class CBuildRestrictionAddOn : public CBuildRestriction
386 {
387 	class functor
388 	{
389 	public:
functor(const CUnitType * type,const Vec2i & _pos)390 		functor(const CUnitType *type, const Vec2i &_pos): Parent(type), pos(_pos) {}
391 		inline bool operator()(const CUnit *const unit) const;
392 	private:
393 		const CUnitType *const Parent;   /// building that is unit is an addon too.
394 		const Vec2i pos; //functor work position
395 	};
396 public:
CBuildRestrictionAddOn()397 	CBuildRestrictionAddOn() : Offset(0, 0), Parent(NULL) {}
~CBuildRestrictionAddOn()398 	virtual ~CBuildRestrictionAddOn() {}
Init()399 	virtual void Init() {this->Parent = UnitTypeByIdent(this->ParentName);}
400 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
401 
402 	Vec2i Offset;           /// offset from the main building to place this
403 	std::string ParentName; /// building that is unit is an addon too.
404 	CUnitType *Parent;      /// building that is unit is an addon too.
405 };
406 
407 class CBuildRestrictionOnTop : public CBuildRestriction
408 {
409 	class functor
410 	{
411 	public:
functor(const CUnitType * type,const Vec2i & _pos)412 		functor(const CUnitType *type, const Vec2i &_pos): ontop(0), Parent(type), pos(_pos) {}
413 		inline bool operator()(CUnit *const unit);
414 		CUnit *ontop;   /// building that is unit is an addon too.
415 	private:
416 		const CUnitType *const Parent;  /// building that is unit is an addon too.
417 		const Vec2i pos;  //functor work position
418 	};
419 public:
CBuildRestrictionOnTop()420 	CBuildRestrictionOnTop() : Parent(NULL), ReplaceOnDie(0), ReplaceOnBuild(0) {};
~CBuildRestrictionOnTop()421 	virtual ~CBuildRestrictionOnTop() {};
Init()422 	virtual void Init() {this->Parent = UnitTypeByIdent(this->ParentName);};
423 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
424 
425 	std::string ParentName;  /// building that is unit is an addon too.
426 	CUnitType *Parent;       /// building that is unit is an addon too.
427 	int ReplaceOnDie: 1;     /// recreate the parent on destruction
428 	int ReplaceOnBuild: 1;   /// remove the parent, or just build over it.
429 };
430 
431 class CBuildRestrictionDistance : public CBuildRestriction
432 {
433 public:
CBuildRestrictionDistance()434 	CBuildRestrictionDistance() : Distance(0), CheckBuilder(false), RestrictType(NULL), Diagonal(true) {};
~CBuildRestrictionDistance()435 	virtual ~CBuildRestrictionDistance() {};
Init()436 	virtual void Init() {this->RestrictType = UnitTypeByIdent(this->RestrictTypeName);};
437 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
438 
439 	int Distance;        /// distance to build (circle)
440 	DistanceTypeType DistanceType;
441 	std::string RestrictTypeName;
442 	std::string RestrictTypeOwner;
443 	CUnitType *RestrictType;
444 	bool CheckBuilder;
445 	bool Diagonal;
446 };
447 
448 class CBuildRestrictionHasUnit : public CBuildRestriction
449 {
450 public:
CBuildRestrictionHasUnit()451 	CBuildRestrictionHasUnit() : Count(0), RestrictType(NULL) {};
~CBuildRestrictionHasUnit()452 	virtual ~CBuildRestrictionHasUnit() {};
Init()453 	virtual void Init() { this->RestrictType = UnitTypeByIdent(this->RestrictTypeName); };
454 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
455 
456 	int Count;
457 	DistanceTypeType CountType;
458 	std::string RestrictTypeName;
459 	CUnitType *RestrictType;
460 	std::string RestrictTypeOwner;
461 };
462 
463 class CBuildRestrictionSurroundedBy : public CBuildRestriction
464 {
465 public:
CBuildRestrictionSurroundedBy()466 	CBuildRestrictionSurroundedBy() : Count(0), Distance(0), DistanceType(Equal), CountType(Equal), RestrictType(NULL), CheckBuilder(false) {};
~CBuildRestrictionSurroundedBy()467 	virtual ~CBuildRestrictionSurroundedBy() {};
Init()468 	virtual void Init() { this->RestrictType = UnitTypeByIdent(this->RestrictTypeName); };
469 	virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
470 
471 	int Distance;
472 	DistanceTypeType DistanceType;
473 	int Count;
474 	DistanceTypeType CountType;
475 	std::string RestrictTypeName;
476 	std::string RestrictTypeOwner;
477 	CUnitType *RestrictType;
478 	bool CheckBuilder;
479 };
480 
481 /// Base structure of unit-type
482 /// @todo n0body: AutoBuildRate not implemented.
483 class CUnitType
484 {
485 public:
486 	CUnitType();
487 	~CUnitType();
488 
GetHalfTileSize()489 	Vec2i GetHalfTileSize() const { return Vec2i(TileWidth / 2, TileHeight / 2); }
490 	PixelSize GetPixelSize() const;
491 
492 	bool CheckUserBoolFlags(const char *BoolFlags) const;
CanTransport()493 	bool CanTransport() const { return MaxOnBoard > 0 && !GivesResource; }
494 	bool CanMove() const;
495 
496 	bool CanSelect(GroupSelectionMode mode = SELECTABLE_BY_RECTANGLE_ONLY) const;
497 
498 public:
499 	std::string Ident;              /// Identifier
500 	std::string Name;               /// Pretty name shown from the engine
501 	int Slot;                       /// Type as number
502 	std::string File;               /// Sprite files
503 	std::string ShadowFile;         /// Shadow file
504 
505 	int Width;                                            /// Sprite width
506 	int Height;                                           /// Sprite height
507 	int OffsetX;                                          /// Sprite horizontal offset
508 	int OffsetY;                                          /// Sprite vertical offset
509 	int DrawLevel;                                        /// Level to Draw UnitType at
510 	int ShadowWidth;                                      /// Shadow sprite width
511 	int ShadowHeight;                                     /// Shadow sprite height
512 	int ShadowOffsetX;                                    /// Shadow horizontal offset
513 	int ShadowOffsetY;                                    /// Shadow vertical offset
514 	char ShadowScale;                                     /// Shadow scale-down factor
515 	char ShadowSpriteFrame;                               /// If > 0, the shadow is a simple sprite without
516 	                                                      /// directions and this selects which frame to use
517 	PixelPos MissileOffsets[UnitSides][MaxAttackPos];     /// Attack offsets for missiles
518 
519 	CAnimations *Animations;        /// Animation scripts
520 	int StillFrame;                 /// Still frame
521 
522 	IconConfig Icon;                /// Icon to display for this unit
523 #ifdef USE_MNG
524 	struct _portrait_ {
525 		std::string *Files;
526 		int Num;
527 		Mng **Mngs;
528 		mutable int CurrMng;
529 		mutable int NumIterations;
530 	} Portrait;
531 #endif
532 	MissileConfig Missile;                           /// Missile weapon
533 	MissileConfig Explosion;                         /// Missile for unit explosion
534 	MissileConfig Impact[ANIMATIONS_DEATHTYPES + 2]; /// Missiles spawned if unit is hit(+shield)
535 
536 	LuaCallback *OnDeath;           /// lua function called when unit is about to die, receives x,y,unit
537 	LuaCallback *OnHit;             /// lua function called when unit is hit
538 	LuaCallback *OnEachCycle;       /// lua function called every cycle
539 	LuaCallback *OnEachSecond;      /// lua function called every second
540 	LuaCallback *OnInit;            /// lua function called on unit init
541 	LuaCallback *OnReady;           /// lua function called when unit ready/built
542 
543 	int TeleportCost;               /// mana used for teleportation
544 	LuaCallback *TeleportEffectIn;   /// lua function to create effects before teleportation
545 	LuaCallback *TeleportEffectOut;  /// lua function to create effects after teleportation
546 
547 	mutable std::string DamageType; /// DamageType (used for extra death animations and impacts)
548 
549 	std::string CorpseName;         /// Corpse type name
550 	CUnitType *CorpseType;          /// Corpse unit-type
551 
552 	CConstruction *Construction;    /// What is shown in construction phase
553 
554 	int RepairHP;                   /// Amount of HP per repair
555 	int RepairCosts[MaxCosts];      /// How much it costs to repair
556 
557 	int TileWidth;                  /// Tile size on map width
558 	int TileHeight;                 /// Tile size on map height
559 	int BoxWidth;                   /// Selected box size width
560 	int BoxHeight;                  /// Selected box size height
561 	int BoxOffsetX;                 /// Selected box size horizontal offset
562 	int BoxOffsetY;                 /// Selected box size vertical offset
563 	int NumDirections;              /// Number of directions unit can face
564 	int MinAttackRange;             /// Minimal attack range
565 	int ReactRangeComputer;         /// Reacts on enemy for computer
566 	int ReactRangePerson;           /// Reacts on enemy for person player
567 	int BurnPercent;                /// Burning percent.
568 	int BurnDamageRate;             /// HP burn rate per sec
569 	int RepairRange;                /// Units repair range.
570 #define InfiniteRepairRange INT_MAX
571 	char *CanCastSpell;             /// Unit is able to use spells.
572 	char *AutoCastActive;           /// Default value for autocast.
573 	int AutoBuildRate;              /// The rate at which the building builds itself
574 	int RandomMovementProbability;  /// Probability to move randomly.
575 	int RandomMovementDistance;     /// Quantity of tiles to move randomly.
576 	int ClicksToExplode;            /// Number of consecutive clicks until unit suicides.
577 	int MaxOnBoard;                 /// Number of Transporter slots.
578 	int BoardSize;                  /// How much "cells" unit occupies inside transporter
579 	int ButtonLevelForTransporter;  /// On which button level game will show units inside transporter
580 	int StartingResources;          /// Amount of Resources on build
581 	/// originally only visual effect, we do more with this!
582 	UnitTypeType UnitType;          /// Land / fly / naval
583 	int DecayRate;                  /// Decay rate in 1/6 seconds
584 	// TODO: not used
585 	int AnnoyComputerFactor;        /// How much this annoys the computer
586 	int AiAdjacentRange;            /// Min radius for AI build surroundings checking
587 	int MouseAction;                /// Right click action
588 #define MouseActionNone      0      /// Nothing
589 #define MouseActionAttack    1      /// Attack
590 #define MouseActionMove      2      /// Move
591 #define MouseActionHarvest   3      /// Harvest resources
592 #define MouseActionSpellCast 5      /// Cast the first spell known
593 #define MouseActionSail      6      /// Sail
594 	int CanTarget;                  /// Which units can it attack
595 #define CanTargetLand 1             /// Can attack land units
596 #define CanTargetSea  2             /// Can attack sea units
597 #define CanTargetAir  4             /// Can attack air units
598 
599 	unsigned Flip : 1;              /// Flip image when facing left
600 	unsigned LandUnit : 1;          /// Land animated
601 	unsigned AirUnit : 1;           /// Air animated
602 	unsigned SeaUnit : 1;           /// Sea animated
603 	unsigned ExplodeWhenKilled : 1; /// Death explosion animated
604 	unsigned Building : 1;          /// Building
605 	unsigned CanAttack : 1;         /// Unit can attack.
606 	unsigned Neutral : 1;           /// Unit is neutral, used by the editor
607 
608 	unsigned SideAttack : 1;            /// Unit turns for attack (used for ships)
609 	unsigned Skirmisher : 1;            /// Unit will try to shoot from max range
610 
611 	CUnitStats DefaultStat;
612 	CUnitStats MapDefaultStat;
613 	struct BoolFlags {
614 		bool value;             /// User defined flag. Used for (dis)allow target.
615 		char CanTransport;      /// Can transport units with this flag.
616 		char CanTargetFlag;     /// Flag needed to target with missile.
617 		char AiPriorityTarget;  /// Attack this units first.
618 	};
619 	std::vector<BoolFlags> BoolFlag;
620 
621 	int CanStore[MaxCosts];             /// Resources that we can store here.
622 	int GivesResource;                  /// The resource this unit gives.
623 	ResourceInfo *ResInfo[MaxCosts];    /// Resource information.
624 	std::vector<CBuildRestriction *> BuildingRules;   /// Rules list for building a building.
625 	std::vector<CBuildRestriction *> AiBuildingRules; /// Rules list for for AI to build a building.
626 	CColor NeutralMinimapColorRGB;   /// Minimap Color for Neutral Units.
627 
628 	CUnitSound Sound;               /// Sounds for events
629 	CUnitSound MapSound;			/// Sounds for events, map-specific
630 
631 	int PoisonDrain;                /// How much health is drained every second when poisoned
632 
633 	// --- FILLED UP ---
634 
635 	unsigned FieldFlags;            /// Unit map field flags
636 	unsigned MovementMask;          /// Unit check this map flags for move
637 
638 	/// @todo This stats should? be moved into the player struct
639 	CUnitStats Stats[PlayerMax];     /// Unit status for each player
640 
641 	CPlayerColorGraphic *Sprite;     /// Sprite images
642 	CGraphic *ShadowSprite;          /// Shadow sprite image
643 };
644 
645 /*----------------------------------------------------------------------------
646 --  Variables
647 ----------------------------------------------------------------------------*/
648 
649 extern std::vector<CUnitType *> UnitTypes;   /// All unit-types
650 
651 /// @todo this hardcoded unit-types must be removed!!
652 extern CUnitType *UnitTypeHumanWall;  /// Human wall
653 extern CUnitType *UnitTypeOrcWall;    /// Orc wall
654 
655 /**
656 **  Variable info for unit and unittype.
657 */
658 class CUnitTypeVar
659 {
660 public:
661 
662 	template <const unsigned int SIZE>
663 	struct CKeys {
664 
665 		struct DataKey {
key_predCKeys::DataKey666 			static bool key_pred(const DataKey &lhs,
667 								 const DataKey &rhs)
668 			{
669 				return ((lhs.keylen == rhs.keylen) ?
670 						(strcmp(lhs.key, rhs.key) < 0) : (lhs.keylen < rhs.keylen));
671 			}
672 			int offset;
673 			unsigned int keylen;
674 			const char *key;
675 		};
676 
CKeysCKeys677 		CKeys(): TotalKeys(SIZE) {}
678 
679 		DataKey buildin[SIZE];
680 		std::map<std::string, int> user;
681 		unsigned int TotalKeys;
682 
InitCKeys683 		void Init()
684 		{
685 			std::sort(buildin, buildin + SIZE, DataKey::key_pred);
686 		}
687 
688 		const char *operator[](int index)
689 		{
690 			for (unsigned int i = 0; i < SIZE; ++i) {
691 				if (buildin[i].offset == index) {
692 					return buildin[i].key;
693 				}
694 			}
695 			for (std::map<std::string, int>::iterator
696 				 it(user.begin()), end(user.end());
697 				 it != end; ++it) {
698 				if ((*it).second == index) {
699 					return ((*it).first).c_str();
700 				}
701 			}
702 			return NULL;
703 		}
704 
705 		/**
706 		**  Return the index of the external storage array/vector.
707 		**
708 		**  @param varname  Name of the variable.
709 		**
710 		**  @return Index of the variable, -1 if not found.
711 		*/
712 		int operator[](const char *const key)
713 		{
714 			DataKey k;
715 			k.key = key;
716 			k.keylen = strlen(key);
717 			const DataKey *p = std::lower_bound(buildin, buildin + SIZE,
718 												k, DataKey::key_pred);
719 			if ((p != buildin + SIZE) && p->keylen == k.keylen &&
720 				0 == strcmp(p->key, key)) {
721 				return p->offset;
722 			} else {
723 				std::map<std::string, int>::iterator
724 				ret(user.find(key));
725 				if (ret != user.end()) {
726 					return (*ret).second;
727 				}
728 			}
729 			return -1;
730 		}
731 
AddKeyCKeys732 		int AddKey(const char *const key)
733 		{
734 			int index = this->operator[](key);
735 			if (index != -1) {
736 				DebugPrint("Warning, Key '%s' already defined\n" _C_ key);
737 				return index;
738 			}
739 			user[key] = TotalKeys++;
740 			return TotalKeys - 1;
741 		}
742 
743 	};
744 
745 	struct CBoolKeys : public CKeys<NBARALREADYDEFINED> {
746 		CBoolKeys();
747 	};
748 
749 	struct CVariableKeys : public CKeys<NVARALREADYDEFINED> {
750 		CVariableKeys();
751 	};
752 
CUnitTypeVar()753 	CUnitTypeVar() {}
754 
755 	void Init();
756 	void Clear();
757 
758 	CBoolKeys BoolFlagNameLookup;      /// Container of name of user defined bool flag.
759 	CVariableKeys VariableNameLookup;  /// Container of names of user defined variables.
760 
761 	//EventType *Event;                  /// Array of functions sets to call when en event occurs.
762 	std::vector<CVariable> Variable;   /// Array of user defined variables (default value for unittype).
763 	std::vector<CDecoVar *> DecoVar;   /// Array to describe how showing variable.
764 
GetNumberBoolFlag()765 	unsigned int GetNumberBoolFlag() const
766 	{
767 		return BoolFlagNameLookup.TotalKeys;
768 	}
769 
GetNumberVariable()770 	unsigned int GetNumberVariable() const
771 	{
772 		return VariableNameLookup.TotalKeys;
773 	}
774 };
775 
776 extern CUnitTypeVar UnitTypeVar;
777 
778 /*----------------------------------------------------------------------------
779 --  Functions
780 ----------------------------------------------------------------------------*/
781 extern CUnitType *CclGetUnitType(lua_State *l);  /// Access unit-type object
782 extern void UnitTypeCclRegister();               /// Register ccl features
783 
784 extern void UpdateUnitStats(CUnitType &type, int reset_to_default);       /// Update unit stats
785 extern void UpdateStats(int reset_to_default);       /// Update unit stats
786 extern CUnitType *UnitTypeByIdent(const std::string &ident);/// Get unit-type by ident
787 
788 extern void SaveUnitTypes(CFile &file);              /// Save the unit-type table
789 extern CUnitType *NewUnitTypeSlot(const std::string &ident);/// Allocate an empty unit-type slot
790 /// Draw the sprite frame of unit-type
791 extern void DrawUnitType(const CUnitType &type, CPlayerColorGraphic *sprite,
792 						 int player, int frame, const PixelPos &screenPos);
793 
794 extern void InitUnitTypes(int reset_player_stats);   /// Init unit-type table
795 extern void LoadUnitTypeSprite(CUnitType &unittype); /// Load the sprite for a unittype
796 extern void LoadUnitTypes();                     /// Load the unit-type data
797 extern void CleanUnitTypes();                    /// Cleanup unit-type module
798 
799 // in script_unittype.c
800 
801 /// Parse User Variables field.
802 extern void DefineVariableField(lua_State *l, CVariable *var, int lua_index);
803 
804 /// Update custom Variables with other variable (like Hp, ...)
805 extern void UpdateUnitVariables(CUnit &unit);
806 
807 extern void SetMapStat(std::string ident, std::string variable_key, int value, std::string variable_type);
808 extern void SetMapSound(std::string ident, std::string sound, std::string sound_type, std::string sound_subtype = "");
809 //@}
810 
811 #endif // !__UNITTYPE_H__
812