Beispiel #1
0
        public static void PlayDamageSound(string damageType, float damage, PhysicsBody body)
        {
            Vector2 bodyPosition = body.DrawPosition;

            PlayDamageSound(damageType, damage, bodyPosition, 800.0f);
        }
Beispiel #2
0
        public LevelTrigger(XElement element, Vector2 position, float rotation, float scale = 1.0f, string parentDebugName = "")
        {
            TriggererPosition = new Dictionary <Entity, Vector2>();

            worldPosition = position;
            if (element.Attributes("radius").Any() || element.Attributes("width").Any() || element.Attributes("height").Any())
            {
                PhysicsBody = new PhysicsBody(element, scale)
                {
                    CollisionCategories = Physics.CollisionLevel,
                    CollidesWith        = Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionProjectile | Physics.CollisionWall
                };
                PhysicsBody.FarseerBody.OnCollision  += PhysicsBody_OnCollision;
                PhysicsBody.FarseerBody.OnSeparation += PhysicsBody_OnSeparation;
                PhysicsBody.FarseerBody.SetIsSensor(true);
                PhysicsBody.FarseerBody.BodyType = BodyType.Static;
                PhysicsBody.FarseerBody.BodyType = BodyType.Kinematic;

                ColliderRadius = ConvertUnits.ToDisplayUnits(Math.Max(Math.Max(PhysicsBody.radius, PhysicsBody.width / 2.0f), PhysicsBody.height / 2.0f));

                PhysicsBody.SetTransform(ConvertUnits.ToSimUnits(position), rotation);
            }

            cameraShake = element.GetAttributeFloat("camerashake", 0.0f);

            InfectIdentifier = element.GetAttributeString("infectidentifier", null);
            InfectionChance  = element.GetAttributeFloat("infectionchance", 0.05f);

            triggerOnce = element.GetAttributeBool("triggeronce", false);

            stayTriggeredDelay       = element.GetAttributeFloat("staytriggereddelay", 0.0f);
            randomTriggerInterval    = element.GetAttributeFloat("randomtriggerinterval", 0.0f);
            randomTriggerProbability = element.GetAttributeFloat("randomtriggerprobability", 0.0f);

            UseNetworkSyncing = element.GetAttributeBool("networksyncing", false);

            unrotatedForce =
                element.Attribute("force") != null && element.Attribute("force").Value.Contains(',') ?
                element.GetAttributeVector2("force", Vector2.Zero) :
                new Vector2(element.GetAttributeFloat("force", 0.0f), 0.0f);

            ForceFluctuationInterval = element.GetAttributeFloat("forcefluctuationinterval", 0.01f);
            ForceFluctuationStrength = Math.Max(element.GetAttributeFloat("forcefluctuationstrength", 0.0f), 0.0f);
            ForceFalloff             = element.GetAttributeBool("forcefalloff", true);

            ForceVelocityLimit = ConvertUnits.ToSimUnits(element.GetAttributeFloat("forcevelocitylimit", float.MaxValue));
            string forceModeStr = element.GetAttributeString("forcemode", "Force");

            if (!Enum.TryParse(forceModeStr, out forceMode))
            {
                DebugConsole.ThrowError("Error in LevelTrigger config: \"" + forceModeStr + "\" is not a valid force mode.");
            }
            CalculateDirectionalForce();

            string triggeredByStr = element.GetAttributeString("triggeredby", "Character");

            if (!Enum.TryParse(triggeredByStr, out triggeredBy))
            {
                DebugConsole.ThrowError("Error in LevelTrigger config: \"" + triggeredByStr + "\" is not a valid triggerer type.");
            }
            UpdateCollisionCategories();
            TriggerOthersDistance = element.GetAttributeFloat("triggerothersdistance", 0.0f);

            var tagsArray = element.GetAttributeStringArray("tags", new string[0]);

            foreach (string tag in tagsArray)
            {
                tags.Add(tag.ToLower());
            }

            if (triggeredBy.HasFlag(TriggererType.OtherTrigger))
            {
                var otherTagsArray = element.GetAttributeStringArray("allowedothertriggertags", new string[0]);
                foreach (string tag in otherTagsArray)
                {
                    allowedOtherTriggerTags.Add(tag.ToLower());
                }
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                    statusEffects.Add(StatusEffect.Load(subElement, string.IsNullOrEmpty(parentDebugName) ? "LevelTrigger" : "LevelTrigger in " + parentDebugName));
                    break;

                case "attack":
                case "damage":
                    var attack = new Attack(subElement, string.IsNullOrEmpty(parentDebugName) ? "LevelTrigger" : "LevelTrigger in " + parentDebugName);
                    if (!triggerOnce)
                    {
                        var multipliedAfflictions = attack.GetMultipliedAfflictions((float)Timing.Step);
                        attack.Afflictions.Clear();
                        foreach (Affliction affliction in multipliedAfflictions)
                        {
                            attack.Afflictions.Add(affliction, null);
                        }
                    }
                    attacks.Add(attack);
                    break;
                }
            }

            forceFluctuationTimer = Rand.Range(0.0f, ForceFluctuationInterval);
            randomTriggerTimer    = Rand.Range(0.0f, randomTriggerInterval);
        }
