← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1657117-fishbreeder-messages into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1657117-fishbreeder-messages into lp:widelands.

Commit message:
Fish Breeder's Houses no longer display a "Can’t find any more resources!" tooltip when the fishing rounds are full. We have the following behaviour instead:

1. Working normally: Don't display anything.
2. Fishing grounds are full: Show tooltip
2. No fields with fish in them in the work area: Show tooltip and send "Out of Resources" message.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1657117 in widelands: "differentiating fish breeder messages "
  https://bugs.launchpad.net/widelands/+bug/1657117

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1657117-fishbreeder-messages/+merge/317028

See commit message. The linked bug has a savegame with an empty fish pond for testing.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1657117-fishbreeder-messages into lp:widelands.
=== modified file 'data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua	2016-11-02 05:48:00 +0000
+++ data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua	2017-02-11 12:22:38 +0000
@@ -82,6 +82,11 @@
 --                productivity_threshold = 30
 --            },
 --
+--    **resource_not_needed_message**.
+--        *Optional*. This string defines the tooltip shown by the productionsite
+--        to the player if all resources have been replenished by its worker in full.
+--        Look at the Atlantean Fish Breeder's House for an example.
+--
 tribes:new_productionsite_type {
    msgctxt = "atlanteans_building",
    name = "atlanteans_armorsmithy",

=== modified file 'data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua	2015-12-11 16:54:00 +0000
+++ data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua	2017-02-11 12:22:38 +0000
@@ -46,4 +46,14 @@
          }
       },
    },
+
+   out_of_resource_notification = {
+      -- Translators: Short for "Out of ..." for a resource
+      title = _"No Fish",
+      heading = _"Out of Fish",
+      message = pgettext("atlanteans_building", "The fish breeder working out of this fish breeder’s house can’t find any fish in his work area. Remember that you can only regenerate your fish resources if there are some fish left to breed."),
+      productivity_threshold = 60
+   },
+   -- Translators: Productivity tooltip for Atlantean fish breeders when all water fields are already full of fish
+   resource_not_needed_message = _"The fishing grounds are full";
 }

=== modified file 'src/logic/findnode.cc'
--- src/logic/findnode.cc	2017-01-28 19:55:25 +0000
+++ src/logic/findnode.cc	2017-02-11 12:22:38 +0000
@@ -116,14 +116,35 @@
 	if (resource != coord.field->get_resources()) {
 		return false;
 	}
