#pragma once #include #include #include #include "animation.hpp" #include "objects/object.hpp" #include "inventory/weapon.hpp" class Character; class Enemy; enum class EnemyStatus { IDLE, RUN, ATTACK, HIT, DEAD, DYING, }; struct EnemyAnimation { std::unordered_map idle; std::unordered_map run; std::unordered_map attack; std::unordered_map hit; std::unordered_map death; }; struct EnemyStats { float health; float health_max; float demage; bool is_attacking; bool has_attacked; float attack_duration; float attack_duration_max; }; struct CollisionInterval { float min_x, max_x; float min_y, max_y; bool valid; }; struct SpawnParams { double spawn_date; WeaponType type; WeaponMaterial material; SDL_FPoint pos; EnemyStats stats; }; struct EnemyMoveThreadData { Enemy* enemy; SDL_FPoint player; bool is_moving; }; enum class EnemyMovingType : uint32_t { NONE, IDLE, CHARACTER, OBJECT, WALK, LAST }; struct EnemyMovingLogic { EnemyMovingType move_type = EnemyMovingType::NONE; void* object = nullptr; SDL_FPoint position = {0,0}; bool position_changed = true; float duration = 0.0f; int max_distance = 120; int min_distance = 80; double path_blocked = 0; // time when blocked? bool avoid_blockage = false; SDL_FPoint moving_distance = {0,0}; }; struct WorkerData { Enemy* enemy; std::shared_ptr> grid; // use shared_ptr for safety }; class Enemy { static int id_next; int id; float speed; float run; // multiplier bool flip; static size_t tile_size; float arm_reach_radius; float detection_radius; public: static SDL_FPoint colider_default; static std::vector enemies; static std::vector enemies_to_spawn; EnemyMovingLogic moving_logic = {EnemyMovingType::NONE, nullptr}; bool moving; EnemyMovingType move_focus = EnemyMovingType::NONE; float x, y; SDL_FPoint next_position = {0,0}; SDL_FRect collider; CollisionInterval last_object_collision = {0,0,0,0,false}; bool avoiding_object = false; SDL_FPoint avoidance_target = {0,0}; std::vector avoidance_targets; Enemy* collidiing_with_enemy = nullptr; CollisionInterval last_map_collision = {0,0,0,0,false}; bool avoiding_map = false; float dist_min = 24; float dist_max = 32; bool is_character_in_range = false; int stuck_moves = 0; std::vector next_moves; SDL_Point last_player_pos{}; SDL_Point last_target_pos{}; AnimationData* active_anim; static EnemyAnimation animation_all; EnemyAnimation animation; WalkDirection direction; std::unordered_map direction_blocked; bool direction_tested_up; bool direction_tested_left; EnemyStatus status; Weapon weapon; EnemyStats stats; float max_death_time; float death_duration; float death_duration_max; bool point_in_reach; Enemy(WeaponType weapon_type, WeaponMaterial weapon_material, SDL_FPoint position, EnemyStats status); std::unordered_map resources; SDL_FPoint collider_world; SDL_Point tile_world; std::vector tiles_in_reach; // START THREAD static std::vector workers; static std::vector job_queue; static std::mutex queue_mutex; static std::condition_variable queue_cv; static bool stop_threads; // Job completion tracking static int jobs_remaining; static std::condition_variable jobs_done_cv; static void init_Workers(int num_threads); static void shutdown_Workers(); static void run_GetMovesThreads(); // END THREAD void Init(); static void init_All(SDL_Renderer*); void set_Status(const EnemyStatus&); void handle_Animation(); void Draw(SDL_Renderer* renderer); static void init_SpawnEnemy(double delay_to_spawn_in_sec, WeaponType weapon_type, WeaponMaterial weapon_material, SDL_FPoint position, EnemyStats status); static bool spawn_Enemy(SpawnParams&); static Enemy* is_InEnemyReach(const SDL_FRect& rect); void Decide(Character& player); bool set_CollisinnWithEnemy(const SDL_FRect& rect); static bool is_CollidingWithEnemy(const SDL_FRect& rect); bool is_CollidingWithObjects(const SDL_FRect& rect); bool is_CollidingWithWorld(const SDL_FRect& rect); bool is_Colliding(const SDL_FRect& rect); inline bool character_InRange(SDL_FPoint char_pos) const; void compute_MapCollisionInterval(size_t cx, size_t cy, size_t max_x, size_t max_y); void death(); static void remove_Dead(); // void // OLD?? // move_ToPosition(SDL_FPoint move_to_position); void set_AlignPosition(const SDL_FPoint& player); void set_NextMoves(const std::vector& map_tiles); void move_Path(); void set_MoveLogic(EnemyMovingType&, Character& player); void Update(Character& player); void attack_Start(); void Attack(bool in_reach); void attack_Stop(); void getting_Hit(float demage); void set_TilesInReach(); static bool save_All(const std::string &path); static bool load_All(const std::string &path); };