the rest of the fucking owl

This commit is contained in:
Sara 2025-06-13 15:12:22 +02:00
parent f89d2ccf53
commit 7f63584f7c
20 changed files with 331 additions and 9 deletions

View file

@ -1,10 +1,49 @@
#include "actor_body.h"
#include "core/object/class_db.h"
#include "core/string/print_string.h"
void ActorBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_attack"), &self_type::request_attack, "target");
}
void ActorBody::_notification(int what) {
if(Engine::get_singleton()->is_editor_hint()) {
return;
}
switch(what) {
case NOTIFICATION_READY:
this->equipment = Object::cast_to<Equipment>(this->get_node(NodePath("Equipment")));
break;
}
}
void ActorBody::_attack() {
if(this->attack_requested != nullptr) {
this->attack_requested->receive_damage(this->equipment->apply(this->equipment->get_weapon()->create_base_damage_event(this), this));
this->attack_requested = nullptr;
}
}
bool ActorBody::is_attack_requested() {
return this->attack_requested != nullptr;
}
void ActorBody::receive_damage(DamageEvent event) {
this->health -= event.compound_damage;
this->health -= this->equipment->apply(event, this).compound_damage;
print_line(vformat("Damage dealth (%d to %s, %d remaining", event.compound_damage, this->get_name(), this->health));
if(this->health < 0) {
this->queue_free();
}
}
void ActorBody::request_attack(ActorBody *target) {
this->attack_requested = target;
}
void ActorBody::set_health(int health) {
this->health = health;
}
int ActorBody::get_health() const {
return this->health;
}

View file

@ -8,13 +8,19 @@ class ActorBody;
class ActorBody : public CharacterBody3D {
GDCLASS(ActorBody, CharacterBody3D);
static void _bind_methods();
void _notification(int what);
public:
void _attack();
bool is_attack_requested();
void receive_damage(DamageEvent event);
void send_damage(int amount, ActorBody *target);
void request_attack(ActorBody *target);
void set_health(int health);
int get_health() const;
private:
int health{10};
int health{50};
int max_health{10};
ActorBody *attack_requested{nullptr};
class Equipment *equipment{nullptr};
Equipment *equipment{nullptr};
};
#endif // !ACTOR_BODY_H

View file

@ -0,0 +1,84 @@
#include "actor_state_machine.h"
#include "core/config/engine.h"
#include "tabtargeting/actor_body.h"
void ActorState::_bind_methods() {
}
void ActorStateMachine::_bind_methods() {
}
void ActorStateMachine::_notification(int what) {
if(Engine::get_singleton()->is_editor_hint()) {
return;
}
switch(what) {
case NOTIFICATION_READY:
this->ready();
break;
case NOTIFICATION_PROCESS:
this->process(this->get_process_delta_time());
break;
default: break;
}
}
void ActorStateMachine::ready() {
this->set_process(true);
this->body = Object::cast_to<ActorBody>(this->get_parent());
this->add_state<IdleState>();
this->add_state<ActingState>();
this->current_state->state_entered();
}
void ActorStateMachine::process(double delta) {
this->current_state->process(delta);
this->try_next_state();
}
void ActorStateMachine::try_next_state() {
StringName name{this->current_state->next_state()};
if(name != this->current_state->get_class()) {
this->switch_state(this->states[name]);
}
}
void ActorStateMachine::switch_state(ActorState *state) {
this->current_state->state_exited();
this->current_state = state;
this->current_state->state_entered();
}
void IdleState::_bind_methods() {}
void IdleState::state_exited() {
print_line("state idle exited");
if(this->body->is_attack_requested()) {
this->body->_attack();
}
}
StringName IdleState::next_state() const {
if(this->body->is_attack_requested()) {
return ActingState::get_class_static();
}
return this->get_class_name();
}
void ActingState::_bind_methods() {}
void ActingState::state_entered() {
print_line("state acting exited");
this->timer = this->seconds_to_wait;
}
void ActingState::process(double delta) {
this->timer -= delta;
}
StringName ActingState::next_state() const {
if(this->timer <= 0) {
return IdleState::get_class_static();
}
return this->get_class();
}