-	if (coord.field->get_resources_amount() < coord.field->get_initial_res_amount()) {
-		return true;
+	switch(strictness) {
+	case AnimalBreedable::kDefault:
+		// We test actual breedability
+		if (coord.field->get_resources_amount() < coord.field->get_initial_res_amount()) {
+			return true;
+		}
+		break;
+	case AnimalBreedable::kAnimalFull:
+		// We test potential breedability, just resources are now full
+		if (coord.field->get_resources_amount() == coord.field->get_initial_res_amount()) {
+			return true;
+		}
+		break;
 	}
 	for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
 		const FCoords neighb = map.get_neighbour(coord, dir);
-		if (resource == neighb.field->get_resources() &&
-		    neighb.field->get_resources_amount() < neighb.field->get_initial_res_amount()) {
-			return true;
+		switch(strictness) {
+		case AnimalBreedable::kDefault:
+			if (resource == neighb.field->get_resources() &&
+				 neighb.field->get_resources_amount() < neighb.field->get_initial_res_amount()) {
+				return true;
+			}
+			break;
+		case AnimalBreedable::kAnimalFull:
+			if (resource == neighb.field->get_resources() &&
+				 neighb.field->get_resources_amount() == neighb.field->get_initial_res_amount()) {
+				return true;
+			}
+			break;
 		}
 	}
 	return false;

=== modified file 'src/logic/findnode.h'
--- src/logic/findnode.h	2017-01-28 19:58:00 +0000
+++ src/logic/findnode.h	2017-02-11 12:22:38 +0000
@@ -28,6 +28,8 @@
 
 namespace Widelands {
 
+enum class AnimalBreedable {kDefault, kAnimalFull};
+
 struct FCoords;
 class Map;
 
@@ -174,15 +176,16 @@
 	DescriptionIndex resource;
 };
 
-/// Accepts a node if it has the given resource type and remaining capacity.
+/// Accepts a node if it has the given resource type and a) has remaining capacity, b) is full
 struct FindNodeResourceBreedable {
-	FindNodeResourceBreedable(DescriptionIndex res) : resource(res) {
+	FindNodeResourceBreedable(DescriptionIndex res, AnimalBreedable br = AnimalBreedable::kDefault) : resource(res), strictness(br) {
 	}
 
 	bool accept(const Map&, const FCoords&) const;
 
 private:
 	DescriptionIndex resource;
+	AnimalBreedable strictness;
 };
 
 /// Accepts a node if it is a shore node in the sense that it is walkable

=== modified file 'src/logic/map_objects/tribes/productionsite.cc'
--- src/logic/map_objects/tribes/productionsite.cc	2017-01-28 14:53:28 +0000
+++ src/logic/map_objects/tribes/productionsite.cc	2017-02-11 12:22:38 +0000
@@ -68,6 +68,7 @@
      out_of_resource_title_(""),
      out_of_resource_heading_(""),
      out_of_resource_message_(""),
+	  resource_not_needed_message_(""),
      out_of_resource_productivity_threshold_(100) {
 	i18n::Textdomain td("tribes");
 	std::unique_ptr<LuaTable> items_table;
@@ -82,6 +83,9 @@
 			out_of_resource_productivity_threshold_ = items_table->get_int("productivity_threshold");
 		}
 	}
+	if (table.has_key("resource_not_needed_message")) {
+		resource_not_needed_message_ = _(table.get_string("resource_not_needed_message"));
+	}
 
 	if (table.has_key("outputs")) {
 		for (const std::string& output : table.get_table("outputs")->array_entries<std::string>()) {
@@ -917,20 +921,28 @@
 	Building::workers_changed();
 }
 
-void ProductionSite::notify_player(Game& game, uint8_t minutes) {
+void ProductionSite::notify_player(Game& game, uint8_t minutes, FailNotificationType type) {
 	if (last_stat_percent_ == 0 ||
 	    (last_stat_percent_ <= descr().out_of_resource_productivity_threshold() &&
 	     trend_ == Trend::kFalling)) {
-		if (descr().out_of_resource_heading().empty()) {
+
+		if (type == FailNotificationType::kFull) {
+			// The building has nothing to do
+			assert(!descr().resource_not_needed_message().empty());
+			set_production_result(descr().resource_not_needed_message());
+		} else if (descr().out_of_resource_message().empty()) {
+			// We have no message body to send
 			set_production_result(_("Can’t find any more resources!"));
 		} else {
+			// Send full message
 			set_production_result(descr().out_of_resource_heading());
 
 			assert(!descr().out_of_resource_message().empty());
 			send_message(game, Message::Type::kEconomy, descr().out_of_resource_title(),
-			             descr().icon_filename(), descr().out_of_resource_heading(),
-			             descr().out_of_resource_message(), true, minutes * 60000, 0);
+							 descr().icon_filename(), descr().out_of_resource_heading(), descr().out_of_resource_message(),
+			             true, minutes * 60000, 0);
 		}
+
 		// The following sends "out of resources" messages to be picked up by AI
 		// used as information for dismantling and upgrading buildings
 		if (descr().get_ismine()) {

=== modified file 'src/logic/map_objects/tribes/productionsite.h'
--- src/logic/map_objects/tribes/productionsite.h	2017-01-28 14:53:28 +0000
+++ src/logic/map_objects/tribes/productionsite.h	2017-02-11 12:22:38 +0000
@@ -43,6 +43,8 @@
 class WaresQueue;
 class WorkerDescr;
 
+enum class FailNotificationType {kDefault, kFull};
+
 /**
  * Every building that is part of the economics system is a production site.
  *
@@ -115,6 +117,11 @@
 	const std::string& out_of_resource_message() const {
 		return out_of_resource_message_;
 	}
+	
+	const std::string& resource_not_needed_message() const {
+		return resource_not_needed_message_;
+	}
+	
 	uint32_t out_of_resource_productivity_threshold() const {
 		return out_of_resource_productivity_threshold_;
 	}
@@ -129,6 +136,7 @@
 	std::string out_of_resource_title_;
 	std::string out_of_resource_heading_;
 	std::string out_of_resource_message_;
+	std::string resource_not_needed_message_;
 	int out_of_resource_productivity_threshold_;
 
 	DISALLOW_COPY_AND_ASSIGN(ProductionSiteDescr);
@@ -219,7 +227,7 @@
 	bool can_start_working() const;
 
 	/// sends a message to the player e.g. if the building's resource can't be found
-	void notify_player(Game& game, uint8_t minutes);
+	void notify_player(Game& game, uint8_t minutes, FailNotificationType type = FailNotificationType::kDefault);
 	void unnotify_player();
 
 	void set_default_anim(std::string);

=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc	2017-01-30 14:40:12 +0000
+++ src/logic/map_objects/tribes/worker.cc	2017-02-11 12:22:38 +0000
@@ -509,10 +509,40 @@
 		functor.add(FindNodeSpace(get_location(game)));
 
 	if (!map.find_reachable_fields(area, &list, cstep, functor)) {
-		molog("  no space found\n");
+
+		// This is default note "out of resources" sent to a player
+		FailNotificationType fail_notification_type = FailNotificationType::kDefault;
+
+		// In case this is a fishbreeder, we do more checks
+		if (action.sparam1.size() && action.iparam4) {
+
+			// we need to create create another functor, that will look for nodes full of fish
+			FindNodeAnd functorAnyFull;
+			functorAnyFull.add(FindNodeSize(static_cast<FindNodeSize::Size>(action.iparam2)));
+			functorAnyFull.add(FindNodeResourceBreedable(
+			   world.get_resource(action.sparam1.c_str()), AnimalBreedable::kAnimalFull));
+			if (action.iparam5 > -1)
+				functorAnyFull.add(FindNodeImmovableAttribute(action.iparam5), true);
+
+			if (action.iparam3)
+				functorAnyFull.add(FindNodeSpace(get_location(game)));
+
+			// now we count fields full of fish
+			if (map.find_reachable_fields(area, &list, cstep, functorAnyFull)) {
+				// Yes there are some such nodes, so we change the type of notification
+				fail_notification_type = FailNotificationType::kFull;
+			}
+		}
+		switch (fail_notification_type) {
+		case FailNotificationType::kFull:
+			molog("  all reachable nodes are full\n");
+			break;
+		default:
+			molog("  no space found\n");
+		}
 
 		if (upcast(ProductionSite, productionsite, get_location(game)))
-			productionsite->notify_player(game, 30);
+			productionsite->notify_player(game, 30, fail_notification_type);
 
 		send_signal(game, "fail");
 		pop_task(game);


Follow ups