feat: started work on actors and party members

This commit is contained in:
Sara 2025-06-27 00:54:15 +02:00
parent 80a948686f
commit 049ac16541
15 changed files with 513 additions and 107 deletions

View file

@ -0,0 +1,68 @@
#include "actor_body.h"
#include "core/config/engine.h"
#include "core/object/object.h"
#include "macros.h"
void ActorBody::_bind_methods() {
BIND_HPROPERTY(Variant::FLOAT, movement_speed, PROPERTY_HINT_RANGE, "0.0,20.0");
}
void ActorBody::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_PHYSICS_PROCESS:
physics_process(get_physics_process_delta_time());
return;
}
}
void ActorBody::physics_process(double delta) {
set_velocity(get_movement_direction() * this->movement_speed);
move_and_slide();
}
void ActorBody::set_movement_direction(Vector3 direction) {
this->mode = Direction;
this->movement_vector = { direction.x, 0.f, direction.y };
}
Vector3 ActorBody::get_movement_direction() const {
switch (this->mode) {
case Position: {
Vector3 const direction_3d{ get_global_position().direction_to(get_movement_target()) };
return Vector3{ direction_3d.x, 0.f, direction_3d.z };
} break;
case Direction:
return this->movement_vector;
}
}
void ActorBody::set_movement_target(Vector3 location) {
this->mode = Position;
this->movement_vector = { location.x, 0.f, location.y };
}
Vector3 ActorBody::get_movement_target() const {
switch (this->mode) {
case Position:
return this->movement_vector;
case Direction:
return get_global_position() + this->movement_vector;
}
}
void ActorBody::set_movement_speed(float speed) {
this->movement_speed = speed;
}
float ActorBody::get_movement_speed() const {
return this->movement_speed;
}
ActorBody::MovementMode ActorBody::get_movement_mode() const {
return this->mode;
}

View file

@ -0,0 +1,34 @@
#ifndef ACTOR_BODY_H
#define ACTOR_BODY_H
#include "scene/3d/physics/character_body_3d.h"
class ActorBody : public CharacterBody3D {
GDCLASS(ActorBody, CharacterBody3D);
static void _bind_methods();
void physics_process(double delta);
public:
// support both directional and positional movement modes
enum MovementMode {
Direction,
Position
};
void _notification(int what);
void set_movement_direction(Vector3 direction);
Vector3 get_movement_direction() const;
void set_movement_target(Vector3 location);
Vector3 get_movement_target() const;
void set_movement_speed(float speed);
float get_movement_speed() const;
MovementMode get_movement_mode() const;
private:
float movement_speed{ 1.f };
Vector3 movement_vector{ 0.f, 0.f, 0.f };
MovementMode mode{ Direction };
};
#endif //! ACTOR_BODY_H

View file

@ -6,6 +6,10 @@ GameState *GameState::singleton_instance{ nullptr };
void GameState::_bind_methods() {
BIND_PROPERTY(Variant::STRING, locale_uid);
BIND_PROPERTY(Variant::STRING, locale_entrance_path);
{
String const party_member_data_hint{ vformat("%s/%s:PartyMemberData", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE) };
BIND_HPROPERTY(Variant::ARRAY, player_party, PROPERTY_HINT_ARRAY_TYPE, party_member_data_hint);
}
}
GameState::GameState() {
@ -35,3 +39,21 @@ void GameState::set_locale_entrance_path(String const &value) {
String GameState::get_locale_entrance_path() const {
return this->locale_uid;
}
void GameState::set_player_party(Array array) {
this->player_party.clear();
for (int i{ 0 }; i < array.size(); ++i) {
Ref<PartyMemberData> data{ array[i] };
if (data.is_valid()) {
this->player_party.push_back(data);
}
}
}
Array GameState::get_player_party() const {
Array a{};
for (Ref<PartyMemberData> const &data : this->player_party) {
a.push_back(data);
}
return a;
}

View file

@ -1,8 +1,9 @@
#ifndef GAME_STATE_H
#define GAME_STATE_H
#include "core/object/class_db.h"
#include "authority/party_member_data.h"
#include "core/object/object.h"
#include "core/templates/vector.h"
class GameState : public Object {
GDCLASS(GameState, Object);
@ -17,10 +18,13 @@ public:
String get_locale_uid() const;
void set_locale_entrance_path(String const &value);
String get_locale_entrance_path() const;
void set_player_party(Array array);
Array get_player_party() const;
private:
String locale_uid{ "" };
String locale_entrance_path{ "" };
Vector<Ref<PartyMemberData>> player_party{};
};
#endif // !GAME_STATE_H

View file

@ -0,0 +1,36 @@
#include "party_member_data.h"
#include "macros.h"
void PartyMemberData::_bind_methods() {
BIND_PROPERTY(Variant::STRING, first_name);
BIND_PROPERTY(Variant::INT, player_trust);
BIND_PROPERTY(Variant::INT, player_fear);
}
int PartyMemberData::get_player_authority() const {
return this->player_fear + this->player_trust;
}
void PartyMemberData::set_first_name(String name) {
this->first_name = name;
}
String PartyMemberData::get_first_name() const {
return this->first_name;
}
void PartyMemberData::set_player_trust(int value) {
this->player_trust = value;
}
int PartyMemberData::get_player_trust() const {
return this->player_trust;
}
void PartyMemberData::set_player_fear(int value) {
this->player_fear = value;
}
int PartyMemberData::get_player_fear() const {
return this->player_fear;
}

View file

@ -0,0 +1,26 @@
#ifndef PARTY_MEMBER_DATA_H
#define PARTY_MEMBER_DATA_H
#include "core/io/resource.h"
class PartyMemberData : public Resource {
GDCLASS(PartyMemberData, Resource);
static void _bind_methods();
public:
int get_player_authority() const;
void set_first_name(String name);
String get_first_name() const;
void set_player_trust(int value);
int get_player_trust() const;
void set_player_fear(int value);
int get_player_fear() const;
private:
String first_name{ "Firstname" };
int player_trust{ 1 };
int player_fear{ 1 };
};
#endif // !PARTY_MEMBER_DATA_H

View file

@ -0,0 +1,27 @@
#include "player_actor.h"
#include "authority/player_input.h"
void PlayerActor::_bind_methods() {
}
void PlayerActor::ready() {
PlayerInput *input{ cast_to<PlayerInput>(get_node(NodePath("%PlayerInput"))) };
input->connect(PlayerInput::signal_movement, callable_mp(this, &self_type::input_move));
}
void PlayerActor::input_move(Vector2 movement) {
set_movement_direction({ movement.x, 0.f, movement.y });
}
void PlayerActor::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_READY:
ready();
return;
}
}

