1 /*
2 	This file is part of Warzone 2100.
3 	Copyright (C) 1999-2004  Eidos Interactive
4 	Copyright (C) 2005-2020  Warzone 2100 Project
5 
6 	Warzone 2100 is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 2 of the License, or
9 	(at your option) any later version.
10 
11 	Warzone 2100 is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with Warzone 2100; if not, write to the Free Software
18 	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 /** @file
21  *  Definitions for the structures.
22  */
23 
24 #ifndef __INCLUDED_SRC_STRUCTURE_H__
25 #define __INCLUDED_SRC_STRUCTURE_H__
26 
27 #include "lib/framework/string_ext.h"
28 #include "lib/framework/wzconfig.h"
29 
30 #include "objectdef.h"
31 #include "structuredef.h"
32 #include "visibility.h"
33 #include "baseobject.h"
34 
35 // how long to wait between CALL_STRUCT_ATTACKED's - plus how long to flash on radar for
36 #define ATTACK_CB_PAUSE		5000
37 
38 /// Extra z padding for assembly points
39 #define ASSEMBLY_POINT_Z_PADDING 10
40 
41 #define	STRUCTURE_DAMAGE_SCALING	400
42 
43 //production loop max
44 #define INFINITE_PRODUCTION	 9//10
45 
46 /*This should correspond to the structLimits! */
47 #define	MAX_FACTORY			5
48 
49 //used to flag when the Factory is ready to start building
50 #define ACTION_START_TIME	0
51 
52 extern std::vector<ProductionRun> asProductionRun[NUM_FACTORY_TYPES];
53 
54 //Value is stored for easy access to this structure stat
55 extern UDWORD	factoryModuleStat;
56 extern UDWORD	powerModuleStat;
57 extern UDWORD	researchModuleStat;
58 
59 // the structure that was last hit
60 extern STRUCTURE	*psLastStructHit;
61 
62 //stores which player the production list has been set up for
63 extern SBYTE         productionPlayer;
64 
65 //holder for all StructureStats
66 extern STRUCTURE_STATS		*asStructureStats;
67 extern UDWORD				numStructureStats;
68 
69 //used to hold the modifiers cross refd by weapon effect and structureStrength
70 extern STRUCTSTRENGTH_MODIFIER		asStructStrengthModifier[WE_NUMEFFECTS][NUM_STRUCT_STRENGTH];
71 
72 void handleAbandonedStructures();
73 
74 int getMaxDroids(int player);
75 int getMaxCommanders(int player);
76 int getMaxConstructors(int player);
77 void setMaxDroids(int player, int value);
78 void setMaxCommanders(int player, int value);
79 void setMaxConstructors(int player, int value);
80 
81 bool structureExists(int player, STRUCTURE_TYPE type, bool built, bool isMission);
82 
83 bool IsPlayerDroidLimitReached(int player);
84 
85 bool loadStructureStats(WzConfig &ini);
86 /*Load the Structure Strength Modifiers from the file exported from Access*/
87 bool loadStructureStrengthModifiers(WzConfig &ini);
88 
89 bool structureStatsShutDown();
90 
91 int requestOpenGate(STRUCTURE *psStructure);
92 int gateCurrentOpenHeight(const STRUCTURE *psStructure, uint32_t time, int minimumStub);  ///< Returns how far open the gate is, or 0 if the structure is not a gate.
93 
94 int32_t structureDamage(STRUCTURE *psStructure, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime, bool isDamagePerSecond, int minDamage);
95 void structureBuild(STRUCTURE *psStructure, DROID *psDroid, int buildPoints, int buildRate = 1);
96 void structureDemolish(STRUCTURE *psStructure, DROID *psDroid, int buildPoints);
97 void structureRepair(STRUCTURE *psStruct, DROID *psDroid, int buildRate);
98 /* Set the type of droid for a factory to build */
99 bool structSetManufacture(STRUCTURE *psStruct, DROID_TEMPLATE *psTempl, QUEUE_MODE mode);
100 uint32_t structureBuildPointsToCompletion(const STRUCTURE & structure);
101 float structureCompletionProgress(const STRUCTURE & structure);
102 
103 //builds a specified structure at a given location
104 STRUCTURE *buildStructure(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y, UDWORD player, bool FromSave);
105 STRUCTURE *buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y, uint16_t direction, UDWORD player, bool FromSave);
106 /// Create a blueprint structure, with just enough information to render it
107 STRUCTURE *buildBlueprint(STRUCTURE_STATS const *psStats, Vector3i xy, uint16_t direction, unsigned moduleIndex, STRUCT_STATES state);
108 /* The main update routine for all Structures */
109 void structureUpdate(STRUCTURE *psBuilding, bool bMission);
110 
111 /* Remove a structure and free it's memory */
112 bool destroyStruct(STRUCTURE *psDel, unsigned impactTime);
113 
114 // remove a structure from a game without any visible effects
115 // bDestroy = true if the object is to be destroyed
116 // (for example used to change the type of wall at a location)
117 bool removeStruct(STRUCTURE *psDel, bool bDestroy);
118 
119 //fills the list with Structures that can be built
120 std::vector<STRUCTURE_STATS *> fillStructureList(UDWORD selectedPlayer, UDWORD limit, bool showFavorites);
121 
122 /// Checks if the two structures would be too close to build together.
123 bool isBlueprintTooClose(STRUCTURE_STATS const *stats1, Vector2i pos1, uint16_t dir1, STRUCTURE_STATS const *stats2, Vector2i pos2, uint16_t dir2);
124 
125 /// Checks that the location is valid to build on.
126 /// pos in world coords
127 bool validLocation(BASE_STATS *psStats, Vector2i pos, uint16_t direction, unsigned player, bool bCheckBuildQueue);
128 
129 bool isWall(STRUCTURE_TYPE type);                                    ///< Structure is a wall. Not completely sure it handles all cases.
130 bool isBuildableOnWalls(STRUCTURE_TYPE type);                        ///< Structure can be built on walls. Not completely sure it handles all cases.
131 
132 void alignStructure(STRUCTURE *psBuilding);
133 
134 /* set the current number of structures of each type built */
135 void setCurrentStructQuantity(bool displayError);
136 /* get a stat inc based on the name */
137 int32_t getStructStatFromName(const WzString &name);
138 /*check to see if the structure is 'doing' anything  - return true if idle*/
139 bool  structureIdle(const STRUCTURE *psBuilding);
140 /*sets the point new droids go to - x/y in world coords for a Factory*/
141 void setAssemblyPoint(FLAG_POSITION *psAssemblyPoint, UDWORD x, UDWORD y, UDWORD player, bool bCheck);
142 
143 /*initialises the flag before a new data set is loaded up*/
144 void initFactoryNumFlag();
145 
146 //called at start of missions
147 void resetFactoryNumFlag();
148 
149 /* get demolish stat */
150 STRUCTURE_STATS *structGetDemolishStat();
151 
152 /*find a location near to the factory to start the droid of*/
153 bool placeDroid(STRUCTURE *psStructure, UDWORD *droidX, UDWORD *droidY);
154 
155 //Set the factory secondary orders to a droid
156 void setFactorySecondaryState(DROID *psDroid, STRUCTURE *psStructure);
157 
158 /* is this a lassat structure? */
isLasSat(STRUCTURE_STATS * pStructureType)159 static inline bool isLasSat(STRUCTURE_STATS *pStructureType)
160 {
161 	ASSERT_OR_RETURN(false, pStructureType != nullptr, "LasSat is invalid?");
162 
163 	return (pStructureType->psWeapStat[0]
164 	        && pStructureType->psWeapStat[0]->weaponSubClass == WSC_LAS_SAT);
165 }
166 
167 /*sets the flag to indicate a SatUplink Exists - so draw everything!*/
168 void setSatUplinkExists(bool state, UDWORD player);
169 
170 /*returns the status of the flag*/
171 bool getSatUplinkExists(UDWORD player);
172 
173 /*sets the flag to indicate a Las Sat Exists - ONLY EVER WANT ONE*/
174 void setLasSatExists(bool state, UDWORD player);
175 
176 /* added int weapon_slot to fix the alway slot 0 hack */
177 bool calcStructureMuzzleLocation(const STRUCTURE *psStructure, Vector3i *muzzle, int weapon_slot);
178 bool calcStructureMuzzleBaseLocation(const STRUCTURE *psStructure, Vector3i *muzzle, int weapon_slot);
179 
180 /*this is called whenever a structure has finished building*/
181 void buildingComplete(STRUCTURE *psBuilding);
182 
183 // these functions are used in game.c inplace of  building complete
184 void checkForResExtractors(STRUCTURE *psPowerGen);
185 void checkForPowerGen(STRUCTURE *psPowerGen);
186 
187 uint16_t countPlayerUnusedDerricks();
188 
189 // Set the command droid that factory production should go to struct _command_droid;
190 void assignFactoryCommandDroid(STRUCTURE *psStruct, struct DROID *psCommander);
191 
192 // remove all factories from a command droid
193 void clearCommandDroidFactory(DROID *psDroid);
194 
195 /*for a given structure, return a pointer to its module stat */
196 STRUCTURE_STATS *getModuleStat(const STRUCTURE *psStruct);
197 
198 /*called when a Res extractor is destroyed or runs out of power or is disconnected
199 adjusts the owning Power Gen so that it can link to a different Res Extractor if one
200 is available*/
201 void releaseResExtractor(STRUCTURE *psRelease);
202 
203 /*called when a Power Gen is destroyed or is disconnected
204 adjusts the associated Res Extractors so that they can link to different Power
205 Gens if any are available*/
206 void releasePowerGen(STRUCTURE *psRelease);
207 
208 //print some info at the top of the screen dependent on the structure
209 void printStructureInfo(STRUCTURE *psStructure);
210 
211 /*Checks the template type against the factory type - returns false
212 if not a good combination!*/
213 bool validTemplateForFactory(const DROID_TEMPLATE *psTemplate, STRUCTURE *psFactory, bool complain);
214 
215 /*calculates the damage caused to the resistance levels of structures*/
216 bool electronicDamage(BASE_OBJECT *psTarget, UDWORD damage, UBYTE attackPlayer);
217 
218 /* EW works differently in multiplayer mode compared with single player.*/
219 bool validStructResistance(const STRUCTURE *psStruct);
220 
221 /*checks to see if a specific structure type exists -as opposed to a structure
222 stat type*/
223 bool checkSpecificStructExists(UDWORD structInc, UDWORD player);
224 
225 int32_t getStructureDamage(const STRUCTURE *psStructure);
226 
227 unsigned structureBodyBuilt(const STRUCTURE *psStruct);  ///< Returns the maximum body points of a structure with the current number of build points.
228 UDWORD structureBody(const STRUCTURE *psStruct);
229 UDWORD structureResistance(const STRUCTURE_STATS *psStats, UBYTE player);
230 
231 void hqReward(UBYTE losingPlayer, UBYTE rewardPlayer);
232 
233 // Is a structure a factory of somekind?
234 bool StructIsFactory(const STRUCTURE *Struct);
235 
236 // Is a flag a factory delivery point?
237 bool FlagIsFactory(const FLAG_POSITION *psCurrFlag);
238 
239 // Find a factories corresonding delivery point.
240 FLAG_POSITION *FindFactoryDelivery(const STRUCTURE *Struct);
241 
242 //Find the factory associated with the delivery point - returns NULL if none exist
243 STRUCTURE *findDeliveryFactory(FLAG_POSITION *psDelPoint);
244 
245 /*this is called when a factory produces a droid. The Template returned is the next
246 one to build - if any*/
247 DROID_TEMPLATE *factoryProdUpdate(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate);
248 
249 //increment the production run for this type
250 void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool add);
251 
252 //returns the quantity of a specific template in the production list
253 ProductionRunEntry getProduction(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate);
254 
255 //looks through a players production list to see if a command droid is being built
256 UBYTE checkProductionForCommand(UBYTE player);
257 
258 //check that delivery points haven't been put down in invalid location
259 void checkDeliveryPoints(UDWORD version);
260 
261 //adjust the loop quantity for this factory
262 void factoryLoopAdjust(STRUCTURE *psStruct, bool add);
263 
264 /*cancels the production run for the factory and returns any power that was
265 accrued but not used*/
266 void cancelProduction(STRUCTURE *psBuilding, QUEUE_MODE mode, bool mayClearProductionRun = true);
267 
268 /*set a factory's production run to hold*/
269 void holdProduction(STRUCTURE *psBuilding, QUEUE_MODE mode);
270 
271 /*release a factory's production run from hold*/
272 void releaseProduction(STRUCTURE *psBuilding, QUEUE_MODE mode);
273 
274 /// Does the next item in the production list.
275 void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MODE mode);
276 
277 // Count number of factories assignable to a command droid.
278 UWORD countAssignableFactories(UBYTE player, UWORD FactoryType);
279 
280 /*Used for determining how much of the structure to draw as being built or demolished*/
281 float structHeightScale(const STRUCTURE *psStruct);
282 
283 /*compares the structure sensor type with the droid weapon type to see if the
284 FIRE_SUPPORT order can be assigned*/
285 bool structSensorDroidWeapon(const STRUCTURE *psStruct, const DROID *psDroid);
286 
287 /*checks if the structure has a Counter Battery sensor attached - returns
288 true if it has*/
289 bool structCBSensor(const STRUCTURE *psStruct);
290 /*checks if the structure has a Standard Turret sensor attached - returns
291 true if it has*/
292 bool structStandardSensor(const STRUCTURE *psStruct);
293 
294 /*checks if the structure has a VTOL Intercept sensor attached - returns
295 true if it has*/
296 bool structVTOLSensor(const STRUCTURE *psStruct);
297 
298 /*checks if the structure has a VTOL Counter Battery sensor attached - returns
299 true if it has*/
300 bool structVTOLCBSensor(const STRUCTURE *psStruct);
301 
302 // return the nearest rearm pad
303 // psTarget can be NULL
304 STRUCTURE *findNearestReArmPad(DROID *psDroid, STRUCTURE *psTarget, bool bClear);
305 
306 // check whether a rearm pad is clear
307 bool clearRearmPad(const STRUCTURE *psStruct);
308 
309 // clear a rearm pad for a vtol to land on it
310 void ensureRearmPadClear(STRUCTURE *psStruct, DROID *psDroid);
311 
312 // return whether a rearm pad has a vtol on it
313 bool vtolOnRearmPad(STRUCTURE *psStruct, DROID *psDroid);
314 
315 /* Just returns true if the structure's present body points aren't as high as the original*/
316 bool	structIsDamaged(STRUCTURE *psStruct);
317 
318 // give a structure from one player to another - used in Electronic Warfare
319 STRUCTURE *giftSingleStructure(STRUCTURE *psStructure, UBYTE attackPlayer, bool electronic_warfare = true);
320 
321 /*Initialise the production list and set up the production player*/
322 void changeProductionPlayer(UBYTE player);
323 
324 // La!
325 bool IsStatExpansionModule(const STRUCTURE_STATS *psStats);
326 
327 /// is this a blueprint and not a real structure?
328 bool structureIsBlueprint(const STRUCTURE *psStructure);
329 bool isBlueprint(const BASE_OBJECT *psObject);
330 
331 /*returns the power cost to build this structure, or to add its next module */
332 UDWORD structPowerToBuildOrAddNextModule(const STRUCTURE *psStruct);
333 
334 // check whether a factory of a certain number and type exists
335 bool checkFactoryExists(UDWORD player, UDWORD factoryType, UDWORD inc);
336 
337 /*checks the structure passed in is a Las Sat structure which is currently
338 selected - returns true if valid*/
339 bool lasSatStructSelected(const STRUCTURE *psStruct);
340 
341 void cbNewDroid(STRUCTURE *psFactory, DROID *psDroid);
342 
343 StructureBounds getStructureBounds(const STRUCTURE *object);
344 StructureBounds getStructureBounds(const STRUCTURE_STATS *stats, Vector2i pos, uint16_t direction);
345 
346 bool canStructureHaveAModuleAdded(const STRUCTURE* const structure);
347 
structSensorRange(const STRUCTURE * psObj)348 static inline int structSensorRange(const STRUCTURE *psObj)
349 {
350 	return objSensorRange((const BASE_OBJECT *)psObj);
351 }
352 
structJammerPower(const STRUCTURE * psObj)353 static inline int structJammerPower(const STRUCTURE *psObj)
354 {
355 	return objJammerPower((const BASE_OBJECT *)psObj);
356 }
357 
structureGetInterpolatedWeaponRotation(STRUCTURE * psStructure,int weaponSlot,uint32_t time)358 static inline Rotation structureGetInterpolatedWeaponRotation(STRUCTURE *psStructure, int weaponSlot, uint32_t time)
359 {
360 	return interpolateRot(psStructure->asWeaps[weaponSlot].prevRot, psStructure->asWeaps[weaponSlot].rot, psStructure->prevTime, psStructure->time, time);
361 }
362 
363 #define setStructureTarget(_psBuilding, _psNewTarget, _idx, _targetOrigin) _setStructureTarget(_psBuilding, _psNewTarget, _idx, _targetOrigin, __LINE__, __FUNCTION__)
_setStructureTarget(STRUCTURE * psBuilding,BASE_OBJECT * psNewTarget,UWORD idx,TARGET_ORIGIN targetOrigin,int line,const char * func)364 static inline void _setStructureTarget(STRUCTURE *psBuilding, BASE_OBJECT *psNewTarget, UWORD idx, TARGET_ORIGIN targetOrigin, int line, const char *func)
365 {
366 	ASSERT_OR_RETURN(, idx < MAX_WEAPONS, "Bad index");
367 	ASSERT_OR_RETURN(, psNewTarget == nullptr || !psNewTarget->died, "setStructureTarget set dead target");
368 	psBuilding->psTarget[idx] = psNewTarget;
369 	psBuilding->asWeaps[idx].origin = targetOrigin;
370 #ifdef DEBUG
371 	psBuilding->targetLine[idx] = line;
372 	sstrcpy(psBuilding->targetFunc[idx], func);
373 #else
374 	// Prevent warnings about unused parameters
375 	(void)line;
376 	(void)func;
377 #endif
378 }
379 
380 // Functions for the GUI to know what's pending, before it's synchronised.
381 template<typename Functionality, typename Subject>
setStatusPendingStart(Functionality & functionality,Subject * subject)382 static inline void setStatusPendingStart(Functionality &functionality, Subject *subject)
383 {
384 	functionality.psSubjectPending = subject;
385 	functionality.statusPending = FACTORY_START_PENDING;
386 	++functionality.pendingCount;
387 }
388 
389 template<typename Functionality>
setStatusPendingCancel(Functionality & functionality)390 static inline void setStatusPendingCancel(Functionality &functionality)
391 {
392 	functionality.psSubjectPending = nullptr;
393 	functionality.statusPending = FACTORY_CANCEL_PENDING;
394 	++functionality.pendingCount;
395 }
396 
397 template<typename Functionality>
setStatusPendingHold(Functionality & functionality)398 static inline void setStatusPendingHold(Functionality &functionality)
399 {
400 	if (functionality.psSubjectPending == nullptr)
401 	{
402 		functionality.psSubjectPending = functionality.psSubject;
403 	}
404 	functionality.statusPending = FACTORY_HOLD_PENDING;
405 	++functionality.pendingCount;
406 }
407 
408 template<typename Functionality>
setStatusPendingRelease(Functionality & functionality)409 static inline void setStatusPendingRelease(Functionality &functionality)
410 {
411 	if (functionality.psSubjectPending == nullptr && functionality.statusPending != FACTORY_CANCEL_PENDING)
412 	{
413 		functionality.psSubjectPending = functionality.psSubject;
414 	}
415 	if (functionality.psSubjectPending != nullptr)
416 	{
417 		functionality.statusPending = FACTORY_START_PENDING;
418 	}
419 	++functionality.pendingCount;
420 }
421 
422 template<typename Functionality>
popStatusPending(Functionality & functionality)423 static inline void popStatusPending(Functionality &functionality)
424 {
425 	if (functionality.pendingCount == 0)
426 	{
427 		++functionality.pendingCount;
428 	}
429 	if (--functionality.pendingCount == 0)
430 	{
431 		// Subject is now synchronised, remove pending.
432 		functionality.psSubjectPending = nullptr;
433 		functionality.statusPending = FACTORY_NOTHING_PENDING;
434 	}
435 }
436 
437 void checkStructure(const STRUCTURE *psStructure, const char *const location_description, const char *function, const int recurse);
438 
439 #define CHECK_STRUCTURE(object) checkStructure((object), AT_MACRO, __FUNCTION__, max_check_object_recursion)
440 
441 void structureInitVars();
442 void initStructLimits();
443 
444 #define syncDebugStructure(psStruct, ch) _syncDebugStructure(__FUNCTION__, psStruct, ch)
445 void _syncDebugStructure(const char *function, STRUCTURE const *psStruct, char ch);
446 
447 
448 // True iff object is a structure.
isStructure(SIMPLE_OBJECT const * psObject)449 static inline bool isStructure(SIMPLE_OBJECT const *psObject)
450 {
451 	return psObject != nullptr && psObject->type == OBJ_STRUCTURE;
452 }
453 // Returns STRUCTURE * if structure or NULL if not.
castStructure(SIMPLE_OBJECT * psObject)454 static inline STRUCTURE *castStructure(SIMPLE_OBJECT *psObject)
455 {
456 	return isStructure(psObject) ? (STRUCTURE *)psObject : (STRUCTURE *)nullptr;
457 }
458 // Returns STRUCTURE const * if structure or NULL if not.
castStructure(SIMPLE_OBJECT const * psObject)459 static inline STRUCTURE const *castStructure(SIMPLE_OBJECT const *psObject)
460 {
461 	return isStructure(psObject) ? (STRUCTURE const *)psObject : (STRUCTURE const *)nullptr;
462 }
463 
getBuildingResearchPoints(STRUCTURE * psStruct)464 static inline int getBuildingResearchPoints(STRUCTURE *psStruct)
465 {
466 	auto &upgrade = psStruct->pStructureType->upgrade[psStruct->player];
467 	return upgrade.research + upgrade.moduleResearch * psStruct->capacity;
468 }
469 
getBuildingProductionPoints(STRUCTURE * psStruct)470 static inline int getBuildingProductionPoints(STRUCTURE *psStruct)
471 {
472 	auto &upgrade = psStruct->pStructureType->upgrade[psStruct->player];
473 	return upgrade.production + upgrade.moduleProduction * psStruct->capacity;
474 }
475 
getBuildingPowerPoints(STRUCTURE * psStruct)476 static inline int getBuildingPowerPoints(STRUCTURE *psStruct)
477 {
478 	auto &upgrade = psStruct->pStructureType->upgrade[psStruct->player];
479 	return upgrade.power + upgrade.modulePower * psStruct->capacity;
480 }
481 
getBuildingRepairPoints(STRUCTURE * psStruct)482 static inline int getBuildingRepairPoints(STRUCTURE *psStruct)
483 {
484 	return psStruct->pStructureType->upgrade[psStruct->player].repair;
485 }
486 
getBuildingRearmPoints(STRUCTURE * psStruct)487 static inline int getBuildingRearmPoints(STRUCTURE *psStruct)
488 {
489 	return psStruct->pStructureType->upgrade[psStruct->player].rearm;
490 }
491 
492 WzString getFavoriteStructs();
493 void setFavoriteStructs(WzString list);
494 
495 struct LineBuild
496 {
backLineBuild497 	Vector2i back() const { return (*this)[count - 1]; }
498 	Vector2i operator [](int i) const { return begin + i*step; }
499 
500 	Vector2i begin = {0, 0};
501 	Vector2i step = {0, 0};
502 	int count = 0;
503 };
504 
505 LineBuild calcLineBuild(Vector2i size, STRUCTURE_TYPE type, Vector2i pos, Vector2i pos2);
506 LineBuild calcLineBuild(STRUCTURE_STATS const *stats, uint16_t direction, Vector2i pos, Vector2i pos2);
507 
508 #endif // __INCLUDED_SRC_STRUCTURE_H__
509