Esempio n. 1
0
    /// <summary>
    /// Make this character perform the event specified in the given object
    /// </summary>
    public void PerformEvent(Brawler.Event e)
    {
        if (e == null)
        {
            Debug.LogError("Event passed to CharacterControl.PerformEvent() is null for character " + character.name);
            return;
        }

        // Stores true if the event specifies a starting time
        bool requiresStartTime = (e.type != Brawler.EventType.None);
        // Holds true if the event requires a duration to be specified
        bool requiresDuration = (e.type == Brawler.EventType.SlowMotion || e.type == Brawler.EventType.Force || e.type == Brawler.EventType.ColorFlash ||
                                 e.type == Brawler.EventType.FreezeAnimation || e.type == Brawler.EventType.ScreenShake || e.type == Brawler.EventType.Tween ||
                                 e.type == Brawler.EventType.Ghosting);

        // The starting time and duration of the event, in seconds
        float startTime = 0;
        float duration  = 0;

        // If the event requires a starting time or duration to be specified, compute them and store them in their respective variables.
        if (requiresStartTime)
        {
            startTime = GetStartTime(e.startTime);
        }
        if (requiresDuration)
        {
            duration = GetDuration(e.duration, startTime);
        }

        // Call a coroutine. Start the given event in 'startTime' seconds. The event will last 'duration' seconds
        StartCoroutine(PerformEventCoroutine(e, startTime, duration));
    }
Esempio n. 2
0
    private IEnumerator PlayTween(Brawler.Event e)
    {
        float startTime = 0;

        if (e.startTime.type == DurationType.Frame)
        {
            startTime = e.startTime.nFrames / CharacterAnimator.FRAME_RATE;
        }
        else
        {
            startTime = e.startTime.seconds;
        }

        Debug.Log("Play tween at " + startTime + " seconds");

        yield return(new WaitForSeconds(startTime));

        float duration;

        if (e.duration.type == DurationType.Frame)
        {
            duration = e.duration.nFrames / CharacterAnimator.FRAME_RATE;
        }
        else
        {
            duration = e.duration.seconds;
        }

        Debug.Log("Play tween for " + duration + " seconds");

        tweener.PerformEvent(e.tweenEvent, duration);
    }
Esempio n. 3
0
 /// <summary>
 /// Update the given event. Updates the event's member variables to the correct info. For instance,
 /// if the event's type is set to 'CameraMovement', the target position of the camera must be updated.
 /// For instance, if the camera must move to the position of the targetted enemy, the event must be
 /// updated to store the Transform or position of this enemy
 /// </summary>
 private void UpdateEvent(Brawler.Event e)
 {
     // If the event is a CameraMovement event
     if (e.type == Brawler.EventType.CameraMovement)
     {
         // If the camera movement requires the camera to move to the location of the event which triggered the event
         if (e.cameraMovement.target == TargetPosition.Self)
         {
             // Set the camera to follow this character's Transform
             e.cameraMovement.targetTransform = character.Transform;
         }
         // Else, if the camera needs to move to the position of the object that was touched
         else if (e.cameraMovement.target == TargetPosition.TouchedObject)
         {
             // Set the camera to follow the targetObject which is targetted by the action that activated this event
             e.cameraMovement.targetTransform = targetObject.transform;
         }
         // Else, if the camera needs to move to the position where the user touched to activate this event
         else if (e.cameraMovement.target == TargetPosition.TouchedPosition)
         {
             // Tell the camera to move to the action's 'targetPosition', the position where the user last touched
             e.cameraMovement.targetPosition = targetPosition;
         }
     }
 }
