← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1738054-random-battle-animations into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1738054-random-battle-animations into lp:widelands.

Commit message:
Added missing call to get_rand_anim when a soldier is dying. Also, removed some code duplication and programming by exception.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1738054 in widelands: "Random soldier battle animations don´t work"
  https://bugs.launchpad.net/widelands/+bug/1738054

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1738054-random-battle-animations/+merge/335296
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1738054-random-battle-animations into lp:widelands.
=== modified file 'src/logic/game_data_error.h'
--- src/logic/game_data_error.h	2017-01-25 18:55:59 +0000
+++ src/logic/game_data_error.h	2017-12-17 17:44:30 +0000
@@ -62,6 +62,6 @@
 	UnhandledVersionError() {
 	}
 };
-}
+} // namespace Widelands
 
 #endif  // end of include guard: WL_LOGIC_GAME_DATA_ERROR_H

=== modified file 'src/logic/map_objects/immovable.cc'
--- src/logic/map_objects/immovable.cc	2017-11-10 09:31:46 +0000
+++ src/logic/map_objects/immovable.cc	2017-12-17 17:44:30 +0000
@@ -575,10 +575,10 @@
 	char const* const animname = fr.c_string();
 	try {
 		imm.anim_ = imm.descr().get_animation(animname);
-	} catch (const MapObjectDescr::AnimationNonexistent&) {
+	} catch (const GameDataError& e) {
 		imm.anim_ = imm.descr().main_animation();
-		log("Warning: (%s) Animation \"%s\" not found, using animation %s).\n",
-		    imm.descr().name().c_str(), animname, imm.descr().get_animation_name(imm.anim_).c_str());
+		log("Warning: Immovable: %s, using animation %s instead.\n",
+		    e.what(), imm.descr().get_animation_name(imm.anim_).c_str());
 	}
 	imm.animstart_ = fr.signed_32();
 	if (packet_version >= 4) {

=== modified file 'src/logic/map_objects/map_object.cc'
--- src/logic/map_objects/map_object.cc	2017-11-13 08:03:31 +0000
+++ src/logic/map_objects/map_object.cc	2017-12-17 17:44:30 +0000
@@ -37,6 +37,7 @@
 #include "io/filewrite.h"
 #include "logic/cmd_queue.h"
 #include "logic/game.h"
+#include "logic/game_data_error.h"
 #include "logic/player.h"
 #include "logic/queue_cmd_ids.h"
 #include "map_io/map_object_loader.h"
@@ -276,14 +277,29 @@
 		const std::string anim_name = prefix + std::string("_") + dirstrings[dir - 1];
 		try {
 			anims->set_animation(dir, get_animation(anim_name));
-		} catch (const MapObjectDescr::AnimationNonexistent&) {
-			throw GameDataError("MO: no directional animation '%s'", anim_name.c_str());
+		} catch (const GameDataError& e) {
+			throw GameDataError("MO: Missing directional animation: %s", e.what());
 		}
 	}
 }
 
