Beispiel #1
0
        public Rotation(BaseEvent be, Character caster, Environment environment)
        {
            this.be          = be;
            this.caster      = caster;
            this.environment = environment;
            ra = (RotationAction)be.ShowAction();
            Entity entity = caster.GameObject().GetComponent <EntityReference>().Entity;

            movementComponent = entity.GetComponent <MovementComponent>();
            TimelineTrigger timelineTrigger = (TimelineTrigger)be.ShowTrigger();

            duration            = ra.ShowDurationInSeconds(timelineTrigger.ShowScaleTime());
            interpolationMethod = ra.ShowInterpolation();
            interpolator        = EasingFunctions.GetEasingFunction(interpolationMethod);
            movingDirection     = ra.ShowMovingDirection();
            mode = ra.mode.ShowRotationMode();
            switch (mode)
            {
            case RotationAction.RotationMode.Delta:
                deltaRotationMode = (RotationAction.DeltaRotationMode)ra.mode;
                break;

            case RotationAction.RotationMode.Destination:
                destinationRotationMode = (RotationAction.DestinationRotationMode)ra.mode;
                break;
            }
        }
 public AudioClipPlayback(BaseEvent ef, Environment environment)
 {
     this.ef          = ef;
     this.environment = environment;
     soundAction      = (SoundAction)ef.ShowAction();
     Play();
 }
Beispiel #3
0
 public Timer(BaseEvent be, Skill skill)
 {
     this.be    = be;
     this.skill = skill;
     ta         = (TimerAction)be.ShowAction();
     waitTime   = FrameAndSecondsConverter._30Fps.FloatFramesToSeconds(ta.frame);
     interval   = FrameAndSecondsConverter._30Fps.FloatFramesToSeconds(ta.interval);
 }
        public CameraSlowMotion(Environment environment, BaseEvent eventFrame)
        {
            this.environment = environment;
            this.eventFrame  = eventFrame;

            CameraAction ca = (CameraAction)eventFrame.ShowAction();

            CameraAction.SlowMotionFx smf = (CameraAction.SlowMotionFx)ca.fx;
            environment.PerformCameraSlowMotion(smf.timeScale, smf.duration);
        }
        public DistanceTracker(BaseEvent be, Skill skill, Character caster)
        {
            this.be     = be;
            this.skill  = skill;
            this.caster = caster;

            distanceTrackerAction = (DistanceTrackerAction)be.ShowAction();
            duration         = FrameAndSecondsConverter._30Fps.FramesToSeconds(distanceTrackerAction.endFrame) - skill.Elapsed;
            lastPosition     = caster.Position();
            distanceInterval = distanceTrackerAction.distance;
        }
Beispiel #6
0
        public Macro(BaseEvent eventFrame, Character character)
        {
            this.eventFrame = eventFrame;
            this.character  = character;

            foreach (string s in ((MacroAction)eventFrame.ShowAction()).skills)
            {
                remainingSkills.Add(new SkillId(s));
            }
            Entity entity = character.GameObject().GetComponent <EntityReference>().Entity;
            HeroStateMachineComponent hsmc = entity.GetComponent <HeroStateMachineComponent>();

            userInput = (DefaultUserInput)hsmc.UserInput;
            character.PostSkillCastEventHandler += CharacterOnPostSkillCastEventHandler;
        }
        public CameraCinematicZoomToSelf(Environment environment, BaseEvent eventFrame, Character caster)
        {
            this.environment = environment;
            this.eventFrame  = eventFrame;
            this.caster      = caster;

            CameraAction ca = (CameraAction)eventFrame.ShowAction();

            CameraAction.CinematicZoomToSelfFx cztsf = (CameraAction.CinematicZoomToSelfFx)ca.fx;
            offset = cztsf.offset.FlipFollowDirection(caster.FacingDirection());
            Vector2 zoomPosition = (Vector2)caster.Position() + offset;

            zoomTarget = environment.PerformCameraCinematicZoom(
                zoomPosition, cztsf.easeDuration, cztsf.ShowEaseType(), cztsf.holdDuration, cztsf.zoomLevel
                );
            zoomTarget.onLeftTarget += () => { isFinished = true; };
        }
