/* * 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. * */ // InitialStatus.cpp : implementation file // #include "stdafx.h" #include "FRED.h" #include "FREDDoc.h" #include "FREDView.h" #include "InitialStatus.h" #include "Management.h" #include "globalincs/linklist.h" #include "globalincs/alphacolors.h" #include "object/objectdock.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // non-class function prototypes, bah void initial_status_mark_dock_leader_helper(object *objp, dock_function_info *infop); void initial_status_unmark_dock_handled_flag(object *objp, dock_function_info *infop); void reset_arrival_to_false(int shipnum, bool reset_wing); /** * @brief Handles setting a flag on a flagset when the value is inconsistent * * This is necessary in case multiple ships with inconsistent object flags have been selected in which case * that flag may not be edited since it would corrupt the value of that flag. This function simplifies handling * that case. */ template static void handle_inconsistent_flag(flagset& flags, T flag, int value) { if (value == 1) { flags.set(flag); } else if (value == 0) { flags.remove(flag); } } ///////////////////////////////////////////////////////////////////////////// // initial_status dialog initial_status::initial_status(CWnd* pParent /*=NULL*/) : CDialog(initial_status::IDD, pParent) { //{{AFX_DATA_INIT(initial_status) m_damage = 0; m_shields = 0; m_velocity = 0; m_hull = 0; m_has_shields = FALSE; m_force_shields = FALSE; m_ship_locked = FALSE; m_weapons_locked = FALSE; m_primaries_locked = FALSE; m_secondaries_locked = FALSE; m_turrets_locked = FALSE; m_afterburner_locked = FALSE; m_cargo_name = _T(""); //}}AFX_DATA_INIT inited = 0; cur_subsys = LB_ERR; dockpoint_array = NULL; num_dock_points = 0; cur_docker_point = -1; cur_dockee = -1; cur_dockee_point = -1; m_multi_edit = 0; } initial_status::~initial_status() { if (dockpoint_array != NULL) delete [] dockpoint_array; } void initial_status::DoDataExchange(CDataExchange* pDX) { CString str; CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(initial_status) DDX_Control(pDX, IDC_HULL_SPIN, m_hull_spin); DDX_Control(pDX, IDC_VELOCITY_SPIN, m_velocity_spin); DDX_Control(pDX, IDC_SHIELDS_SPIN, m_shields_spin); DDX_Control(pDX, IDC_DAMAGE_SPIN, m_damage_spin); DDX_Control(pDX, IDC_TEAMSELECT, m_team_color_setting); DDX_Text(pDX, IDC_DAMAGE, m_damage); DDV_MinMaxInt(pDX, m_damage, 0, 100); DDX_Check(pDX, IDC_HAS_SHIELDS, m_has_shields); DDX_Check(pDX, IDC_FORCE_SHIELDS, m_force_shields); DDX_Check(pDX, IDC_SHIP_LOCKED, m_ship_locked); DDX_Check(pDX, IDC_WEAPONS_LOCKED, m_weapons_locked); DDX_Check(pDX, IDC_PRIMARIES_LOCKED, m_primaries_locked); DDX_Check(pDX, IDC_SECONDARIES_LOCKED, m_secondaries_locked); DDX_Check(pDX, IDC_TURRETS_LOCKED, m_turrets_locked); DDX_Check(pDX, IDC_AFTERBURNER_LOCKED, m_afterburner_locked); DDX_Text(pDX, IDC_CARGO_NAME, m_cargo_name); DDV_MaxChars(pDX, m_cargo_name, 20); //}}AFX_DATA_MAP if (pDX->m_bSaveAndValidate) { GetDlgItem(IDC_VELOCITY)->GetWindowText(str); m_velocity = atoi(str); if (m_velocity < 0) m_velocity = 0; if (m_velocity > 100) m_velocity = 100; GetDlgItem(IDC_SHIELDS)->GetWindowText(str); m_shields = atoi(str); if (m_shields < 0) m_shields = 0; if (m_shields > 100) m_shields = 100; GetDlgItem(IDC_HULL)->GetWindowText(str); m_hull = atoi(str); if (m_hull < 0) m_hull = 0; if (m_hull > 100) m_hull = 100; } } BEGIN_MESSAGE_MAP(initial_status, CDialog) //{{AFX_MSG_MAP(initial_status) ON_LBN_SELCHANGE(IDC_SUBSYS, OnSelchangeSubsys) ON_LBN_SELCHANGE(IDC_DOCKER_POINT, OnSelchangeDockerPoint) ON_CBN_SELCHANGE(IDC_DOCKEE, OnSelchangeDockee) ON_CBN_SELCHANGE(IDC_DOCKEE_POINT, OnSelchangeDockeePoint) ON_BN_CLICKED(IDC_HAS_SHIELDS, OnHasShields) ON_BN_CLICKED(IDC_FORCE_SHIELDS, OnForceShields) ON_BN_CLICKED(IDC_SHIP_LOCKED, OnShipLocked) ON_BN_CLICKED(IDC_WEAPONS_LOCKED, OnWeaponsLocked) ON_BN_CLICKED(IDC_PRIMARIES_LOCKED, OnPrimariesLocked) ON_BN_CLICKED(IDC_SECONDARIES_LOCKED, OnSecondariesLocked) ON_BN_CLICKED(IDC_TURRETS_LOCKED, OnTurretsLocked) ON_BN_CLICKED(IDC_AFTERBURNER_LOCKED, OnAfterburnersLocked) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // initial_status message handlers BOOL initial_status::OnInitDialog() { int z, vflag, sflag, hflag; ship_subsys *ptr; CString str; object *objp = NULL; m_ship = cur_ship; if (m_ship == -1) { Assert((Objects[cur_object_index].type == OBJ_SHIP) || (Objects[cur_object_index].type == OBJ_START)); m_ship = get_ship_from_obj(cur_object_index); Assert(m_ship >= 0); } // initialize dockpoint stuff if (!m_multi_edit) { num_dock_points = model_get_num_dock_points(Ship_info[Ships[m_ship].ship_info_index].model_num); dockpoint_array = new dockpoint_information[num_dock_points]; objp = &Objects[Ships[m_ship].objnum]; for (int i = 0; i < num_dock_points; i++) { object *docked_objp = dock_find_object_at_dockpoint(objp, i); if (docked_objp != NULL) { dockpoint_array[i].dockee_shipnum = docked_objp->instance; dockpoint_array[i].dockee_point = dock_find_dockpoint_used_by_object(docked_objp, objp); } else { dockpoint_array[i].dockee_shipnum = -1; dockpoint_array[i].dockee_point = -1; } } } vflag = sflag = hflag = 0; m_velocity = (int) Objects[cur_object_index].phys_info.speed; m_shields = (int) Objects[cur_object_index].shield_quadrant[0]; m_hull = (int) Objects[cur_object_index].hull_strength; if (Objects[cur_object_index].flags[Object::Object_Flags::No_shields]) m_has_shields = 0; else m_has_shields = 1; if (Ships[m_ship].flags[Ship::Ship_Flags::Force_shields_on]) m_force_shields = 1; else m_force_shields = 0; if (Ships[m_ship].flags[Ship::Ship_Flags::Ship_locked]) m_ship_locked = 1; else m_ship_locked = 0; if (Ships[m_ship].flags[Ship::Ship_Flags::Weapons_locked]) m_weapons_locked = 1; else m_weapons_locked = 0; // Lock primaries if (Ships[m_ship].flags[Ship::Ship_Flags::Primaries_locked]) { m_primaries_locked = 1; } else { m_primaries_locked = 0; } //Lock secondaries if (Ships[m_ship].flags[Ship::Ship_Flags::Secondaries_locked]) { m_secondaries_locked = 1; } else { m_secondaries_locked = 0; } //Lock turrets if (Ships[m_ship].flags[Ship::Ship_Flags::Lock_all_turrets_initially]) { m_turrets_locked = 1; } else { m_turrets_locked = 0; } if (Ships[m_ship].flags[Ship::Ship_Flags::Afterburner_locked]) { m_afterburner_locked = 1; } else { m_afterburner_locked = 0; } if (m_multi_edit) { objp = GET_FIRST(&obj_used_list); while (objp != END_OF_LIST(&obj_used_list)) { if (((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)) && (objp->flags[Object::Object_Flags::Marked])) { if (objp->phys_info.speed != m_velocity) vflag = 1; if ((int) objp->shield_quadrant[0] != m_shields) sflag = 1; if ((int) objp->hull_strength != m_hull) hflag = 1; if (objp->flags[Object::Object_Flags::No_shields]) { if (m_has_shields) m_has_shields = 2; } else { if (!m_has_shields) m_has_shields = 2; } Assert((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)); if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Force_shields_on]) { if (!m_force_shields) m_force_shields = 2; } else { if (m_force_shields) m_force_shields = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Ship_locked]) { if (!m_ship_locked) m_ship_locked = 2; } else { if (m_ship_locked) m_ship_locked = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Weapons_locked]) { if (!m_weapons_locked) m_weapons_locked = 2; } else { if (m_weapons_locked) m_weapons_locked = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Primaries_locked]){ if (!m_primaries_locked) m_primaries_locked = 2; } else { if (m_primaries_locked) m_primaries_locked = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Secondaries_locked]){ if (!m_secondaries_locked) m_secondaries_locked = 2; } else { if (m_secondaries_locked) m_secondaries_locked = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Lock_all_turrets_initially]){ if (!m_turrets_locked) m_turrets_locked = 2; } else { if (m_turrets_locked) m_turrets_locked = 2; } if (Ships[get_ship_from_obj(objp)].flags[Ship::Ship_Flags::Afterburner_locked]){ if (!m_afterburner_locked) m_afterburner_locked = 2; } else { if (m_afterburner_locked) m_afterburner_locked = 2; } } objp = GET_NEXT(objp); } } CDialog::OnInitDialog(); str.Format("%d", m_velocity); GetDlgItem(IDC_VELOCITY)->SetWindowText(str); str.Format("%d", m_shields); GetDlgItem(IDC_SHIELDS)->SetWindowText(str); str.Format("%d", m_hull); GetDlgItem(IDC_HULL)->SetWindowText(str); inited = 1; GetDlgItem(IDC_SHIELDS)->EnableWindow(m_has_shields ? TRUE : FALSE); GetDlgItem(IDC_SHIELDS_SPIN)->EnableWindow(m_has_shields ? TRUE : FALSE); m_velocity_spin.SetRange(0, 100); m_hull_spin.SetRange(0, 100); m_shields_spin.SetRange(0, 100); m_damage_spin.SetRange(0, 100); // init boxes lstDockerPoints = (CListBox *) GetDlgItem(IDC_DOCKER_POINT); cboDockees = (CComboBox *) GetDlgItem(IDC_DOCKEE); cboDockeePoints = (CComboBox *) GetDlgItem(IDC_DOCKEE_POINT); lstDockerPoints->ResetContent(); cboDockees->ResetContent(); cboDockeePoints->ResetContent(); if (!m_multi_edit) { for (int dockpoint = 0; dockpoint < num_dock_points; dockpoint++) { z = lstDockerPoints->AddString(model_get_dock_name(Ship_info[Ships[m_ship].ship_info_index].model_num, dockpoint)); lstDockerPoints->SetItemData(z, dockpoint); } for (ptr = GET_FIRST(&Ships[m_ship].subsys_list); ptr != END_OF_LIST(&Ships[m_ship].subsys_list); ptr = GET_NEXT(ptr)) { ((CListBox *) GetDlgItem(IDC_SUBSYS))->AddString(ptr->system_info->subobj_name); } } else { GetDlgItem(IDC_SUBSYS)->EnableWindow(FALSE); GetDlgItem(IDC_DAMAGE)->EnableWindow(FALSE); } change_docker_point(false); change_subsys(); UpdateData(FALSE); if (vflag) GetDlgItem(IDC_VELOCITY)->SetWindowText(""); if (sflag) GetDlgItem(IDC_SHIELDS)->SetWindowText(""); if (hflag) GetDlgItem(IDC_HULL)->SetWindowText(""); if (objp != NULL) { if (objp->type == OBJ_SHIP || objp->type == OBJ_START) { ship* shipp = &Ships[objp->instance]; int i = 0; if (Ship_info[shipp->ship_info_index].uses_team_colors) { //Add a "None" entry at the beginning to allow simple deselection of colours int t = m_team_color_setting.AddString("None"); m_team_color_setting.SetCurSel(i); m_team_color_setting.SetItemData(t, i); ++i; for (SCP_vector::iterator tni = Team_Names.begin(); tni != Team_Names.end(); ++tni) { z = m_team_color_setting.AddString(tni->c_str()); if (!stricmp(tni->c_str(), shipp->team_name.c_str())) { m_team_color_setting.SetCurSel(i); } m_team_color_setting.SetItemData(z, i); i++; } m_team_color_setting.EnableWindow(); } else { m_team_color_setting.EnableWindow(FALSE); } } } return TRUE; } void initial_status::OnOK() { char buf[256]; int vflag = 0, sflag = 0, hflag = 0; object *objp; if (GetDlgItem(IDC_VELOCITY)->GetWindowText(buf, 255)) vflag = 1; if (GetDlgItem(IDC_SHIELDS)->GetWindowText(buf, 255)) sflag = 1; if (GetDlgItem(IDC_HULL)->GetWindowText(buf, 255)) hflag = 1; UpdateData(TRUE); change_subsys(); if (m_multi_edit) { objp = GET_FIRST(&obj_used_list); while (objp != END_OF_LIST(&obj_used_list)) { if (((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)) && (objp->flags[Object::Object_Flags::Marked])) { if (vflag) MODIFY(objp->phys_info.speed, (float) m_velocity); if (sflag) MODIFY(objp->shield_quadrant[0], (float) m_shields); if (hflag) MODIFY(objp->hull_strength, (float) m_hull); if (m_has_shields == 1) objp->flags.remove(Object::Object_Flags::No_shields); else if (m_has_shields == 0) objp->flags.set(Object::Object_Flags::No_shields); auto shipp = &Ships[get_ship_from_obj(objp)]; // We need to ensure that we handle the inconsistent "boolean" value correctly handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Force_shields_on, m_force_shields); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Ship_locked, m_ship_locked); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Weapons_locked, m_weapons_locked); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Primaries_locked, m_primaries_locked); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Secondaries_locked, m_secondaries_locked); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Lock_all_turrets_initially, m_turrets_locked); handle_inconsistent_flag(shipp->flags, Ship::Ship_Flags::Afterburner_locked, m_afterburner_locked); } objp = GET_NEXT(objp); } } else { MODIFY(Objects[cur_object_index].phys_info.speed, (float) m_velocity); MODIFY(Objects[cur_object_index].shield_quadrant[0], (float) m_shields); MODIFY(Objects[cur_object_index].hull_strength, (float) m_hull); Objects[cur_object_index].flags.set(Object::Object_Flags::No_shields, m_has_shields == 0); // We need to ensure that we handle the inconsistent "boolean" value correctly. Not strictly needed here but just to be safe... handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Force_shields_on, m_force_shields); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Ship_locked, m_ship_locked); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Weapons_locked, m_weapons_locked); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Primaries_locked, m_primaries_locked); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Secondaries_locked, m_secondaries_locked); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Lock_all_turrets_initially, m_turrets_locked); handle_inconsistent_flag(Ships[m_ship].flags, Ship::Ship_Flags::Afterburner_locked, m_afterburner_locked); } if (m_team_color_setting.IsWindowEnabled()) { if (m_team_color_setting.GetCurSel() > 0) Ships[m_ship].team_name = Team_Names[m_team_color_setting.GetCurSel() - 1]; else Ships[m_ship].team_name = "none"; } update_docking_info(); CDialog::OnOK(); } void initial_status::OnHasShields() { if (m_has_shields == 1) { m_has_shields = 0; // can't force shields and also have them off if (m_force_shields) { m_force_shields = 0; ((CButton *) GetDlgItem(IDC_FORCE_SHIELDS))->SetCheck(m_force_shields); // warn on multiple ships of different state if (m_multi_edit) { MessageBox("At least one selected ship was set to Force Shields On. This is now turned off for all selected ships", "Resetting Flag", MB_OK | MB_ICONEXCLAMATION); } } } else m_has_shields = 1; ((CButton *) GetDlgItem(IDC_HAS_SHIELDS))->SetCheck(m_has_shields); GetDlgItem(IDC_SHIELDS)->EnableWindow(m_has_shields); GetDlgItem(IDC_SHIELDS_SPIN)->EnableWindow(m_has_shields); } void initial_status::OnForceShields() { if (m_force_shields == 1) m_force_shields = 0; else { m_force_shields = 1; // can't force shields and also turn have them off if (m_has_shields != 1) { m_has_shields = 1; ((CButton *) GetDlgItem(IDC_HAS_SHIELDS))->SetCheck(m_has_shields); GetDlgItem(IDC_SHIELDS)->EnableWindow(m_has_shields); GetDlgItem(IDC_SHIELDS_SPIN)->EnableWindow(m_has_shields); // warn on multiple ships of different state if (m_multi_edit) { MessageBox("At least one selected ship was set to have no shields. Shields are now enabled for all selected ships", "Resetting Flag", MB_OK | MB_ICONEXCLAMATION); } } } ((CButton *) GetDlgItem(IDC_FORCE_SHIELDS))->SetCheck(m_force_shields); } void initial_status::OnShipLocked() { if (m_ship_locked == 1) m_ship_locked = 0; else m_ship_locked = 1; ((CButton *) GetDlgItem(IDC_SHIP_LOCKED))->SetCheck(m_ship_locked); } void initial_status::OnWeaponsLocked() { if (m_weapons_locked == 1) m_weapons_locked = 0; else m_weapons_locked = 1; ((CButton *) GetDlgItem(IDC_WEAPONS_LOCKED))->SetCheck(m_weapons_locked); } void initial_status::OnSelchangeSubsys() { UpdateData(TRUE); change_subsys(); UpdateData(FALSE); } void initial_status::change_subsys() { int z, cargo_index, enable = FALSE, enable_cargo_name = FALSE; int ship_has_scannable_subsystems; ship_subsys *ptr; // Goober5000 ship_has_scannable_subsystems = Ship_info[Ships[m_ship].ship_info_index].is_huge_ship(); if (Ships[m_ship].flags[Ship::Ship_Flags::Toggle_subsystem_scanning]) ship_has_scannable_subsystems = !ship_has_scannable_subsystems; if (cur_subsys != LB_ERR) { ptr = GET_FIRST(&Ships[m_ship].subsys_list); while (cur_subsys--) { Assert(ptr != END_OF_LIST(&Ships[m_ship].subsys_list)); ptr = GET_NEXT(ptr); } MODIFY(ptr -> current_hits, 100.0f - (float) m_damage); // update cargo name if (strlen(m_cargo_name) > 0) { //-V805 lcl_fred_replace_stuff(m_cargo_name); cargo_index = string_lookup(m_cargo_name, Cargo_names, Num_cargo); if (cargo_index == -1) { if (Num_cargo < MAX_CARGO); cargo_index = Num_cargo++; strcpy(Cargo_names[cargo_index], m_cargo_name); ptr->subsys_cargo_name = cargo_index; } else { ptr->subsys_cargo_name = cargo_index; } } else { ptr->subsys_cargo_name = 0; } set_modified(); } cur_subsys = z = ((CListBox *) GetDlgItem(IDC_SUBSYS)) -> GetCurSel(); if (z == LB_ERR) { m_damage = 100; } else { ptr = GET_FIRST(&Ships[m_ship].subsys_list); while (z--) { Assert(ptr != END_OF_LIST(&Ships[m_ship].subsys_list)); ptr = GET_NEXT(ptr); } m_damage = 100 - (int) ptr -> current_hits; if ( ship_has_scannable_subsystems ) { enable_cargo_name = TRUE; if (ptr->subsys_cargo_name > 0) { m_cargo_name = Cargo_names[ptr->subsys_cargo_name]; } else { m_cargo_name = _T(""); } } else { m_cargo_name = _T(""); } enable = TRUE; } GetDlgItem(IDC_DAMAGE) -> EnableWindow(enable); GetDlgItem(IDC_DAMAGE_SPIN) -> EnableWindow(enable); GetDlgItem(IDC_CARGO_NAME)->EnableWindow(enable && enable_cargo_name); } void initial_status::OnSelchangeDockerPoint() { change_docker_point(true); } void initial_status::change_docker_point(bool store_selection) { int sel; // grab from controls UpdateData(TRUE); // get new selection sel = lstDockerPoints->GetCurSel(); if (sel != LB_ERR) cur_docker_point = (int)lstDockerPoints->GetItemData(sel); else cur_docker_point = -1; // populate the next dropdowns if (cur_docker_point < 0) { // clear the dropdowns list_dockees(-1); list_dockee_points(-1); } else { // populate with all possible dockees list_dockees(model_get_dock_index_type(Ship_info[Ships[m_ship].ship_info_index].model_num, cur_docker_point)); // see if there's a dockee here if (dockpoint_array[cur_docker_point].dockee_shipnum >= 0) { // select the dockee cboDockees->SelectString(-1, Ships[dockpoint_array[cur_docker_point].dockee_shipnum].ship_name); change_dockee(false); } else { // select "Nothing" cboDockees->SetCurSel(0); change_dockee(true); } } // store to controls UpdateData(FALSE); } void initial_status::OnSelchangeDockee() { change_dockee(true); } void initial_status::change_dockee(bool store_selection) { int sel; // grab from controls UpdateData(TRUE); // get new selection sel = cboDockees->GetCurSel(); if (sel != CB_ERR) cur_dockee = (int)cboDockees->GetItemData(sel); else cur_dockee = -1; // are we storing it? if (store_selection) { dockpoint_array[cur_docker_point].dockee_shipnum = cur_dockee; dockpoint_array[cur_docker_point].dockee_point = -1; } // populate the next dropdown if (cur_dockee < 0) { // clear the dropdown list_dockee_points(-1); } else { // populate with dockee points list_dockee_points(cur_dockee); // see if there's a dockpoint here if (dockpoint_array[cur_docker_point].dockee_point >= 0) { // select the dockpoint cboDockeePoints->SelectString(-1, model_get_dock_name(Ship_info[Ships[cur_dockee].ship_info_index].model_num, dockpoint_array[cur_docker_point].dockee_point)); change_dockee_point(false); } // there might not be any dockpoints available else if (cboDockeePoints->GetCount() == 0) { cboDockeePoints->EnableWindow(FALSE); change_dockee_point(false); } else { // just select the first dockpoint cboDockeePoints->SetCurSel(0); change_dockee_point(true); } } // store to controls UpdateData(FALSE); } void initial_status::OnSelchangeDockeePoint() { change_dockee_point(true); } void initial_status::change_dockee_point(bool store_selection) { int sel; // grab from controls UpdateData(TRUE); // get new value sel = cboDockeePoints->GetCurSel(); if (sel != CB_ERR) cur_dockee_point = (int)cboDockeePoints->GetItemData(sel); else cur_dockee_point = -1; // are we storing it? if (store_selection) { dockpoint_array[cur_docker_point].dockee_point = cur_dockee_point; } // store to controls UpdateData(FALSE); } void initial_status::list_dockees(int dock_types) { int z; // enable/disable dropdown cboDockees->EnableWindow((dock_types >= 0) ? TRUE : FALSE); // clear the existing dockees cboDockees->ResetContent(); // that might be all we need to do if (dock_types < 0) return; // populate with potential dockees // add "nothing" z = cboDockees->AddString("Nothing"); cboDockees->SetItemData(z, static_cast(-1)); // add ships for (object *objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp)) { if ((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)) { int ship = get_ship_from_obj(objp); // mustn't be the same ship if (ship == m_ship) continue; // mustn't also be docked elsewhere bool docked_elsewhere = false; for (int i = 0; i < num_dock_points; i++) { // don't erroneously check the same point if (i == cur_docker_point) continue; // see if this ship is also on a different dockpoint if (dockpoint_array[i].dockee_shipnum == ship) { docked_elsewhere = true; break; } } if (docked_elsewhere) continue; // docking must be valid if (!ship_docking_valid(m_ship, ship) && !ship_docking_valid(ship, m_ship)) continue; // dock types must match if (!(model_get_dock_types(Ship_info[Ships[ship].ship_info_index].model_num) & dock_types)) continue; // add to list z = cboDockees->AddString(Ships[ship].ship_name); cboDockees->SetItemData(z, ship); } } } void initial_status::list_dockee_points(int shipnum) { int z; ship *shipp = &Ships[m_ship]; ship *other_shipp = &Ships[shipnum]; // enable/disable dropdown cboDockeePoints->EnableWindow((shipnum >= 0) ? TRUE : FALSE); // clear the existing dockee points cboDockeePoints->ResetContent(); // that might be all we need to do if (shipnum < 0) return; // get the required dock type(s) int dock_type = model_get_dock_index_type(Ship_info[shipp->ship_info_index].model_num, cur_docker_point); // populate with the right kind of dockee points for (int i = 0; i < model_get_num_dock_points(Ship_info[other_shipp->ship_info_index].model_num); i++) { // make sure this dockpoint is not occupied by someone else object *docked_objp = dock_find_object_at_dockpoint(&Objects[other_shipp->objnum], i); if ((docked_objp != NULL) && (docked_objp != &Objects[shipp->objnum])) continue; // make sure its type matches if (!(model_get_dock_index_type(Ship_info[other_shipp->ship_info_index].model_num, i) & dock_type)) continue; // add to list z = cboDockeePoints->AddString(model_get_dock_name(Ship_info[other_shipp->ship_info_index].model_num, i)); cboDockeePoints->SetItemData(z, i); } } void initial_status::update_docking_info() { int i; object *objp = &Objects[Ships[m_ship].objnum]; // remove old info for (i = 0; i < num_dock_points; i++) { // see if the object at this point is no longer there object *dockee_objp = dock_find_object_at_dockpoint(objp, i); if (dockee_objp != NULL) { // check if the dockee ship thinks that this ship is docked to this dock point if (objp != dock_find_object_at_dockpoint(dockee_objp, dockpoint_array[i].dockee_point) ) { // undock it undock(objp, dockee_objp); } } } // add new info for (i = 0; i < num_dock_points; i++) { // see if there is an object at this point that wasn't there before if (dockpoint_array[i].dockee_shipnum >= 0) { if (dock_find_object_at_dockpoint(objp, i) == NULL) { object *dockee_objp = &Objects[Ships[dockpoint_array[i].dockee_shipnum].objnum]; int dockee_point = dockpoint_array[i].dockee_point; // dock it dock(objp, i, dockee_objp, dockee_point); } } } update_map_window(); } void initial_status::dock(object *objp, int dockpoint, object *other_objp, int other_dockpoint) { if (objp == NULL || other_objp == NULL) return; if (dockpoint < 0 || other_dockpoint < 0) return; dock_function_info dfi; // do the docking (do it in reverse so that the current object stays put) ai_dock_with_object(other_objp, other_dockpoint, objp, dockpoint, AIDO_DOCK_NOW); // unmark the handled flag in preparation for the next step dock_evaluate_all_docked_objects(objp, &dfi, initial_status_unmark_dock_handled_flag); // move all other objects to catch up with it dock_move_docked_objects(objp); // set the dock leader dock_evaluate_all_docked_objects(objp, &dfi, initial_status_mark_dock_leader_helper); // if no leader, mark me if (dfi.maintained_variables.int_value == 0) Ships[objp->instance].flags.set(Ship::Ship_Flags::Dock_leader); } void initial_status::undock(object *objp1, object *objp2) { vec3d v; int ship_num, other_ship_num; if (objp1 == NULL || objp2 == NULL) return; vm_vec_sub(&v, &objp2->pos, &objp1->pos); vm_vec_normalize(&v); ship_num = get_ship_from_obj(OBJ_INDEX(objp1)); other_ship_num = get_ship_from_obj(OBJ_INDEX(objp2)); if (Move_ships_when_undocking) { if (ship_class_compare(Ships[ship_num].ship_info_index, Ships[other_ship_num].ship_info_index) <= 0) vm_vec_scale_add2(&objp2->pos, &v, ship_class_get_length(&Ship_info[Ships[objp2->instance].ship_info_index])); else vm_vec_scale_add2(&objp1->pos, &v, ship_class_get_length(&Ship_info[Ships[objp1->instance].ship_info_index]) * -1.0f); } ai_do_objects_undocked_stuff(objp1, objp2); // check to see if one of these ships has an arrival cue of false. If so, then // reset it back to default value of true. be sure to correctly update before // and after setting data. // Goober5000 - but don't reset it if it's part of a wing! Ship_editor_dialog.update_data(1); if ( Ships[ship_num].arrival_cue == Locked_sexp_false && Ships[ship_num].wingnum < 0 ) { Ships[ship_num].arrival_cue = Locked_sexp_true; } else if ( Ships[other_ship_num].arrival_cue == Locked_sexp_false && Ships[other_ship_num].wingnum < 0 ) { Ships[other_ship_num].arrival_cue = Locked_sexp_true; } // if this ship is no longer docked, ensure its dock leader flag is clear if (!object_is_docked(&Objects[Ships[ship_num].objnum])) Ships[ship_num].flags.remove(Ship::Ship_Flags::Dock_leader); // same for the other ship if (!object_is_docked(&Objects[Ships[other_ship_num].objnum])) Ships[other_ship_num].flags.remove(Ship::Ship_Flags::Dock_leader); Ship_editor_dialog.initialize_data(1); } // ----- the following are not contained in the class because of apparent scope issues ----- 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; } // function to set the arrival cue of a ship to false void reset_arrival_to_false(int shipnum, bool reset_wing) { char buf[256]; ship *shipp = &Ships[shipnum]; // falsify the ship cue if (set_cue_to_false(&shipp->arrival_cue)) { sprintf(buf, "Setting arrival cue of ship %s\nto false for initial docking purposes.", shipp->ship_name); MessageBox(NULL, buf, "", MB_OK | MB_ICONEXCLAMATION); } // falsify the wing cue and all ships in that wing if (reset_wing && shipp->wingnum >= 0) { int i; wing *wingp = &Wings[shipp->wingnum]; if (set_cue_to_false(&wingp->arrival_cue)) { sprintf(buf, "Setting arrival cue of wing %s\nto false for initial docking purposes.", wingp->name); MessageBox(NULL, buf, "", MB_OK | MB_ICONEXCLAMATION); } for (i = 0; i < wingp->wave_count; i++) reset_arrival_to_false(wingp->ship_index[i], false); } } // NOTE - in both retail and SCP, the dock "leader" is defined as the only guy in his // group with a non-false arrival cue void initial_status_mark_dock_leader_helper(object *objp, dock_function_info *infop) { ship *shipp = &Ships[objp->instance]; int cue_to_check; // if this guy is part of a wing, he uses his wing's arrival cue if (shipp->wingnum >= 0) { cue_to_check = Wings[shipp->wingnum].arrival_cue; } // check the ship's arrival cue else { cue_to_check = shipp->arrival_cue; } // all ships except the leader should have a locked false arrival cue if (cue_to_check != Locked_sexp_false) { object *existing_leader; // increment number of leaders found infop->maintained_variables.int_value++; // see if we already found a leader existing_leader = infop->maintained_variables.objp_value; if (existing_leader != NULL) { ship *leader_shipp = &Ships[existing_leader->instance]; // keep existing leader if he has a higher priority than us if (ship_class_compare(shipp->ship_info_index, leader_shipp->ship_info_index) >= 0) { // set my arrival cue to false reset_arrival_to_false(SHIP_INDEX(shipp), true); return; } // otherwise, unmark the existing leader and set his arrival cue to false leader_shipp->flags.remove(Ship::Ship_Flags::Dock_leader); reset_arrival_to_false(SHIP_INDEX(leader_shipp), true); } // mark and save me as the leader shipp->flags.set(Ship::Ship_Flags::Dock_leader); infop->maintained_variables.objp_value = objp; } } // self-explanatory, really void initial_status_unmark_dock_handled_flag(object *objp, dock_function_info *infop) { objp->flags.remove(Object::Object_Flags::Docked_already_handled); } void initial_status::OnPrimariesLocked() { if (m_primaries_locked == 1) m_primaries_locked = 0; else m_primaries_locked = 1; ((CButton *) GetDlgItem(IDC_PRIMARIES_LOCKED))->SetCheck(m_primaries_locked); } void initial_status::OnSecondariesLocked() { if (m_secondaries_locked == 1) m_secondaries_locked = 0; else m_secondaries_locked = 1; ((CButton *) GetDlgItem(IDC_SECONDARIES_LOCKED))->SetCheck(m_secondaries_locked); } void initial_status::OnTurretsLocked() { if (m_turrets_locked == 1) m_turrets_locked = 0; else m_turrets_locked = 1; ((CButton *) GetDlgItem(IDC_TURRETS_LOCKED))->SetCheck(m_turrets_locked); } void initial_status::OnAfterburnersLocked() { if (m_afterburner_locked == 1) m_afterburner_locked = 0; else m_afterburner_locked = 1; ((CButton *) GetDlgItem(IDC_AFTERBURNER_LOCKED))->SetCheck(m_afterburner_locked); }