Skip to content

Commit 41d800c

Browse files
committed
Add docking and undocking test to the Lab
1 parent d9381d6 commit 41d800c

7 files changed

Lines changed: 333 additions & 0 deletions

File tree

code/ai/aicode.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,21 @@ void garbage_collect_path_points()
542542

543543
}
544544

545+
void reset_ai_path_points()
546+
{
547+
memset(Path_points, 0, sizeof(Path_points)); // optional: zero out for safety
548+
Ppfp = Path_points;
549+
550+
// Also clear any AI path state
551+
for (int i = 0; i < MAX_SHIPS; ++i) {
552+
if (Ai_info[i].path_length > 0) {
553+
Ai_info[i].path_start = -1;
554+
Ai_info[i].path_cur = -1;
555+
Ai_info[i].path_length = 0;
556+
}
557+
}
558+
}
559+
545560
/**
546561
* Hash two values together, return result.
547562
* Hash function: curval shifted right circular by one, newval xored in.

code/ai/aigoals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ typedef struct ai_goal {
152152

153153
extern void ai_goal_reset(ai_goal *aigp, bool adding_goal = false, ai_goal_mode ai_mode = AI_GOAL_NONE, int ai_submode = -1, ai_goal_type type = ai_goal_type::INVALID);
154154

155+
// Reset all path points. Used in the ship lab. Missions clean up path points with the garbage collector.
156+
extern void reset_ai_path_points();
155157

156158
typedef flag_def_list_templated<ai_goal_mode> ai_goal_list;
157159

code/lab/dialogs/lab_ui.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,94 @@ void LabUi::show_object_options() const
12401240
}
12411241
}
12421242

1243+
const ship* dockee_shipp = &Ships[Objects[getLabManager()->CurrentObject].instance];
1244+
auto dockee_dock_map = get_docking_point_map(Ship_info[dockee_shipp->ship_info_index].model_num);
1245+
1246+
if (!dockee_dock_map.empty()) {
1247+
1248+
if (ImGui::BeginCombo("Docker Ship Class", Ship_info[getLabManager()->DockerClass].name)) {
1249+
for (size_t i = 0; i < Ship_info.size(); ++i) {
1250+
bool is_selected = (static_cast<int>(i) == getLabManager()->DockerClass);
1251+
if (ImGui::Selectable(Ship_info[i].name, is_selected)) {
1252+
getLabManager()->DockerClass = static_cast<int>(i);
1253+
// Load model if needed
1254+
auto& dsip = Ship_info[getLabManager()->DockerClass];
1255+
if (dsip.model_num < 0) {
1256+
dsip.model_num = model_load(dsip.pof_file, &dsip);
1257+
}
1258+
auto new_dock_map = get_docking_point_map(dsip.model_num);
1259+
1260+
// Auto-select first available dockpoint (or clear if none)
1261+
if (!new_dock_map.empty()) {
1262+
getLabManager()->DockerDockPoint = new_dock_map.begin()->second;
1263+
} else {
1264+
getLabManager()->DockerDockPoint.clear();
1265+
}
1266+
}
1267+
if (is_selected)
1268+
ImGui::SetItemDefaultFocus();
1269+
}
1270+
ImGui::EndCombo();
1271+
}
1272+
1273+
auto& dsip = Ship_info[getLabManager()->DockerClass];
1274+
if (dsip.model_num < 0) {
1275+
dsip.model_num = model_load(dsip.pof_file, &dsip);
1276+
}
1277+
auto dock_map = get_docking_point_map(dsip.model_num);
1278+
1279+
// Ensure DockerDockPoint is initialized once based on the current DockerClass
1280+
if (getLabManager()->DockerDockPoint.empty()) {
1281+
if (!dock_map.empty()) {
1282+
getLabManager()->DockerDockPoint = dock_map.begin()->second;
1283+
}
1284+
}
1285+
1286+
const char* docker_label = getLabManager()->DockerDockPoint.c_str();
1287+
1288+
if (ImGui::BeginCombo("Docker Dockpoint", docker_label)) {
1289+
if (!dock_map.empty()) {
1290+
for (const auto& [index, name] : dock_map) {
1291+
bool is_selected = (name == getLabManager()->DockerDockPoint);
1292+
if (ImGui::Selectable(name.c_str(), is_selected)) {
1293+
getLabManager()->DockerDockPoint = name;
1294+
}
1295+
if (is_selected)
1296+
ImGui::SetItemDefaultFocus();
1297+
}
1298+
}
1299+
ImGui::EndCombo();
1300+
}
1301+
1302+
// Auto-select first dockpoint if none currently selected
1303+
if (getLabManager()->DockeeDockPoint.empty()) {
1304+
getLabManager()->DockeeDockPoint = dockee_dock_map.begin()->second;
1305+
}
1306+
1307+
const char* dockee_label = getLabManager()->DockeeDockPoint.c_str();
1308+
1309+
if (ImGui::BeginCombo("Dockee Dockpoint", dockee_label)) {
1310+
for (const auto& [index, name] : dockee_dock_map) {
1311+
bool is_selected = (name == getLabManager()->DockeeDockPoint);
1312+
if (ImGui::Selectable(name.c_str(), is_selected)) {
1313+
getLabManager()->DockeeDockPoint = name;
1314+
}
1315+
if (is_selected)
1316+
ImGui::SetItemDefaultFocus();
1317+
}
1318+
ImGui::EndCombo();
1319+
}
1320+
1321+
if (Button("Begin Docking Test")) {
1322+
getLabManager()->beginDockingTest();
1323+
}
1324+
1325+
if (Button("Begin Undocking Test")) {
1326+
getLabManager()->beginUndockingTest();
1327+
}
1328+
}
1329+
1330+
12431331
build_animation_options(shipp, sip);
12441332
}
12451333
}

code/lab/dialogs/lab_ui_helpers.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@
33
#include "cfile/cfile.h"
44
#include "lab/labv2_internal.h"
55

6+
SCP_map<int, SCP_string> get_docking_point_map(int model_index)
7+
{
8+
SCP_map<int, SCP_string> result;
9+
10+
polymodel* pm = model_get(model_index);
11+
if (pm == nullptr || pm->n_docks <= 0)
12+
return result;
13+
14+
for (int i = 0; i < pm->n_docks; ++i) {
15+
const char* name = pm->docking_bays[i].name;
16+
result[i] = (name && *name) ? SCP_string(name) : SCP_string("<unnamed>");
17+
}
18+
19+
return result;
20+
}
21+
622

723
SCP_string get_ship_table_text(ship_info* sip)
824
{

code/lab/dialogs/lab_ui_helpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include "asteroid/asteroid.h"
44
#include "ship/ship.h"
55

6+
SCP_map<int, SCP_string> get_docking_point_map(int model_index);
7+
68
SCP_string get_ship_table_text(ship_info* sip);
79

810
SCP_string get_weapon_table_text(weapon_info* wip);

0 commit comments

Comments
 (0)