View file

@ -0,0 +1,16 @@
#ifndef PLAYER_ACTOR_H
#define PLAYER_ACTOR_H
#include "actor_body.h"
class PlayerActor : public ActorBody {
GDCLASS(PlayerActor, ActorBody);
static void _bind_methods();
void ready();
void input_move(Vector2 movement);
public:
void _notification(int what);
};
#endif // !PLAYER_ACTOR_H

View file

@ -0,0 +1,72 @@
#include "player_input.h"
#include "core/input/input_event.h"
#include "macros.h"
String const PlayerInput::signal_movement{ "movement" };
void PlayerInput::_bind_methods() {
BIND_PROPERTY(Variant::STRING, action_move_left);
BIND_PROPERTY(Variant::STRING, action_move_right);
BIND_PROPERTY(Variant::STRING, action_move_forward);
BIND_PROPERTY(Variant::STRING, action_move_back);
ADD_SIGNAL(MethodInfo(self_type::signal_movement, PropertyInfo(Variant::VECTOR2, "movement_directions")));
}
void PlayerInput::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_READY:
this->set_process_unhandled_input(true);
return;
}
}
void PlayerInput::unhandled_input(Ref<InputEvent> const &event) {
Input *input{ Input::get_singleton() };
bool is_movement_action{ event->is_action(self_type::action_move_left) };
is_movement_action |= event->is_action(self_type::action_move_right);
is_movement_action |= event->is_action(self_type::action_move_forward);
is_movement_action |= event->is_action(self_type::action_move_back);
if (is_movement_action) {
float const h_axis{ input->get_axis(self_type::action_move_right, self_type::action_move_left) };
float const v_axis{ input->get_axis(self_type::action_move_back, self_type::action_move_forward) };
this->emit_signal(self_type::signal_movement, Vector2{ h_axis, v_axis });
}
}
void PlayerInput::set_action_move_left(String action) {
this->action_move_left = action;
}
String PlayerInput::get_action_move_left() const {
return this->action_move_left;
}
void PlayerInput::set_action_move_right(String action) {
this->action_move_right = action;
}
String PlayerInput::get_action_move_right() const {
return this->action_move_right;
}
void PlayerInput::set_action_move_forward(String action) {
this->action_move_forward = action;
}
String PlayerInput::get_action_move_forward() const {
return this->action_move_forward;
}
void PlayerInput::set_action_move_back(String action) {
this->action_move_back = action;
}
String PlayerInput::get_action_move_back() const {
return this->action_move_back;
}

View file

@ -0,0 +1,33 @@
#ifndef PLAYER_INPUT_H
#define PLAYER_INPUT_H
#include "core/input/input_event.h"
#include "scene/main/node.h"
class PlayerInput : public Node {
GDCLASS(PlayerInput, Node);
static void _bind_methods();
public:
void _notification(int what);
virtual void unhandled_input(Ref<InputEvent> const &event) override;
void set_action_move_left(String action);
String get_action_move_left() const;
void set_action_move_right(String action);
String get_action_move_right() const;
void set_action_move_forward(String action);
String get_action_move_forward() const;
void set_action_move_back(String action);
String get_action_move_back() const;
public:
static String const signal_movement;
private:
String action_move_left{ "move_left" };
String action_move_right{ "move_right" };
String action_move_forward{ "move_forward" };
String action_move_back{ "move_back" };
};
#endif // !PLAYER_INPUT_H

View file

@ -1,7 +1,11 @@
#include "register_types.h"
#include "authority/actor_body.h"
#include "authority/game_state.h"
#include "authority/locale_marker.h"
#include "authority/party_member_data.h"
#include "authority/player_actor.h"
#include "authority/player_input.h"
#include "core/config/engine.h"
#include "core/object/class_db.h"
@ -12,7 +16,11 @@ void initialize_authority_module(ModuleInitializationLevel p_level) {
return;
}
GDREGISTER_CLASS(GameState);
GDREGISTER_CLASS(LocaleMarker);
GDREGISTER_RUNTIME_CLASS(LocaleMarker);
GDREGISTER_RUNTIME_CLASS(PartyMemberData);
GDREGISTER_CLASS(ActorBody);
GDREGISTER_CLASS(PlayerActor);
GDREGISTER_CLASS(PlayerInput);
game_state = memnew(GameState);
Engine::get_singleton()->add_singleton(Engine::Singleton("GameState", GameState::get_singleton()));