View file

@ -1,13 +1,70 @@
#ifndef ACTOR_STATE_MACHINE_H
#define ACTOR_STATE_MACHINE_H
#include "core/string/string_name.h"
#include "scene/main/node.h"
#include "core/object/ref_counted.h"
class ActorBody;
class ActorState : public RefCounted {
GDCLASS(ActorState, Object);
static void _bind_methods();
public:
virtual void state_entered() {}
virtual void process(double delta) {}
virtual StringName next_state() const {
return this->get_class();
}
virtual void state_exited() {}
protected:
ActorBody *body{nullptr};
friend class ActorStateMachine;
};
class ActorStateMachine : public Node {
GDCLASS(ActorStateMachine, Node);
static void _bind_methods();
public:
void _notification(int what);
void ready();
void process(double delta);
template <class TState>
void add_state();
void try_next_state();
void switch_state(ActorState *state);
private:
ActorBody *body{nullptr};
ActorState *current_state{};
HashMap<StringName, ActorState*> states{};
};
template <class TState>
void ActorStateMachine::add_state() {
ActorState *state{memnew(TState)};
state->body = this->body;
this->states.insert(TState::get_class_static(), state);
if(current_state == nullptr) {
this->current_state = state;
}
}
class IdleState : public ActorState {
GDCLASS(IdleState, ActorState);
static void _bind_methods();
public:
virtual void state_exited() override;
virtual StringName next_state() const override;
};
class ActingState : public ActorState {
GDCLASS(ActingState, ActorState);
static void _bind_methods();
public:
virtual void state_entered() override;
virtual void process(double delta) override;
virtual StringName next_state() const override;
private:
double const seconds_to_wait{1.0};
double timer{0.0};
};
#endif // !ACTOR_STATE_MACHINE_H

View file

@ -8,6 +8,14 @@ DamageEvent::DamageEvent(int damage, ActorBody *source)
, source{source}
{}
int DamageEvent::get_initial_damage() const {
return this->initial_damage;
}
ActorBody *DamageEvent::get_source() const {
return this->source;
}
void DamageStats::_bind_methods() {
BIND_PROPERTY(Variant::INT, damage_add);
BIND_PROPERTY(Variant::INT, damage_mul);
@ -101,7 +109,15 @@ void Equipment::_bind_methods() {
}
DamageEvent Equipment::apply(DamageEvent event, ActorBody *target) {
if(this->weapon.is_valid())
event = this->weapon->apply(event, target);
if(this->helmet.is_valid())
event = this->helmet->apply(event, target);
if(this->chest.is_valid())
event = this->chest->apply(event, target);
if(this->legs.is_valid())
event = this->legs->apply(event, target);
return event;
}
void Equipment::set_weapon(Ref<Weapon> weapon) {

View file

@ -2,7 +2,6 @@
#define EQUIPMENT_H
#include "core/io/resource.h"
#include "core/templates/vector.h"
#include "scene/main/node.h"
class ActorBody;

View file

@ -1,6 +1,7 @@
#include "register_types.h"
#include "core/object/class_db.h"
#include "tabtargeting/actor_state_machine.h"
#include "tabtargeting/equipment.h"
#include "tabtargeting/actor_body.h"
@ -9,6 +10,10 @@ void initialize_tabtargeting_module(ModuleInitializationLevel p_level) {
return;
}
ClassDB::register_class<ActorBody>();
ClassDB::register_class<ActorStateMachine>();
ClassDB::register_class<ActorState>();
ClassDB::register_class<ActingState>();
ClassDB::register_class<IdleState>();
ClassDB::register_class<DamageStats>();
ClassDB::register_class<EquipItem>();
ClassDB::register_class<Weapon>();