the rest of the fucking owl
This commit is contained in:
parent
f89d2ccf53
commit
7f63584f7c
20 changed files with 331 additions and 9 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
84
modules/tabtargeting/actor_state_machine.cpp
Normal file
84
modules/tabtargeting/actor_state_machine.cpp
Normal 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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define EQUIPMENT_H
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/templates/vector.h"
|
||||
#include "scene/main/node.h"
|
||||
class ActorBody;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue