object.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439
  1. enum ProcessDirectDamageFlags
  2. {
  3. ALL_TRANSFER,
  4. NO_ATTACHMENT_TRANSFER, //!< Do not transfer damage to attachments
  5. NO_GLOBAL_TRANSFER, //!< Do not transfer damage to global
  6. NO_TRANSFER, //!< NO_ATTACHMENT_TRANSFER | NO_GLOBAL_TRANSFER
  7. }
  8. class ObjectSnapCallback
  9. {
  10. Object m_Owner; //! The owner performing the snap callback
  11. vector m_OwnerPosition; //! The position of the owner in world space
  12. vector m_OwnerDirection; //! The direction of the owner in world space
  13. vector m_Offset; //! The true center of the bounding box of the object to be dropped in model space
  14. vector m_Extents; //! The size of the boundig box, centered
  15. vector m_DirectionFunc; //! How much should the direction be favoured.
  16. bool m_DebugEnabled; //! If 'OnDebug' is to be called
  17. vector m_Transform[4]; //! The transformation currently being debugged
  18. /**@brief Initialization of script variables
  19. *
  20. **/
  21. void OnSetup()
  22. {
  23. }
  24. /**@brief Debug callback for rendering on the screen
  25. **/
  26. void OnDebug(vector p0, vector p1, bool hasHit, bool found)
  27. {
  28. }
  29. /**@brief Called for first layer contacts to determine if this object should be snapped around or default rv raycast placement is fine
  30. * @return True if bounding snap is to be used
  31. *
  32. **/
  33. bool OnFirstContact(Object other)
  34. {
  35. return false;
  36. }
  37. /**@brief Initial query around the owner position to see if an object should be processed in contact testing
  38. * @return True if the object should be counted
  39. *
  40. **/
  41. bool OnQuery(Object other)
  42. {
  43. return true;
  44. }
  45. /**@brief Ray cast line test from owner to a tested position
  46. * @return True if the line test should be broken and make the transformation invalid
  47. *
  48. **/
  49. bool OnCollide(Object other)
  50. {
  51. return true;
  52. }
  53. };
  54. class Object extends IEntity
  55. {
  56. private void ~Object();
  57. private void Object();
  58. bool CanBeSkinned()
  59. {
  60. return false;
  61. }
  62. /**@brief Delete this object in next frame
  63. * @return \p void
  64. *
  65. * @code
  66. * ItemBase item = GetGame().GetPlayer().CreateInInventory("GrenadeRGD5");
  67. * item.Delete();
  68. * @endcode
  69. **/
  70. void Delete()
  71. {
  72. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(GetGame().ObjectDelete, this);
  73. }
  74. proto native void AddProxyPhysics(string proxySelectionName);
  75. proto native void RemoveProxyPhysics(string proxySelectionName);
  76. //! Object entered trigger
  77. void OnEnterTrigger(ScriptedEntity trigger) {}
  78. //! Object left trigger
  79. void OnLeaveTrigger(ScriptedEntity trigger) {}
  80. //! Retrieve all LODS
  81. proto native bool GetLODS(notnull out array<LOD> lods);
  82. //! Retrieve LOD name
  83. proto native owned string GetLODName(LOD lod);
  84. proto native vector GetBoundingCenter();
  85. //! Retrieve LOD by given name
  86. LOD GetLODByName( string name )
  87. {
  88. array<LOD> lods = new array<LOD>;
  89. GetLODS( lods );
  90. for ( int i = 0; i < lods.Count(); ++i )
  91. {
  92. string lod_name = GetLODName( lods.Get( i ) );
  93. lod_name.ToLower();
  94. name.ToLower();
  95. if ( lod_name == name )
  96. {
  97. return lods.Get( i );
  98. }
  99. }
  100. return NULL;
  101. }
  102. //! Returns the hiddenSelections array from the object's config
  103. TStringArray GetHiddenSelections()
  104. {
  105. return HiddenSelectionsData.GetHiddenSelectionsConfig(GetType());
  106. }
  107. //! Returns the hiddenSelectionsTextures array from the object's config
  108. TStringArray GetHiddenSelectionsTextures()
  109. {
  110. return HiddenSelectionsData.GetHiddenSelectionsTexturesConfig(GetType());
  111. }
  112. //! Returns the hiddenSelectionsMaterials array from the object's config
  113. TStringArray GetHiddenSelectionsMaterials()
  114. {
  115. return HiddenSelectionsData.GetHiddenSelectionsMaterialsConfig(GetType());
  116. }
  117. //! Creates an explosion on this object by its ammoType in config.
  118. void Explode(int damageType, string ammoType = "")
  119. {
  120. if (ammoType == "")
  121. ammoType = ConfigGetString("ammoType");
  122. if (ammoType == "")
  123. ammoType = "Dummy_Heavy";
  124. if ( GetGame().IsServer() )
  125. {
  126. SynchExplosion();
  127. DamageSystem.ExplosionDamage(EntityAI.Cast(this), null, ammoType, GetPosition(), damageType);
  128. }
  129. }
  130. void SynchExplosion()
  131. {
  132. if ( GetGame().IsDedicatedServer() ) // Multiplayer server
  133. {
  134. Param1<EntityAI> p = new Param1<EntityAI>(null);
  135. GetGame().RPCSingleParam( this, ERPCs.RPC_EXPLODE_EVENT, p, true);
  136. }
  137. else if ( !GetGame().IsMultiplayer() ) // Singleplayer
  138. {
  139. OnExplodeClient();
  140. }
  141. }
  142. //! Called on clients when this object explodes
  143. void OnExplodeClient()
  144. {
  145. string ammoType = ConfigGetString("ammoType");
  146. if (ammoType == "")
  147. ammoType = "Dummy_Heavy";
  148. vector pos = GetPosition();
  149. // Handle spawn of particle if one is configured in config
  150. AmmoEffects.PlayAmmoParticle(ammoType, pos);
  151. // Handle spawn of Effect if one is configured in config
  152. AmmoEffects.PlayAmmoEffect(ammoType, pos);
  153. }
  154. void OnExplosionEffects(Object source, Object directHit, int componentIndex, string surface, vector pos, vector surfNormal, float energyFactor, float explosionFactor, bool isWater, string ammoType) { }
  155. //! returns action component name by given component index, 'geometry' can be "fire" or "view" (default "" for mixed/legacy mode)
  156. proto native owned string GetActionComponentName(int componentIndex, string geometry = "");
  157. //! returns action component position by given component index, 'geometry' can be "fire" or "view" (default "" for mixed/legacy mode)
  158. proto native owned vector GetActionComponentPosition(int componentIndex, string geometry = "");
  159. //! outputs action component name list by given component index, 'geometry' can be "fire" or "view" (default "" for mixed/legacy mode). Returns -1 (not found), 0 (found default component only), or 1 (found named component)
  160. proto native owned int GetActionComponentNameList(int componentIndex, TStringArray nameList, string geometry = "");
  161. //! return true if selection containts action component, 'geometry' can be "fire" or "view" (default "" for mixed/legacy mode)
  162. proto native bool IsActionComponentPartOfSelection(int componentIndex, string selectionName, string geometry = "");
  163. //! outputs action component index list by given selection, 'geometry' can be "fire" or "view" (default "" for mixed/legacy mode)
  164. proto void GetActionComponentsForSelectionName(int level, string selectionName, TIntArray componentIndices);
  165. //! The center of the component, in model space
  166. proto vector GetActionComponentCenter(int level, int componentIndex);
  167. //! The center of the component, in model space
  168. proto vector GetActionComponentCenterOOB(int level, int componentIndex);
  169. //! The AABB of the component
  170. proto void GetActionComponentMinMax(int level, int componentIndex, out vector min, out vector max);
  171. //! Flag to determine this object is marked to be deleted soon
  172. proto native bool ToDelete();
  173. //! Determine whether this object is in the deletion ProcessDirectDamage
  174. //! Is useful in the case where a parent is being deleted, since the children will be deleted first
  175. //! So to know if something was removed or detached from it's parent, use this check to see if it is because the parent is being deleted
  176. proto native bool IsPendingDeletion();
  177. //! Native functions for getting the level used for calculating the pivot
  178. proto native int GetGeometryLevel();
  179. proto native int GetFireGeometryLevel();
  180. proto native int GetViewGeometryLevel();
  181. proto native int GetMemoryLevel();
  182. #ifdef DEVELOPER
  183. //! Conversion between enfusion and RV bone formats for hierarchy
  184. proto bool ToBonePivot(out int pivot, int level, int bone);
  185. proto bool FromBonePivot(int pivot, out int level, out int bone);
  186. #endif
  187. //! Get the pivot point of the bone from the component index in the LOD, level can be geometry, fire, view or memory
  188. proto int GetBonePivot(int level, int component);
  189. //! Get the pivots assigned to the animation source at the specified LOD
  190. proto native void GetBonePivotsForAnimationSource(int level, string animationSource, out TIntArray pivots);
  191. //! returns local space, model space, world space position of the bone
  192. proto native vector GetBonePositionLS(int pivot);
  193. proto native vector GetBonePositionMS(int pivot);
  194. proto native vector GetBonePositionWS(int pivot);
  195. //! returns local space, model space, world space orientation (quaternion) of a bone
  196. proto native void GetBoneRotationLS(int pivot, out float quaternion[4]);
  197. proto native void GetBoneRotationMS(int pivot, out float quaternion[4]);
  198. proto native void GetBoneRotationWS(int pivot, out float quaternion[4]);
  199. //! returns local space, model space, world space transformations of a bone
  200. proto native void GetBoneTransformLS(int pivot, out vector transform[4]);
  201. proto native void GetBoneTransformMS(int pivot, out vector transform[4]);
  202. proto native void GetBoneTransformWS(int pivot, out vector transform[4]);
  203. /**
  204. \brief Get corner positions in worldspace aligned to the orientation of the object (currently only TOP/BOTTOM supported)
  205. @param axis The axis the object is aligned to
  206. @param corners array[4] of vector, each a corner aligned to the axis ({0,0}, {0,1}, {1,0}, {1,1})
  207. \return true if collision box exists, false otherwise
  208. */
  209. proto native void GetTightlyPackedCorners(ETransformationAxis axis, out vector corners[4]);
  210. #ifdef DIAG_DEVELOPER
  211. void DebugDrawTightlyPackedCorners(ETransformationAxis axis, int color)
  212. {
  213. #ifndef SERVER
  214. vector points[2];
  215. vector corners[4];
  216. GetTightlyPackedCorners(axis, corners);
  217. points[0] = corners[0];
  218. points[1] = corners[1];
  219. Shape.CreateLines(color, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, points, 2);
  220. points[0] = corners[1];
  221. points[1] = corners[3];
  222. Shape.CreateLines(color, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, points, 2);
  223. points[0] = corners[3];
  224. points[1] = corners[2];
  225. Shape.CreateLines(color, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, points, 2);
  226. points[0] = corners[2];
  227. points[1] = corners[0];
  228. Shape.CreateLines(color, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, points, 2);
  229. #endif
  230. }
  231. #endif
  232. //! Retrieve position
  233. proto native vector GetPosition();
  234. //! Returns world position.
  235. //! This function takes proxy transformation into account.
  236. proto native vector GetWorldPosition();
  237. //! Set position
  238. proto native void SetPosition(vector vPos);
  239. /**
  240. \brief Place object on surface
  241. */
  242. proto native void PlaceOnSurface();
  243. /**
  244. \brief Retrieve orientation (yaw, pitch, roll) in <b>degrees</b>
  245. \return vector of yaw, pitch and roll angles (x = yaw, y = pitch, z = roll)
  246. */
  247. proto native vector GetOrientation();
  248. /**
  249. \brief Set orientation (yaw, pitch, roll) in <b>degrees</b>
  250. @param vOrientation, vector of yaw, pitch and roll angles (x = yaw, y = pitch, z = roll)
  251. */
  252. proto native void SetOrientation(vector vOrientation);
  253. //! Retrieve direction vector
  254. proto native vector GetDirection();
  255. /**
  256. \brief Set direction of object
  257. @param vDirection, direction vector
  258. \note object up vector is always y-axis
  259. */
  260. proto native void SetDirection(vector vPos);
  261. //! Retrieve direction up vector
  262. proto native vector GetDirectionUp();
  263. //! Retrieve direction aside vector
  264. proto native vector GetDirectionAside();
  265. //! Calculate local position of other entity to this entity
  266. proto native vector GetLocalPos(vector vPos);
  267. //! Calculate global position to this entity from local position
  268. proto native vector GetGlobalPos(vector vPos);
  269. //! Retrieve object's speed in global space
  270. proto native vector GetSpeed();
  271. //! Retrieve object's speed in local space
  272. proto native vector GetModelSpeed();
  273. //! Returns true if object's geometry can affect pathgraph generation
  274. proto native bool CanAffectPathgraph();
  275. //! Sets if object's geometry affects pathgraph generation. If first parameter is true, it ignores second parameter and sets affecting pathgraph by parameter set in object's config
  276. proto native void SetAffectPathgraph(bool fromConfig, bool affect);
  277. /**
  278. \brief Get Clipping info
  279. @param minMax array[2] of vectors, into minMax[0] is returned min, into minMax[1] is returned max
  280. \return radius of bounding box
  281. @code
  282. vector minMax[2];
  283. float radius = GetGame().GetPlayer().ClippingInfo(minMax);
  284. Print(minMax);
  285. Print(radius);
  286. @endcode
  287. */
  288. proto float ClippingInfo(out vector minMax[2]);
  289. /**
  290. \brief Gets collision bounding box
  291. @param minMax array[2] of vectors, into minMax[0] is returned min, into minMax[1] is returned max
  292. \return true if collision box exists, false otherwise
  293. @code
  294. vector minMax[2];
  295. if(GetGame().GetPlayer().GetCollisionBox(minMax))
  296. Print("has box");
  297. @endcode
  298. */
  299. proto native bool GetCollisionBox(out vector minMax[2]);
  300. /**
  301. \brief Gets collision radius (bounding sphere)
  302. \return bounding sphere radius
  303. */
  304. proto native float GetCollisionRadius();
  305. //! Get total damage (clipped to range 0..1)
  306. proto native float GetDamage();
  307. proto native void GetSelectionList(out TStringArray selectionList);
  308. //! Returns noise multiplier of surface under object
  309. float GetSurfaceNoise()
  310. {
  311. vector position = GetPosition();
  312. return GetGame().SurfaceGetNoiseMultiplier(NULL, position, -1);
  313. }
  314. //! Returns type of surface under object
  315. string GetSurfaceType()
  316. {
  317. string surface_type;
  318. int liquid_type;
  319. GetGame().SurfaceUnderObject(this, surface_type,liquid_type);
  320. // Print(surface_type);
  321. // Print(liquid_type);
  322. return surface_type;
  323. }
  324. //! Returns true if the given selection was found in the p3d file. False if otherwise.
  325. bool HasSelection( string selection )
  326. {
  327. TStringArray selections = new TStringArray;
  328. GetSelectionList( selections );
  329. for ( int i = 0; i < selections.Count(); ++i )
  330. {
  331. if ( selections.Get( i ) == selection )
  332. {
  333. return true;
  334. }
  335. }
  336. return false;
  337. }
  338. //! Searches object's config for the given animation name. Returns true if it was found, or false if not.
  339. bool HasAnimation( string anim_name )
  340. {
  341. string cfg_path_vehicles = "CfgVehicles " + GetType() + " ";
  342. if ( GetGame().ConfigIsExisting (cfg_path_vehicles) && GetGame().ConfigIsExisting (cfg_path_vehicles + "AnimationSources " + anim_name) )
  343. {
  344. return true;
  345. }
  346. string cfg_path_weapons = "CfgWeapons " + GetType() + " ";
  347. if ( GetGame().ConfigIsExisting (cfg_path_weapons) && GetGame().ConfigIsExisting (cfg_path_weapons + "AnimationSources " + anim_name) )
  348. {
  349. return true;
  350. }
  351. string cfg_path_magazines = "CfgMagazines " + GetType() + " ";
  352. if ( GetGame().ConfigIsExisting (cfg_path_magazines) && GetGame().ConfigIsExisting (cfg_path_magazines + "AnimationSources " + anim_name) )
  353. {
  354. return true;
  355. }
  356. return false;
  357. }
  358. //! If Returns true if this item has EnergyManager in its config. Otherwise returns false.
  359. /*bool HasEnergyManager()
  360. {
  361. return false;
  362. }*/
  363. proto native int GetMemoryPointIndex(string memoryPointName);
  364. proto native vector GetMemoryPointPos(string memoryPointName);
  365. proto native vector GetMemoryPointPosByIndex(int pointIndex);
  366. proto native bool MemoryPointExists(string memoryPoint);
  367. proto native void CreateDynamicPhysics(int interactionLayers);
  368. proto native void EnableDynamicCCD(bool state);
  369. proto native void SetDynamicPhysicsLifeTime(float lifeTime);
  370. //! Called when tree is chopped down. 'cutting_entity' can be tool, or player, if cutting bush with bare hands
  371. void OnTreeCutDown(EntityAI cutting_entity);
  372. //! Get config class of object
  373. string GetType()
  374. {
  375. string ret;
  376. GetGame().ObjectGetType(this, ret);
  377. return ret;
  378. }
  379. //! Get display name of entity
  380. string GetDisplayName()
  381. {
  382. string tmp;
  383. if (NameOverride(tmp))
  384. {
  385. tmp = Widget.TranslateString(tmp);
  386. }
  387. else
  388. {
  389. GetGame().ObjectGetDisplayName(this, tmp);
  390. }
  391. return tmp;
  392. }
  393. //Used to specify this object will always display it's own name when attached to another object
  394. bool DisplayNameRuinAttach()
  395. {
  396. return false;
  397. }
  398. //! Returns name of the model of this object without the '.p3d' suffix
  399. string GetModelName()
  400. {
  401. return GetGame().GetModelName(GetType());
  402. }
  403. //! Return path and name of the model
  404. proto native owned string GetShapeName();
  405. int Release()
  406. {
  407. return GetGame().ObjectRelease(this);
  408. }
  409. //! Check config class name of the object
  410. bool IsKindOf(string type)
  411. {
  412. return GetGame().ObjectIsKindOf(this, type);
  413. }
  414. // Check alive state
  415. bool IsAlive()
  416. {
  417. return !IsDamageDestroyed();
  418. }
  419. //! Returns if this entity is Man
  420. bool IsMan()
  421. {
  422. return false;
  423. }
  424. //! Checks if this instance is of type DayZCreature
  425. bool IsDayZCreature()
  426. {
  427. return false;
  428. }
  429. //! Returns if this entity is EntityAI
  430. bool IsEntityAI()
  431. {
  432. return false;
  433. }
  434. //! Returns if this entity is Static Transmitter
  435. bool IsStaticTransmitter()
  436. {
  437. return false;
  438. }
  439. //! Returns if this entity is a non-static Transmitter
  440. bool IsTransmitter()
  441. {
  442. return false;
  443. }
  444. //! Returns if this entity is ItemBase
  445. bool IsItemBase()
  446. {
  447. return false;
  448. }
  449. //Returns true for protector cases and similar items. Usually can be nested in other cargo while full, unlike clothing..
  450. bool IsContainer()
  451. {
  452. return false;
  453. }
  454. //! Returns if this entity is Magazine
  455. bool IsMagazine()
  456. {
  457. return false;
  458. }
  459. //! Returns if this entity is Ammo Pile
  460. bool IsAmmoPile()
  461. {
  462. return false;
  463. }
  464. //! Returns if this entity is InventoryItem
  465. bool IsInventoryItem()
  466. {
  467. return false;
  468. }
  469. //! Returns if this entity is Clothing
  470. bool IsClothing()
  471. {
  472. return false;
  473. }
  474. //! Returns if this entity is fireplacebase
  475. bool IsFireplace()
  476. {
  477. return false;
  478. }
  479. //! Returns if this entity is tree
  480. bool IsTree()
  481. {
  482. return false;
  483. }
  484. //! Returns if this entity is rock
  485. bool IsRock()
  486. {
  487. return false;
  488. }
  489. //! Returns whether object is PlanBase
  490. bool IsWoodBase()
  491. {
  492. return false;
  493. }
  494. //! Returns if this entity is bush
  495. bool IsBush()
  496. {
  497. return false;
  498. }
  499. bool IsCuttable()
  500. {
  501. return false;
  502. }
  503. //! Returns if this entity is Pelt_Base
  504. bool IsPeltBase()
  505. {
  506. return false;
  507. }
  508. //! Returns if this entity is Weapon
  509. bool IsWeapon()
  510. {
  511. return false;
  512. }
  513. //! returns if this entity is Melee Weapon
  514. bool IsMeleeWeapon()
  515. {
  516. return false;
  517. }
  518. //! Returns if this entity is Building
  519. bool IsBuilding()
  520. {
  521. return false;
  522. }
  523. EWaterSourceObjectType GetWaterSourceObjectType()
  524. {
  525. return EWaterSourceObjectType.NONE;
  526. }
  527. int GetLiquidSourceType()
  528. {
  529. return LIQUID_NONE;
  530. }
  531. //! Returns if this entity is Well (extends Building)
  532. //! DEPRECATED by GetWaterSourceObjectType
  533. bool IsWell()
  534. {
  535. return false;
  536. }
  537. //! Returns if this entity is a weapon which can shoot explosive ammo
  538. bool ShootsExplosiveAmmo()//placed on Object so that we can optimize early checks in DayZGame without casting
  539. {
  540. return false;
  541. }
  542. //! Returns if this entity is Fuel Station (extends Building)
  543. bool IsFuelStation()
  544. {
  545. return false;
  546. }
  547. //! Returns if this entity is transport
  548. bool IsTransport()
  549. {
  550. return false;
  551. }
  552. //! Returns if this is an appliance, that can be plugged into electric circuit (== not energy source)
  553. bool IsElectricAppliance()
  554. {
  555. return false;
  556. }
  557. //! Returns if this entity can be constucted,deconstructed (e.g. fence,watchtower)
  558. bool CanUseConstruction()
  559. {
  560. return false;
  561. }
  562. //! Returns if this entity can be built, specifically.
  563. bool CanUseConstructionBuild()
  564. {
  565. return false;
  566. }
  567. //! Returns if this entity can be constructed without tools
  568. bool CanUseHandConstruction()
  569. {
  570. return false;
  571. }
  572. bool IsBeingBackstabbed()
  573. {
  574. return false;
  575. }
  576. void SetBeingBackstabbed(int backstabType){}
  577. //! Returns if this entity if a food item
  578. bool IsFood()
  579. {
  580. return ( IsFruit() || IsMeat() || IsCorpse() || IsMushroom() );
  581. }
  582. bool IsFruit()
  583. {
  584. return false;
  585. }
  586. bool IsMeat()
  587. {
  588. return false;
  589. }
  590. bool IsCorpse()
  591. {
  592. return false;
  593. }
  594. bool IsMushroom()
  595. {
  596. return false;
  597. }
  598. //! Returns if the health of this entity should be displayed (widgets, inventory)
  599. bool IsHealthVisible()
  600. {
  601. return true;
  602. }
  603. //! Returns true if the health of damage zones should be displayed (instead of global HP of the entity) ( action widgets)
  604. bool ShowZonesHealth()
  605. {
  606. return false;
  607. }
  608. bool IsParticle()
  609. {
  610. return false;
  611. }
  612. bool IsItemTent()
  613. {
  614. return false;
  615. }
  616. bool IsScriptedLight()
  617. {
  618. return false;
  619. }
  620. bool IsHologram()
  621. {
  622. return false;
  623. }
  624. bool HasProxyParts()
  625. {
  626. return false;
  627. }
  628. bool CanObstruct()
  629. {
  630. return IsPlainObject() && !IsScenery();
  631. }
  632. bool CanProxyObstruct()
  633. {
  634. return HasProxyParts() || CanUseConstruction();
  635. }
  636. //! can the object's own proxy geometry obstruct it? Currently checking 'ObjIntersectView'
  637. bool CanProxyObstructSelf()
  638. {
  639. return false;
  640. }
  641. bool CanBeIgnoredByDroppedItem()
  642. {
  643. return IsBush() || IsTree() || IsMan() || IsDayZCreature() || IsItemBase();
  644. }
  645. bool CanBeAutoDeleted()
  646. {
  647. return true;
  648. }
  649. //! Disables icon in the vicinity, useful for large, immovable items, that are not buildings
  650. bool DisableVicinityIcon()
  651. {
  652. return false;
  653. }
  654. //! Returns low and high bits of networkID.
  655. //! This id is shared between client and server for whole server-client session.
  656. proto void GetNetworkID( out int lowBits, out int highBits );
  657. string GetNetworkIDString()
  658. {
  659. int low, high;
  660. GetNetworkID( low, high );
  661. return high.ToString() + low.ToString();
  662. }
  663. override string GetDebugName()
  664. {
  665. return GetDebugNameNative();
  666. }
  667. static string GetDebugName(Object o)
  668. {
  669. if (o)
  670. return o.GetDebugName();
  671. return "null";
  672. }
  673. //! native GetDebugName which is internally overloaded where needed
  674. proto string GetDebugNameNative();
  675. //! Remote procedure call shortcut, see CGame.RPC / CGame.RPCSingleParam
  676. void RPC(int rpc_type, array<ref Param> params, bool guaranteed, PlayerIdentity recipient = NULL)
  677. {
  678. GetGame().RPC(this, rpc_type, params, guaranteed, recipient);
  679. }
  680. //! Remote procedure call shortcut, see CGame.RPCSingleParam / CGame.RPC
  681. void RPCSingleParam(int rpc_type, Param param, bool guaranteed, PlayerIdentity recipient = NULL)
  682. {
  683. GetGame().RPCSingleParam(this, rpc_type, param, guaranteed, recipient);
  684. }
  685. /**
  686. \brief Called after remote procedure call is recieved for this object
  687. @param rpc_type user defined identification of RPC
  688. @param ctx read context for params
  689. */
  690. void OnRPC(PlayerIdentity sender, int rpc_type, ParamsReadContext ctx);
  691. vector GetSelectionPositionOld(string name)
  692. {
  693. return GetGame().ObjectGetSelectionPosition(this, name);
  694. }
  695. vector GetSelectionPositionLS(string name)
  696. {
  697. return GetGame().ObjectGetSelectionPositionLS(this, name);
  698. }
  699. vector GetSelectionPositionMS(string name)
  700. {
  701. return GetGame().ObjectGetSelectionPositionMS(this, name);
  702. }
  703. vector GetSelectionPositionWS(string name)
  704. {
  705. return GetGame().ObjectGetSelectionPositionWS(this, name);
  706. }
  707. vector ModelToWorld(vector modelPos)
  708. {
  709. return GetGame().ObjectModelToWorld(this, modelPos);
  710. }
  711. vector WorldToModel(vector worldPos)
  712. {
  713. return GetGame().ObjectWorldToModel(this, worldPos);
  714. }
  715. // config class API
  716. proto string ConfigGetString(string entryName);
  717. /**
  718. \brief Get a raw strings from config entry.
  719. @param entryName
  720. \return value output string
  721. \note use 'FormatRawConfigStringKeys' method to change localization keys to script-friendly
  722. */
  723. proto string ConfigGetStringRaw(string entryName);
  724. proto int ConfigGetInt(string entryName);
  725. bool ConfigGetBool(string entryName)
  726. {
  727. return (ConfigGetInt(entryName) == 1);
  728. }
  729. proto float ConfigGetFloat(string entryName);
  730. proto vector ConfigGetVector(string entryName);
  731. //proto ParamEntry ConfigGetEntry(string entryName);
  732. /**
  733. \brief Get array of strings from config entry.
  734. @param entryName
  735. @param value output
  736. */
  737. proto native void ConfigGetTextArray(string entryName, out TStringArray values);
  738. /**
  739. \brief Get array of raw strings from config entry.
  740. @param entryName
  741. @param value output in raw format (localization keys '$STR_' are not translated).
  742. \note use 'FormatRawConfigStringKeys' method to change localization keys to script-friendly
  743. */
  744. proto native void ConfigGetTextArrayRaw(string entryName, out TStringArray values);
  745. /**
  746. \brief Get array of floats from config entry.
  747. @param entryName
  748. @param value output
  749. */
  750. proto native void ConfigGetFloatArray(string entryName, out TFloatArray values);
  751. /**
  752. \brief Get array of integers from config entry.
  753. @param entryName
  754. @param value output
  755. */
  756. proto native void ConfigGetIntArray(string entryName, out TIntArray values);
  757. /**
  758. \brief Checks if given entry exists.
  759. @param entryName
  760. */
  761. proto native bool ConfigIsExisting(string entryName);
  762. //! Compares config class name to given string
  763. bool KindOf( string tag )
  764. {
  765. bool found = false;
  766. string item_name = this.GetType();
  767. TStringArray item_tag_array = new TStringArray;
  768. ConfigGetTextArray("cfgVehicles " + item_name + " itemInfo", item_tag_array);
  769. int array_size = item_tag_array.Count();
  770. for (int i = 0; i < array_size; i++)
  771. {
  772. if ( item_tag_array.Get(i) == tag )
  773. {
  774. found = true;
  775. break;
  776. }
  777. }
  778. return found;
  779. }
  780. bool IsAnyInherited( array<typename> typenames )
  781. {
  782. bool ret;
  783. for( int i = 0; i < typenames.Count(); i++ )
  784. {
  785. ret = ret || this.IsInherited( typenames.Get(i) );
  786. }
  787. return ret;
  788. }
  789. /**
  790. \brief Is this just static object without config? So we can avoid calling unnecessary methods
  791. */
  792. proto native bool IsPlainObject();
  793. /**
  794. \brief Is this Scenery? (handy for excluding terain when it is not needed)
  795. */
  796. proto native bool IsScenery();
  797. // Damage system
  798. /**
  799. \brief Checks if object's DamageSystem has been initialized(despite the name, does not really reliably answer the question whether the object is configured to have damage system or not)
  800. */
  801. proto native bool HasDamageSystem();
  802. /**
  803. \brief Checks if object is destroyed.
  804. */
  805. proto native bool IsDamageDestroyed();
  806. /**
  807. \brief Sets the time over which to perform DestructTent/DestructTree
  808. @param time time over which to perform DestructTent/DestructTree
  809. */
  810. proto native void SetDestructTime(float time);
  811. /**
  812. \brief Returns current state of health.
  813. @param zoneName if empty string, returns state of global health
  814. @param healthType if empty string, returns state of main health
  815. */
  816. proto native float GetHealth(string zoneName, string healthType);
  817. /**
  818. \brief Returns current state of health in range <0, 1>.
  819. @param zoneName if empty string, returns state of global health
  820. @param healthType if empty string, returns state of main health
  821. */
  822. proto native float GetHealth01(string zoneName, string healthType);
  823. /**
  824. \brief Returns maximum value of health.
  825. @param zoneName if empty string, returns state of global health
  826. @param healthType if empty string, returns state of main health
  827. */
  828. proto native float GetMaxHealth(string zoneName, string healthType);
  829. /**
  830. \brief Sets current state of health.
  831. @param zoneName if empty string, sets state of global health
  832. @param healthType if empty string, sets state of main health
  833. */
  834. proto native void SetHealth(string zoneName, string healthType, float value);
  835. /**
  836. \brief Sets full health to all zones and removes fatal damage when applicable
  837. */
  838. proto native void SetFullHealth();
  839. /**
  840. \brief Adds health.
  841. @param zoneName if empty string, sets state of global health
  842. @param healthType if empty string, sets state of main health
  843. */
  844. proto native void AddHealth(string zoneName, string healthType, float value);
  845. /**
  846. \brief Decreases health.
  847. @param zoneName if empty string, sets state of global health
  848. @param healthType if empty string, sets state of main health
  849. */
  850. proto native void DecreaseHealth(string zoneName, string healthType, float value);
  851. /**
  852. \brief List of additional health types in given zone
  853. @param zoneName if empty string, global will be used
  854. @param outHealthType List of the types found (does not clear the existing content)
  855. @returns false on any error (uninitialized system, bad zone name)
  856. */
  857. proto native bool GetAdditionalHealthTypes(string zoneName, TStringArray outHealthTypes);
  858. /**
  859. \brief Decreases health with the option of auto-deleting the object if its ruined.
  860. @param zoneName if empty string, sets state of global health
  861. @param healthType if empty string, sets state of main health
  862. */
  863. void DecreaseHealth(string zoneName, string healthType, float value, bool auto_delete)
  864. {
  865. DecreaseHealth(zoneName, healthType, value);
  866. if (auto_delete)
  867. {
  868. float result_health = GetHealth(zoneName, healthType);
  869. if (result_health <= 0)
  870. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(GetGame().ObjectDelete, this);
  871. }
  872. }
  873. //! Equivalent of GetHealth("", "");
  874. float GetHealth()
  875. {
  876. return GetHealth("", "");
  877. }
  878. //! Equivalent of GetHealth01("", "");
  879. float GetHealth01()
  880. {
  881. return GetHealth01("", "");
  882. }
  883. //! Equivalent of GetMaxHealth("", "");
  884. float GetMaxHealth()
  885. {
  886. return GetMaxHealth("", "");
  887. }
  888. //! Equivalent of SetHealth("", "", float value);
  889. void SetHealth(float health)
  890. {
  891. SetHealth("", "", health);
  892. }
  893. //! Equivalent of SetHealth("", "", float value);
  894. void SetGlobalHealth(float health)
  895. {
  896. SetHealth("", "", health);
  897. }
  898. //! Sets specific health level. It will use the cutoff value as returned by 'GetHealthLevelValue' as the health value for the given health level, which means it will always be set to the max health as allowed by the given health level.
  899. void SetHealthLevel(int healthLevel, string zone = "")
  900. {
  901. SetHealth01(zone,"", GetHealthLevelValue(healthLevel, zone));
  902. }
  903. //! Similar to 'SetHealthLevel', but allows to jump up/down 'healthLevelDelta' amount of health levels from the current one. Positive values cause health level increase, therefore damage the item, and vice-versa.
  904. void AddHealthLevel(int healthLevelDelta, string zone = "")
  905. {
  906. int maxHealthLevel = GetNumberOfHealthLevels(zone) - 1;
  907. int newHealthLevel = Math.Clamp(GetHealthLevel(zone) + healthLevelDelta,0,maxHealthLevel);
  908. SetHealthLevel(newHealthLevel,zone);
  909. }
  910. //! Sets health relative to its maximum
  911. void SetHealth01(string zoneName, string healthType, float coef)
  912. {
  913. SetHealth(zoneName,healthType,(GetMaxHealth(zoneName,healthType)*coef));
  914. }
  915. //! Sets health to its maximum (zone or global)
  916. void SetHealthMax(string zoneName = "", string healthType = "")
  917. {
  918. SetHealth(zoneName,healthType,GetMaxHealth(zoneName,healthType));
  919. }
  920. //! Equivalent of AddHealth("", "", float value);
  921. void AddHealth( float add_health)
  922. {
  923. AddHealth("", "", add_health);
  924. }
  925. //! Equivalent of DecreaseHealth("", "", float value, bool auto_delete);
  926. void DecreaseHealth(float dec_health, bool auto_delete = true)
  927. {
  928. DecreaseHealth("", "", dec_health, auto_delete);
  929. }
  930. //! Decreases health by the given coeficient.
  931. void DecreaseHealthCoef(float dec_health_coef, bool auto_delete = true)
  932. {
  933. float current_health = GetHealth();
  934. float final_health_coef = GetHealth01() - dec_health_coef;
  935. float final_health = GetMaxHealth() * final_health_coef;
  936. DecreaseHealth("", "", current_health - final_health);
  937. }
  938. /**
  939. \brief Applies damage on object.
  940. @param damageType DT_CLOSE_COMBAT/DT_FIRE_ARM/DT_EXPLOSION/DT_CUSTOM
  941. @param source source of damage
  942. @param componentName which 'DamageZone' was hit (NOT a component name, actually!)
  943. @param ammoName ammoType, which defines how much damage should be applied
  944. @param directHitModelPos local position of hit
  945. @param damageCoef multiplier of applied damage
  946. @param flags enables/disables special behaviour depending on the flags used (ProcessDirectDamageFlags type)
  947. */
  948. proto native void ProcessDirectDamage(int damageType, EntityAI source, string componentName, string ammoName, vector modelPos, float damageCoef = 1.0, int flags = 0);
  949. /**
  950. \brief Event called from C++ right before damage is applied
  951. @return whether to apply the damage or not
  952. */
  953. bool EEOnDamageCalculated(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
  954. {
  955. return true;
  956. }
  957. /**
  958. \brief Obtains a list of nammes of all object's damage zones
  959. @param list of names
  960. */
  961. proto native void GetDamageZones(out TStringArray dmgZones);
  962. /**
  963. \brief Obtains middle position of damage zone based on it's name
  964. @param name of the damage zone
  965. */
  966. proto native vector GetDamageZonePos(string zoneName);
  967. /**
  968. \brief Obtains name of damage zone based on index of specific component
  969. @param index of the component
  970. */
  971. proto native owned string GetDamageZoneNameByComponentIndex(int componentIndex);
  972. /**
  973. \brief Returns global health level specified in object's config class parameter healthLevels
  974. (range is usually 0..4, 0 = pristine, 1 = worn, 2 = damaged, 3 = badly damaged, 4 = ruined but can be changed).
  975. @param zoneName if empty string, returns state of global health level
  976. */
  977. proto native int GetHealthLevel(string zone = "");
  978. /**
  979. \brief Returns global number of health levels specified in object's config class parameter healthLevels
  980. (range is usually 0..4, 0 = pristine, 1 = worn, 2 = damaged, 3 = badly damaged, 4 = ruined but can be changed).
  981. @param zoneName if empty string, returns number of global health levels
  982. */
  983. proto native int GetNumberOfHealthLevels(string zone = "");
  984. /**
  985. \brief Returns cutoff value for health level specified in object's config class parameter healthLevels
  986. @param zoneName if empty string, returns number of global health levels
  987. @param healthLevel the health level to get the value from
  988. */
  989. proto native float GetHealthLevelValue(int healthLevel, string zone = "");
  990. /**
  991. \brief Returns if object can receive damage
  992. */
  993. proto native bool GetAllowDamage();
  994. /**
  995. \brief Enable or disable object to receive damage
  996. @param enable or disable
  997. */
  998. proto native void SetAllowDamage(bool val);
  999. /**
  1000. \brief Returns if object is destroyable
  1001. */
  1002. proto native bool GetCanBeDestroyed();
  1003. /**
  1004. \brief Enable or disable destruction of object (after health is depleated)
  1005. @param enable or disable
  1006. */
  1007. proto native void SetCanBeDestroyed(bool val);
  1008. /**
  1009. \brief Returns whether the object is ruined (0 Health).
  1010. \return \p bool true = item has 0 Health or less
  1011. @code
  1012. if ( item.IsRuined() )
  1013. {
  1014. Print("Object is ruined!");
  1015. }
  1016. @endcode
  1017. */
  1018. bool IsRuined()
  1019. {
  1020. return IsDamageDestroyed();
  1021. }
  1022. //! Event called from C++ when simulation is enabled
  1023. void OnSimulationEnabled() {}
  1024. //! Event called from C++ when simulation is disabled
  1025. void OnSimulationDisabled() {}
  1026. void GetActions(typename action_input_type, out array<ActionBase_Basic> actions)
  1027. {
  1028. }
  1029. //! Plays the given sound once on this object's instance. Range is in meters. Created sound is only local, unless create_local is set to false. Returns the sound itself.
  1030. SoundOnVehicle PlaySound(string sound_name, float range, bool create_local = true)
  1031. {
  1032. return GetGame().CreateSoundOnObject(this, sound_name, range, false, create_local);
  1033. }
  1034. //! Plays the given sound in loop on this object's instance. Range is in meters. Created sound is only local, unless create_local is set to false. Returns the sound itself.
  1035. SoundOnVehicle PlaySoundLoop(string sound_name, float range, bool create_local = true)
  1036. {
  1037. return GetGame().CreateSoundOnObject(this, sound_name, range, true, create_local);
  1038. }
  1039. //! EffectSound - plays soundset on this object and returns state of the sound (true - played, false - not played)
  1040. bool PlaySoundSet( out EffectSound sound, string sound_set, float fade_in, float fade_out, bool loop = false )
  1041. {
  1042. if ( GetGame() && !GetGame().IsDedicatedServer() )
  1043. {
  1044. if ( sound )
  1045. {
  1046. if ( loop )
  1047. {
  1048. return true;
  1049. }
  1050. else
  1051. {
  1052. StopSoundSet( sound ); //auto stop for non-looped sounds
  1053. }
  1054. }
  1055. sound = SEffectManager.PlaySoundOnObject( sound_set, this, fade_in, fade_out, loop );
  1056. sound.SetAutodestroy( true );
  1057. return true;
  1058. }
  1059. return false;
  1060. }
  1061. //! EffectSound - plays soundset on this object in loop and returns state of the sound (true - played, false - not played)
  1062. bool PlaySoundSetLoop( out EffectSound sound, string sound_set, float fade_in, float fade_out )
  1063. {
  1064. return PlaySoundSet( sound, sound_set, fade_in, fade_out, true );
  1065. }
  1066. //! Same as PlaySoundSetAtMemoryPointLooped, only requests stoppage of the currently playing EffectSound if it already exists and playing, before playing the new sound
  1067. bool PlaySoundSetAtMemoryPointLoopedSafe(out EffectSound sound, string soundSet, string memoryPoint,float play_fade_in = 0, float stop_fade_out = 0)
  1068. {
  1069. if (sound && sound.IsPlaying())
  1070. {
  1071. sound.SoundStop();
  1072. }
  1073. return PlaySoundSetAtMemoryPointLooped(sound, soundSet, memoryPoint, play_fade_in, stop_fade_out);
  1074. }
  1075. bool PlaySoundSetAtMemoryPointLooped(out EffectSound sound, string soundSet, string memoryPoint, float play_fade_in = 0, float stop_fade_out = 0)
  1076. {
  1077. return PlaySoundSetAtMemoryPoint(sound, soundSet, memoryPoint, true, play_fade_in, stop_fade_out);
  1078. }
  1079. bool PlaySoundSetAtMemoryPoint(out EffectSound sound, string soundSet, string memoryPoint, bool looped = false, float play_fade_in = 0, float stop_fade_out = 0)
  1080. {
  1081. vector pos;
  1082. if (MemoryPointExists(memoryPoint))
  1083. {
  1084. pos = GetMemoryPointPos(memoryPoint);
  1085. pos = ModelToWorld(pos);
  1086. }
  1087. else
  1088. {
  1089. ErrorEx(string.Format("Memory point %1 not found when playing soundset %2 at memory point location", memoryPoint, soundSet));
  1090. return false;
  1091. }
  1092. sound = SEffectManager.PlaySoundEnviroment(soundSet, pos, play_fade_in, stop_fade_out, looped);
  1093. return true;
  1094. }
  1095. //! EffectSound - stops soundset and returns state of the sound (true - stopped, false - not playing)
  1096. bool StopSoundSet( out EffectSound sound )
  1097. {
  1098. if ( sound && GetGame() && ( !GetGame().IsDedicatedServer() ) )
  1099. {
  1100. sound.SoundStop();
  1101. sound = null;
  1102. return true;
  1103. }
  1104. return false;
  1105. }
  1106. void PostAreaDamageActions();
  1107. void PreAreaDamageActions();
  1108. void SpawnDamageDealtEffect();
  1109. void OnReceivedHit(ImpactEffectsData hitData);
  1110. //! DEPRECATED
  1111. void OnPlayerRecievedHit();
  1112. bool HasNetworkID()
  1113. {
  1114. int lo = 0;
  1115. int hi = 0;
  1116. GetNetworkID(lo, hi);
  1117. return lo | hi;
  1118. }
  1119. bool NameOverride(out string output)
  1120. {
  1121. return false;
  1122. }
  1123. bool DescriptionOverride(out string output)
  1124. {
  1125. return false;
  1126. }
  1127. EntityAI ProcessMeleeItemDamage(int mode = 0) {}
  1128. bool CanBeRepairedToPristine()
  1129. {
  1130. return false;
  1131. }
  1132. vector GetCenter()
  1133. {
  1134. if ( MemoryPointExists("ce_center") )
  1135. {
  1136. //Print("CE_CENTER found");
  1137. return ModelToWorld( GetMemoryPointPos("ce_center") );
  1138. }
  1139. else
  1140. {
  1141. //Print("CE_CENTER DOING A BAMBOOZLE => not found");
  1142. return GetPosition() + Vector(0, 0.2, 0);
  1143. }
  1144. }
  1145. #ifdef DEVELOPER
  1146. void SetDebugItem();
  1147. #endif
  1148. void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
  1149. {
  1150. int pivot = GetBonePivot(GetFireGeometryLevel(), componentIndex);
  1151. vector parentTransMat[4];
  1152. vector arrowTransMat[4];
  1153. if (pivot == -1)
  1154. {
  1155. GetTransform(parentTransMat);
  1156. }
  1157. else
  1158. {
  1159. GetBoneTransformWS(pivot, parentTransMat);
  1160. }
  1161. float scale = GetScale();
  1162. scale = 1 / (scale * scale);
  1163. arrow.GetTransform(arrowTransMat);
  1164. Math3D.MatrixInvMultiply4(parentTransMat, arrowTransMat, arrowTransMat);
  1165. // orthogonalize matrix - parent might be skewed
  1166. Math3D.MatrixOrthogonalize4(arrowTransMat);
  1167. arrowTransMat[3] = arrowTransMat[3] * scale;
  1168. arrow.SetTransform(arrowTransMat);
  1169. AddChild(arrow, pivot);
  1170. }
  1171. bool CanBeActionTarget()
  1172. {
  1173. return !IsHologram();
  1174. }
  1175. bool HasFixedActionTargetCursorPosition()
  1176. {
  1177. return false;
  1178. }
  1179. void OnSpawnByObjectSpawner(ITEM_SpawnerObject item)
  1180. {}
  1181. //Debug
  1182. //----------------------------------------------
  1183. /*void DbgAddPxyPhy(string slot)
  1184. {
  1185. Print("AddProxyPhysics slot: " + slot);
  1186. AddProxyPhysics(slot);
  1187. }*/
  1188. };