/** * Call to load a shockwave, or add it and then load it */ int shockwave_load(char *s_name, bool shock_3D) { size_t i; int s_index = -1; shockwave_info *si = NULL; Assert( s_name ); // make sure that this is, or should be, valid if ( !VALID_FNAME(s_name) ) return -1; for (i = 0; i < Shockwave_info.size(); i++) { if ( !stricmp(Shockwave_info[i].filename, s_name) ) { s_index = i; break; } } if (s_index < 0) { shockwave_info si_tmp; strcpy_s(si_tmp.filename, s_name); Shockwave_info.push_back( si_tmp ); s_index = (int)(Shockwave_info.size() - 1); } Assert( s_index >= 0 ); si = &Shockwave_info[s_index]; // make sure to only try loading the shockwave once if ( (si->bitmap_id >= 0) || (si->model_id >= 0) ) return s_index; if (shock_3D) { si->model_id = model_load( si->filename, 0, NULL ); if ( si->model_id < 0 ) { Shockwave_info.pop_back(); return -1; } } else { si->bitmap_id = bm_load_animation( si->filename, &si->num_frames, &si->fps, NULL, 1 ); if ( si->bitmap_id < 0 ) { Shockwave_info.pop_back(); return -1; } } return s_index; }
void obj_find_overlap_colliders(SCP_vector<int> *overlap_list_out, SCP_vector<int> *list, int axis, bool collide) { size_t i, j; bool overlapped; bool first_not_added = true; SCP_vector<int> overlappers; float min; float max; float overlap_min; float overlap_max; overlappers.clear(); for ( i = 0; i < (*list).size(); ++i ) { overlapped = false; min = obj_get_collider_endpoint((*list)[i], axis, true); max = obj_get_collider_endpoint((*list)[i], axis, false); for ( j = 0; j < overlappers.size(); ) { overlap_min = obj_get_collider_endpoint(overlappers[j], axis, true); overlap_max = obj_get_collider_endpoint(overlappers[j], axis, false); if ( min <= overlap_max ) { overlapped = true; if ( overlappers.size() == 1 && first_not_added ) { first_not_added = false; overlap_list_out->push_back(overlappers[j]); } if ( collide ) { obj_collide_pair(&Objects[(*list)[i]], &Objects[overlappers[j]]); } } else { overlappers[j] = overlappers.back(); overlappers.pop_back(); continue; } ++j; } if ( overlappers.size() == 0 ) { first_not_added = true; } if ( overlapped ) { overlap_list_out->push_back((*list)[i]); } overlappers.push_back((*list)[i]); } overlapped = true; }
void obj_remove_collider(int obj_index) { #ifdef OBJECT_CHECK CheckObjects[obj_index].flags |= OF_NOT_IN_COLL; #endif size_t i; for ( i = 0; i < Collision_sort_list.size(); ++i ) { if ( Collision_sort_list[i] == obj_index ) { Collision_sort_list[i] = Collision_sort_list.back(); Collision_sort_list.pop_back(); break; } } Objects[obj_index].flags |= OF_NOT_IN_COLL; }
void obj_remove_collider(int obj_index) { #ifdef OBJECT_CHECK CheckObjects[obj_index].flags.set(Object::Object_Flags::Not_in_coll); #endif size_t i; for ( i = 0; i < Collision_sort_list.size(); ++i ) { if ( Collision_sort_list[i] == obj_index ) { Collision_sort_list[i] = Collision_sort_list.back(); Collision_sort_list.pop_back(); break; } } Objects[obj_index].flags.set(Object::Object_Flags::Not_in_coll); }
static void handle_includes_impl(SCP_vector<SCP_string>& include_stack, SCP_stringstream& output, int& include_counter, const SCP_string& filename, const SCP_string& original) { include_stack.emplace_back(filename); auto current_source_number = include_counter + 1; const char* INCLUDE_STRING = "#include"; SCP_stringstream input(original); int line_num = 1; for (SCP_string line; std::getline(input, line);) { auto include_start = line.find(INCLUDE_STRING); if (include_start != SCP_string::npos) { auto first_quote = line.find('"', include_start + strlen(INCLUDE_STRING)); auto second_quote = line.find('"', first_quote + 1); if (first_quote == SCP_string::npos || second_quote == SCP_string::npos) { Error(LOCATION, "Shader %s:%d: Malformed include line. Could not find both quote charaters.", filename.c_str(), line_num); } auto file_name = line.substr(first_quote + 1, second_quote - first_quote - 1); auto existing_name = std::find_if(include_stack.begin(), include_stack.end(), [&file_name](const SCP_string& str) { return str == file_name; }); if (existing_name != include_stack.end()) { SCP_stringstream stack_string; for (auto& name : include_stack) { stack_string << "\t" << name << "\n"; } Error(LOCATION, "Shader %s:%d: Detected cyclic include! Previous includes (top level file first):\n%s", filename.c_str(), line_num, stack_string.str().c_str()); } ++include_counter; // The second parameter defines which source string we are currently working with. We keep track of how many // excludes have been in the file so far to specify this output << "#line 1 " << include_counter + 1 << "\n"; handle_includes_impl(include_stack, output, include_counter, file_name, opengl_load_shader(file_name.c_str())); // We are done with the include file so now we can return to the original file output << "#line " << line_num + 1 << " " << current_source_number << "\n"; } else { output << line << "\n"; } ++line_num; } include_stack.pop_back(); }
void parse_everything_else(const char *filename) { Assertion(filename != NULL, "parse_everything_else() called on NULL; get a coder!\n"); read_file_text(filename, CF_TYPE_TABLES); int err_code; if ((err_code = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %d.\n", filename, err_code)); return; } reset_parse(); int rgba[4] = {0,0,0,0}; // reusable temp vars int i, j; SCP_string temp; if (optional_string("#Start Colors")) { // Skip this section; we already parsed it in every file. skip_to_string("#End", NULL); } //Team coloring if (optional_string("#Team Colors")) { while (required_string_either("#End", "$Team Name:")) { required_string("$Team Name:"); // required to move the parse pointer forward team_color temp_color; char temp2[NAME_LENGTH]; stuff_string(temp2, F_NAME, NAME_LENGTH); temp = temp2; if (!stricmp(temp2, "none")) { Warning(LOCATION, "Team color in '%s' defined with a name of '%s'; this won't be usable due to 'None' being used for a lack of a team color by the engine.\n", filename, temp2); } if (required_string("$Team Stripe Color:")) { int rgb[3]; stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { CLAMP(rgb[i], 0, 255); } temp_color.stripe.r = rgb[0] / 255.0f; temp_color.stripe.g = rgb[1] / 255.0f; temp_color.stripe.b = rgb[2] / 255.0f; } if (required_string("$Team Base Color:")) { int rgb[3]; stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { CLAMP(rgb[i], 0, 255); } temp_color.base.r = rgb[0] / 255.0f; temp_color.base.g = rgb[1] / 255.0f; temp_color.base.b = rgb[2] / 255.0f; } if (Team_Colors.find(temp) == Team_Colors.end()) { // Only push to the vector if the team isn't already defined. Team_Names.push_back(temp); } Team_Colors[temp] = temp_color; } required_string("#End"); } // Previously-hardcoded interface colors if (optional_string("#Interface Colors")) { char *color_names[INTERFACE_COLORS] = { "$Text Normal:", "$Text Subselected:", "$Text Selected:", "$Text Error:", "$Text Error Highlighted:", "$Text Active:", "$Text Active Highlighted:", "$Text Heading:", "$More Indicator:", "$Bright More Indicator:", "$Bright:", "$Normal:", }; // now for each color, check if its corresponding string is there for (i = 0; i < INTERFACE_COLORS; i++) { if (optional_string(color_names[i])) { // if so, get its rgba values and initialise it using them mprintf(("'%s' has been redefined.\n", color_names[i])); if ( check_for_string("(") ) { // If we have a list of integers, use them. stuff_int_list(rgba, 4, RAW_INTEGER_TYPE); for (j = 0; j < 4; j++) { if (rgba[j] < 0) { Warning(LOCATION, "RGBA value for '%s' in %s too low (%d), capping to 0.\n", color_names[i], filename, rgba[j]); rgba[j] = 0; } else if (rgba[j] > 255) { Warning(LOCATION, "RGBA value for '%s' in %s too high (%d), capping to 255.\n", color_names[i], filename, rgba[j]); rgba[j] = 255; } } gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]); //} else if (check_for_string("#")) { // stuff_hex_list(rgba, 4); // gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]); } else { // We have a string; it should be the name of a color to use. stuff_string(temp, F_NAME); for (j = 0; j < TOTAL_COLORS; j++) { if ( !temp.compare(COLOR_NAMES[j]) ) { break; } } if ( j == TOTAL_COLORS ) { Warning(LOCATION, "Unknown color '%s' in %s, for definition of '%s'; using default ('%s').\n", temp.c_str(), filename, color_names[i], COLOR_NAMES[interface_defaults[i]]); } else { Assertion(j >= 0 && j < TOTAL_COLORS, "Attempting to copy nonexistant color (%d out of 0-%d)!\n", j, TOTAL_COLORS-1); memcpy(interface_colors[i], COLOR_LIST[j], sizeof(color)); } } } } required_string("#End"); } // Text color tags; for briefings, command briefings, debriefings, and the fiction viewer if (optional_string("#Color Tags")) { while (required_string_either("$Tag:", "#End") < 1) { required_string("$Tag:"); color temp_color; char tag; stuff_string(temp, F_RAW); if (temp[0] == '$') { if (temp[1] == '\0') { Error(LOCATION, "%s - found a '$Tag:' entry with a solitary '$'.\n", filename); } tag = temp[1]; if (temp[2] != '\0') { Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag); } } else if (temp[0] == '\0') { Error(LOCATION, "%s - found a '$Tag:' entry with no tag.\n", filename); } else { tag = temp[0]; if (temp[1] != '\0') { Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag); } } if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // Only push the tag to our list of tags if it's actually new, not just a redefinition. Color_Tags.push_back(tag); } switch(required_string_one_of(4, "+Color:", "+Friendly", "+Hostile", "+Neutral")) { case 0: // +Color required_string("+Color:"); rgba[0] = rgba[1] = rgba[2] = 0; rgba[3] = 255; // Odds are pretty high you want it to have full alpha... if ( check_for_string("(") ) { stuff_int_list(rgba, 4, RAW_INTEGER_TYPE); for (j = 0; j < 4; j++) { if (rgba[j] < 0) { Warning(LOCATION, "RGBA value for '$%c' in %s too low (%d), capping to 0.\n", tag, filename, rgba[j]); rgba[j] = 0; } else if (rgba[j] > 255) { Warning(LOCATION, "RGBA value for '$%c' in %s too high (%d), capping to 255.\n", tag, filename, rgba[j]); rgba[j] = 255; } } gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]); Custom_Colors[tag] = temp_color; Tagged_Colors[tag] = &Custom_Colors[tag]; //} else if ( check_for_string ("#") ) { // stuff_hex_list(rgba, 4); // gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]); // Custom_Colors[tag] = temp_color; // Tagged_Colors[tag] = &Custom_Colors[tag]; } else { // We have a string; it should be the name of a color to use. stuff_string(temp, F_NAME); for (j = 0; j < TOTAL_COLORS; j++) { if ( !temp.compare(COLOR_NAMES[j]) ) { break; } } if ( j == TOTAL_COLORS ) { Error(LOCATION, "Unknown color '%s' in %s, for definition of tag '$%c'.\n", temp.c_str(), filename, tag); } Tagged_Colors[tag] = COLOR_LIST[j]; } break; case 1: // +Friendly required_string("+Friendly"); Tagged_Colors[tag] = &Brief_color_green; break; case 2: // +Hostile required_string("+Hostile"); Tagged_Colors[tag] = &Brief_color_red; break; case 3: // +Neutral required_string("+Neutral"); Tagged_Colors[tag] = &Brief_color_legacy_neutral; break; case -1: // -noparseerrors is set if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // It was a new color, but since we haven't actually defined it... Color_Tags.pop_back(); } break; default: Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n"); break; } } required_string("#End"); } Assertion(Color_Tags.size() == Tagged_Colors.size(), "Color_Tags and Tagged_Colors size mismatch; get a coder!\n"); if (optional_string("#Default Text Colors")) { char* color_names[MAX_DEFAULT_TEXT_COLORS] = { "$Fiction Viewer:", "$Command Briefing:", "$Briefing:", "$Redalert Briefing:", "$Debriefing:", "$Recommendation:", "$Loop Briefing:", }; char *color_value[MAX_DEFAULT_TEXT_COLORS] = { &default_fiction_viewer_color, &default_command_briefing_color, &default_briefing_color, &default_redalert_briefing_color, &default_debriefing_color, &default_recommendation_color, &default_loop_briefing_color, }; for (i = 0; i < MAX_DEFAULT_TEXT_COLORS; i++) { if ( optional_string(color_names[i]) ) { stuff_string(temp, F_RAW); if (temp[0] == '$') { if (temp[1] == '\0') { Error(LOCATION, "%s - default text color '%s' entry with a solitary '$'.\n", filename, color_names[i]); } *color_value[i] = temp[1]; if (temp[2] != '\0') { Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]); } } else if (temp[0] == '\0') { Error(LOCATION, "%s - default text color '%s' entry with no tag.\n", filename, color_names[i]); } else { *color_value[i] = temp[0]; if (temp[1] != '\0') { Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]); } } if (Tagged_Colors.find(*color_value[i]) == Tagged_Colors.end()) { // Just mprintf() this information instead of complaining with a Warning(); the tag might be defined in a later-loading TBM, and if it isn't, nothing too terrible will happen. mprintf(("%s - default text color '%s' set to non-existant tag '$%c'.\n", filename, color_names[i], *color_value[i])); } } } required_string("#End"); } }
void particle_move_all(float frametime) { MONITOR_INC( NumParticles, Num_particles ); if ( !Particles_enabled ) return; if ( Particles.empty() ) return; for (SCP_vector<particle*>::iterator p = Particles.begin(); p != Particles.end(); ) { particle* part = *p; if (part->age == 0.0f) { part->age = 0.00001f; } else { part->age += frametime; } bool remove_particle = false; // if its time expired, remove it if (part->age > part->max_life) { // special case, if max_life is 0 then we want it to render at least once if ( (part->age > frametime) || (part->max_life > 0.0f) ) { remove_particle = true; } } // if the particle is attached to an object which has become invalid, kill it if (part->attached_objnum >= 0) { // if the signature has changed, or it's bogus, kill it if ( (part->attached_objnum >= MAX_OBJECTS) || (part->attached_sig != Objects[part->attached_objnum].signature) ) { remove_particle = true; } } if (remove_particle) { part->signature = 0; delete part; // if we're sitting on the very last particle, popping-back will invalidate the iterator! if (p + 1 == Particles.end()) { Particles.pop_back(); break; } else { *p = Particles.back(); Particles.pop_back(); continue; } } // move as a regular particle vm_vec_scale_add2( &part->pos, &part->velocity, frametime ); // next particle ++p; } }