View Issue Details

IDProjectCategoryView StatusLast Update
0003073FSSCPgraphicspublic2014-07-30 10:09
Reporterngld Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Summary0003073: Additional Mainhall capabilities (Cheats and "+Misc anim over doors:")
DescriptionThis patch adds three new mainhall.tbl options:
* "+Misc anim over doors:" (after "+Misc anim flags:")
  This option renders the given misc anim after the doors.
* "+Cheat String:", "+Anim To Change:" and "+Anim To Change To:" (after "+Name:")
  This option exchanges misc anims once the given cheat code has been entered.

The patch is attached.
The test mainhall is here: https://dl.dropboxusercontent.com/u/6681376/main_hall_ext_test.7z
You have to replace the data/tables/krios-hall.tbm with this one: http://pastebin.com/iybzSJ9Y
TagsNo tags attached.

Activities

ngld

2014-07-03 16:42

reporter  

mainhall_anims.patch (8,496 bytes)   
diff --git a/code/menuui/mainhallmenu.cpp b/code/menuui/mainhallmenu.cpp
index b63ab58..618e015 100644
--- a/code/menuui/mainhallmenu.cpp
+++ b/code/menuui/mainhallmenu.cpp
@@ -44,6 +44,8 @@
 #endif
 
 
+// A reference to io/keycontrol.cpp
+extern void game_process_cheats(int k);
 
 // ----------------------------------------------------------------------------
 // MAIN HALL DATA DEFINES
@@ -60,7 +62,7 @@ main_hall_defines *Main_hall = NULL;
 int Vasudan_funny = 0;
 int Vasudan_funny_plate = -1;
 
-char Main_hall_campaign_cheat[512] = "";
+SCP_string Main_hall_cheat = "";
 
 // ----------------------------------------------------------------------------
 // MISC interface data
@@ -132,7 +134,7 @@ void main_hall_handle_random_intercom_sounds();
 SCP_vector<generic_anim> Main_hall_misc_anim;
 
 // render all playing misc animations
-void main_hall_render_misc_anims(float frametime);
+void main_hall_render_misc_anims(float frametime, bool over_doors);
 
 
 // ----------------------------------------------------------------------------
@@ -573,8 +575,6 @@ void main_hall_init(const SCP_string &main_hall_name)
 
 	Main_hall_region_linger_stamp = -1;
 
