Beispiel #1
0
        public override float GetPriority(Pawn pawn)
        {
            if (pawn == null || pawn.needs == null)
            {
                return(0f);
            }

            Need_Rest needRest = pawn.needs.rest;

            if (needRest == null)
            {
                return(0f);
            }

            float             curLevel          = needRest.CurLevel;
            TimeAssignmentDef timeAssignmentDef = (pawn.timetable != null ? pawn.timetable.CurrentAssignment : TimeAssignmentDefOf.Anything);

            if (timeAssignmentDef == TimeAssignmentDefOf.Anything || timeAssignmentDef == TimeAssignmentDefOf.Work)
            {
                if ((pawn as X2_AIRobot) == null || (pawn as X2_AIRobot).rechargeStation == null || (pawn as X2_AIRobot).rechargeStation.Position == null)
                {
                    return(0f);
                }

                // Own implementation: When level < 45% && dist > 25
                bool isOutsideMaxDistance = !AIRobot_Helper.IsInDistance(pawn.Position, (pawn as X2_AIRobot).rechargeStation.Position, 25f);
                if (curLevel < 0.45f && pawn as X2_AIRobot != null && isOutsideMaxDistance)
                {
                    return(8f);
                }

                if (curLevel < 0.25f)
                {
                    return(8f);
                }

                return(0f);
            }
            if (timeAssignmentDef == TimeAssignmentDefOf.Joy)
            {
                if (curLevel < 0.3f)
                {
                    return(8f);
                }

                return(0f);
            }
            if (timeAssignmentDef == TimeAssignmentDefOf.Sleep)
            {
                if (curLevel < 0.75f)
                {
                    return(8f);
                }

                return(0f);
            }
            return(0f);
        }
        // When the robot is idle, check if it is inside the room of the recharge station. If not, return there.
        public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
        {
            X2_AIRobot robot = pawn as X2_AIRobot;

            if (robot.DestroyedOrNull())
            {
                return(ThinkResult.NoJob);
            }
            if (!robot.Spawned)
            {
                return(ThinkResult.NoJob);
            }

            X2_Building_AIRobotRechargeStation rechargeStation = robot.rechargeStation;

            if (rechargeStation.DestroyedOrNull())
            {
                return(ThinkResult.NoJob);
            }
            if (!rechargeStation.Spawned)
            {
                return(ThinkResult.NoJob);
            }

            Room roomRecharge = rechargeStation.Position.GetRoom(rechargeStation.Map);
            Room roomRobot    = robot.Position.GetRoom(robot.Map);

            if (roomRecharge == roomRobot)
            {
                return(ThinkResult.NoJob);
            }

            // Find target pos, but max 10 cells away!
            Map     mapRecharge = rechargeStation.Map;
            IntVec3 posRecharge = rechargeStation.Position;
            IntVec3 cell        = roomRecharge.Cells.Where(c =>
                                                           c.Standable(mapRecharge) && !c.IsForbidden(pawn) &&
                                                           AIRobot_Helper.IsInDistance(c, posRecharge, 10) &&
                                                           pawn.CanReach(c, PathEndMode.OnCell, Danger.Some, false, TraverseMode.ByPawn)
                                                           )
                                  .FirstOrDefault();

            if (cell == null || cell == IntVec3.Invalid)
            {
                return(ThinkResult.NoJob);
            }

            Job jobGoto = new Job(JobDefOf.Goto, cell);

            jobGoto.locomotionUrgency = LocomotionUrgency.Amble;

            return(new ThinkResult(jobGoto, this, JobTag.Misc, false));
        }
 private bool IsInDistanceToStation(float distance)
 {
     if (Position != null && Position != IntVec3.Invalid &&
         rechargeStation != null && rechargeStation.Position != null && rechargeStation.Position != IntVec3.Invalid)
     {
         return(AIRobot_Helper.IsInDistance(Position, rechargeStation.Position, distance));
     }
     else
     {
         return(false);
     }
 }