Beispiel #3
0
        public void Update(float deltaTime)
        {
            if (ParentTrigger != null && !ParentTrigger.IsTriggered)
            {
                return;
            }

            triggerers.RemoveWhere(t => t.Removed);

            if (PhysicsBody != null)
            {
                //failsafe to ensure triggerers get removed when they're far from the trigger
                float maxExtent = Math.Max(ConvertUnits.ToDisplayUnits(PhysicsBody.GetMaxExtent() * 5), 5000.0f);
                triggerers.RemoveWhere(t =>
                {
                    return(Vector2.Distance(t.WorldPosition, WorldPosition) > maxExtent);
                });
            }

            bool isNotClient = true;

#if CLIENT
            isNotClient = GameMain.Client == null;
#endif

            if (!UseNetworkSyncing || isNotClient)
            {
                if (ForceFluctuationStrength > 0.0f)
                {
                    //no need for force fluctuation (or network updates) if the trigger limits velocity and there are no triggerers
                    if (forceMode != TriggerForceMode.LimitVelocity || triggerers.Any())
                    {
                        forceFluctuationTimer += deltaTime;
                        if (forceFluctuationTimer > ForceFluctuationInterval)
                        {
                            NeedsNetworkSyncing     = true;
                            currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f);
                            forceFluctuationTimer   = 0.0f;
                        }
                    }
                }

                if (randomTriggerProbability > 0.0f)
                {
                    randomTriggerTimer += deltaTime;
                    if (randomTriggerTimer > randomTriggerInterval)
                    {
                        if (Rand.Range(0.0f, 1.0f) < randomTriggerProbability)
                        {
                            NeedsNetworkSyncing = true;
                            triggeredTimer      = stayTriggeredDelay;
                        }
                        randomTriggerTimer = 0.0f;
                    }
                }
            }

            if (stayTriggeredDelay > 0.0f)
            {
                if (triggerers.Count == 0)
                {
                    triggeredTimer -= deltaTime;
                }
                else
                {
                    triggeredTimer = stayTriggeredDelay;
                }
            }

            if (triggerOnce)
            {
                if (triggeredOnce)
                {
                    return;
                }
                if (triggerers.Count > 0)
                {
                    triggeredOnce = true;
                }
            }

            foreach (Entity triggerer in triggerers)
            {
                foreach (StatusEffect effect in statusEffects)
                {
                    Vector2?position = null;
                    if (effect.HasTargetType(StatusEffect.TargetType.This))
                    {
                        position = WorldPosition;
                    }
                    if (triggerer is Character character)
                    {
                        effect.Apply(effect.type, deltaTime, triggerer, character, position);
                        if (effect.HasTargetType(StatusEffect.TargetType.Contained) && character.Inventory != null)
                        {
                            foreach (Item item in character.Inventory.AllItemsMod)
                            {
                                if (item.ContainedItems == null)
                                {
                                    continue;
                                }
                                foreach (Item containedItem in item.ContainedItems)
                                {
                                    effect.Apply(effect.type, deltaTime, triggerer, containedItem.AllPropertyObjects, position);
                                }
                            }
                        }
                    }
                    else if (triggerer is Item item)
                    {
                        effect.Apply(effect.type, deltaTime, triggerer, item.AllPropertyObjects, position);
                    }
                    if (effect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
                        effect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
                    {
                        var targets = new List <ISerializableEntity>();
                        effect.GetNearbyTargets(worldPosition, targets);
                        effect.Apply(effect.type, deltaTime, triggerer, targets);
                    }
                }

                if (triggerer is IDamageable damageable)
                {
                    foreach (Attack attack in attacks)
                    {
                        attack.DoDamage(null, damageable, WorldPosition, deltaTime, false);
                    }
                }
                else if (triggerer is Submarine submarine)
                {
                    foreach (Attack attack in attacks)
                    {
                        float structureDamage = attack.GetStructureDamage(deltaTime);
                        if (structureDamage > 0.0f)
                        {
                            Explosion.RangedStructureDamage(worldPosition, attack.DamageRange, structureDamage, levelWallDamage: 0.0f);
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(InfectIdentifier))
                    {
                        submarine.AttemptBallastFloraInfection(InfectIdentifier, deltaTime, InfectionChance);
                    }
                }

                if (Force.LengthSquared() > 0.01f)
                {
                    if (triggerer is Character character)
                    {
                        ApplyForce(character.AnimController.Collider, deltaTime);
                        foreach (Limb limb in character.AnimController.Limbs)
                        {
                            if (limb.IsSevered)
                            {
                                continue;
                            }
                            ApplyForce(limb.body, deltaTime);
                        }
                    }
                    else if (triggerer is Submarine submarine)
                    {
                        ApplyForce(submarine.SubBody.Body, deltaTime);
                    }
                }

                if (triggerer == Character.Controlled || triggerer == Character.Controlled?.Submarine)
                {
                    GameMain.GameScreen.Cam.Shake = Math.Max(GameMain.GameScreen.Cam.Shake, cameraShake);
                }
            }
        }
Beispiel #4
0
        public Limb(Ragdoll ragdoll, Character character, LimbParams limbParams)
        {
            this.ragdoll   = ragdoll;
            this.character = character;
            this.Params    = limbParams;
            wearingItems   = new List <WearableSprite>();
            dir            = Direction.Right;
            body           = new PhysicsBody(limbParams);
            type           = limbParams.Type;
            if (limbParams.IgnoreCollisions)
            {
                body.CollisionCategories = Category.None;
                body.CollidesWith        = Category.None;
                ignoreCollisions         = true;
            }
            else
            {
                //limbs don't collide with each other
                body.CollisionCategories = Physics.CollisionCharacter;
                body.CollidesWith        = Physics.CollisionAll & ~Physics.CollisionCharacter & ~Physics.CollisionItem & ~Physics.CollisionItemBlocking;
            }
            body.UserData = this;
            pullJoint     = new FixedMouseJoint(body.FarseerBody, ConvertUnits.ToSimUnits(limbParams.PullPos * Scale))
            {
                Enabled = false,
                //MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass
                // 150 or even 400 is too low if the joint is used for moving the character position from the mainlimb towards the collider position
                MaxForce = 1000 * Mass
            };

            GameMain.World.Add(pullJoint);

            var element = limbParams.Element;

            body.BodyType = BodyType.Dynamic;

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "attack":
                    attack = new Attack(subElement, (character == null ? "null" : character.Name) + ", limb " + type);
                    if (attack.DamageRange <= 0)
                    {
                        switch (body.BodyShape)
                        {
                        case PhysicsBody.Shape.Circle:
                            attack.DamageRange = body.radius;
                            break;

                        case PhysicsBody.Shape.Capsule:
                            attack.DamageRange = body.height / 2 + body.radius;
                            break;

                        case PhysicsBody.Shape.Rectangle:
                            attack.DamageRange = new Vector2(body.width / 2.0f, body.height / 2.0f).Length();
                            break;
                        }
                        attack.DamageRange = ConvertUnits.ToDisplayUnits(attack.DamageRange);
                    }
                    break;

                case "damagemodifier":
                    DamageModifiers.Add(new DamageModifier(subElement, character.Name));
                    break;
                }
            }

            SerializableProperties = SerializableProperty.GetProperties(this);

            InitProjSpecific(element);
        }
