Esempio n. 1
0
        public override bool Use(float deltaTime, Character character = null)
        {
            if (character == null || character.Removed)
            {
                return(false);
            }
            if (!character.IsKeyDown(InputType.Aim) || reloadTimer > 0.0f)
            {
                return(false);
            }
            IsActive    = true;
            reloadTimer = reload;

            List <Body> limbBodies = new List <Body>();

            foreach (Limb l in character.AnimController.Limbs)
            {
                limbBodies.Add(l.body.FarseerBody);
            }

            float degreeOfFailure = 1.0f - DegreeOfSuccess(character);

            degreeOfFailure *= degreeOfFailure;

            if (degreeOfFailure > Rand.Range(0.0f, 1.0f))
            {
                ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
            }

            Projectile projectile     = null;
            var        containedItems = item.ContainedItems;

            if (containedItems == null)
            {
                return(true);
            }

            foreach (Item item in containedItems)
            {
                projectile = item.GetComponent <Projectile>();
                if (projectile != null)
                {
                    break;
                }
            }
            //projectile not found, see if one of the contained items contains projectiles
            if (projectile == null)
            {
                foreach (Item item in containedItems)
                {
                    projectile = item.GetComponent <Projectile>();
                    if (projectile != null)
                    {
                        break;
                    }
                }
                //projectile not found, see if one of the contained items contains projectiles
                if (projectile == null)
                {
                    foreach (Item item in containedItems)
                    {
                        var containedSubItems = item.ContainedItems;
                        if (containedSubItems == null)
                        {
                            continue;
                        }
                        foreach (Item subItem in containedSubItems)
                        {
                            projectile = subItem.GetComponent <Projectile>();

                            //apply OnUse statuseffects to the container in case it has to react to it somehow
                            //(play a sound, spawn more projectiles, reduce condition...)
                            subItem.GetComponent <ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
                            if (projectile != null)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            if (projectile == null)
            {
                return(true);
            }

            float spread   = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
            float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;

            rotation += spread * Rand.Range(-0.5f, 0.5f);

            projectile.User = character;
            //add the limbs of the shooter to the list of bodies to be ignored
            //so that the player can't shoot himself
            projectile.IgnoredBodies = new List <Body>(limbBodies);

            Vector2 projectilePos = item.SimPosition;
            Vector2 sourcePos     = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
            Vector2 barrelPos     = TransformedBarrelPos;

            //make sure there's no obstacles between the base of the weapon (or the shoulder of the character) and the end of the barrel
            if (Submarine.PickBody(sourcePos, barrelPos, projectile.IgnoredBodies) == null)
            {
                //no obstacles -> we can spawn the projectile at the barrel
                projectilePos = barrelPos;
            }
            else if ((sourcePos - barrelPos).LengthSquared() > 0.0001f)
            {
                //spawn the projectile body.GetMaxExtent() away from the position where the raycast hit the obstacle
                projectilePos = sourcePos - Vector2.Normalize(barrelPos - projectilePos) * Math.Max(projectile.Item.body.GetMaxExtent(), 0.1f);
            }

            projectile.Item.body.ResetDynamics();
            projectile.Item.SetTransform(projectilePos, rotation);

            projectile.Use(deltaTime);
            projectile.User = character;

            projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));

            //set the rotation of the projectile again because dropping the projectile resets the rotation
            projectile.Item.SetTransform(projectilePos,
                                         rotation + ((item.body.Dir == 1.0f) ? projectile.LaunchRotationRadians : projectile.LaunchRotationRadians - MathHelper.Pi));

            //recoil
            item.body.ApplyLinearImpulse(
                new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f);

            item.RemoveContained(projectile.Item);

            Rope rope = item.GetComponent <Rope>();

            if (rope != null)
            {
                rope.Attach(projectile.Item);
            }

            return(true);
        }
Esempio n. 2
0
        public override bool Use(float deltaTime, Character character = null)
        {
            if (character == null)
            {
                return(false);
            }
            if (!character.IsKeyDown(InputType.Aim) || reloadTimer > 0.0f)
            {
                return(false);
            }
            IsActive    = true;
            reloadTimer = reload;

            List <Body> limbBodies = new List <Body>();

            foreach (Limb l in character.AnimController.Limbs)
            {
                limbBodies.Add(l.body.FarseerBody);
            }

            float degreeOfFailure = (100.0f - DegreeOfSuccess(character)) / 100.0f;

            degreeOfFailure *= degreeOfFailure;

            if (degreeOfFailure > Rand.Range(0.0f, 1.0f))
            {
                ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
            }

            Item[] containedItems = item.ContainedItems;
            if (containedItems != null)
            {
                foreach (Item projectile in containedItems)
                {
                    if (projectile == null)
                    {
                        continue;
                    }
                    //find the projectile-itemcomponent of the projectile,
                    //and add the limbs of the shooter to the list of bodies to be ignored
                    //so that the player can't shoot himself
                    Projectile projectileComponent = projectile.GetComponent <Projectile>();
                    if (projectileComponent == null)
                    {
                        continue;
                    }

                    float spread   = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
                    float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
                    rotation += spread * Rand.Range(-0.5f, 0.5f);

                    projectile.body.ResetDynamics();
                    projectile.SetTransform(TransformedBarrelPos, rotation);
                    projectileComponent.User          = character;
                    projectileComponent.IgnoredBodies = new List <Body>(limbBodies);

                    projectile.Use(deltaTime);

                    projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));

                    //set the rotation of the projectile again because dropping the projectile resets the rotation
                    projectile.SetTransform(projectile.SimPosition, rotation);

                    //recoil
                    item.body.ApplyLinearImpulse(
                        new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f);

                    item.RemoveContained(projectile);

                    Rope rope = item.GetComponent <Rope>();
                    if (rope != null)
                    {
                        rope.Attach(projectile);
                    }

                    return(true);
                }
            }

            return(true);
        }