Esempio n. 4
0
 /// <summary>
 /// Creates a new force instance.
 /// </summary>
 /// <param name="createOnCompleteEvent">If set to <c>true</c> create an onComplete event. This is set to true
 /// by default. This parameter is set to false when the Force is created inside a ForceEvent instance. In this
 /// case, creating an 'onComplete' Event would cause infinite recursion. This is because each ForceEvent holds
 /// an instance of a Force, which creates a new 'Brawler.Event'. Then, the Brawler.Event creates a new ForceEvent,
 /// which then creates a new Force, and the recursion never stops. Therefore, if this Force is a member variable
 /// inside a ForceEvent instance, the onComplete event should not be created.
 /// </param>
 public Force(bool createOnCompleteEvent)
 {
     if (createOnCompleteEvent)
     {
         // Create a new event which will be triggered when the force is done being applied
         onCompleteEvent = new Brawler.Event();
     }
 }
Esempio n. 5
0
 /// <summary>
 /// Returns a deep copy of the given array of events. A deep copy creates a duplicate of each
 /// element in the given array, so that the two arrays don't share any references.
 /// </summary>
 public static Brawler.Event[] DeepCopy(Brawler.Event[] array)
 {
     Brawler.Event[] copy = new Brawler.Event[array.Length];
     for (int i = 0; i < array.Length; i++)
     {
         copy[i] = new Brawler.Event(array[i]);
     }
     return(copy);
 }
Esempio n. 6
0
    /// <summary>
    /// Update the action's events so that their member variables correctly correspond to the action's
    /// current state. For instance, some CameraMovement events require the camera to look at the position
    /// which was touched when the event was triggered. In this case, the touched position of each CameraMovement
    /// has to be updated to correspond to the position of the touch that triggered the CameraMovement event.
    /// </summary>
    public void UpdateEvents()
    {
        // Cycle through each 'onStartEvent' in the action
        for (int i = 0; i < onStartEvents.Length; i++)
        {
            Brawler.Event e = onStartEvents[i];

            // Update the event so that its member variables are set to the correct information
            UpdateEvent(e);
        }

        // Cycle through each 'Force' applied in the action
        for (int i = 0; i < forces.Length; i++)
        {
            // Retrieve the force's 'OnComplete' event
            Brawler.Event e = forces[i].onCompleteEvent;

            // Update the event so that its member variables are set to the correct information
            UpdateEvent(e);
        }

        // Cycle through each 'onStartEvent' in the action
        for (int i = 0; i < hitBoxes.Length; i++)
        {
            // Stores the events performed on the same character that performed this action.
            Brawler.Event[] selfEvents = hitBoxes[i].hitInfo.selfEvents;

            // Cycle through each 'selfEvent' for the hit
            for (int j = 0; j < selfEvents.Length; j++)
            {
                Brawler.Event e = selfEvents[j];

                // Update the event so that its member variables are set to the correct information
                UpdateEvent(e);
            }

            // Stores the events performed by the adversary hit by the hit box.
            Brawler.Event[] adversaryEvents = hitBoxes[i].hitInfo.adversaryEvents;

            // Cycle through each event for the adversary hit by this hit box has to perform
            for (int j = 0; j < adversaryEvents.Length; j++)
            {
                Brawler.Event e = adversaryEvents[j];

                // Update the event so that its member variables are set to the correct information
                UpdateEvent(e);
            }
        }
    }
Esempio n. 7
0
    /// <summary>
    /// Creates a new force instance given a template.
    /// </summary>
    /// <param name="createOnCompleteEvent">If set to <c>true</c> create an onComplete event. This is set to true
    /// by default. This parameter is set to false when the Force is created inside a ForceEvent instance. In this
    /// case, creating an 'onComplete' Event would cause infinite recursion. This is because each ForceEvent holds
    /// an instance of a Force, which creates a new 'Brawler.Event'. Then, the Brawler.Event creates a new ForceEvent,
    /// which then creates a new Force, and the recursion never stops. Therefore, if this Force is a member variable
    /// inside a ForceEvent instance, the onComplete event should not be created.
    /// </param>
    public Force(Force template, bool createOnCompleteEvent)
    {
        if (createOnCompleteEvent)
        {
            // Create a deep copy of the event
            onCompleteEvent = new Brawler.Event(template.onCompleteEvent);
        }

        // Copy the templates values into this new instance
        forceType = template.forceType;
        velocity  = template.velocity;
        relativeToFacingDirection = template.relativeToFacingDirection;
        target = template.target;
        customTargetPosition = template.customTargetPosition;
        faceTarget           = template.faceTarget;
        startTime            = template.startTime;
        duration             = template.duration;
    }
