Skip to content
Open
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
28 changes: 27 additions & 1 deletion code/model/modelrender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3106,7 +3106,7 @@ void modelinstance_replace_active_texture(polymodel_instance* pmi, const char* o

// renders a model as if in the tech room or briefing UI
// model_type 1 for ship class, 2 for weapon class, 3 for pof
bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int y2, float zoom, bool lighting, int class_idx, const matrix* orient, const SCP_string &pof_filename, float close_zoom, const vec3d *close_pos, const SCP_string& tcolor)
bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int y2, float zoom, bool lighting, int class_idx, const matrix* orient, const SCP_string &pof_filename, float close_zoom, const vec3d *close_pos, const SCP_string& tcolor, const SCP_vector<SCP_string>& destroyed_subsystems)
{

model_render_params render_info;
Expand Down Expand Up @@ -3204,8 +3204,34 @@ bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int

// Create an instance for ships that can be used to clear out destroyed subobjects from rendering
if (model_type == TECH_SHIP) {
auto sip = &Ship_info[class_idx];
auto pm = model_get(model_num);
model_instance = model_create_instance(model_objnum_special::OBJNUM_NONE, model_num);
model_set_up_techroom_instance(&Ship_info[class_idx], model_instance);
model_set_up_techroom_instance(sip, model_instance);

if (!destroyed_subsystems.empty()) {
auto pmi = model_get_instance(model_instance);
flagset<Ship::Subsystem_Flags> empty;

for (int idx = 0; idx < sip->n_subsystems; ++idx) {
auto& subsystem = sip->subsystems[idx];

if (subsystem.subobj_num < 0 || subsystem.subobj_num >= pm->n_models ||
subsystem.model_num != model_num) {
continue;
}

for (auto& destroyed_name : destroyed_subsystems) {
if (!stricmp(subsystem.subobj_name, destroyed_name.c_str()) ||
!stricmp(subsystem.name, destroyed_name.c_str())) {
pmi->submodel[subsystem.subobj_num].blown_off = true;
model_replicate_submodel_instance(pm, pmi, subsystem.subobj_num, empty);
break;
}
}
}
}
}

render_info.set_detail_level_lock(0);
Expand Down
2 changes: 1 addition & 1 deletion code/model/modelrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ bool model_render_check_detail_box(const vec3d* view_pos, const polymodel* pm, i
void model_render_arc(const vec3d* v1, const vec3d* v2, const SCP_vector<vec3d> *persistent_arc_points, const color* primary, const color* secondary, float arc_width, ubyte depth_limit);
void model_render_insignias(const insignia_draw_data* insignia);
void model_render_set_wireframe_color(const color* clr);
bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int y2, float zoom, bool lighting, int class_idx, const matrix* orient, const SCP_string& pof_filename = "", float closeup_zoom = 0, const vec3d* closeup_pos = &vmd_zero_vector, const SCP_string& tcolor = "");
bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int y2, float zoom, bool lighting, int class_idx, const matrix* orient, const SCP_string& pof_filename = "", float closeup_zoom = 0, const vec3d* closeup_pos = &vmd_zero_vector, const SCP_string& tcolor = "", const SCP_vector<SCP_string>& destroyed_subsystems = SCP_vector<SCP_string>());

float convert_distance_and_diameter_to_pixel_size(float distance, float diameter, float field_of_view, int screen_width);

Expand Down
47 changes: 41 additions & 6 deletions code/scripting/api/objs/shipclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "graphics/matrix.h"
#include "missionui/missionscreencommon.h"
#include "scripting/api/objs/weaponclass.h"
#include "scripting/lua/LuaTable.h"
#include "model/modelrender.h"
#include "utils/string_utils.h"

