Esempio n. 1
0
        private Vector3 CalculateSpawnPosition()
        {
            Vector2 casterPos = caster.Position();
            Vector2 pivotPos  = casterPos;

            if (config.targetPivot)
            {
                List <Character> nearbyEnemies = environment.FindNearbyCharacters(
                    caster, casterPos, 99,
                    new [] { FindingFilter.ExcludeAllies, FindingFilter.ExcludeDead, FindingFilter.ExcludeMe }
                    );
                if (nearbyEnemies.Count > 0)
                {
                    pivotPos = nearbyEnemies[0].Position();
                }
            }
            Vector2 spawnPosition1 = pivotPos +
                                     config.relativeSpawnPosition.FlipFollowDirection(caster.FacingDirection());
            Vector2 spawnPosition2 = pivotPos +
                                     config.relativeSpawnPosition.FlipFollowDirection(caster.FacingDirection().Opposite());
            Vector2 diff1         = spawnPosition1 - casterPos;
            Vector2 diff2         = spawnPosition2 - casterPos;
            Vector2 spawnPosition = spawnPosition1;

            if (config.faraway && diff2.magnitude > diff1.magnitude)
            {
                spawnPosition = spawnPosition2;
            }
            if (args != null && args.Contains(TemplateArgsName.Position))
            {
                spawnPosition = args.GetEntry <Vector2>(TemplateArgsName.Position);
            }

            Vector2 mostLeftAndMostRightOfCurrentStage = environment.MostLeftAndMostRightOfCurrentStage();

            spawnPosition.x = Mathf.Max(mostLeftAndMostRightOfCurrentStage.x, spawnPosition.x);
            spawnPosition.x = Mathf.Min(mostLeftAndMostRightOfCurrentStage.y, spawnPosition.x);

            if (config.ground)
            {
                Vector3 groundPosition = environment.MapColliders().ClampPositionToGround(spawnPosition);
                spawnPosition.y = groundPosition.y;
            }

            return(spawnPosition);
        }
        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));
        }