easteregg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. enum eCaptureState
  2. {
  3. CAPTURE = 0,
  4. RELEASE = 1,
  5. STASIS = 2,
  6. CAPTUREFX = 3,
  7. RELEASEFX = 4,
  8. //Keep this last value at the end, add any new states before
  9. END
  10. }
  11. class EasterEgg : Inventory_Base
  12. {
  13. //Capture parameters
  14. private DayZCreatureAI m_StoredCreature = null;
  15. private string m_CreatureType;
  16. private int m_CreatureHash = 0; //Used for sync
  17. private int m_CaptureState = eCaptureState.STASIS;
  18. private const vector CAPTURE_VELOCITY = { 0, 0, 0 };
  19. //VFX
  20. protected Particle m_ParCapture;
  21. private float m_ParScale = 1;
  22. private const float PARTICLE_SCALE_MULT = 0.1; //Used because we use DistanceSqr to get relevant scale
  23. //SFX
  24. protected EffectSound m_CaptureSound; //Egg SFX
  25. protected EffectSound m_CreatureSound; //Creature specific SFX
  26. protected bool m_DangerSound = false; //Used to determine if release animal is dangerous and play sound accordingly
  27. protected ref map<int, string> m_CreatureSoundMap; //Store all possible creature sound sets mapped to their respective hash
  28. protected int m_CaptureSoundHash; //Used to find capture sound set in map
  29. protected int m_ReleaseSoundHash; //Used to find release sound set in map
  30. void EasterEgg()
  31. {
  32. m_CreatureType = "";
  33. SetEventMask( EntityEvent.CONTACT | EntityEvent.TOUCH );
  34. SetFlags( EntityFlags.TRIGGER, false );
  35. RegisterNetSyncVariableInt( "m_CaptureState", 0, eCaptureState.END );
  36. RegisterNetSyncVariableInt( "m_CreatureHash", 0, 0 );
  37. RegisterNetSyncVariableFloat( "m_ParScale", 0, 0, 0.1 );
  38. RegisterNetSyncVariableBool( "m_DangerSound" );
  39. RegisterNetSyncVariableInt( "m_CaptureSoundHash", 0, 0 );
  40. RegisterNetSyncVariableInt( "m_ReleaseSoundHash", 0, 0 );
  41. RegisterSoundSetMap();
  42. }
  43. void ~EasterEgg()
  44. {
  45. if ( m_ParCapture )
  46. m_ParCapture.Stop();
  47. }
  48. // ------------------------------
  49. // CORE EXECUTION DEPENDING ON CURRENT STATE
  50. // ------------------------------
  51. void ContactEvent( IEntity other, vector pos )
  52. {
  53. switch ( m_CaptureState )
  54. {
  55. case eCaptureState.CAPTURE:
  56. DayZCreatureAI capAnimal = DayZCreatureAI.Cast( other );
  57. if ( capAnimal && capAnimal.IsAlive() )
  58. {
  59. if ( GetGame().IsServer() )
  60. Capture( capAnimal );
  61. }
  62. else
  63. m_CaptureState = eCaptureState.STASIS; //We did not capture anything, go back to stasis
  64. break;
  65. case eCaptureState.RELEASE:
  66. Release( pos );
  67. PlayVFX();
  68. PlaySFX( eCaptureState.RELEASE );
  69. break;
  70. case eCaptureState.CAPTUREFX:
  71. case eCaptureState.RELEASEFX:
  72. //Intermediate state to play FX on next client side contact event
  73. //Creates slight delay but saves network traffic
  74. if ( m_CreatureHash != 0 )
  75. {
  76. //Make sure to go back in stasis
  77. m_CaptureState = eCaptureState.STASIS;
  78. SetSynchDirty();
  79. }
  80. break;
  81. case eCaptureState.STASIS:
  82. //Do nothing here, feel free to add logic for fun fumble effects when nothing happens :)
  83. break;
  84. default: //default in case state is somehow not initialized
  85. break;
  86. }
  87. }
  88. //Used for capture
  89. override void EOnTouch( IEntity other, int extra )
  90. {
  91. ContactEvent( other, GetPosition() );
  92. }
  93. //Used for release
  94. override void EOnContact( IEntity other, Contact extra )
  95. {
  96. ContactEvent( other, extra.Position );
  97. }
  98. override void OnInventoryExit( Man player )
  99. {
  100. //Do not execute on simple drop as it may cause issues
  101. PlayerBase player_PB = PlayerBase.Cast( player );
  102. if ( player_PB && player_PB.GetThrowing().IsThrowingAnimationPlaying() )
  103. {
  104. if ( m_CreatureType != "" )
  105. m_CaptureState = eCaptureState.RELEASE;
  106. else
  107. m_CaptureState = eCaptureState.CAPTURE;
  108. }
  109. else
  110. {
  111. m_CaptureState = eCaptureState.STASIS;
  112. }
  113. //Make sure state is properly synchronized or VFX might bug out
  114. SetSynchDirty();
  115. }
  116. override void OnInventoryEnter( Man player )
  117. {
  118. //Make sure to stop particles once in inventory
  119. if ( GetGame().IsClient() && m_ParCapture )
  120. {
  121. m_ParCapture.Stop();
  122. m_ParCapture.Delete();
  123. }
  124. }
  125. override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
  126. {
  127. super.EEItemLocationChanged(oldLoc, newLoc);
  128. //DestroyEg();
  129. }
  130. // ------------------------------
  131. // CAPTURE AND RELEASE LOGIC
  132. // ------------------------------
  133. private void Capture( DayZCreatureAI capAnimal )
  134. {
  135. if ( !IsAlive() )
  136. {
  137. if ( m_ParCapture )
  138. m_ParCapture.Delete();
  139. Delete();
  140. return;
  141. }
  142. m_StoredCreature = capAnimal;
  143. m_CreatureType = m_StoredCreature.GetType();
  144. m_CreatureHash = m_CreatureType.Hash();
  145. m_CaptureState = eCaptureState.CAPTUREFX;
  146. m_DangerSound = m_StoredCreature.IsDanger();
  147. m_CaptureSoundHash = m_StoredCreature.CaptureSound().Hash();
  148. m_ReleaseSoundHash = m_StoredCreature.ReleaseSound().Hash();
  149. //Resize particle upon capture as there is enough delay to be sure value is synced
  150. ResizeParticle( capAnimal );
  151. SetSynchDirty();
  152. capAnimal.Delete();
  153. SetQuantity( GetQuantityMax() );
  154. SetVelocity( this, CAPTURE_VELOCITY );
  155. }
  156. private void Release( vector pos )
  157. {
  158. if ( GetGame().IsServer() )
  159. {
  160. m_CaptureState = eCaptureState.RELEASEFX;
  161. m_CreatureHash = 0;
  162. SetSynchDirty();
  163. GetGame().CreateObject( m_CreatureType, pos, false, true );
  164. m_CreatureType = "";
  165. DecreaseHealth( "", "", GetMaxHealth() * 0.4 );
  166. SetQuantity( GetQuantityMin(), false );
  167. SetVelocity( this, CAPTURE_VELOCITY );
  168. if ( !IsAlive() )
  169. {
  170. if ( m_ParCapture )
  171. m_ParCapture.Delete();
  172. Delete();
  173. }
  174. }
  175. }
  176. // ------------------------------
  177. // CAPTURE AND RELEASE EFFECTS
  178. // ------------------------------
  179. private void PlayVFX()
  180. {
  181. if ( !GetGame().IsDedicatedServer() )
  182. {
  183. if ( !m_ParCapture && m_CaptureState != eCaptureState.STASIS )
  184. {
  185. //Ideally play a one time effect such as an explosion
  186. m_ParCapture = ParticleManager.GetInstance().PlayInWorld( ParticleList.EASTER_EGG_ACTIVATE, GetPosition() );
  187. //Resize, -1 signifies ALL emitors
  188. m_ParCapture.SetParameter( -1, EmitorParam.SIZE, m_ParScale );
  189. m_ParCapture.SetWiggle( 7, 0.3 );
  190. }
  191. }
  192. }
  193. private void ResizeParticle( DayZCreatureAI capAnimal )
  194. {
  195. //Determine particle scale depending on captured animal scale
  196. vector mins, maxs;
  197. capAnimal.GetWorldBounds( mins, maxs );
  198. m_ParScale = vector.DistanceSq( mins, maxs );
  199. //Multiply to rescale down as fed values can be really large
  200. m_ParScale *= PARTICLE_SCALE_MULT;
  201. }
  202. private void PlaySFX( int releaseCase = eCaptureState.CAPTURE )
  203. {
  204. if ( !GetGame().IsDedicatedServer() )
  205. {
  206. string soundSet = "";
  207. if ( releaseCase == eCaptureState.CAPTURE )
  208. {
  209. PlaySoundSet( m_CaptureSound, "EasterEgg_Catch_SoundSet", 0, 0 );
  210. m_CreatureSoundMap.Find( m_CaptureSoundHash, soundSet );
  211. PlaySoundSet( m_CreatureSound, soundSet, 0, 0 );
  212. }
  213. else
  214. {
  215. if ( !m_DangerSound )
  216. {
  217. PlaySoundSet( m_CaptureSound, "EasterEgg_Spawn_SoundSet", 0, 0 );
  218. m_CreatureSoundMap.Find( m_ReleaseSoundHash, soundSet );
  219. PlaySoundSet( m_CreatureSound, soundSet, 0, 0 );
  220. }
  221. else
  222. {
  223. PlaySoundSet( m_CaptureSound, "EasterEgg_Spawn_Danger_SoundSet", 0, 0 );
  224. m_CreatureSoundMap.Find( m_ReleaseSoundHash, soundSet );
  225. PlaySoundSet( m_CreatureSound, soundSet, 0, 0 );
  226. }
  227. }
  228. }
  229. }
  230. override void OnVariablesSynchronized()
  231. {
  232. if ( m_CaptureState == eCaptureState.CAPTUREFX )
  233. {
  234. PlayVFX();
  235. PlaySFX();
  236. }
  237. else if ( m_CaptureState == eCaptureState.RELEASEFX )
  238. {
  239. PlayVFX();
  240. PlaySFX( eCaptureState.RELEASE );
  241. }
  242. }
  243. // ------------------------------
  244. // SOUNDSET MAP REGISTRATION
  245. // ------------------------------
  246. void RegisterSoundSetMap()
  247. {
  248. //Register all possible creature sounds in map with their respective hash
  249. string soundSet;
  250. m_CreatureSoundMap = new map<int, string>;
  251. //Cow sounds
  252. soundSet = "CattleMooA_SoundSet";
  253. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  254. soundSet = "CattleBellow_SoundSet";
  255. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  256. //Deer sounds
  257. soundSet = "DeerRoar_SoundSet";
  258. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  259. soundSet = "DeerBleat_SoundSet";
  260. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  261. //Goat sounds
  262. soundSet = "GoatBleat_A_SoundSet";
  263. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  264. soundSet = "GoatBleat_B_SoundSet";
  265. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  266. //Hare sounds
  267. soundSet = "HareChirp_SoundSet";
  268. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  269. soundSet = "HareSquawk_SoundSet";
  270. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  271. //Hen sounds
  272. soundSet = "HenCluck_X_SoundSet";
  273. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  274. soundSet = "HenScream_SoundSet";
  275. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  276. //Hog sounds
  277. soundSet = "HogGrunt_G_SoundSet";
  278. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  279. soundSet = "HogSqueal_SoundSet";
  280. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  281. //Sheep sounds
  282. soundSet = "SheepBleat_G_SoundSet";
  283. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  284. soundSet = "SheepBleat_E_SoundSet";
  285. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  286. //Wolf sounds
  287. soundSet = "WolfBark_SoundSet";
  288. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  289. soundSet = "WolfWhimper_SoundSet";
  290. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  291. //Zmb F sounds
  292. soundSet = "ZmbF_Normal_CallToArmsShort_Soundset";
  293. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  294. soundSet = "ZmbF_Normal_HeavyHit_Soundset";
  295. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  296. //Zmb M sounds
  297. soundSet = "ZmbM_Normal_CallToArmsShort_Soundset";
  298. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  299. soundSet = "ZmbM_Normal_HeavyHit_Soundset";
  300. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  301. //Bear sounds
  302. soundSet = "BearRoarShort_SoundSet";
  303. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  304. soundSet = "BearSnarl_SoundSet";
  305. m_CreatureSoundMap.Insert( soundSet.Hash(), soundSet );
  306. }
  307. // ------------------------------
  308. // STORAGE SAVING AND LOADING
  309. // ------------------------------
  310. override void OnStoreSave( ParamsWriteContext ctx )
  311. {
  312. super.OnStoreSave( ctx );
  313. ctx.Write( m_CaptureState );
  314. ctx.Write( m_CreatureType );
  315. ctx.Write( m_ParScale );
  316. ctx.Write( m_DangerSound );
  317. ctx.Write( m_CaptureSoundHash );
  318. ctx.Write( m_ReleaseSoundHash );
  319. }
  320. override bool OnStoreLoad( ParamsReadContext ctx, int version )
  321. {
  322. if ( !super.OnStoreLoad( ctx, version ) )
  323. return false;
  324. if ( !ctx.Read( m_CaptureState ) )
  325. return false;
  326. if ( !ctx.Read( m_CreatureType ) )
  327. return false;
  328. if ( !ctx.Read( m_ParScale ) )
  329. return false;
  330. if ( !ctx.Read( m_DangerSound ) )
  331. return false;
  332. if ( !ctx.Read( m_CaptureSoundHash ) )
  333. return false;
  334. if ( !ctx.Read( m_ReleaseSoundHash ) )
  335. return false;
  336. return true;
  337. }
  338. //Protection against dupers during 1.12
  339. private void DestroyEg()
  340. {
  341. Delete();
  342. }
  343. };