Beispiel #5
0
        public SubmarineBody(Submarine sub, bool showWarningMessages = true)
        {
            this.submarine = sub;

            Body farseerBody = null;

            if (!Hull.hullList.Any())
            {
                farseerBody = BodyFactory.CreateRectangle(GameMain.World, 1.0f, 1.0f, 1.0f);
                if (showWarningMessages)
                {
                    DebugConsole.ThrowError("WARNING: no hulls found, generating a physics body for the submarine failed.");
                }
            }
            else
            {
                List <Vector2> convexHull = GenerateConvexHull();
                HullVertices = convexHull;
                for (int i = 0; i < convexHull.Count; i++)
                {
                    convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
                }

                Vector2 minExtents = Vector2.Zero, maxExtents = Vector2.Zero;

                farseerBody = BodyFactory.CreateBody(GameMain.World, this);
                foreach (Structure wall in Structure.WallList)
                {
                    if (wall.Submarine != submarine)
                    {
                        continue;
                    }

                    Rectangle rect = wall.Rect;

                    FixtureFactory.AttachRectangle(
                        ConvertUnits.ToSimUnits(wall.BodyWidth),
                        ConvertUnits.ToSimUnits(wall.BodyHeight),
                        50.0f,
                        -wall.BodyRotation,
                        ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2) + wall.BodyOffset),
                        farseerBody, this);

                    minExtents.X = Math.Min(rect.X, minExtents.X);
                    minExtents.Y = Math.Min(rect.Y - rect.Height, minExtents.Y);
                    maxExtents.X = Math.Max(rect.Right, maxExtents.X);
                    maxExtents.Y = Math.Max(rect.Y, maxExtents.Y);
                }

                foreach (Hull hull in Hull.hullList)
                {
                    if (hull.Submarine != submarine)
                    {
                        continue;
                    }

                    Rectangle rect = hull.Rect;
                    FixtureFactory.AttachRectangle(
                        ConvertUnits.ToSimUnits(rect.Width),
                        ConvertUnits.ToSimUnits(rect.Height),
                        100.0f,
                        ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
                        farseerBody, this);

                    minExtents.X = Math.Min(rect.X, minExtents.X);
                    minExtents.Y = Math.Min(rect.Y - rect.Height, minExtents.Y);
                    maxExtents.X = Math.Max(rect.Right, maxExtents.X);
                    maxExtents.Y = Math.Max(rect.Y, maxExtents.Y);
                }

                foreach (Item item in Item.ItemList)
                {
                    if (item.StaticBodyConfig == null || item.Submarine != submarine)
                    {
                        continue;
                    }

                    float radius = item.StaticBodyConfig.GetAttributeFloat("radius", 0.0f) * item.Scale;
                    float width  = item.StaticBodyConfig.GetAttributeFloat("width", 0.0f) * item.Scale;
                    float height = item.StaticBodyConfig.GetAttributeFloat("height", 0.0f) * item.Scale;

                    Vector2 simPos    = ConvertUnits.ToSimUnits(item.Position);
                    float   simRadius = ConvertUnits.ToSimUnits(radius);
                    float   simWidth  = ConvertUnits.ToSimUnits(width);
                    float   simHeight = ConvertUnits.ToSimUnits(height);

                    if (width > 0.0f && height > 0.0f)
                    {
                        FixtureFactory.AttachRectangle(simWidth, simHeight, 5.0f, simPos, farseerBody, this).UserData = item;

                        minExtents.X = Math.Min(item.Position.X - width / 2, minExtents.X);
                        minExtents.Y = Math.Min(item.Position.Y - height / 2, minExtents.Y);
                        maxExtents.X = Math.Max(item.Position.X + width / 2, maxExtents.X);
                        maxExtents.Y = Math.Max(item.Position.Y + height / 2, maxExtents.Y);
                    }
                    else if (radius > 0.0f && width > 0.0f)
                    {
                        FixtureFactory.AttachRectangle(simWidth, simRadius * 2, 5.0f, simPos, farseerBody, this).UserData = item;
                        FixtureFactory.AttachCircle(simRadius, 5.0f, farseerBody, simPos - Vector2.UnitX * simWidth / 2, this).UserData = item;
                        FixtureFactory.AttachCircle(simRadius, 5.0f, farseerBody, simPos + Vector2.UnitX * simWidth / 2, this).UserData = item;
                        minExtents.X = Math.Min(item.Position.X - width / 2 - radius, minExtents.X);
                        minExtents.Y = Math.Min(item.Position.Y - radius, minExtents.Y);
                        maxExtents.X = Math.Max(item.Position.X + width / 2 + radius, maxExtents.X);
                        maxExtents.Y = Math.Max(item.Position.Y + radius, maxExtents.Y);
                    }
                    else if (radius > 0.0f && height > 0.0f)
                    {
                        FixtureFactory.AttachRectangle(simRadius * 2, height, 5.0f, simPos, farseerBody, this).UserData = item;
                        FixtureFactory.AttachCircle(simRadius, 5.0f, farseerBody, simPos - Vector2.UnitY * simHeight / 2, this).UserData = item;
                        FixtureFactory.AttachCircle(simRadius, 5.0f, farseerBody, simPos + Vector2.UnitX * simHeight / 2, this).UserData = item;
                        minExtents.X = Math.Min(item.Position.X - radius, minExtents.X);
                        minExtents.Y = Math.Min(item.Position.Y - height / 2 - radius, minExtents.Y);
                        maxExtents.X = Math.Max(item.Position.X + radius, maxExtents.X);
                        maxExtents.Y = Math.Max(item.Position.Y + height / 2 + radius, maxExtents.Y);
                    }
                    else if (radius > 0.0f)
                    {
                        FixtureFactory.AttachCircle(simRadius, 5.0f, farseerBody, simPos, this).UserData = item;
                        minExtents.X = Math.Min(item.Position.X - radius, minExtents.X);
                        minExtents.Y = Math.Min(item.Position.Y - radius, minExtents.Y);
                        maxExtents.X = Math.Max(item.Position.X + radius, maxExtents.X);
                        maxExtents.Y = Math.Max(item.Position.Y + radius, maxExtents.Y);
                    }
                }

                Borders = new Rectangle((int)minExtents.X, (int)maxExtents.Y, (int)(maxExtents.X - minExtents.X), (int)(maxExtents.Y - minExtents.Y));
            }

            farseerBody.BodyType            = BodyType.Dynamic;
            farseerBody.CollisionCategories = Physics.CollisionWall;
            farseerBody.CollidesWith        =
                Physics.CollisionItem |
                Physics.CollisionLevel |
                Physics.CollisionCharacter |
                Physics.CollisionProjectile |
                Physics.CollisionWall;

            farseerBody.Restitution     = Restitution;
            farseerBody.Friction        = Friction;
            farseerBody.FixedRotation   = true;
            farseerBody.Awake           = true;
            farseerBody.SleepingAllowed = false;
            farseerBody.IgnoreGravity   = true;
            farseerBody.OnCollision    += OnCollision;
            farseerBody.UserData        = submarine;

            Body = new PhysicsBody(farseerBody);
        }
