// delete a whole wing, also deleting its ships if necessary. int delete_wing(int wing_num, int bypass) { int i, r, total; if (already_deleting_wing) return 0; r = check_wing_dependencies(wing_num); if (r) return r; already_deleting_wing = 1; for (i=0; i<Num_reinforcements; i++) if (!stricmp(Wings[wing_num].name, Reinforcements[i].name)) { delete_reinforcement(i); break; } invalidate_references(Wings[wing_num].name, REF_TYPE_WING); if (!bypass) { total = Wings[wing_num].wave_count; for (i=0; i<total; i++) delete_object(wing_objects[wing_num][i]); } Wings[wing_num].wave_count = 0; Wings[wing_num].wing_squad_filename[0] = '\0'; Wings[wing_num].wing_insignia_texture = -1; if (cur_wing == wing_num) set_cur_wing(cur_wing = -1); // yes, one '=' is correct. free_sexp2(Wings[wing_num].arrival_cue); free_sexp2(Wings[wing_num].departure_cue); Num_wings--; set_modified(); update_custom_wing_indexes(); already_deleting_wing = 0; return 0; }
void campaign_tree_view::free_links() { int i; for (i=0; i<Total_links; i++) { sexp_unmark_persistent(Links[i].sexp); free_sexp2(Links[i].sexp); } Total_links = 0; }
// delete a whole wing, leaving ships intact but wingless. void remove_wing(int wing_num) { int i, total; object *ptr; if (check_wing_dependencies(wing_num)) return; Ship_editor_dialog.bypass_errors = Wing_editor_dialog.bypass_errors = 1; Ship_editor_dialog.update_data(0); total = Wings[wing_num].wave_count; for (i=0; i<total; i++) { ptr = &Objects[wing_objects[wing_num][i]]; if (ptr->type == OBJ_SHIP) remove_ship_from_wing(ptr->instance, 0); else if (ptr->type == OBJ_START) remove_player_from_wing(ptr->instance, 0); } Assert(!Wings[wing_num].wave_count); Wings[wing_num].wave_count = 0; Wings[wing_num].wing_squad_filename[0] = '\0'; Wings[wing_num].wing_insignia_texture = -1; Ship_editor_dialog.initialize_data(1); Ship_editor_dialog.bypass_errors = Wing_editor_dialog.bypass_errors = 0; if (cur_wing == wing_num) { set_cur_wing(cur_wing = -1); // yes, one '=' is correct. } free_sexp2(Wings[wing_num].arrival_cue); free_sexp2(Wings[wing_num].departure_cue); Num_wings--; update_custom_wing_indexes(); set_modified(); }
void CMissionGoalsDlg::OnOk() { char buf[256], names[2][MAX_GOALS][NAME_LENGTH]; int i, count; for (i=0; i<Num_goals; i++) free_sexp2(Mission_goals[i].formula); UpdateData(TRUE); if (query_modified()) set_modified(); count = 0; for (i=0; i<Num_goals; i++) Mission_goals[i].satisfied = 0; // use this as a processed flag // rename all sexp references to old events for (i=0; i<m_num_goals; i++) if (m_sig[i] >= 0) { strcpy(names[0][count], Mission_goals[m_sig[i]].name); strcpy(names[1][count], m_goals[i].name); count++; Mission_goals[m_sig[i]].satisfied = 1; } // invalidate all sexp references to deleted events. for (i=0; i<Num_goals; i++) if (!Mission_goals[i].satisfied) { sprintf(buf, "<%s>", Mission_goals[i].name); strcpy(buf + NAME_LENGTH - 2, ">"); // force it to be not too long strcpy(names[0][count], Mission_goals[i].name); strcpy(names[1][count], buf); count++; } Num_goals = m_num_goals; for (i=0; i<Num_goals; i++) { Mission_goals[i] = m_goals[i]; Mission_goals[i].formula = m_goals_tree.save_tree(Mission_goals[i].formula); if ( The_mission.game_type & MISSION_TYPE_MULTI_TEAMS ) { Assert( Mission_goals[i].team != -1 ); } } // now update all sexp references while (count--) update_sexp_references(names[0][count], names[1][count], OPF_GOAL_NAME); theApp.record_window_data(&Mission_goals_wnd_data, this); CDialog::OnOK(); }
bool set_cue_to_false(int *cue) { // if the cue is not false, make it false. Be sure to set all ship editor dialog functions // to update data before and after we modify the cue. if (*cue != Locked_sexp_false) { Ship_editor_dialog.update_data(1); Wing_editor_dialog.update_data(1); free_sexp2(*cue); *cue = Locked_sexp_false; Ship_editor_dialog.initialize_data(1); Wing_editor_dialog.initialize_data(1); return true; } else return false; }
void campaign_tree_view::delete_link(int num) { Assert((num >= 0) && (num < Total_links)); if (Links[num].from != Links[num].to) { Elements[Links[num].from].from_links--; Elements[Links[num].to].to_links--; } sexp_unmark_persistent(Links[num].sexp); free_sexp2(Links[num].sexp); while (num < Total_links - 1) { Links[num] = Links[num + 1]; num++; } Total_links--; sort_links(); Invalidate(); Campaign_modified = 1; return; }
void campaign_editor::save_tree(int clear) { int i; if (m_last_mission < 0){ return; // nothing to save } for (i=0; i<Total_links; i++){ if (Links[i].from == m_last_mission) { sexp_unmark_persistent(Links[i].sexp); free_sexp2(Links[i].sexp); Links[i].sexp = m_tree.save_tree(Links[i].node); sexp_mark_persistent(Links[i].sexp); } } if (clear){ m_last_mission = -1; } }
void event_editor::OnOk() { char buf[256], names[2][MAX_MISSION_EVENTS][NAME_LENGTH]; int i, count; audiostream_close_file(m_wave_id, 0); m_wave_id = -1; save(); if (query_modified()) set_modified(); for (i=0; i<Num_mission_events; i++) { free_sexp2(Mission_events[i].formula); if (Mission_events[i].objective_text) free(Mission_events[i].objective_text); if (Mission_events[i].objective_key_text) free(Mission_events[i].objective_key_text); } count = 0; for (i=0; i<Num_mission_events; i++) Mission_events[i].result = 0; // use this as a processed flag // rename all sexp references to old events for (i=0; i<m_num_events; i++) if (m_sig[i] >= 0) { strcpy_s(names[0][count], Mission_events[m_sig[i]].name); strcpy_s(names[1][count], m_events[i].name); count++; Mission_events[m_sig[i]].result = 1; } // invalidate all sexp references to deleted events. for (i=0; i<Num_mission_events; i++) if (!Mission_events[i].result) { sprintf(buf, "<%s>", Mission_events[i].name); strcpy(buf + NAME_LENGTH - 2, ">"); // force it to be not too long strcpy_s(names[0][count], Mission_events[i].name); strcpy_s(names[1][count], buf); count++; } Num_mission_events = m_num_events; for (i=0; i<m_num_events; i++) { Mission_events[i] = m_events[i]; Mission_events[i].formula = m_event_tree.save_tree(m_events[i].formula); Mission_events[i].objective_text = m_events[i].objective_text; Mission_events[i].objective_key_text = m_events[i].objective_key_text; Mission_events[i].mission_log_flags = m_events[i].mission_log_flags; } // now update all sexp references while (count--) update_sexp_references(names[0][count], names[1][count], OPF_EVENT_NAME); for (i=Num_builtin_messages; i<Num_messages; i++) { if (Messages[i].avi_info.name) free(Messages[i].avi_info.name); if (Messages[i].wave_info.name) free(Messages[i].wave_info.name); } Num_messages = m_num_messages + Num_builtin_messages; for (i=0; i<m_num_messages; i++) Messages[i + Num_builtin_messages] = m_messages[i]; theApp.record_window_data(&Events_wnd_data, this); delete Event_editor_dlg; Event_editor_dlg = NULL; }
// update parts of wing that can't fail. This is useful if for when you need to change // something in a wing that this updates elsewhere in Fred. Normally when auto-update // kicks in, the changes you make will be wiped out by the auto=update, so instead you // would call this function to update the wing, make your changes, and then call the // initialize_data_safe() function to show your changes in the dialog void wing_editor::update_data_safe() { char buf[512]; int i, d, hotkey = -1; nprintf(("Fred routing", "Wing dialog save safe\n")); if (!GetSafeHwnd()) return; UpdateData(TRUE); UpdateData(TRUE); if (cur_wing < 0) return; if (m_threshold >= Wings[cur_wing].wave_count) { m_threshold = Wings[cur_wing].wave_count - 1; if (!bypass_errors) sprintf(buf, "Wave threshold is set too high. Value has been lowered to %d", (int) m_threshold); MessageBox(buf); } if (m_threshold + Wings[cur_wing].wave_count > MAX_SHIPS_PER_WING) { m_threshold = MAX_SHIPS_PER_WING - Wings[cur_wing].wave_count; if (!bypass_errors) sprintf(buf, "Wave threshold is set too high. Value has been lowered to %d", (int) m_threshold); MessageBox(buf); } if (m_waves < 1) { m_waves = 1; if (!bypass_errors) sprintf(buf, "Number of waves illegal. Has been set to 1.", (int) m_waves); MessageBox(buf); } MODIFY(Wings[cur_wing].special_ship, m_special_ship); MODIFY(Wings[cur_wing].num_waves, m_waves); MODIFY(Wings[cur_wing].threshold, m_threshold); MODIFY(Wings[cur_wing].arrival_location, m_arrival_location); MODIFY(Wings[cur_wing].departure_location, m_departure_location); MODIFY(Wings[cur_wing].arrival_delay, m_arrival_delay); if (m_arrival_delay_min > m_arrival_delay_max) { if (!bypass_errors) sprintf(buf, "Arrival delay minimum greater than maximum. Value lowered to %d", m_arrival_delay_max); MessageBox(buf); m_arrival_delay_min = m_arrival_delay_max; } MODIFY(Wings[cur_wing].wave_delay_min, m_arrival_delay_min); MODIFY(Wings[cur_wing].wave_delay_max, m_arrival_delay_max); MODIFY(Wings[cur_wing].arrival_distance, m_arrival_dist); if (m_arrival_target >= 0) { i = ((CComboBox *) GetDlgItem(IDC_ARRIVAL_TARGET)) -> GetItemData(m_arrival_target); MODIFY(Wings[cur_wing].arrival_anchor, i); // when arriving near or in front of a ship, be sure that we are far enough away from it!!! if (((m_arrival_location != ARRIVE_AT_LOCATION) && (m_arrival_location != ARRIVE_FROM_DOCK_BAY)) && (i >= 0) && (i < SPECIAL_ARRIVAL_ANCHORS_OFFSET)) { d = int(min(500, 2.0f * Objects[Ships[i].objnum].radius)); if ((Wings[cur_wing].arrival_distance < d) && (Wings[cur_wing].arrival_distance > -d)) { if (!bypass_errors) sprintf(buf, "Ship must arrive at least %d meters away from target.\n" "Value has been reset to this. Use with caution!\r\n" "Reccomended distance is %d meters.\r\n", d, (int)(2.0f * Objects[Ships[i].objnum].radius) ); MessageBox(buf); if (Wings[cur_wing].arrival_distance < 0) Wings[cur_wing].arrival_distance = -d; else Wings[cur_wing].arrival_distance = d; m_arrival_dist = Wings[cur_wing].arrival_distance; } } } i = ((CComboBox*)GetDlgItem(IDC_DEPARTURE_TARGET))->GetItemData(m_departure_target); if (m_departure_location == DEPART_AT_DOCK_BAY) MODIFY(Wings[cur_wing].departure_anchor, i); else MODIFY(Wings[cur_wing].jump_anchor, m_departure_target); MODIFY(Wings[cur_wing].departure_delay, m_departure_delay); hotkey = m_hotkey - 1; MODIFY(Wings[cur_wing].hotkey, hotkey); if ( m_ignore_count ) { if ( !(Wings[cur_wing].flags & WF_IGNORE_COUNT) ) set_modified(); Wings[cur_wing].flags |= WF_IGNORE_COUNT; } else { if ( Wings[cur_wing].flags & WF_IGNORE_COUNT ) set_modified(); Wings[cur_wing].flags &= ~WF_IGNORE_COUNT; } if ( m_no_arrival_music ) { if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_MUSIC) ) set_modified(); Wings[cur_wing].flags |= WF_NO_ARRIVAL_MUSIC; } else { if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_MUSIC ) set_modified(); Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_MUSIC; } // check the no message flag if ( m_no_arrival_message ) { if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_MESSAGE) ) set_modified(); Wings[cur_wing].flags |= WF_NO_ARRIVAL_MESSAGE; } else { if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_MESSAGE ) set_modified(); Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_MESSAGE; } // set the no warp effect for wings flag if ( m_no_arrival_warp ) { if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_WARP) ) set_modified(); Wings[cur_wing].flags |= WF_NO_ARRIVAL_WARP; } else { if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_WARP ) set_modified(); Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_WARP; } // set the no warp effect for wings flag if ( m_no_departure_warp ) { if ( !(Wings[cur_wing].flags & WF_NO_DEPARTURE_WARP) ) set_modified(); Wings[cur_wing].flags |= WF_NO_DEPARTURE_WARP; } else { if ( Wings[cur_wing].flags & WF_NO_DEPARTURE_WARP ) set_modified(); Wings[cur_wing].flags &= ~WF_NO_DEPARTURE_WARP; } if ( m_no_dynamic ) { if ( !(Wings[cur_wing].flags & WF_NO_DYNAMIC) ) set_modified(); Wings[cur_wing].flags |= WF_NO_DYNAMIC; } else { if ( Wings[cur_wing].flags & WF_NO_DYNAMIC ) set_modified(); Wings[cur_wing].flags &= ~WF_NO_DYNAMIC; } if (Wings[cur_wing].arrival_cue >= 0) free_sexp2(Wings[cur_wing].arrival_cue); Wings[cur_wing].arrival_cue = m_arrival_tree.save_tree(); if (Wings[cur_wing].departure_cue >= 0) free_sexp2(Wings[cur_wing].departure_cue); Wings[cur_wing].departure_cue = m_departure_tree.save_tree(); // copy squad stuff if(stricmp(m_wing_squad_filename, Wings[cur_wing].wing_squad_filename)) { string_copy(Wings[cur_wing].wing_squad_filename, m_wing_squad_filename, MAX_FILENAME_LEN); set_modified(); } if (modified) set_modified(); }
// update wing structure(s) with dialog data. The data is first checked for errors. If // no errors occur, returns 0. If an error occurs, returns -1. If the update is bypassed, // returns 1. Bypass is necessary to avoid an infinite loop, and it doesn't actually // update the data. Bypass only occurs if bypass mode is active and we still get an error. // Once the error no longer occurs, bypass mode is cleared and data is updated. int wing_editor::update_data(int redraw) { char *str, old_name[255], buf[512]; int i, z; object *ptr; nprintf(("Fred routing", "Wing dialog save\n")); if (!GetSafeHwnd()) return 0; UpdateData(TRUE); UpdateData(TRUE); if (cur_wing >= 0) { if (!strnicmp(m_wing_name, "player ", 7)) { if (bypass_errors) return 1; bypass_errors = 1; z = MessageBox("Wing names can't start with the word 'player'\n" "Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL); if (z == IDCANCEL) return -1; m_wing_name = _T(Wings[cur_wing].name); UpdateData(FALSE); } for (i=0; i<MAX_WINGS; i++) if (Wings[i].wave_count && !stricmp(Wings[i].name, m_wing_name) && (i != cur_wing)) { if (bypass_errors) return 1; bypass_errors = 1; z = MessageBox("This wing name is already being used by another wing\n" "Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL); if (z == IDCANCEL) return -1; m_wing_name = _T(Wings[cur_wing].name); UpdateData(FALSE); } ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->type == OBJ_SHIP) { if (!stricmp(m_wing_name, Ships[ptr->instance].ship_name)) { if (bypass_errors) return 1; bypass_errors = 1; z = MessageBox("This wing name is already being used by a ship\n" "Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL); if (z == IDCANCEL) return -1; m_wing_name = _T(Wings[cur_wing].name); UpdateData(FALSE); } } ptr = GET_NEXT(ptr); } for (i=0; i<MAX_WAYPOINT_LISTS; i++) if (Waypoint_lists[i].count && !stricmp(Waypoint_lists[i].name, m_wing_name)) { if (bypass_errors) return 1; bypass_errors = 1; z = MessageBox("This wing name is already being used by a waypoint path\n" "Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL); if (z == IDCANCEL) return -1; m_wing_name = _T(Wings[cur_wing].name); UpdateData(FALSE); } for (i=0; i<Num_jump_nodes; i++) if (!stricmp(Jump_nodes[i].name, m_wing_name)) { if (bypass_errors) return 1; bypass_errors = 1; z = MessageBox("This wing name is already being used by a hyper buoy\n" "Press OK to restore old name", "Error", MB_ICONEXCLAMATION | MB_OKCANCEL); if (z == IDCANCEL) return -1; m_wing_name = _T(Wings[cur_wing].name); UpdateData(FALSE); } strcpy(old_name, Wings[cur_wing].name); string_copy(Wings[cur_wing].name, m_wing_name, NAME_LENGTH, 1); update_data_safe(); bypass_errors = 0; modified = 0; str = Wings[cur_wing].name; if (stricmp(old_name, str)) { update_sexp_references(old_name, str); ai_update_goal_references(REF_TYPE_WING, old_name, str); for (i=0; i<Num_reinforcements; i++) if (!stricmp(old_name, Reinforcements[i].name)) { Assert(strlen(str) < NAME_LENGTH); strcpy(Reinforcements[i].name, str); } for (i=0; i<Wings[cur_wing].wave_count; i++) { if ((Objects[wing_objects[cur_wing][i]].type == OBJ_SHIP) || (Objects[wing_objects[cur_wing][i]].type == OBJ_START)) { sprintf(buf, "%s %d", str, i + 1); rename_ship(Wings[cur_wing].ship_index[i], buf); } } Update_window = 1; } if (set_reinforcement(str, m_reinforcement) == 1) { free_sexp2(Wings[cur_wing].arrival_cue); Wings[cur_wing].arrival_cue = Locked_sexp_false; } } if (redraw) update_map_window(); return 0; }
// Forms a wing from marked objects int create_wing() { char msg[1024]; int i, ship, wing = -1, waypoints = 0, count = 0, illegal_ships = 0; int leader, leader_team; object *ptr; create_wing_dlg dlg; if (!query_valid_object()) return -1; leader = cur_object_index; ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (( (ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START) ) && (ptr->flags & OF_MARKED)) { count++; i = -1; switch (ptr->type) { case OBJ_SHIP: case OBJ_START: i = Ships[ptr->instance].wingnum; break; } if (i >= 0) { if (wing < 0) wing = i; else if (wing != i) wing = MULTI_WING; } } ptr = GET_NEXT(ptr); } if (count > MAX_SHIPS_PER_WING) { sprintf(msg, "You have too many ships marked!\n" "A wing is limited to %d ships total", MAX_SHIPS_PER_WING); Fred_main_wnd->MessageBox(msg, "Error", MB_ICONEXCLAMATION); return -1; } if ((wing >= 0) && (wing != MULTI_WING)) { sprintf(msg, "Do you want to reform wing \"%s\"?", Wings[wing].name); i = Fred_main_wnd->MessageBox(msg, "Query", MB_YESNOCANCEL); if (i == IDCANCEL) return -1; else if (i == IDNO) wing = -1; else { // must be IDYES for (i=Wings[wing].wave_count-1; i>=0; i--) { ptr = &Objects[wing_objects[wing][i]]; switch (ptr->type) { case OBJ_SHIP: remove_ship_from_wing(ptr->instance, 0); break; case OBJ_START: remove_player_from_wing(ptr->instance, 0); break; default: Int3(); // shouldn't be in a wing! } } Assert(!Wings[wing].wave_count); Num_wings--; } } else wing = -1; if (wing < 0) { wing = find_free_wing(); if (wing < 0) { Fred_main_wnd->MessageBox("Too many wings, can't create more!", "Error", MB_ICONEXCLAMATION); return -1; } Wings[wing].num_waves = 1; Wings[wing].threshold = 0; Wings[wing].arrival_location = Wings[wing].departure_location = 0; Wings[wing].arrival_distance = 0; Wings[wing].arrival_anchor = -1; Wings[wing].arrival_delay = 0; Wings[wing].arrival_cue = Locked_sexp_true; Wings[wing].departure_delay = 0; Wings[wing].departure_cue = Locked_sexp_false; Wings[wing].hotkey = -1; Wings[wing].flags = 0; Wings[wing].wave_delay_min = 0; Wings[wing].wave_delay_max = 0; for (i=0; i<MAX_AI_GOALS; i++) { Wings[wing].ai_goals[i].ai_mode = AI_GOAL_NONE; Wings[wing].ai_goals[i].priority = -1; // this sets up the priority field to be like ships } if (dlg.DoModal() == IDCANCEL) return -1; dlg.m_name.TrimLeft(); dlg.m_name.TrimRight(); string_copy(Wings[wing].name, dlg.m_name, NAME_LENGTH - 1); } set_cur_indices(-1); ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { // if ((ptr->type == OBJ_START) && (ptr->instance)) { // starts++; // unmark_object(OBJ_INDEX(ptr)); // } else if (ptr->type == OBJ_WAYPOINT) { if (ptr->type == OBJ_WAYPOINT) { waypoints++; unmark_object(OBJ_INDEX(ptr)); } else if (ptr->type == OBJ_SHIP) { int ship_type = ship_query_general_type(ptr->instance); if(ship_type < 0 || !(Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING)) { illegal_ships++; unmark_object(OBJ_INDEX(ptr)); } } } ptr = GET_NEXT(ptr); } // if this wing is a player starting wing, automatically set the hotkey for this wing for (i = 0; i < MAX_STARTING_WINGS; i++ ) { if ( !stricmp(Wings[wing].name, Starting_wing_names[i]) ) { Wings[wing].hotkey = i; break; } } count = 0; if (Objects[Ships[Player_start_shipnum].objnum].flags & OF_MARKED) count = 1; ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { if ((ptr->type == OBJ_START) && (ptr->instance == Player_start_shipnum)) i = 0; // player 1 start always goes to front of the wing else i = count++; Assert((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)); ship = ptr->instance; if (Ships[ship].wingnum != -1) { if (ptr->type == OBJ_SHIP) remove_ship_from_wing(ship); else remove_player_from_wing(ptr->instance); } wing_bash_ship_name(msg, Wings[wing].name, i + 1); rename_ship(ship, msg); Wings[wing].ship_index[i] = ship; Ships[ship].wingnum = wing; if (Ships[ship].arrival_cue >= 0) free_sexp2(Ships[ship].arrival_cue); Ships[ship].arrival_cue = Locked_sexp_false; if (Ships[ship].departure_cue >= 0) free_sexp2(Ships[ship].departure_cue); Ships[ship].departure_cue = Locked_sexp_false; wing_objects[wing][i] = OBJ_INDEX(ptr); if (OBJ_INDEX(ptr) == leader) Wings[wing].special_ship = i; } ptr = GET_NEXT(ptr); } if (!count) // this should never happen, so if it does, needs to be fixed now. Error(LOCATION, "No valid ships were selected to form wing from"); Wings[wing].wave_count = count; Num_wings++; // if (starts) // Fred_main_wnd->MessageBox("Multi-player starting points can't be part of a wing!\n" // "All marked multi-player starting points were ignored", // "Error", MB_ICONEXCLAMATION); if (waypoints) Fred_main_wnd->MessageBox("Waypoints can't be part of a wing!\n" "All marked waypoints were ignored", "Error", MB_ICONEXCLAMATION); if (illegal_ships) Fred_main_wnd->MessageBox("Some ship types aren't allowed to be in a wing.\n" "All marked ships of these types were ignored", "Error", MB_ICONEXCLAMATION); leader_team = Ships[Wings[wing].ship_index[Wings[wing].special_ship]].team; for (i = 0; i < Wings[wing].wave_count; i++) { if (Ships[Wings[wing].ship_index[i]].team != leader_team) { Fred_main_wnd->MessageBox("Wing contains ships on different teams", "Warning"); break; } } mark_wing(wing); update_custom_wing_indexes(); return 0; }
void debriefing_editor_dlg::update_data(int update) { int enable, save_debriefing; debrief_stage *ptr; save_debriefing = m_current_debriefing; if (update) UpdateData(TRUE); // based on the game type, enable the multiple briefings combo box (or disable it) // set up the pointer to the briefing that we are editing if ( save_debriefing != m_current_debriefing ) Debriefing = &Debriefings[save_debriefing]; else Debriefing = &Debriefings[m_current_debriefing]; if (m_last_stage >= 0) { ptr = &Debriefing->stages[m_last_stage]; if (ptr->formula >= 0) free_sexp2(ptr->formula); ptr->formula = m_tree.save_tree(); deconvert_multiline_string(ptr->new_text, m_text, MAX_DEBRIEF_LEN); deconvert_multiline_string(ptr->new_recommendation_text, m_rec_text, MAX_RECOMMENDATION_LEN); string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN); } // now get new stage data if ((m_cur_stage >= 0) && (m_cur_stage < Debriefing->num_stages)) { ptr = &Debriefing->stages[m_cur_stage]; m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Debriefing->num_stages); m_tree.load_tree(ptr->formula); m_text = convert_multiline_string(ptr->new_text); m_rec_text = convert_multiline_string(ptr->new_recommendation_text); m_voice = ptr->voice; enable = TRUE; } else { m_stage_title = _T("No stages"); m_tree.clear_tree(); m_text = _T(""); m_rec_text = _T(""); m_voice = _T(""); enable = FALSE; m_cur_stage = -1; } if (m_cur_stage == Debriefing->num_stages - 1) GetDlgItem(IDC_NEXT) -> EnableWindow(FALSE); else GetDlgItem(IDC_NEXT) -> EnableWindow(enable); if (m_cur_stage) GetDlgItem(IDC_PREV) -> EnableWindow(enable); else GetDlgItem(IDC_PREV) -> EnableWindow(FALSE); if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES) GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(FALSE); else GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(TRUE); if (Debriefing->num_stages) { GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(enable); GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(enable); } else { GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(FALSE); GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(FALSE); } GetDlgItem(IDC_VOICE) -> EnableWindow(enable); GetDlgItem(IDC_BROWSE) -> EnableWindow(enable); GetDlgItem(IDC_TEXT) -> EnableWindow(enable); GetDlgItem(IDC_REC_TEXT) -> EnableWindow(enable); GetDlgItem(IDC_TREE) -> EnableWindow(enable); m_last_stage = m_cur_stage; UpdateData(FALSE); #ifndef NDEBUG count_free_sexp_nodes(); #endif }
int CMessageEditorDlg::update(int num) { char *ptr, buf[4096]; int i, node, fnode; CListBox *list; UpdateData(TRUE); if (num >= 0) { ptr = (char *) (LPCTSTR) m_message_name; for (i=0; i<Num_messages; i++) if ((i != num) && (!stricmp(m_message_name, Messages[i].name))) break; if (i == Num_messages) { // update name if no conflicts, otherwise keep old name update_sexp_references(Messages[num].name, ptr, OPF_MESSAGE); string_copy(Messages[num].name, m_message_name, NAME_LENGTH - 1); list = (CListBox *) GetDlgItem(IDC_MESSAGE_LIST); list->DeleteString(num); list->InsertString(num, m_message_name); } string_copy(Messages[num].message, m_message_text, MESSAGE_LENGTH - 1); if (Messages[num].avi_info.name) free(Messages[num].avi_info.name); ptr = (char *) (LPCTSTR) m_avi_filename; if (!ptr || !strlen(ptr)) Messages[num].avi_info.name = NULL; else Messages[num].avi_info.name = strdup(ptr); if (Messages[num].wave_info.name) free(Messages[num].wave_info.name); ptr = (char *) (LPCTSTR) m_wave_filename; if (!ptr || !strlen(ptr)) Messages[num].wave_info.name = NULL; else Messages[num].wave_info.name = strdup(ptr); // update the persona to the message. We subtract 1 for the "None" at the beginning of the combo // box list. Messages[num].persona_index = m_persona - 1; if (m_tree.query_false()) { if (m_event_num >= 0) { // need to delete event i = m_event_num; free_sexp2(Mission_events[i].formula); Assert(i < Num_mission_events); while (i < Num_mission_events - 1) { Mission_events[i] = Mission_events[i + 1]; i++; } Num_mission_events--; m_event_num = -1; } } else { if (m_event_num >= 0) free_sexp2(Mission_events[m_event_num].formula); else { if (Num_mission_events == MAX_MISSION_EVENTS) { MessageBox("You have reached the limit on mission events.\n" "Can't add an event to send this message."); goto exit; } Assert(Num_mission_events < MAX_MISSION_EVENTS); m_event_num = Num_mission_events++; string_copy(Mission_events[m_event_num].name, m_message_name, NAME_LENGTH - 1); Mission_events[m_event_num].repeat_count = 1; Mission_events[m_event_num].interval = 1; Mission_events[m_event_num].score = 0; Mission_events[m_event_num].chain_delay = -1; Mission_events[m_event_num].objective_text = NULL; Mission_events[m_event_num].objective_key_text = NULL; } fnode = m_tree.save_tree(); ptr = (char *) (LPCTSTR) m_message_name; node = alloc_sexp(ptr, SEXP_ATOM, SEXP_ATOM_STRING, -1, -1); ((CComboBox *) GetDlgItem(IDC_PRIORITY))->GetLBText(m_priority, buf); node = alloc_sexp(buf, SEXP_ATOM, SEXP_ATOM_STRING, -1, node); ((CComboBox *) GetDlgItem(IDC_SENDER))->GetLBText(m_sender, buf); node = alloc_sexp(buf, SEXP_ATOM, SEXP_ATOM_STRING, -1, node); node = alloc_sexp("send-message", SEXP_ATOM, SEXP_ATOM_OPERATOR, -1, node); node = alloc_sexp("", SEXP_LIST, SEXP_ATOM_LIST, node, -1); node = alloc_sexp("", SEXP_LIST, SEXP_ATOM_LIST, fnode, node); node = alloc_sexp("when", SEXP_ATOM, SEXP_ATOM_OPERATOR, -1, node); Mission_events[m_event_num].formula = node; } } exit: if (query_modified()) set_modified(); modified = 0; return 0; }
// Forms a wing from marked objects int create_wing() { char msg[1024]; int i, ship, wing = -1, waypoints = 0, count = 0, illegal_ships = 0; int friendly, hostile, leader; object *ptr; create_wing_dlg dlg; if (!query_valid_object()) return -1; leader = cur_object_index; ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if ((ptr->type == OBJ_SHIP) && (ptr->flags & OF_MARKED)) { count++; i = -1; switch (ptr->type) { case OBJ_SHIP: case OBJ_START: i = Ships[ptr->instance].wingnum; break; } if (i >= 0) { if (wing < 0) wing = i; else if (wing != i) wing = MULTI_WING; } } ptr = GET_NEXT(ptr); } if (count > MAX_SHIPS_PER_WING) { sprintf(msg, "You have too many ships marked!\n" "A flight group is limited to %d ships total", MAX_SHIPS_PER_WING); Fred_main_wnd->MessageBox(msg, "Error", MB_ICONEXCLAMATION); return -1; } if ((wing >= 0) && (wing != MULTI_WING)) { sprintf(msg, "Do you want to reform flight group \"%s\"?", Wings[wing].name); i = Fred_main_wnd->MessageBox(msg, "Query", MB_YESNOCANCEL); if (i == IDCANCEL) return -1; else if (i == IDNO) wing = -1; else { // must be IDYES for (i=Wings[wing].wave_count-1; i>=0; i--) { ptr = &Objects[wing_objects[wing][i]]; switch (ptr->type) { case OBJ_SHIP: remove_ship_from_wing(ptr->instance, 0); break; case OBJ_START: remove_player_from_wing(ptr->instance, 0); break; default: Int3(); // shouldn't be in a wing! } } Assert(!Wings[wing].wave_count); num_wings--; } } else wing = -1; if (wing < 0) { wing = find_free_wing(); Wings[wing].num_waves = 1; Wings[wing].threshold = 0; Wings[wing].arrival_location = Wings[wing].departure_location = 0; Wings[wing].arrival_distance = 0; Wings[wing].arrival_anchor = -1; Wings[wing].arrival_cue = Locked_sexp_true; Wings[wing].departure_cue = Locked_sexp_false; Wings[wing].hotkey = -1; Wings[wing].flags = 0; for (i=0; i<MAX_AI_GOALS; i++) { Wings[wing].ai_goals[i].ai_mode = AI_GOAL_NONE; Wings[wing].ai_goals[i].priority = -1; // this sets up the priority field to be like ships } if (wing < 0) { Fred_main_wnd->MessageBox("Too many flight groups, can't create more!", "Error", MB_ICONEXCLAMATION); return -1; } if (dlg.DoModal() == IDCANCEL) return -1; string_copy(Wings[wing].name, dlg.m_name, NAME_LENGTH - 1); } set_cur_indices(-1); ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { // if ((ptr->type == OBJ_START) && (ptr->instance)) { // starts++; // unmark_object(OBJ_INDEX(ptr)); // } else if (ptr->type == OBJ_WAYPOINT) { if (ptr->type == OBJ_WAYPOINT) { waypoints++; unmark_object(OBJ_INDEX(ptr)); } else if (ptr->type == OBJ_SHIP) { switch (ship_query_general_type(ptr->instance)) { case SHIP_TYPE_CARGO: case SHIP_TYPE_FIGHTER_BOMBER: case SHIP_TYPE_CRUISER: case SHIP_TYPE_FREIGHTER: case SHIP_TYPE_CAPITAL: case SHIP_TYPE_TRANSPORT: case SHIP_TYPE_REPAIR_REARM: case SHIP_TYPE_NAVBUOY: case SHIP_TYPE_SENTRYGUN: case SHIP_TYPE_SPACE_OBJECT: case SHIP_TYPE_ESCAPEPOD: case SHIP_TYPE_SUPERCAP: case SHIP_TYPE_STEALTH: case SHIP_TYPE_DRYDOCK: //case SHIP_TYPE_AWACS: //case SHIP_TYPE_GAS_MINER: // all ships added so that any craft type can be formed into a flight group /*case SHIP_TYPE_FIGHTER_BOMBER: case SHIP_TYPE_CRUISER: case SHIP_TYPE_AWACS: case SHIP_TYPE_GAS_MINER: case SHIP_TYPE_CORVETTE: case SHIP_TYPE_FREIGHTER: case SHIP_TYPE_CAPITAL: case SHIP_TYPE_TRANSPORT: case SHIP_TYPE_SUPERCAP:*/ break; default: illegal_ships++; unmark_object(OBJ_INDEX(ptr)); } } } ptr = GET_NEXT(ptr); } // if this wing is a player starting wing, automatically set the hotkey for this wing for (i = 0; i < MAX_STARTING_WINGS; i++ ) { if ( !stricmp(Wings[wing].name, Starting_wing_names[i]) ) { Wings[wing].hotkey = i; break; } } count = friendly = hostile = 0; if (Objects[Ships[Player_start_shipnum].objnum].flags & OF_MARKED) count = 1; ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { if ((ptr->type == OBJ_START) && (ptr->instance == Player_start_shipnum)) i = 0; // player 1 start always goes to front of the wing else i = count++; Assert((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)); ship = ptr->instance; if (Ships[ship].wingnum != -1) { if (ptr->type == OBJ_SHIP) remove_ship_from_wing(ship); else remove_player_from_wing(ptr->instance); } sprintf(msg, "%s %d", Wings[wing].name, i + 1); rename_ship(ship, msg); if (Ships[ship].team == TEAM_FRIENDLY) friendly = 1; else if ((Ships[ship].team == TEAM_HOSTILE) || (Ships[ship].team == TEAM_NEUTRAL)) hostile = 1; Wings[wing].ship_index[i] = ship; Ships[ship].wingnum = wing; if (Ships[ship].arrival_cue >= 0) free_sexp2(Ships[ship].arrival_cue); Ships[ship].arrival_cue = Locked_sexp_false; if (Ships[ship].departure_cue >= 0) free_sexp2(Ships[ship].departure_cue); Ships[ship].departure_cue = Locked_sexp_false; wing_objects[wing][i] = OBJ_INDEX(ptr); if (OBJ_INDEX(ptr) == leader) Wings[wing].special_ship = i; } ptr = GET_NEXT(ptr); } if (!count) // this should never happen, so if it does, needs to be fixed now. Error(LOCATION, "No valid ships were selected to form wing from"); Wings[wing].wave_count = count; num_wings++; // if (starts) // Fred_main_wnd->MessageBox("Multi-player starting points can't be part of a wing!\n" // "All marked multi-player starting points were ignored", // "Error", MB_ICONEXCLAMATION); if (waypoints) Fred_main_wnd->MessageBox("Waypoints can't be part of a wing!\n" "All marked waypoints were ignored", "Error", MB_ICONEXCLAMATION); if (illegal_ships) Fred_main_wnd->MessageBox("Some ship types aren't allowed to be in a wing.\n" "All marked ships of these types were ignored", "Error", MB_ICONEXCLAMATION); if (friendly && hostile) Fred_main_wnd->MessageBox("Both hostile and friendly ships in same wing", "Warning"); mark_wing(wing); return 0; }