Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions code/ai/aicode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,19 @@ void garbage_collect_path_points()

}

void reset_ai_path_points()
{
memset(Path_points, 0, sizeof(Path_points)); // optional: zero out for safety
Ppfp = Path_points;

// Also clear any AI path state
for (int i = 0; i < MAX_SHIPS; ++i) {
Ai_info[i].path_start = -1;
Ai_info[i].path_cur = -1;
Ai_info[i].path_length = 0;
}
}

/**
* Hash two values together, return result.
* Hash function: curval shifted right circular by one, newval xored in.
Expand Down
2 changes: 2 additions & 0 deletions code/ai/aigoals.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ typedef struct ai_goal {

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);

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

typedef flag_def_list_templated<ai_goal_mode> ai_goal_list;

Expand Down
93 changes: 93 additions & 0 deletions code/lab/dialogs/lab_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1233,13 +1233,106 @@ void LabUi::show_object_options() const
if (getLabManager()->isSafeForShips()) {
if (Button("Destroy ship")) {
if (Objects[getLabManager()->CurrentObject].type == OBJ_SHIP) {
// If we have an undocker, delete it before destroying the current ship
getLabManager()->deleteDockerObject();

auto obj = &Objects[getLabManager()->CurrentObject];

obj->flags.remove(Object::Object_Flags::Player_ship);
ship_self_destruct(obj);
}
}

const ship* dockee_shipp = &Ships[Objects[getLabManager()->CurrentObject].instance];
auto dockee_dock_map = get_docking_point_map(Ship_info[dockee_shipp->ship_info_index].model_num);

if (!dockee_dock_map.empty()) {

if (ImGui::BeginCombo("Docker Ship Class", Ship_info[getLabManager()->DockerClass].name)) {
for (size_t i = 0; i < Ship_info.size(); ++i) {
bool is_selected = (static_cast<int>(i) == getLabManager()->DockerClass);
if (ImGui::Selectable(Ship_info[i].name, is_selected)) {
getLabManager()->DockerClass = static_cast<int>(i);
// Load model if needed
auto& dsip = Ship_info[getLabManager()->DockerClass];
if (dsip.model_num < 0) {
dsip.model_num = model_load(dsip.pof_file, &dsip);
}
auto new_dock_map = get_docking_point_map(dsip.model_num);

// Auto-select first available dockpoint (or clear if none)
if (!new_dock_map.empty()) {
getLabManager()->DockerDockPoint = new_dock_map.begin()->second;
} else {
getLabManager()->DockerDockPoint.clear();
}
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}

auto& dsip = Ship_info[getLabManager()->DockerClass];
if (dsip.model_num < 0) {
dsip.model_num = model_load(dsip.pof_file, &dsip);
}
auto dock_map = get_docking_point_map(dsip.model_num);

// Ensure DockerDockPoint is initialized once based on the current DockerClass
if (getLabManager()->DockerDockPoint.empty()) {
if (!dock_map.empty()) {
getLabManager()->DockerDockPoint = dock_map.begin()->second;
}
}

const char* docker_label = getLabManager()->DockerDockPoint.c_str();

if (ImGui::BeginCombo("Docker Dockpoint", docker_label)) {
if (!dock_map.empty()) {
for (const auto& [index, name] : dock_map) {
bool is_selected = (name == getLabManager()->DockerDockPoint);
if (ImGui::Selectable(name.c_str(), is_selected)) {
getLabManager()->DockerDockPoint = name;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
Comment thread
JohnAFernandez marked this conversation as resolved.
}
}
}
ImGui::EndCombo();
}

// Auto-select first dockpoint if none currently selected
if (getLabManager()->DockeeDockPoint.empty()) {
getLabManager()->DockeeDockPoint = dockee_dock_map.begin()->second;
}

const char* dockee_label = getLabManager()->DockeeDockPoint.c_str();

if (ImGui::BeginCombo("Dockee Dockpoint", dockee_label)) {
for (const auto& [index, name] : dockee_dock_map) {
bool is_selected = (name == getLabManager()->DockeeDockPoint);
if (ImGui::Selectable(name.c_str(), is_selected)) {
getLabManager()->DockeeDockPoint = name;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
Comment thread
JohnAFernandez marked this conversation as resolved.
}
}
ImGui::EndCombo();
}

if (Button("Begin Docking Test")) {
getLabManager()->beginDockingTest();
}

if (Button("Begin Undocking Test")) {
getLabManager()->beginUndockingTest();
}
}


build_animation_options(shipp, sip);
}
}
Expand Down
16 changes: 16 additions & 0 deletions code/lab/dialogs/lab_ui_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
#include "cfile/cfile.h"
#include "lab/labv2_internal.h"

SCP_map<int, SCP_string> get_docking_point_map(int model_index)
{
SCP_map<int, SCP_string> result;

polymodel* pm = model_get(model_index);
if (pm == nullptr || pm->n_docks <= 0)
return result;

for (int i = 0; i < pm->n_docks; ++i) {
const char* name = pm->docking_bays[i].name;
result[i] = (name && *name) ? SCP_string(name) : SCP_string("<unnamed " + std::to_string(i) + ">");
}

return result;
}


SCP_string get_ship_table_text(ship_info* sip)
{
Expand Down
2 changes: 2 additions & 0 deletions code/lab/dialogs/lab_ui_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "asteroid/asteroid.h"
#include "ship/ship.h"

SCP_map<int, SCP_string> get_docking_point_map(int model_index);

SCP_string get_ship_table_text(ship_info* sip);

SCP_string get_weapon_table_text(weapon_info* wip);
Expand Down
Loading
Loading