Skip to content

Commit 9e618f6

Browse files
authored
Particle effect hooks for subsystem destruction (scp-fs2open#6937)
* add particle hook * partial bugfixing * bugfixing * appeasement * syntax fix
1 parent 43e85dd commit 9e618f6

File tree

7 files changed

+68
-15
lines changed

7 files changed

+68
-15
lines changed

code/model/model.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ class model_subsystem { /* contains rotation rate info */
294294

295295
float density;
296296

297+
particle::ParticleEffectHandle death_effect;
297298
particle::ParticleEffectHandle debris_flame_particles;
298299
particle::ParticleEffectHandle shrapnel_flame_particles;
299300

code/particle/ParticleSource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ bool ParticleSource::process() {
8585
}
8686

8787
void ParticleSource::setNormal(const vec3d& normal) {
88+
Assertion(vm_vec_is_normalized(&normal), "Particle source normal must be normalized!");
8889
m_normal = normal;
8990
}
9091

code/ship/ship.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,8 @@ void ship_info::clone(const ship_info& other)
13521352
ship_passive_arcs = other.ship_passive_arcs;
13531353

13541354
glowpoint_bank_override_map = other.glowpoint_bank_override_map;
1355+
1356+
default_subsys_death_effect = other.default_subsys_death_effect;
13551357
}
13561358

13571359
void ship_info::move(ship_info&& other)
@@ -1698,6 +1700,8 @@ void ship_info::move(ship_info&& other)
16981700

16991701
animations = std::move(other.animations);
17001702
cockpit_animations = std::move(other.cockpit_animations);
1703+
1704+
default_subsys_death_effect = other.default_subsys_death_effect;
17011705
}
17021706

17031707
ship_info &ship_info::operator= (ship_info&& other) noexcept
@@ -2091,6 +2095,8 @@ ship_info::ship_info()
20912095
glowpoint_bank_override_map.clear();
20922096

20932097
ship_passive_arcs.clear();
2098+
2099+
default_subsys_death_effect = particle::ParticleEffectHandle::invalid();
20942100
}
20952101

20962102
ship_info::~ship_info()
@@ -5488,6 +5494,10 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
54885494
required_string("$end_custom_strings");
54895495
}
54905496

5497+
if (optional_string("$Default Subsystem Death Effect:")) {
5498+
sip->default_subsys_death_effect = particle::util::parseEffect(sip->name);
5499+
}
5500+
54915501
if(optional_string("$Default Subsystem Debris Flame Effect:"))
54925502
{
54935503
sip->default_subsys_debris_flame_particles = particle::util::parseEffect(sip->name);
@@ -5595,8 +5605,11 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
55955605
sp->turret_max_bomb_ownage = -1;
55965606
sp->turret_max_target_ownage = -1;
55975607
sp->density = 1.0f;
5608+
5609+
sp->death_effect = particle::ParticleEffectHandle::invalid();
55985610
sp->debris_flame_particles = particle::ParticleEffectHandle::invalid();
55995611
sp->shrapnel_flame_particles = particle::ParticleEffectHandle::invalid();
5612+
56005613
}
56015614
sfo_return = stuff_float_optional(&percentage_of_hits);
56025615
if(sfo_return==2)
@@ -5783,6 +5796,10 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
57835796
}
57845797
}
57855798

5799+
if (optional_string("$Subsystem Death Effect:")) {
5800+
sp->death_effect = particle::util::parseEffect(sip->name);
5801+
}
5802+
57865803
if (optional_string("$Debris Density:")) {
57875804
stuff_float(&sp->density);
57885805
}

code/ship/ship.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,7 @@ class ship_info
12621262
// subsystem information
12631263
int n_subsystems; // this number comes from ships.tbl
12641264
model_subsystem *subsystems; // see model.h for structure definition
1265+
particle::ParticleEffectHandle default_subsys_death_effect;
12651266

12661267
// Energy Transfer System fields
12671268
float power_output; // power output of ships reactor (EU/s)

code/ship/shipfx.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void model_get_rotating_submodel_axis(vec3d *model_axis, vec3d *world_axis, cons
9090
*
9191
* DKA: 5/26/99 make velocity of debris scale according to size of debris subobject (at least for large subobjects)
9292
*/
93-
static void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, const ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, float exp_mag)
93+
static void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, const ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, float exp_mag, bool no_fireballs = false)
9494
{
9595
// initializations
9696
ship *shipp = &Ships[ship_objp->instance];
@@ -146,8 +146,11 @@ static void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, const s
146146
if(fireball_type < 0) {
147147
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
148148
}
149-
// create fireball here.
150-
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), pm->submodel[live_debris_submodel].rad);
149+
150+
if (!no_fireballs) {
151+
// create fireball here.
152+
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), pm->submodel[live_debris_submodel].rad);
153+
}
151154

152155
// create debris
153156
live_debris_obj = debris_create(ship_objp, pm->id, live_debris_submodel, &end_world_pos, exp_center, 1, exp_mag, subsys);
@@ -269,7 +272,7 @@ static void shipfx_maybe_create_live_debris_at_ship_death( object *ship_objp )
269272
}
270273
}
271274

