public override Vector3Int GetJobLocation()
        {
            var currentPos = usedNPC.Position;

            if (_playerState.CallToArmsEnabled && _weapon != null)
            {
                _target = MonsterTracker.Find(currentPos, _weapon.range, _weapon.shootDamage);

                if (_target != null)
                {
                    return(currentPos);
                }

                _target = MonsterTracker.Find(currentPos, CALL_RAD, _weapon.shootDamage);

                if (_target != null)
                {
                    var ranged = _weapon.range - 5;

                    if (ranged < 0)
                    {
                        ranged = 1;
                    }

                    position = new Vector3Int(_target.Position).Add(ranged, 0, ranged);
                    position = AIManager.ClosestPosition(position, currentPos);

                    if (!AIManager.CanStandAt(position))
                    {
                        _tmpVals.Set(COOLDOWN_KEY, _weapon.cooldownMissingItem);
                        _waitingFor++;
                    }
                    else
                    {
                        return(position);
                    }
                }
                else
                {
                    _tmpVals.Set(COOLDOWN_KEY, _weapon.cooldownMissingItem);
                    _waitingFor++;
                }
            }

            if (_waitingFor > 10)
            {
                var banner = BannerTracker.GetClosest(usedNPC.Colony.Owner, currentPos);

                if (banner != null)
                {
                    return(banner.KeyLocation);
                }
            }

            return(currentPos);
        }
Exemple #2
0
        public static MonsterSpawner.ESpawnResult TryGetSpawnLocation(Banner primaryBanner, float maxSpawnWalkDistance, out Vector3Int positionFinal)
        {
            Vector3Int bannerPos   = primaryBanner.KeyLocation;
            var        bannerList  = BannerTracker.GetBanners();
            int        safeRadius  = primaryBanner.SafeRadius;
            int        spawnRadius = Pipliz.Math.RoundToInt(Pipliz.Math.Min(maxSpawnWalkDistance, primaryBanner.MaxSpawnRadius));

            positionFinal = Vector3Int.invalidPos;

            for (int spawnTry = 0; spawnTry < MAX_TRIES; spawnTry++)
            {
                Vector3Int possiblePosition;
                Vector3Int dif;

                while (true)
                {
                    possiblePosition.x = bannerPos.x + Pipliz.Random.Next(-spawnRadius, spawnRadius);
                    possiblePosition.z = bannerPos.z + Pipliz.Random.Next(-spawnRadius, spawnRadius);
                    possiblePosition.y = Pipliz.Math.RoundToInt(TerrainGenerator.UsedGenerator.GetHeight(possiblePosition.x, possiblePosition.z));

                    dif = bannerPos - possiblePosition;

                    if (dif.MaxPartAbs > safeRadius && Pipliz.Math.Abs(dif.x) + Pipliz.Math.Abs(dif.z) < spawnRadius)
                    {
                        break;
                    }
                }

                for (int idxBanner = 0; idxBanner < bannerList.Count; idxBanner++)
                {
                    var    otherBanner = bannerList.GetValueAtIndex(idxBanner);
                    Colony otherColony = Colony.Get(otherBanner.Owner);

                    if (otherColony.FollowerCount > 0 && (otherBanner.KeyLocation - possiblePosition).MaxPartAbs <= otherBanner.SafeRadius)
                    {
                        goto NEXT_TRY;
                    }
                }

                if (!AIManager.Loaded(possiblePosition))
                {
                    return(MonsterSpawner.ESpawnResult.NotLoaded);
                }

                for (int idxOffset = 0; idxOffset < offsets.Length; idxOffset++)
                {
                    Vector3Int positionAITest = possiblePosition.Add(0, offsets[idxOffset], 0);

                    if (AIManager.CanStandAt(positionAITest))
                    {
                        positionFinal = positionAITest;
                        return(MonsterSpawner.ESpawnResult.Success);
                    }
                }

NEXT_TRY:
                continue;
            }

            return(MonsterSpawner.ESpawnResult.Fail);
        }
        protected override void ReconsiderDecision()
        {
            switch (decision.GoalType)
            {
            case ZombieGoal.Banner:

                if ((!decision.IsValid || decision.PathDistance > MinDistanceToReconsiderBanner) &&
                    (ConsiderPlayerTarget(ref decision) || ConsiderNPCTarget(ref decision)))
                {
                    return;
                }

                if (!BannerTracker.Contains(decision.GoalLocation))
                {
                    var closest = BannerTracker.GetClosest(originalGoal, position);

                    if (closest != null &&
                        AIManager.ZombiePathFinder.TryFindPath(position, closest.KeyLocation, out var path,
                                                               2000000000) == EPathFindingResult.Success)
                    {
                        decision.Clear();
                        decision = new ZombieDecision(this, path);
                        return;
                    }

                    SetCooldown(3.0);
                }

                break;

            case ZombieGoal.NPC:

                if (!decision.IsValid || decision.PathDistance > MinDistanceToReconsiderNPC)
                {
                    if (ConsiderPlayerTarget(ref decision))
                    {
                        return;
                    }

                    NPCBase nPCBase;

                    if (NPCTracker.TryGetNear(position.Vector, MaxRadiusToNPCToConsider, out nPCBase))
                    {
                        if (decision.IsGoingTo(nPCBase) && IsMovingTargetPathOkay(nPCBase.Position))
                        {
                            decision.Reconsidered();
                            return;
                        }

                        if (AIManager.ZombiePathFinder.TryFindPath(position, nPCBase.Position, out var path2,
                                                                   decision.PathDistance / 2) ==
                            EPathFindingResult.Success)
                        {
                            decision.Clear();
                            decision = new ZombieDecision(this, nPCBase, path2);
                        }
                    }

                    if (ConsiderBannerTarget(ref decision))
                    {
                        return;
                    }
                }

                break;

            case ZombieGoal.Player:

                if (Players.FindClosestAlive(position.Vector, out var player, out var num))
                {
                    if (decision.IsGoingTo(player) && IsMovingTargetPathOkay(player.VoxelPosition))
                    {
                        decision.Reconsidered();
                        return;
                    }

                    if (num < MaxSqrdRadiusToPlayerToConsider && AIManager.CanStandAt(player.VoxelPosition) &&
                        AIManager.ZombiePathFinder.TryFindPath(position, player.VoxelPosition, out var path3,
                                                               2000000000) == EPathFindingResult.Success)
                    {
                        decision.Clear();
                        decision = new ZombieDecision(this, player, path3);
                    }
                }

                if (ConsiderNPCTarget(ref decision) || ConsiderBannerTarget(ref decision))
                {
                    return;
                }

                break;


            default:

                if (ConsiderPlayerTarget(ref decision) || ConsiderNPCTarget(ref decision) ||
                    ConsiderBannerTarget(ref decision))
                {
                    return;
                }

                break;
            }

            decision.Reconsidered();
        }