combinationlock.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. enum LockAction
  2. {
  3. NONE,
  4. DIAL_NUMBER_CHANED,
  5. DIAL_INDEX_CHANGED,
  6. LOCKED,
  7. UNLOCKED,
  8. COUNT
  9. }
  10. class CombinationLock extends ItemBase
  11. {
  12. int m_LockDigits; //how many digits will the combination contain
  13. int m_Combination; //actual combination that is dialed on lock
  14. int m_CombinationLocked; //combination that was dialed on lock before the shuffle
  15. int m_DialIndex; //index of current combination dial
  16. protected bool m_IsLocked;
  17. protected LockAction m_LockActionPerformed = LockAction.NONE;
  18. protected bool m_IsInitialized;
  19. //Sounds
  20. //build
  21. const string SOUND_LOCK_OPEN = "combinationlock_open_SoundSet";
  22. const string SOUND_LOCK_CLOSE = "combinationlock_close_SoundSet";
  23. const string SOUND_LOCK_CHANGE_NUMBER = "combinationlock_changenumber_SoundSet";
  24. const string SOUND_LOCK_CHANGE_DIAL = "combinationlock_changedial_SoundSet";
  25. protected EffectSound m_Sound;
  26. void CombinationLock()
  27. {
  28. SetBaseLockValues();
  29. //synchronized variables
  30. int combination_length = Math.Pow( 10, m_LockDigits );
  31. RegisterNetSyncVariableBool( "m_IsLocked" );
  32. RegisterNetSyncVariableInt( "m_Combination", 0, combination_length - 1 );
  33. RegisterNetSyncVariableInt( "m_DialIndex", 0, m_LockDigits - 1 );
  34. RegisterNetSyncVariableInt( "m_LockActionPerformed", 0, LockAction.COUNT );
  35. }
  36. protected void SetBaseLockValues()
  37. {
  38. //set lock init values
  39. m_LockDigits = 3;
  40. m_Combination = 111;
  41. m_CombinationLocked = 999;
  42. m_IsLocked = false;
  43. }
  44. override void EEInit()
  45. {
  46. super.EEInit();
  47. GetGame().GetCallQueue( CALL_CATEGORY_GAMEPLAY ).CallLater( SetInitialized, 1000, false );
  48. //SetInitialized();
  49. //set visual on init
  50. UpdateVisuals();
  51. }
  52. void SetInitialized()
  53. {
  54. m_IsInitialized = true;
  55. }
  56. override bool IsInitialized()
  57. {
  58. return m_IsInitialized;
  59. }
  60. override void OnItemLocationChanged( EntityAI old_owner, EntityAI new_owner )
  61. {
  62. super.OnItemLocationChanged( old_owner, new_owner );
  63. //Check combination lock
  64. if ( GetGame().IsServer() )
  65. {
  66. if ( IsInitialized() && new_owner && new_owner.IsInherited( BaseBuildingBase ) )
  67. {
  68. LockServer( new_owner );
  69. }
  70. }
  71. }
  72. // --- EVENTS
  73. override void OnStoreSave( ParamsWriteContext ctx )
  74. {
  75. super.OnStoreSave( ctx );
  76. //write data
  77. ctx.Write( m_Combination );
  78. ctx.Write( m_CombinationLocked );
  79. }
  80. override bool OnStoreLoad( ParamsReadContext ctx, int version )
  81. {
  82. if ( !super.OnStoreLoad( ctx, version ) )
  83. return false;
  84. //--- Combination Lock data ---
  85. //combination
  86. if ( !ctx.Read( m_Combination ) )
  87. {
  88. m_Combination = 0;
  89. return false;
  90. }
  91. //combination locked
  92. if ( !ctx.Read( m_CombinationLocked ) )
  93. {
  94. m_CombinationLocked = 0;
  95. return false;
  96. }
  97. //is lock attached
  98. if ( version < 105 ) //removed in 105
  99. {
  100. bool is_lock_attached;
  101. if ( !ctx.Read( is_lock_attached ) )
  102. {
  103. return false;
  104. }
  105. }
  106. return true;
  107. }
  108. override void AfterStoreLoad()
  109. {
  110. super.AfterStoreLoad();
  111. //Check combination lock
  112. if ( GetGame().IsServer() )
  113. {
  114. EntityAI parent = GetHierarchyParent();
  115. if ( parent && parent.IsInherited( BaseBuildingBase ) )
  116. {
  117. LockServer( parent, true );
  118. }
  119. }
  120. //synchronize
  121. Synchronize();
  122. }
  123. // --- SYNCHRONIZATION
  124. void Synchronize()
  125. {
  126. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] CombinationLock.Synchronize " + " m_Combination=" + m_Combination + " m_CombinationLocked=" + m_CombinationLocked);
  127. if ( GetGame().IsServer() )
  128. {
  129. SetSynchDirty();
  130. GetGame().GetCallQueue( CALL_CATEGORY_SYSTEM ).CallLater( ResetActionVar, 1000);//synced var used to trigger client sound needs to be reset after triggering the sound
  131. UpdateVisuals();
  132. }
  133. }
  134. void ResetActionVar()
  135. {
  136. m_LockActionPerformed = LockAction.NONE;
  137. }
  138. override void OnVariablesSynchronized()
  139. {
  140. super.OnVariablesSynchronized();
  141. //update visuals (client)
  142. UpdateVisuals();
  143. //update sound (client)
  144. if (m_LockActionPerformed)
  145. UpdateSound();
  146. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] CombinationLock.OnVariablesSynchronized " + " m_Combination=" + m_Combination + " m_CombinationLocked=" + m_CombinationLocked);
  147. }
  148. void SetCombination( int combination )
  149. {
  150. m_Combination = combination;
  151. }
  152. void SetCombinationLocked( int combination )
  153. {
  154. m_CombinationLocked = combination;
  155. }
  156. int GetCombination()
  157. {
  158. return m_Combination;
  159. }
  160. int GetLockDigits()
  161. {
  162. return m_LockDigits;
  163. }
  164. // --- ACTIONS
  165. void DialNextNumber()
  166. {
  167. string combination_text = m_Combination.ToString();
  168. string dialed_text;
  169. //insert zeros to dials with 0 value
  170. int length_diff = m_LockDigits - combination_text.Length();
  171. for ( int i = 0; i < length_diff; ++i )
  172. {
  173. combination_text = "0" + combination_text;
  174. }
  175. //assemble the whole combination with increased part
  176. for ( int j = 0; j < combination_text.Length(); ++j )
  177. {
  178. if ( j == m_DialIndex )
  179. {
  180. int next_dialed_number = combination_text.Get( j ).ToInt() + 1;
  181. if ( next_dialed_number > 9 )
  182. {
  183. next_dialed_number = 0;
  184. }
  185. dialed_text += next_dialed_number.ToString();
  186. }
  187. else
  188. {
  189. dialed_text += combination_text.Get( j );
  190. }
  191. }
  192. //set new number
  193. SetCombination( dialed_text.ToInt() );
  194. m_LockActionPerformed = LockAction.DIAL_INDEX_CHANGED;
  195. CheckLockedStateServer();
  196. //synchronize
  197. Synchronize();
  198. }
  199. int GetDialIndex()
  200. {
  201. return m_DialIndex;
  202. }
  203. void SetNextDial()
  204. {
  205. if ( m_LockDigits > 1 )
  206. {
  207. if ( m_DialIndex <= m_LockDigits - 2 )
  208. {
  209. m_DialIndex++;
  210. }
  211. else if ( m_DialIndex >= m_LockDigits > - 1 )
  212. {
  213. m_DialIndex = 0;
  214. }
  215. }
  216. else
  217. {
  218. m_DialIndex = 0;
  219. }
  220. //performed action
  221. m_LockActionPerformed = LockAction.DIAL_NUMBER_CHANED;
  222. //synchronize
  223. Synchronize();
  224. }
  225. //Lock lock
  226. void LockServer( EntityAI parent, bool ignore_combination = false )
  227. {
  228. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] CombinationLock.LockServer " + " m_Combination=" + m_Combination + " m_CombinationLocked=" + m_CombinationLocked);
  229. if ( IsLockAttached() )
  230. {
  231. if ( !ignore_combination )
  232. {
  233. SetCombinationLocked( m_Combination );
  234. //set slot lock
  235. InventoryLocation inventory_location = new InventoryLocation;
  236. GetInventory().GetCurrentInventoryLocation( inventory_location );
  237. parent.GetInventory().SetSlotLock( inventory_location.GetSlot(), true );
  238. m_LockActionPerformed = LockAction.LOCKED;
  239. }
  240. ShuffleLock();
  241. SetTakeable(false);
  242. CheckLockedStateServer();
  243. //synchronize
  244. Synchronize();
  245. }
  246. //reset performed action
  247. //m_LockActionPerformed = LockAction.NONE;
  248. }
  249. void UnlockServer( EntityAI player, EntityAI parent )
  250. {
  251. if (LogManager.IsBaseBuildingLogEnable()) bsbDebugPrint("[bsb] CombinationLock.UnlockServer " + " m_Combination=" + m_Combination + " m_CombinationLocked=" + m_CombinationLocked);
  252. if ( IsLockAttached() )
  253. {
  254. Fence fence = Fence.Cast( parent );
  255. //set slot unlock
  256. InventoryLocation inventory_location = new InventoryLocation;
  257. GetInventory().GetCurrentInventoryLocation( inventory_location );
  258. fence.GetInventory().SetSlotLock( inventory_location.GetSlot(), false );
  259. //drop entity from attachment slot
  260. if (GetGame().IsMultiplayer())
  261. {
  262. if (player)
  263. player.ServerDropEntity(this);
  264. else
  265. parent.GetInventory().DropEntity(InventoryMode.SERVER, parent, this);
  266. }
  267. else
  268. {
  269. if (player)
  270. player.LocalDropEntity(this);
  271. else
  272. parent.GetInventory().DropEntity(InventoryMode.LOCAL, parent, this);
  273. }
  274. SetPosition( fence.GetKitSpawnPosition() );
  275. PlaceOnSurface();
  276. m_LockActionPerformed = LockAction.UNLOCKED;
  277. SetTakeable(true);
  278. CheckLockedStateServer();
  279. //synchronize
  280. Synchronize();
  281. }
  282. //reset performed action
  283. //m_LockActionPerformed = LockAction.NONE;
  284. }
  285. //Shuffle lock
  286. void ShuffleLock()
  287. {
  288. string combination_text = m_Combination.ToString();
  289. string shuffled_text;
  290. //insert zeros to dials with 0 value
  291. int length_diff = m_LockDigits - combination_text.Length();
  292. for ( int i = 0; i < length_diff; ++i )
  293. {
  294. combination_text = "0" + combination_text;
  295. }
  296. //assemble the whole combination with increased part
  297. for ( int j = 0; j < combination_text.Length(); ++j )
  298. {
  299. int dial_number = combination_text.Get( j ).ToInt();
  300. dial_number = ( dial_number + Math.RandomInt( 1, 9 ) ) % 10;
  301. shuffled_text = shuffled_text + dial_number.ToString();
  302. }
  303. SetCombination( shuffled_text.ToInt() );
  304. }
  305. bool IsLocked()
  306. {
  307. return m_IsLocked;
  308. }
  309. void CheckLockedStateServer()
  310. {
  311. m_IsLocked = m_Combination != m_CombinationLocked;
  312. }
  313. bool IsLockedOnGate()
  314. {
  315. Fence fence = Fence.Cast( GetHierarchyParent() );
  316. if ( fence )
  317. {
  318. if ( IsLocked() )
  319. {
  320. return true;
  321. }
  322. }
  323. return false;
  324. }
  325. bool IsLockAttached()
  326. {
  327. Fence fence = Fence.Cast( GetHierarchyParent() );
  328. if ( fence )
  329. {
  330. return true;
  331. }
  332. return false;
  333. }
  334. //destroy lock
  335. void DestroyLock()
  336. {
  337. GetGame().ObjectDelete( this );
  338. }
  339. // --- VISUALS
  340. void UpdateVisuals()
  341. {
  342. //Client/Server
  343. if ( IsLockedOnGate() )
  344. {
  345. GetGame().GetCallQueue( CALL_CATEGORY_GAMEPLAY ).CallLater( HideItem, 0, false );
  346. GetGame().GetCallQueue( CALL_CATEGORY_GAMEPLAY ).CallLater( ShowAttached, 0, false );
  347. }
  348. else
  349. {
  350. GetGame().GetCallQueue( CALL_CATEGORY_GAMEPLAY ).CallLater( ShowItem, 0, false );
  351. GetGame().GetCallQueue( CALL_CATEGORY_GAMEPLAY ).CallLater( HideAttached, 0, false );
  352. }
  353. }
  354. void UpdateSound()
  355. {
  356. //was locked
  357. if ( m_LockActionPerformed == LockAction.LOCKED )
  358. {
  359. SoundLockClose();
  360. }
  361. //was unlocked
  362. if ( m_LockActionPerformed == LockAction.UNLOCKED )
  363. {
  364. SoundLockOpen();
  365. }
  366. //next dial index
  367. if ( m_LockActionPerformed == LockAction.DIAL_INDEX_CHANGED )
  368. {
  369. SoundLockChangeDial();
  370. }
  371. //dialed new number
  372. if ( m_LockActionPerformed == LockAction.DIAL_NUMBER_CHANED )
  373. {
  374. SoundLockChangeNumber();
  375. }
  376. }
  377. //Show/Hide anims
  378. protected void ShowItem()
  379. {
  380. SetAnimationPhase( "Combination_Lock_Item", 0 );
  381. SetAnimationPhase( "Lock_Item_1", 0 );
  382. SetAnimationPhase( "Lock_Item_2", 0 );
  383. }
  384. protected void HideItem()
  385. {
  386. SetAnimationPhase( "Combination_Lock_Item", 1 );
  387. SetAnimationPhase( "Lock_Item_1", 1 );
  388. SetAnimationPhase( "Lock_Item_2", 1 );
  389. }
  390. protected void ShowAttached()
  391. {
  392. SetAnimationPhase( "Combination_Lock_Attached", 0 );
  393. SetAnimationPhase( "Lock_Attached_1", 0 );
  394. SetAnimationPhase( "Lock_Attached_2", 0 );
  395. }
  396. protected void HideAttached()
  397. {
  398. SetAnimationPhase( "Combination_Lock_Attached", 1 );
  399. SetAnimationPhase( "Lock_Attached_1", 1 );
  400. SetAnimationPhase( "Lock_Attached_2", 1 );
  401. }
  402. // ---
  403. //================================================================
  404. // SOUNDS
  405. //================================================================
  406. protected void SoundLockOpen()
  407. {
  408. PlaySoundSet( m_Sound, SOUND_LOCK_OPEN, 0, 0 );
  409. }
  410. protected void SoundLockClose()
  411. {
  412. PlaySoundSet( m_Sound, SOUND_LOCK_CLOSE, 0, 0 );
  413. }
  414. void SoundLockChangeNumber()
  415. {
  416. PlaySoundSet( m_Sound, SOUND_LOCK_CHANGE_NUMBER, 0, 0 );
  417. }
  418. void SoundLockChangeDial()
  419. {
  420. PlaySoundSet( m_Sound, SOUND_LOCK_CHANGE_DIAL, 0, 0 );
  421. }
  422. override void SetActions()
  423. {
  424. super.SetActions();
  425. AddAction(ActionAttachToConstruction);
  426. AddAction(ActionNextCombinationLockDial);
  427. AddAction(ActionDialCombinationLock);
  428. AddAction(ActionNextCombinationLockDialOnTarget);
  429. AddAction(ActionDialCombinationLockOnTarget);
  430. }
  431. }