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)); }