-	strcpy_s(Main_hall_campaign_cheat, "");
-
 	// initialize door sound handles
 	Main_hall_door_sound_handles.clear();
 	for (idx = 0; idx < Main_hall->num_door_animations; idx++) {
@@ -662,8 +662,91 @@ void main_hall_do(float frametime)
 	code = snazzy_menu_do(Main_hall_mask_data, Main_hall_mask_w, Main_hall_mask_h, Main_hall_num_options, Main_hall_region, &snazzy_action, 1, &key);
 
 	if (key) {
-		extern void game_process_cheats(int k);
 		game_process_cheats(key);
+		
+		Main_hall_cheat += (char) key_to_ascii(key);
+		if(Main_hall_cheat.length() > 40) {
+			Main_hall_cheat = Main_hall_cheat.substr(Main_hall_cheat.length() - 40);
+		}
+		
+		int cur_frame;
+		float anim_time;
+		bool cheat_anim_found, cheat_found = false;
+		
+		for (int c_idx = 0; c_idx < (int) Main_hall->cheat.size(); c_idx++) {
+			cheat_anim_found = false;
+			
+			if(Main_hall_cheat.find(Main_hall->cheat.at(c_idx)) != SCP_string::npos) {
+				cheat_found = true;
+				// switch animations
+				
+				for (int idx = 0; idx < Main_hall->num_misc_animations; idx++) {
+					if (Main_hall->misc_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+						Main_hall->misc_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+						
+						cur_frame = Main_hall_misc_anim.at(idx).current_frame;
+						anim_time = Main_hall_misc_anim.at(idx).anim_time;
+						
+						generic_anim_unload(&Main_hall_misc_anim.at(idx));
+						generic_anim_init(&Main_hall_misc_anim.at(idx), Main_hall->misc_anim_name.at(idx));
+						
+						if (generic_anim_stream(&Main_hall_misc_anim.at(idx)) == -1) {
+							nprintf(("General","WARNING! Could not load misc %s anim in main hall\n", Main_hall->misc_anim_name.at(idx).c_str()));
+						} else {
+							// start paused
+							if (Main_hall->misc_anim_modes.at(idx) == MISC_ANIM_MODE_HOLD)
+								Main_hall_misc_anim.at(idx).direction |= GENERIC_ANIM_DIRECTION_NOLOOP;
+						}
+						
+						Main_hall_misc_anim.at(idx).current_frame = cur_frame;
+						Main_hall_misc_anim.at(idx).anim_time = anim_time;
+
+						// null out the delay timestamps
+						Main_hall->misc_anim_delay.at(idx).at(0) = -1;
+
+						cheat_anim_found = true;
+						break;
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					for (int idx = 0; idx < Main_hall->num_door_animations; idx++) {
+						if (Main_hall->door_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+							Main_hall->door_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+							
+							cur_frame = Main_hall_door_anim.at(idx).current_frame;
+							anim_time = Main_hall_door_anim.at(idx).anim_time;
+							
+							generic_anim_unload(&Main_hall_door_anim.at(idx));
+							generic_anim_init(&Main_hall_door_anim.at(idx), Main_hall->door_anim_name.at(idx));
+							
+							if (generic_anim_stream(&Main_hall_door_anim.at(idx)) == -1) {
+								nprintf(("General","WARNING! Could not load door anim %s in main hall\n", Main_hall->door_anim_name.at(idx).c_str()));
+							} else {
+								Main_hall_door_anim.at(idx).direction = GENERIC_ANIM_DIRECTION_BACKWARDS | GENERIC_ANIM_DIRECTION_NOLOOP;
+							}
+							
+							Main_hall_door_anim.at(idx).current_frame = cur_frame;
+							Main_hall_door_anim.at(idx).anim_time = anim_time;
+							
+							cheat_anim_found = true;
+							break;
+						}
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					// Note: This can also happen if the cheat triggers a second time since the animations are already switched at that point.
+					nprintf(("General", "Could not find animation '%s' for cheat '%s'!", Main_hall->cheat_anim_from.at(c_idx).c_str(), Main_hall->cheat.at(c_idx).c_str()));
+				}
+			}
+		}
+		
+		if(cheat_found) {
+			// Found a cheat, clear the buffer.
+			
+			Main_hall_cheat = "";
+		}
 	}
 
 	switch(key) {
@@ -709,11 +792,7 @@ void main_hall_do(float frametime)
 						gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
 						main_hall_do_multi_ready();
 					} else {
-						if (strlen(Main_hall_campaign_cheat)) {
-							gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
-						} else {
-							gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
-						}
+						gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
 						gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
 					}
 					break;
@@ -825,10 +904,13 @@ void main_hall_do(float frametime)
 	}
 
 	// render misc animations
-	main_hall_render_misc_anims(frametime);
+	main_hall_render_misc_anims(frametime, false);
 
 	// render door animtions
 	main_hall_render_door_anims(frametime);
+	
+	// render misc animations (over doors)
+	main_hall_render_misc_anims(frametime, true);
 
 	// blit any appropriate tooltips
 	main_hall_maybe_blit_tooltips();
@@ -1050,7 +1132,7 @@ void main_hall_stop_music(bool fade)
  * 
  * @param frametime Animation frame time
  */
-void main_hall_render_misc_anims(float frametime)
+void main_hall_render_misc_anims(float frametime, bool over_doors)
 {
 	std::deque<bool> group_anims_weve_checked;
 	int idx, s_idx, jdx;
@@ -1061,7 +1143,7 @@ void main_hall_render_misc_anims(float frametime)
 		group_anims_weve_checked.push_back(false);
 
 		// render it
-		if (Main_hall_misc_anim.at(idx).num_frames > 0) {
+		if (Main_hall_misc_anim.at(idx).num_frames > 0 && Main_hall->misc_anim_over_doors.at(idx) == over_doors) {
 			// animation is paused
 			if (Main_hall->misc_anim_paused.at(idx)) {
 				// if the timestamp is -1, then regenerate it
@@ -1996,6 +2078,20 @@ void parse_main_hall_table(const char* filename)
 
 				m->name = Main_hall_defines.at(count).at(0).name;
 			}
+			
+			// add cheats
+			while (optional_string("+Cheat String:")) {
+				stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
+				m->cheat.push_back(temp_string);
+				
+				required_string("+Anim To Change:");
+				stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
+				m->cheat_anim_from.push_back(temp_string);
+				
+				required_string("+Anim To Change To:");
+				stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
+				m->cheat_anim_to.push_back(temp_string);
+			}
 
 			// minimum resolution
 			if (optional_string("+Min Resolution:")) {
@@ -2165,6 +2261,16 @@ void parse_main_hall_table(const char* filename)
 					m->misc_anim_sound_flag.at(idx).push_back(0);
 				}
 			}
+			
+			for (idx = 0; idx < m->num_misc_animations; idx++) {
+				// render over doors - default to false
+				m->misc_anim_over_doors.push_back(0);
+				
+				if (optional_string("+Misc anim over doors:")) {
+					stuff_boolean(&rval);
+					m->misc_anim_over_doors.at(idx) = rval;
+				}
+			}
 
 			// door animations
 			required_string("+Num Door Animations:");
diff --git a/code/menuui/mainhallmenu.h b/code/menuui/mainhallmenu.h
index 6ef6915..e771e33 100644
--- a/code/menuui/mainhallmenu.h
+++ b/code/menuui/mainhallmenu.h
@@ -19,6 +19,10 @@
 typedef struct main_hall_defines {
 	// mainhall name identifier
 	SCP_string name;
+	
+	SCP_vector<SCP_string> cheat;
+	SCP_vector<SCP_string> cheat_anim_from;
+	SCP_vector<SCP_string> cheat_anim_to;
 
 	// minimum resolution and aspect ratio needed to display this main hall
 	int min_width;
@@ -90,6 +94,9 @@ typedef struct main_hall_defines {
 
 	//flags for each of the misc anim sounds
 	SCP_vector<SCP_vector<int> > misc_anim_sound_flag;
+	
+	// controls the render order
+	SCP_vector<bool> misc_anim_over_doors;
 
 
 	// door animations --------------------
mainhall_anims.patch (8,496 bytes)   

MjnMixael

2014-07-03 16:43

manager   ~0016015

I have tested the patch and it works. :)

niffiwan

2014-07-17 23:16

developer   ~0016085

Does this patch depend on 0003071 at all?

MjnMixael

2014-07-17 23:44

manager   ~0016087

Last edited: 2014-07-18 01:46

I'm 99% sure they are exclusive from each other.

EDIT: Clarification. The feature don't depend on the features in the other patch at all. I'm also pretty sure the patches work exclusively of each other.

ngld

2014-07-18 09:27

reporter   ~0016094

The patch is completly independent (you can apply it straight to trunk).
It should work but it still uses at() to access vector elements and no iterators.

I can update it according to Goober's advice but I never got a response from him on the other bug.

The_E

2014-07-20 17:59

administrator   ~0016099

Patch needs to be in svn format to make it into 3.7.2

niffiwan

2014-07-21 03:31

developer   ~0016109

I've got off my lazy rear and have reviewed the patch - comments below:

if(Main_hall_cheat.length() > 40) {
    Main_hall_cheat = Main_hall_cheat.substr(Main_hall_cheat.length() - 40);

I'm not fond of magic numbers, could the 40 be replaced with a name, either a #define or a const int variable? I'm guessing that the purpose is to keep 40 chars in a rolling buffer and search for valid cheat strings in this buffer. If that's correct then a warning should be generated when parsing "+Cheat String" if the string is greater than 40 chars in length.
Also the 40 is much less than the previous limit of 512? (which admittedly seems rather excessive) Is there a limit of 40 elsewhere in cheat-code handling? I guess I'm just wondering what prompted the selection of this size?

In addition, maybe use size() instead of length to be consistent with the other new code. It also seems that other FSO vectors prefer the use of size().


for (int c_idx = 0; c_idx < (int) Main_hall->cheat.size(); c_idx++) {

It would probably be a good idea to use an iterator here rather than an int (per the other patch).


Lastly, I don't mind the use of .at() without exceptions in place to catch the error. Firstly, FSO doesn't currently have a defined exception handling scheme/hierarachy in place. Secondly, an exception from .at() will crash FSO and that seems like a perfectly reasonable response to the attempt to access out-of-bounds data :)

ngld

2014-07-29 18:03

reporter  

mainhall_anims2.patch (8,825 bytes)   
Index: code/menuui/mainhallmenu.cpp
===================================================================
--- code/menuui/mainhallmenu.cpp	(revision 10960)
+++ code/menuui/mainhallmenu.cpp	(working copy)
@@ -45,6 +45,8 @@
 #endif
 
 
+// A reference to io/keycontrol.cpp
+extern void game_process_cheats(int k);
 
 // ----------------------------------------------------------------------------
 // MAIN HALL DATA DEFINES
@@ -53,6 +55,7 @@
 #define MISC_ANIM_MODE_HOLD			1		// play to the end and hold the animation
 #define MISC_ANIM_MODE_TIMED		2		// uses timestamps to determine when a finished anim should be checked again
 #define NUM_REGIONS					7		// (6 + 1 for multiplayer equivalent of campaign room)
+#define MAIN_HALL_MAX_CHEAT_LEN		40		// cheat buffer length (also maximum cheat length)
 
 SCP_vector< SCP_vector<main_hall_defines> > Main_hall_defines;
 
@@ -61,7 +64,7 @@
 int Vasudan_funny = 0;
 int Vasudan_funny_plate = -1;
 
-char Main_hall_campaign_cheat[512] = "";
+SCP_string Main_hall_cheat = "";
 
 // ----------------------------------------------------------------------------
 // MISC interface data
@@ -133,7 +136,7 @@
 SCP_vector<generic_anim> Main_hall_misc_anim;
 
 // render all playing misc animations
-void main_hall_render_misc_anims(float frametime);
+void main_hall_render_misc_anims(float frametime, bool over_doors);
 
 
 // ----------------------------------------------------------------------------
@@ -595,8 +598,6 @@
 
 	Main_hall_region_linger_stamp = -1;
 
-	strcpy_s(Main_hall_campaign_cheat, "");
-
 	// initialize door sound handles
 	Main_hall_door_sound_handles.clear();
 	for (idx = 0; idx < Main_hall->num_door_animations; idx++) {
@@ -685,8 +686,91 @@
 	code = snazzy_menu_do(Main_hall_mask_data, Main_hall_mask_w, Main_hall_mask_h, (int)Main_hall->regions.size(), Main_hall_region, &snazzy_action, 1, &key);
 
 	if (key) {
-		extern void game_process_cheats(int k);
 		game_process_cheats(key);
+		
+		Main_hall_cheat += (char) key_to_ascii(key);
+		if(Main_hall_cheat.size() > MAIN_HALL_MAX_CHEAT_LEN) {
+			Main_hall_cheat = Main_hall_cheat.substr(Main_hall_cheat.size() - MAIN_HALL_MAX_CHEAT_LEN);
+		}
+		
+		int cur_frame;
+		float anim_time;
+		bool cheat_anim_found, cheat_found = false;
+		
+		for (int c_idx = 0; c_idx < (int) Main_hall->cheat.size(); c_idx++) {
+			cheat_anim_found = false;
+			
+			if(Main_hall_cheat.find(Main_hall->cheat.at(c_idx)) != SCP_string::npos) {
+				cheat_found = true;
+				// switch animations
+				
+				for (int idx = 0; idx < Main_hall->num_misc_animations; idx++) {
+					if (Main_hall->misc_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+						Main_hall->misc_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+						
+						cur_frame = Main_hall_misc_anim.at(idx).current_frame;
+						anim_time = Main_hall_misc_anim.at(idx).anim_time;
+						
+						generic_anim_unload(&Main_hall_misc_anim.at(idx));
+						generic_anim_init(&Main_hall_misc_anim.at(idx), Main_hall->misc_anim_name.at(idx));
+						
+						if (generic_anim_stream(&Main_hall_misc_anim.at(idx)) == -1) {
+							nprintf(("General","WARNING! Could not load misc %s anim in main hall\n", Main_hall->misc_anim_name.at(idx).c_str()));
+						} else {
+							// start paused
+							if (Main_hall->misc_anim_modes.at(idx) == MISC_ANIM_MODE_HOLD)
+								Main_hall_misc_anim.at(idx).direction |= GENERIC_ANIM_DIRECTION_NOLOOP;
+						}
+						
+						Main_hall_misc_anim.at(idx).current_frame = cur_frame;
+						Main_hall_misc_anim.at(idx).anim_time = anim_time;
+
+						// null out the delay timestamps
+						Main_hall->misc_anim_delay.at(idx).at(0) = -1;
+
+						cheat_anim_found = true;
+						break;
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					for (int idx = 0; idx < Main_hall->num_door_animations; idx++) {
+						if (Main_hall->door_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+							Main_hall->door_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+							
+							cur_frame = Main_hall_door_anim.at(idx).current_frame;
+							anim_time = Main_hall_door_anim.at(idx).anim_time;
+							
+							generic_anim_unload(&Main_hall_door_anim.at(idx));
+							generic_anim_init(&Main_hall_door_anim.at(idx), Main_hall->door_anim_name.at(idx));
+							
+							if (generic_anim_stream(&Main_hall_door_anim.at(idx)) == -1) {
+								nprintf(("General","WARNING! Could not load door anim %s in main hall\n", Main_hall->door_anim_name.at(idx).c_str()));
+							} else {
+								Main_hall_door_anim.at(idx).direction = GENERIC_ANIM_DIRECTION_BACKWARDS | GENERIC_ANIM_DIRECTION_NOLOOP;
+							}
+							
+							Main_hall_door_anim.at(idx).current_frame = cur_frame;
+							Main_hall_door_anim.at(idx).anim_time = anim_time;
+							
+							cheat_anim_found = true;
+							break;
+						}
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					// Note: This can also happen if the cheat triggers a second time since the animations are already switched at that point.
+					nprintf(("General", "Could not find animation '%s' for cheat '%s'!", Main_hall->cheat_anim_from.at(c_idx).c_str(), Main_hall->cheat.at(c_idx).c_str()));
+				}
+			}
+		}
+		
+		if(cheat_found) {
+			// Found a cheat, clear the buffer.
+			
+			Main_hall_cheat = "";
+		}
 	}
 
 	switch(key) {
@@ -759,11 +843,7 @@
 					Player->flags &= ~PLAYER_FLAGS_IS_MULTI;
 					Game_mode = GM_NORMAL;
 					
-					if (strlen(Main_hall_campaign_cheat)) {
-						gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
-					} else {
-						gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
-					}
+					gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
 					gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
 					break;
 
@@ -873,10 +953,13 @@
 	}
 
 	// render misc animations
-	main_hall_render_misc_anims(frametime);
+	main_hall_render_misc_anims(frametime, false);
 
 	// render door animtions
 	main_hall_render_door_anims(frametime);
+	
+	// render misc animations (over doors)
+	main_hall_render_misc_anims(frametime, true);
 
 	// blit any appropriate tooltips
 	main_hall_maybe_blit_tooltips();
@@ -1098,7 +1181,7 @@
  * 
  * @param frametime Animation frame time
  */
-void main_hall_render_misc_anims(float frametime)
+void main_hall_render_misc_anims(float frametime, bool over_doors)
 {
 	std::deque<bool> group_anims_weve_checked;
 	int idx, s_idx, jdx;
@@ -1109,7 +1192,7 @@
 		group_anims_weve_checked.push_back(false);
 
 		// render it
-		if (Main_hall_misc_anim.at(idx).num_frames > 0) {
+		if (Main_hall_misc_anim.at(idx).num_frames > 0 && Main_hall->misc_anim_over_doors.at(idx) == over_doors) {
 			// animation is paused
 			if (Main_hall->misc_anim_paused.at(idx)) {
 				// if the timestamp is -1, then regenerate it
@@ -2051,7 +2134,27 @@
 
 				m->name = Main_hall_defines.at(count).at(0).name;
 			}
+			
+			// add cheats
+			while (optional_string("+Cheat String:")) {
+				stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
+				m->cheat.push_back(temp_string);
 
+				if(strlen(temp_string) > MAIN_HALL_MAX_CHEAT_LEN) {
+					// Since the value is longer than the cheat buffer it will never match.
+
+					Warning(LOCATION, "The value '%s' for '+Cheat String:' is too long! It can be at most %d characters long.", temp_string, MAIN_HALL_MAX_CHEAT_LEN);
+				}
+				
+				required_string("+Anim To Change:");
+				stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
+				m->cheat_anim_from.push_back(temp_string);
+				
+				required_string("+Anim To Change To:");
+				stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
+				m->cheat_anim_to.push_back(temp_string);
+			}
+
 			// minimum resolution
 			if (optional_string("+Min Resolution:")) {
 				stuff_int(&m->min_width);
@@ -2221,6 +2324,17 @@
 				}
 			}
 			
+			for (idx = 0; idx < m->num_misc_animations; idx++) {
+				// render over doors - default to false
+				
+				if (optional_string("+Misc anim over doors:")) {
+					stuff_boolean(&rval);
+					m->misc_anim_over_doors.push_back(rval);
+				} else {
+					m->misc_anim_over_doors.push_back(0);
+				}
+			}
+
 			region_info_init(*m);
 			
 			int mask;
Index: code/menuui/mainhallmenu.h
===================================================================
--- code/menuui/mainhallmenu.h	(revision 10960)
+++ code/menuui/mainhallmenu.h	(working copy)
@@ -26,6 +26,10 @@
 typedef struct main_hall_defines {
 	// mainhall name identifier
 	SCP_string name;
+	
+	SCP_vector<SCP_string> cheat;
+	SCP_vector<SCP_string> cheat_anim_from;
+	SCP_vector<SCP_string> cheat_anim_to;
 
 	// minimum resolution and aspect ratio needed to display this main hall
 	int min_width;
@@ -97,6 +101,9 @@
 
 	//flags for each of the misc anim sounds
 	SCP_vector<SCP_vector<int> > misc_anim_sound_flag;
+	
+	// controls the render order
+	SCP_vector<bool> misc_anim_over_doors;
 
 
 	// door animations --------------------
mainhall_anims2.patch (8,825 bytes)   

ngld

2014-07-29 18:11

reporter   ~0016143

I've uploaded a new patch. This time it's in svn format.

I've defined the new constant MAIN_HALL_MAX_CHEAT_LEN which now holds the length of the rolling buffer. I've picked 40 for no particular reason, I just thought that would be long enough for cheat codes. I also added a warning, if the "+Cheat String" is too long.

I could use an iterator but then I'd have to calculate the index for each item to access Main_hall->cheat_anim_from and Main_hall->cheat_anim_to. I don't see the benefit in this case.

m_m

2014-07-29 20:13

developer   ~0016144

When parsing the "+Cheat String" values you stuff the string into a char array although you always assign the string value to a SCP_string.
You could just stuff that into a SCP_string and push that into the vector which would also get rid of the hard-coded string length limits.

Apart from that it looks good to me.

ngld

2014-07-29 21:23

reporter  

mainhall_anims3.patch (8,809 bytes)   
Index: code/menuui/mainhallmenu.cpp
===================================================================
--- code/menuui/mainhallmenu.cpp	(revision 10960)
+++ code/menuui/mainhallmenu.cpp	(working copy)
@@ -45,6 +45,8 @@
 #endif
 
 
+// A reference to io/keycontrol.cpp
+extern void game_process_cheats(int k);
 
 // ----------------------------------------------------------------------------
 // MAIN HALL DATA DEFINES
@@ -53,6 +55,7 @@
 #define MISC_ANIM_MODE_HOLD			1		// play to the end and hold the animation
 #define MISC_ANIM_MODE_TIMED		2		// uses timestamps to determine when a finished anim should be checked again
 #define NUM_REGIONS					7		// (6 + 1 for multiplayer equivalent of campaign room)
+#define MAIN_HALL_MAX_CHEAT_LEN		40		// cheat buffer length (also maximum cheat length)
 
 SCP_vector< SCP_vector<main_hall_defines> > Main_hall_defines;
 
@@ -61,7 +64,7 @@
 int Vasudan_funny = 0;
 int Vasudan_funny_plate = -1;
 
-char Main_hall_campaign_cheat[512] = "";
+SCP_string Main_hall_cheat = "";
 
 // ----------------------------------------------------------------------------
 // MISC interface data
@@ -133,7 +136,7 @@
 SCP_vector<generic_anim> Main_hall_misc_anim;
 
 // render all playing misc animations
-void main_hall_render_misc_anims(float frametime);
+void main_hall_render_misc_anims(float frametime, bool over_doors);
 
 
 // ----------------------------------------------------------------------------
@@ -595,8 +598,6 @@
 
 	Main_hall_region_linger_stamp = -1;
 
-	strcpy_s(Main_hall_campaign_cheat, "");
-
 	// initialize door sound handles
 	Main_hall_door_sound_handles.clear();
 	for (idx = 0; idx < Main_hall->num_door_animations; idx++) {
@@ -685,8 +686,91 @@
 	code = snazzy_menu_do(Main_hall_mask_data, Main_hall_mask_w, Main_hall_mask_h, (int)Main_hall->regions.size(), Main_hall_region, &snazzy_action, 1, &key);
 
 	if (key) {
-		extern void game_process_cheats(int k);
 		game_process_cheats(key);
+		
+		Main_hall_cheat += (char) key_to_ascii(key);
+		if(Main_hall_cheat.size() > MAIN_HALL_MAX_CHEAT_LEN) {
+			Main_hall_cheat = Main_hall_cheat.substr(Main_hall_cheat.size() - MAIN_HALL_MAX_CHEAT_LEN);
+		}
+		
+		int cur_frame;
+		float anim_time;
+		bool cheat_anim_found, cheat_found = false;
+		
+		for (int c_idx = 0; c_idx < (int) Main_hall->cheat.size(); c_idx++) {
+			cheat_anim_found = false;
+			
+			if(Main_hall_cheat.find(Main_hall->cheat.at(c_idx)) != SCP_string::npos) {
+				cheat_found = true;
+				// switch animations
+				
+				for (int idx = 0; idx < Main_hall->num_misc_animations; idx++) {
+					if (Main_hall->misc_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+						Main_hall->misc_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+						
+						cur_frame = Main_hall_misc_anim.at(idx).current_frame;
+						anim_time = Main_hall_misc_anim.at(idx).anim_time;
+						
+						generic_anim_unload(&Main_hall_misc_anim.at(idx));
+						generic_anim_init(&Main_hall_misc_anim.at(idx), Main_hall->misc_anim_name.at(idx));
+						
+						if (generic_anim_stream(&Main_hall_misc_anim.at(idx)) == -1) {
+							nprintf(("General","WARNING! Could not load misc %s anim in main hall\n", Main_hall->misc_anim_name.at(idx).c_str()));
+						} else {
+							// start paused
+							if (Main_hall->misc_anim_modes.at(idx) == MISC_ANIM_MODE_HOLD)
+								Main_hall_misc_anim.at(idx).direction |= GENERIC_ANIM_DIRECTION_NOLOOP;
+						}
+						
+						Main_hall_misc_anim.at(idx).current_frame = cur_frame;
+						Main_hall_misc_anim.at(idx).anim_time = anim_time;
+
+						// null out the delay timestamps
+						Main_hall->misc_anim_delay.at(idx).at(0) = -1;
+
+						cheat_anim_found = true;
+						break;
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					for (int idx = 0; idx < Main_hall->num_door_animations; idx++) {
+						if (Main_hall->door_anim_name.at(idx) == Main_hall->cheat_anim_from.at(c_idx)) {
+							Main_hall->door_anim_name.at(idx) = Main_hall->cheat_anim_to.at(c_idx);
+							
+							cur_frame = Main_hall_door_anim.at(idx).current_frame;
+							anim_time = Main_hall_door_anim.at(idx).anim_time;
+							
+							generic_anim_unload(&Main_hall_door_anim.at(idx));
+							generic_anim_init(&Main_hall_door_anim.at(idx), Main_hall->door_anim_name.at(idx));
+							
+							if (generic_anim_stream(&Main_hall_door_anim.at(idx)) == -1) {
+								nprintf(("General","WARNING! Could not load door anim %s in main hall\n", Main_hall->door_anim_name.at(idx).c_str()));
+							} else {
+								Main_hall_door_anim.at(idx).direction = GENERIC_ANIM_DIRECTION_BACKWARDS | GENERIC_ANIM_DIRECTION_NOLOOP;
+							}
+							
+							Main_hall_door_anim.at(idx).current_frame = cur_frame;
+							Main_hall_door_anim.at(idx).anim_time = anim_time;
+							
+							cheat_anim_found = true;
+							break;
+						}
+					}
+				}
+				
+				if (!cheat_anim_found) {
+					// Note: This can also happen if the cheat triggers a second time since the animations are already switched at that point.
+					nprintf(("General", "Could not find animation '%s' for cheat '%s'!", Main_hall->cheat_anim_from.at(c_idx).c_str(), Main_hall->cheat.at(c_idx).c_str()));
+				}
+			}
+		}
+		
+		if(cheat_found) {
+			// Found a cheat, clear the buffer.
+			
+			Main_hall_cheat = "";
+		}
 	}
 
 	switch(key) {
@@ -759,11 +843,7 @@
 					Player->flags &= ~PLAYER_FLAGS_IS_MULTI;
 					Game_mode = GM_NORMAL;
 					
-					if (strlen(Main_hall_campaign_cheat)) {
-						gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
-					} else {
-						gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
-					}
+					gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
 					gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
 					break;
 
@@ -873,10 +953,13 @@
 	}
 
 	// render misc animations
-	main_hall_render_misc_anims(frametime);
+	main_hall_render_misc_anims(frametime, false);
 
 	// render door animtions
 	main_hall_render_door_anims(frametime);
+	
+	// render misc animations (over doors)
+	main_hall_render_misc_anims(frametime, true);
 
 	// blit any appropriate tooltips
 	main_hall_maybe_blit_tooltips();
@@ -1098,7 +1181,7 @@
  * 
  * @param frametime Animation frame time
  */
-void main_hall_render_misc_anims(float frametime)
+void main_hall_render_misc_anims(float frametime, bool over_doors)
 {
 	std::deque<bool> group_anims_weve_checked;
 	int idx, s_idx, jdx;
@@ -1109,7 +1192,7 @@
 		group_anims_weve_checked.push_back(false);
 
 		// render it
-		if (Main_hall_misc_anim.at(idx).num_frames > 0) {
+		if (Main_hall_misc_anim.at(idx).num_frames > 0 && Main_hall->misc_anim_over_doors.at(idx) == over_doors) {
 			// animation is paused
 			if (Main_hall->misc_anim_paused.at(idx)) {
 				// if the timestamp is -1, then regenerate it
@@ -2051,7 +2134,27 @@
 
 				m->name = Main_hall_defines.at(count).at(0).name;
 			}
+			
+			// add cheats
+			while (optional_string("+Cheat String:")) {
+				stuff_string(temp_scp_string, F_RAW);
+				m->cheat.push_back(temp_scp_string);
 
+				if(temp_scp_string.size() > MAIN_HALL_MAX_CHEAT_LEN) {
+					// Since the value is longer than the cheat buffer it will never match.
+
+					Warning(LOCATION, "The value '%s' for '+Cheat String:' is too long! It can be at most %d characters long.", temp_scp_string.size(), MAIN_HALL_MAX_CHEAT_LEN);
+				}
+				
+				required_string("+Anim To Change:");
+				stuff_string(temp_scp_string, F_NAME);
+				m->cheat_anim_from.push_back(temp_scp_string);
+				
+				required_string("+Anim To Change To:");
+				stuff_string(temp_scp_string, F_NAME);
+				m->cheat_anim_to.push_back(temp_scp_string);
+			}
+
 			// minimum resolution
 			if (optional_string("+Min Resolution:")) {
 				stuff_int(&m->min_width);
@@ -2221,6 +2324,17 @@
 				}
 			}
 			
+			for (idx = 0; idx < m->num_misc_animations; idx++) {
+				// render over doors - default to false
+				
+				if (optional_string("+Misc anim over doors:")) {
+					stuff_boolean(&rval);
+					m->misc_anim_over_doors.push_back(rval);
+				} else {
+					m->misc_anim_over_doors.push_back(0);
+				}
+			}
+
 			region_info_init(*m);
 			
 			int mask;
Index: code/menuui/mainhallmenu.h
===================================================================
--- code/menuui/mainhallmenu.h	(revision 10960)
+++ code/menuui/mainhallmenu.h	(working copy)
@@ -26,6 +26,10 @@
 typedef struct main_hall_defines {
 	// mainhall name identifier
 	SCP_string name;
+	
+	SCP_vector<SCP_string> cheat;
+	SCP_vector<SCP_string> cheat_anim_from;
+	SCP_vector<SCP_string> cheat_anim_to;
 
 	// minimum resolution and aspect ratio needed to display this main hall
 	int min_width;
@@ -97,6 +101,9 @@
 
 	//flags for each of the misc anim sounds
 	SCP_vector<SCP_vector<int> > misc_anim_sound_flag;
+	
+	// controls the render order
+	SCP_vector<bool> misc_anim_over_doors;
 
 
 	// door animations --------------------
mainhall_anims3.patch (8,809 bytes)   

ngld

2014-07-29 21:25

reporter   ~0016145

Fixed. The MAIN_HALL_MAX_CHEAT_LEN limit still applies though.

m_m

2014-07-29 21:32

developer   ~0016146

Sure, MAIN_HALL_MAX_CHEAT_LEN has to stay.
As noted above, looks good to me in the current version.

niffiwan

2014-07-30 03:17

developer   ~0016147

ok, looks good to me, I'll commit it tonight or tomorrow night.

niffiwan

2014-07-30 10:09

developer   ~0016148

Fix committed to trunk@10961.

Related Changesets

fs2open: trunk r10961

2014-07-30 06:36

niffiwan


Ported: N/A

Details Diff
Fix mantis 3073: Additional Mainhall capabilities (from ngld)

Adds two new mainhall.tbl options:
1) "+Misc anim over doors:" (misc anim rendered after doors)
2) "+Cheat String:" (exchanges misc anim when cheat is entered)
Affected Issues
0003073
mod - /trunk/fs2_open/code/menuui/mainhallmenu.cpp Diff File
mod - /trunk/fs2_open/code/menuui/mainhallmenu.h Diff File

Issue History

Date Modified Username Field Change
2014-07-03 16:42 ngld New Issue
2014-07-03 16:42 ngld File Added: mainhall_anims.patch
2014-07-03 16:43 MjnMixael Note Added: 0016015
2014-07-03 16:44 MjnMixael Assigned To => MjnMixael
2014-07-03 16:44 MjnMixael Status new => code review
2014-07-03 16:44 MjnMixael Assigned To MjnMixael =>
2014-07-17 23:16 niffiwan Note Added: 0016085
2014-07-17 23:44 MjnMixael Note Added: 0016087
2014-07-18 01:46 MjnMixael Note Edited: 0016087
2014-07-18 09:27 ngld Note Added: 0016094
2014-07-20 17:59 The_E Note Added: 0016099
2014-07-21 03:31 niffiwan Note Added: 0016109
2014-07-29 18:03 ngld File Added: mainhall_anims2.patch
2014-07-29 18:11 ngld Note Added: 0016143
2014-07-29 20:13 m_m Note Added: 0016144
2014-07-29 21:23 ngld File Added: mainhall_anims3.patch
2014-07-29 21:25 ngld Note Added: 0016145
2014-07-29 21:32 m_m Note Added: 0016146
2014-07-30 03:17 niffiwan Note Added: 0016147
2014-07-30 10:09 niffiwan Changeset attached => fs2open trunk r10961
2014-07-30 10:09 niffiwan Note Added: 0016148
2014-07-30 10:09 niffiwan Status code review => resolved
2014-07-30 10:09 niffiwan Resolution open => fixed