public PatrolGuard(LevelState parentWorld, Vector2 position)
        {
            this.parentWorld = parentWorld;
            this.position    = position;
            this.dimensions  = GlobalGameConstants.TileSize;

            bulletAnim = AnimationLib.getFrameAnimationSet("testBullet");

            deadCushySoundTimer = 0;

            bullets = new GunBullet[bulletSupply];
            for (int i = 0; i < bulletSupply; i++)
            {
                bullets[i].active = false;
            }

            direction_facing = GlobalGameConstants.Direction.Down;
            guardState       = PatrolGuardState.MoveWait;
            enemy_type       = EnemyType.Guard;

            prob_item_drop    = 0.3;
            number_drop_items = 3;

            directionAnims = new AnimationLib.SpineAnimationSet[4];
            directionAnims[(int)GlobalGameConstants.Direction.Up]   = AnimationLib.loadNewAnimationSet("patrolUp");
            directionAnims[(int)GlobalGameConstants.Direction.Down] = AnimationLib.loadNewAnimationSet("patrolDown");
            directionAnims[(int)GlobalGameConstants.Direction.Left] = AnimationLib.loadNewAnimationSet("patrolRight");
            directionAnims[(int)GlobalGameConstants.Direction.Left].Skeleton.FlipX = true;
            directionAnims[(int)GlobalGameConstants.Direction.Right] = AnimationLib.loadNewAnimationSet("patrolRight");
            for (int i = 0; i < 4; i++)
            {
                directionAnims[i].Animation = directionAnims[i].Skeleton.Data.FindAnimation("run");
            }

            health = 15;

            //calculate the center of the chunk you're placed in
            chunkCenter.X = (((int)((position.X / (GlobalGameConstants.TileSize.X)) / GlobalGameConstants.TilesPerRoomWide)) * GlobalGameConstants.TilesPerRoomWide * GlobalGameConstants.TileSize.X) + ((GlobalGameConstants.TilesPerRoomWide / 2) * GlobalGameConstants.TileSize.X);
            chunkCenter.Y = (((int)((position.Y / (GlobalGameConstants.TileSize.Y)) / GlobalGameConstants.TilesPerRoomHigh)) * GlobalGameConstants.TilesPerRoomHigh * GlobalGameConstants.TileSize.Y) + ((GlobalGameConstants.TilesPerRoomHigh / 2) * GlobalGameConstants.TileSize.Y);

            retreatTimer = 0;
        }
        public override void knockBack(Vector2 direction, float magnitude, int damage, Entity attacker)
        {
            if (guardState == PatrolGuardState.KnockBack)
            {
                return;
            }

            health -= damage;

            if (health <= 0 && guardState != PatrolGuardState.Dying)
            {
                if (attacker is Player)
                {
                    GameCampaign.AlterAllegiance(-0.01f);
                }

                guardState     = PatrolGuardState.Dying;
                animation_time = 0;

                velocity = Vector2.Zero;

                dimensions /= 8;

                parentWorld.pushCoin(this);

                death = true;

                return;
            }
            else if (guardState == PatrolGuardState.Dying)
            {
                parentWorld.Particles.pushBloodParticle(CenterPoint);
                parentWorld.Particles.pushBloodParticle(CenterPoint);
                parentWorld.Particles.pushBloodParticle(CenterPoint);

                if (deadCushySoundTimer > 500f)
                {
                    AudioLib.playSoundEffect("fleshyKnockBack");

                    deadCushySoundTimer = 0;
                }

                return;
            }

            direction.Normalize();
            velocity = direction * (magnitude / 2);

            knockBackTime = 0.0f;

            guardState     = PatrolGuardState.KnockBack;
            animation_time = 0;

            parentWorld.Particles.pushBloodParticle(CenterPoint);
            parentWorld.Particles.pushBloodParticle(CenterPoint);
            parentWorld.Particles.pushBloodParticle(CenterPoint);

            AudioLib.playSoundEffect("fleshyKnockBack");

            //where you look in the entity's direction and start chasing them
            if (attacker != null && (attacker.Enemy_Type != EnemyType.NoType && attacker.Enemy_Type != enemy_type))
            {
                target = attacker;
            }
        }
        public override void update(GameTime currentTime)
        {
            animation_time      += currentTime.ElapsedGameTime.Milliseconds;
            deadCushySoundTimer += currentTime.ElapsedGameTime.Milliseconds;


            if (guardState == PatrolGuardState.InvalidState)
            {
                throw new Exception("Patrol Guard went into invalid state");
            }
            else if (guardState == PatrolGuardState.MoveWait)
            {
                moveWaitTimer += currentTime.ElapsedGameTime.Milliseconds;

                if (moveWaitStepping)
                {
                    switch (direction_facing)
                    {
                    case GlobalGameConstants.Direction.Up:
                        velocity = new Vector2(0.0f, -patrolMoveSpeed);
                        break;

                    case GlobalGameConstants.Direction.Down:
                        velocity = new Vector2(0.0f, patrolMoveSpeed);
                        break;

                    case GlobalGameConstants.Direction.Left:
                        velocity = new Vector2(-patrolMoveSpeed, 0.0f);
                        break;

                    case GlobalGameConstants.Direction.Right:
                        velocity = new Vector2(patrolMoveSpeed, 0.0f);
                        break;
                    }

                    directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("run");
                }
                else
                {
                    velocity = Vector2.Zero;

                    directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("idle");
                }

                if (moveWaitTimer > (moveWaitStepping ? moveStepTime : moveStepWaitTime))
                {
                    moveWaitStepping = !moveWaitStepping;
                    moveWaitTimer    = 0.0f;

                    if (moveWaitStepping)
                    {
                        direction_facing = (GlobalGameConstants.Direction)(((int)direction_facing + ((Game1.rand.Next() % 3) - 1) + 4) % 4);
                    }
                }

                if (target == null)
                {
                    sightBox        = new GunBullet();
                    sightBox.hitbox = new Vector2(100, 100);
                    switch (direction_facing)
                    {
                    case GlobalGameConstants.Direction.Down:
                        sightBox.position.X = CenterPoint.X - 50;
                        sightBox.position.Y = position.Y + dimensions.Y;
                        sightBox.hitbox.Y   = 150;
                        break;

                    case GlobalGameConstants.Direction.Up:
                        sightBox.position.X = CenterPoint.X - 50;
                        sightBox.position.Y = position.Y - 120;
                        sightBox.hitbox.Y   = 150;
                        break;

                    case GlobalGameConstants.Direction.Right:
                        sightBox.position.X = position.X + dimensions.X;
                        sightBox.position.Y = CenterPoint.Y - 50;
                        sightBox.hitbox.X   = 120;
                        break;

                    case GlobalGameConstants.Direction.Left:
                        sightBox.position.X = position.X - 120;
                        sightBox.position.Y = CenterPoint.Y - 50;
                        sightBox.hitbox.X   = 120;
                        break;
                    }

                    for (int it = 0; it < parentWorld.EntityList.Count; it++)
                    {
                        if (parentWorld.EntityList[it].Enemy_Type == Entity.EnemyType.Guard || parentWorld.EntityList[it] is Coin || parentWorld.EntityList[it] is Pickup || parentWorld.EntityList[it] is BetaEndLevelFag)
                        {
                            continue;
                        }

                        if (Vector2.Distance(parentWorld.EntityList[it].CenterPoint, chunkCenter) > 1000)
                        {
                            continue;
                        }

                        if (Vector2.Distance(parentWorld.EntityList[it].CenterPoint, CenterPoint) > GlobalGameConstants.TileSize.X * 10)
                        {
                            continue;
                        }

                        if (!sightBox.hitTestBullet(parentWorld.EntityList[it]))
                        {
                            continue;
                        }

                        if (parentWorld.EntityList[it].Enemy_Type != enemy_type || parentWorld.EntityList[it].Enemy_Type != EnemyType.NoType)
                        {
                            if (GameCampaign.PlayerAllegiance > 0.7f && parentWorld.EntityList[it] is Player)
                            {
                                continue;
                            }
                            else
                            {
                                target = parentWorld.EntityList[it];
                            }
                        }

                        else if (parentWorld.EntityList[it] is ShopKeeper)
                        {
                            target = parentWorld.EntityList[it];
                        }
                    }

                    if (target != null)
                    {
                        chaseWaitTime = 0f;
                        guardState    = PatrolGuardState.Chase;
                    }
                }
                else
                {
                    target = null;
                }

                if (Vector2.Distance(CenterPoint, chunkCenter) > 1000)
                {
                    guardState = PatrolGuardState.RetreatToCenter;
                }
            }
            else if (guardState == PatrolGuardState.RetreatToCenter)
            {
                retreatTimer += currentTime.ElapsedGameTime.Milliseconds;

                if (Vector2.Distance(CenterPoint, chunkCenter) < 350 || retreatTimer > retreatMaxTime)
                {
                    guardState   = PatrolGuardState.MoveWait;
                    retreatTimer = 0;
                    return;
                }

                double theta = Math.Atan2(CenterPoint.Y - chunkCenter.Y, CenterPoint.X - chunkCenter.X);

                if (theta < Math.PI / 4 || theta > (Math.PI * 2) - (Math.PI / 4))
                {
                    direction_facing = GlobalGameConstants.Direction.Down;
                }
                else if (theta > Math.PI / 4 && theta < Math.PI - (Math.PI / 4))
                {
                    direction_facing = GlobalGameConstants.Direction.Left;
                }
                else if (theta > Math.PI - (Math.PI / 4) / 4 && theta < Math.PI + (Math.PI / 4))
                {
                    direction_facing = GlobalGameConstants.Direction.Right;
                }
                else if (theta > Math.PI + (Math.PI / 4) / 4 && theta < (Math.PI * 2) - (Math.PI / 4))
                {
                    direction_facing = GlobalGameConstants.Direction.Up;
                }

                velocity = -patrolMoveSpeed * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));

                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("run");
            }
            else if (guardState == PatrolGuardState.Chase)
            {
                //this employs short-circut evaluation for safe code, which I'm not sure if is a good idea
                if (target == null || target.Remove_From_List == true || target.Death == true)
                {
                    guardState = PatrolGuardState.MoveWait;

                    target = null;

                    return;
                }

                if (Vector2.Distance(target.CenterPoint, chunkCenter) > 1000)
                {
                    guardState = PatrolGuardState.RetreatToCenter;
                    target     = null;
                    return;
                }

                double theta = Math.Atan2(target.CenterPoint.Y - CenterPoint.Y, target.CenterPoint.X - CenterPoint.X);

                if (Math.Abs(Math.Sin(theta)) > Math.Abs(Math.Cos(theta)))
                {
                    if (Math.Sin(theta) < 0)
                    {
                        direction_facing = GlobalGameConstants.Direction.Up;
                    }
                    else
                    {
                        direction_facing = GlobalGameConstants.Direction.Down;
                    }
                }
                else
                {
                    if (Math.Cos(theta) < 0)
                    {
                        direction_facing = GlobalGameConstants.Direction.Left;
                    }
                    else
                    {
                        direction_facing = GlobalGameConstants.Direction.Right;
                    }
                }

                //approach player, but keep a distance
                float dist = Vector2.Distance(CenterPoint, target.CenterPoint);
                if (dist < GlobalGameConstants.TileSize.X * 3)
                {
                    //chaseWaitTime -= currentTime.ElapsedGameTime.Milliseconds;

                    velocity = -patrolChaseSpeed * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));

                    if (direction_facing == GlobalGameConstants.Direction.Up || direction_facing == GlobalGameConstants.Direction.Down)
                    {
                        if (Math.Abs(CenterPoint.X - target.CenterPoint.X) > 10.0f)
                        {
                            if (CenterPoint.X < target.CenterPoint.X)
                            {
                                velocity.X += patrolChaseSpeed / 8;
                            }
                            else if (CenterPoint.X > target.CenterPoint.X)
                            {
                                velocity.X -= patrolChaseSpeed / 8;
                            }
                        }
                    }

                    if (direction_facing == GlobalGameConstants.Direction.Left || direction_facing == GlobalGameConstants.Direction.Right)
                    {
                        if (Math.Abs(CenterPoint.Y - target.CenterPoint.Y) > 10.0f)
                        {
                            if (CenterPoint.Y < target.CenterPoint.Y)
                            {
                                velocity.Y += patrolChaseSpeed / 8;
                            }
                            else if (CenterPoint.Y > target.CenterPoint.Y)
                            {
                                velocity.Y -= patrolChaseSpeed / 8;
                            }
                        }
                    }
                }
                else if (dist > GlobalGameConstants.TileSize.X * 4)
                {
                    //chaseWaitTime -= currentTime.ElapsedGameTime.Milliseconds;

                    velocity = patrolChaseSpeed * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));

                    if (direction_facing == GlobalGameConstants.Direction.Up || direction_facing == GlobalGameConstants.Direction.Down)
                    {
                        if (Math.Abs(CenterPoint.X - target.CenterPoint.X) > 10.0f)
                        {
                            if (CenterPoint.X < target.CenterPoint.X)
                            {
                                velocity.X += patrolChaseSpeed / 8;
                            }
                            else if (CenterPoint.X > target.CenterPoint.X)
                            {
                                velocity.X -= patrolChaseSpeed / 8;
                            }
                        }
                    }

                    if (direction_facing == GlobalGameConstants.Direction.Left || direction_facing == GlobalGameConstants.Direction.Right)
                    {
                        if (Math.Abs(CenterPoint.Y - target.CenterPoint.Y) > 10.0f)
                        {
                            if (CenterPoint.Y < target.CenterPoint.Y)
                            {
                                velocity.Y += patrolChaseSpeed / 8;
                            }
                            else if (CenterPoint.Y > target.CenterPoint.Y)
                            {
                                velocity.Y -= patrolChaseSpeed / 8;
                            }
                        }
                    }
                }
                else
                {
                    chaseWaitTime += currentTime.ElapsedGameTime.Milliseconds;

                    velocity = Vector2.Zero;

                    if (chaseWaitTime > chaseWaitDuration)
                    {
                        chaseWaitTime  = 0.0f;
                        guardState     = PatrolGuardState.WindUp;
                        animation_time = 0.0f;
                    }
                }

                if (chaseWaitTime < 0)
                {
                    chaseWaitTime = 0f;
                }

                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("chase");
            }
            else if (guardState == PatrolGuardState.WindUp)
            {
                velocity = Vector2.Zero;

                windUpTime += currentTime.ElapsedGameTime.Milliseconds;

                if (windUpTime > windUpDuration)
                {
                    windUpTime     = 0.0f;
                    animation_time = 0.0f;
                    guardState     = PatrolGuardState.Shooting;

                    for (int i = 0; i < bulletSupply; i++)
                    {
                        if (!(bullets[i].active))
                        {
                            AudioLib.playSoundEffect("pistolTEST");
                            parentWorld.Particles.pushBulletCasing(new Vector2(directionAnims[(int)direction_facing].Skeleton.FindBone("gun").WorldX, directionAnims[(int)direction_facing].Skeleton.FindBone("gun").WorldY));
                            Vector2 muzzleLocation = new Vector2(directionAnims[(int)direction_facing].Skeleton.FindBone("muzzle").WorldX, directionAnims[(int)direction_facing].Skeleton.FindBone("muzzle").WorldY);
                            bullets[i] = new GunBullet(muzzleLocation, direction_facing, this);

                            parentWorld.Particles.pushPistolFlash(muzzleLocation, Color.White, direction_facing);

                            break;
                        }
                    }
                }

                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("windUp");
            }
            else if (guardState == PatrolGuardState.Shooting)
            {
                windUpTime += currentTime.ElapsedGameTime.Milliseconds;

                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("attack");

                if (windUpTime > windUpDuration)
                {
                    windUpTime     = 0.0f;
                    animation_time = 0.0f;
                    guardState     = PatrolGuardState.Chase;

                    directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("chase");
                }
            }
            else if (guardState == PatrolGuardState.KnockBack)
            {
                if (health < 0)
                {
                    remove_from_list = true;
                    return;
                }

                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("hurt");

                knockBackTime += currentTime.ElapsedGameTime.Milliseconds;

                if (knockBackTime > knockBackDuration)
                {
                    //target = null;

                    guardState = PatrolGuardState.Chase;
                }
            }
            else if (guardState == PatrolGuardState.Dying)
            {
                directionAnims[(int)direction_facing].Animation = directionAnims[(int)direction_facing].Skeleton.Data.FindAnimation("die");

                death = true;

                velocity = Vector2.Zero;
            }

            Vector2 newPos   = position + (currentTime.ElapsedGameTime.Milliseconds * velocity);
            Vector2 finalPos = parentWorld.Map.reloactePosition(position, newPos, dimensions);

            position = finalPos;

            for (int i = 0; i < bulletSupply; i++)
            {
                bullets[i].update(parentWorld, currentTime);
            }

            directionAnims[(int)direction_facing].Animation.Apply(directionAnims[(int)direction_facing].Skeleton, animation_time / 1000f, (guardState == PatrolGuardState.MoveWait || guardState == PatrolGuardState.Chase || guardState == PatrolGuardState.RetreatToCenter) ? true : false);
        }