public override World Update(float secondsPassed, World world) { var speedStep = 5 * secondsPassed; switch (_logic.State) { case State.Idle: return world; case State.FindPlanet: { var planet = world.Wobs.Values.OfType<Planet>() .MinBy(p => (float)p.Pos.DistanceSquared(_pose.Location)); if (planet == null || planet.Pos.DistanceSquared(_pose.Location) > 300 * 300) return world.SetWob(SetLogic(Logic.Idle())); return world.SetWob(SetLogic(Logic.GoToPlanet(planet.ID))); } case State.GoToPlanet: { var planet = world.GetWob<Planet>(_logic.PlanetID); if (planet == null || planet.Pos.DistanceSquared(_pose.Location) < 70 * 70) return world.SetWob(SetLogic(Logic.OrbitPlanet(_logic.PlanetID))); var toPlanet = (planet.Pos - _pose.Location).ToNormalized(); return world.SetWob(SetPose(new Pose(_pose.Location + toPlanet * speedStep, toPlanet, _pose.Up))); } case State.OrbitPlanet: { var planet = world.GetWob<Planet>(_logic.PlanetID); if (planet == null) return world.SetWob(SetLogic(Logic.Idle())); var orbitLocation = _pose.Location - planet.Pos; var altitude = orbitLocation.Length; var orbitAngle = speedStep / altitude; var move = Quaternion.FromAngleAxis(orbitAngle, _pose.Up); var location = planet.Pos + move * orbitLocation; var gatheringSeconds = _logic.GatheringSeconds + secondsPassed; var gatheringInterval = 5; var gatheredAmount = (int)(gatheringSeconds / gatheringInterval); if (gatheredAmount > 0) { var gatheredStack = new Items.ItemStack(Guid.NewGuid(), Items.ItemType.MiningDroid, gatheredAmount); world = world.SetWob(world.GetWob<Inventory>(_inventoryID).Add(gatheredStack)); } gatheringSeconds -= gatheredAmount * gatheringInterval; return world.SetWob( SetPose(new Pose(location, move * _pose.Front, move * _pose.Up)) .SetLogic(_logic.SetGatheringSeconds(gatheringSeconds))); } default: throw new NotImplementedException(); } }