Beispiel #8
0
        public Dash(BaseEvent ef, Character caster, bool ignoreMinSpeedOnAir, Skill skill, Environment environment)
        {
            this.ef     = ef;
            this.caster = caster;
            this.ignoreMinSpeedOnAir = ignoreMinSpeedOnAir;
            this.skill = skill;
            mapGround  = environment.MapColliders().bottom;
            mapCeil    = environment.MapColliders().top;
            GameObject gameObject = caster.GameObject();

            casterTransform   = gameObject.transform;
            casterBoxCollider = gameObject.GetComponent <BoxCollider>();
            casterEntity      = gameObject.GetComponent <EntityReference>().Entity;
            movementComponent = casterEntity.GetComponent <MovementComponent>();
            da = (DashAction)ef.ShowAction();
            if (ef.ShowTrigger().ShowTriggerType() == TriggerType.Frame)
            {
                TimelineTrigger tt = (TimelineTrigger)ef.ShowTrigger();
                duration = da.ShowEndFrameInSeconds(tt.ShowScaleTime());
            }
            else
            {
                duration = da.ShowEndFrameInSeconds(1);
            }
            PerformDash(da, caster);
            isDashPerformed = true;
            CacheOriginalColliderData(ef, caster);
            ResizeCollider(ef);
            if (da.collision)
            {
                cubeShape = new CubeShape(GetCenterOfHitbox(), casterBoxCollider.size, new List <SsarTuple <Color, float> >(new [] { new SsarTuple <Color, float>(Color.cyan, duration), }));
                GizmosDrawer.Instance.AddRequest(new DrawRequest(cubeShape, duration));
            }

            if (da.collision)
            {
                collisionDetectionCoroutineHandle = Timing.RunCoroutine(DetectCollision(), Segment.FixedUpdate);
                centerOfHitBoxAtPreviousFrame     = GetCenterOfHitbox();
            }

            positionAtPreviousFrame = movementComponent.Position;
        }
Beispiel #9
0
        public PassiveSkillOnOff(BaseEvent passiveEvent, Character caster)
        {
            this.passiveEvent = passiveEvent;
            this.caster       = caster;

            PassiveSkillOnOffAction act           = (PassiveSkillOnOffAction)passiveEvent.ShowAction();
            List <SkillId>          ongoingSkills = this.caster.OngoingSkills();

            foreach (SkillId sid in ongoingSkills)
            {
                if (sid.StringValue.Equals(act.id))
                {
                    if (!act.state)
                    {
                        caster.FindOngoingSkill(sid).Deactivate();
                    }
                    else
                    {
                        caster.FindOngoingSkill(sid).Activate();
                    }
                }
            }
        }
