Beispiel #1
0
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetGlobalVariable(Storage.GenericParameter parameter)
        {
            string     variableName          = parameter.SafeString(0);
            int        setMode               = parameter.SafeInt(1);
            int        numeratorSubjectId    = parameter.SafeInt(2);
            string     numeratorVariableName = parameter.SafeString(1);
            int        defaultValue          = parameter.SafeInt(3);
            FixedFloat percentage            = (numeratorSubjectId == 0 || defaultValue == 0) ? 1 : ((FixedFloat)defaultValue) / 100;

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                int variableValue = GetNumeratorValue(model, numeratorSubjectId, numeratorVariableName, defaultValue, subjectModels);
                variableValue = (int)(variableValue * percentage);

                // Global variable may have references to a team ID, character name, player number, etc
                numeratorVariableName = CharacterConditionsBuilder.ParseVariableValuesInGlobalName(model, numeratorVariableName);
                WorldModel worldModel = StateManager.state.MainModel as WorldModel;
                switch (setMode)
                {
                case 1:                         // add
                    if (worldModel.globalVariables.ContainsKey(variableName))
                    {
                        worldModel.globalVariables[variableName] += variableValue;
                    }
                    else
                    {
                        worldModel.globalVariables[variableName] = variableValue;
                    }
                    break;

                default:                         // set
                    worldModel.globalVariables[variableName] = variableValue;
                    break;
                }
            });
        }
Beispiel #2
0
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildGetHurt(Storage.GenericParameter parameter)
        {
            int    hittersSubjectId      = parameter.SafeInt(1);
            int    numeratorSubjectId    = parameter.SafeInt(2);
            string numeratorVariableName = parameter.SafeString(0);
            int    defaultPercentage     = parameter.SafeInt(3);
            int    facingOptions         = parameter.SafeInt(4);

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                List <GameEntityModel> hitterSubjects = ConditionUtils <GameEntityModel> .GetNonEmptySubjectOrNil(subjectModels, hittersSubjectId);

                if (hitterSubjects == null || hitterSubjects.Count == 0)
                {
                    return;
                }
                FixedFloat percentage = GetNumeratorValue(model, numeratorSubjectId, numeratorVariableName, defaultPercentage, subjectModels);
                percentage /= 100;

                switch (facingOptions)
                {
                case -1:
                    // Use hit data
                    GameEntityController.HurtBasedOnHitData(model, percentage, hitterSubjects);
                    break;

                default:
                    // Use given facing options
                    GameEntityController.HurtBasedOnFacingOptions(model, (HitData.HitFacing)facingOptions, percentage, hitterSubjects);
                    break;
                }
            });
        }
        // Natural reaction: slide along the plane
        protected bool CollisionNaturalReaction(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection)
        {
            bool intersectionChanged = false;

            if (pointModel.position != intersection)
            {
                // Project remaining velocity against the plane
                FixedVector3 normal            = planeModel.normal;
                FixedVector3 pos1              = pointModel.position;
                FixedVector3 pos2              = pointModel.position + normal;
                FixedVector3 pointDeltaPos     = pos2 - pos1;
                FixedVector3 pos1ToOrigin      = planeModel.origin - pos1;
                FixedFloat   dotDeltaPosNormal = FixedVector3.Dot(pointDeltaPos, normal);
                FixedFloat   t = FixedVector3.Dot(pos1ToOrigin, normal) / dotDeltaPosNormal;
                FixedVector3 newIntersection = pos1 + t * pointDeltaPos;
                if (newIntersection != intersection)
                {
                    intersection        = newIntersection;
                    intersectionChanged = true;
                }

                // finally, our new position is the intersection point
                pointModel.position = intersection;
            }

            // in the end, also sum the plane velocity, essential for platforms
            GainPlaneVelocity(world, pointModel, planeModel);

            return(!intersectionChanged);            // if intersection didn't change, it's considered stable
        }
Beispiel #4
0
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetVariable(Storage.GenericParameter parameter)
        {
            string     variableName          = parameter.SafeString(0);
            int        setMode               = parameter.SafeInt(1);
            int        numeratorSubjectId    = parameter.SafeInt(2);
            string     numeratorVariableName = parameter.SafeString(1);
            int        defaultValue          = parameter.SafeInt(3);
            FixedFloat percentage            = (numeratorSubjectId == 0 || defaultValue == 0) ? 1 : ((FixedFloat)defaultValue) / 100;

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                int variableValue = GetNumeratorValue(model, numeratorSubjectId, numeratorVariableName, defaultValue, subjectModels);
                variableValue = (int)(variableValue * percentage);
                switch (setMode)
                {
                case 1:                         // add
                    if (model.customVariables.ContainsKey(variableName))
                    {
                        model.customVariables[variableName] += variableValue;
                    }
                    else
                    {
                        model.customVariables[variableName] = variableValue;
                    }
                    break;

                default:                         // set
                    model.customVariables[variableName] = variableValue;
                    break;
                }
            });
        }
