123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class CondomDispenser : Collidable
- {
- #region Unity Singleton
- private static CondomDispenser _instance;
- public static CondomDispenser Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = FindObjectOfType(typeof(CondomDispenser)) as CondomDispenser;
- if (_instance == null)
- {
- Debug.LogError("No gameObject with CondomDispenser component exists. Make sure to create a gameObject with CondomDispenser component");
- }
- }
- return _instance;
- }
- }
- protected override void Awake()
- {
- base.Awake();
- if (_instance != null && _instance != this)
- {
- Debug.LogWarning("CondomDispenser instance already exists on another gameObject. Destroying this gameObject CondomDispenser");
- Destroy(gameObject);
- return;
- }
- _instance = this;
- DontDestroyOnLoad(gameObject);
- Init();
- }
- #endregion
- private static Transform _transform;
- public static Transform GetTransform() { return _transform; }
- public const int INFINITE_AMMO = -1;
- public float moveSpeed = 1f;
- public float recoilOffset = 20;
- public float recoilTimeOut = 0.04f;
- public float recoilTimeIn = 0.2f;
- public int maxQueuedTaps = 3;
- public Weapon defaultWeapon;
- public Weapon[] otherWeapons;
- /// <summary>
- /// Using List instead of Queue, due to capping the queue, and the last tap is replaced by the latest tap
- /// </summary>
- private List<Vector2> _queuedTaps = new List<Vector2>();
- private Vector3 _originalPosition;
- private Weapon _currentWeapon;
- private Dictionary<PickupType, Weapon> _weaponsDictionary;
- [HideInInspector]
- public List<CondomBase>condoms = new List<CondomBase>();
- public int ammoLeft = INFINITE_AMMO;
- #region FSM decleration
- private enum DispenserState
- {
- NullState,
- Idle,
- Moving,
- Shooting,
- CheckingQueue
- }
- private enum DispenserTransition
- {
- NullTransition,
- Move,
- Shoot,
- CheckQueue,
- NoQueuedTaps,
- HasQueuedTaps
- }
- private FSMSystem<DispenserTransition, DispenserState> fsm;
- #endregion
- #region Unity Callbacks
- protected void Init()
- {
- _transform = transform;
- _originalPosition = transform.localPosition;
- _weaponsDictionary = new Dictionary<PickupType, Weapon>();
- _weaponsDictionary[defaultWeapon.type] = defaultWeapon;
- foreach (Weapon w in otherWeapons)
- {
- _weaponsDictionary[w.type] = w;
- }
- MakeFSM();
- }
- void OnEnable()
- {
- iTween.Stop(gameObject); //stop any itweens from the previous game, just in case
- NotificationCenter.AddListener(OnFire, NotificationType.Fire);
- NotificationCenter.AddListener(Reset, NotificationType.GameStart);
- NotificationCenter.AddListener(OnPickedUpWeaponUpgrade, NotificationType.PickedUpWeaponUpgrade);
- NotificationCenter.AddListener(OnFireIndependently, NotificationType.FireIndependently);
- NotificationCenter.AddListener(OnSpawnCondom, NotificationType.SpawnCondom);
- }
- void OnDisable()
- {
- NotificationCenter.RemoveListener(OnFire, NotificationType.Fire);
- NotificationCenter.RemoveListener(Reset, NotificationType.GameStart);
- NotificationCenter.RemoveListener(OnPickedUpWeaponUpgrade, NotificationType.PickedUpWeaponUpgrade);
- NotificationCenter.RemoveListener(OnFireIndependently, NotificationType.FireIndependently);
- NotificationCenter.RemoveListener(OnSpawnCondom, NotificationType.SpawnCondom);
- condoms.Clear();
- }
- public void CustomFixedUpdate()
- {
- //AVDebug.Log("CD "+transform.localPosition.x+","+transform.localPosition.y+" at tick "+RecordingManager.Ticks);
- fsm.Update();
- if (_currentWeapon != null)
- {
- if (_currentWeapon.isAutomatic)
- {
- //move with the mouse (or current touch position)
- Vector2 pos = UICamera.mainCamera.ScreenToWorldPoint(Input.mousePosition);
- Vector3 newPos = transform.position;
- newPos.y = pos.y;
- transform.position = newPos;
- }
- _currentWeapon.UpdateWeapon();
- if (_currentWeapon.IsEmpty)
- {
- ResetWeaponToDefault();
- }
- }
-
-
- }
- public void UpdateCondoms()
- {
- for (int i = condoms.Count - 1; i >= 0; i--)
- {
- CondomBase c = condoms[i];
- if (c.gameObject.activeInHierarchy)
- {
- c.BroadcastMessage("CustomFixedUpdate");
- } else
- {
- condoms.RemoveAt(i);
- }
- }
- }
- #endregion
- #region Notification callbacks
- void Reset(Notification note)
- {
- #if LEVEL_EDITOR
- ammoLeft = -1; //TODO should be read from some level editor field
- #else
- ammoLeft = LevelsManager.Instance.CurrentLevel.Ammo;
- #endif
- NotificationCenter.Post(NotificationType.UpdateAmmoLeft, ammoLeft);
- transform.localPosition = _originalPosition;
- _queuedTaps.Clear();
- ResetWeaponToDefault();
- MakeFSM();
- }
- void OnFire(Notification note)
- {
- if (HasAmmo())
- {
- if (maxQueuedTaps > 0 && // 0 means infinite
- _queuedTaps.Count >= maxQueuedTaps)
- {
- //remove the last tap
- _queuedTaps.RemoveAt(_queuedTaps.Count-1);
- }
- Vector2 tapPos = (Vector2)note.data;
- _queuedTaps.Add(tapPos);
- if (fsm.CurrentStateID == DispenserState.Idle)
- {
- fsm.PerformTransition(DispenserTransition.Move);
- }
- DecrementAmmo();
- }
- else
- {
- SoundManager.Play(SoundEvent.emptyDispenser);
- #if LEVEL_EDITOR
- Debug.LogWarning("No more ammo!");
- Debug.Break();
- #endif
- }
- }
- void OnPickedUpWeaponUpgrade(Notification note)
- {
- SetWeapon((PickupType)note.data);
- }
- /// <summary>
- /// This is mainly used when a homing missile is fired automatically
- /// When a virus is spawned
- /// </summary>
- void OnFireIndependently(Notification note)
- {
- PoolObject condom = (PoolObject)note.data;
- condoms.Add(condom.GetComponent<CondomBase>());
- Transform condomTransform = condom.transform;
- Vector3 originalScale = condomTransform.localScale;
- condomTransform.parent = transform.parent;
- condomTransform.localScale = originalScale;
- condomTransform.localPosition = transform.localPosition;
- if (_currentWeapon.IsEmpty)
- {
- ResetWeaponToDefault();
- }
- }
- #endregion
- #region iTween Callbacks
- void OniTweenMoveFinished()
- {
- //AVDebug.Log("CD move finished at tick "+RecordingManager.Ticks);
- fsm.PerformTransition(DispenserTransition.Shoot);
- }
- void OniTweenRecoilPushbackFinished()
- {
- //AVDebug.Log("CD recoil pushback finished at tick "+RecordingManager.Ticks);
- iTween.MoveTo(gameObject, iTween.Hash(
- "usefixedupdate", true,
- "islocal", true,
- "x", _originalPosition.x,
- "time", recoilTimeIn,
- "oncomplete", "OniTweenRecoilFinished",
- "oncompletetarget", gameObject));
- }
- void OniTweenRecoilFinished()
- {
- //AVDebug.Log("CD recoil finished at tick "+RecordingManager.Ticks);
- fsm.PerformTransition(DispenserTransition.CheckQueue);
- }
- #endregion
- #region FSM
- /// <summary>
- /// (start)->(Idle)
- /// (Idle)-Move>(Moving)
- /// (Moving)-Shoot>(Shooting)
- /// (Shooting)-CheckQueue>(CheckingQueue)
- /// (CheckingQueue)-HasQueuedTaps>(Moving)
- /// (CheckingQueue)-NoQueuedTaps>(Idle)
- /// http://yuml.me/edit/f6369289
- /// </summary>
- void MakeFSM()
- {
- var idleState = new FSMState<DispenserTransition, DispenserState>(DispenserState.Idle);
- idleState.AddTransition(DispenserTransition.Move, DispenserState.Moving);
- var movingState = new FSMState<DispenserTransition, DispenserState>(DispenserState.Moving);
- movingState.AddTransition(DispenserTransition.Shoot, DispenserState.Shooting);
- movingState.DoBeforeEntering = DoBeforeEnteringMoving;
- var shootingState = new FSMState<DispenserTransition, DispenserState>(DispenserState.Shooting);
- shootingState.AddTransition(DispenserTransition.CheckQueue, DispenserState.CheckingQueue);
- shootingState.DoBeforeEntering = DoBeforeEnteringShooting;
- var checkingQueueState = new FSMState<DispenserTransition, DispenserState>(DispenserState.CheckingQueue);
- checkingQueueState.AddTransition(DispenserTransition.HasQueuedTaps, DispenserState.Moving);
- checkingQueueState.AddTransition(DispenserTransition.NoQueuedTaps, DispenserState.Idle);
- checkingQueueState.DoBeforeEntering = DoBeforeEnteringCheckingQueue;
- fsm = new FSMSystem<DispenserTransition, DispenserState>("CondomDispenser FSM");
- //fsm.isDebug = true;
- fsm.AddState(idleState);
- fsm.AddState(movingState);
- fsm.AddState(shootingState);
- fsm.AddState(checkingQueueState);
- }
- void DoBeforeEnteringMoving()
- {
- //dequeue
- Vector2 pos = _queuedTaps[0];
- pos = UICamera.mainCamera.ScreenToWorldPoint(pos);
- _queuedTaps.RemoveAt(0);
- if (_currentWeapon.isAutomatic)
- {
- //don't waste time with animations when the weapon fires automatically
- Vector3 newPos = transform.position;
- newPos.y = pos.y;
- transform.position = newPos;
- fsm.PerformTransition(DispenserTransition.Shoot);
- } else
- {
- //AVDebug.Log("CD start moving at tick "+RecordingManager.Ticks);
- iTween.MoveTo(gameObject, iTween.Hash(
- "usefixedupdate", true,
- "y", pos.y,
- "speed", moveSpeed,
- "oncomplete", "OniTweenMoveFinished",
- "oncompletetarget", gameObject));
- }
- }
- void DoBeforeEnteringShooting()
- {
- if (RecordingManager.Instance.IsRecording)
- {
- NotificationCenter.Post(NotificationType.SpawnCondom, new Vector2(transform.localPosition.x, transform.localPosition.y));
- }
- //make recoil animation
- iTween.MoveTo(gameObject, iTween.Hash(
- "usefixedupdate", true,
- "islocal", true,
- "x", transform.localPosition.x + recoilOffset,
- "time", recoilTimeOut,
- "oncomplete", "OniTweenRecoilPushbackFinished",
- "oncompletetarget", gameObject));
- if (_currentWeapon.IsEmpty)
- {
- ResetWeaponToDefault();
- }
- }
- void DoBeforeEnteringCheckingQueue()
- {
- if (_queuedTaps.Count > 0)
- {
- fsm.PerformTransition(DispenserTransition.HasQueuedTaps);
- } else
- {
- fsm.PerformTransition(DispenserTransition.NoQueuedTaps);
- }
- }
- #endregion
- void ResetWeaponToDefault()
- {
- SetWeapon(PickupType.DefaultWeapon);
- NotificationCenter.Post(NotificationType.WeaponReset);
- }
- void SetWeapon(PickupType pickupType)
- {
- if (_currentWeapon != null)
- {
- _currentWeapon.Disarm();
- }
- _currentWeapon = _weaponsDictionary[pickupType];
- _currentWeapon.Arm();
- }
- void OnSpawnCondom(Notification note)
- {
- //if playing back this is crucial due to iTween not being particularly replayable for some strange reason
- iTween.Stop(gameObject);
- Vector3 newPos = (Vector2)note.data;
- newPos.z = _originalPosition.z;
- transform.localPosition = newPos;
- //create condom
- PoolObject condom = _currentWeapon.Fire();
- condoms.Add(condom.GetComponent<CondomBase>());
- Transform condomTransform = condom.transform;
- Vector3 originalScale = condomTransform.localScale;
- condomTransform.parent = transform.parent;
- condomTransform.localScale = originalScale;
- condomTransform.localPosition = transform.localPosition;
- }
- bool HasAmmo()
- {
- return (ammoLeft == INFINITE_AMMO || ammoLeft > 0);
- }
- void DecrementAmmo()
- {
- if (ammoLeft > 0 &&
- _currentWeapon.type == PickupType.DefaultWeapon)
- {
- --ammoLeft;
- NotificationCenter.Post(NotificationType.UpdateAmmoLeft, ammoLeft);
- }
- }
- }
|