Skip to content

Commit

Permalink
electrical arc upgrade, stage 2: make arrays dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
Goober5000 committed Sep 21, 2024
1 parent 4b21bd5 commit f41fc22
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 98 deletions.
33 changes: 14 additions & 19 deletions code/debris/debris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ int Debris_num_submodels = 0;

#define DEBRIS_INDEX(dp) (int)(dp-Debris.data())

// Find the first available arc slot.
debris_electrical_arc *debris_find_electrical_arc_slot(debris *db);
// Find the first available arc slot. If none is available, and no_create is false, add one.
debris_electrical_arc *debris_find_or_create_electrical_arc_slot(debris *db, bool no_create);

/**
* Start the sequence of a piece of debris writhing in unholy agony!!!
Expand Down Expand Up @@ -251,22 +251,19 @@ void debris_process_post(object * obj, float frame_time)

if (db->is_hull) {

int n, n_arcs = Random::next(1, 3); // Create 1-3 sparks
int n_arcs = Random::next(1, 3); // Create 1-3 sparks

vec3d v1 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v2 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v3 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v4 = submodel_get_random_point(db->model_num, db->submodel_num);

n = 0;

int lifetime = Random::next(100, 1000);

// Create the spark effects
for (int i=0; i<MAX_DEBRIS_ARCS; ++i) {
auto arc = &db->electrical_arcs[i];
if ( !arc->timestamp.isValid() ) {

for (int n = 0; n < n_arcs; n++) {
auto arc = debris_find_or_create_electrical_arc_slot(db, db->electrical_arcs.size() >= MAX_DEBRIS_ARCS);
if (arc) {
arc->timestamp = _timestamp(lifetime); // live up to a second

switch( n ) {
Expand All @@ -286,10 +283,6 @@ void debris_process_post(object * obj, float frame_time)
default:
UNREACHABLE("Unhandled case %d for electrical arc creation in debris_process_post()!", n);
}

n++;
if ( n == n_arcs )
break; // Don't need to create anymore
}
}

Expand Down Expand Up @@ -582,9 +575,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
db->parent_alt_name = alt_type_index;
db->damage_mult = 1.0f;

for (int i=0; i<MAX_DEBRIS_ARCS; ++i) { // NOLINT
db->electrical_arcs[i].timestamp = TIMESTAMP::invalid();
}
db->electrical_arcs.clear();

if ( db->is_hull ) {
// Percent of debris pieces with arcs controlled via table (default 50%)
Expand Down Expand Up @@ -1238,7 +1229,7 @@ void create_generic_debris(object* ship_objp, vec3d* pos, float min_num_debris,
}
}

debris_electrical_arc *debris_find_electrical_arc_slot(debris *db)
debris_electrical_arc *debris_find_or_create_electrical_arc_slot(debris *db, bool no_create)
{
size_t i = 0;
for (auto& ii : db->electrical_arcs)
Expand All @@ -1248,8 +1239,12 @@ debris_electrical_arc *debris_find_electrical_arc_slot(debris *db)
i++;
}

if (i == MAX_DEBRIS_ARCS)
return nullptr;
if (i == db->electrical_arcs.size())
{
if (no_create)
return nullptr;
db->electrical_arcs.emplace_back();
}

return &db->electrical_arcs[i];
}
4 changes: 2 additions & 2 deletions code/debris/debris.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class object;
struct CFILE;
class model_draw_list;

#define MAX_DEBRIS_ARCS 8 // Must be less than MAX_ARC_EFFECTS in model.h
#define MAX_DEBRIS_ARCS 8

FLAG_LIST(Debris_Flags) {
Used,
Expand Down Expand Up @@ -56,7 +56,7 @@ typedef struct debris {
TIMESTAMP sound_delay; // timestamp to signal when sound should start
fix time_started; // time when debris was created

debris_electrical_arc electrical_arcs[MAX_DEBRIS_ARCS];
SCP_vector<debris_electrical_arc> electrical_arcs;
int arc_frequency; // Starts at 1000, gets bigger

int parent_alt_name;
Expand Down
8 changes: 1 addition & 7 deletions code/model/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,11 @@ struct submodel_instance
vec3d canonical_offset = vmd_zero_vector;
vec3d canonical_prev_offset = vmd_zero_vector;

int num_arcs = 0; // See model_add_arc for more info
model_electrical_arc electrical_arcs[MAX_ARC_EFFECTS];
SCP_vector<model_electrical_arc> electrical_arcs;

//SMI-Specific movement axis. Only valid in MOVEMENT_TYPE_TRIGGERED.
vec3d rotation_axis = vmd_zero_vector;
vec3d translation_axis = vmd_zero_vector;

submodel_instance()
{
memset(electrical_arcs, 0, MAX_ARC_EFFECTS * sizeof(model_electrical_arc));
}
};

#define TM_BASE_TYPE 0 // the standard base map
Expand Down
9 changes: 2 additions & 7 deletions code/model/modelinterp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,20 +785,15 @@ void model_draw_bay_paths_htl(int model_num)
gr_set_cull(cull);
}

static const int MAX_ARC_SEGMENT_POINTS = 50;
int Num_arc_segment_points = 0;
vec3d Arc_segment_points[MAX_ARC_SEGMENT_POINTS];
SCP_vector<vec3d> Arc_segment_points;

void interp_render_arc_segment(const vec3d *v1, const vec3d *v2, int depth )
{
float d = vm_vec_dist_quick( v1, v2 );
const float scaler = 0.30f;

if ( (d < scaler) || (depth > 4) ) {
// the real limit appears to be 33, so we should never hit this unless the code changes
Assert( Num_arc_segment_points < MAX_ARC_SEGMENT_POINTS );

memcpy( &Arc_segment_points[Num_arc_segment_points++], v2, sizeof(vec3d) );
Arc_segment_points.push_back(*v2);
} else {
// divide in half
vec3d tmp;
Expand Down
26 changes: 12 additions & 14 deletions code/model/modelread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5159,7 +5159,7 @@ void model_instance_clear_arcs(polymodel *pm, polymodel_instance *pmi)
Assert(pm->id == pmi->model_num);

for (int i = 0; i < pm->n_models; ++i) {
pmi->submodel[i].num_arcs = 0; // Turn off any electric arcing effects
pmi->submodel[i].electrical_arcs.clear(); // Turn off any electric arcing effects
}
}

Expand All @@ -5179,20 +5179,18 @@ void model_instance_add_arc(polymodel *pm, polymodel_instance *pmi, int sub_mode
if ( sub_model_num >= pm->n_models ) return;
auto smi = &pmi->submodel[sub_model_num];

if ( smi->num_arcs < MAX_ARC_EFFECTS ) {
auto &new_arc = smi->electrical_arcs[smi->num_arcs];
new_arc.type = static_cast<ubyte>(arc_type);
new_arc.endpoint_1 = *v1;
new_arc.endpoint_2 = *v2;

if (arc_type == MARC_TYPE_SHIP || arc_type == MARC_TYPE_SCRIPTED) {
new_arc.primary_color_1 = *primary_color_1;
new_arc.primary_color_2 = *primary_color_2;
new_arc.secondary_color = *secondary_color;
new_arc.width = width;
}
smi->electrical_arcs.emplace_back();
auto &new_arc = smi->electrical_arcs.back();

new_arc.type = static_cast<ubyte>(arc_type);
new_arc.endpoint_1 = *v1;
new_arc.endpoint_2 = *v2;

smi->num_arcs++;
if (arc_type == MARC_TYPE_SHIP || arc_type == MARC_TYPE_SCRIPTED) {
new_arc.primary_color_1 = *primary_color_1;
new_arc.primary_color_2 = *primary_color_2;
new_arc.secondary_color = *secondary_color;
new_arc.width = width;
}
}

Expand Down
31 changes: 12 additions & 19 deletions code/model/modelrender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ extern int Model_polys;
extern int tiling;
extern float model_radius;

extern const int MAX_ARC_SEGMENT_POINTS;
extern int Num_arc_segment_points;
extern vec3d Arc_segment_points[];
extern SCP_vector<vec3d> Arc_segment_points;

extern bool Scene_framebuffer_in_frame;
color Wireframe_color;
Expand Down Expand Up @@ -810,12 +808,9 @@ model_draw_list::~model_draw_list() {

void model_render_add_lightning(model_draw_list *scene, const model_render_params* interp, const polymodel *pm, const submodel_instance *smi )
{
int i;
float width = 0.9f;
color primary, secondary;

Assert( smi->num_arcs > 0 );

if ( interp->get_model_flags() & MR_SHOW_OUTLINE_PRESET ) {
return;
}
Expand All @@ -825,9 +820,7 @@ void model_render_add_lightning(model_draw_list *scene, const model_render_param
return;
}

for ( i = 0; i < smi->num_arcs; i++ ) {
auto &arc = smi->electrical_arcs[i];

for (auto &arc: smi->electrical_arcs) {
// pick a color based upon arc type
switch ( arc.type ) {
// "normal", FreeSpace 1 style arcs
Expand Down Expand Up @@ -1306,7 +1299,7 @@ void model_render_children_buffers(model_draw_list* scene, model_material *rende
}
}

if ( smi != nullptr && smi->num_arcs > 0 ) {
if ( smi != nullptr && !smi->electrical_arcs.empty() ) {
model_render_add_lightning( scene, interp, pm, smi );
}

Expand Down Expand Up @@ -1626,7 +1619,7 @@ void submodel_render_queue(const model_render_params *render_info, model_draw_li
}
}

if ( pmi && pmi->submodel[submodel_num].num_arcs > 0 ) {
if ( pmi && !pmi->submodel[submodel_num].electrical_arcs.empty() ) {
model_render_add_lightning( scene, render_info, pm, &pmi->submodel[submodel_num] );
}

Expand Down Expand Up @@ -2080,8 +2073,8 @@ void model_render_glow_points(const polymodel *pm, const polymodel_instance *pmi
Assert( bank->points != nullptr );
int flick;

if (pmi != nullptr && pmi->submodel[pm->detail[0]].num_arcs > 0) {
flick = static_rand( timestamp() % 20 ) % (pmi->submodel[pm->detail[0]].num_arcs + j); //the more damage, the more arcs, the more likely the lights will fail
if (pmi != nullptr && !pmi->submodel[pm->detail[0]].electrical_arcs.empty()) {
flick = static_rand( timestamp() % 20 ) % (pmi->submodel[pm->detail[0]].electrical_arcs.size() + j); //the more damage, the more arcs, the more likely the lights will fail
} else {
flick = 1;
}
Expand Down Expand Up @@ -2516,21 +2509,21 @@ void model_render_insignias(const insignia_draw_data *insignia_data)

void model_render_arc(const vec3d *v1, const vec3d *v2, const color *primary, const color *secondary, float arc_width)
{
Num_arc_segment_points = 0;
Arc_segment_points.clear();

// need need to add the first point
memcpy( &Arc_segment_points[Num_arc_segment_points++], v1, sizeof(vec3d) );
// need to add the first point
Arc_segment_points.push_back(*v1);

// this should fill in all of the middle, and the last, points
interp_render_arc_segment(v1, v2, 0);

// use primary color for fist pass
Assert( primary );

g3_render_rod(primary, Num_arc_segment_points, Arc_segment_points, arc_width);
g3_render_rod(primary, static_cast<int>(Arc_segment_points.size()), Arc_segment_points.data(), arc_width);

if (secondary) {
g3_render_rod(secondary, Num_arc_segment_points, Arc_segment_points, arc_width * 0.33f);
g3_render_rod(secondary, static_cast<int>(Arc_segment_points.size()), Arc_segment_points.data(), arc_width * 0.33f);
}
}

Expand Down Expand Up @@ -2940,7 +2933,7 @@ void model_render_queue(const model_render_params* interp, model_draw_list* scen
} else {
model_render_buffers(scene, &rendering_material, interp, &pm->submodel[detail_model_num].buffer, pm, detail_model_num, detail_level, tmap_flags);

if ( pmi != nullptr && pmi->submodel[detail_model_num].num_arcs > 0 ) {
if ( pmi != nullptr && !pmi->submodel[detail_model_num].electrical_arcs.empty() ) {
model_render_add_lightning( scene, interp, pm, &pmi->submodel[detail_model_num] );
}
}
Expand Down
10 changes: 5 additions & 5 deletions code/scripting/api/objs/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2694,8 +2694,8 @@ ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number

auto shipp = &Ships[objh->objp()->instance];

// spawn the arc in the first unused slot
auto arc = ship_find_electrical_arc_slot(shipp);
// spawn the arc in the first unused slot, or in a new slot if there are no unused ones
auto arc = ship_find_or_create_electrical_arc_slot(shipp, false);
if (arc)
{
arc->timestamp = _timestamp(fl2i(duration * MILLISECONDS_PER_SECOND));
Expand All @@ -2712,7 +2712,7 @@ ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number

arc->width = width;

return ade_set_args(L, "i", static_cast<int>(arc - shipp->electrical_arcs) + 1); // FS2 -> Lua
return ade_set_args(L, "i", static_cast<int>(arc - shipp->electrical_arcs.data()) + 1); // FS2 -> Lua
}

return ade_set_args(L, "i", 0);
Expand All @@ -2735,7 +2735,7 @@ ADE_FUNC(DeleteElectricArc, l_Ship, "number index",
auto shipp = &Ships[objh->objp()->instance];

index--; // Lua -> FS2
if (index >= 0 && index < MAX_ARC_EFFECTS)
if (SCP_vector_inbounds(shipp->electrical_arcs, index))
{
shipp->electrical_arcs[index].timestamp = TIMESTAMP::invalid();
}
Expand Down Expand Up @@ -2764,7 +2764,7 @@ ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector sec
auto shipp = &Ships[objh->objp()->instance];

index--; // Lua -> FS2
if (index >= 0 && index < MAX_ARC_EFFECTS)
if (SCP_vector_inbounds(shipp->electrical_arcs, index))
{
auto &arc = shipp->electrical_arcs[index];
arc.endpoint_1 = *v1;
Expand Down
14 changes: 8 additions & 6 deletions code/ship/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6866,9 +6866,7 @@ void ship::clear()
for (int i = 0; i < NUM_SUB_EXPL_HANDLES; i++)
sub_expl_sound_handle[i] = sound_handle::invalid();

memset(&electrical_arcs, 0, MAX_ARC_EFFECTS * sizeof(ship_electrical_arc));
for (int i = 0; i < MAX_ARC_EFFECTS; i++)
electrical_arcs[i].timestamp = TIMESTAMP::invalid();
electrical_arcs.clear();
arc_next_time = TIMESTAMP::invalid();

emp_intensity = -1.0f;
Expand Down Expand Up @@ -21399,7 +21397,7 @@ int ship_check_visibility(const ship* viewed, ship* viewer)
return ship_is_visible;
}

ship_electrical_arc *ship_find_electrical_arc_slot(ship *shipp)
ship_electrical_arc *ship_find_or_create_electrical_arc_slot(ship *shipp, bool no_create)
{
size_t i = 0;
for (auto &ii : shipp->electrical_arcs)
Expand All @@ -21409,8 +21407,12 @@ ship_electrical_arc *ship_find_electrical_arc_slot(ship *shipp)
i++;
}

if (i == MAX_ARC_EFFECTS)
return nullptr;
if (i == shipp->electrical_arcs.size())
{
if (no_create)
return nullptr;
shipp->electrical_arcs.emplace_back();
}

return &shipp->electrical_arcs[i];
}
6 changes: 3 additions & 3 deletions code/ship/ship.h
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ class ship
std::array<sound_handle, NUM_SUB_EXPL_HANDLES> sub_expl_sound_handle;

// Stuff for showing electrical arcs on damaged ships
ship_electrical_arc electrical_arcs[MAX_ARC_EFFECTS];
SCP_vector<ship_electrical_arc> electrical_arcs;
TIMESTAMP arc_next_time; // When the next damage/emp arc will be created.
SCP_vector<TIMESTAMP> passive_arc_next_times; // When the next passive ship arc will be created.

Expand Down Expand Up @@ -2126,7 +2126,7 @@ bool ship_secondary_has_ammo(ship_weapon* swp, int bank_index);
// Used to check if one ship can see the other on radar
int ship_check_visibility(const ship* viewed, ship* viewer);

// Find the first available arc slot.
ship_electrical_arc *ship_find_electrical_arc_slot(ship *shipp);
// Find the first available arc slot. If none is available, and no_create is false, add one.
ship_electrical_arc *ship_find_or_create_electrical_arc_slot(ship *shipp, bool no_create);

#endif
Loading

0 comments on commit f41fc22

Please sign in to comment.