Beispiel #6
0
        public Limb(Character character, XElement element, float scale = 1.0f)
        {
            this.character = character;

            WearingItems = new List <WearableSprite>();

            dir      = Direction.Right;
            DoesFlip = element.GetAttributeBool("flip", false);

            Scale = scale;

            body = new PhysicsBody(element, scale);

            if (element.GetAttributeBool("ignorecollisions", false))
            {
                body.CollisionCategories = Category.None;
                body.CollidesWith        = Category.None;

                ignoreCollisions = true;
            }
            else
            {
                //limbs don't collide with each other
                body.CollisionCategories = Physics.CollisionCharacter;
                body.CollidesWith        = Physics.CollisionAll & ~Physics.CollisionCharacter & ~Physics.CollisionItem;
            }

            body.UserData = this;

            RefJointIndex = -1;

            Vector2 pullJointPos = Vector2.Zero;

            if (element.Attribute("type") != null)
            {
                try
                {
                    type = (LimbType)Enum.Parse(typeof(LimbType), element.Attribute("type").Value, true);
                }
                catch
                {
                    type = LimbType.None;
                    DebugConsole.ThrowError("Error in " + element + "! \"" + element.Attribute("type").Value + "\" is not a valid limb type");
                }


                pullJointPos = element.GetAttributeVector2("pullpos", Vector2.Zero) * scale;
                pullJointPos = ConvertUnits.ToSimUnits(pullJointPos);

                stepOffset = element.GetAttributeVector2("stepoffset", Vector2.Zero) * scale;
                stepOffset = ConvertUnits.ToSimUnits(stepOffset);

                RefJointIndex = element.GetAttributeInt("refjoint", -1);
            }
            else
            {
                type = LimbType.None;
            }

            pullJoint          = new FixedMouseJoint(body.FarseerBody, pullJointPos);
            pullJoint.Enabled  = false;
            pullJoint.MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass;

            GameMain.World.AddJoint(pullJoint);

            SteerForce = element.GetAttributeFloat("steerforce", 0.0f);

            if (element.Attribute("mouthpos") != null)
            {
                MouthPos = ConvertUnits.ToSimUnits(element.GetAttributeVector2("mouthpos", Vector2.Zero));
            }

            body.BodyType = BodyType.Dynamic;
            body.FarseerBody.AngularDamping = LimbAngularDamping;

            damageModifiers = new List <DamageModifier>();

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "sprite":
                    string spritePath = subElement.Attribute("texture").Value;

                    string spritePathWithTags = spritePath;

                    if (character.Info != null)
                    {
                        spritePath = spritePath.Replace("[GENDER]", (character.Info.Gender == Gender.Female) ? "f" : "");
                        spritePath = spritePath.Replace("[HEADID]", character.Info.HeadSpriteId.ToString());

                        if (character.Info.HeadSprite != null && character.Info.SpriteTags.Any())
                        {
                            string tags = "";
                            character.Info.SpriteTags.ForEach(tag => tags += "[" + tag + "]");

                            spritePathWithTags = Path.Combine(
                                Path.GetDirectoryName(spritePath),
                                Path.GetFileNameWithoutExtension(spritePath) + tags + Path.GetExtension(spritePath));
                        }
                    }

                    if (File.Exists(spritePathWithTags))
                    {
                        sprite = new Sprite(subElement, "", spritePathWithTags);
                    }
                    else
                    {
                        sprite = new Sprite(subElement, "", spritePath);
                    }

                    break;

                case "damagedsprite":
                    string damagedSpritePath = subElement.Attribute("texture").Value;

                    if (character.Info != null)
                    {
                        damagedSpritePath = damagedSpritePath.Replace("[GENDER]", (character.Info.Gender == Gender.Female) ? "f" : "");
                        damagedSpritePath = damagedSpritePath.Replace("[HEADID]", character.Info.HeadSpriteId.ToString());
                    }

                    damagedSprite = new Sprite(subElement, "", damagedSpritePath);
                    break;

                case "attack":
                    attack = new Attack(subElement);
                    break;

                case "damagemodifier":
                    damageModifiers.Add(new DamageModifier(subElement));
                    break;
                }
            }

            InitProjSpecific(element);
        }