272-
void shipfx_blow_off_subsystem(object *ship_objp, ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, bool no_explosion)
275+
void shipfx_blow_off_subsystem(object *ship_objp, ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, bool no_explosion, bool no_fireballs)
273276
{
274277
vec3d subobj_pos;
275278

@@ -286,14 +289,16 @@ void shipfx_blow_off_subsystem(object *ship_objp, ship *ship_p, const ship_subsy
286289

287290
// create live debris objects, if any
288291
// TODO: some MULTIPLAYER implcations here!!
289-
shipfx_subsystem_maybe_create_live_debris(ship_objp, ship_p, subsys, exp_center, 1.0f);
292+
shipfx_subsystem_maybe_create_live_debris(ship_objp, ship_p, subsys, exp_center, 1.0f, no_fireballs);
290293

291-
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
292-
if(fireball_type < 0) {
293-
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
294+
if (!no_fireballs) {
295+
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
296+
if(fireball_type < 0) {
297+
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
298+
}
299+
// create first fireball
300+
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), psub->radius );
294301
}
295-
// create first fireball
296-
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), psub->radius );
297302
}
298303
}
299304

code/ship/shipfx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct matrix;
3232
void shipfx_emit_spark( int n, int sn );
3333

3434
// Does the special effects to blow a subsystem off a ship
35-
extern void shipfx_blow_off_subsystem(object *ship_obj, ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, bool no_explosion = false);
35+
extern void shipfx_blow_off_subsystem(object *ship_obj, ship *ship_p, const ship_subsys *subsys, const vec3d *exp_center, bool no_explosion = false, bool no_fireballs = false);
3636

3737
// Creates "ndebris" pieces of debris on random verts of the "submodel" in the
3838
// ship's model.

code/ship/shiphit.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,34 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, const vec3d*
157157

158158
// create fireballs when subsys destroy for large ships.
159159
if (!(subsys->flags[Ship::Subsystem_Flags::Vanished, Ship::Subsystem_Flags::No_disappear]) && !no_explosion) {
160-
if (ship_objp->radius > 100.0f) {
160+
vec3d center_to_subsys;
161+
vm_vec_sub(&center_to_subsys, &g_subobj_pos, &ship_objp->pos);
162+
163+
particle::ParticleEffectHandle death_effect;
164+
165+
if (psub->death_effect.isValid()) {
166+
death_effect = psub->death_effect;
167+
} else {
168+
death_effect = sip->default_subsys_death_effect;
169+
}
170+
171+
if (death_effect.isValid()) {
172+
vec3d subsys_local_pos;
173+
if (psub->subobj_num >= 0) {
174+
// the vmd_zero_vector here should probably be psub->pnt instead, but this matches the behavior of get_subsystem_world_pos
175+
model_instance_local_to_global_point(&subsys_local_pos, &vmd_zero_vector, ship_p->model_instance_num, psub->subobj_num);
176+
} else {
177+
subsys_local_pos = psub->pnt;
178+
}
179+
vec3d normalized_center_to_subsys = center_to_subsys;
180+
vm_vec_normalize(&normalized_center_to_subsys);
181+
// spawn particle effect
182+
auto source = particle::ParticleManager::get()->createSource(death_effect);
183+
source->setHost(make_unique<EffectHostObject>(ship_objp, subsys_local_pos, vmd_identity_matrix));
184+
source->setTriggerRadius(psub->radius);
185+
source->setNormal(normalized_center_to_subsys);
186+
source->finishCreation();
187+
} else if (ship_objp->radius > 100.0f) {
161188
// number of fireballs determined by radius of subsys
162189
int num_fireballs;
163190
if ( psub->radius < 3 ) {
@@ -166,8 +193,7 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, const vec3d*
166193
num_fireballs = 5;
167194
}
168195

169-
vec3d temp_vec, center_to_subsys, rand_vec;
170-
vm_vec_sub(&center_to_subsys, &g_subobj_pos, &ship_objp->pos);
196+
vec3d temp_vec, rand_vec;
171197
for (i=0; i<num_fireballs; i++) {
172198
if (i==0) {
173199
// make first fireball at hitpos
@@ -308,9 +334,11 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, const vec3d*
308334
));
309335
}
310336

337+
bool no_fireballs = psub->death_effect.isValid() || sip->default_subsys_death_effect.isValid();
338+
311339
if (!(subsys->flags[Ship::Subsystem_Flags::No_disappear])) {
312340
if (psub->subobj_num > -1) {
313-
shipfx_blow_off_subsystem(ship_objp, ship_p, subsys, &g_subobj_pos, no_explosion);
341+
shipfx_blow_off_subsystem(ship_objp, ship_p, subsys, &g_subobj_pos, no_explosion, no_fireballs);
314342
subsys->submodel_instance_1->blown_off = true;
315343
}
316344

0 commit comments

Comments
 (0)