Beispiel #10
0
        protected void Trigger(BaseEvent be, TemplateArgs args = null)
        {
            try {
                if (!IsEventTriggerable(be))
                {
                    return;
                }

                BaseAction ba         = be.ShowAction();
                ActionType actionType = ba.ShowActionType();
                switch (actionType)
                {
                case ActionType.CastProjectile:
                case ActionType.Impact:
                    List <ProjectileComponent> justLaunchedProjectiles = LaunchProjectiles(be);
                    projectiles.AddRange(justLaunchedProjectiles);
                    break;

                default:
                    Loopable loopable = loopableElementFactory.Produce(
                        caster, this, config.ShowSkillId(), be, config.ShowSkillCastingSource(), args
                        );
                    loopableElements.Insert(0, loopable);
                    if (actionType == ActionType.Jump)
                    {
                        jumps.Add((Jump)loopable);
                    }
                    OnLoopableElementProduction(be, loopable);
                    break;
                }
            }
            catch (Exception e) {
                Exception ex = new Exception("Error trigger event of skill id " + config.ShowSkillId(), e);
                DLog.LogException(ex);
            }
        }
        public CameraAddTarget(Environment environment, BaseEvent eventFrame, Character caster)
        {
            this.environment = environment;
            this.eventFrame  = eventFrame;

            CameraAction ca = (CameraAction)eventFrame.ShowAction();

            atf = (CameraAction.AddTargetFx)ca.fx;
            Character target = environment.FindNearbyCharacters(
                caster, Vector3.zero, 999,
                new[] { FindingFilter.ExcludeMe, FindingFilter.ExcludeDead, FindingFilter.ExcludeAllies }
                )[0];

            joint = target.GameObject().transform.FindDeepChild(atf.joint);
            pc2d  = environment.GetCamera().GetComponent <ProCamera2D>();
            casterCameraTarget = pc2d.CameraTargets[0];
            originalX          = casterCameraTarget.TargetInfluenceH;
            originalY          = casterCameraTarget.TargetInfluenceV;
            casterCameraTarget.TargetInfluenceH = atf.curInfX;
            casterCameraTarget.TargetInfluenceV = atf.curInfY;
            cameraTarget = pc2d.AddCameraTarget(
                joint, atf.influenceY, atf.influenceX, atf.translationDuration
                );
        }
        public SsarTuple <Entity, IPromise <Entity> > Spawn(BaseEvent instruction,
                                                            Character caster, Skill parentSkill,
                                                            TemplateArgs preferedArgs = null)
        {
            CastProjectileAction cpa = (CastProjectileAction)instruction.ShowAction();
            BaseProjectile       projectileConfig = cpa.ShowProjectile();
            ProjectileType       projectileType   = projectileConfig.ShowProjectileType();

            TemplateArgs      args             = new TemplateArgs();
            Entity            projectileEntity = null;
            IPromise <Entity> creationPromise  = null;
            Vector2           relativePos      = Vector2.zero;
            string            prefabPath       = String.Empty;
            Entity            casterEntity     = promiseWorld.GetEntityById(caster.Id());
            bool found;
            List <CastProjectileAction.Lifetime> lifetimes = null;
            TrajectoryConfig   trajectoryConfig            = null;
            DamageTickerConfig damageTickerConfig          = projectileConfig.damageTickerConfig;
            List <HitBoxShape> hitBoxes      = new List <HitBoxShape>();
            Vector2            pivotPosition = caster.Position();
            UsageGoal          usageGoal     = cpa is ImpactAction ? UsageGoal.CollisionDetection : UsageGoal.DamageDealing;
            int  targetLockingDuration       = 0;
            int  targetLockingEventId        = -1;
            bool targetLockingClampY         = false;

            switch (projectileType)
            {
            case ProjectileType.Melee:
                MeleeProjectileConfig meleeProjectileConfig = (MeleeProjectileConfig)projectileConfig;
                HitBoxShape           firstHitBox           = meleeProjectileConfig.hitBoxes[0];
                hitBoxes.AddRange(meleeProjectileConfig.hitBoxes);
                relativePos = firstHitBox.ShowRelativePositionOfCenterPivot()
                              .FlipFollowDirection(caster.FacingDirection());
                prefabPath = meleeProjectilePrefabPath;
                lifetimes  = meleeProjectileConfig.lifetimes;
                FollowerMode followerMode = meleeProjectileConfig.anchor.ShowFollowerMode();
                switch (followerMode)
                {
                case FollowerMode.None:
                    StationaryTrajectoryConfig stationaryTrajectoryConfig  = new StationaryTrajectoryConfig();
                    CastProjectileAction.NoneAnchorFollower anchorFollower = (CastProjectileAction.NoneAnchorFollower)meleeProjectileConfig.anchor;
                    stationaryTrajectoryConfig.directionReverse = anchorFollower.directionReverse;
                    trajectoryConfig = stationaryTrajectoryConfig;
                    break;

                case FollowerMode.Caster:
                    stationaryTrajectoryConfig = new StationaryTrajectoryConfig();
                    stationaryTrajectoryConfig.followCaster = true;
                    trajectoryConfig = stationaryTrajectoryConfig;
                    break;

                case FollowerMode.Joint:
                    JointFollowerTrajectoryConfig jftc = new JointFollowerTrajectoryConfig();
                    JointAnchorFollower           jaf  = (JointAnchorFollower)meleeProjectileConfig.anchor;
                    jftc.joint             = jaf.joint;
                    jftc.rotation          = jaf.rotation;
                    jftc.rotationDirection = jaf.rotationDirection;
                    jftc.axis        = jaf.axis;
                    trajectoryConfig = jftc;
                    break;

                default:
                    throw new Exception(string.Format(
                                            "Missing logic to create config of FollowerMode '{0}'", followerMode
                                            ));
                }
                break;

            case ProjectileType.Ranger:
                RangerProjectileConfig rangerProjectileConfig = (RangerProjectileConfig)projectileConfig;
                if (rangerProjectileConfig.useOwnPivotPosition)
                {
                    pivotPosition = rangerProjectileConfig.pivotPosition;
                }
                relativePos = rangerProjectileConfig.hitBox.ShowRelativePositionOfCenterPivot();
                if (rangerProjectileConfig.flipRelativePositionTowardCasterFacingDirection)
                {
                    relativePos = relativePos.FlipFollowDirection(caster.FacingDirection());
                }
                prefabPath       = rangerProjectileConfig.prefabPath;
                lifetimes        = rangerProjectileConfig.lifetimes;
                trajectoryConfig = rangerProjectileConfig.trajectoryConfig;
                hitBoxes.Add(rangerProjectileConfig.hitBox);
                targetLockingDuration = rangerProjectileConfig.lockDuration;
                targetLockingEventId  = rangerProjectileConfig.lockEid;
                targetLockingClampY   = rangerProjectileConfig.clampY;
                break;

            default:
                DLog.LogError(string.Format(
                                  "Cannot create projectile of type '{0}'", projectileType
                                  ));
                break;
            }

            Vector2 worldPos = pivotPosition + relativePos;

            args.SetEntry(TemplateArgsName.Position, worldPos);
            args.SetEntry(TemplateArgsName.EntityType, EntityType.Projectile);
            args.SetEntry(TemplateArgsName.Group, caster.Group());
            args.SetEntry(TemplateArgsName.Projectile_PrefabPath, prefabPath);
            args.SetEntry(TemplateArgsName.Projectile_ParentCharacter, caster);
            args.SetEntry(TemplateArgsName.Projectile_ParentSkill, parentSkill);
            args.SetEntry(TemplateArgsName.Projectile_HitBoxes, hitBoxes);
            args.SetEntry(
                TemplateArgsName.Projectile_ParentEntity_TimeScaleComponent,
                casterEntity.GetComponent <TimeScaleComponent>()
                );
            args.SetEntry(TemplateArgsName.Projectile_Lifetime, lifetimes);
            args.SetEntry(TemplateArgsName.Projectile_Trajectory, trajectoryConfig);
            args.SetEntry(TemplateArgsName.Projectile_DamageTicker, damageTickerConfig);
            args.SetEntry(TemplateArgsName.Projectile_Blockable, cpa.projectile.blockable);
            args.SetEntry(TemplateArgsName.Projectile_BlockDirection, BlockDirection.Front);
            args.SetEntry(TemplateArgsName.Projectile_BlockSource, Source.PlainValue);
            args.SetEntry(TemplateArgsName.Projectile_BlockCount, 0);
            args.SetEntry(TemplateArgsName.Projectile_BlockDirection, BlockDirection.Front);
            args.SetEntry(TemplateArgsName.Projectile_UsageGoal, usageGoal);
            args.SetEntry(TemplateArgsName.MapColliderBoundaries, mapColliders);
            args.SetEntry(TemplateArgsName.Projectile_CollisionEvaluator, projectileConfig.ShowCollisionGroupEvaluator());
            args.SetEntry(TemplateArgsName.Projectile_SleepTime, cpa.projectile.sleep);
            args.SetEntry(TemplateArgsName.Projectile_TargetLockingDuration, targetLockingDuration);
            args.SetEntry(TemplateArgsName.Projectile_TargetLockingEventId, targetLockingEventId);
            args.SetEntry(TemplateArgsName.Projectile_TargetLockingClampY, targetLockingClampY);
            args.SetEntry(TemplateArgsName.Projectile_PivotCharacter, caster);
            args.SetEntry(TemplateArgsName.Projectile_Environment, environment);
            if (preferedArgs != null)
            {
                if (preferedArgs.Contains(TemplateArgsName.Position))
                {
                    pivotPosition = preferedArgs.GetEntry <Vector2>(TemplateArgsName.Position);
                    worldPos      = pivotPosition + relativePos;
                    args.SetEntry(TemplateArgsName.Position, worldPos);
                }

                if (preferedArgs.Contains(TemplateArgsName.Projectile_BlockDirection))
                {
                    args.SetEntry(
                        TemplateArgsName.Projectile_BlockDirection,
                        preferedArgs.GetEntry <BlockDirection>(TemplateArgsName.Projectile_BlockDirection)
                        );
                }

                if (preferedArgs.Contains(TemplateArgsName.Projectile_BlockSource))
                {
                    args.SetEntry(
                        TemplateArgsName.Projectile_BlockSource,
                        preferedArgs.GetEntry <Source>(TemplateArgsName.Projectile_BlockSource)
                        );
                }

                if (preferedArgs.Contains(TemplateArgsName.Projectile_BlockCount))
                {
                    args.SetEntry(
                        TemplateArgsName.Projectile_BlockCount,
                        preferedArgs.GetEntry <int>(TemplateArgsName.Projectile_BlockCount)
                        );
                }

                if (preferedArgs.Contains(TemplateArgsName.Projectile_PivotCharacter))
                {
                    args.SetEntry(
                        TemplateArgsName.Projectile_PivotCharacter,
                        preferedArgs.GetEntry <Character>(TemplateArgsName.Projectile_PivotCharacter)
                        );
                }
            }
            projectileEntity = promiseWorld.CreateEntity(null, TemplateName.Projectile, args);
            creationPromise  = projectileEntity.GetComponent <EntityCreationPromiseComponent>().Promise;
            creationPromise.Then(entity => { CheckIfProjectileGameObjectIsInstantiated(caster, parentSkill, entity); });

            return(new SsarTuple <Entity, IPromise <Entity> >(projectileEntity, creationPromise));
        }
        public JumpTowardTarget(BaseEvent ef, Character caster, Environment environment)
        {
            this.ef          = ef;
            this.caster      = caster;
            this.environment = environment;

            jtta     = (JumpTowardTargetAction)ef.ShowAction();
            duration = jtta.timeToPeak + jtta.timeToFloat + jtta.timeToGround;
            List <Character> enemies = environment.FindNearbyCharacters(
                caster, Vector3.zero, 999,
                new[] {
                FindingFilter.ExcludeAllies, FindingFilter.ExcludeMe
            }
                );

            if (enemies.Count > 0)
            {
                Character enemy = enemies[0];
                Vector2   translationFromCasterToEnemy = Vector2.zero;
                float     distanceToJump = 0;
                mode = jtta.ShowTargetMode();
                switch (mode)
                {
                case JumpTowardTargetAction.TargetMode.Joint:
                    joint = enemy.GameObject().transform.FindDeepChild(jtta.joint);
                    Vector3 jumpTarget = joint.TransformPoint(jtta.offset);
                    translationFromCasterToEnemy = jumpTarget - caster.Position();
                    distanceToJump = Mathf.Abs(translationFromCasterToEnemy.x);
                    break;

                case JumpTowardTargetAction.TargetMode.KeepDistance:
                    translationFromCasterToEnemy = enemy.Position() - caster.Position();
                    float distanceOnXAxis = Math.Abs(translationFromCasterToEnemy.x);
                    bool  isTargetFarAway = distanceOnXAxis > jtta.distanceToKeep;
                    if (isTargetFarAway)
                    {
                        distanceToJump = distanceOnXAxis - jtta.distanceToKeep;
                        if (jtta.maxDistance >= 0)
                        {
                            distanceToJump = Mathf.Min(distanceToJump, jtta.maxDistance);
                        }
                    }
                    break;
                }
                if (translationFromCasterToEnemy.x > 0)
                {
                    caster.SetFacingDirectionToRight();
                    caster.SetMovingDirectionToRight();
                }
                else
                {
                    caster.SetFacingDirectionToLeft();
                    caster.SetMovingDirectionToLeft();
                }
                jumpRequest = caster.JumpOverDistance(
                    jtta.height, jtta.timeToPeak,
                    distanceToJump, jtta.timeToGround,
                    false, jtta.timeToFloat, jtta.stopHorizontal
                    );
            }
            else
            {
                isFinish = true;
            }
        }
        public DashTowardTarget(BaseEvent ef, Character caster, Environment environment)
        {
            this.ef          = ef;
            this.caster      = caster;
            this.environment = environment;

            dtta = (DashTowardTargetAction)ef.ShowAction();
            float scaletime = 1;

            if (ef.ShowTrigger() is TimelineTrigger)
            {
                TimelineTrigger tt = (TimelineTrigger)ef.ShowTrigger();
                scaletime = tt.ShowScaleTime();
            }
            duration = dtta.ShowDurationInSeconds(scaletime);
            List <Character> enemies = environment.FindNearbyCharacters(
                caster, Vector3.zero, 999,
                new[] {
                FindingFilter.ExcludeAllies, FindingFilter.ExcludeMe
            }
                );

            if (enemies.Count > 0)
            {
                enemy = enemies[0];
                Vector2 diff = enemy.Position() - caster.Position();

                if (!dtta.track)
                {
                    float distance        = Math.Abs(diff.x);
                    bool  isTargetFarAway = distance > dtta.distanceToKeep;
                    if (isTargetFarAway)
                    {
                        float distanceToDash = distance - dtta.distanceToKeep;
                        if (dtta.maxDistance >= 0)
                        {
                            distanceToDash = Mathf.Min(distanceToDash, dtta.maxDistance);
                        }
                        if (diff.x > 0)
                        {
                            caster.SetFacingDirectionToRight();
                            caster.SetMovingDirectionToRight();
                        }
                        else
                        {
                            caster.SetFacingDirectionToLeft();
                            caster.SetMovingDirectionToLeft();
                        }
                        dashRequest = (DashRequest)caster.Dash(distanceToDash, duration, 0, true, true, true, dtta.uniform);
                    }
                    else
                    {
                        isFinished = true;
                    }
                }
                else
                {
                    if (diff.x > 0)
                    {
                        caster.SetFacingDirectionToRight();
                        caster.SetMovingDirectionToRight();
                    }
                    else
                    {
                        caster.SetFacingDirectionToLeft();
                        caster.SetMovingDirectionToLeft();
                    }
                    dashRequest = (DashRequest)caster.Dash(dtta.distance, duration, 0, true, true, true, dtta.uniform);
                }
            }
            else
            {
                isFinished = true;
            }
        }