+uint32_t MapObjectDescr::get_animation(char const* const anim) const {
+	std::map<std::string, uint32_t>::const_iterator it = anims_.find(anim);
+	if (it == anims_.end()) {
+		throw GameDataError("Unknown animation: %s for %s", anim, name().c_str());
+	}
+	return it->second;
+}
+
+uint32_t MapObjectDescr::get_animation(const std::string& animname) const {
+	return get_animation(animname.c_str());
+}
+
+uint32_t MapObjectDescr::main_animation() const {
+	return !anims_.empty() ? anims_.begin()->second : 0;
+}
+
 std::string MapObjectDescr::get_animation_name(uint32_t const anim) const {
-
 	for (const auto& temp_anim : anims_) {
 		if (temp_anim.second == anim) {
 			return temp_anim.first;

=== modified file 'src/logic/map_objects/map_object.h'
--- src/logic/map_objects/map_object.h	2017-11-27 08:22:14 +0000
+++ src/logic/map_objects/map_object.h	2017-12-17 17:44:30 +0000
@@ -120,24 +120,10 @@
 		return type_;
 	}
 
-	struct AnimationNonexistent {};
-	uint32_t get_animation(char const* const anim) const {
-		std::map<std::string, uint32_t>::const_iterator it = anims_.find(anim);
-		if (it == anims_.end())
-			throw AnimationNonexistent();
-		return it->second;
-	}
-	uint32_t get_animation(const std::string& animname) const {
-		return get_animation(animname.c_str());
-	}
-
-	uint32_t main_animation() const {
-		return !anims_.empty() ? anims_.begin()->second : 0;
-	}
-
+	uint32_t get_animation(char const* const anim) const;
+	uint32_t get_animation(const std::string& animname) const;
+	uint32_t main_animation() const ;
 	std::string get_animation_name(uint32_t) const;  ///< needed for save, debug
-	bool has_attribute(uint32_t) const;
-	static uint32_t get_attribute_id(const std::string& name, bool add_if_not_exists = false);
 
 	bool is_animation_known(const std::string& name) const;
 	void add_animation(const std::string& name, uint32_t anim);
@@ -158,6 +144,9 @@
 	/// Returns the image fileneme for the menu image if the MapObject has one, is empty otherwise
 	const std::string& icon_filename() const;
 
+	bool has_attribute(uint32_t) const;
+	static uint32_t get_attribute_id(const std::string& name, bool add_if_not_exists = false);
+
 protected:
 	// Add all the special attributes to the attribute list. Only the 'allowed_special'
 	// attributes are allowed to appear - i.e. resi are fine for immovables.

=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc	2017-11-30 10:59:06 +0000
+++ src/logic/map_objects/tribes/building.cc	2017-12-17 17:44:30 +0000
@@ -197,6 +197,11 @@
 	hints_.set_trainingsites_max_percent(percent);
 }
 
+uint32_t BuildingDescr::get_unoccupied_animation() const {
+	return get_animation(is_animation_known("unoccupied") ? "unoccupied" : "idle");
+}
+
+
 /**
  * Normal buildings don't conquer anything, so this returns 0 by default.
  *
@@ -357,10 +362,7 @@
 	}
 
 	// Start the animation
-	if (descr().is_animation_known("unoccupied"))
-		start_animation(egbase, descr().get_animation("unoccupied"));
-	else
-		start_animation(egbase, descr().get_animation("idle"));
+	start_animation(egbase, descr().get_unoccupied_animation());
 
 	leave_time_ = egbase.get_gametime();
 	return true;

=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h	2017-11-30 10:59:06 +0000
+++ src/logic/map_objects/tribes/building.h	2017-12-17 17:44:30 +0000
@@ -167,6 +167,8 @@
 	const BuildingHints& hints() const;
 	void set_hints_trainingsites_max_percent(int percent);
 
+	uint32_t get_unoccupied_animation() const;
+
 protected:
 	virtual Building& create_object() const = 0;
 	Building& create_constructionsite() const;

=== modified file 'src/logic/map_objects/tribes/constructionsite.cc'
--- src/logic/map_objects/tribes/constructionsite.cc	2017-06-23 16:16:28 +0000
+++ src/logic/map_objects/tribes/constructionsite.cc	2017-12-17 17:44:30 +0000
@@ -39,6 +39,38 @@
 
 namespace Widelands {
 
+void ConstructionsiteInformation::draw(const Vector2f& point_on_dst,
+													float scale,
+													const RGBColor& player_color,
+													RenderTarget* dst) const {
+	// Draw the construction site marker
+	const uint32_t anim_idx = becomes->is_animation_known("build") ?
+				becomes->get_animation("build") :
+				becomes->get_unoccupied_animation();
+
+	const Animation& anim = g_gr->animations().get_animation(anim_idx);
+	const size_t nr_frames = anim.nr_frames();
+	const uint32_t cur_frame = totaltime ? completedtime * nr_frames / totaltime : 0;
+	uint32_t anim_time = cur_frame * FRAME_LENGTH;
+
+	if (cur_frame) {  //  not the first pic
+		// Draw the complete prev pic , so we won't run into trouble if images have different sizes
+		dst->blit_animation(point_on_dst, scale, anim_idx, anim_time - FRAME_LENGTH, player_color);
+	} else if (was) {
+		//  Is the first picture but there was another building here before,
+		//  get its most fitting picture and draw it instead.
+		dst->blit_animation(
+		   point_on_dst, scale, was->get_unoccupied_animation(), anim_time - FRAME_LENGTH, player_color);
+	}
+	// Now blit a segment of the current construction phase from the bottom.
+	int percent = 100 * completedtime * nr_frames;
+	if (totaltime) {
+		percent /= totaltime;
+	}
+	percent -= 100 * cur_frame;
+	dst->blit_animation(point_on_dst, scale, anim_idx, anim_time, player_color, percent);
+}
+
 /**
   * The contents of 'table' are documented in
   * /data/tribes/buildings/partially_finished/constructionsite/init.lua
@@ -323,42 +355,7 @@
 		info_.completedtime += CONSTRUCTIONSITE_STEP_TIME + gametime - work_steptime_;
 	}
 
-	uint32_t anim_idx;
-	try {
-		anim_idx = building().get_animation("build");
-	} catch (MapObjectDescr::AnimationNonexistent&) {
-		try {
-			anim_idx = building().get_animation("unoccupied");
-		} catch (MapObjectDescr::AnimationNonexistent) {
-			anim_idx = building().get_animation("idle");
-		}
-	}
-	const Animation& anim = g_gr->animations().get_animation(anim_idx);
-	const size_t nr_frames = anim.nr_frames();
-	const uint32_t cur_frame =
-	   info_.totaltime ? info_.completedtime * nr_frames / info_.totaltime : 0;
-	tanim = cur_frame * FRAME_LENGTH;
-
-	if (cur_frame) {  //  not the first pic
-		// Draw the complete prev pic , so we won't run into trouble if images have different sizes
-		dst->blit_animation(point_on_dst, scale, anim_idx, tanim - FRAME_LENGTH, player_color);
-	} else if (!old_buildings_.empty()) {
-		DescriptionIndex prev_idx = old_buildings_.back();
-		const BuildingDescr* prev_building = owner().tribe().get_building_descr(prev_idx);
-		//  Is the first picture but there was another building here before,
-		//  get its most fitting picture and draw it instead.
-		const uint32_t prev_building_anim_idx = prev_building->get_animation(
-		   prev_building->is_animation_known("unoccupied") ? "unoccupied" : "idle");
-		dst->blit_animation(
-		   point_on_dst, scale, prev_building_anim_idx, tanim - FRAME_LENGTH, player_color);
-	}
-	// Now blit a segment of the current construction phase from the bottom.
-	int percent = 100 * info_.completedtime * nr_frames;
-	if (info_.totaltime) {
-		percent /= info_.totaltime;
-	}
-	percent -= 100 * cur_frame;
-	dst->blit_animation(point_on_dst, scale, anim_idx, tanim, player_color, percent);
+	info_.draw(point_on_dst, scale, player_color, dst);
 
 	// Draw help strings
 	draw_info(draw_text, point_on_dst, scale, dst);

=== modified file 'src/logic/map_objects/tribes/constructionsite.h'
--- src/logic/map_objects/tribes/constructionsite.h	2017-06-24 08:47:46 +0000
+++ src/logic/map_objects/tribes/constructionsite.h	2017-12-17 17:44:30 +0000
@@ -36,6 +36,13 @@
 struct ConstructionsiteInformation {
 	ConstructionsiteInformation() : becomes(nullptr), was(nullptr), totaltime(0), completedtime(0) {
 	}
+
+	/// Draw the partly finished constructionsite
+	void draw(const Vector2f& point_on_dst,
+				 float scale,
+				 const RGBColor& player_color,
+				 RenderTarget* dst) const;
+
 	const BuildingDescr*
 	   becomes;  // Also works as a marker telling whether there is a construction site.
 	const BuildingDescr* was;  // only valid if "becomes" is an enhanced building.

=== modified file 'src/logic/map_objects/tribes/dismantlesite.cc'
--- src/logic/map_objects/tribes/dismantlesite.cc	2017-08-18 17:32:16 +0000
+++ src/logic/map_objects/tribes/dismantlesite.cc	2017-12-17 17:44:30 +0000
@@ -229,10 +229,8 @@
 	dst->blit_animation(point_on_dst, scale, anim_, tanim, player_color);
 
 	// Blit bottom part of the animation according to dismantle progress
-	const uint32_t anim_idx =
-	   building_->get_animation(building_->is_animation_known("unoccupied") ? "unoccupied" : "idle");
 	dst->blit_animation(
-	   point_on_dst, scale, anim_idx, tanim, player_color, 100 - ((get_built_per64k() * 100) >> 16));
+	   point_on_dst, scale, building_->get_unoccupied_animation(), tanim, player_color, 100 - ((get_built_per64k() * 100) >> 16));
 
 	// Draw help strings
 	draw_info(draw_text, point_on_dst, scale, dst);

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2017-08-20 17:45:42 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2017-12-17 17:44:30 +0000
@@ -1403,8 +1403,8 @@
 	// Dead soldier is not owned by a location
 	set_location(nullptr);
 
-	start_task_idle(
-	   game, descr().get_animation(combat_walking_ == CD_COMBAT_W ? "die_w" : "die_e"), 1000);
+	const uint32_t anim = descr().get_rand_anim(game, combat_walking_ == CD_COMBAT_W ? "die_w" : "die_e");
+	start_task_idle(game, anim, 1000);
 }
 
 void Soldier::die_update(Game& game, State& state) {

=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc	2017-09-22 20:47:13 +0000
+++ src/map_io/map_buildingdata_packet.cc	2017-12-17 17:44:30 +0000
@@ -36,6 +36,7 @@
 #include "io/filewrite.h"
 #include "logic/editor_game_base.h"
 #include "logic/game.h"
+#include "logic/game_data_error.h"
 #include "logic/map.h"
 #include "logic/map_objects/tribes/constructionsite.h"
 #include "logic/map_objects/tribes/dismantlesite.h"
@@ -93,12 +94,11 @@
 						char const* const animation_name = fr.c_string();
 						try {
 							building.anim_ = building.descr().get_animation(animation_name);
-						} catch (const MapObjectDescr::AnimationNonexistent&) {
-							log("WARNING: %s %s does not have animation \"%s\"; "
-							    "using animation \"idle\" instead\n",
-							    building.owner().tribe().name().c_str(),
-							    building.descr().descname().c_str(), animation_name);
+						} catch (const GameDataError& e) {
 							building.anim_ = building.descr().get_animation("idle");
+							log("Warning: Tribe %s building: %s, using animation %s instead.\n",
+								 building.owner().tribe().name().c_str(),
+							    e.what(), building.descr().get_animation_name(building.anim_).c_str());
 						}
 					} else {
 						building.anim_ = 0;

=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc	2017-10-24 05:38:53 +0000
+++ src/wui/interactive_player.cc	2017-12-17 17:44:30 +0000
@@ -130,57 +130,12 @@
 	}
 	if (player_field.constructionsite.becomes) {
 		assert(field.owner != nullptr);
-		const Widelands::ConstructionsiteInformation& csinf = player_field.constructionsite;
-		// draw the partly finished constructionsite
-		uint32_t anim_idx;
-		try {
-			anim_idx = csinf.becomes->get_animation("build");
-		} catch (Widelands::MapObjectDescr::AnimationNonexistent&) {
-			try {
-				anim_idx = csinf.becomes->get_animation("unoccupied");
-			} catch (Widelands::MapObjectDescr::AnimationNonexistent) {
-				anim_idx = csinf.becomes->get_animation("idle");
-			}
-		}
-		const Animation& anim = g_gr->animations().get_animation(anim_idx);
-		const size_t nr_frames = anim.nr_frames();
-		uint32_t cur_frame = csinf.totaltime ? csinf.completedtime * nr_frames / csinf.totaltime : 0;
-		uint32_t tanim = cur_frame * FRAME_LENGTH;
-
-		uint32_t percent = 100 * csinf.completedtime * nr_frames;
-		if (csinf.totaltime) {
-			percent /= csinf.totaltime;
-		}
-		percent -= 100 * cur_frame;
-
-		if (cur_frame) {  // not the first frame
-			// Draw the prev frame
-			dst->blit_animation(field.rendertarget_pixel, scale, anim_idx, tanim - FRAME_LENGTH,
-			                    field.owner->get_playercolor());
-		} else if (csinf.was) {
-			// Is the first frame, but there was another building here before,
-			// get its last build picture and draw it instead.
-			uint32_t a;
-			try {
-				a = csinf.was->get_animation("unoccupied");
-			} catch (Widelands::MapObjectDescr::AnimationNonexistent&) {
-				a = csinf.was->get_animation("idle");
-			}
-			dst->blit_animation(field.rendertarget_pixel, scale, a, tanim - FRAME_LENGTH,
-			                    field.owner->get_playercolor());
-		}
-		dst->blit_animation(
-		   field.rendertarget_pixel, scale, anim_idx, tanim, field.owner->get_playercolor(), percent);
+		player_field.constructionsite.draw(field.rendertarget_pixel, scale, field.owner->get_playercolor(), dst);
+
 	} else if (upcast(const Widelands::BuildingDescr, building, player_field.map_object_descr)) {
 		assert(field.owner != nullptr);
 		// this is a building therefore we either draw unoccupied or idle animation
-		uint32_t pic;
-		try {
-			pic = building->get_animation("unoccupied");
-		} catch (Widelands::MapObjectDescr::AnimationNonexistent&) {
-			pic = building->get_animation("idle");
-		}
-		dst->blit_animation(field.rendertarget_pixel, scale, pic, 0, field.owner->get_playercolor());
+		dst->blit_animation(field.rendertarget_pixel, scale, building->get_unoccupied_animation(), 0, field.owner->get_playercolor());
 	} else if (player_field.map_object_descr->type() == Widelands::MapObjectType::FLAG) {
 		assert(field.owner != nullptr);
 		dst->blit_animation(field.rendertarget_pixel, scale, field.owner->tribe().flag_animation(), 0,


Follow ups