Esempio n. 8
0
    /// <summary>
    /// Called when the force is done being applied on the character. If the force has any events that should
    /// occur once it has ended, they will be performed here.
    /// </summary>
    public void OnForceEnd(Force force)
    {
        // Stores the action that should be completed once the given force is done being applied
        Brawler.Event eventOnComplete = force.onCompleteEvent;

        // Perform the event if it exists
        if (eventOnComplete != null)
        {
            // Perform the event that should be performed once the force is done being applied.
            character.CharacterControl.PerformEvent(eventOnComplete);
        }

        // If the given force is the same as the force being currently applied on the character
        if (currentForce == force)
        {
            // Nullify the current force acting on the character, since the force has just finished being applied if this statement is reached.
            currentForce = null;
        }
    }
Esempio n. 9
0
    /// <summary>
    /// Called when this hit box hits another character. This method is called from the CharacterCollider.OnCollision()
    /// method when a hit box enters a character's collider. This method performs necessary actions, such as inflicting
    /// damage on the character and playing an impact sound.
    /// </summary>
    public void OnHit(Character adversary)
    {
        // Stores the 'HitInfo' instance which dictates how much damage to deal when this HitBox hits an adversary
        HitInfo hitInfo = hitBoxInfo.hitInfo;

        // Inform the CharacterStats component that he was hit by a hit box. Inflicts damage to the character hit by this hit box
        adversary.CharacterStats.OnHit(hitInfo, hitBoxInfo.Character);

        // Generate a knockback force on the adversary. Wait until 'freezeFrames' frames have passed before applying the knockback.
        Knockback(adversary, hitInfo.freezeFrames);

        // Freeze the characters' animations for a small amount of time to add impact to the hit
        FreezeAnimations(hitBoxInfo.Character, adversary);

        // Cycle through the events in the 'hitInfo.selfEvents' array. These events are supposed to be executed by the character which
        // generated this hit
        for (int i = 0; i < hitInfo.selfEvents.Length; i++)
        {
            // Cache the event being cycled through
            Brawler.Event e = hitInfo.selfEvents[i];

            // Make the character that hit the adversary perform the events specified in the 'hitInfo.events' array. These events
            // are meant to be triggered when the hit is registered.
            hitBoxInfo.Character.CharacterControl.PerformEvent(hitInfo.selfEvents[i]);
        }

        // Cycle through the events in the 'hitInfo.adversaryEvents' array. These events are supposed to be executed by the character which
        // received the hit
        for (int i = 0; i < hitInfo.adversaryEvents.Length; i++)
        {
            // Make the character that got hit (the adversary) perform the events specified in the 'hitInfo.adversaryEvents' array. These events
            // are meant to be triggered when the hit is registered.
            adversary.CharacterControl.PerformEvent(hitInfo.adversaryEvents[i]);
        }

        // Increment the combo for the character belonging to this hit box. This character just hit an opponent and must thus increase his combo
        hitBoxInfo.Character.CharacterStats.IncrementCombo();

        // Play one of the impact sounds associated to this hit box. This plays a sound right when the hit box hits a target
        hitBoxInfo.Character.Sound.PlayRandomSound(hitBoxInfo.Action.impactSounds);
    }