Beispiel #15
0
        public Loopable Produce(Character caster, Skill skill, SkillId skillId, BaseEvent baseEvent,
                                SkillCastingSource skillCastingSource, TemplateArgs args)
        {
            BaseAction ba         = baseEvent.ShowAction();
            ActionType actionType = ba.ShowActionType();
            Loopable   loopable   = null;

            switch (actionType)
            {
            case ActionType.Camera:
                CameraAction        ca     = (CameraAction)ba;
                CameraAction.BaseFx bf     = ca.fx;
                CameraAction.FxType fxType = bf.ShowFxType();
                switch (fxType)
                {
                case CameraAction.FxType.Shake:
                    CameraAction.ShakeFx sf = (CameraAction.ShakeFx)bf;
                    loopable = new CameraShake(environment, sf);
                    break;

                case CameraAction.FxType.Fade:
                    loopable = new CameraFade(environment, baseEvent);
                    break;

                case CameraAction.FxType.CinematicZoomToSelf:
                    loopable = new CameraCinematicZoomToSelf(environment, baseEvent, caster);
                    break;

                case CameraAction.FxType.SlowMotion:
                    loopable = new CameraSlowMotion(environment, baseEvent);
                    break;

                case CameraAction.FxType.AddTarget:
                    loopable = new CameraAddTarget(environment, baseEvent, caster);
                    break;

                default:
                    throw new Exception("Missing logic to handle camera fx of type " + fxType);
                }
                break;

            case ActionType.Dash:
                Dash dash = new Dash(baseEvent, caster, skill.IgnoreMinSpeedOnAirForDashes(), skill, environment);
                loopable = dash;
                break;

            case ActionType.Jump:
                bool jumpOverDistance = true;
                if (args != null)
                {
                    bool found;
                    jumpOverDistance = args.TryGetEntry <bool>(TemplateArgsName.JumpSkill_JumpOverDistance, out found);
                    if (!found)
                    {
                        jumpOverDistance = true;
                    }
                }
                Jump jump = new Jump(baseEvent, caster, skill, environment, jumpOverDistance);
                loopable = jump;
                break;

            case ActionType.Vfx:
                Vfxs.Vfx vfx = new Vfxs.Vfx(
                    baseEvent, environment, caster, skillCastingSource, skill, args
                    );
                loopable = vfx;
                break;

            case ActionType.Modifier:
                ModifierAction     ma       = (ModifierAction)ba;
                BaseModifierConfig bmc      = ma.modifierConfig;
                ModifierInfo       mi       = modifierInfoFactory.CreateFrom(skill, bmc, environment);
                EntityReference    er       = caster.GameObject().GetComponent <EntityReference>();
                Modifier           modifier = DamageSystem.Instance.CreateModifier(
                    mi, er.Entity, er.Entity, caster.Position(),
                    caster.Position(), skill, skillId, 0
                    );
                if (modifier != null)
                {
                    caster.AddModifier(modifier);
                }
                loopable = new ModifierLoopable(modifier);
                break;

            case ActionType.Animation:
                loopable = new AnimationPlayback(baseEvent, caster);
                break;

            case ActionType.Teleport:
                TeleportAction          ta   = (TeleportAction)baseEvent.action;
                TeleportAction.ModeName mode = ta.mode.ShowModeName();
                switch (mode)
                {
                case TeleportAction.ModeName.PredefinedPositionOnMap:
                    new Teleport(baseEvent, caster, environment);
                    loopable = new ImmediatelyFinishedLoopable();
                    break;

                case TeleportAction.ModeName.KeepDistance:
                    TeleportAction.KeepDistanceMode kdm = (TeleportAction.KeepDistanceMode)ta.mode;
                    loopable = new TeleportKeepDistanceLogic(kdm, skill, environment, caster);
                    break;

                case TeleportAction.ModeName.AroundTarget:
                    TeleportAction.AroundTargetMode atm = (TeleportAction.AroundTargetMode)ta.mode;
                    loopable = new TeleportAroundTargetLogic(atm, caster, environment, skill);
                    break;

                case TeleportAction.ModeName.AroundTeamMate:
                    TeleportAction.AroundTeamMateMode atmm = (TeleportAction.AroundTeamMateMode)ta.mode;
                    loopable = new TeleportAroundTeamMate(atmm, caster, environment, skill);
                    break;

                default:
                    throw new Exception("Cannot create teleport of type " + mode);
                }
                break;

            case ActionType.FacingDirection:
                loopable = new FacingDirection(baseEvent, caster, environment);
                break;

            case ActionType.DashTowardTarget:
                DashTowardTarget dtt = new DashTowardTarget(baseEvent, caster, environment);
                loopable = dtt;
                break;

            case ActionType.JumpTowardTarget:
                loopable = new JumpTowardTarget(baseEvent, caster, environment);
                break;

            case ActionType.SpawnCharacter:
                SpawnCharacterAction sca = (SpawnCharacterAction)ba;
                loopable = new SpawnCharacter(sca, entitySpawner, caster, args, environment, skillId, hamc);
                break;

            case ActionType.Rotation:
                loopable = new Rotation(baseEvent, caster, environment);
                break;

            case ActionType.Timer:
                loopable = new Timer(baseEvent, skill);
                break;

            case ActionType.Sound:
                loopable = new AudioClipPlayback(baseEvent, environment);
                break;

            case ActionType.PassiveSkillOnOff:
                loopable = new PassiveSkillOnOff(baseEvent, caster);
                break;

            case ActionType.DistanceTracker:
                loopable = new DistanceTracker(baseEvent, skill, caster);
                break;

            case ActionType.SelfDamageDealing:
                loopable = new SelfDamageDealing(baseEvent, caster, skill, skillId);
                break;

            case ActionType.SwitchPhase:
                loopable = new SwitchPhase(skill);
                break;

            case ActionType.Movable:
                Entity        casterEntity  = caster.GameObject().GetComponent <EntityReference>().Entity;
                UserInput     userInput     = casterEntity.GetComponent <HeroStateMachineComponent>().UserInput;
                MovableAction movableAction = (MovableAction)ba;
                loopable = new Movable(movableAction, skill, caster.FacingDirection(), userInput, caster);
                break;

            case ActionType.Input:
                casterEntity = caster.GameObject().GetComponent <EntityReference>().Entity;
                userInput    = casterEntity.GetComponent <HeroStateMachineComponent>().UserInput;
                InputAction ia = (InputAction)ba;
                loopable = new InputSimulation(ia, (DefaultUserInput)userInput);
                break;

#if UNITY_EDITOR
            case ActionType.Macro:
                loopable = new Macro(baseEvent, caster);
                break;
#endif
            default:
                DLog.Log("Missing logic to handle action of type " + actionType);
                break;
            }

            return(loopable);
        }