remotedetonator.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. enum ERemoteDetonatorLEDState
  2. {
  3. OFF = 0,
  4. LIT,
  5. }
  6. class RemoteDetonator : Inventory_Base
  7. {
  8. const string COLOR_LED_OFF = "#(argb,8,8,3)color(0,0,0,1.0,co)";
  9. const string COLOR_LED_LIT = "#(argb,8,8,3)color(1,0,0,1.0,co)";
  10. const string SELECTION_NAME_LED = "LED";
  11. protected ERemoteDetonatorLEDState m_LastLEDState;
  12. bool IsKit()
  13. {
  14. return true;
  15. }
  16. void UpdateLED(ERemoteDetonatorLEDState pState, bool pForced = false)
  17. {
  18. int selectionIdx = GetHiddenSelectionIndex(SELECTION_NAME_LED);
  19. switch (pState)
  20. {
  21. case ERemoteDetonatorLEDState.LIT:
  22. SetObjectTexture(selectionIdx, COLOR_LED_LIT);
  23. break;
  24. default:
  25. SetObjectTexture(selectionIdx, COLOR_LED_OFF);
  26. }
  27. m_LastLEDState = pState;
  28. SetSynchDirty();
  29. }
  30. override void SetActions()
  31. {
  32. super.SetActions();
  33. AddAction(ActionAttachExplosivesTrigger);
  34. AddAction(ActionDisarmExplosiveWithRemoteDetonatorUnpaired);
  35. }
  36. }
  37. class RemoteDetonatorTrigger : RemoteDetonator
  38. {
  39. protected const string ANIM_PHASE_TRIGGER = "trigger";
  40. protected bool m_LED;
  41. protected ref RemotelyActivatedItemBehaviour m_RAIB;
  42. void RemoteDetonatorTrigger()
  43. {
  44. m_RAIB = new RemotelyActivatedItemBehaviour(this);
  45. m_RAIB.SetTrigger();
  46. RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdLow");
  47. RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdHigh");
  48. RegisterNetSyncVariableInt("m_LastLEDState", 0, EnumTools.GetEnumSize(ERemoteDetonatorLEDState));
  49. UpdateLED(m_LastLEDState);
  50. }
  51. override bool IsKit()
  52. {
  53. return false;
  54. }
  55. override void OnVariablesSynchronized()
  56. {
  57. super.OnVariablesSynchronized();
  58. if (m_RAIB)
  59. {
  60. m_RAIB.OnVariableSynchronized();
  61. }
  62. UpdateLED(m_LastLEDState);
  63. }
  64. override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
  65. {
  66. super.EEItemLocationChanged(oldLoc, newLoc);
  67. if (m_RAIB)
  68. {
  69. m_RAIB.Pair();
  70. }
  71. }
  72. override RemotelyActivatedItemBehaviour GetRemotelyActivatedItemBehaviour()
  73. {
  74. return m_RAIB;
  75. }
  76. override void OnCEUpdate()
  77. {
  78. super.OnCEUpdate();
  79. if (!IsRuined() && IsConnected() && GetControlledDevice())
  80. {
  81. if (vector.DistanceSq(GetPosition(), GetControlledDevice().GetPosition()) <= Math.SqrFloat(UAMaxDistances.EXPLOSIVE_REMOTE_ACTIVATION))
  82. {
  83. UpdateLED(ERemoteDetonatorLEDState.LIT);
  84. return;
  85. }
  86. }
  87. UpdateLED(ERemoteDetonatorLEDState.OFF);
  88. }
  89. override void PairRemote(notnull EntityAI trigger)
  90. {
  91. m_RAIB.Pair(trigger);
  92. }
  93. override void UnpairRemote()
  94. {
  95. UpdateLED(ERemoteDetonatorLEDState.OFF);
  96. m_RAIB.Unpair();
  97. }
  98. override void OnActivatedByItem(notnull ItemBase item)
  99. {
  100. if (GetGame().IsServer())
  101. {
  102. if (m_RAIB.IsPaired() && !IsRuined())
  103. {
  104. ItemBase device = ItemBase.Cast(GetControlledDevice());
  105. if (device && vector.DistanceSq(GetPosition(), device.GetPosition()) <= Math.SqrFloat(UAMaxDistances.EXPLOSIVE_REMOTE_ACTIVATION))
  106. {
  107. device.OnActivatedByItem(this);
  108. }
  109. }
  110. }
  111. }
  112. void SetControlledDevice(EntityAI pDevice)
  113. {
  114. m_RAIB.Pair(pDevice);
  115. }
  116. bool IsConnected()
  117. {
  118. return m_RAIB.IsPaired();
  119. }
  120. EntityAI GetControlledDevice()
  121. {
  122. return m_RAIB.GetPairDevice();
  123. }
  124. static RemoteDetonatorTrigger SpawnInPlayerHands(notnull EntityAI pEntity, EntityAI deviceToPair = null)
  125. {
  126. string type = "RemoteDetonatorTrigger";
  127. RemoteDetonatorTrigger rdt;
  128. PlayerBase player = PlayerBase.Cast(pEntity);
  129. if (player)
  130. {
  131. ItemBase inHandsItem = player.GetItemInHands();
  132. if (inHandsItem)
  133. {
  134. if (deviceToPair)
  135. {
  136. ReplaceDetonatorItemOnArmLambda onArmLambda = new ReplaceDetonatorItemOnArmLambda(inHandsItem, type);
  137. onArmLambda.SetPairDevice(deviceToPair);
  138. MiscGameplayFunctions.TurnItemIntoItemEx(player, onArmLambda);
  139. }
  140. else
  141. {
  142. ReplaceDetonatorItemLambda lambda = new ReplaceDetonatorItemLambda(inHandsItem, type);
  143. MiscGameplayFunctions.TurnItemIntoItemEx(player, lambda);
  144. }
  145. rdt = RemoteDetonatorTrigger.Cast(player.GetItemInHands());
  146. }
  147. else
  148. rdt = RemoteDetonatorTrigger.Cast(player.GetHumanInventory().CreateInHands(type));
  149. //! item replaced, use different IK
  150. if (player.GetItemInHands())
  151. player.GetItemAccessor().OnItemInHandsChanged();
  152. }
  153. return rdt;
  154. }
  155. override void OnAnimationPhaseStarted(string animSource, float phase)
  156. {
  157. if (animSource == ANIM_PHASE_TRIGGER)
  158. {
  159. if (phase > 0.01)
  160. {
  161. UpdateLED(ERemoteDetonatorLEDState.OFF);
  162. }
  163. }
  164. }
  165. override void SetActions()
  166. {
  167. super.SetActions();
  168. RemoveAction(ActionAttachExplosivesTrigger);
  169. AddAction(ActionAttachOnTrap);
  170. AddAction(ActionDisarmExplosiveWithRemoteDetonator);
  171. AddAction(ActionTriggerRemotely);
  172. }
  173. #ifdef DIAG_DEVELOPER
  174. override protected string GetDebugText()
  175. {
  176. string debug_output;
  177. debug_output += string.Format("low net id: %1\n", m_RAIB.GetPairDeviceNetIdLow());
  178. debug_output += string.Format("high net id: %1\n", m_RAIB.GetPairDeviceNetIdHigh());
  179. debug_output += string.Format("pair device: %1\n", m_RAIB.GetPairDevice());
  180. return debug_output;
  181. }
  182. #endif
  183. }
  184. class RemoteDetonatorReceiver : RemoteDetonator
  185. {
  186. void RemoteDetonatorReceiver()
  187. {
  188. UpdateLED(ERemoteDetonatorLEDState.OFF, true);
  189. }
  190. override bool IsKit()
  191. {
  192. return false;
  193. }
  194. override void OnWasDetached(EntityAI parent, int slot_id)
  195. {
  196. UpdateLED(ERemoteDetonatorLEDState.OFF);
  197. }
  198. override void EEKilled(Object killer)
  199. {
  200. super.EEKilled(killer);
  201. UpdateLED(ERemoteDetonatorLEDState.OFF, true);
  202. }
  203. override void SetActions()
  204. {
  205. super.SetActions();
  206. RemoveAction(ActionAttachExplosivesTrigger);
  207. RemoveAction(ActionDisarmExplosiveWithRemoteDetonatorUnpaired);
  208. }
  209. }
  210. class ReplaceDetonatorItemLambda : ReplaceItemWithNewLambdaBase
  211. {
  212. override void CopyOldPropertiesToNew(notnull EntityAI old_item, EntityAI new_item)
  213. {
  214. super.CopyOldPropertiesToNew(old_item, new_item);
  215. MiscGameplayFunctions.TransferItemProperties(old_item, new_item);
  216. }
  217. }
  218. class ReplaceDetonatorItemOnArmLambda : ReplaceDetonatorItemLambda
  219. {
  220. EntityAI m_PairDevice
  221. void SetPairDevice(EntityAI device)
  222. {
  223. m_PairDevice = device;
  224. }
  225. override void OnSuccess(EntityAI new_item)
  226. {
  227. super.OnSuccess(new_item);
  228. RemoteDetonator detonator = RemoteDetonator.Cast(new_item);
  229. if (detonator)
  230. {
  231. ExplosivesBase explosive = ExplosivesBase.Cast(m_PairDevice);
  232. if (explosive)
  233. {
  234. ItemBase receiver = ItemBase.Cast(explosive.GetInventory().CreateAttachment("RemoteDetonatorReceiver"));
  235. if (receiver)
  236. {
  237. MiscGameplayFunctions.TransferItemProperties(detonator, receiver);
  238. receiver.LockToParent();
  239. explosive.SetTakeable(false);
  240. explosive.PairWithDevice(detonator);
  241. explosive.Arm();
  242. }
  243. }
  244. }
  245. }
  246. override void OnAbort()
  247. {
  248. ExplosivesBase explosive = ExplosivesBase.Cast(m_PairDevice);
  249. if (explosive)
  250. {
  251. explosive.LockTriggerSlots();
  252. explosive.SetTakeable(true);
  253. }
  254. }
  255. }
  256. class ReplaceDetonatorItemOnDisarmLambda : ReplaceDetonatorItemLambda
  257. {
  258. override void OnSuccess(EntityAI new_item)
  259. {
  260. super.OnSuccess(new_item);
  261. RemoteDetonator detonator = RemoteDetonator.Cast(m_OldItem);
  262. if (detonator)
  263. {
  264. if (detonator.GetRemotelyActivatedItemBehaviour())
  265. {
  266. ExplosivesBase explosive = ExplosivesBase.Cast(detonator.GetRemotelyActivatedItemBehaviour().GetPairDevice());
  267. if (explosive)
  268. {
  269. explosive.Disarm();
  270. }
  271. }
  272. }
  273. }
  274. override void OnAbort()
  275. {
  276. super.OnAbort();
  277. RemoteDetonator detonator = RemoteDetonator.Cast(m_OldItem);
  278. if (detonator)
  279. {
  280. if (detonator.GetRemotelyActivatedItemBehaviour())
  281. {
  282. ExplosivesBase explosive = ExplosivesBase.Cast(detonator.GetRemotelyActivatedItemBehaviour().GetPairDevice());
  283. if (explosive)
  284. {
  285. explosive.LockExplosivesSlots();
  286. }
  287. }
  288. }
  289. }
  290. }