Esempio n. 10
0
    /** Displays a foldout of a list of events */
    public Brawler.Event[] Display()
    {
        showFoldout = EditorGUILayout.Foldout(showFoldout, title + " (" + events.Length + ")");

        if (showFoldout)
        {
            EditorGUILayout.BeginVertical();
            {
                EditorGUI.indentLevel++;

                // Cycle through each event
                for (int i = 0; i < events.Length; i++)
                {
                    Brawler.Event e = events[i];

                    EditorGUILayout.BeginHorizontal();
                    {
                        e.type = (Brawler.EventType)EditorGUILayout.EnumPopup("Type:", e.type);
                        if (GUILayout.Button("X", GUILayout.Width(40)))
                        {
                            this.events           = ArrayUtils.RemoveAt <Brawler.Event> (this.events, i);
                            showStartTimeFoldouts = ArrayUtils.RemoveAt <bool>(showStartTimeFoldouts, i);
                            showDurationFoldouts  = ArrayUtils.RemoveAt <bool>(showDurationFoldouts, i);

                            continue;
                        }
                    }
                    EditorGUILayout.EndHorizontal();

                    if (e.type == Brawler.EventType.PerformAction)
                    {
                        // Select an action
                        e.actionToPerform = (ActionScriptableObject)EditorGUILayout.ObjectField("Action:", e.actionToPerform,
                                                                                                typeof(ActionScriptableObject), false);
                    }
                    else if (e.type == Brawler.EventType.PerformBasicAction)
                    {
                        // Select a basic action
                        e.basicActionToPerform = (BasicActionType)EditorGUILayout.EnumPopup("Basic action:", e.basicActionToPerform);
                    }
                    else if (e.type == Brawler.EventType.CameraMovement)
                    {
                        // Set the camera settings
                        e.cameraMovement.target = (TargetPosition)EditorGUILayout.EnumPopup("Target position:", e.cameraMovement.target);
                        if (e.cameraMovement.target == TargetPosition.CustomPosition)
                        {
                            e.cameraMovement.targetPosition = EditorGUILayout.Vector2Field("Position to move to:", e.cameraMovement.targetPosition);
                        }
                        e.cameraMovement.zoom        = EditorGUILayout.FloatField("Zoom:", e.cameraMovement.zoom);
                        e.cameraMovement.cameraSpeed = EditorGUILayout.FloatField("Camera speed:", e.cameraMovement.cameraSpeed);
                    }
                    else if (e.type == Brawler.EventType.SoundEffect)
                    {
                        // Select the sound effect to play when the event is triggered
                        e.soundEffect = (AudioClip)EditorGUILayout.ObjectField("Sound effect:", e.soundEffect, typeof(AudioClip), false);
                    }
                    else if (e.type == Brawler.EventType.SlowMotion)
                    {
                        e.slowMotion.timeScale = EditorGUILayout.Slider("Time scale:", e.slowMotion.timeScale, 0.001f, 1.0f);
                    }
                    else if (e.type == Brawler.EventType.ParticleEffect)
                    {
                        // Select a particle effect
                        e.particleEvent.effect     = (ParticleEffect)EditorGUILayout.EnumPopup("Particle Effect:", e.particleEvent.effect);
                        e.particleEvent.spawnPoint = (ParticleSpawnPoint)EditorGUILayout.EnumPopup("Spawn Point:", e.particleEvent.spawnPoint);
                        e.particleEvent.offset     = EditorGUILayout.Vector3Field("Offset:", e.particleEvent.offset);
                    }
                    else if (e.type == Brawler.EventType.Force)
                    {
                        Force force = e.forceEvent;

                        // Select a force type
                        force.forceType = (ForceType)EditorGUILayout.EnumPopup("Force Type:", force.forceType);
                        switch (force.forceType)
                        {
                        case ForceType.Velocity:
                            force.velocity = EditorGUILayout.Vector2Field("Velocity:", force.velocity);
                            force.relativeToFacingDirection = EditorGUILayout.Toggle("Relative to facing direction?", force.relativeToFacingDirection);
                            break;

                        case ForceType.Position:
                            force.target = (TargetPosition)EditorGUILayout.EnumPopup("Target Position:", force.target);
                            if (force.target == TargetPosition.CustomPosition)
                            {
                                force.customTargetPosition = EditorGUILayout.Vector2Field("Custom Position:", force.customTargetPosition);
                            }
                            force.faceTarget = EditorGUILayout.Toggle("Face target?", force.faceTarget);
                            break;
                        }
                    }
                    else if (e.type == Brawler.EventType.ColorFlash)
                    {
                        ColorFlash colorFlash = e.colorFlash;

                        // Edit the color-flashing event
                        colorFlash.color = EditorGUILayout.ColorField("Color:", colorFlash.color);

                        colorFlash.renderInFront = EditorGUILayout.Toggle("Render in front", colorFlash.renderInFront);
                    }
                    else if (e.type == Brawler.EventType.Ghosting)
                    {
                        GhostEffect ghostEffect = e.ghostEffect;

                        // Edit the ghosting effect
                        ghostEffect.color = EditorGUILayout.ColorField("Color:", ghostEffect.color);

                        ghostEffect.renderInFront = EditorGUILayout.Toggle("Render in front", ghostEffect.renderInFront);
                    }
                    else if (e.type == Brawler.EventType.ScreenShake)
                    {
                        ScreenShake screenShake = e.screenShake;

                        // Modify the screen shake settings
                        screenShake.speed     = EditorGUILayout.FloatField("Speed:", screenShake.speed);
                        screenShake.magnitude = EditorGUILayout.FloatField("Magnitude:", screenShake.magnitude);
                    }
                    else if (e.type == Brawler.EventType.Tween)
                    {
                        TweenEvent tweenEvent = e.tweenEvent;

                        TweenEventEditor(tweenEvent);
                    }

                    // Stores true if the event being edited requires a starting time to be specified
                    bool editStartTime = (e.type != Brawler.EventType.None);

                    // If we require to edit the duration
                    if (editStartTime)
                    {
                        // "Starting Time" foldout
                        showStartTimeFoldouts[i] = EditorGUILayout.Foldout(showStartTimeFoldouts[i], "Starting Time");

                        if (showStartTimeFoldouts[i])
                        {
                            ActionEditor.StartTimeFoldout(e.startTime);
                        }
                    }

                    // Stores true if the event being edited requires a 'duration' to be specified
                    bool editDuration = (e.type == Brawler.EventType.SlowMotion || e.type == Brawler.EventType.Force || e.type == Brawler.EventType.ColorFlash ||
                                         e.type == Brawler.EventType.FreezeAnimation || e.type == Brawler.EventType.ScreenShake || e.type == Brawler.EventType.Tween ||
                                         e.type == Brawler.EventType.Ghosting);

                    // If we require to edit the duration
                    if (editDuration)
                    {
                        // "Duration" foldout
                        showDurationFoldouts[i] = EditorGUILayout.Foldout(showDurationFoldouts[i], "Duration");

                        if (showDurationFoldouts[i])
                        {
                            ActionEditor.DurationFoldout(e.duration);
                        }
                    }

                    EditorGUILayout.Space();
                }

                // Add event ("+") button
                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.LabelField("");
                    // Add new event
                    if (GUILayout.Button("+", GUILayout.Width(40)))
                    {
                        this.events           = ArrayUtils.Add <Brawler.Event>(this.events, new Brawler.Event());
                        showStartTimeFoldouts = ArrayUtils.Add <bool>(showStartTimeFoldouts, false);
                        showDurationFoldouts  = ArrayUtils.Add <bool>(showDurationFoldouts, false);
                    }
                }
                EditorGUILayout.EndHorizontal();

                EditorGUI.indentLevel--;
            }
            EditorGUILayout.EndVertical();
        }

        // Return the modified array of events
        return(events);
    }
