construction.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349
  1. enum ConstructionMaterialType
  2. {
  3. MATERIAL_NONE = 0,
  4. MATERIAL_LOG = 1,
  5. MATERIAL_WOOD = 2,
  6. MATERIAL_STAIRS = 3,
  7. MATERIAL_METAL = 4,
  8. MATERIAL_WIRE = 5
  9. }
  10. class Construction
  11. {
  12. static const float REPAIR_MATERIAL_PERCENTAGE = 0.15;
  13. static const float DECONSTURCT_MATERIAL_LOSS = 0.2;
  14. protected ref map<string, ref ConstructionPart> m_ConstructionParts; //string - part name; int - 0-not constructed, 1-constructed
  15. protected BaseBuildingBase m_Parent;
  16. //Debug
  17. protected Shape m_CollisionBox;
  18. //Collision detectection
  19. protected ConstructionBoxTrigger m_ConstructionBoxTrigger;
  20. //============================================
  21. // Construction
  22. //============================================
  23. void Construction( BaseBuildingBase parent )
  24. {
  25. m_ConstructionParts = new ref map<string, ref ConstructionPart>;
  26. //set parent object
  27. SetParent( parent );
  28. }
  29. void Init()
  30. {
  31. UpdateConstructionParts();
  32. }
  33. //parent
  34. protected BaseBuildingBase GetParent()
  35. {
  36. return m_Parent;
  37. }
  38. protected void SetParent( BaseBuildingBase parent )
  39. {
  40. m_Parent = parent;
  41. }
  42. //============================================
  43. // Construction process
  44. //============================================
  45. //constructed parts
  46. void AddToConstructedParts( string part_name )
  47. {
  48. ConstructionPart constrution_part = GetConstructionPart( part_name );
  49. if ( constrution_part )
  50. {
  51. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " AddToConstructedParts part=" + constrution_part.GetPartName());
  52. constrution_part.SetBuiltState( true );
  53. }
  54. }
  55. void RemoveFromConstructedParts( string part_name )
  56. {
  57. ConstructionPart constrution_part = GetConstructionPart( part_name );
  58. if ( constrution_part )
  59. {
  60. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " RemoveFromConstructedParts part=" + constrution_part.GetPartName());
  61. constrution_part.SetBuiltState( false );
  62. }
  63. }
  64. //BuildPart
  65. void BuildPartServer( notnull Man player, string part_name, int action_id )
  66. {
  67. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction BuildPartServer | " + part_name);
  68. //reset DamageZone health
  69. string damage_zone;
  70. if (DamageSystem.GetDamageZoneFromComponentName(GetParent(),part_name,damage_zone))
  71. {
  72. GetParent().SetAllowDamage(true);
  73. GetParent().SetHealthMax(damage_zone);
  74. GetParent().ProcessInvulnerabilityCheck(GetParent().GetInvulnerabilityTypeString());
  75. }
  76. //on action
  77. TakeMaterialsServer( part_name );
  78. //destroy build collision check trigger
  79. DestroyCollisionTrigger();
  80. //call event
  81. GetParent().OnPartBuiltServer( player, part_name, action_id );
  82. }
  83. //DismantlePart
  84. void DismantlePartServer( notnull Man player, string part_name, int action_id )
  85. {
  86. string damage_zone;
  87. DamageSystem.GetDamageZoneFromComponentName( GetParent(),part_name,damage_zone );
  88. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction DismantlePartServer | " + part_name);
  89. //receive materials
  90. ReceiveMaterialsServer( player, part_name, damage_zone );
  91. //drop non-usable materials
  92. DropNonUsableMaterialsServer( player, part_name );
  93. //call event
  94. GetParent().OnPartDismantledServer( player, part_name, action_id );
  95. //set DamageZone health to zero (redundant?)
  96. /*if ( GetParent().GetHealth(damage_zone,"Health") > 0 )
  97. {
  98. GetParent().SetHealth(damage_zone,"Health",0);
  99. }*/
  100. }
  101. //DestroyPart
  102. void DestroyPartServer( Man player, string part_name, int action_id, bool destroyed_by_connected_part = false )
  103. {
  104. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction DestroyPartServer | " + part_name);
  105. //destroy attached materials (if locked)
  106. DestroyMaterialsServer( player, part_name );
  107. //drop non-usable materials
  108. DropNonUsableMaterialsServer( player, part_name );
  109. //call event
  110. GetParent().OnPartDestroyedServer( player, part_name, action_id, destroyed_by_connected_part );
  111. //set DamageZone health to zero (redundant?)
  112. string damage_zone;
  113. if ( DamageSystem.GetDamageZoneFromComponentName(GetParent(),part_name,damage_zone) && GetParent().GetHealth(damage_zone,"Health") > 0 )
  114. {
  115. GetParent().SetHealth(damage_zone,"Health",0);
  116. }
  117. }
  118. void DestroyConnectedParts(string part_name)
  119. {
  120. array<string> parts;// = new array<string>;
  121. parts = GetValidDepenentPartsArray(part_name);
  122. if (parts)
  123. {
  124. for (int i = 0; i < parts.Count(); i++)
  125. {
  126. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction DestroyConnectedParts | " + parts.Get(i));
  127. if (!ExceptionCheck(parts.Get(i)))
  128. DestroyPartServer(null,parts.Get(i),AT_DESTROY_PART,true);
  129. }
  130. }
  131. }
  132. //!Exceptions from 'dependent parts' hierarchy are handled here
  133. bool ExceptionCheck(string part_name)
  134. {
  135. //gate hack
  136. ConstructionPart part = GetConstructionPart(part_name);
  137. if( /*Fence.Cast(m_Parent) && */part.IsGate() )
  138. {
  139. if( GetConstructionPart("wall_base_down").IsBuilt() || GetConstructionPart("wall_base_up").IsBuilt() )
  140. return true;
  141. }
  142. return false;
  143. }
  144. //============================================
  145. // Update construction
  146. //============================================
  147. //update visual
  148. void InitVisuals()
  149. {
  150. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " InitVisuals");
  151. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  152. {
  153. string key = m_ConstructionParts.GetKey( i );
  154. ConstructionPart value = m_ConstructionParts.Get( key );
  155. if ( value.IsBuilt() )
  156. {
  157. ShowConstructionPart( value.GetPartName() );
  158. }
  159. }
  160. }
  161. void UpdateVisuals()
  162. {
  163. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " UpdateVisuals");
  164. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  165. {
  166. string key = m_ConstructionParts.GetKey( i );
  167. ConstructionPart value = m_ConstructionParts.Get( key );
  168. if ( value.IsBuilt() )
  169. {
  170. ShowConstructionPart( value.GetPartName() );
  171. }
  172. else
  173. {
  174. HideConstructionPart( value.GetPartName() );
  175. }
  176. }
  177. }
  178. //update physics (only)
  179. void UpdatePhysics()
  180. {
  181. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " UpdatePhysics m_ConstructionParts=" + m_ConstructionParts.Count());
  182. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  183. {
  184. string key = m_ConstructionParts.GetKey( i );
  185. ConstructionPart value = m_ConstructionParts.Get( key );
  186. if ( value.IsBuilt() )
  187. {
  188. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] GetType=" + m_Parent.GetType() + " i=" + i + " ADD");
  189. ShowConstructionPartPhysics( value.GetPartName() );
  190. }
  191. else
  192. {
  193. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] GetType=" + m_Parent.GetType() + " i=" + i + " RM");
  194. HideConstructionPartPhysics( value.GetPartName() );
  195. }
  196. }
  197. }
  198. void InitBaseState ()
  199. {
  200. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction " + Object.GetDebugName(m_Parent) + " InitBaseState");
  201. InitVisuals();
  202. }
  203. //update construction parts
  204. protected void UpdateConstructionParts()
  205. {
  206. m_ConstructionParts.Clear();
  207. string construction_path = "cfgVehicles" + " " + GetParent().GetType() + " " + "Construction";
  208. if ( GetGame().ConfigIsExisting( construction_path ) )
  209. {
  210. //main parts
  211. for ( int i = 0; i < GetGame().ConfigGetChildrenCount( construction_path ); ++i )
  212. {
  213. string main_part_name;
  214. GetGame().ConfigGetChildName( construction_path, i, main_part_name );
  215. string part_path = construction_path + " " + main_part_name;
  216. //parts
  217. for ( int j = 0; j < GetGame().ConfigGetChildrenCount( part_path ); ++j )
  218. {
  219. string part_name;
  220. GetGame().ConfigGetChildName( part_path, j, part_name );
  221. string name;
  222. GetGame().ConfigGetTextRaw( part_path + " " + part_name + " " + "name", name ); //name
  223. GetGame().FormatRawConfigStringKeys(name);
  224. bool show_on_init = GetGame().ConfigGetInt( part_path + " " + part_name + " " + "show_on_init" ); //show on init
  225. int id = GetGame().ConfigGetInt( part_path + " " + part_name + " " + "id" ); //part id
  226. bool is_base = GetGame().ConfigGetInt( part_path + " " + part_name + " " + "is_base" ); //is base (part)
  227. bool is_gate = GetGame().ConfigGetInt( part_path + " " + part_name + " " + "is_gate" ); //is gate (part)
  228. m_ConstructionParts.Insert( part_name, new ConstructionPart( name, part_name, main_part_name, id, show_on_init, is_base, is_gate, GetRequiredParts(part_name,main_part_name) ) );
  229. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction name=" + name + " part_name=" + part_name + " show=" + show_on_init + " base=" + is_base + " gate=" + is_gate);
  230. }
  231. }
  232. }
  233. }
  234. //============================================
  235. // Parts
  236. //============================================
  237. map<string, ref ConstructionPart> GetConstructionParts()
  238. {
  239. return m_ConstructionParts;
  240. }
  241. ConstructionPart GetConstructionPart( string part_name )
  242. {
  243. return m_ConstructionParts.Get( part_name );
  244. }
  245. //CONSTRUCTION
  246. /*ConstructionPart GetConstructionPartToBuild( string part_name, ItemBase tool )
  247. {
  248. if ( CanBuildPart( part_name, tool ) )
  249. {
  250. return GetConstructionPart( part_name );
  251. }
  252. return NULL;
  253. }*/
  254. bool CanBuildPart( string part_name, ItemBase tool, bool use_tool )
  255. {
  256. if ( !IsPartConstructed( part_name ) && HasRequiredPart( part_name ) && !HasConflictPart( part_name ) && HasMaterials( part_name ) && (!use_tool || CanUseToolToBuildPart( part_name, tool )) && !MaterialIsRuined(part_name) )
  257. {
  258. return true;
  259. }
  260. return false;
  261. }
  262. bool MaterialIsRuined(string part_name)
  263. {
  264. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  265. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  266. if ( GetGame().ConfigIsExisting( cfg_path ) )
  267. {
  268. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  269. for ( int i = 0; i < child_count; i++ )
  270. {
  271. string child_name;
  272. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  273. //get type, quantity from material
  274. string config_path;
  275. string slot_name;
  276. config_path = cfg_path + " " + child_name + " " + "slot_name";
  277. GetGame().ConfigGetText( config_path, slot_name );
  278. config_path = cfg_path + " " + child_name + " " + "quantity";
  279. float quantity = GetGame().ConfigGetFloat( config_path );
  280. config_path = cfg_path + " " + child_name + " " + "lockable";
  281. bool lockable = GetGame().ConfigGetInt( config_path );
  282. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( slot_name ) );
  283. if (attachment.IsRuined())
  284. return true;
  285. }
  286. }
  287. return false;
  288. }
  289. //Get all construction parts that can be build (at that current time)
  290. void GetConstructionPartsToBuild( string main_part_name, out array<ConstructionPart> construction_parts, ItemBase tool, out string real_constructionTarget, bool use_tool )
  291. {
  292. construction_parts.Clear();
  293. string part_name;
  294. ConstructionPart value;
  295. string key;
  296. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  297. {
  298. key = m_ConstructionParts.GetKey( i );
  299. value = m_ConstructionParts.Get( key );
  300. if ( main_part_name == value.GetMainPartName() && CanBuildPart( value.GetPartName(), tool, use_tool ) )
  301. {
  302. construction_parts.Insert( value );
  303. }
  304. if ( main_part_name == value.GetPartName() )
  305. {
  306. part_name = value.GetMainPartName();
  307. }
  308. }
  309. if( construction_parts.Count() == 0 && part_name )
  310. {
  311. for ( i = 0; i < m_ConstructionParts.Count(); ++i )
  312. {
  313. key = m_ConstructionParts.GetKey( i );
  314. value = m_ConstructionParts.Get( key );
  315. if ( part_name == value.GetMainPartName() && CanBuildPart( value.GetPartName(), tool, use_tool ) )
  316. {
  317. construction_parts.Insert( value );
  318. }
  319. }
  320. }
  321. }
  322. //Returns (first found) base construction part
  323. ConstructionPart GetBaseConstructionPart()
  324. {
  325. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  326. {
  327. string key = m_ConstructionParts.GetKey( i );
  328. ConstructionPart value = m_ConstructionParts.Get( key );
  329. if ( value.IsBase() )
  330. {
  331. return value;
  332. }
  333. }
  334. return NULL;
  335. }
  336. //Returns (first found) gate construction part
  337. ConstructionPart GetGateConstructionPart()
  338. {
  339. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  340. {
  341. string key = m_ConstructionParts.GetKey( i );
  342. ConstructionPart value = m_ConstructionParts.Get( key );
  343. if ( value.IsGate() )
  344. {
  345. return value;
  346. }
  347. }
  348. return NULL;
  349. }
  350. //checks if construction part has required part already built
  351. protected bool HasRequiredPart( string part_name )
  352. {
  353. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  354. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "required_parts";
  355. ref array<string> required_parts = new array<string>;
  356. GetGame().ConfigGetTextArray( cfg_path, required_parts );
  357. //check if parts are already built
  358. for ( int i = 0; i < required_parts.Count(); ++i )
  359. {
  360. if ( !IsPartConstructed( required_parts.Get( i ) ) )
  361. {
  362. return false;
  363. }
  364. //hack - gate
  365. /*else if (part_name == "wall_gate" && (IsPartConstructed("wall_base_down") || IsPartConstructed("wall_base_up")))
  366. {
  367. return true;
  368. }*/
  369. }
  370. return true;
  371. }
  372. //checks if there are conflict parts already built
  373. protected bool HasConflictPart( string part_name )
  374. {
  375. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  376. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "conflicted_parts";
  377. ref array<string> conflict_parts = new array<string>;
  378. GetGame().ConfigGetTextArray( cfg_path, conflict_parts );
  379. //check if parts are already built
  380. for ( int i = 0; i < conflict_parts.Count(); i++ )
  381. {
  382. if ( IsPartConstructed( conflict_parts.Get( i ) ) )
  383. {
  384. return true;
  385. }
  386. }
  387. return false;
  388. }
  389. //DECONSTRUCTION
  390. ConstructionPart GetConstructionPartToDismantle( string part_name, ItemBase tool )
  391. {
  392. if ( CanDismantlePart( part_name, tool ) )
  393. {
  394. return GetConstructionPart( part_name );
  395. }
  396. return NULL;
  397. }
  398. bool CanDismantlePart( string part_name, ItemBase tool )
  399. {
  400. if ( IsPartConstructed( part_name ) && !HasDependentPart( part_name ) && CanUseToolToDismantlePart( part_name, tool ) )
  401. {
  402. return true;
  403. }
  404. return false;
  405. }
  406. //checks if construction part has dependent part (that is already built) because of which it cannot be deconstruct
  407. //TODO return whole array of dependent parts/dependencies (one or the other), should be used to eventually destroy all dependent parts instead
  408. bool HasDependentPart( string part_name )
  409. {
  410. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  411. {
  412. string key = m_ConstructionParts.GetKey( i );
  413. ConstructionPart construction_part = m_ConstructionParts.Get( key );
  414. if ( construction_part.IsBuilt() )
  415. {
  416. if ( construction_part.GetRequiredParts().Find( part_name ) > -1 )
  417. {
  418. return true;
  419. }
  420. }
  421. }
  422. return false;
  423. }
  424. //returns array of BUILT parts that directly depend on 'part_name'
  425. protected array<string> GetValidDepenentPartsArray( string part_name, array<string> recurs = null )
  426. {
  427. string name;
  428. string cfg_path;
  429. ref array<string> dependent_parts;
  430. for ( int i = 0; i < m_ConstructionParts.Count(); ++i )
  431. {
  432. name = m_ConstructionParts.GetKey( i );
  433. ConstructionPart construction_part = m_ConstructionParts.Get( name );
  434. if ( construction_part.IsBuilt() && construction_part.GetRequiredParts() && construction_part.GetRequiredParts().Find( part_name ) > -1 ) //does the construction part need 'part_name' to exist?
  435. {
  436. if ( !dependent_parts )
  437. {
  438. dependent_parts = new array<string>;
  439. }
  440. if ( !recurs || (recurs.Find(name) == -1 ) )
  441. {
  442. dependent_parts.Insert(name);
  443. }
  444. // Print("part #" + i + ": " + name);
  445. }
  446. }
  447. //fully recursive search, disconnected (unnescessary)
  448. /*if (dependent_parts)
  449. {
  450. if ( dependent_parts.Count() > 0 )
  451. {
  452. ref array<string> temp = new array<string>;
  453. for ( i = 0; i < dependent_parts.Count(); i++ )
  454. {
  455. temp = GetValidDepenentPartsArray(dependent_parts.Get(i),dependent_parts);
  456. if (temp.Count() > 0)
  457. {
  458. dependent_parts.InsertAll(temp);
  459. }
  460. }
  461. }
  462. Print("dependent_parts.Count(): " + dependent_parts.Count());
  463. }*/
  464. return dependent_parts;
  465. }
  466. //gets all required parts of a construction part; fills into ConstructionPart on init
  467. array<string> GetRequiredParts( string part_name, string main_part_name )
  468. {
  469. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " " + "Construction" + " " + main_part_name + " " + part_name + " " + "required_parts";
  470. ref array<string> required_parts = new array<string>;
  471. GetGame().ConfigGetTextArray( cfg_path, required_parts );
  472. return required_parts;
  473. }
  474. //DESTROY
  475. ConstructionPart GetConstructionPartToDestroy( string part_name )
  476. {
  477. if ( CanDestroyPart( part_name ) )
  478. {
  479. return GetConstructionPart( part_name );
  480. }
  481. return NULL;
  482. }
  483. bool CanDestroyPart( string part_name )
  484. {
  485. if ( IsPartConstructed( part_name ) && !HasDependentPart( part_name ) )
  486. {
  487. return true;
  488. }
  489. return false;
  490. }
  491. //CONSTRUCTION PART STATE
  492. //show/hide construction part
  493. protected void ShowConstructionPart( string part_name )
  494. {
  495. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction ShowConstructionPart - " + part_name);
  496. GetParent().SetAnimationPhase( part_name, 0 );
  497. }
  498. protected void HideConstructionPart( string part_name )
  499. {
  500. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] Construction HideConstructionPart - " + part_name);
  501. GetParent().SetAnimationPhase( part_name, 1 );
  502. }
  503. //show/hide physics
  504. void ShowConstructionPartPhysics( string part_name )
  505. {
  506. GetParent().AddProxyPhysics( part_name );
  507. }
  508. void HideConstructionPartPhysics( string part_name )
  509. {
  510. GetParent().RemoveProxyPhysics( part_name );
  511. }
  512. //is part constructed
  513. bool IsPartConstructed( string part_name )
  514. {
  515. ConstructionPart construction_part = GetConstructionPart( part_name );
  516. if ( construction_part && construction_part.IsBuilt() )
  517. {
  518. return true;
  519. }
  520. return false;
  521. }
  522. //============================================
  523. // Materials for construction
  524. //============================================
  525. //has materials
  526. bool HasMaterials( string part_name, bool repairing = false )
  527. {
  528. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  529. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  530. if ( GetGame().ConfigIsExisting( cfg_path ) )
  531. {
  532. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  533. for ( int i = 0; i < child_count; i++ )
  534. {
  535. string child_name;
  536. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  537. //get type, quantity from material
  538. string material_path;
  539. string slot_name;
  540. float quantity;
  541. material_path = cfg_path + " " + child_name + " " + "slot_name";
  542. GetGame().ConfigGetText( material_path, slot_name );
  543. material_path = cfg_path + " " + child_name + " " + "quantity";
  544. quantity = GetGame().ConfigGetFloat( material_path );
  545. if (repairing)
  546. {
  547. quantity *= REPAIR_MATERIAL_PERCENTAGE;
  548. quantity = Math.Max(Math.Floor(quantity),1);
  549. }
  550. //if the selected material (or its quantity) is not available
  551. if ( !HasMaterialWithQuantityAttached( slot_name, quantity ) )
  552. {
  553. return false;
  554. }
  555. }
  556. }
  557. return true; //return true even if no material required
  558. }
  559. //check if parent object has attachment of required quantity attached to it
  560. protected bool HasMaterialWithQuantityAttached( string slot_name, float quantity )
  561. {
  562. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( slot_name ) );
  563. if ( attachment && attachment.GetQuantity() >= quantity )
  564. {
  565. return true;
  566. }
  567. return false;
  568. }
  569. //take materials when building
  570. void TakeMaterialsServer( string part_name, bool repairing = false )
  571. {
  572. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  573. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  574. if ( GetGame().ConfigIsExisting( cfg_path ) )
  575. {
  576. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  577. for ( int i = 0; i < child_count; i++ )
  578. {
  579. string child_name;
  580. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  581. //get type, quantity from material
  582. string config_path;
  583. string slot_name;
  584. config_path = cfg_path + " " + child_name + " " + "slot_name";
  585. GetGame().ConfigGetText( config_path, slot_name );
  586. config_path = cfg_path + " " + child_name + " " + "quantity";
  587. float quantity = GetGame().ConfigGetFloat( config_path );
  588. config_path = cfg_path + " " + child_name + " " + "lockable";
  589. bool lockable = GetGame().ConfigGetInt( config_path );
  590. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( slot_name ) );
  591. if ( lockable )
  592. {
  593. //lock attachment
  594. InventoryLocation inventory_location = new InventoryLocation;
  595. attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
  596. GetParent().GetInventory().SetSlotLock( inventory_location.GetSlot(), true );
  597. }
  598. else
  599. {
  600. if ( quantity > -1 ) //0 - ignores quantity
  601. {
  602. if (repairing)
  603. {
  604. quantity *= REPAIR_MATERIAL_PERCENTAGE;
  605. quantity = Math.Max(Math.Floor(quantity),1);
  606. }
  607. //subtract quantity
  608. attachment.AddQuantity( -quantity );
  609. }
  610. else //-1 - deletes the object
  611. {
  612. GetGame().ObjectDelete( attachment );
  613. }
  614. }
  615. }
  616. }
  617. }
  618. //receive materials when dismantling
  619. protected void ReceiveMaterialsServer( notnull Man player, string part_name, string damagezone_name )
  620. {
  621. ConstructionPart construction_part = GetConstructionPart( part_name );
  622. bool is_base = construction_part.IsBase();
  623. string main_part_name = construction_part.GetMainPartName();
  624. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  625. if ( GetGame().ConfigIsExisting( cfg_path ) )
  626. {
  627. StaticConstructionMethods.SpawnConstructionMaterialPiles(GetParent(),player,cfg_path,part_name,damagezone_name,is_base);
  628. }
  629. }
  630. //destroy lockable materials when destroying
  631. protected void DestroyMaterialsServer( Man player, string part_name )
  632. {
  633. ConstructionPart cPart = GetConstructionPart( part_name );
  634. string main_part_name = cPart.GetMainPartName();
  635. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  636. if ( GetGame().ConfigIsExisting( cfg_path ) )
  637. {
  638. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  639. for ( int i = 0; i < child_count; i++ )
  640. {
  641. string child_name;
  642. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  643. //get type, quantity from material
  644. string config_path;
  645. string type;
  646. string slot_name;
  647. config_path = cfg_path + " " + child_name + " " + "type";
  648. GetGame().ConfigGetText( config_path, type );
  649. config_path = cfg_path + " " + child_name + " " + "slot_name";
  650. GetGame().ConfigGetText( config_path, slot_name );
  651. config_path = cfg_path + " " + child_name + " " + "quantity";
  652. float quantity = GetGame().ConfigGetFloat( config_path );
  653. config_path = cfg_path + " " + child_name + " " + "lockable";
  654. bool lockable = GetGame().ConfigGetInt( config_path );
  655. //get material
  656. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( slot_name ) );
  657. //material still attached
  658. if ( lockable ) //if lockable
  659. {
  660. if ( attachment )
  661. {
  662. InventoryLocation inventory_location = new InventoryLocation;
  663. attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
  664. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] " + Object.GetDebugName(GetParent()) + " DestroyMaterialsServer unlock slot=" + inventory_location.GetSlot());
  665. GetParent().GetInventory().SetSlotLock( inventory_location.GetSlot() , false );
  666. GetGame().ObjectDelete( attachment ); //delete object
  667. }
  668. }
  669. }
  670. }
  671. }
  672. void DropNonUsableMaterialsServer( Man player, string part_name )
  673. {
  674. ConstructionPart construction_part = GetConstructionPart( part_name );
  675. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " " + "Construction" + " " + construction_part.GetMainPartName() + " " + construction_part.GetPartName() + " " + "platform_support";
  676. string platform_support;
  677. if ( GetGame().ConfigIsExisting( cfg_path ) )
  678. {
  679. GetGame().ConfigGetText( cfg_path, platform_support );
  680. }
  681. if ( platform_support.Length() > 0 || construction_part.IsBase() )
  682. {
  683. string at_cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "GUIInventoryAttachmentsProps";
  684. if ( GetGame().ConfigIsExisting( at_cfg_path ) )
  685. {
  686. int child_count = GetGame().ConfigGetChildrenCount( at_cfg_path );
  687. for ( int i = 0; i < child_count; i++ )
  688. {
  689. string child_name;
  690. GetGame().ConfigGetChildName( at_cfg_path, i, child_name );
  691. child_name.ToLower();
  692. if ( child_name.Contains( platform_support ) )
  693. {
  694. ref array<string> attachment_slots = new array<string>;
  695. GetGame().ConfigGetTextArray( at_cfg_path + " " + child_name + " " + "attachmentSlots", attachment_slots );
  696. for ( int j = 0; j < attachment_slots.Count(); ++j )
  697. {
  698. //get material
  699. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( attachment_slots.Get( j ) ) );
  700. //material still attached
  701. if ( attachment )
  702. {
  703. InventoryLocation inventory_location = new InventoryLocation;
  704. attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
  705. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] " + Object.GetDebugName(GetParent()) + " DropNonUsableMaterials UNlocking slot=" + inventory_location.GetSlot());
  706. //unlock slot
  707. GetParent().GetInventory().SetSlotLock( inventory_location.GetSlot() , false );
  708. EntityAI parent = GetParent();
  709. if (!parent)
  710. parent = player;
  711. int quantity_max = attachment.GetTargetQuantityMax(-1);
  712. InventoryLocation dst = new InventoryLocation;
  713. vector mat[4];
  714. attachment.GetTransform(mat);
  715. if ( parent.MemoryPointExists("" + part_name + "_materials") )
  716. {
  717. vector destination = parent.GetMemoryPointPos("" + part_name + "_materials");
  718. destination = GetGame().ObjectModelToWorld(parent,destination);
  719. float health = attachment.GetHealth("","Health");
  720. float quantity = attachment.GetQuantity() - 1;
  721. if (quantity < 1.0)
  722. quantity = 1.0;
  723. float dir[4];
  724. inventory_location.GetDir(dir);
  725. dst.SetGroundEx(attachment,destination,dir);
  726. //Print(dst.DumpToString());
  727. MiscGameplayFunctions.CreateItemBasePiles(attachment.GetType(),destination,quantity,health,true);
  728. attachment.AddQuantity( -quantity );
  729. }
  730. else
  731. {
  732. dst.SetGround(attachment,mat);
  733. for ( int k = attachment.GetQuantity(); k > quantity_max; )
  734. {
  735. Object o = parent.GetInventory().LocationCreateEntity( dst, attachment.GetType(), ECE_PLACE_ON_SURFACE, RF_DEFAULT );
  736. ItemBase new_item = ItemBase.Cast( o );
  737. if( new_item )
  738. {
  739. MiscGameplayFunctions.TransferItemProperties( attachment, new_item );
  740. attachment.AddQuantity( -quantity_max );
  741. new_item.SetQuantity( quantity_max );
  742. }
  743. k -= quantity_max;
  744. }
  745. }
  746. //drop
  747. if (attachment.GetQuantity() > 0)
  748. {
  749. if ( GetGame().IsMultiplayer() )
  750. {
  751. parent.ServerTakeToDst( inventory_location, dst );
  752. }
  753. else
  754. {
  755. parent.LocalTakeToDst( inventory_location, dst );
  756. }
  757. }
  758. else
  759. {
  760. attachment.Delete();
  761. }
  762. }
  763. }
  764. }
  765. }
  766. }
  767. }
  768. }
  769. //set lock on materials that are attached and cannot be locked/unlocked
  770. void SetLockOnAttachedMaterials( string part_name, bool lock_slot )
  771. {
  772. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  773. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "Materials";
  774. if ( GetGame().ConfigIsExisting( cfg_path ) )
  775. {
  776. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  777. for ( int i = 0; i < child_count; i++ )
  778. {
  779. string child_name;
  780. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  781. //get type, quantity from material
  782. string config_path;
  783. string type;
  784. string slot_name;
  785. config_path = cfg_path + " " + child_name + " " + "type";
  786. GetGame().ConfigGetText( config_path, type );
  787. config_path = cfg_path + " " + child_name + " " + "slot_name";
  788. GetGame().ConfigGetText( config_path, slot_name );
  789. config_path = cfg_path + " " + child_name + " " + "quantity";
  790. float quantity = GetGame().ConfigGetFloat( config_path );
  791. config_path = cfg_path + " " + child_name + " " + "lockable";
  792. bool lockable = GetGame().ConfigGetInt( config_path );
  793. //get material
  794. ItemBase attachment = ItemBase.Cast( GetParent().FindAttachmentBySlotName( slot_name ) );
  795. //material still attached
  796. if ( lockable ) //if lockable
  797. {
  798. if ( attachment )
  799. {
  800. InventoryLocation inventory_location = new InventoryLocation;
  801. attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
  802. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] " + Object.GetDebugName(GetParent()) + " SetLockOnAttachedMaterials lock=" + lock_slot +" slot=" + inventory_location.GetSlot());
  803. GetParent().GetInventory().SetSlotLock( inventory_location.GetSlot(), lock_slot );
  804. }
  805. }
  806. }
  807. }
  808. }
  809. //============================================
  810. // Construction tools
  811. //============================================
  812. bool CanUseToolToBuildPart( string part_name, ItemBase tool )
  813. {
  814. ConstructionPart construction_part = GetConstructionPart( part_name );
  815. string part_cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + construction_part.GetMainPartName() + " " + construction_part.GetPartName() + " " + "build_action_type";
  816. if ( GetGame().ConfigIsExisting( part_cfg_path ) )
  817. {
  818. int part_build_action_type = GetGame().ConfigGetInt( part_cfg_path );
  819. string tool_cfg_path = "cfgVehicles" + " " + tool.GetType() + " " + "build_action_type";
  820. if ( GetGame().ConfigIsExisting( tool_cfg_path ) )
  821. {
  822. int tool_build_action_type = GetGame().ConfigGetInt( tool_cfg_path );
  823. if ( ( part_build_action_type & tool_build_action_type ) > 0 )
  824. {
  825. return true;
  826. }
  827. }
  828. }
  829. return false;
  830. }
  831. bool CanUseToolToDismantlePart( string part_name, ItemBase tool )
  832. {
  833. ConstructionPart construction_part = GetConstructionPart( part_name );
  834. string part_cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + construction_part.GetMainPartName() + " " + construction_part.GetPartName() + " " + "dismantle_action_type";
  835. if ( GetGame().ConfigIsExisting( part_cfg_path ) )
  836. {
  837. int part_dismantle_action_type = GetGame().ConfigGetInt( part_cfg_path );
  838. string tool_cfg_path = "cfgVehicles" + " " + tool.GetType() + " " + "dismantle_action_type";
  839. if ( GetGame().ConfigIsExisting( tool_cfg_path ) )
  840. {
  841. int tool_dismantle_action_type = GetGame().ConfigGetInt( tool_cfg_path );
  842. if ( ( part_dismantle_action_type & tool_dismantle_action_type ) > 0 )
  843. {
  844. return true;
  845. }
  846. }
  847. }
  848. return false;
  849. }
  850. ConstructionMaterialType GetMaterialType( string part_name )
  851. {
  852. ConstructionPart construction_part = GetConstructionPart( part_name );
  853. string part_cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + construction_part.GetMainPartName() + " " + construction_part.GetPartName() + " " + "material_type";
  854. if ( GetGame().ConfigIsExisting( part_cfg_path ) )
  855. {
  856. return GetGame().ConfigGetInt( part_cfg_path );
  857. }
  858. return ConstructionMaterialType.MATERIAL_NONE;
  859. }
  860. //============================================
  861. // Collision check
  862. //============================================
  863. //Collisions (BBox and Trigger); deprecated
  864. bool IsColliding( string part_name )
  865. {
  866. if (CfgGameplayHandler.GetDisableIsCollidingCheck())
  867. return false;
  868. ConstructionPart construction_part = GetConstructionPart( part_name );
  869. if ( construction_part )
  870. {
  871. vector center;
  872. float absolute_ofset = 0.05; //we need to lift BBox even more, because it colliddes with house floors due to various reasons (probably geometry or float imperfections)
  873. vector edge_length;
  874. vector min_max[2]; //data used for creating trigger
  875. ref array<Object> excluded_objects = new array<Object>;
  876. ref array<Object> collided_objects = new array<Object>;
  877. excluded_objects.Insert( GetParent() );
  878. //get min_max and center from config and memory points
  879. GetCollisionBoxData( part_name, min_max );
  880. center = GetBoxCenter( min_max );
  881. center = GetParent().ModelToWorld( center ); //convert to world coordinates
  882. edge_length = GetCollisionBoxSize( min_max );
  883. //Create trigger
  884. //CreateCollisionTrigger( part_name, min_max, center );
  885. //check collision on box trigger and collision box
  886. //IsTrigger colliding was turned off (for now) for easier way to build something with other players around
  887. if ( /* IsTriggerColliding() || */ GetGame().IsBoxCollidingGeometry( Vector( center[0], center[1] + absolute_ofset, center[2] ), GetParent().GetOrientation(), edge_length, ObjIntersectView, ObjIntersectGeom, excluded_objects, collided_objects ) )
  888. {
  889. //Debug
  890. // DrawDebugCollisionBox( min_max, ARGB( 150, 255, 0, 0 ) );
  891. //
  892. for (int i = 0; i < collided_objects.Count(); i++)
  893. {
  894. //Print(collided_objects.Get(i).GetType());
  895. EntityAI entity = EntityAI.Cast(collided_objects.Get(i));
  896. if ( entity && !entity.IsIgnoredByConstruction() )
  897. return true;
  898. }
  899. }
  900. //Debug
  901. // DrawDebugCollisionBox( min_max, ARGB( 150, 255, 255, 255 ) );
  902. }
  903. return false;
  904. }
  905. //! Collision check for building part
  906. bool IsCollidingEx( CollisionCheckData check_data )
  907. {
  908. if (CfgGameplayHandler.GetDisableIsCollidingCheck())
  909. return false;
  910. ConstructionPart construction_part = GetConstructionPart( check_data.m_PartName );
  911. if ( construction_part )
  912. {
  913. vector center;
  914. float absolute_ofset = 0.05; //we need to lift BBox even more, because it colliddes with house floors due to various reasons (probably geometry or float imperfections)
  915. vector edge_length;
  916. vector min_max[2]; //data used for creating trigger
  917. ref array<Object> excluded_objects = new array<Object>;
  918. ref array<Object> collided_objects = new array<Object>;
  919. excluded_objects.Insert( GetParent() );
  920. if (check_data.m_AdditionalExcludes.Count() > 0)
  921. {
  922. excluded_objects.InsertAll(check_data.m_AdditionalExcludes);
  923. }
  924. GetCollisionBoxData( check_data.m_PartName, min_max );
  925. center = GetBoxCenter( min_max );
  926. center = GetParent().ModelToWorld( center ); //convert to world coordinates
  927. edge_length = GetCollisionBoxSize( min_max );
  928. if ( GetGame().IsBoxCollidingGeometry( Vector( center[0], center[1] + absolute_ofset, center[2] ), GetParent().GetOrientation(), edge_length, check_data.m_PrimaryGeometry, check_data.m_SecondaryGeometry, excluded_objects, collided_objects ) )
  929. {
  930. //Debug
  931. //DrawDebugCollisionBox( min_max, ARGB( 150, 255, 0, 0 ) );
  932. for (int i = 0; i < collided_objects.Count(); i++)
  933. {
  934. EntityAI entity = EntityAI.Cast(collided_objects.Get(i));
  935. if ( entity && !entity.IsIgnoredByConstruction() )
  936. return true;
  937. }
  938. }
  939. //Debug
  940. //DrawDebugCollisionBox( min_max, ARGB( 150, 255, 255, 255 ) );
  941. }
  942. return false;
  943. }
  944. vector GetCollisionBoxSize( vector min_max[2] )
  945. {
  946. vector box_size = Vector( 0, 0, 0 );
  947. box_size[0] = Math.AbsFloat( min_max[1][0] - min_max[0][0] );
  948. box_size[1] = Math.AbsFloat( min_max[1][1] - min_max[0][1] );
  949. box_size[2] = Math.AbsFloat( min_max[1][2] - min_max[0][2] );
  950. return box_size;
  951. }
  952. //returns collision box data from construction config and model p3d
  953. protected void GetCollisionBoxData( string part_name, out vector min_max[2] )
  954. {
  955. string main_part_name = GetConstructionPart( part_name ).GetMainPartName();
  956. string cfg_path = "cfgVehicles" + " " + GetParent().GetType() + " "+ "Construction" + " " + main_part_name + " " + part_name + " " + "collision_data";
  957. ref array<string> collision_data = new array<string>;
  958. GetGame().ConfigGetTextArray( cfg_path, collision_data );
  959. if ( collision_data.Count() > 0 )
  960. {
  961. if ( GetParent().MemoryPointExists( collision_data[0] ) )
  962. {
  963. min_max[0] = GetParent().GetMemoryPointPos( collision_data[0] );
  964. }
  965. if ( GetParent().MemoryPointExists( collision_data[1] ) )
  966. {
  967. min_max[1] = GetParent().GetMemoryPointPos( collision_data[1] );
  968. }
  969. }
  970. }
  971. //returns center point of box defined by min/max values
  972. vector GetBoxCenter( vector min_max[2] )
  973. {
  974. vector center;
  975. center[0] = ( min_max[1][0] - min_max[0][0] ) / 2;
  976. center[1] = ( min_max[1][1] - min_max[0][1] ) / 2;
  977. center[2] = ( min_max[1][2] - min_max[0][2] ) / 2;
  978. center = Vector( min_max[1][0] - center[0], min_max[1][1] - center[1], min_max[1][2] - center[2] ); //offset to box center
  979. return center;
  980. }
  981. void GetTriggerExtents( vector min_max[2], out vector extents[2] )
  982. {
  983. vector egde_length = GetCollisionBoxSize( min_max );
  984. extents[0][0] = -egde_length[0] / 2; //min
  985. extents[0][1] = -egde_length[1] / 2;
  986. extents[0][2] = -egde_length[2] / 2;
  987. extents[1][0] = egde_length[0] / 2; //max
  988. extents[1][1] = egde_length[1] / 2;
  989. extents[1][2] = egde_length[2] / 2;
  990. }
  991. //Debug
  992. protected void DrawDebugCollisionBox( vector min_max[2], int color )
  993. {
  994. DestroyDebugCollisionBox();
  995. vector mat[4];
  996. GetParent().GetTransform( mat );
  997. m_CollisionBox = Debug.DrawBox( min_max[0], min_max[1], color );
  998. m_CollisionBox.SetMatrix( mat );
  999. }
  1000. protected void DestroyDebugCollisionBox()
  1001. {
  1002. if ( m_CollisionBox )
  1003. {
  1004. m_CollisionBox.Destroy();
  1005. m_CollisionBox = NULL;
  1006. }
  1007. }
  1008. void CreateCollisionTrigger( string part_name, vector min_max[2], vector center )
  1009. {
  1010. if ( m_ConstructionBoxTrigger )
  1011. {
  1012. if ( m_ConstructionBoxTrigger.GetPartName() == part_name ) //already created
  1013. {
  1014. return;
  1015. }
  1016. else
  1017. {
  1018. DestroyCollisionTrigger();
  1019. }
  1020. }
  1021. //get proper trigger extents (min<max)
  1022. vector extents[2];
  1023. GetTriggerExtents( min_max, extents );
  1024. //create trigger
  1025. m_ConstructionBoxTrigger = ConstructionBoxTrigger.Cast( GetGame().CreateObject( "ConstructionBoxTrigger", center, false, false, false ) );
  1026. m_ConstructionBoxTrigger.SetPosition( center );
  1027. m_ConstructionBoxTrigger.SetOrientation( GetParent().GetOrientation() );
  1028. m_ConstructionBoxTrigger.SetExtents( extents[0], extents[1] );
  1029. m_ConstructionBoxTrigger.SetPartName( part_name );
  1030. }
  1031. //
  1032. void DestroyCollisionTrigger()
  1033. {
  1034. GetGame().ObjectDelete( m_ConstructionBoxTrigger );
  1035. m_ConstructionBoxTrigger = NULL;
  1036. }
  1037. bool IsTriggerColliding()
  1038. {
  1039. return m_ConstructionBoxTrigger.IsColliding();
  1040. }
  1041. }
  1042. class StaticConstructionMethods
  1043. {
  1044. //! spawns material from any construction; 'player' parameter optional
  1045. static void SpawnConstructionMaterialPiles(notnull EntityAI entity, Man player, string cfg_path, string main_part_name, string damagezone_name = "", bool is_base = false )
  1046. {
  1047. int child_count = GetGame().ConfigGetChildrenCount( cfg_path );
  1048. for ( int i = 0; i < child_count; i++ )
  1049. {
  1050. string child_name;
  1051. GetGame().ConfigGetChildName( cfg_path, i, child_name );
  1052. //get type, quantity from material
  1053. string config_path;
  1054. string type;
  1055. string slot_name;
  1056. config_path = cfg_path + " " + child_name + " " + "type";
  1057. GetGame().ConfigGetText( config_path, type );
  1058. config_path = cfg_path + " " + child_name + " " + "slot_name";
  1059. GetGame().ConfigGetText( config_path, slot_name );
  1060. config_path = cfg_path + " " + child_name + " " + "quantity";
  1061. float quantity = GetGame().ConfigGetFloat( config_path );
  1062. config_path = cfg_path + " " + child_name + " " + "lockable";
  1063. bool lockable = GetGame().ConfigGetInt( config_path );
  1064. //receive material quantity
  1065. ItemBase attachment = ItemBase.Cast( entity.FindAttachmentBySlotName( slot_name ) );
  1066. int slot_id;
  1067. //material still attached
  1068. if ( lockable ) //if lockable
  1069. {
  1070. if ( attachment )
  1071. {
  1072. InventoryLocation src = new InventoryLocation;
  1073. attachment.GetInventory().GetCurrentInventoryLocation( src );
  1074. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] " + Object.GetDebugName( entity) + " DropNonUsableMaterials UNlocking slot=" + src.GetSlot() );
  1075. entity.GetInventory().SetSlotLock( src.GetSlot() , false );
  1076. //detach if base
  1077. if ( is_base )
  1078. {
  1079. if ( GetGame().IsMultiplayer() && player )
  1080. {
  1081. InventoryLocation dst = new InventoryLocation;
  1082. GameInventory.SetGroundPosByOwner( player, src.GetItem(), dst );
  1083. player.ServerTakeToDst( src, dst );
  1084. }
  1085. else
  1086. {
  1087. entity.GetInventory().DropEntity( InventoryMode.PREDICTIVE, entity, attachment );
  1088. }
  1089. }
  1090. }
  1091. }
  1092. else
  1093. {
  1094. float pile_health;
  1095. float qty_coef;
  1096. vector destination = entity.GetPosition();
  1097. //placed on helper memory point, if available
  1098. if ( entity.MemoryPointExists("" + main_part_name + "_materials") )
  1099. {
  1100. destination = entity.GetMemoryPointPos("" + main_part_name + "_materials");
  1101. destination = GetGame().ObjectModelToWorld(entity,destination);
  1102. }
  1103. else if ( entity.MemoryPointExists(main_part_name) )
  1104. {
  1105. destination = entity.GetMemoryPointPos(main_part_name);
  1106. destination = GetGame().ObjectModelToWorld(entity,destination);
  1107. }
  1108. //pile_health = GameConstants.DAMAGE_WORN_VALUE * MiscGameplayFunctions.GetTypeMaxGlobalHealth(type);
  1109. pile_health = entity.GetHealth01(damagezone_name,"Health") * MiscGameplayFunctions.GetTypeMaxGlobalHealth(type);
  1110. qty_coef = 1 - (entity.GetHealthLevel(damagezone_name) * Construction.DECONSTURCT_MATERIAL_LOSS) - Construction.DECONSTURCT_MATERIAL_LOSS;
  1111. quantity *= qty_coef;
  1112. quantity = Math.Max(Math.Floor(quantity),1);
  1113. MiscGameplayFunctions.CreateItemBasePiles(type,destination,quantity,pile_health,true);
  1114. }
  1115. }
  1116. }
  1117. }
  1118. //! Data structure for passing parameters (extendable, modable)
  1119. class CollisionCheckData
  1120. {
  1121. ref array<Object> m_AdditionalExcludes;
  1122. string m_PartName;
  1123. int m_PrimaryGeometry;
  1124. int m_SecondaryGeometry;
  1125. void CollisionCheckData()
  1126. {
  1127. m_AdditionalExcludes = new array<Object>;
  1128. m_PartName = "";
  1129. m_PrimaryGeometry = ObjIntersectGeom;
  1130. m_SecondaryGeometry = ObjIntersectView;
  1131. }
  1132. }
  1133. class ConstructionBoxTrigger : ManTrigger
  1134. {
  1135. string m_PartName;
  1136. void SetPartName( string part_name )
  1137. {
  1138. m_PartName = part_name;
  1139. }
  1140. string GetPartName()
  1141. {
  1142. return m_PartName;
  1143. }
  1144. override protected void UpdateInsiders( int timeout )
  1145. {
  1146. super.UpdateInsiders( 20 );
  1147. }
  1148. bool IsColliding()
  1149. {
  1150. if ( GetInsiders().Count() > 0 )
  1151. {
  1152. return true;
  1153. }
  1154. return false;
  1155. }
  1156. }