entityai.c 122 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575
  1. enum EWetnessLevel
  2. {
  3. DRY,
  4. DAMP,
  5. WET,
  6. SOAKING,
  7. DRENCHED
  8. }
  9. enum SurfaceAnimationBone
  10. {
  11. LeftFrontLimb = 0,
  12. RightFrontLimb,
  13. LeftBackLimb,
  14. RightBackLimb
  15. }
  16. enum PlantType
  17. {
  18. TREE_HARD = 1000,
  19. TREE_SOFT = 1001,
  20. BUSH_HARD = 1002,
  21. BUSH_SOFT = 1003,
  22. }
  23. enum WeightUpdateType
  24. {
  25. FULL = 0,
  26. ADD,
  27. REMOVE,
  28. RECURSIVE_ADD,
  29. RECURSIVE_REMOVE
  30. }
  31. enum EItemManipulationContext
  32. {
  33. UPDATE, //generic operation
  34. ATTACHING,
  35. DETACHING,
  36. }
  37. //! icon visibility, meant to be used in a bitmask
  38. enum EInventoryIconVisibility
  39. {
  40. ALWAYS = 0,
  41. HIDE_VICINITY = 1,
  42. //further values yet unused, but nice to have anyway
  43. HIDE_PLAYER_CONTAINER = 2,
  44. HIDE_HANDS_SLOT = 4
  45. }
  46. //!EXCLUSIVITY values, restrict attachment combinations
  47. enum EAttExclusions
  48. {
  49. OCCUPANCY_INVALID = -1,
  50. //Legacy relations
  51. LEGACY_EYEWEAR_HEADGEAR,
  52. LEGACY_EYEWEAR_MASK,
  53. LEGACY_HEADSTRAP_HEADGEAR,
  54. LEGACY_HEADSTRAP_MASK,
  55. LEGACY_HEADGEAR_MASK,
  56. LEGACY_HEADGEAR_EYEWEWEAR,
  57. LEGACY_HEADGEAR_HEADSTRAP,
  58. LEGACY_MASK_HEADGEAR,
  59. LEGACY_MASK_EYEWEWEAR,
  60. LEGACY_MASK_HEADSTRAP,
  61. //
  62. EXCLUSION_HEADGEAR_HELMET_0, //full helmet
  63. //EXCLUSION_HEADGEAR_HELMET_0_A, //example of another 'vector' of potential conflict, like between helmet and eyewear..otherwise the other non-helmet entities would collide through the 'EXCLUSION_HEADSTRAP_0' value.
  64. EXCLUSION_HEADSTRAP_0,
  65. EXCLUSION_MASK_0,
  66. EXCLUSION_MASK_1,
  67. EXCLUSION_MASK_2, //Mostly Gasmasks
  68. EXCLUSION_MASK_3, //bandana mask special behavior
  69. EXCLUSION_GLASSES_REGULAR_0,
  70. EXCLUSION_GLASSES_TIGHT_0,
  71. //values to solve the edge-cases with shaving action
  72. SHAVING_MASK_ATT_0,
  73. SHAVING_HEADGEAR_ATT_0,
  74. SHAVING_EYEWEAR_ATT_0,
  75. }
  76. class DebugSpawnParams
  77. {
  78. Man m_Player;
  79. static DebugSpawnParams WithPlayer(Man player)
  80. {
  81. DebugSpawnParams params = new DebugSpawnParams();
  82. params.m_Player = player;
  83. return params;
  84. }
  85. };
  86. class TSelectableActionInfoArrayEx extends array<ref Param> {}
  87. typedef Param3<int, int, string> TSelectableActionInfo;
  88. typedef Param4<int, int, string, int> TSelectableActionInfoWithColor;
  89. class EntityAI extends Entity
  90. {
  91. bool m_DeathSyncSent;
  92. bool m_KilledByHeadshot;
  93. bool m_PreparedToDelete = false;
  94. bool m_RefresherViable = false;
  95. bool m_WeightDirty = 1;
  96. protected bool m_RoofAbove = false;
  97. private ref map<int,ref set<int>> m_AttachmentExclusionSlotMap; //own masks for different slots <slot,mask>. Kept on instance to better respond to various state changes
  98. private ref set<int> m_AttachmentExclusionMaskGlobal; //additional mask values and simple item values. Independent of slot-specific behavior!
  99. private ref set<int> m_AttachmentExclusionMaskChildren; //additional mask values and simple item values
  100. ref DestructionEffectBase m_DestructionBehaviourObj;
  101. ref KillerData m_KillerData;
  102. private ref HiddenSelectionsData m_HiddenSelectionsData;
  103. const int DEAD_REPLACE_DELAY = 250;
  104. const int DELETE_CHECK_DELAY = 100;
  105. ref array<EntityAI> m_AttachmentsWithCargo;
  106. ref array<EntityAI> m_AttachmentsWithAttachments;
  107. ref InventoryLocation m_OldLocation;
  108. protected ref DamageZoneMap m_DamageZoneMap;
  109. private ref map<int, string> m_DamageDisplayNameMap = new map<int, string>; //values are localization keys as strings, use 'Widget.TranslateString' method to get the localized one
  110. float m_Weight;
  111. float m_WeightEx;
  112. float m_ConfigWeight = ConfigGetInt("weight");
  113. protected bool m_CanDisplayWeight;
  114. private float m_LastUpdatedTime; //CE update time
  115. protected float m_ElapsedSinceLastUpdate; //CE update time
  116. protected float m_PreviousRoofTestTime = 0;
  117. protected UTemperatureSource m_UniversalTemperatureSource;
  118. bool m_PendingDelete = false;
  119. bool m_Initialized = false;
  120. bool m_TransportHitRegistered = false;
  121. vector m_TransportHitVelocity;
  122. // ============================================
  123. // Variable Manipulation System
  124. // ============================================
  125. int m_VariablesMask;//this holds information about which vars have been changed from their default values
  126. // Temperature
  127. float m_VarTemperature;
  128. float m_VarTemperatureInit;
  129. float m_VarTemperatureMin;
  130. float m_VarTemperatureMax;
  131. float m_VarTemperatureFreezeThreshold;
  132. float m_VarTemperatureThawThreshold;
  133. float m_VarTemperatureFreezeTime;
  134. float m_VarTemperatureThawTime;
  135. float m_VarTemperatureOverheatTime;
  136. float m_VarHeatPermeabilityCoef;
  137. protected ref TemperatureAccessComponent m_TAC;
  138. protected bool m_IsFrozen;
  139. protected bool m_IsFrozenLocal;
  140. protected float m_FreezeThawProgress;
  141. protected float m_OverheatProgress;
  142. //---------------------------------------------
  143. //Called on item attached to this item (EntityAI item, string slot, EntityAI parent)
  144. protected ref ScriptInvoker m_OnItemAttached;
  145. //Called on item detached from this item (EntityAI item, string slot, EntityAI parent)
  146. protected ref ScriptInvoker m_OnItemDetached;
  147. //Called when an item is added to the cargo of this item (EntityAI item, EntityAI parent)
  148. protected ref ScriptInvoker m_OnItemAddedIntoCargo;
  149. //Called when an item is removed from the cargo of this item (EntityAI item, EntityAI parent)
  150. protected ref ScriptInvoker m_OnItemRemovedFromCargo;
  151. //Called when an item is moved around in the cargo of this item (EntityAI item, EntityAI parent)
  152. protected ref ScriptInvoker m_OnItemMovedInCargo;
  153. //Called when an item is flipped around in cargo (bool flip)
  154. protected ref ScriptInvoker m_OnItemFlipped;
  155. //Called when an items view index is changed
  156. protected ref ScriptInvoker m_OnViewIndexChanged;
  157. //Called when an location in this item is reserved (EntityAI item) - cargo
  158. protected ref ScriptInvoker m_OnSetLock;
  159. //Called when this item is unreserved (EntityAI item) - cargo
  160. protected ref ScriptInvoker m_OnReleaseLock;
  161. //Called when an location in this item is reserved (EntityAI item) - attachment
  162. protected ref ScriptInvoker m_OnAttachmentSetLock;
  163. //Called when this item is unreserved (EntityAI item) - attachment
  164. protected ref ScriptInvoker m_OnAttachmentReleaseLock;
  165. //Called when this entity is hit
  166. protected ref ScriptInvoker m_OnHitByInvoker;
  167. //Called when this entity is killed
  168. protected ref ScriptInvoker m_OnKilledInvoker;
  169. #ifdef DEVELOPER
  170. float m_LastFTChangeTime;;
  171. float m_PresumedTimeRemaining;
  172. #endif
  173. void EntityAI()
  174. {
  175. // Set up the Energy Manager
  176. string type = GetType();
  177. string param_access_energy_sys = "CfgVehicles " + type + " EnergyManager ";
  178. bool is_electic_device = GetGame().ConfigIsExisting(param_access_energy_sys);
  179. if (is_electic_device) // TO DO: Check if this instance is a hologram (advanced placement). If Yes, then do not create Energy Manager component.
  180. {
  181. CreateComponent(COMP_TYPE_ENERGY_MANAGER);
  182. RegisterNetSyncVariableBool("m_EM.m_IsSwichedOn");
  183. RegisterNetSyncVariableBool("m_EM.m_CanWork");
  184. RegisterNetSyncVariableBool("m_EM.m_IsPlugged");
  185. RegisterNetSyncVariableInt("m_EM.m_EnergySourceNetworkIDLow");
  186. RegisterNetSyncVariableInt("m_EM.m_EnergySourceNetworkIDHigh");
  187. RegisterNetSyncVariableFloat("m_EM.m_Energy");
  188. }
  189. // Item preview index
  190. RegisterNetSyncVariableInt( "m_ViewIndex", 0, 99 );
  191. // Refresher signalization
  192. RegisterNetSyncVariableBool("m_RefresherViable");
  193. m_AttachmentsWithCargo = new array<EntityAI>();
  194. m_AttachmentsWithAttachments = new array<EntityAI>();
  195. m_LastUpdatedTime = 0.0;
  196. m_ElapsedSinceLastUpdate = 0.0;
  197. m_CanDisplayWeight = ConfigGetBool("displayWeight");
  198. InitDamageZoneMapping();
  199. InitDamageZoneDisplayNameMapping();
  200. InitItemVariables();
  201. m_HiddenSelectionsData = new HiddenSelectionsData( GetType() );
  202. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DeferredInit,34);
  203. }
  204. void ~EntityAI()
  205. {
  206. }
  207. void InitItemVariables()
  208. {
  209. m_VarTemperatureInit = ConfigGetFloat("varTemperatureInit");
  210. m_VarTemperatureMin = ConfigGetFloat("varTemperatureMin");
  211. m_VarTemperatureMax = ConfigGetFloat("varTemperatureMax");
  212. if (ConfigIsExisting("varTemperatureFreezePoint"))
  213. m_VarTemperatureFreezeThreshold = ConfigGetFloat("varTemperatureFreezePoint");
  214. else
  215. m_VarTemperatureFreezeThreshold = float.LOWEST;
  216. if (ConfigIsExisting("varTemperatureThawPoint"))
  217. m_VarTemperatureThawThreshold = ConfigGetFloat("varTemperatureThawPoint");
  218. else
  219. m_VarTemperatureThawThreshold = float.LOWEST;
  220. m_VarTemperatureFreezeTime = Math.Clamp(ConfigGetFloat("varTemperatureFreezeTime"),1,float.MAX);
  221. m_VarTemperatureThawTime = Math.Clamp(ConfigGetFloat("varTemperatureThawTime"),1,float.MAX);
  222. if (ConfigIsExisting("varTemperatureOverheatTime"))
  223. m_VarTemperatureOverheatTime = ConfigGetFloat("varTemperatureOverheatTime");
  224. else
  225. m_VarTemperatureOverheatTime = -1;
  226. if (ConfigIsExisting("varHeatPermeabilityCoef"))
  227. m_VarHeatPermeabilityCoef = ConfigGetFloat("varHeatPermeabilityCoef");
  228. else
  229. m_VarHeatPermeabilityCoef = 1;
  230. if (CanHaveTemperature())
  231. {
  232. RegisterNetSyncVariableFloat("m_VarTemperature", GetTemperatureMin(),GetTemperatureMax());
  233. RegisterNetSyncVariableBool("m_IsFrozen");
  234. if (GetGame().IsServer())
  235. m_TAC = new TemperatureAccessComponent(this);
  236. if (!GetGame().IsMultiplayer() || GetGame().IsClient())
  237. m_FreezeThawProgress = -1;
  238. }
  239. }
  240. void DeferredInit()
  241. {
  242. m_Initialized = true;
  243. }
  244. bool IsInitialized()
  245. {
  246. return m_Initialized;
  247. }
  248. //! should the item's icon be hidden in any part of the inventory?
  249. int GetHideIconMask()
  250. {
  251. return EInventoryIconVisibility.ALWAYS;
  252. }
  253. private ref ComponentsBank m_ComponentsBank;
  254. ComponentEnergyManager m_EM; // This reference is necesarry due to synchronization, since it's impossible to synchronize values from a component :(
  255. //! CreateComponent
  256. Component CreateComponent(int comp_type, string extended_class_name="")
  257. {
  258. return GetComponent(comp_type, extended_class_name);
  259. }
  260. //! GetComponent
  261. Component GetComponent(int comp_type, string extended_class_name="")
  262. {
  263. if ( m_ComponentsBank == NULL )
  264. m_ComponentsBank = new ComponentsBank(this);
  265. return m_ComponentsBank.GetComponent(comp_type, extended_class_name);
  266. }
  267. //! DeleteComponent
  268. bool DeleteComponent(int comp_type)
  269. {
  270. return m_ComponentsBank.DeleteComponent(comp_type);
  271. }
  272. string GetDestructionBehaviour()
  273. {
  274. return "";
  275. }
  276. bool IsDestructionBehaviour()
  277. {
  278. return false;
  279. }
  280. //! IsComponentExist
  281. bool HasComponent(int comp_type)
  282. {
  283. if ( m_ComponentsBank )
  284. return m_ComponentsBank.IsComponentAlreadyExist(comp_type);
  285. return false;
  286. }
  287. //! Calculates if the max lifetime is higher than refresher frequency (i.e. gets kept alive by refresher)
  288. void MaxLifetimeRefreshCalc()
  289. {
  290. if ( (!GetGame().IsMultiplayer() || GetGame().IsServer()) && GetEconomyProfile() )
  291. {
  292. float lifetime = GetEconomyProfile().GetLifetime();
  293. int frequency = GetCEApi().GetCEGlobalInt("FlagRefreshFrequency");
  294. if ( frequency <= 0 )
  295. {
  296. frequency = GameConstants.REFRESHER_FREQUENCY_DEFAULT;
  297. }
  298. if ( frequency <= lifetime )
  299. {
  300. m_RefresherViable = true;
  301. SetSynchDirty();
  302. }
  303. }
  304. }
  305. bool IsRefresherSignalingViable()
  306. {
  307. if (IsRuined())
  308. {
  309. return false;
  310. }
  311. return m_RefresherViable;
  312. }
  313. #ifdef DEVELOPER
  314. override void SetDebugItem()
  315. {
  316. super.SetDebugItem();
  317. _item = this;
  318. }
  319. #endif
  320. //! Initializes script-side map of damage zones and their components (named selections in models)
  321. void InitDamageZoneMapping()
  322. {
  323. m_DamageZoneMap = new DamageZoneMap;
  324. DamageSystem.GetDamageZoneMap(this,m_DamageZoneMap);
  325. }
  326. //! Initialize map of damage zone display names for more optimized retrieval
  327. void InitDamageZoneDisplayNameMapping()
  328. {
  329. string path_base;
  330. string path;
  331. string component_name;
  332. if ( IsWeapon() )
  333. {
  334. path_base = CFG_WEAPONSPATH;
  335. }
  336. else if ( IsMagazine() )
  337. {
  338. path_base = CFG_MAGAZINESPATH;
  339. }
  340. else
  341. {
  342. path_base = CFG_VEHICLESPATH;
  343. }
  344. path_base = string.Format( "%1 %2 DamageSystem DamageZones", path_base, GetType() );
  345. if ( !GetGame().ConfigIsExisting(path_base) )
  346. {
  347. component_name = GetDisplayName();
  348. GetGame().FormatRawConfigStringKeys(component_name);
  349. m_DamageDisplayNameMap.Insert( "".Hash(), component_name );
  350. }
  351. else
  352. {
  353. TStringArray zone_names = new TStringArray;
  354. GetDamageZones( zone_names );
  355. for ( int i = 0; i < zone_names.Count(); i++ )
  356. {
  357. path = string.Format( "%1 %2 displayName", path_base, zone_names[i] );
  358. if (GetGame().ConfigIsExisting(path) && GetGame().ConfigGetTextRaw(path,component_name))
  359. {
  360. GetGame().FormatRawConfigStringKeys(component_name);
  361. m_DamageDisplayNameMap.Insert( zone_names[i].Hash(), component_name );
  362. }
  363. }
  364. }
  365. }
  366. protected float ConvertNonlethalDamage(float damage, DamageType damageType)
  367. {
  368. return 0.0;
  369. }
  370. //! DEPRECATED - for legacy purposes
  371. float ConvertNonlethalDamage(float damage)
  372. {
  373. return 0.0;
  374. }
  375. DamageZoneMap GetEntityDamageZoneMap()
  376. {
  377. return m_DamageZoneMap;
  378. }
  379. map<int, string> GetEntityDamageDisplayNameMap()
  380. {
  381. return m_DamageDisplayNameMap;
  382. }
  383. //! 'displayWeight' in item config
  384. bool CanDisplayWeight()
  385. {
  386. return m_CanDisplayWeight;
  387. }
  388. //! Log
  389. void Log(string msg, string fnc_name = "n/a")
  390. {
  391. Debug.Log(msg, "Object", "n/a", fnc_name, this.GetType());
  392. }
  393. //! LogWarning
  394. void LogWarning(string msg, string fnc_name = "n/a")
  395. {
  396. Debug.LogWarning(msg, "Object", "n/a", fnc_name, this.GetType());
  397. }
  398. //! LogError
  399. void LogError(string msg, string fnc_name = "n/a")
  400. {
  401. Debug.LogError(msg, "Object", "n/a", fnc_name, this.GetType());
  402. }
  403. ///@{ Skinning
  404. bool IsSkinned()
  405. {
  406. return GetCompBS() && GetCompBS().IsSkinned();
  407. }
  408. void SetAsSkinned()
  409. {
  410. if (GetCompBS())
  411. GetCompBS().SetAsSkinned();
  412. }
  413. bool CanBeSkinnedWith(EntityAI tool)
  414. {
  415. if ( !IsSkinned() && tool )
  416. if ( !IsAlive() )
  417. return true;
  418. return false;
  419. }
  420. ///@} Skinning
  421. // ITEM TO ITEM FIRE DISTRIBUTION
  422. //! Override this method to return TRUE when this item has or can provide fire. Evaluated on server and client.
  423. bool HasFlammableMaterial()
  424. {
  425. return false;
  426. }
  427. //! Override this method so it checks whenever this item can be ignited right now or not. Evaluated on Server and Client.
  428. bool CanBeIgnitedBy(EntityAI igniter = NULL)
  429. {
  430. return false;
  431. }
  432. //! Override this method and check if the given item can be ignited right now by this one. Evaluated on Server and Client.
  433. bool CanIgniteItem(EntityAI ignite_target = NULL)
  434. {
  435. return false;
  436. }
  437. //! Override this method and make it so it returns whenever this item is on fire right now or not. Evaluated on Server and Client.
  438. bool IsIgnited()
  439. {
  440. if (m_EM)
  441. return m_EM.IsWorking();
  442. return false;
  443. }
  444. // Change return value to true if last detached item cause disassemble of item - different handlig some inventory operations
  445. bool DisassembleOnLastDetach()
  446. {
  447. return false;
  448. }
  449. bool IsBasebuildingKit()
  450. {
  451. return false;
  452. }
  453. //! Should return false if you want to disable hologram rotation
  454. bool PlacementCanBeRotated()
  455. {
  456. return true;
  457. }
  458. //! Executed on Server when this item ignites some target item
  459. void OnIgnitedTarget( EntityAI target_item)
  460. {
  461. }
  462. //! Executed on Server when some item ignited this one
  463. void OnIgnitedThis( EntityAI fire_source)
  464. {
  465. }
  466. //! Executed on Server when this item failed to ignite target item
  467. void OnIgnitedTargetFailed( EntityAI target_item)
  468. {
  469. }
  470. //! Executed on Server when some item failed to ignite this one
  471. void OnIgnitedThisFailed( EntityAI fire_source)
  472. {
  473. }
  474. //! Final evaluation just before the target item is actually ignited. Evaluated on Server.
  475. bool IsTargetIgnitionSuccessful(EntityAI item_target)
  476. {
  477. return true;
  478. }
  479. //! Final evaluation just before this item is actually ignited from fire source. Evaluated on Server.
  480. bool IsThisIgnitionSuccessful(EntityAI item_source = NULL)
  481. {
  482. return true;
  483. }
  484. // End of fire distribution ^
  485. // ADVANCED PLACEMENT EVENTS
  486. void OnPlacementStarted(Man player);
  487. void OnHologramBeingPlaced(Man player);
  488. void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0");
  489. void OnPlacementCancelled(Man player);
  490. bool CanBePlaced(Man player, vector position)
  491. {
  492. return true;
  493. }
  494. //! Method which returns message why object can't be placed at given position
  495. string CanBePlacedFailMessage( Man player, vector position )
  496. {
  497. return "";
  498. }
  499. //! Do the roof check when placing this?
  500. bool DoPlacingHeightCheck()
  501. {
  502. return false;
  503. }
  504. //! used as script-side override of distance for specific height checks
  505. float HeightCheckOverride()
  506. {
  507. return 0.0;
  508. }
  509. //! used as script-side override of start pos for specific height checks
  510. float HeightStartCheckOverride()
  511. {
  512. return 0.0;
  513. }
  514. //! is this container empty or not, checks both cargo and attachments
  515. bool IsEmpty()
  516. {
  517. return (!HasAnyCargo() && GetInventory().AttachmentCount() == 0);
  518. }
  519. //! returns just the configured 'canBeSplit' bool
  520. bool IsSplitable()
  521. {
  522. return false;
  523. }
  524. //! returns current splitability
  525. bool CanBeSplit()
  526. {
  527. return false;
  528. }
  529. //! is this container empty or not, checks only cargo
  530. bool HasAnyCargo()
  531. {
  532. CargoBase cargo = GetInventory().GetCargo();
  533. if(!cargo) return false;//this is not a cargo container
  534. if( cargo.GetItemCount() > 0 )
  535. {
  536. return true;
  537. }
  538. else
  539. {
  540. return false;
  541. }
  542. }
  543. array<EntityAI> GetAttachmentsWithCargo()
  544. {
  545. return m_AttachmentsWithCargo;
  546. }
  547. array<EntityAI> GetAttachmentsWithAttachments()
  548. {
  549. return m_AttachmentsWithAttachments;
  550. }
  551. //is there any roof above
  552. bool IsRoofAbove()
  553. {
  554. return m_RoofAbove;
  555. }
  556. void SetRoofAbove(bool state)
  557. {
  558. m_RoofAbove = state;
  559. }
  560. //! Roof check for entity, limited by time (anti-spam solution)
  561. void CheckForRoofLimited(float timeTresholdMS = 3000);
  562. int GetAgents() { return 0; }
  563. void RemoveAgent(int agent_id);
  564. void RemoveAllAgents();
  565. void RemoveAllAgentsExcept(int agent_to_keep);
  566. void InsertAgent(int agent, float count = 1);
  567. override bool IsEntityAI() { return true; }
  568. bool IsInventoryVisible()
  569. {
  570. return !( GetParent() || GetHierarchyParent() );
  571. }
  572. bool IsPlayer()
  573. {
  574. return false;
  575. }
  576. bool IsAnimal()
  577. {
  578. return false;
  579. }
  580. bool IsZombie()
  581. {
  582. return false;
  583. }
  584. bool IsZombieMilitary()
  585. {
  586. return false;
  587. }
  588. bool IsIgnoredByConstruction()
  589. {
  590. return IsDamageDestroyed();
  591. }
  592. bool CanBeTargetedByAI(EntityAI ai)
  593. {
  594. if (ai && ai.IsBeingBackstabbed())
  595. {
  596. return false;
  597. }
  598. if ( !dBodyIsActive( this ) && !IsMan() )
  599. return false;
  600. return !IsDamageDestroyed();
  601. }
  602. bool CanBeBackstabbed()
  603. {
  604. return false;
  605. }
  606. /**@brief Delete this object in next frame
  607. * @return \p void
  608. *
  609. * @code
  610. * ItemBase item = GetGame().GetPlayer().CreateInInventory("GrenadeRGD5");
  611. * item.Delete();
  612. * @endcode
  613. **/
  614. override void Delete()
  615. {
  616. m_PendingDelete = true;
  617. super.Delete();
  618. }
  619. void DeleteOnClient()
  620. {
  621. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(GetGame().ObjectDeleteOnClient, this);
  622. }
  623. // delete synchronized between server and client
  624. void DeleteSafe()
  625. {
  626. if (GetHierarchyRootPlayer() == null || (GetHierarchyRootPlayer() && !GetHierarchyRootPlayer().IsAlive()))
  627. {
  628. Delete();
  629. }
  630. else
  631. {
  632. if (GetGame().IsServer() && GetGame().IsMultiplayer())
  633. GetHierarchyRootPlayer().JunctureDeleteItem(this);
  634. else
  635. GetHierarchyRootPlayer().AddItemToDelete(this);
  636. }
  637. }
  638. //legacy, wrong name, use 'DeleteSafe()' instead
  639. void DeleteSave()
  640. {
  641. DeleteSafe();
  642. }
  643. bool IsSetForDeletion()
  644. {
  645. return IsPreparedToDelete() || m_PendingDelete || ToDelete() || IsPendingDeletion();
  646. }
  647. override bool CanBeActionTarget()
  648. {
  649. if (super.CanBeActionTarget())
  650. {
  651. return !IsSetForDeletion();
  652. }
  653. else
  654. {
  655. return false;
  656. }
  657. }
  658. void SetPrepareToDelete()
  659. {
  660. m_PreparedToDelete = true;
  661. }
  662. bool IsPreparedToDelete()
  663. {
  664. return m_PreparedToDelete;
  665. }
  666. void CheckForDestroy()
  667. {
  668. if (IsPrepareToDelete())
  669. {
  670. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(TryDelete, DELETE_CHECK_DELAY, false);
  671. }
  672. }
  673. bool IsPrepareToDelete()
  674. {
  675. return false;
  676. }
  677. bool TryDelete()
  678. {
  679. if (!IsPrepareToDelete())
  680. {
  681. Debug.Log("TryDelete - not ready for deletion");
  682. return false;
  683. }
  684. if (GetGame().HasInventoryJunctureItem(this))
  685. {
  686. Debug.Log("TryDelete - deferred call");
  687. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(TryDelete, DELETE_CHECK_DELAY, false);
  688. return false;
  689. }
  690. OnBeforeTryDelete();
  691. Debug.Log("TryDelete - OnBeforeTryDelete end");
  692. DeleteSafe();
  693. Debug.Log("TryDelete - DeleteSafe end");
  694. return true;
  695. }
  696. void OnBeforeTryDelete();
  697. //! Returns root of current hierarchy (for example: if this entity is in Backpack on gnd, returns Backpack)
  698. proto native EntityAI GetHierarchyRoot();
  699. //! Returns root of current hierarchy cast to Man
  700. proto native Man GetHierarchyRootPlayer();
  701. //! Returns direct parent of current entity
  702. proto native EntityAI GetHierarchyParent();
  703. //! Get economy item profile (if assigned, otherwise null)
  704. proto native CEItemProfile GetEconomyProfile();
  705. // !returns the number of levels bellow the hierarchy root this entity is at
  706. int GetHierarchyLevel(int lvl = 0)
  707. {
  708. if (!GetHierarchyParent())
  709. return lvl;
  710. return GetHierarchyParent().GetHierarchyLevel(lvl+1);
  711. }
  712. void OnInventoryInit()
  713. {
  714. InitAttachmentExclusionValues();
  715. }
  716. //! Called upon object creation
  717. void EEInit()
  718. {
  719. if (GetInventory())
  720. {
  721. GetInventory().EEInit();
  722. m_AttachmentsWithCargo.Clear();
  723. m_AttachmentsWithAttachments.Clear();
  724. for ( int i = 0; i < GetInventory().AttachmentCount(); i++ )
  725. {
  726. EntityAI attachment = GetInventory().GetAttachmentFromIndex( i );
  727. if ( attachment )
  728. {
  729. if ( attachment.GetInventory().GetCargo() )
  730. {
  731. m_AttachmentsWithCargo.Insert( attachment );
  732. }
  733. if ( attachment.GetInventory().GetAttachmentSlotsCount() > 0 )
  734. {
  735. m_AttachmentsWithAttachments.Insert( attachment );
  736. }
  737. }
  738. }
  739. }
  740. MaxLifetimeRefreshCalc();
  741. if (CanHaveTemperature() && GetGame().IsServer())
  742. InitTemperature();
  743. }
  744. //! Called right before object deleting
  745. void EEDelete(EntityAI parent)
  746. {
  747. m_PendingDelete = true;
  748. GetInventory().EEDelete(parent);
  749. if (m_EM)
  750. m_EM.OnDeviceDestroyed();
  751. }
  752. override void OnExplosionEffects(Object source, Object directHit, int componentIndex, string surface, vector pos, vector surfNormal, float energyFactor, float explosionFactor, bool isWater, string ammoType)
  753. {
  754. super.OnExplosionEffects(source, directHit, componentIndex, surface, pos, surfNormal, energyFactor, explosionFactor, isWater, ammoType);
  755. #ifndef SERVER
  756. g_Game.GetWorld().AddEnvShootingSource(pos, 1.0);
  757. #endif
  758. if (m_DestructionBehaviourObj && m_DestructionBehaviourObj.HasExplosionDamage())
  759. {
  760. m_DestructionBehaviourObj.OnExplosionEffects(source, directHit, componentIndex, surface, pos, surfNormal, energyFactor, explosionFactor, isWater, ammoType);
  761. }
  762. }
  763. void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner) { }
  764. void OnChildItemRemoved(InventoryItem item) { }
  765. void OnChildItemReceived(InventoryItem item) { }
  766. void OnItemAttachmentSlotChanged (notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc) {}
  767. void EEItemLocationChanged (notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
  768. {
  769. EntityAI old_owner = oldLoc.GetParent();
  770. EntityAI new_owner = newLoc.GetParent();
  771. OnItemLocationChanged(old_owner, new_owner);
  772. if (oldLoc.GetType() == InventoryLocationType.ATTACHMENT && newLoc.GetType() == InventoryLocationType.ATTACHMENT)
  773. {
  774. OnItemAttachmentSlotChanged(oldLoc,newLoc);
  775. }
  776. if (oldLoc.GetType() == InventoryLocationType.ATTACHMENT)
  777. {
  778. if (old_owner)
  779. OnWasDetached(old_owner, oldLoc.GetSlot());
  780. else
  781. Error("EntityAI::EEItemLocationChanged - detached, but old_owner is null");
  782. }
  783. if (newLoc.GetType() == InventoryLocationType.ATTACHMENT)
  784. {
  785. if (new_owner)
  786. OnWasAttached(newLoc.GetParent(), newLoc.GetSlot());
  787. else
  788. Error("EntityAI::EEItemLocationChanged - attached, but new_owner is null");
  789. }
  790. }
  791. //! Called from 'IEntity.AddChild'
  792. void EEParentedTo(EntityAI parent)
  793. {
  794. }
  795. //! Called from 'IEntity.RemoveChild' or 'IEntity.AddChild' when hierarchy changes
  796. void EEParentedFrom(EntityAI parent)
  797. {
  798. }
  799. void EEInventoryIn (Man newParentMan, EntityAI diz, EntityAI newParent)
  800. {
  801. }
  802. void EEInventoryOut (Man oldParentMan, EntityAI diz, EntityAI newParent)
  803. {
  804. m_LastUpdatedTime = GetGame().GetTickTime();
  805. if (GetInventory() && newParent == null)
  806. {
  807. GetInventory().ResetFlipCargo();
  808. }
  809. }
  810. void EEAmmoChanged()
  811. {
  812. SetWeightDirty();
  813. }
  814. void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
  815. {
  816. // Notify potential parent that this item was ruined
  817. EntityAI parent = GetHierarchyParent();
  818. if (newLevel == GameConstants.STATE_RUINED)
  819. {
  820. if (parent)
  821. {
  822. parent.OnAttachmentRuined(this);
  823. }
  824. if (!zone)
  825. {
  826. OnDamageDestroyed(oldLevel);
  827. }
  828. AttemptDestructionBehaviour(oldLevel,newLevel, zone);
  829. }
  830. }
  831. //! Called when the health gets to the min value, 'oldLevel' is previous health level, 'oldLevel' -1 means this entity was just spawned
  832. void OnDamageDestroyed(int oldLevel);
  833. void AttemptDestructionBehaviour(int oldLevel, int newLevel, string zone)
  834. {
  835. if (IsDestructionBehaviour() && GetDestructionBehaviour())
  836. {
  837. typename destType = GetDestructionBehaviour().ToType();
  838. if (destType)
  839. {
  840. if (!m_DestructionBehaviourObj)
  841. {
  842. m_DestructionBehaviourObj = DestructionEffectBase.Cast(destType.Spawn());
  843. }
  844. if (m_DestructionBehaviourObj)
  845. {
  846. m_DestructionBehaviourObj.OnHealthLevelChanged(this, oldLevel, newLevel, zone);
  847. }
  848. }
  849. else
  850. {
  851. ErrorEx("Incorrect destruction behaviour type, make sure the class returned in 'GetDestructionBehaviour()' is a valid type inheriting from 'DestructionEffectBase'");
  852. }
  853. }
  854. }
  855. void SetTakeable(bool pState);
  856. //! called on server when the entity is killed
  857. void EEKilled(Object killer)
  858. {
  859. if (m_OnKilledInvoker)
  860. m_OnKilledInvoker.Invoke(this, killer);
  861. GetGame().GetAnalyticsServer().OnEntityKilled(killer, this);
  862. if (ReplaceOnDeath())
  863. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DeathUpdate, DEAD_REPLACE_DELAY, false);
  864. }
  865. bool ReplaceOnDeath()
  866. {
  867. return false;
  868. }
  869. string GetDeadItemName()
  870. {
  871. return "";
  872. }
  873. bool KeepHealthOnReplace()
  874. {
  875. return false;
  876. }
  877. void DeathUpdate()
  878. {
  879. EntityAI dead_entity = EntityAI.Cast( GetGame().CreateObjectEx( GetDeadItemName(), GetPosition(), ECE_OBJECT_SWAP, RF_ORIGINAL ) );
  880. dead_entity.SetOrientation(GetOrientation());
  881. if (KeepHealthOnReplace())
  882. dead_entity.SetHealth(GetHealth());
  883. DeleteSafe();
  884. }
  885. //! Called when some attachment of this parent is ruined. Called on server and client side.
  886. void OnAttachmentRuined(EntityAI attachment);
  887. void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
  888. {
  889. if (m_OnHitByInvoker)
  890. m_OnHitByInvoker.Invoke(this, damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
  891. #ifdef DEVELOPER
  892. //Print("EEHitBy: " + this + "; damageResult:"+ damageResult.GetDamage("","") +"; damageType: "+ damageType +"; source: "+ source +"; component: "+ component +"; dmgZone: "+ dmgZone +"; ammo: "+ ammo +"; modelPos: "+ modelPos);
  893. #endif
  894. }
  895. // called only on the client who caused the hit
  896. void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
  897. {
  898. }
  899. // !Called on PARENT when a child is attached to it.
  900. void EEItemAttached(EntityAI item, string slot_name)
  901. {
  902. int slotId = InventorySlots.GetSlotIdFromString(slot_name);
  903. PropagateExclusionValueRecursive(item.GetAttachmentExclusionMaskAll(slotId),slotId); //Performed from parent to avoid event order issues on swap
  904. SetWeightDirty();
  905. if ( m_ComponentsBank != NULL )
  906. {
  907. for ( int comp_key = 0; comp_key < COMP_TYPE_COUNT; ++comp_key )
  908. {
  909. if ( m_ComponentsBank.IsComponentAlreadyExist(comp_key) )
  910. {
  911. m_ComponentsBank.GetComponent(comp_key).Event_OnItemAttached(item, slot_name);
  912. }
  913. }
  914. }
  915. // Energy Manager
  916. if ( m_EM && item.GetCompEM())
  917. m_EM.OnAttachmentAdded(item);
  918. if ( item.GetInventory().GetCargo() )
  919. m_AttachmentsWithCargo.Insert( item );
  920. if ( item.GetInventory().GetAttachmentSlotsCount() > 0 )
  921. m_AttachmentsWithAttachments.Insert( item );
  922. if ( m_OnItemAttached )
  923. m_OnItemAttached.Invoke( item, slot_name, this );
  924. }
  925. void SwitchItemSelectionTexture(EntityAI item, string slot_name);
  926. void SwitchItemSelectionTextureEx(EItemManipulationContext context, Param par = null);
  927. // !Called on PARENT when a child is detached from it.
  928. void EEItemDetached(EntityAI item, string slot_name)
  929. {
  930. int slotId = InventorySlots.GetSlotIdFromString(slot_name);
  931. ClearExclusionValueRecursive(item.GetAttachmentExclusionMaskAll(slotId),slotId); //Performed from parent to avoid event order issues on swap
  932. SetWeightDirty();
  933. if ( m_ComponentsBank != NULL )
  934. {
  935. for ( int comp_key = 0; comp_key < COMP_TYPE_COUNT; ++comp_key )
  936. {
  937. if ( m_ComponentsBank.IsComponentAlreadyExist(comp_key) )
  938. {
  939. m_ComponentsBank.GetComponent(comp_key).Event_OnItemDetached(item, slot_name);
  940. }
  941. }
  942. }
  943. // Energy Manager
  944. if (m_EM && item.GetCompEM())
  945. m_EM.OnAttachmentRemoved(item);
  946. if ( m_AttachmentsWithCargo.Find( item ) > -1 )
  947. m_AttachmentsWithCargo.RemoveItem( item );
  948. if ( m_AttachmentsWithAttachments.Find( item ) > -1 )
  949. m_AttachmentsWithAttachments.RemoveItem( item );
  950. if ( m_OnItemDetached )
  951. m_OnItemDetached.Invoke( item, slot_name, this );
  952. }
  953. void EECargoIn(EntityAI item)
  954. {
  955. SetWeightDirty();
  956. if( m_OnItemAddedIntoCargo )
  957. m_OnItemAddedIntoCargo.Invoke( item, this );
  958. item.OnMovedInsideCargo(this);
  959. }
  960. void EECargoOut(EntityAI item)
  961. {
  962. SetWeightDirty();
  963. if( m_OnItemRemovedFromCargo )
  964. m_OnItemRemovedFromCargo.Invoke( item, this );
  965. item.OnRemovedFromCargo(this);
  966. }
  967. void EECargoMove(EntityAI item)
  968. {
  969. if( m_OnItemMovedInCargo )
  970. m_OnItemMovedInCargo.Invoke( item, this );
  971. item.OnMovedWithinCargo(this);
  972. }
  973. ScriptInvoker GetOnItemAttached()
  974. {
  975. if( !m_OnItemAttached )
  976. m_OnItemAttached = new ScriptInvoker;
  977. return m_OnItemAttached;
  978. }
  979. ScriptInvoker GetOnItemDetached()
  980. {
  981. if( !m_OnItemDetached )
  982. m_OnItemDetached = new ScriptInvoker;
  983. return m_OnItemDetached;
  984. }
  985. ScriptInvoker GetOnItemAddedIntoCargo()
  986. {
  987. if( !m_OnItemAddedIntoCargo )
  988. m_OnItemAddedIntoCargo = new ScriptInvoker;
  989. return m_OnItemAddedIntoCargo;
  990. }
  991. ScriptInvoker GetOnItemRemovedFromCargo()
  992. {
  993. if( !m_OnItemRemovedFromCargo )
  994. m_OnItemRemovedFromCargo = new ScriptInvoker;
  995. return m_OnItemRemovedFromCargo;
  996. }
  997. ScriptInvoker GetOnItemMovedInCargo()
  998. {
  999. if( !m_OnItemMovedInCargo )
  1000. m_OnItemMovedInCargo = new ScriptInvoker;
  1001. return m_OnItemMovedInCargo;
  1002. }
  1003. ScriptInvoker GetOnItemFlipped()
  1004. {
  1005. if( !m_OnItemFlipped )
  1006. m_OnItemFlipped = new ScriptInvoker;
  1007. return m_OnItemFlipped;
  1008. }
  1009. ScriptInvoker GetOnViewIndexChanged()
  1010. {
  1011. if( !m_OnViewIndexChanged )
  1012. m_OnViewIndexChanged = new ScriptInvoker;
  1013. return m_OnViewIndexChanged;
  1014. }
  1015. ScriptInvoker GetOnSetLock()
  1016. {
  1017. if( !m_OnSetLock )
  1018. m_OnSetLock = new ScriptInvoker;
  1019. return m_OnSetLock;
  1020. }
  1021. ScriptInvoker GetOnReleaseLock()
  1022. {
  1023. if( !m_OnReleaseLock )
  1024. m_OnReleaseLock = new ScriptInvoker;
  1025. return m_OnReleaseLock;
  1026. }
  1027. ScriptInvoker GetOnAttachmentSetLock()
  1028. {
  1029. if( !m_OnAttachmentSetLock )
  1030. m_OnAttachmentSetLock = new ScriptInvoker;
  1031. return m_OnAttachmentSetLock;
  1032. }
  1033. ScriptInvoker GetOnAttachmentReleaseLock()
  1034. {
  1035. if( !m_OnAttachmentReleaseLock )
  1036. m_OnAttachmentReleaseLock = new ScriptInvoker;
  1037. return m_OnAttachmentReleaseLock;
  1038. }
  1039. ScriptInvoker GetOnHitByInvoker()
  1040. {
  1041. if ( !m_OnHitByInvoker )
  1042. m_OnHitByInvoker = new ScriptInvoker;
  1043. return m_OnHitByInvoker;
  1044. }
  1045. ScriptInvoker GetOnKilledInvoker()
  1046. {
  1047. if ( !m_OnKilledInvoker )
  1048. m_OnKilledInvoker = new ScriptInvoker;
  1049. return m_OnKilledInvoker;
  1050. }
  1051. //! Called when this item enters cargo of some container
  1052. void OnMovedInsideCargo(EntityAI container)
  1053. {
  1054. if (m_EM)
  1055. m_EM.HandleMoveInsideCargo(container);
  1056. }
  1057. //! Called when this item exits cargo of some container
  1058. void OnRemovedFromCargo(EntityAI container)
  1059. {
  1060. }
  1061. //! Called when this item moves within cargo of some container
  1062. void OnMovedWithinCargo(EntityAI container)
  1063. {
  1064. }
  1065. //! Called when entity is part of "connected system" and being restored after load
  1066. void EEOnAfterLoad()
  1067. {
  1068. // ENERGY MANAGER
  1069. // Restore connections between devices which were connected before server restart
  1070. if ( m_EM && m_EM.GetRestorePlugState() )
  1071. {
  1072. int b1 = m_EM.GetEnergySourceStorageIDb1();
  1073. int b2 = m_EM.GetEnergySourceStorageIDb2();
  1074. int b3 = m_EM.GetEnergySourceStorageIDb3();
  1075. int b4 = m_EM.GetEnergySourceStorageIDb4();
  1076. // get pointer to EntityAI based on this ID
  1077. EntityAI potential_energy_source = GetGame().GetEntityByPersitentID(b1, b2, b3, b4); // This function is available only in this event!
  1078. // IMPORTANT!
  1079. // Object IDs acquired here become INVALID when electric devices are transfered to another server while in plugged state (like Flashlight plugged into its attachment 9V battery)
  1080. // To avoid issues, these items must be excluded from this system of restoring plug state so they don't unintentionally plug to incorrect devices through these invalid IDs.
  1081. // Therefore their plug state is being restored withing the EEItemAttached() event while being excluded by the following 'if' conditions...
  1082. bool is_attachment = false;
  1083. if (potential_energy_source)
  1084. is_attachment = GetInventory().HasAttachment(potential_energy_source);
  1085. if ( !is_attachment && potential_energy_source )
  1086. is_attachment = potential_energy_source.GetInventory().HasAttachment(this);
  1087. if ( potential_energy_source && potential_energy_source.GetCompEM() /*&& potential_energy_source.HasEnergyManager()*/ && !is_attachment )
  1088. m_EM.PlugThisInto(potential_energy_source); // restore connection
  1089. }
  1090. }
  1091. //! Called when entity is being created as new by CE/ Debug
  1092. void EEOnCECreate()
  1093. {
  1094. }
  1095. //! Called when entity is being loaded from DB or Storage (after all children loaded)
  1096. void AfterStoreLoad()
  1097. {
  1098. }
  1099. //! Called when an item fails to get loaded into the inventory of an entity and gets dropped
  1100. void OnBinLoadItemsDropped()
  1101. {
  1102. if (GetHierarchyRootPlayer())
  1103. GetHierarchyRootPlayer().SetProcessUIWarning(true);
  1104. }
  1105. //! Sets all animation values to 1, making them INVISIBLE if they are configured in models.cfg in such way. These selections must also be defined in the entity's config class in 'AnimationSources'.
  1106. void HideAllSelections()
  1107. {
  1108. string cfg_path = "cfgVehicles " + GetType() + " AnimationSources";
  1109. if ( GetGame().ConfigIsExisting(cfg_path) )
  1110. {
  1111. int selections = GetGame().ConfigGetChildrenCount(cfg_path);
  1112. for (int i = 0; i < selections; i++)
  1113. {
  1114. string selection_name;
  1115. GetGame().ConfigGetChildName(cfg_path, i, selection_name);
  1116. HideSelection(selection_name);
  1117. }
  1118. }
  1119. }
  1120. //! Sets all animation values to 0, making them VISIBLE if they are configured in models.cfg in such way. These selections must also be defined in the entity's config class in 'AnimationSources'.
  1121. void ShowAllSelections()
  1122. {
  1123. string cfg_path = "cfgVehicles " + GetType() + " AnimationSources";
  1124. if ( GetGame().ConfigIsExisting(cfg_path) )
  1125. {
  1126. int selections = GetGame().ConfigGetChildrenCount(cfg_path);
  1127. for (int i = 0; i < selections; i++)
  1128. {
  1129. string selection_name;
  1130. GetGame().ConfigGetChildName(cfg_path, i, selection_name);
  1131. ShowSelection(selection_name);
  1132. }
  1133. }
  1134. }
  1135. /**@fn CanReceiveAttachment
  1136. * @brief calls this->CanReceiveAttachment(attachment)
  1137. * @return true if action allowed
  1138. *
  1139. * @note: return scriptConditionExecute(this, attachment, "CanReceiveAttachment");
  1140. **/
  1141. bool CanReceiveAttachment (EntityAI attachment, int slotId)
  1142. {
  1143. //generic occupancy check
  1144. EntityAI currentAtt = GetInventory().FindAttachment(slotId);
  1145. bool hasInternalConflict = attachment.HasInternalExclusionConflicts(slotId);
  1146. set<int> diff;
  1147. InventoryLocation curLoc = new InventoryLocation();
  1148. if (currentAtt) //probably a swap or same-type swap
  1149. {
  1150. diff = attachment.GetAttachmentExclusionMaskAll(slotId);
  1151. diff.RemoveItems(currentAtt.GetAttachmentExclusionMaskAll(slotId));
  1152. if (diff.Count() == 0)
  1153. {
  1154. return !hasInternalConflict;
  1155. }
  1156. else
  1157. {
  1158. return !hasInternalConflict && !IsExclusionFlagPresentRecursive(diff,slotId);
  1159. }
  1160. }
  1161. else if (attachment.GetInventory().GetCurrentInventoryLocation(curLoc) && curLoc.GetType() == InventoryLocationType.ATTACHMENT)
  1162. {
  1163. EntityAI rootOwner = attachment.GetHierarchyRoot();
  1164. if (rootOwner && rootOwner == this.GetHierarchyRoot()) //attachment within the same exclusion hierarchy context
  1165. {
  1166. diff = attachment.GetAttachmentExclusionMaskAll(slotId);
  1167. diff.RemoveItems(attachment.GetAttachmentExclusionMaskAll(curLoc.GetSlot()));
  1168. if (diff.Count() == 0)
  1169. {
  1170. return !hasInternalConflict;
  1171. }
  1172. else
  1173. {
  1174. return !hasInternalConflict && !IsExclusionFlagPresentRecursive(diff,slotId);
  1175. }
  1176. }
  1177. }
  1178. return !hasInternalConflict && !IsExclusionFlagPresentRecursive(attachment.GetAttachmentExclusionMaskAll(slotId),slotId);
  1179. }
  1180. /**@fn CanLoadAsAttachment
  1181. * @brief calls this->CanLoadAsAttachment(attachment), is called on server start when loading in the storage
  1182. * @return true if action allowed
  1183. *
  1184. * @note: return scriptConditionExecute(this, attachment, "CanLoadAsAttachment");
  1185. **/
  1186. bool CanLoadAttachment(EntityAI attachment)
  1187. {
  1188. return true;
  1189. }
  1190. /**@fn CanPutAsAttachment
  1191. * @brief calls this->CanPutAsAttachment(parent)
  1192. * @param[in] parent \p target entity this is trying to attach to
  1193. * @return true if action allowed
  1194. *
  1195. * @note: engine code is scriptConditionExecute(this, parent, "CanPutAsAttachment")
  1196. **/
  1197. bool CanPutAsAttachment (EntityAI parent)
  1198. {
  1199. return !IsHologram();
  1200. }
  1201. //If return true, item can be attached even from parent to this. Item will be switched during proccess. (only hands)
  1202. bool CanSwitchDuringAttach(EntityAI parent)
  1203. {
  1204. return false;
  1205. }
  1206. /**@fn CanReleaseAttachment
  1207. * @brief calls this->CanReleaseAttachment(attachment)
  1208. * @return true if action allowed
  1209. *
  1210. * @note: return scriptConditionExecute(this, attachment, "CanReleaseAttachment");
  1211. **/
  1212. bool CanReleaseAttachment (EntityAI attachment)
  1213. {
  1214. if( attachment && attachment.GetInventory() && GetInventory() )
  1215. {
  1216. InventoryLocation il = new InventoryLocation();
  1217. attachment.GetInventory().GetCurrentInventoryLocation( il );
  1218. if( il.IsValid() )
  1219. {
  1220. int slot = il.GetSlot();
  1221. return !GetInventory().GetSlotLock( slot );
  1222. }
  1223. }
  1224. return true;
  1225. }
  1226. /**@fn CanDetachAttachment
  1227. * @brief calls this->CanDetachAttachment(parent)
  1228. * @return true if action allowed
  1229. *
  1230. * @note: return scriptConditionExecute(this, parent, "CanDetachAttachment");
  1231. **/
  1232. bool CanDetachAttachment (EntityAI parent)
  1233. {
  1234. return true;
  1235. }
  1236. bool CanBeFSwaped()
  1237. {
  1238. return true;
  1239. }
  1240. bool CanCombineAttachment(notnull EntityAI e, int slot, bool stack_max_limit = false)
  1241. {
  1242. EntityAI att = GetInventory().FindAttachment(slot);
  1243. if(att)
  1244. return att.CanBeCombined(e, true, stack_max_limit);
  1245. return false;
  1246. }
  1247. bool CanBeCombined(EntityAI other_item, bool reservation_check = true, bool stack_max_limit = false )
  1248. {
  1249. return false;
  1250. }
  1251. void CombineItemsEx(EntityAI entity2, bool use_stack_max = false );
  1252. void SplitIntoStackMaxEx(EntityAI destination_entity, int slot_id);
  1253. void CombineItemsClient(EntityAI entity2, bool use_stack_max = false )
  1254. {}
  1255. void SplitIntoStackMaxClient(EntityAI destination_entity, int slot_id);
  1256. /**@fn CanReceiveItemIntoCargo
  1257. * @brief calls this->CanReceiveItemIntoCargo(item)
  1258. * @return true if action allowed
  1259. *
  1260. * @note: return scriptConditionExecute(this, item, "CanReceiveItemIntoCargo");
  1261. **/
  1262. bool CanReceiveItemIntoCargo(EntityAI item)
  1263. {
  1264. if (GetInventory() && GetInventory().GetCargo())
  1265. return GetInventory().GetCargo().CanReceiveItemIntoCargo(item));
  1266. return true;
  1267. }
  1268. /**@fn CanLoadItemIntoCargo
  1269. * @brief calls this->CanLoadItemIntoCargo(item), is called on server start when loading in the storage
  1270. * @return true if action allowed
  1271. *
  1272. * @note: return scriptConditionExecute(this, item, "CanLoadItemIntoCargo");
  1273. **/
  1274. bool CanLoadItemIntoCargo(EntityAI item)
  1275. {
  1276. return true;
  1277. }
  1278. /**@fn CanPutInCargo
  1279. * @brief calls this->CanPutInCargo(parent)
  1280. * @return true if action allowed
  1281. *
  1282. * @note: return scriptConditionExecute(this, parent, "CanPutInCargo");
  1283. **/
  1284. bool CanPutInCargo (EntityAI parent)
  1285. {
  1286. return !IsHologram();
  1287. }
  1288. /**@fn CanSwapItemInCargo
  1289. * @brief calls this->CanSwapItemInCargo(child_entity, new_entity)
  1290. * @return true if action allowed
  1291. *
  1292. * @note: return ScriptConditionExecute(GetOwner(), child_entity, "CanSwapItemInCargo", new_entity);
  1293. **/
  1294. bool CanSwapItemInCargo (EntityAI child_entity, EntityAI new_entity)
  1295. {
  1296. if (GetInventory() && GetInventory().GetCargo())
  1297. return GetInventory().GetCargo().CanSwapItemInCargo(child_entity, new_entity));
  1298. return true;
  1299. }
  1300. /**@fn CanReleaseCargo
  1301. * @brief calls this->CanReleaseCargo(cargo)
  1302. * @return true if action allowed
  1303. *
  1304. * @note: return scriptConditionExecute(this, cargo, "CanReleaseCargo");
  1305. **/
  1306. bool CanReleaseCargo (EntityAI cargo)
  1307. {
  1308. return true;
  1309. }
  1310. /**@fn CanRemoveFromCargo
  1311. * @brief calls this->CanRemoveFromCargo(parent)
  1312. * @return true if action allowed
  1313. *
  1314. * @note: return scriptConditionExecute(this, parent, "CanRemoveFromCargo");
  1315. **/
  1316. bool CanRemoveFromCargo (EntityAI parent)
  1317. {
  1318. return true;
  1319. }
  1320. /**@fn CanReceiveItemIntoInventory
  1321. * @brief calls this->CanReceiveItemIntoInventory(item)
  1322. * @return true if action allowed
  1323. *
  1324. * @note: return scriptConditionExecute(this, , "CanReceiveItemIntoInventory");
  1325. **/
  1326. /*bool CanReceiveItemIntoInventory (EntityAI entity_ai)
  1327. {
  1328. return true;
  1329. }*/
  1330. /**@fn CanPutInInventory
  1331. * @brief calls this->CanPutInInventory(parent)
  1332. * @return true if action allowed
  1333. *
  1334. * @note: return scriptConditionExecute(this, parent, "ConditionIntoInventory");
  1335. **/
  1336. /*bool CanPutInInventory (EntityAI parent)
  1337. {
  1338. return true;
  1339. }*/
  1340. /**@fn CanReceiveItemIntoHands
  1341. * @brief calls this->CanReceiveItemIntoHands(item_to_hands)
  1342. * @return true if action allowed
  1343. *
  1344. * @note: scriptConditionExecute(this, item_to_hands, "CanReceiveItemIntoHands");
  1345. **/
  1346. bool CanReceiveItemIntoHands (EntityAI item_to_hands)
  1347. {
  1348. return true;
  1349. }
  1350. bool AreChildrenAccessible()
  1351. {
  1352. InventoryLocation lcn = new InventoryLocation();
  1353. EntityAI ent = this;
  1354. int attachmentDepth = 0;
  1355. while (ent)
  1356. {
  1357. if (ent.GetInventory().GetCurrentInventoryLocation(lcn) && lcn.IsValid())
  1358. {
  1359. if (lcn.GetType() == InventoryLocationType.CARGO || lcn.GetType() == InventoryLocationType.PROXYCARGO)
  1360. {
  1361. return false;
  1362. }
  1363. //hands treated as regular attachment here
  1364. if (lcn.GetType() == InventoryLocationType.ATTACHMENT || lcn.GetType() == InventoryLocationType.HANDS)
  1365. {
  1366. attachmentDepth++;
  1367. }
  1368. }
  1369. ent = ent.GetHierarchyParent();
  1370. }
  1371. return attachmentDepth <= GameConstants.INVENTORY_MAX_REACHABLE_DEPTH_ATT;
  1372. }
  1373. bool IsBeingPlaced()
  1374. {
  1375. return false;
  1376. }
  1377. override bool IsHologram()
  1378. {
  1379. return false;
  1380. }
  1381. bool CanSaveItemInHands (EntityAI item_in_hands)
  1382. {
  1383. return true;
  1384. }
  1385. /**@fn CanPutIntoHands
  1386. * @brief calls this->CanPutIntoHands(parent)
  1387. * @return true if action allowed
  1388. *
  1389. * @note: return scriptConditionExecute(this, parent, "CanPutIntoHands");
  1390. **/
  1391. bool CanPutIntoHands (EntityAI parent)
  1392. {
  1393. return !IsHologram();
  1394. }
  1395. /**@fn CanReleaseFromHands
  1396. * @brief calls this->CanReleaseFromHands(handheld)
  1397. * @return true if action allowed
  1398. *
  1399. * @note: scriptConditionExecute(this, handheld, "CanReleaseFromHands");
  1400. **/
  1401. bool CanReleaseFromHands (EntityAI handheld)
  1402. {
  1403. return true;
  1404. }
  1405. /**@fn CanRemoveFromHands
  1406. * @brief calls this->CanRemoveFromHands(parent)
  1407. * @return true if action allowed
  1408. *
  1409. * @note: return scriptConditionExecute(this, parent, "CanRemoveFromHands");
  1410. **/
  1411. bool CanRemoveFromHands (EntityAI parent)
  1412. {
  1413. return true;
  1414. }
  1415. /**@fn CanDisplayAttachmentSlot
  1416. * @param slot_name->name of the attachment slot that will or won't be displayed
  1417. * @return true if attachment icon can be displayed in UI (inventory)
  1418. **/
  1419. bool CanDisplayAttachmentSlot( string slot_name )
  1420. {
  1421. Debug.LogWarning("Obsolete function - use CanDisplayAttachmentSlot with slot id parameter");
  1422. return InventorySlots.GetShowForSlotId(InventorySlots.GetSlotIdFromString(slot_name));
  1423. }
  1424. /**@fn CanDisplayAttachmentSlot
  1425. * @param slot_id->id of the attachment slot that will or won't be displayed
  1426. * @return true if attachment icon can be displayed in UI (inventory)
  1427. **/
  1428. bool CanDisplayAttachmentSlot( int slot_id )
  1429. {
  1430. return InventorySlots.GetShowForSlotId(slot_id);
  1431. }
  1432. /**@fn CanDisplayAnyAttachmentSlot
  1433. * @return true if any attachment slot can be shown
  1434. **/
  1435. bool CanDisplayAnyAttachmentSlot()
  1436. {
  1437. int count = GetInventory().GetAttachmentSlotsCount();
  1438. int slotID;
  1439. for (int i = 0; i < count; i++)
  1440. {
  1441. slotID = GetInventory().GetAttachmentSlotId(i);
  1442. if (CanDisplayAttachmentSlot(slotID))
  1443. {
  1444. return true;
  1445. }
  1446. }
  1447. return false;
  1448. }
  1449. /**@fn CanDisplayAttachmentCategory
  1450. * @param category_name->name of the attachment category that will or won't be displayed
  1451. * @return true if attachment icon can be displayed in UI (inventory)
  1452. **/
  1453. bool CanDisplayAttachmentCategory( string category_name )
  1454. {
  1455. return true;
  1456. }
  1457. /**@fn CanDisplayCargo
  1458. * @return true if cargo can be displayed in UI (inventory)
  1459. **/
  1460. bool CanDisplayCargo()
  1461. {
  1462. return GetInventory().GetCargo() != null;
  1463. }
  1464. /**@fn CanAssignToQuickbar
  1465. * @return true if item can be assigned to quickbar safely
  1466. **/
  1467. bool CanAssignToQuickbar()
  1468. {
  1469. return true;
  1470. }
  1471. /**@fn CanAssignAttachmentsToQuickbar
  1472. * @return true if attached item can be assigned to quickbar safely
  1473. **/
  1474. bool CanAssignAttachmentsToQuickbar()
  1475. {
  1476. return true;
  1477. }
  1478. /**@fn IgnoreOutOfReachCondition
  1479. * @return if true, attachment condition for out of reach (inventory) will be ignored
  1480. **/
  1481. bool IgnoreOutOfReachCondition()
  1482. {
  1483. return GetHierarchyRootPlayer() == GetGame().GetPlayer();
  1484. }
  1485. // !Called on CHILD when it's attached to parent.
  1486. void OnWasAttached( EntityAI parent, int slot_id );
  1487. // !Called on CHILD when it's detached from parent.
  1488. void OnWasDetached( EntityAI parent, int slot_id )
  1489. {
  1490. if (!IsFlagSet(EntityFlags.VISIBLE))
  1491. {
  1492. SetInvisible(false);
  1493. OnInvisibleSet(false);
  1494. SetInvisibleRecursive(false,parent);
  1495. }
  1496. }
  1497. void OnCargoChanged() { }
  1498. bool IsTakeable()
  1499. {
  1500. return false;
  1501. }
  1502. proto native GameInventory GetInventory();
  1503. proto native void CreateAndInitInventory();
  1504. proto native void DestroyInventory();
  1505. int GetSlotsCountCorrect()
  1506. {
  1507. if (GetInventory())
  1508. return GetInventory().GetAttachmentSlotsCount();
  1509. else
  1510. return -1;
  1511. }
  1512. EntityAI FindAttachmentBySlotName(string slot_name)
  1513. {
  1514. if ( GetGame() )
  1515. {
  1516. int slot_id = InventorySlots.GetSlotIdFromString(slot_name);
  1517. if (slot_id != InventorySlots.INVALID)
  1518. return GetInventory().FindAttachment(slot_id);
  1519. }
  1520. return null;
  1521. }
  1522. /**@fn IsLockedInSlot
  1523. * @return true if entity is locked in attachment slot
  1524. **/
  1525. bool IsLockedInSlot()
  1526. {
  1527. EntityAI parent = GetHierarchyParent();
  1528. if ( parent )
  1529. {
  1530. InventoryLocation inventory_location = new InventoryLocation();
  1531. GetInventory().GetCurrentInventoryLocation( inventory_location );
  1532. return parent.GetInventory().GetSlotLock( inventory_location.GetSlot() );
  1533. }
  1534. return false;
  1535. }
  1536. /**
  1537. \brief Put item anywhere into this entity (as attachment or into cargo, recursively)
  1538. */
  1539. bool PredictiveTakeEntityToInventory (FindInventoryLocationType flags, notnull EntityAI item)
  1540. {
  1541. if ( GetGame().IsMultiplayer() )
  1542. return GetInventory().TakeEntityToInventory(InventoryMode.JUNCTURE, flags, item);
  1543. else
  1544. return GetInventory().TakeEntityToInventory(InventoryMode.PREDICTIVE, flags, item);
  1545. }
  1546. bool LocalTakeEntityToInventory (FindInventoryLocationType flags, notnull EntityAI item)
  1547. {
  1548. return GetInventory().TakeEntityToInventory(InventoryMode.LOCAL, flags, item);
  1549. }
  1550. bool ServerTakeEntityToInventory (FindInventoryLocationType flags, notnull EntityAI item)
  1551. {
  1552. return GetInventory().TakeEntityToInventory(InventoryMode.SERVER, flags, item);
  1553. }
  1554. bool PredictiveTakeEntityToTargetInventory (notnull EntityAI target, FindInventoryLocationType flags, notnull EntityAI item)
  1555. {
  1556. if ( GetGame().IsMultiplayer() )
  1557. return GetInventory().TakeEntityToTargetInventory(InventoryMode.JUNCTURE, target, flags, item);
  1558. else
  1559. return GetInventory().TakeEntityToTargetInventory(InventoryMode.PREDICTIVE, target, flags, item);
  1560. }
  1561. bool LocalTakeEntityToTargetInventory (notnull EntityAI target, FindInventoryLocationType flags, notnull EntityAI item)
  1562. {
  1563. return GetInventory().TakeEntityToTargetInventory(InventoryMode.LOCAL, target, flags, item);
  1564. }
  1565. bool ServerTakeEntityToTargetInventory (notnull EntityAI target, FindInventoryLocationType flags, notnull EntityAI item)
  1566. {
  1567. return GetInventory().TakeEntityToTargetInventory(InventoryMode.SERVER, target, flags, item);
  1568. }
  1569. /**
  1570. \brief Put item into into cargo
  1571. */
  1572. bool PredictiveTakeEntityToCargo (notnull EntityAI item)
  1573. {
  1574. if ( GetGame().IsMultiplayer() )
  1575. return GetInventory().TakeEntityToCargo(InventoryMode.JUNCTURE, item);
  1576. else
  1577. return GetInventory().TakeEntityToCargo(InventoryMode.PREDICTIVE, item);
  1578. }
  1579. bool LocalTakeEntityToCargo (notnull EntityAI item)
  1580. {
  1581. return GetInventory().TakeEntityToCargo(InventoryMode.LOCAL, item);
  1582. }
  1583. bool ServerTakeEntityToCargo (notnull EntityAI item)
  1584. {
  1585. return GetInventory().TakeEntityToCargo(InventoryMode.SERVER, item);
  1586. }
  1587. bool PredictiveTakeEntityToTargetCargo (notnull EntityAI target, notnull EntityAI item)
  1588. {
  1589. if ( GetGame().IsMultiplayer() )
  1590. return GetInventory().TakeEntityToTargetCargo(InventoryMode.JUNCTURE, target, item);
  1591. else
  1592. return GetInventory().TakeEntityToTargetCargo(InventoryMode.PREDICTIVE, target, item);
  1593. }
  1594. bool LocalTakeEntityToTargetCargo (notnull EntityAI target, notnull EntityAI item)
  1595. {
  1596. return GetInventory().TakeEntityToTargetCargo(InventoryMode.LOCAL, target, item);
  1597. }
  1598. bool ServerTakeEntityToTargetCargo (notnull EntityAI target, notnull EntityAI item)
  1599. {
  1600. return GetInventory().TakeEntityToTargetCargo(InventoryMode.SERVER, target, item);
  1601. }
  1602. /**
  1603. \brief Put item into into cargo on specific cargo location
  1604. */
  1605. bool PredictiveTakeEntityToCargoEx (notnull EntityAI item, int idx, int row, int col)
  1606. {
  1607. if ( GetGame().IsMultiplayer() )
  1608. return GetInventory().TakeEntityToCargoEx(InventoryMode.JUNCTURE, item, idx, row, col);
  1609. else
  1610. return GetInventory().TakeEntityToCargoEx(InventoryMode.PREDICTIVE, item, idx, row, col);
  1611. }
  1612. bool LocalTakeEntityToCargoEx (notnull EntityAI item, int idx, int row, int col)
  1613. {
  1614. return GetInventory().TakeEntityToCargoEx(InventoryMode.LOCAL, item, idx, row, col);
  1615. }
  1616. bool PredictiveTakeEntityToTargetCargoEx (notnull CargoBase cargo, notnull EntityAI item, int row, int col)
  1617. {
  1618. if ( GetGame().IsMultiplayer() )
  1619. return GetInventory().TakeEntityToTargetCargoEx(InventoryMode.JUNCTURE, cargo, item, row, col);
  1620. else
  1621. return GetInventory().TakeEntityToTargetCargoEx(InventoryMode.PREDICTIVE, cargo, item, row, col);
  1622. }
  1623. bool LocalTakeEntityToTargetCargoEx (notnull CargoBase cargo, notnull EntityAI item, int row, int col)
  1624. {
  1625. return GetInventory().TakeEntityToTargetCargoEx(InventoryMode.LOCAL, cargo, item, row, col);
  1626. }
  1627. bool ServerTakeEntityToTargetCargoEx (notnull CargoBase cargo, notnull EntityAI item, int row, int col)
  1628. {
  1629. return GetInventory().TakeEntityToTargetCargoEx(InventoryMode.SERVER, cargo, item, row, col);
  1630. }
  1631. /**
  1632. \brief Returns if item can be added as attachment on specific slot. Note that slot index IS NOT slot ID! Slot ID is defined in DZ/data/config.cpp
  1633. */
  1634. bool PredictiveTakeEntityAsAttachmentEx (notnull EntityAI item, int slot)
  1635. {
  1636. if ( GetGame().IsMultiplayer() )
  1637. return GetInventory().TakeEntityAsAttachmentEx(InventoryMode.JUNCTURE, item, slot);
  1638. else
  1639. return GetInventory().TakeEntityAsAttachmentEx(InventoryMode.PREDICTIVE, item, slot);
  1640. }
  1641. bool LocalTakeEntityAsAttachmentEx (notnull EntityAI item, int slot)
  1642. {
  1643. return GetInventory().TakeEntityAsAttachmentEx(InventoryMode.LOCAL, item, slot);
  1644. }
  1645. bool ServerTakeEntityAsAttachmentEx (notnull EntityAI item, int slot)
  1646. {
  1647. return GetInventory().TakeEntityAsAttachmentEx(InventoryMode.SERVER, item, slot);
  1648. }
  1649. bool PredictiveTakeEntityToTargetAttachmentEx (notnull EntityAI target, notnull EntityAI item, int slot)
  1650. {
  1651. if ( GetGame().IsMultiplayer() )
  1652. return GetInventory().TakeEntityAsTargetAttachmentEx(InventoryMode.JUNCTURE, target, item, slot);
  1653. else
  1654. return GetInventory().TakeEntityAsTargetAttachmentEx(InventoryMode.PREDICTIVE, target, item, slot);
  1655. }
  1656. bool LocalTakeEntityToTargetAttachmentEx (notnull EntityAI target, notnull EntityAI item, int slot)
  1657. {
  1658. return GetInventory().TakeEntityAsTargetAttachmentEx(InventoryMode.LOCAL, target, item, slot);
  1659. }
  1660. bool ServerTakeEntityToTargetAttachmentEx (notnull EntityAI target, notnull EntityAI item, int slot)
  1661. {
  1662. return GetInventory().TakeEntityAsTargetAttachmentEx(InventoryMode.SERVER, target, item, slot);
  1663. }
  1664. bool PredictiveTakeEntityToTargetAttachment (notnull EntityAI target, notnull EntityAI item)
  1665. {
  1666. if ( GetGame().IsMultiplayer() )
  1667. return GetInventory().TakeEntityAsTargetAttachment(InventoryMode.JUNCTURE, target, item);
  1668. else
  1669. return GetInventory().TakeEntityAsTargetAttachment(InventoryMode.PREDICTIVE, target, item);
  1670. }
  1671. bool LocalTakeEntityToTargetAttachment (notnull EntityAI target, notnull EntityAI item)
  1672. {
  1673. return GetInventory().TakeEntityAsTargetAttachment(InventoryMode.LOCAL, target, item);
  1674. }
  1675. bool ServerTakeEntityToTargetAttachment (notnull EntityAI target, notnull EntityAI item)
  1676. {
  1677. return GetInventory().TakeEntityAsTargetAttachment(InventoryMode.SERVER, target, item);
  1678. }
  1679. bool PredictiveTakeToDst (notnull InventoryLocation src, notnull InventoryLocation dst)
  1680. {
  1681. if ( GetGame().IsMultiplayer() )
  1682. return GetInventory().TakeToDst(InventoryMode.JUNCTURE, src, dst);
  1683. else
  1684. return GetInventory().TakeToDst(InventoryMode.PREDICTIVE, src, dst);
  1685. }
  1686. bool LocalTakeToDst (notnull InventoryLocation src, notnull InventoryLocation dst)
  1687. {
  1688. return GetInventory().TakeToDst(InventoryMode.LOCAL, src, dst);
  1689. }
  1690. bool ServerTakeToDst (notnull InventoryLocation src, notnull InventoryLocation dst)
  1691. {
  1692. return GetInventory().TakeToDst(InventoryMode.SERVER, src, dst);
  1693. }
  1694. /**
  1695. \brief Put item into as attachment
  1696. */
  1697. bool PredictiveTakeEntityAsAttachment(notnull EntityAI item)
  1698. {
  1699. if (GetGame().IsMultiplayer())
  1700. return GetInventory().TakeEntityAsAttachment(InventoryMode.JUNCTURE, item);
  1701. else
  1702. return GetInventory().TakeEntityAsAttachment(InventoryMode.PREDICTIVE, item);
  1703. }
  1704. bool LocalTakeEntityAsAttachment (notnull EntityAI item)
  1705. {
  1706. return GetInventory().TakeEntityAsAttachment(InventoryMode.LOCAL, item);
  1707. }
  1708. bool ServerTakeEntityAsAttachment (notnull EntityAI item)
  1709. {
  1710. return GetInventory().TakeEntityAsAttachment(InventoryMode.SERVER, item);
  1711. }
  1712. bool PredictiveDropEntity(notnull EntityAI item)
  1713. {
  1714. return false;
  1715. }
  1716. bool LocalDropEntity(notnull EntityAI item)
  1717. {
  1718. return false;
  1719. }
  1720. bool ServerDropEntity(notnull EntityAI item)
  1721. {
  1722. return false;
  1723. }
  1724. /**
  1725. \brief Get attached entity by type
  1726. */
  1727. EntityAI GetAttachmentByType(typename type)
  1728. {
  1729. for ( int i = 0; i < GetInventory().AttachmentCount(); i++ )
  1730. {
  1731. EntityAI attachment = GetInventory().GetAttachmentFromIndex( i );
  1732. if ( attachment && attachment.IsInherited( type ) )
  1733. return attachment;
  1734. }
  1735. return NULL;
  1736. }
  1737. /**
  1738. \brief Get attached entity by config type name
  1739. */
  1740. EntityAI GetAttachmentByConfigTypeName(string type)
  1741. {
  1742. for ( int i = 0; i < GetInventory().AttachmentCount(); i++ )
  1743. {
  1744. EntityAI attachment = GetInventory().GetAttachmentFromIndex ( i );
  1745. if ( attachment.IsKindOf ( type ) )
  1746. return attachment;
  1747. }
  1748. return NULL;
  1749. }
  1750. /**
  1751. \brief Returns if item can be dropped out from this entity
  1752. */
  1753. bool CanDropEntity(notnull EntityAI item)
  1754. {
  1755. return true;
  1756. }
  1757. EntityAI SpawnInInventoryOrGroundPos(string object_name, GameInventory inv, vector pos)
  1758. {
  1759. if (inv)
  1760. {
  1761. EntityAI res = inv.CreateInInventory(object_name);
  1762. if (res)
  1763. {
  1764. return res;
  1765. }
  1766. }
  1767. return SpawnEntityOnGroundPos(object_name, pos);
  1768. }
  1769. /**
  1770. **/
  1771. EntityAI SpawnEntityOnGroundPos(string object_name, vector pos)
  1772. {
  1773. InventoryLocation il = new InventoryLocation();
  1774. vector mat[4];
  1775. Math3D.MatrixIdentity4(mat);
  1776. mat[3] = pos;
  1777. il.SetGround(NULL, mat);
  1778. return SpawnEntity(object_name, il,ECE_PLACE_ON_SURFACE,RF_DEFAULT);
  1779. }
  1780. /**
  1781. **/
  1782. EntityAI SpawnEntityOnGround(string object_name, vector mat[4])
  1783. {
  1784. InventoryLocation il = new InventoryLocation();
  1785. il.SetGround(NULL, mat);
  1786. return SpawnEntity(object_name, il,ECE_PLACE_ON_SURFACE,RF_DEFAULT);
  1787. }
  1788. //----------------------------------------------------------------
  1789. bool CanSwapEntities(EntityAI otherItem, InventoryLocation otherDestination, InventoryLocation destination)
  1790. {
  1791. return true;
  1792. }
  1793. // Forward declarations to allow lower modules to access properties that are modified from higher modules
  1794. // These are mainly used within the ItemBase
  1795. void SetWet(float value, bool allow_client = false);
  1796. void AddWet(float value);
  1797. void SetWetMax();
  1798. float GetWet()
  1799. {
  1800. return 0;
  1801. }
  1802. float GetWetMax()
  1803. {
  1804. return 0;
  1805. }
  1806. float GetWetMin()
  1807. {
  1808. return 0;
  1809. }
  1810. float GetWetInit()
  1811. {
  1812. return 0;
  1813. }
  1814. bool HasWetness()
  1815. {
  1816. return GetWetMax() - GetWetMin() != 0;
  1817. }
  1818. void OnWetChanged(float newVal, float oldVal);
  1819. void OnWetLevelChanged(EWetnessLevel newLevel, EWetnessLevel oldLevel);
  1820. // ! Returns current wet level of the entity
  1821. EWetnessLevel GetWetLevel();
  1822. // ! Calculates wet level from a given wetness, to get level of an entity, use 'GetWetLevel()' instead
  1823. static EWetnessLevel GetWetLevelInternal(float wetness)
  1824. {
  1825. if (wetness < GameConstants.STATE_DAMP)
  1826. {
  1827. return EWetnessLevel.DRY;
  1828. }
  1829. else if (wetness < GameConstants.STATE_WET)
  1830. {
  1831. return EWetnessLevel.DAMP;
  1832. }
  1833. else if (wetness < GameConstants.STATE_SOAKING_WET)
  1834. {
  1835. return EWetnessLevel.WET;
  1836. }
  1837. else if (wetness < GameConstants.STATE_DRENCHED)
  1838. {
  1839. return EWetnessLevel.SOAKING;
  1840. }
  1841. return EWetnessLevel.DRENCHED;
  1842. }
  1843. //----------------------------------------------------------------
  1844. bool HasQuantity()
  1845. {
  1846. return false;
  1847. }
  1848. bool SetQuantity(float value, bool destroy_config = true, bool destroy_forced = false, bool allow_client = false, bool clamp_to_stack_max = true);
  1849. float GetQuantity()
  1850. {
  1851. return 0;
  1852. }
  1853. float GetQuantityNormalized()
  1854. {
  1855. return 0;
  1856. }
  1857. int GetQuantityMax()
  1858. {
  1859. return 0;
  1860. }
  1861. int GetQuantityMin()
  1862. {
  1863. return 0;
  1864. }
  1865. void SetQuantityToMinimum();
  1866. int GetTargetQuantityMax(int attSlotID = -1)
  1867. {
  1868. return 0;
  1869. }
  1870. int GetQuickBarBonus()
  1871. {
  1872. return 0;
  1873. }
  1874. //----------------------------------------------------------------
  1875. bool UseConfigInitTemperature()
  1876. {
  1877. return (IsMan() || IsAnimal() || IsZombie()) && IsAlive() || IsCorpse();
  1878. }
  1879. protected void InitTemperature()
  1880. {
  1881. EntityAI rootParent = GetHierarchyRoot();
  1882. bool isParentAliveOrganism = false;
  1883. if (rootParent && rootParent != this)
  1884. isParentAliveOrganism = (rootParent.IsMan() || rootParent.IsAnimal() || rootParent.IsZombie()) && rootParent.IsAlive();
  1885. if (UseConfigInitTemperature())
  1886. {
  1887. SetTemperatureDirect(m_VarTemperatureInit);
  1888. }
  1889. else if (isParentAliveOrganism) //living player's inventory etc.
  1890. {
  1891. SetTemperatureDirect(rootParent.GetTemperature());
  1892. }
  1893. else
  1894. {
  1895. SetTemperatureDirect(g_Game.GetMission().GetWorldData().GetBaseEnvTemperatureAtObject(this));
  1896. }
  1897. SetFrozen(GetTemperature() < GetTemperatureFreezeThreshold());
  1898. }
  1899. void SetTemperatureDirect(float value, bool allow_client = false)
  1900. {
  1901. if (!IsServerCheck(allow_client))
  1902. return;
  1903. float min = GetTemperatureMin();
  1904. float max = GetTemperatureMax();
  1905. float previousValue = m_VarTemperature;
  1906. m_VarTemperature = Math.Clamp(value, min, max);
  1907. if (previousValue != m_VarTemperature)
  1908. SetVariableMask(VARIABLE_TEMPERATURE);
  1909. }
  1910. //! not really deprecated, but missing context info from TemperatureData. Default values used instead.
  1911. void SetTemperature(float value, bool allow_client = false)
  1912. {
  1913. /*#ifdef DEVELOPER
  1914. ErrorEx("Obsolete 'SetTemperature' called! Metadata will be extrapolated from base values.");
  1915. #endif*/
  1916. if (!IsServerCheck(allow_client))
  1917. return;
  1918. SetTemperatureEx(new TemperatureData(value));
  1919. }
  1920. void AddTemperature(float value)
  1921. {
  1922. SetTemperature(value + GetTemperature());
  1923. }
  1924. ////////////////////////////////////////////
  1925. //! sets temperature, handles base overheating and freezing state progression logics
  1926. void SetTemperatureEx(TemperatureData data)
  1927. {
  1928. #ifdef DEVELOPER
  1929. m_LastFTChangeTime = -1;
  1930. m_PresumedTimeRemaining = -1;
  1931. #endif
  1932. if (!CanHaveTemperature())
  1933. {
  1934. Debug.Log("SetTemperatureEx | entity " + this + " does not have temperature range defined!");
  1935. return;
  1936. }
  1937. if (!m_TAC.TryAccessSource(data))
  1938. return;
  1939. if (!IsServerCheck(false))
  1940. return;
  1941. InterpolateTempData(TemperatureDataInterpolated.Cast(data));
  1942. float target = Math.Clamp(data.m_AdjustedTarget, GetTemperatureMin(), GetTemperatureMax());
  1943. float delta;
  1944. //overheating
  1945. if (CanItemOverheat())
  1946. {
  1947. if (GetTemperature() > GetItemOverheatThreshold())
  1948. delta = data.m_AdjustedTarget - GetTemperature();
  1949. else
  1950. delta = data.m_AdjustedTarget - GetItemOverheatThreshold();
  1951. HandleItemOverheating(delta,data);
  1952. }
  1953. //freezing, can obstruct temperature change
  1954. if (CanFreeze())
  1955. {
  1956. if (!m_IsFrozen)
  1957. {
  1958. delta = target - GetTemperatureFreezeThreshold();
  1959. if (target < GetTemperatureFreezeThreshold())
  1960. {
  1961. //first crossing the threshold
  1962. if (m_VarTemperature >= GetTemperatureFreezeThreshold()) //going DOWN or STAYING AT THRESHOLD, FREEZING;
  1963. {
  1964. SetTemperatureDirect(GetTemperatureFreezeThreshold());
  1965. }
  1966. else //going UP, still FREEZING
  1967. {
  1968. SetTemperatureDirect(target);
  1969. }
  1970. HandleFreezingProgression(delta,data);
  1971. }
  1972. else
  1973. {
  1974. SetTemperatureDirect(target);
  1975. if (target > GetTemperatureFreezeThreshold())
  1976. HandleFreezingProgression(delta,data);
  1977. }
  1978. }
  1979. else
  1980. {
  1981. delta = target - GetTemperatureThawThreshold();
  1982. if (target > GetTemperatureThawThreshold())
  1983. {
  1984. //first crossing the threshold
  1985. if (m_VarTemperature <= GetTemperatureThawThreshold()) //going UP, THAWING
  1986. {
  1987. SetTemperatureDirect(GetTemperatureThawThreshold());
  1988. }
  1989. else //going DOWN, still THAWING
  1990. {
  1991. SetTemperatureDirect(target);
  1992. }
  1993. HandleFreezingProgression(delta,data);
  1994. }
  1995. else
  1996. {
  1997. SetTemperatureDirect(target);
  1998. if (target < GetTemperatureThawThreshold())
  1999. HandleFreezingProgression(delta,data);
  2000. }
  2001. }
  2002. }
  2003. else //!CanFreeze
  2004. {
  2005. SetTemperatureDirect(target);
  2006. }
  2007. }
  2008. //! refreshes access without setting temperature, keeps the source locked in
  2009. void RefreshTemperatureAccess(TemperatureData data)
  2010. {
  2011. if (!CanHaveTemperature())
  2012. {
  2013. Debug.Log("RefreshTemperatureAccess | entity " + this + " does not have temperature range defined!");
  2014. return;
  2015. }
  2016. m_TAC.TryAccessSource(data);
  2017. }
  2018. void InterpolateTempData(TemperatureDataInterpolated data)
  2019. {
  2020. if (data)
  2021. data.InterpolateTemperatureDelta(GetTemperature());
  2022. }
  2023. ////////////////////////////////////////////
  2024. //! presumably for debug purposes?
  2025. void SetTemperatureMax()
  2026. {
  2027. SetTemperatureDirect(GetTemperatureMax());
  2028. SetFrozen(GetTemperature() < GetTemperatureFreezeThreshold());
  2029. }
  2030. float GetTemperature()
  2031. {
  2032. return m_VarTemperature;
  2033. }
  2034. float GetTemperatureInit()
  2035. {
  2036. return m_VarTemperatureInit;
  2037. }
  2038. float GetTemperatureMin()
  2039. {
  2040. return m_VarTemperatureMin;
  2041. }
  2042. float GetTemperatureMax()
  2043. {
  2044. return m_VarTemperatureMax;
  2045. }
  2046. //! specifically for cooking system, to get heat source target temperatures
  2047. bool GetCookingTargetTemperature(out float temperature)
  2048. {
  2049. return false;
  2050. }
  2051. /**
  2052. \brief Returns temperature change speed multiplier for this item and all its children (multiplicative interaction)
  2053. \note Values > 1 accelerate, values in <0,1) interval decelerate. Values < 0 should not be used here, but I'm not your mom.
  2054. */
  2055. float GetHeatPermeabilityCoef()
  2056. {
  2057. return m_VarHeatPermeabilityCoef;
  2058. }
  2059. float GetTemperatureFreezeThreshold()
  2060. {
  2061. return m_VarTemperatureFreezeThreshold;
  2062. }
  2063. float GetTemperatureThawThreshold()
  2064. {
  2065. return m_VarTemperatureThawThreshold;
  2066. }
  2067. float GetTemperatureFreezeTime()
  2068. {
  2069. return m_VarTemperatureFreezeTime;
  2070. }
  2071. float GetTemperatureThawTime()
  2072. {
  2073. return m_VarTemperatureThawTime;
  2074. }
  2075. //! on server only
  2076. float GetFreezeThawProgress()
  2077. {
  2078. return m_FreezeThawProgress;
  2079. }
  2080. //! 0->1 when freezing, 1->0 when thawing
  2081. protected void SetFreezeThawProgress(float val)
  2082. {
  2083. m_FreezeThawProgress = val;
  2084. }
  2085. bool CanFreeze()
  2086. {
  2087. return CanHaveTemperature() && GetTemperatureFreezeThreshold() > GetTemperatureMin() && GetTemperatureThawThreshold() < GetTemperatureMax();
  2088. }
  2089. bool GetIsFrozen()
  2090. {
  2091. return m_IsFrozen;
  2092. }
  2093. void SetFrozen(bool frozen)
  2094. {
  2095. if (!CanFreeze() && frozen)
  2096. return;
  2097. bool previous = m_IsFrozen;
  2098. m_IsFrozen = frozen;
  2099. SetFreezeThawProgress(frozen);
  2100. if (previous != frozen)
  2101. {
  2102. SetSynchDirty();
  2103. OnFreezeStateChangeServer();
  2104. }
  2105. }
  2106. protected void HandleFreezingProgression(float deltaHeat, TemperatureData data)
  2107. {
  2108. float progressVal = m_FreezeThawProgress;
  2109. float progressDelta = 1;
  2110. if (deltaHeat > 0)
  2111. progressDelta = -1;
  2112. if (data.m_UpdateTimeInfo == -1)
  2113. progressDelta = (-deltaHeat / GameConstants.TEMPERATURE_RATE_AVERAGE_ABS) * GameConstants.TEMPERATURE_FREEZETHAW_LEGACY_COEF; //reverse-calculate the progress if actual time is not available
  2114. else
  2115. progressDelta *= data.m_UpdateTimeInfo;
  2116. if (progressDelta == 0)
  2117. return;
  2118. float changeTimeDefault;
  2119. float changeTimeMin;
  2120. float changeTime;
  2121. if (!m_IsFrozen)
  2122. {
  2123. changeTimeDefault = GetTemperatureFreezeTime();
  2124. changeTimeMin = GameConstants.TEMPERATURE_TIME_FREEZE_MIN;
  2125. }
  2126. else
  2127. {
  2128. changeTimeDefault = GetTemperatureThawTime();
  2129. changeTimeMin = GameConstants.TEMPERATURE_TIME_THAW_MIN;
  2130. }
  2131. float coef = data.m_UpdateTimeCoef;
  2132. if (deltaHeat < 0) //use cooling coef when freezing (mostly just to make sure)
  2133. coef = GameConstants.TEMP_COEF_COOLING_GLOBAL;
  2134. if (coef != 0)
  2135. changeTimeDefault *= 1/coef;
  2136. changeTime = Math.Lerp(Math.Max(changeTimeDefault,changeTimeMin),changeTimeMin,data.m_InterpolatedFraction);
  2137. progressVal = progressVal + progressDelta / changeTime;
  2138. float remnantTemp = 0;
  2139. if (!m_IsFrozen && progressVal >= 1)
  2140. {
  2141. SetFrozen(true);
  2142. if (progressVal > 1.0)
  2143. {
  2144. if (data.m_UpdateTimeInfo == -1)
  2145. remnantTemp = (progressVal - 1) * changeTime * GameConstants.TEMPERATURE_RATE_AVERAGE_ABS * -1;
  2146. else
  2147. remnantTemp = (((progressVal - 1) * changeTime) / progressDelta) * deltaHeat;
  2148. }
  2149. }
  2150. else if (m_IsFrozen && progressVal <= 0)
  2151. {
  2152. SetFrozen(false);
  2153. if (progressVal < 0.0)
  2154. {
  2155. if (data.m_UpdateTimeInfo == -1)
  2156. remnantTemp = -progressVal * changeTime * GameConstants.TEMPERATURE_RATE_AVERAGE_ABS;
  2157. else
  2158. remnantTemp = ((-progressVal * changeTime) / progressDelta) * deltaHeat;
  2159. }
  2160. }
  2161. else
  2162. {
  2163. SetFreezeThawProgress(Math.Clamp(progressVal,0,1));
  2164. }
  2165. if (remnantTemp >= GameConstants.TEMPERATURE_SENSITIVITY_THRESHOLD)//discards tiny values
  2166. SetTemperatureDirect(GetTemperature() + remnantTemp);
  2167. #ifdef DEVELOPER
  2168. if (progressVal > 0 && progressVal < 1)
  2169. {
  2170. m_LastFTChangeTime = changeTime;
  2171. if (!m_IsFrozen)
  2172. m_PresumedTimeRemaining = (1 - progressVal) * changeTime;
  2173. else
  2174. m_PresumedTimeRemaining = progressVal * changeTime;
  2175. }
  2176. #endif
  2177. }
  2178. void OnFreezeStateChangeClient();
  2179. void OnFreezeStateChangeServer();
  2180. //----------------------------------------------------------------
  2181. //! Overheat time CAN be 0, GameConstants.TEMPERATURE_TIME_OVERHEAT_MIN is ignored if so
  2182. bool CanItemOverheat()
  2183. {
  2184. return GetItemOverheatTime() >= 0;
  2185. }
  2186. //! if undefined, max temperature used as default
  2187. float GetItemOverheatThreshold()
  2188. {
  2189. return GetTemperatureMax();
  2190. }
  2191. //! any configured value >= 0 will simulate overheating
  2192. float GetItemOverheatTime()
  2193. {
  2194. return m_VarTemperatureOverheatTime;
  2195. }
  2196. bool IsItemOverheated()
  2197. {
  2198. return m_OverheatProgress >= 1;
  2199. }
  2200. float GetItemOverheatProgress()
  2201. {
  2202. return m_OverheatProgress;
  2203. }
  2204. void SetItemOverheatProgress(float val, float deltaTime = 0)
  2205. {
  2206. float previous = m_OverheatProgress;
  2207. m_OverheatProgress = Math.Clamp(val,0,1);
  2208. if (m_OverheatProgress >= 1)
  2209. {
  2210. if (previous < 1)
  2211. OnItemOverheatStart();
  2212. OnItemOverheat(deltaTime);
  2213. }
  2214. else if (previous >= 1)
  2215. {
  2216. OnItemOverheatEnd();
  2217. }
  2218. }
  2219. //! override to implement desired overheat behavior on entity
  2220. protected void OnItemOverheatStart();
  2221. protected void OnItemOverheat(float deltaTime); //! note, that the deltaTime could be reverse-calculated and not totally accurate
  2222. protected void OnItemOverheatEnd();
  2223. protected void HandleItemOverheating(float deltaHeat, TemperatureData data)
  2224. {
  2225. float deltaTime = 1;
  2226. float progressVal = m_OverheatProgress;
  2227. if (deltaHeat < 0)
  2228. deltaTime = -1;
  2229. if (data.m_UpdateTimeInfo == -1)
  2230. deltaTime = deltaHeat / GameConstants.TEMPERATURE_RATE_AVERAGE_ABS; //reverse-calculate the progress if actual time is not available
  2231. else
  2232. deltaTime *= data.m_UpdateTimeInfo;
  2233. if (GetItemOverheatTime() > 0)
  2234. {
  2235. float changeTime = Math.Lerp(Math.Max(GameConstants.TEMPERATURE_TIME_OVERHEAT_MIN,GetItemOverheatTime()),GameConstants.TEMPERATURE_TIME_OVERHEAT_MIN,Math.Clamp(data.m_InterpolatedFraction,0,1));
  2236. progressVal += deltaTime / changeTime;
  2237. }
  2238. else
  2239. {
  2240. if (deltaHeat < 0)
  2241. progressVal = 0;
  2242. else if (deltaHeat > 0)
  2243. progressVal = 1;
  2244. }
  2245. SetItemOverheatProgress(Math.Clamp(progressVal,0,1),deltaTime);
  2246. }
  2247. //----------------------------------------------------------------
  2248. void SetLiquidType(int value, bool allow_client = false);
  2249. int GetLiquidType()
  2250. {
  2251. return 0;
  2252. }
  2253. //----------------------------------------------------------------
  2254. void SetColor(int r, int g, int b, int a);
  2255. void GetColor(out int r,out int g,out int b,out int a)
  2256. {
  2257. r = -1;
  2258. g = -1;
  2259. b = -1;
  2260. a = -1;
  2261. }
  2262. //----------------------------------------------------------------
  2263. void SetStoreLoad(bool value);
  2264. bool IsStoreLoad()
  2265. {
  2266. return false;
  2267. }
  2268. void SetStoreLoadedQuantity(float value);
  2269. float GetStoreLoadedQuantity()
  2270. {
  2271. return 0.0;
  2272. }
  2273. //----------------------------------------------------------------
  2274. void SetCleanness(int value, bool allow_client = false);
  2275. int GetCleanness()
  2276. {
  2277. return 0;
  2278. }
  2279. //----------------------------------------------------------------
  2280. bool IsServerCheck(bool allow_client)
  2281. {
  2282. if (g_Game.IsServer())
  2283. return true;
  2284. if (allow_client)
  2285. return true;
  2286. if (GetGame().IsClient() && GetGame().IsMultiplayer())
  2287. {
  2288. Error("Attempting to change variable client side, variables are supposed to be changed on server only !!");
  2289. return false;
  2290. }
  2291. return true;
  2292. }
  2293. //----------------------------------------------------------------
  2294. HiddenSelectionsData GetHiddenSelectionsData()
  2295. {
  2296. return m_HiddenSelectionsData;
  2297. }
  2298. //! Returns index of the string found in cfg array 'hiddenSelections'. If it's not found then it returns -1.
  2299. int GetHiddenSelectionIndex( string selection )
  2300. {
  2301. if (m_HiddenSelectionsData)
  2302. return m_HiddenSelectionsData.GetHiddenSelectionIndex( selection );
  2303. return -1;
  2304. }
  2305. //! Returns the hiddenSelectionsTextures array from the object's config
  2306. override TStringArray GetHiddenSelections()
  2307. {
  2308. if (m_HiddenSelectionsData)
  2309. return m_HiddenSelectionsData.m_HiddenSelections;
  2310. else
  2311. return super.GetHiddenSelections();
  2312. }
  2313. //! Returns the hiddenSelectionsTextures array from the object's config
  2314. override TStringArray GetHiddenSelectionsTextures()
  2315. {
  2316. if (m_HiddenSelectionsData)
  2317. return m_HiddenSelectionsData.m_HiddenSelectionsTextures;
  2318. else
  2319. return super.GetHiddenSelectionsTextures();
  2320. }
  2321. //! Returns the hiddenSelectionsMaterials array from the object's config
  2322. override TStringArray GetHiddenSelectionsMaterials()
  2323. {
  2324. if (m_HiddenSelectionsData)
  2325. return m_HiddenSelectionsData.m_HiddenSelectionsMaterials;
  2326. else
  2327. return super.GetHiddenSelectionsMaterials();
  2328. }
  2329. /**
  2330. * @fn EntityPlaceOnSurfacePointWithRotation
  2331. * @brief applies correct rotation according to WRUtils::EntityPlacementRotation(type->GetRotationFlags())
  2332. *
  2333. * @param[out] trans \p the transform to apply the correct rotation on
  2334. * @param[in] pos \p position to check
  2335. * @param[in] dx \p up vector x to align to
  2336. * @param[in] dz \p up vector z to align to
  2337. * @param[in] fAngle \p angle to position
  2338. * @param[in] align \p align to surface
  2339. **/
  2340. proto native void PlaceOnSurfaceRotated(out vector trans[4], vector pos, float dx = 0, float dz = 0, float fAngle = 0, bool align = false);
  2341. /**
  2342. * @fn RegisterNetSyncVariableBool
  2343. * @brief registers bool variable synchronized over network
  2344. *
  2345. * @param[in] variableName \p which variable should be synchronized
  2346. **/
  2347. proto native void RegisterNetSyncVariableBool(string variableName);
  2348. /**
  2349. * @fn RegisterNetSyncVariableBoolSignal
  2350. * @brief when bool variable is true, it's sent to clients and become false again
  2351. *
  2352. * @param[in] variableName \p which variable should be synchronized
  2353. **/
  2354. proto native void RegisterNetSyncVariableBoolSignal(string variableName);
  2355. /**
  2356. * @fn RegisterNetSyncVariableInt
  2357. * @brief registers int variable synchronized over network
  2358. *
  2359. * @param[in] variableName \p which variable should be synchronized
  2360. * @param[in] minValue \p minimal value used for quantization (when minValue == maxValue, no quatization is done)
  2361. * @param[in] maxValue \p maximal value used for quantization (when minValue == maxValue, no quatization is done)
  2362. **/
  2363. proto native void RegisterNetSyncVariableInt(string variableName, int minValue = 0, int maxValue = 0);
  2364. /**
  2365. * @fn RegisterNetSyncVariableFloat
  2366. * @brief registers float variable synchronized over network
  2367. *
  2368. * @param[in] variableName \p which variable should be synchronized
  2369. * @param[in] minValue \p minimal value used for quantization (when minValue == maxValue, no quatization is done)
  2370. * @param[in] maxValue \p maximal value used for quantization (when minValue == maxValue, no quatization is done)
  2371. * @param[in] precision \p precision in number of digits after decimal point
  2372. **/
  2373. proto native void RegisterNetSyncVariableFloat(string variableName, float minValue = 0, float maxValue = 0, int precision = 1);
  2374. /**
  2375. * @fn RegisterNetSyncVariableObject
  2376. * @brief registers object variable synchronized over network, only synchronizes if network id is assigned. Doesn't handle object despawn on client
  2377. *
  2378. * @param[in] variableName \p which variable should be synchronized
  2379. **/
  2380. proto native void RegisterNetSyncVariableObject(string variableName);
  2381. proto native void UpdateNetSyncVariableInt(string variableName, float minValue = 0, float maxValue = 0);
  2382. proto native void UpdateNetSyncVariableFloat(string variableName, float minValue = 0, float maxValue = 0, int precision = 1);
  2383. proto native void SwitchLight(bool isOn);
  2384. //! Simple hidden selection state; 0 == hidden
  2385. proto native void SetSimpleHiddenSelectionState(int index, bool state);
  2386. proto native bool IsSimpleHiddenSelectionVisible(int index);
  2387. //! Change texture in hiddenSelections
  2388. proto native void SetObjectTexture(int index, string texture_name);
  2389. proto native owned string GetObjectTexture(int index);
  2390. //! Change material in hiddenSelections
  2391. proto native void SetObjectMaterial(int index, string mat_name);
  2392. proto native owned string GetObjectMaterial(int index);
  2393. proto native bool IsPilotLight();
  2394. proto native void SetPilotLight(bool isOn);
  2395. /**
  2396. \brief Engine calls this function to collect data from entity to store for persistence (on server side).
  2397. @code
  2398. void OnStoreSave(ParamsWriteContext ctx)
  2399. {
  2400. // dont forget to propagate this call trough class hierarchy!
  2401. super.OnStoreSave(ctx);
  2402. // write any data (using params) you want to store
  2403. int a = 5;
  2404. float b = 6.0;
  2405. ctx.Write(a);
  2406. ctx.Write(b);
  2407. }
  2408. @endcode
  2409. */
  2410. void OnStoreSave(ParamsWriteContext ctx)
  2411. {
  2412. // Saving of energy related states
  2413. if ( m_EM )
  2414. {
  2415. // Save energy amount
  2416. ctx.Write( m_EM.GetEnergy() );
  2417. // Save passive/active state
  2418. ctx.Write( m_EM.IsPassive() );
  2419. // Save ON/OFF state
  2420. ctx.Write( m_EM.IsSwitchedOn() );
  2421. // Save plugged/unplugged state
  2422. ctx.Write( m_EM.IsPlugged() );
  2423. // ENERGY SOURCE
  2424. // Save energy source IDs
  2425. EntityAI energy_source = m_EM.GetEnergySource();
  2426. int b1 = 0;
  2427. int b2 = 0;
  2428. int b3 = 0;
  2429. int b4 = 0;
  2430. if (energy_source)
  2431. {
  2432. energy_source.GetPersistentID(b1, b2, b3, b4);
  2433. }
  2434. ctx.Write( b1 ); // Save energy source block 1
  2435. ctx.Write( b2 ); // Save energy source block 2
  2436. ctx.Write( b3 ); // Save energy source block 3
  2437. ctx.Write( b4 ); // Save energy source block 4
  2438. }
  2439. // variable management system
  2440. SaveVariables(ctx);
  2441. }
  2442. /**
  2443. \brief Called when data is loaded from persistence (on server side).
  2444. @code
  2445. void OnStoreLoad(ParamsReadContext ctx, int version)
  2446. {
  2447. // dont forget to propagate this call trough class hierarchy!
  2448. if ( !super.OnStoreLoad(ctx, version) )
  2449. return false;
  2450. // read data loaded from game database (format and order of reading must be the same as writing!)
  2451. int a;
  2452. if ( !ctx.Read(a) )
  2453. return false;
  2454. float b;
  2455. if ( !ctx.Read(b) )
  2456. return false;
  2457. return true;
  2458. }
  2459. @endcode
  2460. */
  2461. bool OnStoreLoad (ParamsReadContext ctx, int version)
  2462. {
  2463. // Restoring of energy related states
  2464. if ( m_EM )
  2465. {
  2466. // Load energy amount
  2467. float f_energy = 0;
  2468. if ( !ctx.Read( f_energy ) )
  2469. f_energy = 0;
  2470. m_EM.SetEnergy(f_energy);
  2471. // Load passive/active state
  2472. bool b_is_passive = false;
  2473. if ( !ctx.Read( b_is_passive ) )
  2474. return false;
  2475. m_EM.SetPassiveState(b_is_passive);
  2476. // Load ON/OFF state
  2477. bool b_is_on = false;
  2478. if ( !ctx.Read( b_is_on ) )
  2479. {
  2480. m_EM.SwitchOn();
  2481. return false;
  2482. }
  2483. // Load plugged/unplugged state
  2484. bool b_is_plugged = false;
  2485. if ( !ctx.Read( b_is_plugged ) )
  2486. return false;
  2487. // ENERGY SOURCE
  2488. if ( version <= 103 )
  2489. {
  2490. // Load energy source ID low
  2491. int i_energy_source_ID_low = 0; // Even 0 can be valid ID!
  2492. if ( !ctx.Read( i_energy_source_ID_low ) )
  2493. return false;
  2494. // Load energy source ID high
  2495. int i_energy_source_ID_high = 0; // Even 0 can be valid ID!
  2496. if ( !ctx.Read( i_energy_source_ID_high ) )
  2497. return false;
  2498. }
  2499. else
  2500. {
  2501. int b1 = 0;
  2502. int b2 = 0;
  2503. int b3 = 0;
  2504. int b4 = 0;
  2505. if ( !ctx.Read(b1) ) return false;
  2506. if ( !ctx.Read(b2) ) return false;
  2507. if ( !ctx.Read(b3) ) return false;
  2508. if ( !ctx.Read(b4) ) return false;
  2509. if ( b_is_plugged )
  2510. {
  2511. // Because function GetEntityByPersitentID() cannot be called here, ID values must be stored and used later.
  2512. m_EM.StoreEnergySourceIDs( b1, b2, b3, b4 );
  2513. m_EM.RestorePlugState(true);
  2514. }
  2515. }
  2516. if (b_is_on)
  2517. {
  2518. m_EM.SwitchOn();
  2519. }
  2520. }
  2521. if (version >= 140)
  2522. {
  2523. // variable management system
  2524. if (!LoadVariables(ctx, version))
  2525. return false;
  2526. }
  2527. return true;
  2528. }
  2529. //! Sets object synchronization dirty flag, which signalize that object wants to be synchronized (take effect only in MP on server side)
  2530. proto native void SetSynchDirty();
  2531. /**
  2532. \brief Called on clients after receiving synchronization data from server.
  2533. */
  2534. void OnVariablesSynchronized()
  2535. {
  2536. if ( m_EM )
  2537. {
  2538. if ( GetGame().IsMultiplayer() )
  2539. {
  2540. bool is_on = m_EM.IsSwitchedOn();
  2541. if (is_on != m_EM.GetPreviousSwitchState())
  2542. {
  2543. if (is_on)
  2544. m_EM.SwitchOn();
  2545. else
  2546. m_EM.SwitchOff();
  2547. }
  2548. int id_low = m_EM.GetEnergySourceNetworkIDLow();
  2549. int id_High = m_EM.GetEnergySourceNetworkIDHigh();
  2550. EntityAI energy_source = EntityAI.Cast( GetGame().GetObjectByNetworkId(id_low, id_High) );
  2551. if (energy_source)
  2552. {
  2553. ComponentEnergyManager esem = energy_source.GetCompEM();
  2554. if ( !esem )
  2555. {
  2556. string object = energy_source.GetType();
  2557. Error("Synchronization error! Object " + object + " has no instance of the Energy Manager component!");
  2558. }
  2559. m_EM.PlugThisInto(energy_source);
  2560. }
  2561. else
  2562. {
  2563. m_EM.UnplugThis();
  2564. }
  2565. m_EM.DeviceUpdate();
  2566. m_EM.StartUpdates();
  2567. }
  2568. }
  2569. if (m_IsFrozen != m_IsFrozenLocal && !GetGame().IsDedicatedServer())
  2570. {
  2571. m_IsFrozenLocal = m_IsFrozen;
  2572. OnFreezeStateChangeClient();
  2573. }
  2574. }
  2575. //-----------------------------
  2576. // VARIABLE MANIPULATION SYSTEM
  2577. //-----------------------------
  2578. //!'true' if this variable has ever been changed from default
  2579. bool IsVariableSet(int variable)
  2580. {
  2581. return (variable & m_VariablesMask);
  2582. }
  2583. void SetVariableMask(int variable)
  2584. {
  2585. m_VariablesMask = variable | m_VariablesMask;
  2586. if (GetGame().IsServer())
  2587. {
  2588. SetSynchDirty();
  2589. }
  2590. }
  2591. //!Removes variable from variable mask, making it appear as though the variable has never been changed from default
  2592. void RemoveItemVariable(int variable)
  2593. {
  2594. m_VariablesMask = ~variable & m_VariablesMask;
  2595. }
  2596. void TransferVariablesFloat(array<float> float_vars)
  2597. {
  2598. DeSerializeNumericalVars(float_vars);
  2599. }
  2600. array<float> GetVariablesFloat()
  2601. {
  2602. CachedObjectsArrays.ARRAY_FLOAT.Clear();
  2603. SerializeNumericalVars(CachedObjectsArrays.ARRAY_FLOAT);
  2604. return CachedObjectsArrays.ARRAY_FLOAT;
  2605. }
  2606. void SaveVariables(ParamsWriteContext ctx)
  2607. {
  2608. //first set the flags
  2609. int varFlags = 0;
  2610. if (m_VariablesMask)
  2611. varFlags = ItemVariableFlags.FLOAT;
  2612. ctx.Write(varFlags);
  2613. //-------------------
  2614. //now serialize the variables
  2615. //floats
  2616. if (m_VariablesMask)
  2617. WriteVarsToCTX(ctx);
  2618. }
  2619. //----------------------------------------------------------------
  2620. bool LoadVariables(ParamsReadContext ctx, int version = -1)
  2621. {
  2622. int varFlags;
  2623. //read the flags
  2624. if (!ctx.Read(varFlags))
  2625. {
  2626. return false;
  2627. }
  2628. //--------------
  2629. if (varFlags & ItemVariableFlags.FLOAT)
  2630. {
  2631. if (!ReadVarsFromCTX(ctx, version))
  2632. return false;
  2633. }
  2634. return true;
  2635. }
  2636. //! Writes to storage CTX
  2637. void WriteVarsToCTX(ParamsWriteContext ctx)
  2638. {
  2639. ctx.Write(m_VariablesMask);
  2640. //--------------------------------------------
  2641. if (IsVariableSet(VARIABLE_TEMPERATURE))
  2642. {
  2643. ctx.Write(GetTemperature());
  2644. ctx.Write((int)GetIsFrozen());
  2645. }
  2646. }
  2647. //! Reads from storage CTX
  2648. bool ReadVarsFromCTX(ParamsReadContext ctx, int version = -1)//with ID optimization
  2649. {
  2650. if (version < 140)
  2651. return true;
  2652. int intValue;
  2653. float value;
  2654. if (!ctx.Read(intValue))
  2655. return false;
  2656. m_VariablesMask = intValue; //necessary for higher implement overrides. Hope it does not bork some init somewhere.
  2657. //--------------------------------------------
  2658. if (m_VariablesMask & VARIABLE_TEMPERATURE)
  2659. {
  2660. if (!ctx.Read(value))
  2661. return false;
  2662. SetTemperatureDirect(value);
  2663. if (!ctx.Read(intValue))
  2664. return false;
  2665. SetFrozen(intValue);
  2666. }
  2667. return true;
  2668. }
  2669. void SerializeNumericalVars(array<float> floats_out)
  2670. {
  2671. // the order of serialization must be the same as the order of de-serialization
  2672. floats_out.Insert(m_VariablesMask);
  2673. //--------------------------------------------
  2674. if (IsVariableSet(VARIABLE_TEMPERATURE))
  2675. {
  2676. floats_out.Insert(m_VarTemperature);
  2677. floats_out.Insert((float)GetIsFrozen());
  2678. }
  2679. }
  2680. void DeSerializeNumericalVars(array<float> floats)
  2681. {
  2682. // the order of serialization must be the same as the order of de-serialization
  2683. int index = 0;
  2684. int mask = Math.Round(floats.Get(index));
  2685. index++;
  2686. //--------------------------------------------
  2687. if (mask & VARIABLE_TEMPERATURE)
  2688. {
  2689. float temperature = floats.Get(index);
  2690. SetTemperatureDirect(temperature);
  2691. floats.RemoveOrdered(index);
  2692. bool frozen = Math.Round(floats.Get(index));
  2693. SetFrozen(frozen);
  2694. floats.RemoveOrdered(index);
  2695. }
  2696. }
  2697. //----------------------------------------------------------------
  2698. proto native void SetAITargetCallbacks(AbstractAITargetCallbacks callbacks);
  2699. override void EOnFrame(IEntity other, float timeSlice)
  2700. {
  2701. if ( m_ComponentsBank != NULL )
  2702. {
  2703. for ( int comp_key = 0; comp_key < COMP_TYPE_COUNT; ++comp_key )
  2704. {
  2705. if ( m_ComponentsBank.IsComponentAlreadyExist(comp_key) )
  2706. {
  2707. m_ComponentsBank.GetComponent(comp_key).Event_OnFrame(other, timeSlice);
  2708. }
  2709. }
  2710. }
  2711. }
  2712. string GetDebugText()
  2713. {
  2714. string text = string.Empty;
  2715. text += "Weight: " + GetWeightEx() + "\n";
  2716. text += "Disabled: " + GetIsSimulationDisabled() + "\n";
  2717. #ifdef SERVER
  2718. if (GetEconomyProfile())
  2719. text += "CE Lifetime default: " + (int)GetEconomyProfile().GetLifetime() + "\n";
  2720. text += "CE Lifetime remaining: " + (int)GetLifetime() + "\n";
  2721. #endif
  2722. ComponentEnergyManager compEM = GetCompEM();
  2723. if (compEM)
  2724. {
  2725. text += "Energy Source: " + Object.GetDebugName(compEM.GetEnergySource()) + "\n";
  2726. text += "Switched On: " + compEM.IsSwitchedOn() + "\n";
  2727. text += "Is Working: " + compEM.IsWorking() + "\n";
  2728. }
  2729. return text;
  2730. }
  2731. void GetDebugButtonNames(out string button1, out string button2, out string button3, out string button4){}//DEPRICATED, USE GetDebugActions / OnAction
  2732. void OnDebugButtonPressClient(int button_index){}//DEPRICATED, USE GetDebugActions / OnAction
  2733. void OnDebugButtonPressServer(int button_index){}//DEPRICATED, USE GetDebugActions / OnAction
  2734. Shape DebugBBoxDraw()
  2735. {
  2736. return GetComponent(COMP_TYPE_ETITY_DEBUG).DebugBBoxDraw();
  2737. }
  2738. void DebugBBoxSetColor(int color)
  2739. {
  2740. GetComponent(COMP_TYPE_ETITY_DEBUG).DebugBBoxSetColor(color);
  2741. }
  2742. void DebugBBoxDelete()
  2743. {
  2744. GetComponent(COMP_TYPE_ETITY_DEBUG).DebugBBoxDelete();
  2745. }
  2746. Shape DebugDirectionDraw(float distance = 1)
  2747. {
  2748. return GetComponent(COMP_TYPE_ETITY_DEBUG).DebugDirectionDraw(distance);
  2749. }
  2750. void DebugDirectionSetColor(int color)
  2751. {
  2752. GetComponent(COMP_TYPE_ETITY_DEBUG).DebugDirectionSetColor(color);
  2753. }
  2754. void DebugDirectionDelete()
  2755. {
  2756. GetComponent(COMP_TYPE_ETITY_DEBUG).DebugDirectionDelete();
  2757. }
  2758. //! Hides selection of the given name. Must be configed in config.cpp and models.cfg
  2759. void HideSelection( string selection_name )
  2760. {
  2761. if ( !ToDelete() )
  2762. {
  2763. SetAnimationPhase ( selection_name, 1 ); // 1 = hide, 0 = unhide!
  2764. }
  2765. }
  2766. //! Shows selection of the given name. Must be configed in config.hpp and models.cfg
  2767. void ShowSelection( string selection_name )
  2768. {
  2769. if ( !ToDelete() )
  2770. {
  2771. SetAnimationPhase ( selection_name, 0 ); // 1 = hide, 0 = unhide!
  2772. }
  2773. }
  2774. //! Returns blocks of bits of persistence id of this entity.
  2775. //! This id stays the same even after server restart.
  2776. proto void GetPersistentID( out int b1, out int b2, out int b3, out int b4 );
  2777. //! Set (override) remaining economy lifetime (seconds)
  2778. proto native void SetLifetime( float fLifeTime );
  2779. //! Get remaining economy lifetime (seconds)
  2780. proto native float GetLifetime();
  2781. //! Reset economy lifetime to default (seconds)
  2782. proto native void IncreaseLifetime();
  2783. //! Set (override) max economy lifetime per entity instance (seconds)
  2784. proto native void SetLifetimeMax( float fLifeTime );
  2785. //! Get max economy lifetime per instance - default is from DB (seconds)
  2786. proto native float GetLifetimeMax();
  2787. //! Reset economy lifetime to default across entity hierarchy all the way to the topmost entity
  2788. void IncreaseLifetimeUp()
  2789. {
  2790. IncreaseLifetime();
  2791. if (GetHierarchyParent())
  2792. GetHierarchyParent().IncreaseLifetimeUp();
  2793. }
  2794. // BODY STAGING
  2795. //! Use this to access Body Staging component on dead character. Returns NULL if the given object lacks such component.
  2796. ComponentBodyStaging GetCompBS()
  2797. {
  2798. if ( HasComponent(COMP_TYPE_BODY_STAGING) )
  2799. return ComponentBodyStaging.Cast( GetComponent(COMP_TYPE_BODY_STAGING) );
  2800. return NULL;
  2801. }
  2802. ///@{ energy manager
  2803. //! ENERGY MANAGER:Documentation: Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
  2804. //! Use this to access Energy Manager component on your device. Returns NULL if the given object lacks such component.
  2805. ComponentEnergyManager GetCompEM()
  2806. {
  2807. if (m_EM)
  2808. return m_EM;
  2809. if ( HasComponent(COMP_TYPE_ENERGY_MANAGER) )
  2810. return ComponentEnergyManager.Cast( GetComponent(COMP_TYPE_ENERGY_MANAGER) );
  2811. return NULL;
  2812. }
  2813. //! If this item has class EnergyManager in its config then it returns true. Otherwise returns false.
  2814. bool HasEnergyManager()
  2815. {
  2816. return HasComponent(COMP_TYPE_ENERGY_MANAGER);
  2817. }
  2818. // ------ Public Events for Energy manager component. Overwrite these and put your own functionality into them. ------
  2819. //! Energy manager event: Called only once when this device starts doing its work
  2820. void OnWorkStart() {}
  2821. //! Energy manager event: Called every device update if its supposed to do some work. The update can be every second or at random, depending on its manipulation.
  2822. void OnWork( float consumed_energy ) {}
  2823. //! Energy manager event: Called when the device stops working (was switched OFF or ran out of energy)
  2824. void OnWorkStop() {}
  2825. //! Energy manager event: Called when the device is switched on
  2826. void OnSwitchOn() {}
  2827. //! Energy manager event: Called when the device is switched OFF
  2828. void OnSwitchOff() {}
  2829. //! Energy manager event: Called when this device is plugged into some energy source
  2830. void OnIsPlugged(EntityAI source_device) {}
  2831. //! Energy manager event: Called when this device is UNPLUGGED from the energy source
  2832. void OnIsUnplugged( EntityAI last_energy_source ) {}
  2833. //! Energy manager event: When something is plugged into this device
  2834. void OnOwnSocketTaken( EntityAI device ) {}
  2835. //! Energy manager event: When something is UNPLUGGED from this device
  2836. void OnOwnSocketReleased( EntityAI device ) {}
  2837. //! Energy manager event: Object's initialization. Energy Manager is fully initialized by this point.
  2838. void OnInitEnergy() {}
  2839. //! Energy manager event: Called when energy was consumed on this device. ALWAYS CALL super.OnEnergyConsumed() !!!
  2840. void OnEnergyConsumed() {}
  2841. //! Energy manager event: Called when energy was added on this device. ALWAYS CALL super.OnEnergyAdded() !!!
  2842. void OnEnergyAdded() {}
  2843. ///@} energy manager
  2844. override void OnRPC(PlayerIdentity sender, int rpc_type, ParamsReadContext ctx)
  2845. {
  2846. super.OnRPC(sender, rpc_type, ctx);
  2847. if ( GetGame().IsClient() )
  2848. {
  2849. switch (rpc_type)
  2850. {
  2851. // BODY STAGING - server => client synchronization of skinned state.
  2852. case ERPCs.RPC_BS_SKINNED_STATE:
  2853. {
  2854. Param1<bool> p_skinned_state= new Param1<bool>(false);
  2855. if (ctx.Read(p_skinned_state))
  2856. {
  2857. float state = p_skinned_state.param1;
  2858. if (state && GetCompBS())
  2859. GetCompBS().SetAsSkinnedClient();
  2860. }
  2861. break;
  2862. }
  2863. case ERPCs.RPC_EXPLODE_EVENT:
  2864. {
  2865. OnExplodeClient();
  2866. break;
  2867. }
  2868. }
  2869. }
  2870. }
  2871. #ifdef DIAG_DEVELOPER
  2872. void FixEntity()
  2873. {
  2874. if (!(GetGame().IsServer()))
  2875. return;
  2876. SetFullHealth();
  2877. if (GetInventory())
  2878. {
  2879. int i = 0;
  2880. int AttachmentsCount = GetInventory().AttachmentCount();
  2881. if (AttachmentsCount > 0)
  2882. {
  2883. for (i = 0; i < AttachmentsCount; i++)
  2884. {
  2885. GetInventory().GetAttachmentFromIndex(i).FixEntity();
  2886. }
  2887. }
  2888. CargoBase cargo = GetInventory().GetCargo();
  2889. if (cargo)
  2890. {
  2891. int cargoCount = cargo.GetItemCount();
  2892. for (i = 0; i < cargoCount; i++)
  2893. {
  2894. cargo.GetItem(i).FixEntity();
  2895. }
  2896. }
  2897. }
  2898. }
  2899. #endif
  2900. float GetWetWeightModifier()
  2901. {
  2902. return CfgGameplayHandler.GetWetnessWeightModifiers()[GetWetLevel()];
  2903. }
  2904. float GetConfigWeightModified()
  2905. {
  2906. return m_ConfigWeight * GetWetWeightModifier();
  2907. }
  2908. #ifdef DEVELOPER
  2909. string GetConfigWeightModifiedDebugText()
  2910. {
  2911. if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
  2912. {
  2913. return "(" + m_ConfigWeight + "(config weight) * " + GetWetWeightModifier() + "(Wetness Modifier))";
  2914. }
  2915. return string.Empty;
  2916. }
  2917. #endif
  2918. //Obsolete, use GetWeightEx()
  2919. int GetWeight()
  2920. {
  2921. return GetWeightEx();
  2922. }
  2923. void ClearWeightDirty()
  2924. {
  2925. //Print("ent:" + this + " - ClearWeightDirty");
  2926. m_WeightDirty = 0;
  2927. }
  2928. void SetWeightDirty()
  2929. {
  2930. #ifdef DEVELOPER
  2931. if (WeightDebug.m_VerbosityFlags & WeightDebugType.SET_DIRTY_FLAG)
  2932. {
  2933. Print("---------------------------------------");
  2934. Print("ent:" + this + " - SetWeightDirty");
  2935. if (WeightDebug.m_VerbosityFlags & WeightDebugType.DUMP_STACK)
  2936. {
  2937. DumpStack();
  2938. }
  2939. Print("---------------------------------------");
  2940. }
  2941. #endif
  2942. m_WeightDirty = 1;
  2943. if (GetHierarchyParent())
  2944. {
  2945. GetHierarchyParent().SetWeightDirty();
  2946. }
  2947. }
  2948. // returns weight of all cargo and attachments
  2949. float GetInventoryAndCargoWeight(bool forceRecalc = false)
  2950. {
  2951. float totalWeight;
  2952. if (GetInventory())
  2953. {
  2954. int i = 0;
  2955. int AttachmentsCount = GetInventory().AttachmentCount();
  2956. if (AttachmentsCount > 0)
  2957. {
  2958. for (i = 0; i < AttachmentsCount; i++)
  2959. {
  2960. totalWeight += GetInventory().GetAttachmentFromIndex(i).GetWeightEx(forceRecalc);
  2961. }
  2962. }
  2963. CargoBase cargo = GetInventory().GetCargo();
  2964. if (cargo)
  2965. {
  2966. int cargoCount = cargo.GetItemCount();
  2967. for (i = 0; i < cargoCount; i++)
  2968. {
  2969. totalWeight += cargo.GetItem(i).GetWeightEx(forceRecalc);
  2970. }
  2971. }
  2972. }
  2973. return totalWeight;
  2974. }
  2975. //! returns weight of the entity in a way that's specific to the entity type and is internal to the weight system calculation, to obtain entity's weight, use the 'GetWeightEx' method instead
  2976. protected float GetWeightSpecialized(bool forceRecalc = false)
  2977. {
  2978. return GetInventoryAndCargoWeight(forceRecalc);
  2979. }
  2980. //! returns overall weight of the entity, 'forceRecalc = true' is meant to be used only when debugging, using it in gameplay code is higly inadvisable as it bypasses the weight caching and has adverse effect on performance
  2981. //this method is not meant to be overriden, to adjust weight calculation for specific item type, override 'GetWeightSpecialized(bool forceRecalc = false)' instead
  2982. float GetWeightEx(bool forceRecalc = false)
  2983. {
  2984. if (m_WeightDirty || forceRecalc)//recalculate
  2985. {
  2986. m_WeightEx = GetWeightSpecialized(forceRecalc);
  2987. ClearWeightDirty();
  2988. #ifdef DEVELOPER
  2989. if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
  2990. {
  2991. WeightDebug.GetWeightDebug(this).SetWeight(m_WeightEx);
  2992. }
  2993. if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_DIRTY)
  2994. {
  2995. Print("ent:" + this + " - Dirty Recalc");
  2996. if (WeightDebug.m_VerbosityFlags & WeightDebugType.DUMP_STACK)
  2997. {
  2998. DumpStack();
  2999. }
  3000. }
  3001. #endif
  3002. }
  3003. return m_WeightEx;
  3004. }
  3005. void UpdateWeight(WeightUpdateType updateType = WeightUpdateType.FULL, float weightAdjustment = 0);
  3006. float GetSingleInventoryItemWeightEx(){}
  3007. void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
  3008. {
  3009. //fix entity
  3010. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.FIX_ENTITY, "Fix Entity", FadeColors.LIGHT_GREY));
  3011. //weight
  3012. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GET_TOTAL_WEIGHT, "Print Weight", FadeColors.LIGHT_GREY));
  3013. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GET_TOTAL_WEIGHT_RECALC, "Print Weight Verbose", FadeColors.LIGHT_GREY));
  3014. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GET_PLAYER_WEIGHT, "Print Player Weight", FadeColors.LIGHT_GREY));
  3015. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GET_PLAYER_WEIGHT_RECALC, "Print Player Weight Verbose", FadeColors.LIGHT_GREY));
  3016. }
  3017. bool OnAction(int action_id, Man player, ParamsReadContext ctx)
  3018. {
  3019. if (action_id == EActions.FIX_ENTITY)
  3020. {
  3021. #ifdef DIAG_DEVELOPER
  3022. FixEntity();
  3023. #endif
  3024. }
  3025. else if (action_id == EActions.GET_TOTAL_WEIGHT) //Prints total weight of item + its contents
  3026. {
  3027. WeightDebug.ClearWeightDebug();
  3028. #ifndef SERVER
  3029. Debug.Log("======================== "+ GetType() +" =================================");
  3030. #endif
  3031. Debug.Log("Weight:" + GetWeightEx().ToString());
  3032. Debug.Log("Weight excluding cargo and attachments:" + GetSingleInventoryItemWeightEx());
  3033. Debug.Log("----------------------------------------------------------------------------------------------");
  3034. }
  3035. else if (action_id == EActions.GET_TOTAL_WEIGHT_RECALC) //Prints total weight of item + its contents
  3036. {
  3037. WeightDebug.ClearWeightDebug();
  3038. WeightDebug.SetVerbosityFlags(WeightDebugType.RECALC_FORCED);
  3039. #ifndef SERVER
  3040. Debug.Log("======================== "+ GetType() +" RECALC ===========================");
  3041. #endif
  3042. Debug.Log("Weight:" + GetWeightEx(true).ToString());
  3043. Debug.Log("Weight excluding cargo and attachments:" + GetSingleInventoryItemWeightEx());
  3044. WeightDebug.PrintAll(this);
  3045. Debug.Log("----------------------------------------------------------------------------------------------");
  3046. WeightDebug.SetVerbosityFlags(0);
  3047. }
  3048. else if (action_id == EActions.GET_PLAYER_WEIGHT) //Prints total weight of item + its contents
  3049. {
  3050. WeightDebug.ClearWeightDebug();
  3051. #ifndef SERVER
  3052. Debug.Log("======================== PLAYER: "+player+" ===========================");
  3053. #endif
  3054. Debug.Log("New overall weight Player:"+player.GetWeightEx().ToString());
  3055. Debug.Log("----------------------------------------------------------------------------------------------");
  3056. }
  3057. else if (action_id == EActions.GET_PLAYER_WEIGHT_RECALC) //Prints total weight of item + its contents
  3058. {
  3059. WeightDebug.ClearWeightDebug();
  3060. WeightDebug.SetVerbosityFlags(WeightDebugType.RECALC_FORCED);
  3061. #ifndef SERVER
  3062. Debug.Log("======================== PLAYER RECALC: "+player+" ===========================");
  3063. #endif
  3064. Debug.Log("New overall weight Player:"+player.GetWeightEx(true).ToString());
  3065. WeightDebug.PrintAll(player);
  3066. Debug.Log("----------------------------------------------------------------------------------------------");
  3067. WeightDebug.SetVerbosityFlags(0);
  3068. }
  3069. return false;
  3070. }
  3071. ///@{ view index
  3072. //! Item view index is used to setup which camera will be used in item view widget in inventory.
  3073. //! With this index you can setup various camera angles for different item states (e.g. fireplace, weapons).
  3074. int m_ViewIndex = 0;
  3075. //! Sets item preview index
  3076. void SetViewIndex( int index )
  3077. {
  3078. m_ViewIndex = index;
  3079. if( GetGame().IsServer() )
  3080. {
  3081. SetSynchDirty();
  3082. }
  3083. }
  3084. //! Returns item preview index !!!! IF OVERRIDING with more dynamic events call GetOnViewIndexChanged() in constructor on client !!!!
  3085. int GetViewIndex()
  3086. {
  3087. if ( MemoryPointExists( "invView2" ) )
  3088. {
  3089. #ifdef PLATFORM_WINDOWS
  3090. InventoryLocation il = new InventoryLocation();
  3091. GetInventory().GetCurrentInventoryLocation( il );
  3092. InventoryLocationType type = il.GetType();
  3093. switch ( type )
  3094. {
  3095. case InventoryLocationType.CARGO:
  3096. {
  3097. return 0;
  3098. }
  3099. case InventoryLocationType.ATTACHMENT:
  3100. {
  3101. return 1;
  3102. }
  3103. case InventoryLocationType.HANDS:
  3104. {
  3105. return 0;
  3106. }
  3107. case InventoryLocationType.GROUND:
  3108. {
  3109. return 1;
  3110. }
  3111. case InventoryLocationType.PROXYCARGO:
  3112. {
  3113. return 0;
  3114. }
  3115. default:
  3116. {
  3117. return 0;
  3118. }
  3119. }
  3120. #endif
  3121. #ifdef PLATFORM_CONSOLE
  3122. return 1;
  3123. #endif
  3124. }
  3125. return 0;
  3126. }
  3127. ///@} view index
  3128. //! Returns hit component for the Entity (overriden for each Type - PlayerBase, DayZInfected, DayZAnimal, etc.)
  3129. string GetHitComponentForAI()
  3130. {
  3131. Debug.LogError("EntityAI: HitComponentForAI not set properly for that entity (" + GetType() + ")");
  3132. //! returns Global so it is obvious you need to configure that properly on entity
  3133. return "";
  3134. }
  3135. //! returns default hit component for the Entity (overriden for each Type - PlayerBase, DayZInfected, DayZAnimal, etc.)
  3136. string GetDefaultHitComponent()
  3137. {
  3138. Debug.LogError("EntityAI: DefaultHitComponent not set properly for that entity (" + GetType() + ")");
  3139. //! returns Global so it is obvious you need to configure that properly on entity
  3140. return "";
  3141. }
  3142. //! returns default hit position component name for the Entity (overriden by type if needed - used mainly as support for impact particles)
  3143. string GetDefaultHitPositionComponent()
  3144. {
  3145. Debug.LogError("EntityAI: DefaultHitPositionComponent not set for that entity (" + GetType() + ")");
  3146. return "";
  3147. }
  3148. array<string> GetSuitableFinisherHitComponents()
  3149. {
  3150. Debug.LogError("EntityAI: SuitableFinisherHitComponents not set for that entity (" + GetType() + ")");
  3151. return null;
  3152. }
  3153. vector GetDefaultHitPosition()
  3154. {
  3155. Debug.LogError("EntityAI: DefaultHitPosition not set for that entity (" + GetType() + ")");
  3156. return vector.Zero;
  3157. }
  3158. //! value is related to EMeleeTargetType
  3159. int GetMeleeTargetType()
  3160. {
  3161. return EMeleeTargetType.ALIGNABLE;
  3162. }
  3163. //! returns sound type of attachment (used for clothing and weapons on DayZPlayerImplement, paired with Anim*Type enum from DayZAnimEvents)
  3164. string GetAttachmentSoundType()
  3165. {
  3166. return "None";
  3167. }
  3168. //! returns item behaviour of item (more in ItemBase)
  3169. bool IsHeavyBehaviour()
  3170. {
  3171. return false;
  3172. }
  3173. //! returns item behaviour of item (more in ItemBase)
  3174. bool IsOneHandedBehaviour()
  3175. {
  3176. return false;
  3177. }
  3178. //! returns item behaviour of item (more in ItemBase)
  3179. bool IsTwoHandedBehaviour()
  3180. {
  3181. return false;
  3182. }
  3183. string ChangeIntoOnAttach(string slot) {}
  3184. string ChangeIntoOnDetach() {}
  3185. //! returns true used on selected items that have a temperature effect and can processes temperature changes
  3186. bool CanHaveTemperature()
  3187. {
  3188. return GetTemperatureMin() < GetTemperatureMax();
  3189. }
  3190. bool IsSelfAdjustingTemperature()
  3191. {
  3192. return false;
  3193. }
  3194. /**
  3195. \brief Central economy calls this function whenever going over all the entities
  3196. @code
  3197. void OnCEUpdate()
  3198. {
  3199. // dont forget to propagate this call trough class hierarchy! - always at the start of the function
  3200. super.OnCEUpdate();
  3201. // use m_ElapsedSinceLastUpdate for time-related purposes
  3202. }
  3203. @endcode
  3204. */
  3205. void OnCEUpdate()
  3206. {
  3207. float currentTime = GetGame().GetTickTime();
  3208. if (m_LastUpdatedTime == 0)
  3209. m_LastUpdatedTime = currentTime;
  3210. m_ElapsedSinceLastUpdate = currentTime - m_LastUpdatedTime;
  3211. m_LastUpdatedTime = currentTime;
  3212. ProcessVariables();
  3213. }
  3214. void ProcessVariables()
  3215. {
  3216. //currently only temperature on EntityAI
  3217. if (g_Game.IsWorldWetTempUpdateEnabled())
  3218. {
  3219. if (CanHaveTemperature() && !IsSelfAdjustingTemperature() && !GetHierarchyRoot().IsSelfAdjustingTemperature())
  3220. {
  3221. float target = g_Game.GetMission().GetWorldData().GetBaseEnvTemperatureAtObject(this);
  3222. if (GetTemperature() != target)
  3223. {
  3224. float heatPermCoef = 1.0;
  3225. EntityAI ent = this;
  3226. while (ent)
  3227. {
  3228. heatPermCoef *= ent.GetHeatPermeabilityCoef();
  3229. ent = ent.GetHierarchyParent();
  3230. }
  3231. SetTemperatureEx(new TemperatureDataInterpolated(target,ETemperatureAccessTypes.ACCESS_WORLD,m_ElapsedSinceLastUpdate,GameConstants.TEMP_COEF_WORLD,heatPermCoef));
  3232. }
  3233. }
  3234. }
  3235. }
  3236. void OnDebugSpawnEx(DebugSpawnParams params)
  3237. {
  3238. OnDebugSpawn();
  3239. }
  3240. void OnDebugSpawn()
  3241. {
  3242. array<string> slots = new array<string>;
  3243. ConfigGetTextArray("Attachments", slots);
  3244. array<string> mags = new array<string>;
  3245. ConfigGetTextArray("magazines", mags);
  3246. //-------
  3247. TStringArray all_paths = new TStringArray;
  3248. all_paths.Insert(CFG_VEHICLESPATH);
  3249. all_paths.Insert(CFG_MAGAZINESPATH);
  3250. all_paths.Insert(CFG_WEAPONSPATH);
  3251. string config_path;
  3252. string child_name;
  3253. int scope;
  3254. string path;
  3255. int consumable_count;
  3256. for (int i = 0; i < all_paths.Count(); i++)
  3257. {
  3258. config_path = all_paths.Get(i);
  3259. int children_count = GetGame().ConfigGetChildrenCount(config_path);
  3260. for (int x = 0; x < children_count; x++)
  3261. {
  3262. GetGame().ConfigGetChildName(config_path, x, child_name);
  3263. path = config_path + " " + child_name;
  3264. scope = GetGame().ConfigGetInt( config_path + " " + child_name + " scope" );
  3265. bool should_check = 1;
  3266. if ( config_path == "CfgVehicles" && scope == 0)
  3267. {
  3268. should_check = 0;
  3269. }
  3270. if ( should_check )
  3271. {
  3272. string inv_slot;
  3273. GetGame().ConfigGetText( config_path + " " + child_name + " inventorySlot",inv_slot );
  3274. for (int z = 0; z < slots.Count(); z++)
  3275. {
  3276. if (slots.Get(z) == inv_slot)
  3277. {
  3278. this.GetInventory().CreateInInventory( child_name );
  3279. continue;
  3280. //Print("matching attachment: " + child_name + " for inv. slot name:" +inv_slot);
  3281. }
  3282. }
  3283. }
  3284. }
  3285. }
  3286. };
  3287. override EntityAI ProcessMeleeItemDamage(int mode = 0)
  3288. {
  3289. if (GetGame().IsServer())
  3290. AddHealth("","Health",-MELEE_ITEM_DAMAGE);
  3291. return this;
  3292. }
  3293. //! Returns liquid throughput coeficient
  3294. float GetLiquidThroughputCoef()
  3295. {
  3296. return LIQUID_THROUGHPUT_DEFAULT;
  3297. }
  3298. string GetInvulnerabilityTypeString()
  3299. {
  3300. return "";
  3301. }
  3302. void ProcessInvulnerabilityCheck(string servercfg_param)
  3303. {
  3304. if ( GetGame() && GetGame().IsMultiplayer() && GetGame().IsServer() )
  3305. {
  3306. int invulnerability;
  3307. switch (servercfg_param)
  3308. {
  3309. case "disableContainerDamage":
  3310. invulnerability = CfgGameplayHandler.GetDisableContainerDamage();
  3311. break;
  3312. case "disableBaseDamage":
  3313. invulnerability = CfgGameplayHandler.GetDisableBaseDamage();
  3314. break;
  3315. }
  3316. if (invulnerability > 0)
  3317. {
  3318. SetAllowDamage(false);
  3319. }
  3320. }
  3321. }
  3322. void SetBayonetAttached(bool pState, int slot_idx = -1) {};
  3323. bool HasBayonetAttached() {};
  3324. int GetBayonetAttachmentIdx() {};
  3325. void SetButtstockAttached(bool pState, int slot_idx = -1) {};
  3326. bool HasButtstockAttached() {};
  3327. int GetButtstockAttachmentIdx() {};
  3328. void SetInvisibleRecursive(bool invisible, EntityAI parent = null, array<int> attachments = null)
  3329. {
  3330. array<int> childrenAtt = new array<int>;
  3331. array<int> attachmentsArray = new array<int>;
  3332. if (attachments)
  3333. attachmentsArray.Copy(attachments);
  3334. else
  3335. {
  3336. for (int i = 0; i < GetInventory().GetAttachmentSlotsCount(); i++)
  3337. {
  3338. attachmentsArray.Insert(GetInventory().GetAttachmentSlotId(i));
  3339. }
  3340. }
  3341. EntityAI item;
  3342. foreach( int slot : attachmentsArray )
  3343. {
  3344. if( parent )
  3345. item = parent.GetInventory().FindAttachment(slot);
  3346. else
  3347. item = this;//GetInventory().FindAttachment(slot);
  3348. if( item )
  3349. {
  3350. if( item.GetInventory().AttachmentCount() > 0 )
  3351. {
  3352. for(i = 0; i < item.GetInventory().GetAttachmentSlotsCount(); i++)
  3353. {
  3354. childrenAtt.Insert(item.GetInventory().GetAttachmentSlotId(i));
  3355. }
  3356. SetInvisibleRecursive(invisible,item,childrenAtt);
  3357. }
  3358. item.SetInvisible(invisible);
  3359. item.OnInvisibleSet(invisible);
  3360. }
  3361. }
  3362. }
  3363. void SoundHardTreeFallingPlay()
  3364. {
  3365. EffectSound sound = SEffectManager.PlaySound( "hardTreeFall_SoundSet", GetPosition() );
  3366. sound.SetAutodestroy( true );
  3367. }
  3368. void SoundSoftTreeFallingPlay()
  3369. {
  3370. EffectSound sound = SEffectManager.PlaySound( "softTreeFall_SoundSet", GetPosition() );
  3371. sound.SetAutodestroy( true );
  3372. }
  3373. void SoundHardBushFallingPlay()
  3374. {
  3375. EffectSound sound = SEffectManager.PlaySound( "hardBushFall_SoundSet", GetPosition() );
  3376. sound.SetAutodestroy( true );
  3377. }
  3378. void SoundSoftBushFallingPlay()
  3379. {
  3380. EffectSound sound = SEffectManager.PlaySound( "softBushFall_SoundSet", GetPosition() );
  3381. sound.SetAutodestroy( true );
  3382. }
  3383. void RegisterTransportHit(Transport transport)
  3384. {
  3385. if (!m_TransportHitRegistered)
  3386. {
  3387. m_TransportHitRegistered = true;
  3388. m_TransportHitVelocity = GetVelocity(transport);
  3389. Car car;
  3390. Boat boat;
  3391. float damage;
  3392. vector impulse;
  3393. // a different attempt to solve hits from "standing" car to the players
  3394. if (Car.CastTo(car, transport))
  3395. {
  3396. if (car.GetSpeedometerAbsolute() > 2 )
  3397. {
  3398. damage = m_TransportHitVelocity.Length();
  3399. ProcessDirectDamage(DT_CUSTOM, transport, "", "TransportHit", "0 0 0", damage);
  3400. }
  3401. else
  3402. {
  3403. m_TransportHitRegistered = false;
  3404. }
  3405. // compute impulse and apply only if the body dies
  3406. if (IsDamageDestroyed() && car.GetSpeedometerAbsolute() > 3)
  3407. {
  3408. impulse = 40 * m_TransportHitVelocity;
  3409. impulse[1] = 40 * 1.5;
  3410. dBodyApplyImpulse(this, impulse);
  3411. }
  3412. }
  3413. else if (Boat.CastTo(boat, transport))
  3414. {
  3415. Human player = Human.Cast(this);
  3416. if (player && player.PhysicsGetLinkedEntity() == boat) // standing on boat
  3417. {
  3418. m_TransportHitRegistered = false;
  3419. return;
  3420. }
  3421. if (m_TransportHitVelocity.Normalize() > 5) // 5 m/s
  3422. {
  3423. damage = m_TransportHitVelocity.Length() * 0.5;
  3424. ProcessDirectDamage(DT_CUSTOM, transport, "", "TransportHit", "0 0 0", damage);
  3425. }
  3426. else
  3427. m_TransportHitRegistered = false;
  3428. }
  3429. else //old solution just in case if somebody use it
  3430. {
  3431. // avoid damage because of small movements
  3432. if (m_TransportHitVelocity.Length() > 0.1)
  3433. {
  3434. damage = m_TransportHitVelocity.Length();
  3435. ProcessDirectDamage(DT_CUSTOM, transport, "", "TransportHit", "0 0 0", damage);
  3436. }
  3437. else
  3438. {
  3439. m_TransportHitRegistered = false;
  3440. }
  3441. // compute impulse and apply only if the body dies
  3442. if (IsDamageDestroyed() && m_TransportHitVelocity.Length() > 0.3)
  3443. {
  3444. impulse = 40 * m_TransportHitVelocity;
  3445. impulse[1] = 40 * 1.5;
  3446. dBodyApplyImpulse(this, impulse);
  3447. }
  3448. }
  3449. }
  3450. }
  3451. bool GetInventoryHandAnimation(notnull InventoryLocation loc, out int value)
  3452. {
  3453. value = -1;
  3454. return false;
  3455. }
  3456. bool TranslateSlotFromSelection(string selection_name, out int slot_id)
  3457. {
  3458. return false;
  3459. }
  3460. //! Universal Temperature Sources Helpers
  3461. bool IsUniversalTemperatureSource()
  3462. {
  3463. return GetUniversalTemperatureSource() != null && GetUniversalTemperatureSource().IsActive();
  3464. }
  3465. UTemperatureSource GetUniversalTemperatureSource()
  3466. {
  3467. return m_UniversalTemperatureSource;
  3468. }
  3469. void SetUniversalTemperatureSource(UTemperatureSource uts)
  3470. {
  3471. m_UniversalTemperatureSource = uts;
  3472. }
  3473. vector GetUniversalTemperatureSourcePosition()
  3474. {
  3475. return GetPosition();
  3476. }
  3477. //! Remotely controlled devices helpers
  3478. RemotelyActivatedItemBehaviour GetRemotelyActivatedItemBehaviour();
  3479. void PairRemote(notnull EntityAI trigger);
  3480. void UnpairRemote();
  3481. EntityAI GetPairDevice();
  3482. void SetPersistentPairID(int id)
  3483. {
  3484. RemotelyActivatedItemBehaviour raib = GetRemotelyActivatedItemBehaviour();
  3485. if (raib)
  3486. {
  3487. raib.SetPersistentPairID(id);
  3488. }
  3489. }
  3490. //! Turnable Valve behaviour
  3491. bool HasTurnableValveBehavior();
  3492. bool IsValveTurnable(int pValveIndex);
  3493. int GetTurnableValveIndex(int pComponentIndex);
  3494. void ExecuteActionsConnectedToValve(int pValveIndex);
  3495. //////////////////////////////////
  3496. // attachment exclusion section //
  3497. //////////////////////////////////
  3498. private void InitAttachmentExclusionValues()
  3499. {
  3500. m_AttachmentExclusionSlotMap = new map<int,ref set<int>>();
  3501. m_AttachmentExclusionMaskGlobal = new set<int>;
  3502. m_AttachmentExclusionMaskChildren = new set<int>();
  3503. int count = GetInventory().GetSlotIdCount();
  3504. //no sense in performing inits for something that cannot be attached anywhere (hand/lefthand and some other 'special' slots are the reason for creating 'new' sets above)
  3505. if (count == 0)
  3506. return;
  3507. InitInherentSlotExclusionMap();
  3508. InitGlobalExclusionValues();
  3509. InitLegacyConfigExclusionValues();
  3510. }
  3511. //! map stored on instance to better respond to various state changes
  3512. private void InitInherentSlotExclusionMap()
  3513. {
  3514. int count = GetInventory().GetSlotIdCount();
  3515. //starting with the INVALID slot, so it is always in the map of attachable items
  3516. SetAttachmentExclusionMaskSlot(InventorySlots.INVALID,GetAttachmentExclusionInitSlotValue(InventorySlots.INVALID));
  3517. int slotId;
  3518. for (int i = 0; i < count; i++)
  3519. {
  3520. slotId = GetInventory().GetSlotId(i);
  3521. SetAttachmentExclusionMaskSlot(slotId,GetAttachmentExclusionInitSlotValue(slotId));
  3522. }
  3523. }
  3524. //! override this to modify slot behavior for specific items, or just set 'm_AttachmentExclusionMaskGlobal' value for simple items
  3525. protected set<int> GetAttachmentExclusionInitSlotValue(int slotId)
  3526. {
  3527. set<int> dflt = new set<int>;
  3528. return dflt;
  3529. }
  3530. //Initiated last, and only for items that do not have others defined already
  3531. protected void InitLegacyConfigExclusionValues()
  3532. {
  3533. bool performLegacyInit = InitLegacyExclusionCheck();
  3534. //adding implicit slot info AFTER the check is performed
  3535. InitLegacySlotExclusionValuesImplicit();
  3536. if (performLegacyInit)
  3537. InitLegacySlotExclusionValuesDerived();
  3538. }
  3539. //returns 'false' if the script initialization
  3540. protected bool InitLegacyExclusionCheck()
  3541. {
  3542. //first check the globals
  3543. if (m_AttachmentExclusionMaskGlobal.Count() > 0)
  3544. return false;
  3545. //now the map
  3546. int count = m_AttachmentExclusionSlotMap.Count();
  3547. if (count > 1) //more than InventorySlots.INVALID
  3548. {
  3549. for (int i = 0; i < count; i++)
  3550. {
  3551. int countSet = m_AttachmentExclusionSlotMap.GetElement(i).Count();
  3552. if (countSet > 0) //SOMETHING is defined
  3553. {
  3554. return false;
  3555. }
  3556. }
  3557. }
  3558. return true;
  3559. }
  3560. /**@fn InitLegacySlotExclusionValuesImplicit
  3561. * @brief adding base one-directional relations between headgear, masks, eyewear, and headstraps (exception)
  3562. *
  3563. * @note: 'InitLegacyConfigExclusionValues' adds them the other way if the item does not have any script-side exclusions AND has some legacy config parameter.
  3564. **/
  3565. protected void InitLegacySlotExclusionValuesImplicit()
  3566. {
  3567. int slotId;
  3568. int slotCount = GetInventory().GetSlotIdCount();
  3569. for (int i = 0; i < slotCount; i++)
  3570. {
  3571. slotId = GetInventory().GetSlotId(i);
  3572. set<int> tmp;
  3573. switch (slotId)
  3574. {
  3575. case InventorySlots.HEADGEAR:
  3576. {
  3577. tmp = new set<int>;
  3578. tmp.Copy(GetAttachmentExclusionInitSlotValue(slotId));
  3579. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_MASK);
  3580. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_HEADSTRAP);
  3581. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_EYEWEWEAR);
  3582. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3583. break;
  3584. }
  3585. case InventorySlots.MASK:
  3586. {
  3587. tmp = new set<int>;
  3588. tmp.Copy(GetAttachmentExclusionInitSlotValue(slotId));
  3589. tmp.Insert(EAttExclusions.LEGACY_MASK_HEADGEAR);
  3590. tmp.Insert(EAttExclusions.LEGACY_MASK_HEADSTRAP);
  3591. tmp.Insert(EAttExclusions.LEGACY_MASK_EYEWEWEAR);
  3592. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3593. break;
  3594. }
  3595. case InventorySlots.EYEWEAR:
  3596. {
  3597. tmp = new set<int>;
  3598. tmp.Copy(GetAttachmentExclusionInitSlotValue(slotId));
  3599. if (ConfigGetBool("isStrap"))
  3600. {
  3601. tmp.Insert(EAttExclusions.LEGACY_HEADSTRAP_HEADGEAR);
  3602. tmp.Insert(EAttExclusions.LEGACY_HEADSTRAP_MASK);
  3603. }
  3604. else
  3605. {
  3606. tmp.Insert(EAttExclusions.LEGACY_EYEWEAR_HEADGEAR);
  3607. tmp.Insert(EAttExclusions.LEGACY_EYEWEAR_MASK);
  3608. }
  3609. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3610. break;
  3611. }
  3612. }
  3613. }
  3614. }
  3615. protected void InitLegacySlotExclusionValuesDerived()
  3616. {
  3617. int slotId;
  3618. int slotCount = GetInventory().GetSlotIdCount();
  3619. for (int i = 0; i < slotCount; i++)
  3620. {
  3621. slotId = GetInventory().GetSlotId(i);
  3622. set<int> tmp;
  3623. switch (slotId)
  3624. {
  3625. case InventorySlots.HEADGEAR:
  3626. {
  3627. tmp = new set<int>;
  3628. tmp.Copy(GetAttachmentExclusionMaskSlot(slotId));
  3629. if (ConfigGetBool("noNVStrap"))
  3630. {
  3631. tmp.Insert(EAttExclusions.LEGACY_HEADSTRAP_HEADGEAR);
  3632. }
  3633. if (ConfigGetBool("noMask"))
  3634. {
  3635. tmp.Insert(EAttExclusions.LEGACY_MASK_HEADGEAR);
  3636. }
  3637. if (ConfigGetBool("noEyewear"))
  3638. {
  3639. tmp.Insert(EAttExclusions.LEGACY_EYEWEAR_HEADGEAR);
  3640. }
  3641. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3642. break;
  3643. }
  3644. case InventorySlots.MASK:
  3645. {
  3646. tmp = new set<int>;
  3647. tmp.Copy(GetAttachmentExclusionMaskSlot(slotId));
  3648. if (ConfigGetBool("noNVStrap"))
  3649. {
  3650. tmp.Insert(EAttExclusions.LEGACY_HEADSTRAP_MASK);
  3651. }
  3652. if (ConfigGetBool("noHelmet"))
  3653. {
  3654. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_MASK);
  3655. }
  3656. if (ConfigGetBool("noEyewear"))
  3657. {
  3658. tmp.Insert(EAttExclusions.LEGACY_EYEWEAR_MASK);
  3659. }
  3660. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3661. break;
  3662. }
  3663. case InventorySlots.EYEWEAR:
  3664. {
  3665. tmp = new set<int>;
  3666. tmp.Copy(GetAttachmentExclusionMaskSlot(slotId));
  3667. if (ConfigGetBool("isStrap"))
  3668. {
  3669. if (ConfigGetBool("noHelmet"))
  3670. {
  3671. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_HEADSTRAP);
  3672. }
  3673. if (ConfigGetBool("noMask"))
  3674. {
  3675. tmp.Insert(EAttExclusions.LEGACY_MASK_HEADSTRAP);
  3676. }
  3677. }
  3678. else
  3679. {
  3680. if (ConfigGetBool("noHelmet"))
  3681. {
  3682. tmp.Insert(EAttExclusions.LEGACY_HEADGEAR_EYEWEWEAR);
  3683. }
  3684. if (ConfigGetBool("noMask"))
  3685. {
  3686. tmp.Insert(EAttExclusions.LEGACY_MASK_EYEWEWEAR);
  3687. }
  3688. }
  3689. SetAttachmentExclusionMaskSlot(slotId,tmp);
  3690. break;
  3691. }
  3692. }
  3693. }
  3694. }
  3695. //! override to init part of the mask, independent of slot-specific behavior
  3696. protected void InitGlobalExclusionValues();
  3697. //! to help with item staging exclusions
  3698. protected void AddSingleExclusionValueGlobal(EAttExclusions value)
  3699. {
  3700. if (m_AttachmentExclusionMaskGlobal.Find(value) == -1)
  3701. m_AttachmentExclusionMaskGlobal.Insert(value);
  3702. }
  3703. //! to help with item staging exclusions
  3704. protected void ClearSingleExclusionValueGlobal(EAttExclusions value)
  3705. {
  3706. int idx = m_AttachmentExclusionMaskGlobal.Find(value);
  3707. if (idx != -1)
  3708. m_AttachmentExclusionMaskGlobal.Remove(idx);
  3709. }
  3710. protected void SetAttachmentExclusionMaskGlobal(set<int> values)
  3711. {
  3712. m_AttachmentExclusionMaskGlobal.Clear();
  3713. m_AttachmentExclusionMaskGlobal.Copy(values);
  3714. }
  3715. //! sets values for specific slot
  3716. protected void SetAttachmentExclusionMaskSlot(int slotId, set<int> values)
  3717. {
  3718. if (m_AttachmentExclusionSlotMap)
  3719. {
  3720. m_AttachmentExclusionSlotMap.Set(slotId,values);
  3721. }
  3722. else
  3723. ErrorEx("m_AttachmentExclusionSlotMap not available! Fill the 'inventorySlot[]' in the " + this + " config file.");
  3724. }
  3725. private void PropagateExclusionValueRecursive(set<int> values, int slotId)
  3726. {
  3727. if (values && values.Count() != 0)
  3728. {
  3729. set<int> passThis;
  3730. InventoryLocation lcn = new InventoryLocation();
  3731. GetInventory().GetCurrentInventoryLocation(lcn);
  3732. if (CheckExclusionAccessPropagation(lcn.GetSlot(), slotId, values, passThis))
  3733. {
  3734. m_AttachmentExclusionMaskChildren.InsertSet(passThis);
  3735. EntityAI parent = GetHierarchyParent();
  3736. if (parent)
  3737. parent.PropagateExclusionValueRecursive(passThis,lcn.GetSlot());
  3738. }
  3739. }
  3740. }
  3741. private void ClearExclusionValueRecursive(set<int> values, int slotId)
  3742. {
  3743. if (values && values.Count() != 0)
  3744. {
  3745. set<int> passThis;
  3746. InventoryLocation lcn = new InventoryLocation();
  3747. GetInventory().GetCurrentInventoryLocation(lcn);
  3748. if (CheckExclusionAccessPropagation(lcn.GetSlot(), slotId, values, passThis))
  3749. {
  3750. int count = passThis.Count();
  3751. for (int i = 0; i < count; i++)
  3752. {
  3753. m_AttachmentExclusionMaskChildren.RemoveItem(passThis[i]);
  3754. }
  3755. EntityAI parent = GetHierarchyParent();
  3756. if (parent)
  3757. parent.ClearExclusionValueRecursive(passThis,lcn.GetSlot());
  3758. }
  3759. }
  3760. }
  3761. //! Slot-specific, children (attachments), and additional (state etc.) masks combined
  3762. set<int> GetAttachmentExclusionMaskAll(int slotId)
  3763. {
  3764. set<int> values = new set<int>();
  3765. set<int> slotValues = GetAttachmentExclusionMaskSlot(slotId);
  3766. if (slotValues)
  3767. values.InsertSet(slotValues);
  3768. values.InsertSet(m_AttachmentExclusionMaskGlobal);
  3769. values.InsertSet(m_AttachmentExclusionMaskChildren);
  3770. return values;
  3771. }
  3772. //! Specific slot behavior
  3773. set<int> GetAttachmentExclusionMaskSlot(int slotId)
  3774. {
  3775. return m_AttachmentExclusionSlotMap.Get(slotId);
  3776. }
  3777. //! Global mask value, independent of slot-specific behavior!
  3778. set<int> GetAttachmentExclusionMaskGlobal()
  3779. {
  3780. return m_AttachmentExclusionMaskGlobal;
  3781. }
  3782. //! Mask value coming from the item's attachments
  3783. set<int> GetAttachmentExclusionMaskChildren()
  3784. {
  3785. return m_AttachmentExclusionMaskChildren;
  3786. }
  3787. //! checks if any attachment or item state would interfere with this being attached into a different slot (Headgear -> Mask)
  3788. private bool HasInternalExclusionConflicts(int targetSlot)
  3789. {
  3790. set<int> targetSlotValues = GetAttachmentExclusionMaskSlot(targetSlot);
  3791. if (targetSlotValues) //can be null, if so, no conflict
  3792. {
  3793. set<int> additionalValues = new set<int>(); //NOT slot values
  3794. additionalValues.InsertSet(GetAttachmentExclusionMaskGlobal());
  3795. additionalValues.InsertSet(GetAttachmentExclusionMaskChildren());
  3796. if (additionalValues.Count() > 0)
  3797. {
  3798. int countTarget = targetSlotValues.Count();
  3799. for (int i = 0; i < countTarget; i++)
  3800. {
  3801. if (additionalValues.Find(targetSlotValues[i]) != -1)
  3802. {
  3803. return true;
  3804. }
  3805. }
  3806. }
  3807. }
  3808. return false;
  3809. }
  3810. //! checks 'this' if the incoming flag is present for the current state (slot behavior and others)
  3811. protected bool IsExclusionFlagPresent(set<int> values)
  3812. {
  3813. int slotId;
  3814. string slotName;
  3815. GetInventory().GetCurrentAttachmentSlotInfo(slotId,slotName); //if currently attached, treat it accordingly
  3816. set<int> currentSlotValuesAll = GetAttachmentExclusionMaskAll(slotId);
  3817. int count = values.Count();
  3818. for (int i = 0; i < count; i++)
  3819. {
  3820. if (currentSlotValuesAll.Find(values[i]) != -1)
  3821. return true;
  3822. }
  3823. return false;
  3824. }
  3825. //! Gets flag from what is effectively an owner
  3826. protected bool IsExclusionFlagPresentRecursive(set<int> values, int targetSlot)
  3827. {
  3828. if (values && values.Count() != 0)
  3829. {
  3830. InventoryLocation lcn = new InventoryLocation();
  3831. GetInventory().GetCurrentInventoryLocation(lcn);
  3832. EntityAI parent = GetHierarchyParent();
  3833. set<int> passThis;
  3834. if (CheckExclusionAccessCondition(lcn.GetSlot(),targetSlot, values, passThis))
  3835. {
  3836. if (parent && parent != this) //we reached root if false
  3837. {
  3838. return parent.IsExclusionFlagPresentRecursive(passThis,lcn.GetSlot());
  3839. }
  3840. }
  3841. return IsExclusionFlagPresent(passThis);
  3842. }
  3843. return false;
  3844. }
  3845. //!
  3846. protected bool CheckExclusionAccessCondition(int occupiedSlot, int targetSlot, set<int> value, inout set<int> adjustedValue)
  3847. {
  3848. bool occupiedException = occupiedSlot == InventorySlots.HANDS || occupiedSlot == InventorySlots.SHOULDER || occupiedSlot == InventorySlots.MELEE || occupiedSlot == InventorySlots.LEFTHAND;
  3849. bool targetException = targetSlot == InventorySlots.HANDS || targetSlot == InventorySlots.SHOULDER || targetSlot == InventorySlots.MELEE || targetSlot == InventorySlots.LEFTHAND;
  3850. if (occupiedException)
  3851. {
  3852. adjustedValue = value;
  3853. return false;
  3854. }
  3855. if (targetException)
  3856. {
  3857. adjustedValue = null;
  3858. return false;
  3859. }
  3860. AdjustExclusionAccessCondition(occupiedSlot,targetSlot,value,adjustedValue);
  3861. return adjustedValue.Count() != 0;
  3862. }
  3863. //!if we want to filter
  3864. protected void AdjustExclusionAccessCondition(int occupiedSlot, int testedSlot, set<int> value, inout set<int> adjustedValue)
  3865. {
  3866. adjustedValue = value;
  3867. }
  3868. //! special propagation contition
  3869. protected bool CheckExclusionAccessPropagation(int occupiedSlot, int targetSlot, set<int> value, inout set<int> adjustedValue)
  3870. {
  3871. bool occupiedException = occupiedSlot == InventorySlots.HANDS || occupiedSlot == InventorySlots.SHOULDER || occupiedSlot == InventorySlots.MELEE || occupiedSlot == InventorySlots.LEFTHAND;
  3872. bool targetException = targetSlot == InventorySlots.HANDS || targetSlot == InventorySlots.SHOULDER || targetSlot == InventorySlots.MELEE || targetSlot == InventorySlots.LEFTHAND || targetSlot == InventorySlots.INVALID;
  3873. if (targetException)
  3874. {
  3875. adjustedValue = null;
  3876. return false;
  3877. }
  3878. AdjustExclusionAccessPropagation(occupiedSlot,targetSlot,value,adjustedValue);
  3879. return adjustedValue.Count() != 0;
  3880. }
  3881. //!if we want to filter propagation specifically; DO NOT override unless you know what you are doing.
  3882. protected void AdjustExclusionAccessPropagation(int occupiedSlot, int testedSlot, set<int> value, inout set<int> adjustedValue)
  3883. {
  3884. AdjustExclusionAccessCondition(occupiedSlot,testedSlot,value,adjustedValue);
  3885. }
  3886. bool IsManagingArrows()
  3887. {
  3888. return false;
  3889. }
  3890. ArrowManagerBase GetArrowManager()
  3891. {
  3892. return null;
  3893. }
  3894. void SetFromProjectile(ProjectileStoppedInfo info)
  3895. {
  3896. }
  3897. void ClearInventory();
  3898. };
  3899. #ifdef DEVELOPER
  3900. void SetDebugDeveloper_item(Object entity)//without a setter,the place where the setting happens is near impossible to find as way too many hits for "_item" exist
  3901. {
  3902. if (entity)
  3903. entity.SetDebugItem();
  3904. }
  3905. Object _item;//watched item goes here(LCTRL+RMB->Watch)
  3906. #endif