diff --git a/src/person.cpp b/src/person.cpp --- a/src/person.cpp +++ b/src/person.cpp @@ -784,15 +784,13 @@ void Person::DeActivate(AnimateResult ar } /** - * Update the animation of the guest. + * Update the animation of a person. * @param delay Amount of milliseconds since the last update. - * @return If \c false, de-activate the person. - * @todo Merge things common to all persons to Person::OnAnimate. + * @return Whether to keep the person active or how to deactivate him/her. + * @return Result code of the visit. */ -AnimateResult Guest::OnAnimate(int delay) +AnimateResult Person::OnAnimate(int delay) { - if (this->activity == GA_ON_RIDE) return OAR_OK; // Guest is not animated while on ride. - this->frame_time -= delay; if (this->frame_time > 0) return OAR_OK; @@ -885,16 +883,8 @@ AnimateResult Guest::OnAnimate(int delay assert(this->x_pos >= 0 && this->x_pos < 256); assert(this->y_pos >= 0 && this->y_pos < 256); - /* If the guest ended up off-world, quit. */ - if (this->x_vox < 0 || this->x_vox >= _world.GetXSize() * 256 || - this->y_vox < 0 || this->y_vox >= _world.GetYSize() * 256) { - return OAR_DEACTIVATE; - } - - /* If the guest arrived at the 'go home' tile while going home, quit. */ - if (this->activity == GA_GO_HOME && this->x_vox == _guests.start_voxel.x && this->y_vox == _guests.start_voxel.y) { - return OAR_DEACTIVATE; - } + AnimateResult ar = this->EdgeOfWorldOnAnimate(); + if (ar != OAR_CONTINUE) return ar; /* Handle raising of z position. */ if (this->z_pos > 128) { @@ -909,22 +899,10 @@ AnimateResult Guest::OnAnimate(int delay if (instance >= SRI_FULL_RIDES) { assert(exit_edge != INVALID_EDGE); RideInstance *ri = _rides_manager.GetRideInstance(instance); - if (ri->CanBeVisited(this->x_vox, this->y_vox, this->z_vox, exit_edge) && this->SelectItem(ri) != ITP_NOTHING) { - /* All lights are green, let's try to enter the ride. */ - this->activity = GA_ON_RIDE; - this->ride = ri; - RideEntryResult rer = ri->EnterRide(this->id, exit_edge); - if (rer != RER_REFUSED) { - this->BuyItem(ri); - /* Either the guest is already back at a path or he will be (through ExitRide). */ - return OAR_OK; - } + AnimateResult ar = this->VisitRideOnAnimate(ri, exit_edge); + if (ar != OAR_CONTINUE) return ar; - /* Could not enter, find another ride. */ - this->ride = nullptr; - this->activity = GA_WANDER; - } - /* Ride is closed, fall-through to reversing movement. */ + /* Ride is could not be visited, fall-through to reversing movement. */ } else if (HasValidPath(v)) { this->AddSelf(v); @@ -978,13 +956,6 @@ RideVisitDesire Person::WantToVisit(cons } /** - * @fn AnimateResult Person::OnAnimate(int delay) - * Update the animation of the person. - * @param delay Amount of milliseconds since the last update. - * @return Whether to keep the person active or how to deactivate him/her. - */ - -/** * @fn bool Person::DailyUpdate() * Daily ponderings of a person. * @return If \c false, de-activate the person. @@ -1038,6 +1009,58 @@ void Guest::DeActivate(AnimateResult ar) this->Person::DeActivate(ar); } +AnimateResult Guest::OnAnimate(int delay) +{ + if (this->activity == GA_ON_RIDE) return OAR_OK; // Guest is not animated while on ride. + return this->Person::OnAnimate(delay); +} + +/** + * Handle the case of a guest reaching the end of the game world. + * @return Result code of the visit. + */ +AnimateResult Guest::EdgeOfWorldOnAnimate() +{ + /* If the guest ended up off-world, quit. */ + if (this->x_vox < 0 || this->x_vox >= _world.GetXSize() * 256 || + this->y_vox < 0 || this->y_vox >= _world.GetYSize() * 256) { + return OAR_DEACTIVATE; + } + + /* If the guest arrived at the 'go home' tile while going home, quit. */ + if (this->activity == GA_GO_HOME && this->x_vox == _guests.start_voxel.x && this->y_vox == _guests.start_voxel.y) { + return OAR_DEACTIVATE; + } + + return OAR_CONTINUE; +} + +/** + * Handle guest ride visiting. + * @param ri Ride that can be visited. + * @param exit_edge Exit edge being examined. + * @return Result code of the visit. + */ +AnimateResult Guest::VisitRideOnAnimate(RideInstance *ri, TileEdge exit_edge) +{ + if (ri->CanBeVisited(this->x_vox, this->y_vox, this->z_vox, exit_edge) && this->SelectItem(ri) != ITP_NOTHING) { + /* All lights are green, let's try to enter the ride. */ + this->activity = GA_ON_RIDE; + this->ride = ri; + RideEntryResult rer = ri->EnterRide(this->id, exit_edge); + if (rer != RER_REFUSED) { + this->BuyItem(ri); + /* Either the guest is already back at a path or he will be (through ExitRide). */ + return OAR_OK; + } + + /* Could not enter, find another ride. */ + this->ride = nullptr; + this->activity = GA_WANDER; + } + return OAR_CONTINUE; +} + /** * Update the happiness of the guest. * @param amount Amount of change. diff --git a/src/person.h b/src/person.h --- a/src/person.h +++ b/src/person.h @@ -73,6 +73,7 @@ struct WalkInformation { /** Exit codes of the Person::OnAnimate call. */ enum AnimateResult { + OAR_CONTINUE, ///< No result yet, continue the routine. OAR_OK, ///< All OK, keep running. OAR_REMOVE, ///< Remove person from the person-list, and de-activate. OAR_DEACTIVATE, ///< Person is already removed from the person-list, only de-activate. @@ -99,7 +100,7 @@ public: const ImageData *GetSprite(const SpriteStorage *sprites, ViewOrientation orient, const Recolouring **recolour) const override; - virtual AnimateResult OnAnimate(int delay) = 0; + virtual AnimateResult OnAnimate(int delay); virtual bool DailyUpdate() = 0; virtual void Activate(const Point16 &start, PersonType person_type); @@ -138,6 +139,8 @@ protected: void StartAnimation(const WalkInformation *walk); virtual RideVisitDesire WantToVisit(const RideInstance *ri); + virtual AnimateResult EdgeOfWorldOnAnimate() = 0; + virtual AnimateResult VisitRideOnAnimate(RideInstance *ri, TileEdge exit_edge) = 0; }; /** Activities of the guest. */ @@ -193,6 +196,8 @@ protected: RideVisitDesire ComputeExitDesire(TileEdge current_edge, int x, int y, int z, TileEdge exit_edge, bool *seen_wanted_ride); uint8 GetExitDirections(const Voxel *v, TileEdge start_edge, bool *seen_wanted_ride, bool *queue_mode); RideVisitDesire WantToVisit(const RideInstance *ri) override; + AnimateResult EdgeOfWorldOnAnimate() override; + AnimateResult VisitRideOnAnimate(RideInstance *ri, TileEdge exit_edge) override; RideVisitDesire NeedForItem(enum ItemType it, bool use_random); void AddItem(ItemType it);