magnum.c 13 KB

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