Beispiel #7
0
        public SubmarineBody(Submarine sub)
        {
            this.submarine = sub;

            Body farseerBody = null;

            if (!Hull.hullList.Any())
            {
                Body        = new PhysicsBody(1, 1, 1, 1);
                farseerBody = Body.FarseerBody;
                DebugConsole.ThrowError("WARNING: no hulls found, generating a physics body for the submarine failed.");
            }
            else
            {
                List <Vector2> convexHull = GenerateConvexHull();
                HullVertices = convexHull;

                for (int i = 0; i < convexHull.Count; i++)
                {
                    convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
                }

                convexHull.Reverse();

                //get farseer 'vertices' from vectors
                Vertices shapevertices = new Vertices(convexHull);

                AABB hullAABB = shapevertices.GetAABB();

                Borders = new Rectangle(
                    (int)ConvertUnits.ToDisplayUnits(hullAABB.LowerBound.X),
                    (int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y),
                    (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f),
                    (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f));

                farseerBody = BodyFactory.CreateBody(GameMain.World, this);

                foreach (Structure wall in Structure.WallList)
                {
                    if (wall.Submarine != submarine)
                    {
                        continue;
                    }

                    Rectangle rect = wall.Rect;

                    FixtureFactory.AttachRectangle(
                        ConvertUnits.ToSimUnits(rect.Width),
                        ConvertUnits.ToSimUnits(rect.Height),
                        50.0f,
                        ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
                        farseerBody, this);
                }

                foreach (Hull hull in Hull.hullList)
                {
                    if (hull.Submarine != submarine)
                    {
                        continue;
                    }

                    Rectangle rect = hull.Rect;
                    FixtureFactory.AttachRectangle(
                        ConvertUnits.ToSimUnits(rect.Width),
                        ConvertUnits.ToSimUnits(rect.Height),
                        5.0f,
                        ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
                        farseerBody, this);
                }
            }



            farseerBody.BodyType            = BodyType.Dynamic;
            farseerBody.CollisionCategories = Physics.CollisionWall;
            farseerBody.CollidesWith        =
                Physics.CollisionItem |
                Physics.CollisionLevel |
                Physics.CollisionCharacter |
                Physics.CollisionProjectile |
                Physics.CollisionWall;

            farseerBody.Restitution   = Restitution;
            farseerBody.Friction      = Friction;
            farseerBody.FixedRotation = true;
            //mass = Body.Mass;
            farseerBody.Awake           = true;
            farseerBody.SleepingAllowed = false;
            farseerBody.IgnoreGravity   = true;
            farseerBody.OnCollision    += OnCollision;
            farseerBody.UserData        = submarine;

            Body = new PhysicsBody(farseerBody);
        }
