/// <summary>Overridden from <see cref="Engine.EntitySystem.Entity.OnTick()"/>.</summary>
        protected override void OnTick()
        {
            base.OnTick();

            if (force != 0)
            {
                foreach (MapObject obj in ObjectsInRegion)
                {
                    if (obj.IsSetForDeletion)
                    {
                        continue;
                    }

                    //impulse
                    if (impulsePerSecond != 0)
                    {
                        PhysicsModel objPhysicsModel = obj.PhysicsModel;
                        if (objPhysicsModel != null)
                        {
                            foreach (Body body in objPhysicsModel.Bodies)
                            {
                                if (body.Static)
                                {
                                    continue;
                                }

                                EngineRandom random = World.Instance.Random;

                                float distanceCoef = GetDistanceCoefficient(body.Position);

                                float randomCoef = 1.0f + random.NextFloatCenter() * .1f;

                                float v = impulsePerSecond * force * distanceCoef * randomCoef * TickDelta;

                                Vec3 point = new Vec3(
                                    random.NextFloat() * .1f,
                                    random.NextFloat() * .1f,
                                    random.NextFloat() * .1f);

                                body.AddForce(ForceType.GlobalAtLocalPos, TickDelta,
                                              Rotation * new Vec3(v, 0, 0), point);
                            }
                        }
                    }

                    if (InfluenceType != null || DamagePerSecond != 0)
                    {
                        Dynamic dynamic = obj as Dynamic;
                        if (dynamic != null)
                        {
                            float distanceCoef = GetDistanceCoefficient(obj.Position);

                            if (InfluenceType != null)
                            {
                                dynamic.AddInfluence(InfluenceType,
                                                     InfluenceTimePerSecond * distanceCoef * TickDelta, true);
                            }
                            if (DamagePerSecond != 0)
                            {
                                dynamic.DoDamage(null, obj.Position, null,
                                                 DamagePerSecond * distanceCoef * TickDelta, false);
                            }
                        }
                    }
                }
            }
        }
Example #2
0
        private void DoEffect()
        {
            float radius    = Type.Radius;
            float radiusInv = 1.0f / radius;

            List <MapObject>  objects     = mapObjectListAllocator.Alloc();
            List <DamageItem> damageItems = damageItemListAllocator.Alloc();

            //generate objects list
            Map.Instance.GetObjects(new Sphere(Position, radius), delegate(MapObject obj)
            {
                if (Type.IgnoreReasonObject && obj == ReasonObject)
                {
                    return;
                }
                objects.Add(obj);
            });

            //enumerate objects
            foreach (MapObject obj in objects)
            {
                if (obj.IsSetForDeletion)
                {
                    continue;
                }
                if (!obj.Visible)
                {
                    continue;
                }

                PhysicsModel objPhysicsModel = obj.PhysicsModel;

                float totalObjImpulse = 0;
                float totalObjDamage  = 0;

                if (Type.Impulse != 0 && objPhysicsModel != null)
                {
                    float bodyCountInv = 1.0f / objPhysicsModel.Bodies.Length;

                    foreach (Body body in objPhysicsModel.Bodies)
                    {
                        if (body.Static)
                        {
                            continue;
                        }

                        Vec3  dir      = body.Position - Position;
                        float distance = dir.Normalize();

                        if (distance < radius)
                        {
                            float objImpulse = MathFunctions.Cos((distance * radiusInv) *
                                                                 (MathFunctions.PI / 2)) * Type.Impulse * DamageCoefficient;
                            objImpulse *= bodyCountInv;

                            //forcePos for torque
                            Vec3 forcePos;
                            {
                                Vec3         gabarites = body.GetGlobalBounds().GetSize() * .05f;
                                EngineRandom random    = World.Instance.Random;
                                forcePos = new Vec3(
                                    random.NextFloatCenter() * gabarites.X,
                                    random.NextFloatCenter() * gabarites.Y,
                                    random.NextFloatCenter() * gabarites.Z);
                            }
                            body.AddForce(ForceType.GlobalAtLocalPos, 0, dir * objImpulse, forcePos);

                            totalObjImpulse += objImpulse;
                        }
                    }
                }

                if (Type.Damage != 0)
                {
                    Dynamic dynamic = obj as Dynamic;
                    if (dynamic != null)
                    {
                        float distance = (dynamic.Position - Position).Length();
                        if (distance < radius)
                        {
                            float objDamage = MathFunctions.Cos((distance * radiusInv) *
                                                                (MathFunctions.PI / 2)) * Type.Damage * DamageCoefficient;

                            //add damages to cache and apply after influences (for correct influences work)
                            damageItems.Add(new DamageItem(dynamic, obj.Position, objDamage));
                            //dynamic.DoDamage( dynamic, obj.Position, objDamage, false );

                            totalObjDamage += objDamage;
                        }
                    }
                }

                //PlayerCharacter contusion
                if (totalObjDamage > 10 && totalObjImpulse > 500)
                {
                    PlayerCharacter playerCharacter = obj as PlayerCharacter;
                    if (playerCharacter != null)
                    {
                        playerCharacter.ContusionTimeRemaining += totalObjDamage * .05f;
                    }
                }

                //Influence
                if (Type.InfluenceType != null && (totalObjDamage != 0 || totalObjImpulse != 0))
                {
                    Dynamic dynamic = obj as Dynamic;
                    if (dynamic != null)
                    {
                        float coef = 0;
                        if (Type.Damage != 0)
                        {
                            coef = totalObjDamage / Type.Damage;
                        }
                        if (Type.Impulse != 0)
                        {
                            coef = Math.Max(coef, totalObjImpulse / Type.Impulse);
                        }

                        if (coef > 1)
                        {
                            coef = 1;
                        }
                        if (coef != 0)
                        {
                            dynamic.AddInfluence(Type.InfluenceType, Type.InfluenceMaxTime * coef, true);
                        }
                    }
                }
            }

            //Create splash for water
            CreateWaterPlaneSplash();

            //Apply damages
            foreach (DamageItem item in damageItems)
            {
                if (!item.dynamic.IsSetForDeletion)
                {
                    item.dynamic.DoDamage(this, item.position, null, item.damage, false);
                }
            }

            mapObjectListAllocator.Free(objects);
            damageItemListAllocator.Free(damageItems);
        }