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