Esempio n. 11
0
    /// <summary>
    /// Initialializes the basic moves' default properties. Accepts the Character which is performing these basic actions.
    /// This method is called in the 'ActionSetEditor.OnEnabled()' method every time the basic actions need to be edited.
    /// Ensures that, if ever a new basic action is created or edited, it is initialized with the correct properties
    /// </summary>
    public void Init()
    {
        // Sets the default properties for the idle action
        idle.name       = "Idle";
        idle.cancelable = true;
        idle.animationSequences[0].loopLastAnimation = true;
        basicActionsDictionary.Insert(BasicActionType.Idle, idle);

        // Sets the default properties for the walking action
        walk.name = "Walk";
        // Create the force which will make the player walk
        Force walkForce = new Force();

        // Start walking immediately
        walkForce.startTime.type    = DurationType.Frame;
        walkForce.startTime.nFrames = 0;
        walkForce.duration.type     = DurationType.UsePhysicsData;
        // Move to the user's cursor
        walkForce.forceType = ForceType.Position;
        walkForce.target    = TargetPosition.TouchedPosition;
        // Return to idle once character has reached his move target
        walkForce.onCompleteEvent.type = Brawler.EventType.PerformBasicAction;
        walkForce.onCompleteEvent.basicActionToPerform = BasicActionType.Idle;
        walkForce.faceTarget = true;
        walk.forces          = new Force[] { walkForce };
        // Extra properties
        walk.cancelable     = true;
        walk.listensToInput = true;
        walk.inputType      = InputType.Click;
        walk.inputRegion    = InputRegion.Any;
        walk.animationSequences[0].loopLastAnimation = true;
        basicActionsDictionary.Insert(BasicActionType.Walk, walk);

        // Sets the default properties for the idle action
        hit.name               = "Hit";
        hit.cancelable         = true;
        hit.overrideCancelable = true;
        basicActionsDictionary.Insert(BasicActionType.Hit, hit);

        // Set the default properties for the 'knockback' action
        knockback.name = "Knockback";
        // Create the force which will make the character be knocked back

        /*Force knockbackForce = new Force();
         * // Start the knockback force immediately
         * knockbackForce.startTime.type = DurationType.Frame;
         * knockbackForce.startTime.nFrames = 0;
         * knockbackForce.duration.type = DurationType.UsePhysicsData;
         * knockbackForce.forceType = ForceType.Velocity;
         * knockbackForce.target = TargetPosition.TouchedPosition;
         * // Return to idle once character has reached his move target
         * walkForce.onCompleteEvent.type = Brawler.EventType.PerformBasicAction;
         * walkForce.onCompleteEvent.basicActionToPerform = BasicAction.Idle;
         * walkForce.faceTarget = true;
         * walk.forces = new Force[]{walkForce};*/
        knockback.cancelable         = false;
        knockback.overrideCancelable = true;
        basicActionsDictionary.Insert(BasicActionType.Knockback, knockback);

        // Set the default properties for the 'rising after knockback' action
        knockbackRise.name       = "Knockback_Rise";
        knockbackRise.cancelable = false;
        basicActionsDictionary.Insert(BasicActionType.KnockbackRise, knockbackRise);

        // Set the default properties for the 'die' action
        death.name = "Death";
        // The event which makes this character die after the death animation finishes playing.
        Brawler.Event deathEvent = new Brawler.Event();
        deathEvent.type = Brawler.EventType.Die;
        // Kill the character once the death animation is complete
        deathEvent.startTime.type = DurationType.WaitForAnimationComplete;
        deathEvent.startTime.animationToWaitFor = 0;
        death.onStartEvents = new Brawler.Event[1] {
            deathEvent
        };
        death.cancelable = false;
        basicActionsDictionary.Insert(BasicActionType.Death, death);

        // Set the default properties for the 'DeathKnockback' action
        deathKnockback.name               = "DeathKnockback";
        deathKnockback.cancelable         = false;
        deathKnockback.overrideCancelable = true;
        basicActionsDictionary.Insert(BasicActionType.DeathKnockback, deathKnockback);

        // Set the default properties for the 'Null' action
        nullAction.name = "NullAction";
        // Loop the 'Null' animation, freezing the character's animation until he performs a new action
        nullAction.animationSequences[0].loopLastAnimation = true;
        basicActionsDictionary.Insert(BasicActionType.NullAction, nullAction);
    }
