Compare commits

..

No commits in common. "c4bd5edb540a0bc4991a5ea1cc865a1a73f500e6" and "6153e73492ee9e03e09617d966267a348914b49f" have entirely different histories.

21 changed files with 239 additions and 372 deletions

3
.gitignore vendored
View file

@ -22,6 +22,3 @@ build.zip
wave-survival-fps.kdev4
__pycache__
modules/wave_survival/__pycache__
# blender auto backups
*.blend1

2
engine

@ -1 +1 @@
Subproject commit 084d5d407e62efcd5be9de44148c5dedce3b9386
Subproject commit c6d130abd9188f313e6701d01a0ddd6ea32166a0

View file

@ -4,7 +4,7 @@ BUILD_NAME := "wave_survival"
build: format
# Compiling Editor
cd engine/ && scons target=editor symbols=yes optimization=debug dev_build=yes linker=mold use_llvm=yes custom_modules="../modules" compiledb=yes
cd engine/ && scons target=editor symbols=yes optimization=debug dev_build=yes linker=mold use_llvm=yes custom_modules="../modules"
run: build
# Running Editor

View file

@ -33,11 +33,9 @@ void DamageBox::_notification(int what) {
default:
return;
case NOTIFICATION_ENTER_TREE:
if (!is_ready()) {
connect("body_entered", callable_mp(this, &self_type::on_body_entered));
connect("area_entered", callable_mp(this, &self_type::on_body_entered));
set_monitoring(false);
}
return;
}
}

View file

@ -1,26 +0,0 @@
#include "enemy_rifleman.h"
void EnemyRifleman::_bind_methods() {
}
void EnemyRifleman::on_child_entered() {
}
void EnemyRifleman::ready() {
}
void EnemyRifleman::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_ENTER_TREE:
enter_tree();
return;
case NOTIFICATION_READY:
ready();
return;
}
}

View file

@ -2,55 +2,10 @@
#define ENEMY_RIFLEMAN_H
#include "wave_survival/enemy_body.h"
#include "wave_survival/state.h"
class AnimationPlayer;
class NavigationAgent3D;
class EnemyRifleman : public EnemyBody {
GDCLASS(EnemyRifleman, EnemyBody);
static void _bind_methods();
void on_child_entered();
void enter_tree();
void ready();
protected:
void _notification(int what);
};
/* ============================== STATES ============================== */
class RiflemanState : public State {
GDCLASS(RiflemanState, State);
static void _bind_methods();
public:
virtual void set_target(Node *target) override;
EnemyRifleman *get_target() const;
NpcUnit *get_unit() const;
NavigationAgent3D *get_agent() const;
AnimationPlayer *get_anim() const;
private:
EnemyRifleman *target{ nullptr };
};
class RiflemanPatrolState : public RiflemanState {
GDCLASS(RiflemanPatrolState, RiflemanState);
static void _bind_methods();
public:
virtual void enter_state() override;
virtual void process(double delta) override;
};
class RiflemanSeekState : public RiflemanState {
GDCLASS(RiflemanSeekState, RiflemanState);
static void _bind_methods();
};
class RiflemanFireState : public RiflemanState {
GDCLASS(RiflemanFireState, RiflemanState);
static void _bind_methods();
};
#endif // !ENEMY_RIFLEMAN_H

View file

