mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
Particle Curves with access to host object & ship properties (#7047)
* Add parent / host input curves * reorder some includes to allow particles access to ship.h * Allow modular_curves to deal with functions returning optionals * Add convenience function to return an optional from an objp and an instance type * Add a bunch of particle curve inputs * Fix internal linkage warning * Add hitpoint and shield fraction (albeit limited to ships)
This commit is contained in:
1 parent
db4f9e4370
commit
3c939f5cc4
11 files changed
+114
-23
No files matched your search
@@ -32,6 +32,7 @@
|
||||
#include "object/objcollide.h"
|
||||
#include "object/object.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "scripting/global_hooks.h"
|
||||
#include "particle/hosts/EffectHostVector.h"
|
||||
#include "render/3d.h"
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ class object;
|
||||
#define INTIAL_ENGINE_RECHARGE_INDEX 4 // default engine charge rate (index in Energy_levels[])
|
||||
|
||||
#define NUM_ENERGY_LEVELS 13
|
||||
#define MAX_ENERGY_INDEX (NUM_ENERGY_LEVELS - 1)
|
||||
inline constexpr int MAX_ENERGY_INDEX = (NUM_ENERGY_LEVELS - 1);
|
||||
|
||||
#define AI_MODIFY_ETS_INTERVAL 500 // time between ets modifications for ai's (in milliseconds)
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
#include "model/model_flags.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/ship_flags.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "particle/particle.h"
|
||||
|
||||
class object;
|
||||
class ship_info;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "asteroid/asteroid.h"
|
||||
#include "debris/debris.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
template<int type>
|
||||
inline auto obj_get_instance_maybe(const object* objp) {
|
||||
if constexpr(type == OBJ_SHIP)
|
||||
return objp->type == type ? std::optional(&Ships[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_WEAPON)
|
||||
return objp->type == type ? std::optional(&Weapons[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_FIREBALL)
|
||||
return objp->type == type ? std::optional(&Fireballs[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_DEBRIS)
|
||||
return objp->type == type ? std::optional(&Debris[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_WING)
|
||||
return objp->type == type ? std::optional(&Wings[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_ASTEROID)
|
||||
return objp->type == type ? std::optional(&Asteroids[objp->instance]) : std::nullopt;
|
||||
else if constexpr(type == OBJ_BEAM)
|
||||
return objp->type == type ? std::optional(&Beams[objp->instance]) : std::nullopt;
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -11,6 +11,11 @@
|
||||
#include "utils/modular_curves.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
#include "object/objectshield.h"
|
||||
#include "ship/ship.h"
|
||||
#include "object/object_instance.h"
|
||||
#include "hud/hudets.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
class EffectHost;
|
||||
@@ -261,7 +266,6 @@ public:
|
||||
std::pair {"Trigger Velocity", modular_curves_submember_input<&ParticleSource::m_triggerVelocity>{}},
|
||||
std::pair {"Host Radius", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getHostRadius>{}},
|
||||
std::pair {"Host Velocity", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getVelocityMagnitude>{}},
|
||||
//TODO Long term, this should have access to a lot of interesting host properties, especially also those that change during gameplay like current hitpoints
|
||||
std::pair {"Effects Running", modular_curves_math_input<
|
||||
modular_curves_submember_input<&ParticleSource::m_effect_is_running, &decltype(ParticleSource::m_effect_is_running)::count>,
|
||||
modular_curves_submember_input<&ParticleSource::getEffect, &SCP_vector<ParticleEffect>::size>,
|
||||
@@ -274,7 +278,25 @@ public:
|
||||
std::pair {"Nebula Usage Score", modular_curves_math_input<
|
||||
modular_curves_global_submember_input<get_particle_count>,
|
||||
modular_curves_global_submember_input<Detail, &detail_levels::nebula_detail>,
|
||||
ModularCurvesMathOperators::division>{}})
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Object Hitpoints", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &object::hull_strength>{}},
|
||||
std::pair {"Host Ship Hitpoints Fraction", modular_curves_math_input<
|
||||
modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &object::hull_strength>,
|
||||
modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::ship_max_hull_strength>,
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Object Shield", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &shield_get_strength>{}},
|
||||
std::pair {"Host Ship Shield Fraction", modular_curves_math_input<
|
||||
modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &shield_get_strength>,
|
||||
modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::ship_max_shield_strength>,
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Ship AB Fuel Left", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::afterburner_fuel>{}},
|
||||
std::pair {"Host Ship Countermeasures Left", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::cmeasure_count>{}},
|
||||
std::pair {"Host Ship Weapon Energy Left", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::weapon_energy>{}},
|
||||
std::pair {"Host Ship ETS Engines", modular_curves_math_input<modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::engine_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Ship ETS Shields", modular_curves_math_input<modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::shield_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Ship ETS Weapons", modular_curves_math_input<modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::weapon_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Host Ship EMP Intensity", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::emp_intensity>{}},
|
||||
std::pair {"Host Ship Time Until Explosion", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::final_death_time, static_cast<int (*)(int)>(×tamp_until)>{}})
|
||||
.derive_modular_curves_input_only_subset<size_t>( //Effect Number
|
||||
std::pair {"Spawntime Left", modular_curves_functional_full_input<&ParticleSource::getEffectRemainingTime>{}},
|
||||
std::pair {"Time Running", modular_curves_functional_full_input<&ParticleSource::getEffectRunningTime>{}})
|
||||
@@ -293,7 +315,7 @@ public:
|
||||
std::pair {"Radius Mult", ParticleLifetimeCurvesOutput::RADIUS_MULT}, // Modern Naming Alias
|
||||
std::pair {"Velocity Mult", ParticleLifetimeCurvesOutput::VELOCITY_MULT}, // Modern Naming Alias
|
||||
std::pair {"Length Mult", ParticleLifetimeCurvesOutput::LENGTH_MULT},
|
||||
std::pair {"Anim State Mult", ParticleLifetimeCurvesOutput::ANIM_STATE},
|
||||
std::pair {"Anim State", ParticleLifetimeCurvesOutput::ANIM_STATE},
|
||||
std::pair {"Light Radius Mult", ParticleLifetimeCurvesOutput::LIGHT_RADIUS_MULT},
|
||||
std::pair {"Light Source Radius Mult", ParticleLifetimeCurvesOutput::LIGHT_SOURCE_RADIUS_MULT},
|
||||
std::pair {"Light Intensity Mult", ParticleLifetimeCurvesOutput::LIGHT_INTENSITY_MULT},
|
||||
@@ -311,7 +333,25 @@ public:
|
||||
modular_curves_submember_input<&particle::max_life>,
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Radius", modular_curves_submember_input<&particle::radius>{}},
|
||||
std::pair {"Velocity", modular_curves_submember_input<&particle::velocity, &vm_vec_mag_quick>{}})
|
||||
std::pair {"Velocity", modular_curves_submember_input<&particle::velocity, &vm_vec_mag_quick>{}},
|
||||
std::pair {"Parent Object Hitpoints", modular_curves_submember_input<&particle::attached_objnum, &Objects, &object::hull_strength>{}},
|
||||
std::pair {"Parent Ship Hitpoints Fraction", modular_curves_math_input<
|
||||
modular_curves_submember_input<&particle::attached_objnum, &Objects, &object::hull_strength>,
|
||||
modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::ship_max_hull_strength>,
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Parent Object Shield", modular_curves_submember_input<&particle::attached_objnum, &Objects, &shield_get_strength>{}},
|
||||
std::pair {"Parent Ship Shield Fraction", modular_curves_math_input<
|
||||
modular_curves_submember_input<&particle::attached_objnum, &Objects, &shield_get_strength>,
|
||||
modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::ship_max_shield_strength>,
|
||||
ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Parent Ship AB Fuel Left", modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::afterburner_fuel>{}},
|
||||
std::pair {"Parent Ship Countermeasures Left", modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::cmeasure_count>{}},
|
||||
std::pair {"Parent Ship Weapon Energy Left", modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::weapon_energy>{}},
|
||||
std::pair {"Parent Ship ETS Engines", modular_curves_math_input<modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::engine_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Parent Ship ETS Shields", modular_curves_math_input<modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::shield_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Parent Ship ETS Weapons", modular_curves_math_input<modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::weapon_recharge_index>, modular_curves_global_submember_input<MAX_ENERGY_INDEX>, ModularCurvesMathOperators::division>{}},
|
||||
std::pair {"Parent Ship EMP Intensity", modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::emp_intensity>{}},
|
||||
std::pair {"Parent Ship Time Until Explosion", modular_curves_submember_input<&particle::attached_objnum, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::final_death_time, static_cast<int (*)(int)>(×tamp_until)>{}})
|
||||
.derive_modular_curves_input_only_subset<float>(
|
||||
std::pair {"Post-Curves Velocity", modular_curves_self_input{}}
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "utils/id.h"
|
||||
|
||||
#include "particle/hosts/EffectHostBeam.h"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <math/bitarray.h>
|
||||
#include "freespace.h"
|
||||
#include "particle/ParticleSource.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
namespace particle {
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "particle/particle.h"
|
||||
#include "particle/ParticleManager.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "debugconsole/console.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
@@ -1034,6 +1034,7 @@ add_file_folder("Object"
|
||||
object/waypoint.cpp
|
||||
object/waypoint.h
|
||||
object/object_flags.h
|
||||
object/object_instance.h
|
||||
)
|
||||
|
||||
# Observer files
|
||||
|
||||
+33
-15
@@ -83,20 +83,34 @@ struct modular_curves_submember_input {
|
||||
const auto& current_access = grab_part<input_type, grabber>(input.get());
|
||||
//If the current grabber isn't guaranteed to succeed, check for completion first
|
||||
if constexpr (is_optional_v<std::decay_t<decltype(current_access)>>) {
|
||||
using lower_return_type = decltype(grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access));
|
||||
using return_type = typename std::conditional_t<is_optional_v<std::decay_t<lower_return_type>>, lower_return_type, std::optional<lower_return_type>>;
|
||||
//If we're already nullopt (i.e. this array access failed) return early
|
||||
if (current_access.has_value()) {
|
||||
//Now, it's possible that lower acceses _also_ produce optionals. In this case, we need to forward the lower result, not re-wrap it.
|
||||
if constexpr (is_optional_v<std::decay_t<lower_return_type>>) {
|
||||
return grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access);
|
||||
}
|
||||
else{
|
||||
return return_type(grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access));
|
||||
}
|
||||
if constexpr (is_instance_of_v<std::decay_t<decltype(*current_access)>, std::reference_wrapper>) {
|
||||
using lower_return_type = decltype(grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access));
|
||||
using return_type = typename std::conditional_t<is_optional_v<std::decay_t<lower_return_type>>, lower_return_type, std::optional<lower_return_type>>;
|
||||
//If we're already nullopt (i.e. this array access failed) return early
|
||||
if (current_access.has_value()) {
|
||||
//Now, it's possible that lower acceses _also_ produce optionals. In this case, we need to forward the lower result, not re-wrap it.
|
||||
if constexpr (is_optional_v<std::decay_t<lower_return_type>>) {
|
||||
return grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access);
|
||||
} else {
|
||||
return return_type(grab_internal<std::decay_t<decltype((*current_access).get())>, other_grabbers...>(*current_access));
|
||||
}
|
||||
} else
|
||||
return return_type(std::nullopt);
|
||||
}
|
||||
else {
|
||||
using lower_return_type = decltype(grab_internal<std::decay_t<decltype(*current_access)>, other_grabbers...>(*current_access));
|
||||
using return_type = typename std::conditional_t<is_optional_v<std::decay_t<lower_return_type>>, lower_return_type, std::optional<lower_return_type>>;
|
||||
//If we're already nullopt (i.e. this array access failed) return early
|
||||
if (current_access.has_value()) {
|
||||
//Now, it's possible that lower acceses _also_ produce optionals. In this case, we need to forward the lower result, not re-wrap it.
|
||||
if constexpr (is_optional_v<std::decay_t<lower_return_type>>) {
|
||||
return grab_internal<std::decay_t<decltype(*current_access)>, other_grabbers...>(*current_access);
|
||||
} else {
|
||||
return return_type(grab_internal<std::decay_t<decltype(*current_access)>, other_grabbers...>(*current_access));
|
||||
}
|
||||
} else
|
||||
return return_type(std::nullopt);
|
||||
}
|
||||
else
|
||||
return return_type(std::nullopt);
|
||||
}
|
||||
//Otherwise just send it on to the next grabber
|
||||
else if constexpr (is_instance_of_v<std::decay_t<decltype(current_access)>, std::reference_wrapper>) {
|
||||
@@ -136,8 +150,12 @@ struct modular_curves_submember_input {
|
||||
static inline float grab(const input_type& input) {
|
||||
const auto& result = grab_internal<std::decay_t<decltype(grab_from_tuple<tuple_idx, input_type>(input).get())>, grabbers...>(grab_from_tuple<tuple_idx, input_type>(input));
|
||||
if constexpr (is_optional_v<typename std::decay_t<decltype(result)>>) {
|
||||
if (result.has_value())
|
||||
return number_to_float(result->get());
|
||||
if (result.has_value()) {
|
||||
if constexpr (is_instance_of_v<std::decay_t<decltype(*result)>, std::reference_wrapper>)
|
||||
return number_to_float(result->get());
|
||||
else
|
||||
return number_to_float(*result);
|
||||
}
|
||||
else
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "object/object.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "particle/particle.h"
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "weapon/muzzleflash.h"
|
||||
#include "model/modelrender.h"
|
||||
|
||||
|
||||
Reference in new issue
Block a user