Beispiel #4
0
        private void Button_SpawnBot()
        {
            if (isRepairRequestActive)
            {
                return;
            }

            if (this.robot != null || robotIsDestroyed)
            {
                if (this.robot != null && this.robot.Spawned && AIRobot_Helper.IsInDistance(this.Position, robot.Position, 3))
                {
                    this.robot.jobs.ClearQueuedJobs();
                    this.robot.stances.CancelBusyStanceHard();
                    this.robot.jobs.StopAll(false);
                    this.robot.pather.StopDead();
                }

                return;
            }

            if (spawnThingDef.NullOrEmpty())
            {
                Log.Error("Robot Recharge Station: Wanted to spawn robot, but spawnThingDef is null or empty!");
                return;
            }

            X2_AIRobot spawnedRobot = null;

            if (!IsRobotInContainer())
            {
                spawnedRobot = X2_Building_AIRobotCreator.CreateRobot(spawnThingDef, this.Position, this.Map, Faction.OfPlayer);
            }
            else
            {
                spawnedRobot = container[0] as X2_AIRobot;
                container.Remove(spawnedRobot);
                spawnedRobot = GenSpawn.Spawn(spawnedRobot, this.Position, this.Map) as X2_AIRobot;
            }

            this.robot = spawnedRobot;
            this.robot.rechargeStation = this;
            this.robotSpawnedOnce      = true;

            this.SpawnRobotAfterRecharge = true;
        }
        public override void Tick()
        {
            base.Tick();

            //Handle graphic update
            UpdateGraphic();

            // robot in container => recharge or release needed?
            if (robot == null)
            {
                if (notify_spawnRequested)
                {
                    // Don't start all robots at the same time
                    if (!this.IsHashIntervalTick(5))
                    {
                        return;
                    }

                    notify_spawnRequested = false;
                    Button_SpawnBot();
                    return;
                }

                if (IsRobotInContainer())
                {
                    X2_AIRobot containedRobot = container[0] as X2_AIRobot;
                    if (containedRobot == null)
                    {
                        container.Remove(container[0]);
                        return;
                    }

                    if (SpawnRobotAfterRecharge && containedRobot.needs.rest.CurLevel >= 0.99f)
                    {
                        Button_SpawnBot();
                    }
                    else if (containedRobot.needs.rest.CurLevel < 1f)
                    {
                        containedRobot.needs.rest.CurLevel += (0.1f / GenDate.TicksPerHour) * rechargeEfficiency;
                        if (containedRobot.needs.rest.CurLevel > 1f)
                        {
                            containedRobot.needs.rest.CurLevel = 1f;
                        }

                        TryThrowBatteryMote(containedRobot);
                    }

                    // Try to heal robot
                    TryHealDamagedBodyPartOfRobot(containedRobot);
                    return;
                }
            }
            notify_spawnRequested = false;

            if (robotIsDestroyed)
            {
                // What do we do, when the robot is destroyed?
                TryThrowNoRobotMote(this);

                // Last step: do nothing more!
                return;
            }

            if (robot == null && (!robotSpawnedOnce || !IsRobotInContainer()))
            {
                return;
            }

            // if the robot is dead...
            if (robotSpawnedOnce && !IsRobotInContainer() && (robot == null || robot.Destroyed || robot.Dead))
            {
                if ((robot.Destroyed || robot.Dead) && robot.Corpse != null)
                {
                    robot.Corpse.Destroy(DestroyMode.Vanish);
                }

                robotIsDestroyed = true;
                return;
            }

            if (isRechargeActive && robot != null && Gen.IsHashIntervalTick(robot, 30) && !AIRobot_Helper.IsInDistance(robot.Position, this.Position, 3))
            {
                robot.jobs.ClearQueuedJobs();
                isRechargeActive = false;
            }

            if (isRechargeActive)
            {
                if (robot.needs.rest.CurLevel < 1f)
                {
                    robot.needs.rest.CurLevel += (0.1f / GenDate.TicksPerHour) * rechargeEfficiency * 2;
                    if (robot.needs.rest.CurLevel > 1f)
                    {
                        robot.needs.rest.CurLevel = 1f;
                    }

                    TryThrowBatteryMote(robot);
                }
                else
                {
                    robot.jobs.ClearQueuedJobs();
                    robot.jobs.EndCurrentJob(JobCondition.Succeeded, true);
                    isRechargeActive = false;
                }
                return;
            }


            if (!Gen.IsHashIntervalTick(robot, 250))
            {
                return;
            }

            TryUpdateAllowedArea(robot);

            if (calcDistanceRestCheck == -1)
            {
                calcDistanceRestCheck = AIRobot_Helper.GetSlopePoint(robot.GetStatValue(StatDefOf.MoveSpeed, true), 1f, 6f, 15f, 40f); // movementspeed slope: speed 1 -> 30 cells, speed 6 -> 50 cells
            }
            // If battery of robot is < 40% and distance > 25 cells => try to recall him
            // Also recall if battery is < 10% (emergency if ThinkTree isn't working)
            if ((robot.needs.rest.CurLevel < 0.40f && !AIRobot_Helper.IsInDistance(this.Position, robot.Position, calcDistanceRestCheck)) ||
                robot.needs.rest.CurLevel < 0.10f)
            {
                Notify_CallBotForRecharge();
            }
        }
        public override void Tick()
        {
            base.Tick();

            //Handle graphic update
            UpdateGraphic();

            // robot in container => recharge or release needed?
            if (robot == null && IsRobotInContainer())
            {
                X2_AIRobot containedRobot = container[0] as X2_AIRobot;
                if (containedRobot == null)
                {
                    container.Remove(container[0]);
                    return;
                }

                if (SpawnRobotAfterRecharge && containedRobot.needs.rest.CurLevel >= 0.99f)
                {
                    Button_SpawnBot();
                }
                else if (containedRobot.needs.rest.CurLevel < 1f)
                {
                    containedRobot.needs.rest.CurLevel += (0.1f / GenDate.TicksPerHour) * rechargeEfficiency;
                    if (containedRobot.needs.rest.CurLevel > 1f)
                    {
                        containedRobot.needs.rest.CurLevel = 1f;
                    }

                    TryThrowBatteryMote(containedRobot);
                }

                // Try to heal robot
                TryHealDamagedBodyPartOfRobot(containedRobot);
                return;
            }

            if (robotIsDestroyed)
            {
                // TODO: What do we do, when the robot is destroyed?


                // Last step: do nothing more!
                return;
            }

            if (robot == null && (!robotSpawnedOnce || !IsRobotInContainer()))
            {
                return;
            }

            // if the robot is dead...
            if (robotSpawnedOnce && !IsRobotInContainer() && (robot == null || robot.Destroyed || robot.Dead))
            {
                if ((robot.Destroyed || robot.Dead) && robot.Corpse != null)
                {
                    robot.Corpse.Destroy(DestroyMode.Vanish);
                }

                robotIsDestroyed = true;
                return;
            }


            if (!Gen.IsHashIntervalTick(robot, 250))
            {
                return;
            }

            TryUpdateAllowedArea(robot);

            if (calcDistanceRestCheck == -1)
            {
                calcDistanceRestCheck = AIRobot_Helper.GetSlopePoint(robot.GetStatValue(StatDefOf.MoveSpeed, true), 1f, 6f, 15f, 40f); // movementspeed slope: speed 1 -> 30 cells, speed 6 -> 50 cells
            }
            //Log.Error("Max allowed distance: " + calcDistanceRestCheck.ToString("0.##") + " / MoveSpeed: " + robot.GetStatValue(StatDefOf.MoveSpeed, true).ToString());

            // If battery of robot is < 40% and distance > 25 cells => try to recall him
            // Also recall if battery is < 10% (emergency if ThinkTree isn't working)
            if ((robot.needs.rest.CurLevel < 0.40f && !AIRobot_Helper.IsInDistance(this.Position, robot.Position, calcDistanceRestCheck)) ||
                robot.needs.rest.CurLevel < 0.10f)
            {
                Button_CallBotForShutdown();
                SpawnRobotAfterRecharge = true;
            }
        }