Compare commits
13 commits
6153e73492
...
c4bd5edb54
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4bd5edb54 | ||
|
|
2f6c7e13e5 | ||
|
|
d5a633c973 | ||
|
|
71bd8cd630 | ||
|
|
e303c853e9 | ||
|
|
a5cbee6b44 | ||
|
|
28183fceb8 | ||
|
|
5f61fafe7b | ||
|
|
777f7908de | ||
|
|
c66d6f56b4 | ||
|
|
4efcf58a01 | ||
|
|
75c64a786a | ||
|
|
d7eeb98b5b |
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -22,3 +22,6 @@ build.zip
|
|||
wave-survival-fps.kdev4
|
||||
__pycache__
|
||||
modules/wave_survival/__pycache__
|
||||
|
||||
# blender auto backups
|
||||
*.blend1
|
||||
|
|
|
|||
2
engine
2
engine
|
|
@ -1 +1 @@
|
|||
Subproject commit c6d130abd9188f313e6701d01a0ddd6ea32166a0
|
||||
Subproject commit 084d5d407e62efcd5be9de44148c5dedce3b9386
|
||||
2
justfile
2
justfile
|
|
@ -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"
|
||||
cd engine/ && scons target=editor symbols=yes optimization=debug dev_build=yes linker=mold use_llvm=yes custom_modules="../modules" compiledb=yes
|
||||
|
||||
run: build
|
||||
# Running Editor
|
||||
|
|
|
|||
|
|
@ -33,9 +33,11 @@ void DamageBox::_notification(int what) {
|
|||
default:
|
||||
return;
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
modules/wave_survival/enemies/enemy_rifleman.cpp
Normal file
26
modules/wave_survival/enemies/enemy_rifleman.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,55 @@
|
|||
#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
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ void EnemyWretched::_notification(int what) {
|
|||
default:
|
||||
return;
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
|
||||
if (!is_ready()) {
|
||||
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
|
||||
}
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
ready();
|
||||
|
|
|
|||
|
|
@ -19,11 +19,15 @@ 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 });
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/3d/marker_3d.h"
|
||||
class MapRegion;
|
||||
class PatrolPath;
|
||||
|
||||
|
|
@ -19,8 +19,8 @@ public:
|
|||
HashMap<int, Ref<PackedScene>> difficulty_spawns{};
|
||||
};
|
||||
|
||||
class EnemySpawner : public Node3D {
|
||||
GDCLASS(EnemySpawner, Node3D);
|
||||
class EnemySpawner : public Marker3D {
|
||||
GDCLASS(EnemySpawner, Marker3D);
|
||||
static void _bind_methods();
|
||||
void on_phase_change(bool hunt);
|
||||
void ready();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "health_status.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "macros.h"
|
||||
|
||||
String HealthStatus::sig_death{ "death" };
|
||||
|
|
|
|||
|
|
@ -11,18 +11,28 @@ 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 (EnemyBody *npc : this->npcs) {
|
||||
for (Vector<EnemyBody>::Size i{ 0 }; i < this->npcs.size(); ++i) {
|
||||
EnemyBody *npc{ this->npcs[i] };
|
||||
if (npc->get_health()->get_health() <= 0) {
|
||||
this->get_parent()->add_child(npc);
|
||||
this->npcs.erase(npc);
|
||||
break;
|
||||
--living;
|
||||
}
|
||||
}
|
||||
// remove unit from world once all npcs are dead
|
||||
if (this->npcs.size() <= 0) {
|
||||
if (living == 0) {
|
||||
for (EnemyBody *npc : this->npcs) {
|
||||
remove_npc(npc);
|
||||
}
|
||||
this->set_region(nullptr); // de-register from region
|
||||
this->queue_free();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ 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);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#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" };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "state_machine.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "state.h"
|
||||
|
||||
void StateMachine::_bind_methods() {}
|
||||
|
|
@ -18,7 +19,7 @@ void StateMachine::switch_to_state(State *state) {
|
|||
}
|
||||
|
||||
void StateMachine::process(double delta) {
|
||||
if (this->current_state) {
|
||||
if (this->current_state && is_enabled()) {
|
||||
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.
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
|
|
@ -7,23 +7,43 @@ script/source = "extends EnemyWretched
|
|||
|
||||
@export var difficulty_weight : float = 10
|
||||
|
||||
func _on_health_status_death() -> void:
|
||||
var is_dead := false
|
||||
|
||||
func on_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.26953125
|
||||
radius = 0.58691406
|
||||
|
||||
[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")
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ config_version=5
|
|||
|
||||
config/name="wave_survival"
|
||||
run/main_scene="uid://dti7d1rslmhgp"
|
||||
config/features=PackedStringArray("4.5", "Forward Plus")
|
||||
config/features=PackedStringArray("4.6", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[display]
|
||||
|
|
@ -103,13 +103,10 @@ 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue