magnum.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. const float MAGNUM_ROTATION_POSITION_M1 = -0.167;
  2. const float MAGNUM_ROTATION_POSITION_0 = 0.0;
  3. const float MAGNUM_ROTATION_POSITION_1 = 0.167;
  4. const float MAGNUM_ROTATION_POSITION_2 = 0.334;
  5. const float MAGNUM_ROTATION_POSITION_3 = 0.500;
  6. const float MAGNUM_ROTATION_POSITION_4 = 0.668;
  7. const float MAGNUM_ROTATION_POSITION_5 = 0.835;
  8. const float MAGNUM_ROTATION_POSITION_6 = 1.0;
  9. enum MagnumAnimState
  10. {
  11. DEFAULT = 0, ///< default weapon state
  12. };
  13. enum MagnumStableStateID
  14. {
  15. UNKNOWN = 0,
  16. DEFAULT = 1,
  17. }
  18. class Magnum_Static_State extends WeaponStableState
  19. {
  20. bool init = false;
  21. override void OnEntry(WeaponEventBase e)
  22. {
  23. if (LogManager.IsWeaponLogEnable()) { wpnPrint("[wpnstate] { Magnum stable state"); }
  24. super.OnEntry(e);
  25. if (init)
  26. {
  27. Magnum_Base magnum;
  28. if (CastTo(magnum, m_weapon))
  29. {
  30. magnum.SyncCylinderRotation();
  31. //magnum.SyncSelectionStateFromState();
  32. }
  33. }
  34. init = true;
  35. }
  36. override void OnExit (WeaponEventBase e) { super.OnExit(e); if (LogManager.IsWeaponLogEnable()) { wpnPrint("[wpnstate] } Magnum stable state"); } }
  37. override int GetCurrentStateID () { return MagnumStableStateID.DEFAULT; }
  38. override bool HasBullet() { return m_weapon.IsChamberFull(m_weapon.GetCurrentMuzzle()); }
  39. override bool HasMagazine() { return false; }
  40. override bool IsJammed() { return m_weapon.IsJammed(); }
  41. override bool IsSingleState() { return true; }
  42. };
  43. class Magnum_Base extends Weapon_Base
  44. {
  45. ref WeaponStableState C;
  46. int m_LastMuzzleloaded;
  47. int m_ActiveMuzzle;
  48. const string ATT_SLOT_CYLINDER = "RevolverCylinder";
  49. const string ATT_SLOT_EJECTOR = "RevolverEjector";
  50. override void SetActions()
  51. {
  52. super.SetActions();
  53. AddAction(FirearmActionLoadMultiBullet);
  54. RemoveAction(FirearmActionLoadBulletQuick); // Easy reload
  55. AddAction(FirearmActionLoadMultiBulletQuick); // Easy reload
  56. }
  57. override RecoilBase SpawnRecoilObject()
  58. {
  59. return new MagnumRecoil(this);
  60. }
  61. void Magnum_Base ()
  62. {
  63. m_LastMuzzleloaded = 0;
  64. m_ActiveMuzzle = 0;
  65. /*m_abilities.Insert(new AbilityRecord(WeaponActions.CHAMBERING, WeaponActionTypes.CHAMBERING_STARTLOOPABLE_CLOSED));
  66. m_abilities.Insert(new AbilityRecord(WeaponActions.CHAMBERING, WeaponActionTypes.CHAMBERING_ENDLOOPABLE));
  67. m_abilities.Insert(new AbilityRecord(WeaponActions.MECHANISM, WeaponActionTypes.MECHANISM_CLOSED));
  68. m_abilities.Insert(new AbilityRecord(WeaponActions.MECHANISM, WeaponActionTypes.MECHANISM_SPECIAL));
  69. m_abilities.Insert(new AbilityRecord(WeaponActions.UNJAMMING, WeaponActionTypes.UNJAMMING_START));
  70. m_abilities.Insert(new AbilityRecord(WeaponActions.UNJAMMING, WeaponActionTypes.UNJAMMING_END));
  71. m_abilities.Insert(new AbilityRecord(WeaponActions.FIRE, WeaponActionTypes.FIRE_NORMAL));
  72. m_abilities.Insert(new AbilityRecord(WeaponActions.FIRE, WeaponActionTypes.FIRE_COCKED));*/
  73. }
  74. override void InitStateMachine ()
  75. {
  76. m_abilities.Insert(new AbilityRecord(WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_STARTLOOPABLE_CLOSED));
  77. m_abilities.Insert(new AbilityRecord(WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_STARTLOOPABLE_CLOSED_KEEP));
  78. m_abilities.Insert(new AbilityRecord(WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_ENDLOOPABLE));
  79. m_abilities.Insert(new AbilityRecord(WeaponActions.MECHANISM, WeaponActionMechanismTypes.MECHANISM_CLOSED));
  80. m_abilities.Insert(new AbilityRecord(WeaponActions.MECHANISM, WeaponActionMechanismTypes.MECHANISM_SPECIAL));
  81. m_abilities.Insert(new AbilityRecord(WeaponActions.FIRE, WeaponActionFireTypes.FIRE_NORMAL));
  82. m_abilities.Insert(new AbilityRecord(WeaponActions.FIRE, WeaponActionFireTypes.FIRE_COCKED));
  83. m_abilities.Insert(new AbilityRecord(WeaponActions.FIRE, WeaponActionFireTypes.FIRE_UNCOCKED));
  84. // setup state machine
  85. // basic weapon state
  86. C = new Magnum_Static_State(this, NULL, MagnumAnimState.DEFAULT);
  87. WeaponMagnumChambering Chamber = new WeaponMagnumChambering(this, NULL, WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_STARTLOOPABLE_CLOSED_KEEP,WeaponActionChamberingTypes.CHAMBERING_ENDLOOPABLE);
  88. WeaponMagnumChambering Chamber_E = new WeaponMagnumChambering(this, NULL, WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_STARTLOOPABLE_CLOSED,WeaponActionChamberingTypes.CHAMBERING_ENDLOOPABLE);
  89. //WeaponMagnumChambering Chamber_CC00 = new WeaponMagnumChambering(this, NULL, WeaponActions.CHAMBERING, WeaponActionChamberingTypes.CHAMBERING_END);
  90. WeaponCharging Mech = new WeaponCharging(this, NULL, WeaponActions.MECHANISM, WeaponActionMechanismTypes.MECHANISM_CLOSED);
  91. WeaponStateBase Trigger_normal = new WeaponFireMagnum(this, NULL, WeaponActions.FIRE, WeaponActionFireTypes.FIRE_NORMAL);
  92. WeaponStateBase Trigger_dry = new WeaponFireMagnum(this, NULL, WeaponActions.FIRE, WeaponActionFireTypes.FIRE_COCKED);
  93. // events
  94. WeaponEventBase __L__ = new WeaponEventLoad1Bullet;
  95. WeaponEventBase _fin_ = new WeaponEventHumanCommandActionFinished;
  96. WeaponEventBase _abt_ = new WeaponEventHumanCommandActionAborted;
  97. WeaponEventBase __M__ = new WeaponEventMechanism;
  98. WeaponEventBase __T__ = new WeaponEventTrigger;
  99. WeaponEventBase _rto_ = new WeaponEventReloadTimeout;
  100. WeaponEventBase _dto_ = new WeaponEventDryFireTimeout;
  101. m_fsm = new WeaponFSM();
  102. m_fsm.AddTransition(new WeaponTransition( C, __L__, Chamber, null, new WeaponGuardAnyChamberFiredOut(this))); // chamber from closed charged
  103. m_fsm.AddTransition(new WeaponTransition( Chamber, _fin_, C));
  104. m_fsm.AddTransition(new WeaponTransition( Chamber, _abt_, C));
  105. m_fsm.AddTransition(new WeaponTransition( C, __L__, Chamber_E)); // chamber from closed charged
  106. m_fsm.AddTransition(new WeaponTransition( Chamber_E, _fin_, C));
  107. m_fsm.AddTransition(new WeaponTransition( Chamber_E, _abt_, C));
  108. m_fsm.AddTransition(new WeaponTransition( C, __M__, Mech)); // charge from closed
  109. m_fsm.AddTransition(new WeaponTransition( Mech, _fin_, C));
  110. m_fsm.AddTransition(new WeaponTransition( Mech, _abt_, C));
  111. m_fsm.AddTransition(new WeaponTransition( C, __T__, Trigger_normal, null, new GuardAnd (new WeaponGuardCurrentChamberFull(this), new GuardNot(new WeaponGuardCurrentChamberFiredOut(this))) )); // fire.cocked
  112. m_fsm.AddTransition(new WeaponTransition( Trigger_normal, _fin_, C));
  113. m_fsm.AddTransition(new WeaponTransition( Trigger_normal, _dto_, C));
  114. m_fsm.AddTransition(new WeaponTransition( Trigger_normal, _abt_, C));
  115. m_fsm.AddTransition(new WeaponTransition( C, __T__, Trigger_dry)); // fire.cocked
  116. m_fsm.AddTransition(new WeaponTransition( Trigger_dry, _fin_, C));
  117. m_fsm.AddTransition(new WeaponTransition( Trigger_dry, _dto_, C));
  118. m_fsm.AddTransition(new WeaponTransition( Trigger_dry, _abt_, C));
  119. SetInitialState(C);
  120. SelectionBulletHide();
  121. SetCurrentMuzzle(0);
  122. //HideMagazine();
  123. m_fsm.Start();
  124. }
  125. override bool CanChamberBullet(int muzzleIndex, Magazine mag)
  126. {
  127. for (int i = 0; i < GetMuzzleCount(); i++)
  128. {
  129. if ( CanChamberFromMag(i, mag) )
  130. {
  131. if (IsChamberEmpty(i))
  132. return true;
  133. if (IsChamberFiredOut(i))
  134. return true;
  135. }
  136. }
  137. return false;
  138. }
  139. override void AssembleGun()
  140. {
  141. super.AssembleGun();
  142. if ( !FindAttachmentBySlotName(ATT_SLOT_EJECTOR) )
  143. {
  144. GetInventory().CreateAttachment("Magnum_Ejector");
  145. }
  146. if ( !FindAttachmentBySlotName(ATT_SLOT_CYLINDER) )
  147. {
  148. GetInventory().CreateAttachment("Magnum_Cylinder");
  149. }
  150. ForceSyncSelectionState();
  151. SyncCylinderRotation();
  152. }
  153. static float GetCylinderRotation(int muzzleIndex)
  154. {
  155. switch (muzzleIndex)
  156. {
  157. case 0:
  158. return MAGNUM_ROTATION_POSITION_0;
  159. case 1:
  160. return MAGNUM_ROTATION_POSITION_5;
  161. case 2:
  162. return MAGNUM_ROTATION_POSITION_4;
  163. case 3:
  164. return MAGNUM_ROTATION_POSITION_3;
  165. case 4:
  166. return MAGNUM_ROTATION_POSITION_2;
  167. case 5:
  168. return MAGNUM_ROTATION_POSITION_1;
  169. }
  170. ErrorEx(string.Format("Invalid muzzle index: %1", muzzleIndex));
  171. return MAGNUM_ROTATION_POSITION_0;
  172. }
  173. void SetCylinderRotationAnimationPhase(float rot, bool reset = false)
  174. {
  175. Magnum_Cylinder cylinder = Magnum_Cylinder.Cast(GetAttachmentByType(Magnum_Cylinder));
  176. Magnum_Ejector ejector = Magnum_Ejector.Cast(GetAttachmentByType(Magnum_Ejector));
  177. if (cylinder && ejector)
  178. {
  179. float anim_phase = cylinder.GetAnimationPhase("Rotate_Cylinder");
  180. if ( Math.AbsFloat(anim_phase - rot) > 0.1 )
  181. {
  182. if (reset)
  183. {
  184. cylinder.ResetAnimationPhase("Rotate_Cylinder", rot );
  185. ejector.ResetAnimationPhase("Rotate_Ejector", rot );
  186. }
  187. else if (rot == MAGNUM_ROTATION_POSITION_0)
  188. {
  189. cylinder.ResetAnimationPhase("Rotate_Cylinder", MAGNUM_ROTATION_POSITION_M1 );
  190. ejector.ResetAnimationPhase("Rotate_Ejector", MAGNUM_ROTATION_POSITION_M1 );
  191. }
  192. cylinder.SetAnimationPhase("Rotate_Cylinder", rot );
  193. ejector.SetAnimationPhase("Rotate_Ejector", rot );
  194. }
  195. }
  196. }
  197. void SyncCylinderRotation(bool reset = true)
  198. {
  199. SetCylinderRotationAnimationPhase(GetCylinderRotation(GetCurrentMuzzle()), reset);
  200. }
  201. override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
  202. {
  203. super.EEHealthLevelChanged(oldLevel,newLevel,zone);
  204. if (GetGame().IsClient())
  205. return;
  206. SetAttachmentsHealth();
  207. }
  208. //sets health of cylinder and ejector objects
  209. void SetAttachmentsHealth()
  210. {
  211. EntityAI entity;
  212. ItemBase attachment;
  213. for (int i = 0; i < GetInventory().AttachmentCount(); i++)
  214. {
  215. entity = GetInventory().GetAttachmentFromIndex(i);
  216. if ( Class.CastTo(attachment,entity) )
  217. {
  218. attachment.SetHealth01("","Health",GetHealth01());
  219. }
  220. }
  221. }
  222. override void OnFire(int muzzle_index)
  223. {
  224. super.OnFire(muzzle_index);
  225. Magnum_Cylinder cylinder = Magnum_Cylinder.Cast(GetAttachmentByType(Magnum_Cylinder));
  226. if (cylinder)
  227. {
  228. string bullet_nose = "bullet_nose";
  229. if (muzzle_index > 0)
  230. bullet_nose = string.Format("bullet_nose_" + (muzzle_index + 1));
  231. cylinder.HideSelection(bullet_nose);
  232. }
  233. }
  234. override bool IsShowingChamberedBullet()
  235. {
  236. return false;
  237. }
  238. override bool CanEjectBullet()
  239. {
  240. for (int i = 0; i < GetMuzzleCount(); i++)
  241. {
  242. if (IsChamberFull(i))
  243. return true;
  244. }
  245. return false;
  246. }
  247. override void ShowBullet(int muzzleIndex)
  248. {
  249. super.ShowBullet(muzzleIndex);
  250. Magnum_Cylinder cylinder = Magnum_Cylinder.Cast(GetAttachmentByType(Magnum_Cylinder));
  251. if (cylinder)
  252. {
  253. string bullet = "bullet";
  254. if (muzzleIndex > 0)
  255. bullet = string.Format("bullet_" + (muzzleIndex + 1));
  256. cylinder.ShowSelection(bullet);
  257. if (!IsChamberFiredOut(muzzleIndex))
  258. {
  259. string bullet_nose = "bullet_nose";
  260. if (muzzleIndex > 0)
  261. bullet_nose = string.Format("bullet_nose_" + (muzzleIndex + 1));
  262. cylinder.ShowSelection(bullet_nose);
  263. }
  264. }
  265. }
  266. override void HideBullet(int muzzleIndex)
  267. {
  268. super.HideBullet(muzzleIndex);
  269. Magnum_Cylinder cylinder = Magnum_Cylinder.Cast(GetAttachmentByType(Magnum_Cylinder));
  270. if (cylinder)
  271. {
  272. string bullet = "bullet";
  273. if (muzzleIndex > 0)
  274. bullet = string.Format("bullet_" + (muzzleIndex + 1));
  275. cylinder.HideSelection(bullet);
  276. string bullet_nose = "bullet_nose";
  277. if (muzzleIndex > 0)
  278. bullet_nose = string.Format("bullet_nose_" + (muzzleIndex + 1));
  279. cylinder.HideSelection(bullet_nose);
  280. }
  281. }
  282. //Debug menu Spawn Ground Special
  283. override void OnDebugSpawn()
  284. {
  285. super.OnDebugSpawn();
  286. EntityAI entity;
  287. if ( Class.CastTo(entity, this) )
  288. {
  289. entity.SpawnEntityOnGroundPos("Ammo_357", entity.GetPosition());
  290. }
  291. }
  292. };
  293. class Magnum extends Magnum_Base
  294. {
  295. override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
  296. {
  297. super.GetDebugActions(outputList);
  298. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "", FadeColors.LIGHT_GREY));
  299. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SPIN, "Spin", FadeColors.LIGHT_GREY));
  300. }
  301. override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
  302. {
  303. if (GetGame().IsServer())
  304. {
  305. if (action_id == EActions.SPIN)
  306. {
  307. const float animPhaseOffset = 0.167;
  308. Magnum_Cylinder cylinder = Magnum_Cylinder.Cast(GetAttachmentByType(Magnum_Cylinder));
  309. Magnum_Ejector ejector = Magnum_Ejector.Cast(GetAttachmentByType(Magnum_Ejector));
  310. if (cylinder)
  311. {
  312. float animPhase = cylinder.GetAnimationPhase("Rotate_Cylinder");
  313. if (animPhase + animPhaseOffset > 1.0)
  314. {
  315. animPhase -= 1.0;
  316. cylinder.ResetAnimationPhase("Rotate_Cylinder", animPhase);
  317. ejector.ResetAnimationPhase("Rotate_Ejector", animPhase);
  318. }
  319. cylinder.SetAnimationPhase("Rotate_Cylinder", animPhase);
  320. ejector.ResetAnimationPhase("Rotate_Ejector", animPhase);
  321. }
  322. }
  323. }
  324. return super.OnAction(action_id, player, ctx);
  325. }
  326. }
  327. class SawedoffMagnum extends Magnum_Base {};
  328. class Magnum_Cylinder extends DummyItem {};
  329. class Magnum_Ejector extends DummyItem {};