# HG changeset patch # Parent 4234d1b8f0a925fa043995ccdce7fe1ba815fe75 diff --git a/src/person.cpp b/src/person.cpp --- a/src/person.cpp +++ b/src/person.cpp @@ -25,6 +25,8 @@ #include "viewport.h" #include "weather.h" +static const int MEAN_LITTER_DROPCOUNT = 30; ///< Average number of tiles after finishing eating to drop wrapper as litter. + static PersonTypeData _person_type_datas[PERSON_TYPE_COUNT]; ///< Data about each type of person. /** @@ -382,6 +384,11 @@ TileEdge Person::GetCurrentEdge() const } /** + * @fn Person::DecideMoveDirection() + * Decide where to go from the current position. + */ + +/** * Decide whether visiting the exit edge is useful. * @param current_edge Edge at the current position. * @param x X coordinate of the current voxel. @@ -626,13 +633,32 @@ static int GetDesiredEdgeIndex(TileEdge } /** - * @fn Person::DecideMoveDirection() - * Decide where to go from the current position. + * Attempt to drop the wrapper onto the path in the voxel. + * @param v %Voxel to drop the wrapper. + * @param wrapper_counter Counter of number of tiles to wait until the wrapper is forcibly dropped. + * @return Whether or not the wrapper was dropped. */ +static bool TryDropWrapper(Voxel *v, uint16 wrapper_counter) +{ + uint16 path_instance_data = v->GetInstanceData(); + if (wrapper_counter > 1 && (GetPathDecoration(path_instance_data) != PDEC_LITTERBIN || GetVisiblePathLitter(path_instance_data) > 0)) { + return false; // Wait for a better place to drop the litter. + } + + /* Should drop the wrapper asap. */ + if (GetVisiblePathLitter(path_instance_data) == 3) return false; // Already maximal litter, wait until the next tile. + + uint litter = GetPathLitter(path_instance_data); + path_instance_data = SetPathLitter(path_instance_data, litter + 1); + v->SetInstanceData(path_instance_data); + return true; // Dropped. + +} + void Guest::DecideMoveDirection() { - const VoxelStack *vs = _world.GetStack(this->vox_pos.x, this->vox_pos.y); - const Voxel *v = vs->Get(this->vox_pos.z); + VoxelStack *vs = _world.GetModifyStack(this->vox_pos.x, this->vox_pos.y); + Voxel *v = vs->GetCreate(this->vox_pos.z, false); TileEdge start_edge = this->GetCurrentEdge(); // Edge the person is currently. if (this->activity == GA_ENTER_PARK && vs->owner == OWN_PARK) { @@ -641,10 +667,19 @@ void Guest::DecideMoveDirection() // Add some happiness?? (Somewhat useless as every guest enters the park. On the other hand, a nice point to configure difficulty level perhaps?) } - /* Find feasible exits and shops. */ uint8 exits, shops; bool queue_path; if (HasValidPath(v)) { + /* Can we drop the wrapper? */ + if (this->food == 0 && this->drink == 0 && this->wrapper_counter > 0) { // Guest has finished eating, and is holding a wrapper. + if (TryDropWrapper(v, this->wrapper_counter)) { + this->wrapper_counter = 0; + } else { + if (this->wrapper_counter > 1) this->wrapper_counter--; + } + } + + /* Find feasible exits and shops. */ bool seen_wanted_ride; exits = GetExitDirections(v, start_edge, &seen_wanted_ride, &queue_path); shops = exits >> 4; @@ -1019,8 +1054,8 @@ void Guest::Activate(const Point16 &star this->has_map = false; this->has_umbrella = false; this->has_balloon = false; - this->has_wrapper = false; this->salty_food = false; + this->wrapper_counter = 0; this->food = 0; this->drink = 0; this->hunger_level = 50; @@ -1104,7 +1139,6 @@ void Guest::ChangeHappiness(int16 amount * Daily ponderings of a guest. * @return If \c false, de-activate the guest. * @todo Make going home a bit more random. - * @todo Implement dropping litter (Guest::has_wrapper) to the path, and also drop the wrapper when passing a non-empty litter bin. * @todo Implement nausea (Guest::nausea). * @todo Implement energy (for tiredness of guests). */ @@ -1134,10 +1168,7 @@ bool Guest::DailyUpdate() } int16 happiness_change = 0; - if (!eating) { - if (this->has_wrapper && this->rnd.Success1024(25)) this->has_wrapper = false; // XXX Drop litter. - if (this->hunger_level > 200) happiness_change--; - } + if (!eating && this->hunger_level > 200) happiness_change--; if (this->waste > 170) happiness_change -= 2; switch (_weather.GetWeatherType()) { @@ -1159,7 +1190,10 @@ bool Guest::DailyUpdate() this->ChangeHappiness(happiness_change); - if (this->activity == GA_WANDER && this->happiness <= 10) this->activity = GA_GO_HOME; // Go home when bored. + if (this->activity == GA_WANDER && this->happiness <= 10) { + this->wrapper_counter = 0; + this->activity = GA_GO_HOME; // Go home when bored. + } return true; } @@ -1248,23 +1282,23 @@ void Guest::AddItem(ItemType it) case ITP_DRINK: this->drink = 5; - this->has_wrapper = true; + this->wrapper_counter = this->rnd.Exponential(MEAN_LITTER_DROPCOUNT); break; case ITP_ICE_CREAM: this->drink = 7; - this->has_wrapper = false; + this->wrapper_counter = 0; break; case ITP_NORMAL_FOOD: this->food = 10; - this->has_wrapper = true; + this->wrapper_counter = this->rnd.Exponential(MEAN_LITTER_DROPCOUNT); this->salty_food = false; break; case ITP_SALTY_FOOD: this->food = 15; - this->has_wrapper = true; + this->wrapper_counter = this->rnd.Exponential(MEAN_LITTER_DROPCOUNT); this->salty_food = true; break; diff --git a/src/person.h b/src/person.h --- a/src/person.h +++ b/src/person.h @@ -189,9 +189,9 @@ public: /* Possessions of the guest. */ bool has_map; ///< Whether guest has a park map. bool has_umbrella; ///< Whether guest has an umbrella. - bool has_wrapper; ///< Guest has a wrapper for the food or drink. bool has_balloon; ///< Guest has a balloon. bool salty_food; ///< The food in #food is salty. + uint16 wrapper_counter; ///< When non-zero, guest is holding a wrapper that gets dropped when the counter becomes \c 0. uint8 souvenirs; ///< Number of souvenirs bought by the guest. int8 food; ///< Amount of food in the hand (one unit/day). int8 drink; ///< Amount of drink in the hand (one unit/day). diff --git a/src/person_gui.cpp b/src/person_gui.cpp --- a/src/person_gui.cpp +++ b/src/person_gui.cpp @@ -107,7 +107,7 @@ void GuestInfoWindow::SetWidgetStringPar break; case GIW_ITEMS: - _str_params.SetStrID(1, (this->guest->has_wrapper ? GUI_ITEM_WRAPPER : GUI_ITEM_NONE)); + _str_params.SetStrID(1, ((this->guest->wrapper_counter > 0) ? GUI_ITEM_WRAPPER : GUI_ITEM_NONE)); break; default: break;