private void Fire(bool source)
    {
        if(backpack_controller.HasAmmo(ammo_per_shot)) {
            //start code for stat tracking
            if (player == null) {
                player = GameObject.FindGameObjectWithTag("Player");
            }
            if (player != null && stats == null) {
                stats = player.GetComponent<StatisticsRecorderController>();
            }
            if (stats != null) {
                if(source) {
                    stats.fireWeapon(backpack_controller.GetWeaponName());
                    stats.fireShot();
                }
            }
            //end code for stat tracking
            if (shot_sound != null && (player.transform.position - this.transform.position).magnitude < 10)
            {
                shot_sound.Play();
            }
            //var instantiated_bullet = (GameObject) Instantiate(bullet, muzzle.position, muzzle.rotation * bullet_rotation);
            /*
            if (gameObject.name.Contains("Pistol"))
            {
                instantiated_bullet = pool.getPistolBullet();
            }
            else if (gameObject.name.Contains("Crazy Gun"))
            {
                instantiated_bullet = pool.getCrazyGunBullet();
            }
            else if (gameObject.name.Contains("Machine Gun"))
            {
                instantiated_bullet = pool.getMachineGunBullet();
            }
            else if (gameObject.name.Contains("Ray"))
            {
                instantiated_bullet = pool.getRayGunBullet();
            }
            else
            {
                return;
            }
             * */
            //instantiated_bullet = getBullet();

            SpawnBullet(source);
            backpack_controller.ChangeAmmo(-ammo_per_shot);

        }
    }
    // Update
    void LateUpdate()
    {
        if (Time.timeScale == 0) return;

        if (!gameObject.activeInHierarchy) return;

        //Die if at zero hp
        if (health_controller.GetCurrentHealth() <= 0)
        {
            //start stat tracking code
            if (player == null) {
                player = GameObject.FindGameObjectWithTag("Player");
            }
            if (player != null && stats == null) {
                stats = player.GetComponent<StatisticsRecorderController>();
            }
            if (stats != null) {
                stats.killEnemy();
            }
            //end stat tracking code
            //for hit canvas
            player.GetComponent<HitCanvasController>().scoreKill();
            //end hit canvas
            var explosion_i = pool.getExplosion();
            explosion_i.transform.position = gameObject.transform.position;
            explosion_i.transform.rotation = gameObject.transform.rotation;
            explosion_i.SetActive(true);
            //var treasure_instantiation = (GameObject)Instantiate(treasure_chest, gameObject.transform.position, gameObject.transform.rotation);
            var treasure_i = pool.getTreasure();
            treasure_i.transform.position = gameObject.transform.position;
            treasure_i.transform.rotation = gameObject.transform.rotation;
            treasure_i.SetActive(true);
            gameObject.SetActive(false);
            combo_controller.IncrementCombo();
            // add experience to player
            CreateExp();
            StageBuilder.EnemyDied();

        }

        //Movement
        //call primary movement logic to get movement direction
        Vector3 mvt = ((LMMove)GetComponent("LMMove")).MoveLogic(this, player);

        // If primary movement is zero, and not aggroed, run auxiliary movement pattern
        if (mvt.magnitude == 0 && !AggroState)
        {
            var aux = (LMAuxMove)GetComponent("LMAuxMove");
            if (aux != null)
            {
                mvt = aux.AuxMoveLogic(this, player);
            }
        }

        //apply the movement
        PrevTime = Time.deltaTime;
        GetComponent<Rigidbody>().AddForce(mvt*speed);

        PrevMvt = transform.position - PrevPos;     //save the net amount of movement done
        PrevPos = transform.position;

        //Face in the direction of movement
        if (RBody.velocity.magnitude >= 0.1)
            transform.forward = RBody.velocity;

        //Do not exceed maximum speed
        if (RBody.velocity.magnitude > SpeedLimit)
        {
            RBody.velocity = RBody.velocity.normalized * SpeedLimit;
        }

        //decrement wall hit timer
        WallHitTimer -= PrevTime;
        if (WallHitTimer < 0)
        {
            WallHitTimer = 0;
            WallHit = false;
        }

        //Perform attack & face according to attack logic
        if (AggroState) {

            Vector3 face = ((LMAttack)GetComponent("LMAttack")).AttackLogic(this, player);

            if (face.magnitude != 0)
                transform.forward = face;

            if (!Stationary && gun != null)
            {
                gun.LookAt(player.transform);
            }
        }

        //Apply animations
        if(RBody.velocity.magnitude > 0) {
            if (anim != null)
                anim.SetBool("Moving", true);
        } else {
            if (anim != null)
                anim.SetBool("Moving", false);
        }
    }
    void FixedUpdate()
    {
        //logic from http://wiki.unity3d.com/index.php?title=DontGoThroughThings

        //have we moved more than our minimum extent?
        Vector3 movementThisStep = myRigidbody.position - previousPosition;
        float movementSqrMagnitude = movementThisStep.sqrMagnitude;

        if (movementSqrMagnitude > sqrMinimumExtent)
        {
            float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
            RaycastHit hitInfo;

           //check for obstructions we might have missed
            if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude))
            {
                //Ignore if it is a trigger
                if (hitInfo.collider.isTrigger)
                    return;

                myRigidbody.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;

                GameObject other = hitInfo.collider.gameObject;

               //Player-fired bullets do not hit the player
                if (source_player && other.tag == "Player")
                    return;

               //Enemy-fired bullets do not hit enemies
               //if (!source_player && other.tag != "Player")
                if (!source_player && other.tag == "Enemy")
                    return;

                var victim_health = other.GetComponent<HealthController>();
               if (victim_health != null)
               {
                   if (other.tag == "Player") {
                       victim_health.ChangeHealth(PC.GetDefense() * -damage);
                   } else {
                       victim_health.ChangeHealth(-damage);
                   }

                   //start code for stat tracking
                   if (player == null)
                   {
                       player = GameObject.FindGameObjectWithTag("Player");
                   }
                   if (player != null && stats == null)
                   {
                       stats = player.GetComponent<StatisticsRecorderController>();
                   }
                   if (stats != null)
                   {
                       if (source_player)
                       {
                           stats.dealDamage(damage);
                           stats.hitShot();
                           //for hit canvas
                           player.GetComponent<HitCanvasController>().scoreHit();
                           //end hit canvas
                       }
                       else
                       {
                           stats.takeDamage(damage);
                       }
                   }
                   //end code for stat tracking

                   if (is_laser) {
                        return;
                   }

               }
               //if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude, layerMask.value))
               //{
               //    myRigidbody.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;
               //Debug.Log("other tag: " + other.tag);
               //Debug.Log("other name: " + other.name);

               if (other.tag == "Player" || other.tag == "Enemy" || other.name.Contains("Wall"))
               {
                   /*
                   gameObject.GetComponent<Rigidbody>().Sleep();
                   gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
                   gameObject.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
                   gameObject.SetActive(false);
                    * */
                   Destroy(gameObject);
               }

               //}
                   //myRigidbody.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;
               //Destroy(gameObject);
               //gameObject.SetActive(false);
               //gameObject.GetComponent<Rigidbody>().Sleep();
               //gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
               //gameObject.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
               //gameObject.SetActive(false);
           }
           }
           previousPosition = myRigidbody.position;
    }
    void OnCollisionEnter(Collision collision)
    {
        //Player-fired bullets do not hit the player
        if (source_player && collision.gameObject.tag == "Player")
            return;

        //Enemy-fired bullets do not hit enemies
        if (!source_player && collision.gameObject.tag != "Player")
            return;

        var victim_health = collision.gameObject.GetComponent<HealthController>();
        if(victim_health != null) {
            //this means you're hitting an enemy, not a wall ... if it's a laser then keep going
            if (gameObject.tag == "Player") {
                victim_health.ChangeHealth(PC.GetDefense() * -damage, transform.position);
            } else {
                victim_health.ChangeHealth(-damage, transform.position);
            }
            //don't let it get destroyed if it collides with an enemy and is a laser, only a wall

            //start code for stat tracking
            if (player == null) {
                player = GameObject.FindGameObjectWithTag("Player");
            }
            if (player != null && stats == null) {
                stats = player.GetComponent<StatisticsRecorderController>();
            }
            if (stats != null) {
                if (source_player) {
                    stats.dealDamage(damage);
                    stats.hitShot();
                    //for hit canvas
                    player.GetComponent<HitCanvasController>().scoreHit();
                    //end hit canvas
                } else {
                    stats.takeDamage(damage);
                }
            }
            //end code for stat tracking

            /*
            if (is_laser) {
                return;
            }*/ //laser not stopping leads to very screwy behavior given visible bolt
        }
        Destroy(gameObject);

        /*gameObject.GetComponent<Rigidbody>().Sleep();
        gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
        gameObject.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
        gameObject.SetActive(false);
         * */
    }
    public void NextLevel(int level)
    {
		//start code for stat tracking
		if (player == null) {
			player = GameObject.FindGameObjectWithTag("Player");
		}
		if (player != null && stats == null) {
			stats = player.GetComponent<StatisticsRecorderController>();
		}
		if (stats != null) {
			stats.resetStats();
		}
		//end code for stat tracking

        //CameraShake();
        PlayerController pc = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
        this.currentLevel = level;
        if (level >= levels.Count) //level is exactly one deeper than previous depth
        {
            DestroyCurrentLevel();
            CreateNewLevel(); //equivalent to the constructor method when stage is first made
            pc.incrementDeepestLevelVisited();
            MovePlayerToEntrance();

        }
        else //level has already been made. Must be loaded
        {
            DestroyCurrentLevel();
            LoadLevel(level);
            
        }

        pc.setCurrentFloor(level);
        //Create the dungeon
        Create();
        //Move player to the entrance
        WaitTwoSecs();


        
        GameObject.FindGameObjectWithTag("ElevatorCanvas").GetComponent<ElevatorController>().FadeIn();

    }
 private void Start()
 {
     current_combo = 0;
     last_combo_time = -combo_delay;
     stats = GameObject.FindGameObjectWithTag("Player").GetComponent<StatisticsRecorderController>();
 }