Beispiel #5
0
        // Check collisions between physic models, and apply gravity to them
        public FixedVector3 Raycast(PhysicWorldModel world, FixedVector3 origin, FixedVector3 direction)
        {
            // A raycast long enough
            FixedVector3 target = origin + direction * 99;

            // Get all planes to check collisions
            List <PhysicPlaneModel> allPlanes = GetAllPlanes(world);

            FixedVector3 intersection;

            // Find closest intersection
            FixedVector3 closestIntersection         = new FixedVector3(FixedFloat.MaxValue, FixedFloat.MaxValue, FixedFloat.MaxValue);
            FixedFloat   closestIntersectionDistance = FixedFloat.MaxValue;

            foreach (PhysicPlaneModel planeModel in allPlanes)
            {
                if (PhysicPlaneController.CheckIntersection(planeModel, origin, target, FixedVector3.Zero, out intersection))
                {
                    FixedFloat distance = FixedVector3.Distance(origin, intersection);
                    if (distance < closestIntersectionDistance)
                    {
                        closestIntersectionDistance = distance;
                        closestIntersection         = intersection;
                    }
                }
            }
            return(closestIntersection);
        }
 public void Set(FixedFloat x, FixedFloat y, FixedFloat z)
 {
     this.x = x;
     this.y = y;
     this.z = z;
     magnitudeIsUpToDate = false;
 }
 public FixedVector3(FixedFloat x, FixedFloat y, FixedFloat z)
 {
     this.x              = x;
     this.y              = y;
     this.z              = z;
     magnitude           = 0;
     magnitudeIsUpToDate = false;
 }
 public static FixedVector3 Lerp(FixedVector3 first, FixedVector3 second, FixedFloat blend)
 {
     first.Set(first.x + (second.x - first.x) * blend,
               first.y + (second.y - first.y) * blend,
               first.z + (second.z - first.z) * blend
               );
     return(first);
 }
 public static FixedVector3 Clamp(FixedVector3 vec, FixedVector3 min, FixedVector3 max)
 {
     vec.Set(FixedFloat.Clamp(vec.x, min.x, max.x),
             FixedFloat.Clamp(vec.y, min.y, max.y),
             FixedFloat.Clamp(vec.z, min.z, max.z)
             );
     return(vec);
 }
 public static FixedFloat Angle(FixedVector3 from, FixedVector3 to)
 {
     if (from.Magnitude == FixedFloat.Zero || to.Magnitude == FixedFloat.Zero)
     {
         return(FixedFloat.Zero);
     }
     return(FixedFloat.Acos((FixedVector3.Dot(from, to)) / (from.Magnitude * to.Magnitude)));
 }
Beispiel #11
0
        // Build a point
        static FixedVector3 BuildFixedVector3(Storage.GenericParameter parameter, int startFloatIndex = 0)
        {
            FixedFloat x = parameter.SafeFloat(startFloatIndex);
            FixedFloat y = parameter.SafeFloat(startFloatIndex + 1);
            FixedFloat z = parameter.SafeFloat(startFloatIndex + 2);

            return(new FixedVector3(x, y, z));
        }
Beispiel #12
0
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetMaxInputVelocity(Storage.GenericParameter parameter)
        {
            FixedFloat maxX = parameter.SafeFloat(0);
            FixedFloat maxZ = parameter.SafeFloat(1);

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                model.maxInputVelocity = new FixedVector3(maxX, 0, maxZ);
            });
        }
        public static void HurtBasedOnHitData(GameEntityModel model, FixedFloat damagePercentage, List <GameEntityModel> hitterSubjects = null)
        {
            GameEntityController controller = model.Controller() as GameEntityController;

            if (controller.lastHurts.Count > 0)
            {
                HitData hitData = controller.lastHurts[0].hitData;
                HurtBasedOnFacingOptions(model, hitData.facingOptions, damagePercentage, hitterSubjects);
            }
        }
