feat: re-added artillery splashdowns

This commit is contained in:
Sara 2024-12-08 17:32:12 +01:00
parent bc7a9ec8ef
commit 9341b09b63
24 changed files with 340 additions and 100 deletions

65
src/artillery_target.cpp Normal file
View file

@ -0,0 +1,65 @@
#include "artillery_target.hpp"
#include "utils/godot_macros.hpp"
#include <godot_cpp/variant/utility_functions.hpp>
void ArtilleryTarget::_bind_methods() {
#define CLASSNAME ArtilleryTarget
GDPROPERTY_HINTED(effect, gd::Variant::OBJECT, gd::PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
GDPROPERTY(spread, gd::Variant::FLOAT);
GDPROPERTY(frequency_min, gd::Variant::FLOAT);
GDPROPERTY(frequency_max, gd::Variant::FLOAT);
}
void ArtilleryTarget::_ready() {
this->timer = memnew(gd::Timer);
this->add_child(this->timer);
this->timer->connect("timeout", callable_mp(this, &ArtilleryTarget::timer_end));
this->start_timer();
}
void ArtilleryTarget::set_effect(gd::Ref<gd::PackedScene> scene) {
this->effect = scene;
}
gd::Ref<gd::PackedScene> ArtilleryTarget::get_effect() const {
return this->effect;
}
void ArtilleryTarget::set_spread(float value) {
this->spread = value;
}
float ArtilleryTarget::get_spread() const {
return this->spread;
}
void ArtilleryTarget::set_frequency_min(float value) {
this->frequency_min = value;
}
float ArtilleryTarget::get_frequency_min() const {
return this->frequency_min;
}
void ArtilleryTarget::set_frequency_max(float value) {
this->frequency_max = value;
}
float ArtilleryTarget::get_frequency_max() const {
return this->frequency_max;
}
void ArtilleryTarget::timer_end() {
this->start_timer();
gd::Node *instance{this->effect->instantiate()};
this->add_child(instance);
if(gd::Node3D *inst3d{gd::Object::cast_to<gd::Node3D>(instance)}) {
double const distance{gd::Math::sqrt(gd::UtilityFunctions::randf_range(0.f, 1.f) * this->spread)};
double const angle{gd::UtilityFunctions::randf_range(0., M_2_PI)};
inst3d->set_global_position(this->get_global_position() + gd::Vector3{1.f, 0.f, 0.f}.rotated({0.f, 1.f, 0.f}, angle) * distance);
}
}
void ArtilleryTarget::start_timer() {
this->timer->start(gd::UtilityFunctions::randf_range(this->frequency_min, this->frequency_max));
}

33
src/artillery_target.hpp Normal file
View file

@ -0,0 +1,33 @@
#ifndef ARTILLERY_TARGET_HPP
#define ARTILLERY_TARGET_HPP
#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/classes/timer.hpp>
#include <godot_cpp/classes/packed_scene.hpp>
namespace gd = godot;
class ArtilleryTarget : public gd::Node3D {
GDCLASS(ArtilleryTarget, gd::Node3D);
static void _bind_methods();
public:
virtual void _ready() override;
void set_effect(gd::Ref<gd::PackedScene> scene);
gd::Ref<gd::PackedScene> get_effect() const;
void set_spread(float value);
float get_spread() const;
void set_frequency_min(float value);
float get_frequency_min() const;
void set_frequency_max(float value);
float get_frequency_max() const;
private:
void timer_end();
void start_timer();
private:
float spread{5.f};
float frequency_min{0.5f};
float frequency_max{2.f};
gd::Ref<gd::PackedScene> effect{};
gd::Timer *timer{nullptr};
};
#endif // !ARTILLERY_TARGET_HPP

View file

@ -0,0 +1,62 @@
#include "camera_effect_source.hpp"
#include "utils/godot_macros.hpp"
#include <godot_cpp/classes/viewport.hpp>
void CameraEffectSource::_bind_methods() {
#define CLASSNAME CameraEffectSource
GDFUNCTION(trigger);
GDPROPERTY(play_on_ready, gd::Variant::BOOL);
GDPROPERTY(falloff, gd::Variant::FLOAT);
GDPROPERTY(intensity, gd::Variant::FLOAT);
GDPROPERTY(time, gd::Variant::FLOAT);
}
void CameraEffectSource::_ready() {
if(this->play_on_ready)
this->trigger();
}
void CameraEffectSource::trigger() {
if(CameraEffects *effects{CameraEffectSource::get_camera()}) {
float const falloff_mod{this->falloff_max_distance == 0.f
? 1.f
: gd::Math::max(0.f, 1.f - effects->get_global_position().distance_to(this->get_global_position()) / this->falloff_max_distance)};
effects->push_effect(this->time, this->intensity * falloff_mod);
}
}
void CameraEffectSource::set_play_on_ready(bool play_on_ready) {
this->play_on_ready = play_on_ready;
}
bool CameraEffectSource::get_play_on_ready() const {
return this->play_on_ready;
}
void CameraEffectSource::set_falloff(float max_distance) {
this->falloff_max_distance = max_distance;
}
float CameraEffectSource::get_falloff() const {
return this->falloff_max_distance;
}
void CameraEffectSource::set_intensity(float intensity) {
this->intensity = intensity;
}
float CameraEffectSource::get_intensity() const {
return this->intensity;
}
void CameraEffectSource::set_time(float time) {
this->time = time;
}
float CameraEffectSource::get_time() const {
return this->time;
}
CameraEffects *CameraEffectSource::get_camera() {
return gd::Object::cast_to<CameraEffects>(this->get_viewport()->get_camera_3d());
}

View file

@ -0,0 +1,32 @@
#ifndef CAMERA_EFFECT_SOURCE_HPP
#define CAMERA_EFFECT_SOURCE_HPP
#include "camera_effects.hpp"
#include <godot_cpp/classes/node3d.hpp>
namespace gd = godot;
class CameraEffectSource : public gd::Node3D {
GDCLASS(CameraEffectSource, gd::Node3D);
static void _bind_methods();
public:
virtual void _ready() override;
void trigger();
void set_play_on_ready(bool play_on_ready);
bool get_play_on_ready() const;
void set_falloff(float max_distance); //!< set to zero to affect camera regardless of distance
float get_falloff() const;
void set_intensity(float intensity);
float get_intensity() const;
void set_time(float time);
float get_time() const;
private:
CameraEffects *get_camera();
private:
bool play_on_ready{false};
float falloff_max_distance{20.f};
float intensity{1.f};
double time{0.5f};
};
#endif // !CAMERA_EFFECT_SOURCE_HPP

40
src/camera_effects.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "camera_effects.hpp"
#include "utils/util_functions.hpp"
#include <godot_cpp/variant/utility_functions.hpp>
void CameraEffects::_bind_methods() {}
void CameraEffects::_ready() {
this->home = this->get_position();
this->target = this->home;
}
void CameraEffects::_process(double delta [[maybe_unused]]) {
this->home = this->get_position();
if(utils::time_seconds() > this->end_time) {
intensity = 0.f;
this->set_position(this->home);
}
if(intensity == 0.f)
return;
gd::Vector3 pos{this->get_position()};
pos = this->target;
this->set_position(this->home + pos);
this->select_target();
}
void CameraEffects::push_effect(float time, float intensity) {
if(intensity > this->intensity) {
this->intensity = intensity;
this->end_time = utils::time_seconds() + time;
}
}
void CameraEffects::select_target() {
float const intensity_mod{this->intensity * 0.01f};
this->target = {
float(gd::UtilityFunctions::randf_range(0.f, 1.f) * -gd::Math::sign(this->target.x) * intensity_mod),
float(gd::UtilityFunctions::randf_range(-1.f, 1.f) * intensity_mod),
0.f
};
}

23
src/camera_effects.hpp Normal file
View file

@ -0,0 +1,23 @@
#ifndef CAMERA_EFFECTS_HPP
#define CAMERA_EFFECTS_HPP
#include <godot_cpp/classes/camera3d.hpp>
#include <godot_cpp/templates/vector.hpp>
namespace gd = godot;
class CameraEffects : public gd::Camera3D {
GDCLASS(CameraEffects, gd::Camera3D);
static void _bind_methods();
public:
virtual void _ready() override;
virtual void _process(double delta) override;
void push_effect(float time, float intensity);
void select_target();
private:
double end_time{0.5f};
float intensity{1.f};
gd::Vector3 target{0.f, 0.f, 0.f};
gd::Vector3 home{0.f, 0.f, 0.f};
};
#endif // !CAMERA_EFFECTS_HPP

View file

@ -9,6 +9,9 @@
#include "player_anim_tree.hpp"
#include "enemy.hpp"
#include "hitscan_muzzle.hpp"
#include "camera_effects.hpp"
#include "camera_effect_source.hpp"
#include "artillery_target.hpp"
using namespace godot;
@ -22,6 +25,9 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level)
GDREGISTER_CLASS(PlayerAnimTree);
GDREGISTER_CLASS(Enemy);
GDREGISTER_CLASS(HitscanMuzzle);
GDREGISTER_RUNTIME_CLASS(CameraEffects);
GDREGISTER_RUNTIME_CLASS(CameraEffectSource);
GDREGISTER_RUNTIME_CLASS(ArtilleryTarget);
}
extern "C"