Beispiel #8
0
        public LevelObject(LevelObjectPrefab prefab, Vector3 position, float scale, float rotation = 0.0f)
        {
            ActivePrefab = Prefab = prefab;
            Position     = position;
            Scale        = scale;
            Rotation     = rotation;

            spriteIndex = ActivePrefab.Sprites.Any() ? Rand.Int(ActivePrefab.Sprites.Count, Rand.RandSync.Server) : -1;

            if (Sprite != null && prefab.SpriteSpecificPhysicsBodyElements.ContainsKey(Sprite))
            {
                PhysicsBody = new PhysicsBody(prefab.SpriteSpecificPhysicsBodyElements[Sprite], ConvertUnits.ToSimUnits(new Vector2(position.X, position.Y)), Scale);
            }
            else if (prefab.PhysicsBodyElement != null)
            {
                PhysicsBody = new PhysicsBody(prefab.PhysicsBodyElement, ConvertUnits.ToSimUnits(new Vector2(position.X, position.Y)), Scale);
            }

            if (PhysicsBody != null)
            {
                PhysicsBody.SetTransformIgnoreContacts(PhysicsBody.SimPosition, -Rotation);
                PhysicsBody.BodyType            = BodyType.Static;
                PhysicsBody.CollisionCategories = Physics.CollisionLevel;
                PhysicsBody.CollidesWith        = Physics.CollisionWall | Physics.CollisionCharacter;
            }

            foreach (XElement triggerElement in prefab.LevelTriggerElements)
            {
                Triggers ??= new List <LevelTrigger>();
                Vector2 triggerPosition = triggerElement.GetAttributeVector2("position", Vector2.Zero) * scale;

                if (rotation != 0.0f)
                {
                    var ca = (float)Math.Cos(rotation);
                    var sa = (float)Math.Sin(rotation);

                    triggerPosition = new Vector2(
                        ca * triggerPosition.X + sa * triggerPosition.Y,
                        -sa * triggerPosition.X + ca * triggerPosition.Y);
                }

                var newTrigger         = new LevelTrigger(triggerElement, new Vector2(position.X, position.Y) + triggerPosition, -rotation, scale, prefab.Name);
                int parentTriggerIndex = prefab.LevelTriggerElements.IndexOf(triggerElement.Parent);
                if (parentTriggerIndex > -1)
                {
                    newTrigger.ParentTrigger = Triggers[parentTriggerIndex];
                }
                Triggers.Add(newTrigger);
            }

            if (spriteIndex == -1)
            {
                foreach (var overrideProperties in prefab.OverrideProperties)
                {
                    if (overrideProperties == null)
                    {
                        continue;
                    }
                    if (overrideProperties.Sprites.Count > 0)
                    {
                        spriteIndex = Rand.Int(overrideProperties.Sprites.Count, Rand.RandSync.Server);
                        break;
                    }
                }
            }

            NeedsUpdate = NeedsNetworkSyncing || (Triggers != null && Triggers.Any()) || Prefab.PhysicsBodyTriggerIndex > -1;

            InitProjSpecific();
        }