/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ /* * $Logfile: /Freespace2/code/Fred2/wing.cpp $ * $Revision: 1.1 $ * $Date: 2006-01-19 02:27:32 $ * $Author: Goober5000 $ * * Wing management functions for dealing with wing related operations * * $Log: not supported by cvs2svn $ * Revision 1.11 2006/01/14 05:24:19 Goober5000 * first pass at converting FRED to use new IFF stuff * --Goober5000 * * Revision 1.10 2005/12/29 08:21:00 wmcoolmon * No my widdle FRED, I didn't forget about you ^_^ (codebase commit) * * Revision 1.9 2005/10/29 23:02:33 Goober5000 * partial FRED commit of changes * --Goober5000 * * Revision 1.8 2005/09/26 07:58:27 Goober5000 * hooray, more custom wing fixes * --Goober5000 * * Revision 1.7 2005/08/23 07:28:02 Goober5000 * grammar * --Goober5000 * * Revision 1.6 2005/04/13 20:11:06 chhogg * Changed vector to vec3d for Fred. * * Revision 1.5 2005/03/29 03:43:11 phreak * ai directory fixes as well as fixes for the new jump node code * * Revision 1.4 2003/01/06 20:49:15 Goober5000 * FRED2 support for wing squad logos - look in the wing editor * --Goober5000 * * Revision 1.3 2002/08/15 04:35:44 penguin * Changes to build with fs2_open code.lib * * Revision 1.2 2002/08/15 01:06:34 penguin * Include filename reorg (to coordinate w/ fs2_open) * * Revision 1.1.1.1 2002/07/15 03:11:03 inquisitor * Initial FRED2 Checking * * * 4 7/09/99 5:54p Dave * Seperated cruiser types into individual types. Added tons of new * briefing icons. Campaign screen. * * 3 3/01/99 10:00a Dave * Fxied several dogfight related stats bugs. * * 2 10/07/98 6:28p Dave * Initial checkin. Renamed all relevant stuff to be Fred2 instead of * Fred. Globalized mission and campaign file extensions. Removed Silent * Threat specific code. * * 1 10/07/98 3:02p Dave * * 1 10/07/98 3:00p Dave * * 59 2/26/98 4:59p Allender * groundwork for team vs team briefings. Moved weaponry pool into the * Team_data structure. Added team field into the p_info structure. * Allow for mutliple structures in the briefing code. * * 58 1/06/98 2:27p Hoffoss * Made wing deleting free up arrival and departure cue sexp trees, which * wasn't happening before for some reason. * * 57 12/29/97 4:55p Johnson * Added some fixes. * * 56 11/21/97 11:46a Johnson * Changed code to delete reinforcement wings when the wing is deleted. * * 55 11/13/97 4:14p Allender * automatic assignment of hotkeys for starting wings. Appripriate * warnings when they are incorrectly used. hotkeys correctly assigned to * ships/wing arriving after mission start * * 54 10/01/97 12:37p Hoffoss * Changed Fred (and FreeSpace) to utilize alpha, beta and gamma as player * starting wing names. * * 53 9/16/97 9:41p Hoffoss * Changed Fred code around to stop using Parse_player structure for * player information, and use actual ships instead. * * 52 9/11/97 4:04p Hoffoss * Fixed bug in Fred: disband wing wasn't making sure the ship editor's * data was synced. * * 51 9/06/97 2:13p Mike * Replace support for TEAM_NEUTRAL * * 50 9/02/97 3:44p Johnson * Fixed bugs with thresholds not being lowered. * * 49 9/02/97 3:24p Johnson * Fixed bug: ships removed from wings will lower threshold if required. * * 48 8/30/97 9:52p Hoffoss * Implemented arrival location, distance, and anchor in Fred. * * 47 8/25/97 5:58p Hoffoss * Created menu items for keypress functions in Fred, and fixed bug this * uncovered with wing_delete function. * * 46 8/16/97 6:44p Hoffoss * Changes to allow any player to be in a wing. * * 45 8/16/97 4:51p Hoffoss * Fixed bugs with wing deletion and removing ships from a wing. * * 44 8/15/97 1:07a Hoffoss * Changed code to disallow some ship types from being in a wing, and * disallowing some ship types from being able to have initial orders. * * 43 8/12/97 1:55a Hoffoss * Made extensive changes to object reference checking and handling for * object deletion call. * * 42 8/10/97 4:24p Hoffoss * Added warning when creating a wing if wing is mixed. * * 41 8/08/97 1:31p Hoffoss * Added syncronization protection to cur_object_index changes. * * 40 8/08/97 10:07a Hoffoss * Fixed bug where ship references aren't updated when wing is created * (i.e. ships being renamed, but not in the references too). * * 39 8/01/97 3:24p Hoffoss * Fixed bug where when player is removed from a wing, the ship associated * with the player doesn't get its wingnum variable updated. * * 38 7/09/97 2:38p Allender * organized ship/wing editor dialogs. Added protect ship and ignore * count checkboxes to those dialogs. Changed flag code for * parse_objects. Added unprotect sexpressions * * 37 6/30/97 11:36a Hoffoss * Fixed bug with wing reforming. * * 36 6/18/97 2:36p Hoffoss * Wing ship numbering starts at 1 instead of 0, and changed form wing to * allow reforming a wing. * * 35 6/04/97 12:00a Allender * make wing goal priorities default to -1 so that their priorities get * set more appropriatly in the initial order dialog * * 34 5/14/97 4:08p Lawrance * removing my_index from game arrays * * 33 5/08/97 10:54a Hoffoss * Fixed bug in reforming wings screwing up ship names. * * 32 4/30/97 9:17a Hoffoss * Hotkey for wing set to none when new wing created. * * 31 3/28/97 3:19p Hoffoss * Fixed bug. * * 30 3/20/97 3:55p Hoffoss * Major changes to how dialog boxes initialize (load) and update (save) * their internal data. This should simplify things and create less * problems. * * 29 3/17/97 4:29p Hoffoss * Automated player's wing flaging as a starting player wing. * * 28 3/12/97 12:40p Hoffoss * Fixed bugs in wing object management functions, several small additions * and rearrangements. * * 27 3/04/97 6:27p Hoffoss * Changes to Fred to handle new wing structure. * * 26 2/28/97 11:31a Hoffoss * Implemented modeless dialog saving and restoring, and changed some * variables names. * * 25 2/27/97 3:16p Allender * major wing structure enhancement. simplified wing code. All around * better wing support * * 24 2/27/97 2:31p Hoffoss * Changed wing create code to bash ship's cues to false. * * 23 2/24/97 5:38p Hoffoss * Added dialog box to name a wing at creation, code to change ship names * to match wing name, and code to maintain these ship names. * * 22 2/20/97 4:03p Hoffoss * Several ToDo items: new reinforcement clears arrival cue, reinforcement * control from ship and wing dialogs, show grid toggle. * * 21 2/17/97 5:28p Hoffoss * Checked RCS headers, added them were missing, changing description to * something better, etc where needed. * * $NoKeywords: $ */ #include "stdafx.h" #include "FRED.h" #include "FREDDoc.h" #include "FREDView.h" #include "render/3d.h" #include "physics/physics.h" #include "object/object.h" #include "editor.h" #include "ai/ailocal.h" #include "ship/ship.h" #include "math/vecmat.h" #include "Management.h" #include "globalincs/linklist.h" #include "MainFrm.h" #include "wing.h" #include "CreateWingDlg.h" #include "Management.h" #define MULTI_WING 999999 #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif int already_deleting_wing = 0; void remove_player_from_wing(int player, int min = 1); // Finds a free wing slot (i.e. unused) int find_free_wing() { int i; for (i=0; i= 0 && Wings[wing].special_ship < Wings[wing].wave_count); set_cur_object_index(wing_objects[wing][Wings[wing].special_ship]); for (i=0; i= Wings[wing].wave_count)) Wings[wing].threshold = Wings[wing].wave_count - 1; } Ships[ship].wingnum = -1; } set_modified(); // reset ship name to non-wing default ship name sprintf(buf, "%s %d", Ship_info[Ships[ship].ship_info_index].name, ship); rename_ship(ship, buf); } // Takes a player out of a wing, deleting wing if that was the only ship in it. void remove_player_from_wing(int player, int min) { remove_ship_from_wing(player, min); } // 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->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_cue = Locked_sexp_true; Wings[wing].departure_cue = Locked_sexp_false; Wings[wing].hotkey = -1; Wings[wing].flags = 0; for (i=0; iflags & 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); } sprintf(msg, "%s %d", 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; } ///////////////////////////////////////////////////////////////////////////////////// // Old stuff down there.. #define MAX_WING_VECTORS 8 // 8 vectors per wing formation. Possible to have more // than 8 ships. A vector is where a ship is located relative // to the leader. Other ships can be located at the same // vector relative to another member. So wing formation // size is not limited by this constant. #define MAX_WING_FORMATIONS 8 // 8 different kinds of wing formations typedef struct formation { int num_vectors; vec3d offsets[MAX_WING_VECTORS]; } formation; formation Wing_formations[MAX_WING_FORMATIONS]; //wing Wings[MAX_WINGS]; int Wings_initialized = 0; void initialize_wings(void) { if (Wings_initialized) return; Wings_initialized = 1; Wing_formations[0].num_vectors = 2; Wing_formations[0].offsets[0].xyz.x = -5.0f; Wing_formations[0].offsets[0].xyz.y = +1.0f; Wing_formations[0].offsets[0].xyz.z = -5.0f; Wing_formations[0].offsets[1].xyz.x = +5.0f; Wing_formations[0].offsets[1].xyz.y = +1.0f; Wing_formations[0].offsets[1].xyz.z = -5.0f; } void create_wings_from_objects(void) { int i; for (i=0; i= 0) && (wingnum < MAX_WINGS)); Assert(Wings[wingnum].wave_count < MAX_SHIPS_PER_WING); // JEH strcpy(Wings[wingnum].ship_names[Wings[wingnum].count++], i; } } int get_free_objnum(void) { int i; for (i=1; i= 0) && (wing_type < MAX_WING_FORMATIONS)); Assert(Wing_formations[wing_type].num_vectors > 0); Assert(Wing_formations[wing_type].num_vectors < MAX_WING_VECTORS); Assert(Objects[leader_index].type != OBJ_NONE); Assert(max_size < MAX_SHIPS_PER_WING); num_placed = 0; wingp = &Wing_formations[wing_type]; num_vectors = wingp->num_vectors; cur_vec_index = 0; parent = lobjp; vm_copy_transpose_matrix(&rotmat, &lobjp->orient); while (num_placed < max_size) { vec3d wvec; int curobj; if (*wingmen == -1) { if (!fill_flag) break; else { curobj = get_free_objnum(); Assert(curobj != -1); Objects[curobj].type = lobjp->type; Assert(Wings[cur_wing].wave_count < MAX_SHIPS_PER_WING); // JEH Wings[cur_wing].ship_list[Wings[cur_wing].count] = curobj; Wings[cur_wing].wave_count++; } } else curobj = *wingmen++; Objects[curobj] = *lobjp; vm_vec_rotate(&wvec, &wingp->offsets[cur_vec_index], &rotmat); cur_vec_index = (cur_vec_index + 1) % num_vectors; if (num_placed < num_vectors) parent = lobjp; else parent = &Objects[wing_list[num_placed - num_vectors]]; wing_list[num_placed] = curobj; vm_vec_add(&Objects[curobj].pos, &parent->pos, &wvec); num_placed++; } } // Create a wing. // cur_object_index becomes the leader. // If count == -1, then all objects of wing cur_wing get added to the wing. // If count == +n, then n objects are added to the wing. void test_form_wing(int count) { int i, wingmen[MAX_OBJECTS]; int j, fill_flag; j = 0; Assert(cur_object_index != -1); Assert(Objects[cur_object_index].type != OBJ_NONE); Assert(get_wingnum(cur_object_index) != -1); get_wingnum(cur_object_index); wingmen[0] = -1; for (i=1; i 0) { fill_flag = 1; j += count; } set_wingnum(cur_object_index, cur_wing); create_wing(0, cur_object_index, wingmen, j, fill_flag); }