Beispiel #14
0
        public static FixedFloat CollisionZForce(GameEntityModel model)
        {
            PhysicPointModel pointModel = GameEntityController.GetPointModel(model);

            if (pointModel == null)
            {
                return(FixedFloat.Zero);
            }
            return(FixedFloat.Abs(pointModel.collisionInpact.Z));
        }
        public static FixedVector3 operator /(FixedVector3 vec, FixedFloat scale)
        {
            FixedFloat mult = FixedFloat.One / scale;

            //		if (mult == 0){
            //			UnityEngine.Debug.Log("Precision error: DIV");
            //		}
            vec.Set(vec.x * mult, vec.y * mult, vec.z * mult);
            return(vec);
        }
        public static FixedVector3 ClampMagnitude(FixedVector3 vec, FixedFloat maxMagnitude)
        {
            FixedFloat magnitude = vec.Magnitude;

            if (magnitude > maxMagnitude)
            {
                FixedFloat scaleFactor = magnitude / maxMagnitude;
                vec *= scaleFactor;
            }
            return(vec);
        }
        // Offsets a box, used to apply world coordinates of the entity, and it's orientation
        private Box OffsettedBox(Box box, FixedVector3 offset, bool facingRight)
        {
            FixedVector3 newPos1 = box.pointOne;
            FixedVector3 newPos2 = box.pointTwo;

            if (!facingRight)
            {
                // swap and make symetric
                FixedFloat tmp = -newPos1.X;
                newPos1.X = -newPos2.X;
                newPos2.X = tmp;
            }
            return(new Box(offset + newPos1, offset + newPos2));
        }
        // CompareWithNumerator, FixedFloat version
        private static bool CompareWithNumerator(
            GameEntityModel mainModel,
            int numeratorSubjectId,
            string numeratorSubjectVarName,
            FixedFloat comparisonValue,
            FixedFloat staticComparisonValue,
            ConditionUtils <GameEntityModel> .ComparisonOperation comparisonOperator,
            List <GameEntityModel>[] subjectModels
            )
        {
            // no subject
            if (numeratorSubjectId == 0)
            {
                return(ConditionUtils <GameEntityModel> .Compare(comparisonOperator, comparisonValue, staticComparisonValue));
            }
            // global variable
            if (numeratorSubjectId == 1)
            {
                // Global variable may have references to a team ID, character name, player number, etc
                numeratorSubjectVarName = ParseVariableValuesInGlobalName(mainModel, numeratorSubjectVarName);

                int        globalVariableValue = 0;
                WorldModel worldModel          = StateManager.state.MainModel as WorldModel;
                worldModel.globalVariables.TryGetValue(numeratorSubjectVarName, out globalVariableValue);
                return(ConditionUtils <GameEntityModel> .Compare(comparisonOperator, comparisonValue, (FixedFloat)globalVariableValue));
            }
            // subject variable
            numeratorSubjectId -= 2;
            List <GameEntityModel> comparisonSubject = ConditionUtils <GameEntityModel> .GetNonEmptySubjectOrNil(subjectModels, numeratorSubjectId);

            if (comparisonSubject == null || comparisonSubject.Count == 0)
            {
                return(false);
            }
            // compare each model's velocity with each comparison subject variable, return true if all pass
            int variableValue;

            foreach (GameEntityModel comparisonModel in comparisonSubject)
            {
                if (!comparisonModel.customVariables.TryGetValue(numeratorSubjectVarName, out variableValue))
                {
                    return(false);
                }
                if (!ConditionUtils <GameEntityModel> .Compare(comparisonOperator, comparisonValue, (FixedFloat)variableValue))
                {
                    return(false);
                }
            }
            return(true);
        }
        // Collision reaction.
        // Return true if collision is considered stable (no position modifications occured)
        public virtual bool OnCollision(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection)
        {
            //		if (pointModel.position == intersection){
            //			// Nothing to change
            //			return true;
            //		}

            // Pick one of two methods depending on the plane's normal angle against up vector
            FixedFloat planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Up);

            // If it's too much inclined, use natural reaction
            if (planeAngle > FixedFloat.PI * 0.4)
            {
                // check direction against 4 walls
                FixedFloat maxDelta = FixedFloat.PI * 0.4;
                planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Left);
                if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta)
                {
                    // collision in the X axis
                    FixedFloat inpactX = pointModel.GetVelocity().X - planeModel.GetVelocity().X;
                    if (FixedFloat.Abs(inpactX) > FixedFloat.Abs(newCollisionInpact.X))
                    {
                        newCollisionInpact.X = inpactX;
                    }
                }
                planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Forward);
                if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta)
                {
                    // collision in the Z axis
                    FixedFloat inpactZ = pointModel.GetVelocity().Z - planeModel.GetVelocity().Z;
                    if (FixedFloat.Abs(inpactZ) > FixedFloat.Abs(newCollisionInpact.Z))
                    {
                        newCollisionInpact.Z = inpactZ;
                    }
                }
                return(CollisionNaturalReaction(world, pointModel, planeModel, intersection));
            }
            else
            {
                // Otherwise we're hitting the ground, do not slide
                FixedFloat inpactY = pointModel.GetVelocity().Y - planeModel.GetVelocity().Y;
                if (FixedFloat.Abs(inpactY) > FixedFloat.Abs(newCollisionInpact.Y))
                {
                    newCollisionInpact.Y = inpactY;
                }
                // We use a lot of arguments here just to avoid recalculating them
                return(CollisionGroundReaction(world, pointModel, planeModel, intersection));
            }
        }