Esempio n. 12
0
    /// <summary>
    /// Performs the given event. The event will start at 'startTime' seconds, and last a total of 'duration' seconds.
    /// </summary>
    /// <returns>The event coroutine.</returns>
    /// <param name="startTime">The time in seconds relative to the time this function is called at which the event
    /// starts. Some events don't require this field.</param>
    /// <param name="duration">The time in seconds that this event lasts. Some events don't require this field, and thus
    /// this value is ignored.</param>
    private IEnumerator PerformEventCoroutine(Brawler.Event e, float startTime, float duration)
    {
        // Wait 'startTime' seconds before performing the given event
        yield return(StartCoroutine(Wait(startTime)));

        Debug.Log("Perform event: " + e.type.ToString() + " on " + character.name + " in " + startTime + " seconds");

        // Perform the given event.
        if (e.type == Brawler.EventType.PerformAction)
        {
            PerformAction(e.actionToPerform);
        }
        else if (e.type == Brawler.EventType.PerformBasicAction)
        {
            PerformAction(e.basicActionToPerform);
        }
        else if (e.type == Brawler.EventType.CameraMovement)
        {
            Debug.Log("Game Camera: " + GameManager.Instance.GameCamera);
            // Apply the camera movement to the main game camera.
            GameManager.Instance.GameCamera.ApplyCameraMovement(e.cameraMovement);
        }
        else if (e.type == Brawler.EventType.SoundEffect)
        {
            // Play the sound effect specified by the event
            character.Sound.Play(e.soundEffect);
        }
        else if (e.type == Brawler.EventType.SlowMotion)
        {
            // Activate slow motion using the TimeManager, and by changing the game's time scale
            TimeManager.Instance.SetTimeScale(e.slowMotion.timeScale, duration);
        }
        else if (e.type == Brawler.EventType.ParticleEffect)
        {
            // If the particle effect should spawn at this character's position
            if (e.particleEvent.spawnPoint == ParticleSpawnPoint.Self)
            {
                // Calculate the position where the particles should spawn. They should spawn at this character's
                // position, plus the offset specified by the particle event
                Vector3 position = character.Transform.position;

                // Stores the offset of the particle effect, relative to the character's position
                Vector3 offset = e.particleEvent.offset;

                // If the character is facing left
                if (character.CharacterMovement.FacingDirection == Direction.Left)
                {
                    // Flip the x-direction of the particle effect's offset. This way, the offset is relative to the character
                    offset.x *= -1;
                }

                // Add the pre-computed offset to the particle effect's spawn position.
                position += offset;

                // Play the particle effect at the position computed above.
                ParticleManager.Instance.Play(e.particleEvent.effect, position);
            }
        }
        else if (e.type == Brawler.EventType.Force)
        {
            // Apply the force event on this character
            character.CharacterForces.ApplyForceEvent(e.forceEvent, duration);
        }
        else if (e.type == Brawler.EventType.ColorFlash)
        {
            // Tell the character's animator to flash the given color for the desired duration
            character.CharacterAnimator.ColorFlash(e.colorFlash.color, duration, e.colorFlash.renderInFront);
        }
        else if (e.type == Brawler.EventType.Ghosting)
        {
            // Enable the ghosting effect for 'duration' seconds.
            character.CharacterAnimator.EnableGhosting(e.ghostEffect.color, duration, e.ghostEffect.renderInFront);
        }
        else if (e.type == Brawler.EventType.FreezeAnimation)
        {
            // Freeze the character's animation for 'duration' seconds
            character.CharacterAnimator.FreezeAnimation(duration);
        }
        else if (e.type == Brawler.EventType.ScreenShake)
        {
            // Shake the screen with the settings given by the event
            GameManager.Instance.GameCamera.Shake(duration, e.screenShake.speed, e.screenShake.magnitude);
        }
        else if (e.type == Brawler.EventType.Tween)
        {
            // Tween the character, as indicated by the tween event
            character.CharacterAnimator.Tween(e.tweenEvent, duration);
        }
        else if (e.type == Brawler.EventType.Die)
        {
            // Inform the character instance that he has died so that subscribers to the 'Character.OnDeath' event can be
            // notified of this character's death.
            character.Die();
        }
    }