@ -33,9 +33,7 @@ void EnemyWretched::_notification(int what) {
default:
return;
case NOTIFICATION_ENTER_TREE:
if (!is_ready()) {
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
}
return;
case NOTIFICATION_READY:
ready();

View file

@ -19,15 +19,11 @@ void EnemyBody::on_child_added(Node *node) {
void EnemyBody::ready() {
this->fsm = cast_to<StateMachine>(get_node(NodePath("%StateMachine")));
this->nav = cast_to<NavigationAgent3D>(get_node(NodePath("%NavigationAgent3D")));
this->health = cast_to<HealthStatus>(get_node(NodePath("%HealthStatus")));
}
void EnemyBody::physics_process(double delta) {
GETSET(velocity, {
velocity = Vector3{ this->movement_direction.x * this->movement_speed, velocity.y, this->movement_direction.y * this->movement_speed } + (velocity * delta);
if (!is_on_floor() && this->health->get_health() > 0) {
velocity += get_gravity() * delta;
}
});
if (!this->movement_direction.is_zero_approx()) {
look_at(get_global_position() + Vector3{ this->movement_direction.x, 0.f, this->movement_direction.y });

View file

@ -3,7 +3,7 @@
#include "core/io/resource.h"
#include "core/templates/hash_map.h"
#include "scene/3d/marker_3d.h"
#include "scene/3d/node_3d.h"
class MapRegion;
class PatrolPath;
@ -19,8 +19,8 @@ public:
HashMap<int, Ref<PackedScene>> difficulty_spawns{};
};
class EnemySpawner : public Marker3D {
GDCLASS(EnemySpawner, Marker3D);
class EnemySpawner : public Node3D {
GDCLASS(EnemySpawner, Node3D);
static void _bind_methods();
void on_phase_change(bool hunt);
void ready();

View file

@ -1,5 +1,4 @@
#include "health_status.h"
#include "core/config/engine.h"
#include "macros.h"
String HealthStatus::sig_death{ "death" };

View file

@ -11,28 +11,18 @@ void NpcUnit::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, region, PROPERTY_HINT_NODE_TYPE, "MapRegion");
}
void NpcUnit::remove_npc(EnemyBody *npc) {
Transform3D const tf{ npc->get_global_transform() };
remove_child(npc);
this->get_parent()->add_child(npc);
npc->set_global_transform(tf);
}
void NpcUnit::on_npc_death() {
Vector<EnemyBody>::Size living{ this->npcs.size() };
// remove any dead npcs from the list
// leaving their bodies as separate nodes part of the tree
for (Vector<EnemyBody>::Size i{ 0 }; i < this->npcs.size(); ++i) {
EnemyBody *npc{ this->npcs[i] };
for (EnemyBody *npc : this->npcs) {
if (npc->get_health()->get_health() <= 0) {
--living;
this->get_parent()->add_child(npc);
this->npcs.erase(npc);
break;
}
}
// remove unit from world once all npcs are dead
if (living == 0) {
for (EnemyBody *npc : this->npcs) {
remove_npc(npc);
}
if (this->npcs.size() <= 0) {
this->set_region(nullptr); // de-register from region
this->queue_free();
}

View file

@ -10,7 +10,6 @@ class MapRegion;
class NpcUnit : public Node3D {
GDCLASS(NpcUnit, Node3D);
static void _bind_methods();
void remove_npc(EnemyBody *unit);
void on_npc_death();
void on_npc_awareness_changed(bool seen);
void child_added(Node *node);

View file

@ -1,6 +1,4 @@
#include "player_input.h"
#include "core/config/engine.h"
#include "core/input/input.h"
#include "scene/main/scene_tree.h"
String PlayerInput::sig_movement_input{ "movement_input" };

View file

@ -1,5 +1,4 @@
#include "state_machine.h"
#include "core/config/engine.h"
#include "state.h"
void StateMachine::_bind_methods() {}
@ -19,7 +18,7 @@ void StateMachine::switch_to_state(State *state) {
}
void StateMachine::process(double delta) {
if (this->current_state && is_enabled()) {
if (this->current_state) {
this->current_state->process(delta);
String new_state{ this->current_state->get_next_state() };
if (new_state != this->current_state->get_class()) {

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -7,43 +7,23 @@ script/source = "extends EnemyWretched
@export var difficulty_weight : float = 10
var is_dead := false
func on_death() -> void:
func _on_health_status_death() -> void:
%StateMachine.process_mode = Node.PROCESS_MODE_DISABLED
%NavigationAgent3D.process_mode = Node.PROCESS_MODE_DISABLED
$wretched/AnimationPlayer.play(\"death\")
$CollisionShape3D.disabled = true
set_movement_direction(Vector2())
func _on_health_status_death() -> void:
$wretched/AnimationPlayer.play(\"death\")
get_unit().region.raise_difficulty(1.0 / difficulty_weight)
on_death.call_deferred()
is_dead = true
func _enter_tree() -> void:
if is_dead and $wretched/AnimationPlayer.current_animation != \"death\":
$wretched/AnimationPlayer.play.call_deferred(\"death\")
$wretched/AnimationPlayer.advance.call_deferred(INF)
elif is_dead:
$wretched/AnimationPlayer.play.call_deferred(\"death\")
"
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ng1ul"]
radius = 0.58691406
radius = 0.26953125
[node name="EnemyWretched" type="EnemyWretched"]
wall_min_slide_angle = 0.0
script = SubResource("GDScript_qot2n")
[node name="wretched" parent="." instance=ExtResource("1_qot2n")]
[node name="Body" parent="wretched/Character/Skeleton3D" index="0"]
gi_mode = 0
[node name="club" parent="wretched/Character/Skeleton3D" index="1"]
gi_mode = 0
[node name="Hitbox" parent="wretched/Character/Skeleton3D" index="2" node_paths=PackedStringArray("health")]
health = NodePath("../../../../HealthStatus")

View file

@ -12,7 +12,7 @@ config_version=5
config/name="wave_survival"
run/main_scene="uid://dti7d1rslmhgp"
config/features=PackedStringArray("4.6", "Forward Plus")
config/features=PackedStringArray("4.5", "Forward Plus")
config/icon="res://icon.svg"
[display]
@ -103,10 +103,13 @@ reload={
3d_physics/layer_4="Hitbox(Player)"
3d_physics/layer_5="Interactables"
[physics]
3d/physics_engine="Jolt Physics"
[rendering]
lights_and_shadows/directional_shadow/size=8192
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=4
lights_and_shadows/positional_shadow/soft_shadow_filter_quality=5
global_illumination/voxel_gi/quality=1
lights_and_shadows/positional_shadow/atlas_size=8192