Beispiel #20
0
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildPausePhysics(Storage.GenericParameter parameter)
        {
            int        numeratorSubjectId    = parameter.SafeInt(1);
            string     numeratorVariableName = parameter.SafeString(0);
            int        defaultValue          = parameter.SafeInt(2);
            FixedFloat percentage            = (numeratorSubjectId == 0 || defaultValue == 0) ? 1 : ((FixedFloat)defaultValue) / 100;

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                int numeratorValue = GetNumeratorValue(model, numeratorSubjectId, numeratorVariableName, defaultValue, subjectModels);
                int pauseValue = (int)(numeratorValue * percentage);
                if (pauseValue > 0)
                {
                    GameEntityController.PausePhysics(model, pauseValue);
                }
            });
        }
Beispiel #21
0
        // 'walk'
        private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetAnimation(Storage.GenericParameter parameter)
        {
            string     animationName  = parameter.SafeString(0);
            FixedFloat transitionTime = parameter.SafeFloat(0);

            return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){
                AnimationModel animModel = StateManager.state.GetModel(model.animationModelId) as AnimationModel;
                if (animModel == null)
                {
                    return;
                }
                animModel.SetNextAnimation(animationName, 0);
                AnimationView view = animModel.View() as AnimationView;
                if (view != null)
                {
                    view.transitionTime = (float)transitionTime;
                }
            });
        }
        // Auxiliar method to get Oriented Axis
        private static FixedFloat getOrientedAxisValue(FixedVector3 axis, Orientation orientation, bool useModule)
        {
            FixedFloat axisValue = FixedFloat.Zero;

            switch (orientation)
            {
            case Orientation.horizontal: axisValue = axis.X; break;

            case Orientation.vertical:   axisValue = axis.Y; break;

            case Orientation.z:                      axisValue = axis.Z; break;

            case Orientation.any:            axisValue = axis.Magnitude; break;
            }
            if (useModule)
            {
                axisValue = FixedFloat.Abs(axisValue);
            }
            return(axisValue);
        }
        // Velocity
        private static EventCondition <GameEntityModel> .EvaluationDelegate BuildVelocity(Storage.GenericParameter parameter, out int keyFrame, Storage.CharacterAnimation animation)
        {
            keyFrame = InvalidKeyframe;
            // Read orientation, operator, numerator subject, numerator var, number, module
            Orientation orientation = (Orientation)parameter.SafeInt(1);

            ConditionUtils <GameEntityModel> .ComparisonOperation comparisonOperator = (ConditionUtils <GameEntityModel> .ComparisonOperation)parameter.SafeInt(2);
            int        numeratorSubjectId      = parameter.SafeInt(3);
            string     numeratorSubjectVarName = parameter.SafeString(0);
            FixedFloat staticComparisonValue   = parameter.SafeFloat(0);
            bool       useModule = parameter.SafeBool(1);

            // return delegate
            return(delegate(GameEntityModel mainModel, List <GameEntityModel>[] subjectModels){
                PhysicPointModel pointModel = StateManager.state.GetModel(mainModel.physicsModelId) as PhysicPointModel;
                if (pointModel == null)
                {
                    return false;
                }
                FixedFloat velocityValue = getOrientedAxisValue(pointModel.GetVelocity(), orientation, useModule);
                return CompareWithNumerator(mainModel, numeratorSubjectId, numeratorSubjectVarName, velocityValue, staticComparisonValue, comparisonOperator, subjectModels);
            });
        }
        // Compute the intersection point against a line segment
        public static bool CheckIntersection(PhysicPlaneModel planeModel, FixedVector3 pos1, FixedVector3 pos2, FixedVector3 stepTolerance, out FixedVector3 intersection)
        {
            // plane may be moving, sum velocity to initial point position
            pos1 += planeModel.GetVelocity();

            // Check bounding box intersection, including step tolerance
            if (!BoxIntersection(planeModel, pos1 + stepTolerance, pos2))
            {
                intersection = FixedVector3.Zero;
                return(false);
            }

            // check collision with the hiperplane
            FixedVector3 pointDeltaPos = pos2 - pos1;

            if (pointDeltaPos.Magnitude == 0)
            {
                // The point is not moving relatively to the plane
                intersection = FixedVector3.Zero;
                return(false);
            }
            FixedVector3 pos1ToOrigin      = planeModel.origin - pos1;
            FixedFloat   dotDeltaPosNormal = FixedVector3.Dot(pointDeltaPos, planeModel.normal);

            if (dotDeltaPosNormal >= 0)
            {
                // Point moving away from the plane
                intersection = FixedVector3.Zero;
                return(false);
            }

            // Find intersection location in the deltapos vector
            FixedFloat t = FixedVector3.Dot(pos1ToOrigin, planeModel.normal) / dotDeltaPosNormal;

            // a small delta due to precision errors
            // based on deltaPos magnitude (the smaller the magnitude the higher the error)
            FixedFloat error = 0.01 / pointDeltaPos.Magnitude;

            if (t < -error)
            {
                // falling through the plane, try step tolerance to recover
                pos1             += stepTolerance;
                pointDeltaPos     = pos2 - pos1;
                pos1ToOrigin      = planeModel.origin - pos1;
                dotDeltaPosNormal = FixedVector3.Dot(pointDeltaPos, planeModel.normal);
                t     = FixedVector3.Dot(pos1ToOrigin, planeModel.normal) / dotDeltaPosNormal;
                error = 0.01 / pointDeltaPos.Magnitude;
            }
            // give some tolerance
            if (t < -error || t > 1 + error)
            {
                // not colliding
                intersection = FixedVector3.Zero;
                return(false);
            }
            intersection = pos1 + t * pointDeltaPos;

            // Check if intersection point is inside the plane
            FixedFloat   anglesSum    = FixedFloat.Zero;
            FixedVector3 originVector = planeModel.origin - intersection;
            FixedVector3 vec1         = originVector;
            FixedVector3 vec2         = FixedVector3.Zero;
            FixedVector3 vertex;

            for (int i = 0; i < planeModel.offsets.Count; ++i)
            {
                vertex     = planeModel.GetPointFromOffsetId(i);
                vec2       = vertex - intersection;
                anglesSum += FixedVector3.Angle(vec1, vec2);
                vec1       = vec2;
            }
            // last vertex with origin
            anglesSum += FixedVector3.Angle(vec2, originVector);

            // a small delta due to precision errors
            return(FixedFloat.Abs(anglesSum - FixedFloat.TwoPI) < 0.2);
        }