Expand Down Expand Up @@ -1114,7 +1115,7 @@ ADE_FUNC(isInTechroom, l_Shipclass, NULL, "Gets whether or not the ship class is
ADE_FUNC(renderTechModel,
l_Shipclass,
"number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number "
"BankPercent=40, number Zoom=1.3, boolean Lighting=true, teamcolor TeamColor=nil]",
"BankPercent=40, number Zoom=1.3, boolean Lighting=true, teamcolor TeamColor=nil, string[] DestroyedSubsystems=nil]",
"Draws ship model as if in techroom. True for regular lighting, false for flat lighting.",
"boolean",
"Whether ship was rendered")
Expand All @@ -1125,7 +1126,8 @@ ADE_FUNC(renderTechModel,
float zoom = 1.3f;
bool lighting = true;
int tc_idx = -1;
if(!ade_get_args(L, "oiiii|ffffbo", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, &rot_angles.h, &rot_angles.p, &rot_angles.b, &zoom, &lighting, l_TeamColor.Get(&tc_idx)))
auto destroyed_subsystems_table = luacpp::LuaTable::create(L);
if(!ade_get_args(L, "oiiii|ffffbot", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, &rot_angles.h, &rot_angles.p, &rot_angles.b, &zoom, &lighting, l_TeamColor.Get(&tc_idx), &destroyed_subsystems_table))
return ade_set_error(L, "b", false);

if(idx < 0 || idx >= ship_info_size())
Expand Down Expand Up @@ -1158,18 +1160,35 @@ ADE_FUNC(renderTechModel,
}
}

return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, lighting, idx, &orient, tcolor));
SCP_vector<SCP_string> destroyed_subsystems;
if (destroyed_subsystems_table.isValid()) {
for (const auto& item : destroyed_subsystems_table) {
if (!item.second.is(luacpp::ValueType::STRING)) {
LuaError(L, "DestroyedSubsystems must be a table of strings.");
return ade_set_args(L, "b", false);
}

try {
destroyed_subsystems.emplace_back(item.second.getValue<SCP_string>());
} catch (const luacpp::LuaException& /*e*/) {
return ade_set_args(L, "b", false);
}
}
}

return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, lighting, idx, &orient, "", 0, &vmd_zero_vector, tcolor, destroyed_subsystems));
}

// Nuke's alternate tech model rendering function
ADE_FUNC(renderTechModel2, l_Shipclass, "number X1, number Y1, number X2, number Y2, [orientation Orientation=nil, number Zoom=1.3, teamcolor TeamColor=nil]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
ADE_FUNC(renderTechModel2, l_Shipclass, "number X1, number Y1, number X2, number Y2, [orientation Orientation=nil, number Zoom=1.3, teamcolor TeamColor=nil, string[] DestroyedSubsystems=nil]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
{
int x1,y1,x2,y2;
int idx;
float zoom = 1.3f;
matrix_h *mh = nullptr;
int tc_idx = -1;
if(!ade_get_args(L, "oiiiio|fo", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, l_Matrix.GetPtr(&mh), &zoom, l_TeamColor.Get(&tc_idx)))
auto destroyed_subsystems_table = luacpp::LuaTable::create(L);
if(!ade_get_args(L, "oiiiio|fot", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, l_Matrix.GetPtr(&mh), &zoom, l_TeamColor.Get(&tc_idx), &destroyed_subsystems_table))
return ade_set_error(L, "b", false);

if(idx < 0 || idx >= ship_info_size())
Expand All @@ -1191,7 +1210,23 @@ ADE_FUNC(renderTechModel2, l_Shipclass, "number X1, number Y1, number X2, number
}
}

return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, true, idx, orient, tcolor));
SCP_vector<SCP_string> destroyed_subsystems;
if (destroyed_subsystems_table.isValid()) {
for (const auto& item : destroyed_subsystems_table) {
if (!item.second.is(luacpp::ValueType::STRING)) {
LuaError(L, "DestroyedSubsystems must be a table of strings.");
return ade_set_args(L, "b", false);
}

try {
destroyed_subsystems.emplace_back(item.second.getValue<SCP_string>());
} catch (const luacpp::LuaException& /*e*/) {
return ade_set_args(L, "b", false);
}
}
}

return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, true, idx, orient, "", 0, &vmd_zero_vector, tcolor, destroyed_subsystems));
}

ADE_FUNC(renderSelectModel,
Expand Down