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
4 changes: 2 additions & 2 deletions code/ai/aiturret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,7 @@ bool turret_fire_weapon(int weapon_num,
}
//spawn particle effect
auto particleSource = particle::ParticleManager::get()->createSource(wip->muzzle_effect);
particleSource->setHost(make_unique<EffectHostTurret>(&Objects[parent_ship->objnum], turret->system_info->turret_gun_sobj, turret->turret_next_fire_pos));
particleSource->setHost(make_unique<EffectHostTurret>(&Objects[parent_ship->objnum], turret->system_info->turret_gun_sobj, turret->turret_next_fire_pos, false));
particleSource->setTriggerRadius(objp->radius * radius_mult);
particleSource->setTriggerVelocity(vm_vec_mag_quick(&objp->phys_info.vel));
particleSource->finishCreation();
Expand Down Expand Up @@ -2163,7 +2163,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
if (Weapon_info[tsi->weapon_class].muzzle_effect.isValid()) {
//spawn particle effect
auto particleSource = particle::ParticleManager::get()->createSource(Weapon_info[tsi->weapon_class].muzzle_effect);
particleSource->setHost(make_unique<EffectHostTurret>(&Objects[tsi->parent_objnum], tsi->turret->system_info->turret_gun_sobj, tsi->turret->turret_next_fire_pos - 1));
particleSource->setHost(make_unique<EffectHostTurret>(&Objects[tsi->parent_objnum], tsi->turret->system_info->turret_gun_sobj, tsi->turret->turret_next_fire_pos - 1, false));
particleSource->setTriggerRadius(Objects[weapon_objnum].radius);
particleSource->finishCreation();
}
Expand Down
4 changes: 4 additions & 0 deletions code/particle/ParticleSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ void ParticleSource::finishCreation() {
if (Is_standalone)
return;

Assertion(isValid(), "Cannot create a ParticleSource that is not valid!");
if (!isValid())
return;

m_host->setupProcessing();

const auto& effectList = ParticleManager::get()->getEffect(m_effect);
Expand Down
18 changes: 12 additions & 6 deletions code/particle/hosts/EffectHostTurret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
#include "model/model.h"
#include "ship/ship.h"

EffectHostTurret::EffectHostTurret(object* objp, int submodel, int fire_pnt, matrix orientationOverride, bool orientationOverrideRelative) :
EffectHost(orientationOverride, orientationOverrideRelative), m_objnum(OBJ_INDEX(objp)), m_objsig(objp->signature), m_submodel(submodel), m_fire_pnt(fire_pnt) {}
EffectHostTurret::EffectHostTurret(const object* objp, int submodel, int fire_pnt, bool is_fighterbeam, matrix orientationOverride, bool orientationOverrideRelative) :
EffectHost(orientationOverride, orientationOverrideRelative), m_objnum(OBJ_INDEX(objp)), m_objsig(objp ? objp->signature : -1), m_submodel(submodel), m_fire_pnt(fire_pnt), m_is_fighterbeam(is_fighterbeam) {}

std::pair<vec3d, matrix> EffectHostTurret::getPositionAndOrientation(bool relativeToParent, float interp, const std::optional<vec3d>& tabled_offset) const {
ship& shipp = Ships[Objects[m_objnum].instance];
const polymodel* pm = model_get(Ship_info[shipp.ship_info_index].model_num);
const polymodel_instance* pmi = model_get_instance(shipp.model_instance_num);

vec3d gvec, pos;
model_subsystem *tp = ship_get_indexed_subsys(&shipp, pm->submodel[m_submodel].subsys_num)->system_info;
model_subsystem* tp;
if (m_is_fighterbeam) {
tp = &shipp.beam_sys_info;
} else {
auto subsys = ship_get_subsys_for_submodel(&shipp, m_submodel);
Assertion(subsys != nullptr, "EffectHostTurret constructed with missing subsystem!");
tp = subsys->system_info;
}
vec3d* gun_pos = &tp->turret_firing_point[m_fire_pnt % tp->turret_num_firing_points];
const matrix& gun_frame_of_reference = pm->submodel[m_submodel].frame_of_reference;

Expand Down Expand Up @@ -72,6 +79,5 @@ float EffectHostTurret::getHostRadius() const {
}

bool EffectHostTurret::isValid() const {
return m_objnum >= 0 && m_submodel >= 0 && Objects[m_objnum].signature == m_objsig && Objects[m_objnum].type == OBJ_SHIP &&
model_get(Ship_info[Ships[Objects[m_objnum].instance].ship_info_index].model_num)->submodel[m_submodel].subsys_num >= 0;
}
return m_objnum >= 0 && m_submodel >= 0 && Objects[m_objnum].signature == m_objsig && Objects[m_objnum].type == OBJ_SHIP;
}
5 changes: 3 additions & 2 deletions code/particle/hosts/EffectHostTurret.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

class EffectHostTurret : public EffectHost {
int m_objnum, m_objsig, m_submodel, m_fire_pnt;
bool m_is_fighterbeam;

public:
EffectHostTurret(object* objp, int submodel, int fire_pnt, matrix orientationOverride = vmd_identity_matrix, bool orientationOverrideRelative = true);
EffectHostTurret(const object* objp, int submodel, int fire_pnt, bool is_fighterbeam, matrix orientationOverride = vmd_identity_matrix, bool orientationOverrideRelative = true);

std::pair<vec3d, matrix> getPositionAndOrientation(bool relativeToParent, float interp, const std::optional<vec3d>& tabled_offset) const override;

Expand All @@ -18,4 +19,4 @@ class EffectHostTurret : public EffectHost {
float getHostRadius() const override;

bool isValid() const override;
};
};
12 changes: 11 additions & 1 deletion code/scripting/api/objs/particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "model.h"
#include "particle/ParticleManager.h"
#include "particle/ParticleEffect.h"
#include "ship/ship.h"

namespace scripting {
namespace api {
Expand Down Expand Up @@ -397,11 +398,20 @@ ADE_FUNC(createOnTurret, l_ParticleSource, "object object, submodel submodel, nu
if (!(subobjh.isValid() && objh.isValid()))
return ade_set_args(L, "b", false);

if (objh.objp()->type != OBJ_SHIP)
return ade_set_args(L, "b", false);

// this submodel must be a turret
auto shipp = &Ships[objh.objp()->instance];
auto subsys = ship_get_subsys_for_submodel(shipp, subobjh.GetSubmodelIndex());
if (subsys == nullptr || subsys->system_info->type != SUBSYSTEM_TURRET)
return ade_set_args(L, "b", false);

particle::ParticleSource* psp = ps.Get();
if (psp == nullptr)
return ade_set_args(L, "b", false);

psp->setHost(std::make_unique<EffectHostTurret>(objh.objp(), subobjh.GetSubmodelIndex(), firepoint, *orientationOverride.GetMatrix(), orientationOverrideRelative));
psp->setHost(std::make_unique<EffectHostTurret>(objh.objp(), subobjh.GetSubmodelIndex(), firepoint, false, *orientationOverride.GetMatrix(), orientationOverrideRelative));
psp->finishCreation();

return ade_set_args(L, "b", true);
Expand Down
20 changes: 9 additions & 11 deletions code/ship/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21941,20 +21941,18 @@ void toggle_ignore_list_flag(Ship::Ship_Flags flag) {

ship_subsys* ship_get_subsys_for_submodel(ship* shipp, int submodel)
{
ship_subsys* subsys;

if (submodel == -1) {
// no submodel
if (submodel == -1)
return nullptr;
}

for (subsys = GET_FIRST(&shipp->subsys_list); subsys != END_OF_LIST(&shipp->subsys_list);
subsys = GET_NEXT(subsys)) {
if (subsys->system_info->subobj_num == submodel) {
return subsys;
}
}
auto pm = model_get(Ship_info[shipp->ship_info_index].model_num);
Assertion(submodel >= 0 && submodel < pm->n_models, "Ship %s submodel index %d is out of range!", shipp->ship_name, submodel);

return nullptr;
// no associated subsystem
if (pm->submodel[submodel].subsys_num == -1)
return nullptr;

return ship_get_indexed_subsys(shipp, pm->submodel[submodel].subsys_num);
}

/**
Expand Down
9 changes: 8 additions & 1 deletion code/weapon/beam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,14 @@ int beam_fire(beam_fire_info *fire_info)
host = std::make_unique<EffectHostObject>(new_item->objp, local_pos, orient);
}
else {
host = std::make_unique<EffectHostTurret>(new_item->objp, new_item->subsys->system_info->turret_gun_sobj, new_item->firingpoint);
bool is_fighterbeam = false;
if (new_item->objp->type == OBJ_SHIP) {
auto shipp = &Ships[new_item->objp->instance];
if (new_item->subsys == &shipp->fighter_beam_turret_data) {
is_fighterbeam = true;
}
}
host = std::make_unique<EffectHostTurret>(new_item->objp, new_item->subsys->system_info->turret_gun_sobj, new_item->firingpoint, is_fighterbeam);
}

source->setHost(std::move(host));
Expand Down