Beispiel #25
0
 public FixedFloat NextFloat(FixedFloat min, FixedFloat max)
 {
     return(min + NextFloat() * (max - min));
 }
Beispiel #26
0
 // Random Fixed Float between [0, 1]
 public FixedFloat NextFloat()
 {
     // The magic number below is 1/(2^32 + 2).
     // The result is strictly between 0 and 1.
     return(FixedFloat.Create((NextUnsignedInt() + 1.0) * 2.328306435454494e-10));
 }
        public static void HurtBasedOnFacingOptions(GameEntityModel model, HitData.HitFacing facingOptions, FixedFloat damagePercentage, List <GameEntityModel> hitterSubjects = null)
        {
            // Facing
            if (facingOptions == HitData.HitFacing.hitterLocation || facingOptions == HitData.HitFacing.inverseHitterLocation)
            {
                FaceToHitterLocation(model, facingOptions == HitData.HitFacing.inverseHitterLocation);
            }
            else if (facingOptions == HitData.HitFacing.hitterOrientation || facingOptions == HitData.HitFacing.inverseHitterOrientation)
            {
                FaceToHitterDirection(model, facingOptions == HitData.HitFacing.inverseHitterOrientation);
            }
            else
            {
                // None, nothing to do
            }

            // Damage!
            if (damagePercentage != 0 && model.customVariables.ContainsKey("energy"))
            {
                GameEntityController controller = model.Controller() as GameEntityController;
                foreach (HitInformation hitInfo in controller.lastHurts)
                {
                    if (hitterSubjects == null || hitterSubjects.Find(x => x.Index == hitInfo.entityId) != null)
                    {
                        int damageValue = (int)(hitInfo.hitData.damage * damagePercentage);
                        if (damageValue == 0)
                        {
                            damageValue = 1;
                        }
                        model.customVariables["energy"] -= damageValue;
                    }
                }
            }
        }