# 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;