From 16fab455c6fa338d86a3626fa8d414bd28818cb5 Mon Sep 17 00:00:00 2001 From: SeregaN8 Date: Sun, 9 Apr 2023 22:58:17 +0300 Subject: [PATCH] baseTurnManager --- Source/TurnBasedTutorial/BasicTurnManager.cpp | 152 ++++++++++++++++++ Source/TurnBasedTutorial/BasicTurnManager.h | 81 ++++++++++ 2 files changed, 233 insertions(+) create mode 100644 Source/TurnBasedTutorial/BasicTurnManager.cpp create mode 100644 Source/TurnBasedTutorial/BasicTurnManager.h diff --git a/Source/TurnBasedTutorial/BasicTurnManager.cpp b/Source/TurnBasedTutorial/BasicTurnManager.cpp new file mode 100644 index 0000000..780e220 --- /dev/null +++ b/Source/TurnBasedTutorial/BasicTurnManager.cpp @@ -0,0 +1,152 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BasicTurnManager.h" +#include "Templates/UnrealTemplate.h" + +namespace basic_api_classes { + base_ability::base_ability(double cost_, double damage_, double max_activation_radius_, double splash_radius_, double linear_width_) : + cost(cost_), damage(damage_), max_activation_radius(max_activation_radius_), splash_radius(splash_radius_), linear_width(linear_width_) {}; + + bool base_ability::is_pers_hurt(double attacker_x, double attacker_y, double activation_x, double activation_y, double defender_x, double defender_y) { + { + double dist = (activation_x - defender_x) * (activation_x - defender_x) + + (activation_y - defender_y) * (activation_y - defender_y); + if (dist + 1e-6 < splash_radius * splash_radius) return true; + } + { + double dist = (attacker_x - defender_x) * (attacker_x - defender_x) + + (attacker_y - defender_y) * (attacker_y - defender_y); + double dist1 = (attacker_x - activation_x) * (attacker_x - activation_x) + + (attacker_y - activation_y) * (attacker_y - activation_y); + if (dist > dist1 + 1e-6) return false; + + double height = defender_x * (activation_y - attacker_y) - defender_y * (activation_x - attacker_x) - + attacker_x * activation_y + attacker_y * activation_x; + height *= height; + return height < ((activation_y - attacker_y)* (activation_y - attacker_y) + (activation_x - attacker_x) * (activation_x - attacker_x))* + linear_width*linear_width; + } + } + + base_personage::base_personage(double x_, double y_, double hp, double trav_cost, TArray&& abils) : is_dead(false), x_coordinate(x_), + y_coordinate(y_), hitpoints(hp), travel_cost(trav_cost), abilities(MoveTemp(abils)) {}; + + FVector2D base_personage::get_personage_cords() const{ + return FVector2D{ static_cast(x_coordinate), static_cast(y_coordinate) }; + } + + double base_personage::get_hitpoints() const{ + return hitpoints; + } + + void base_personage::move_to_position(double new_x, double new_y, double& rest_action_points) { + double dist = (new_x - x_coordinate) * (new_x - x_coordinate) + (new_y - y_coordinate) * (new_y - y_coordinate); + dist = sqrt(dist); + if (rest_action_points + 1e-6 < dist * travel_cost) { + rest_action_points -= dist * travel_cost; + x_coordinate = new_x, y_coordinate = new_y; + } + } + + void base_personage::accept_damage(double damage) { + if (is_dead) return; + hitpoints -= damage; + if (hitpoints < 1e-6) { + hitpoints = 0; + is_dead = true; + } + } + + bool base_personage::is_attack_startable(size_t ability_number, double attack_pos_x, double attack_pos_y, double rest_action_points) const{ + if (ability_number >= abilities.Num()) return false; + base_ability* ba = abilities[ability_number]; + double dist = (attack_pos_x - x_coordinate) * (attack_pos_x - x_coordinate) + + (attack_pos_y - y_coordinate) * (attack_pos_y - y_coordinate); + return dist + 1e-6 < ba->max_activation_radius * ba->max_activation_radius && ba->cost + 1e-6 < rest_action_points; + } + + bool base_personage::is_pers_dead() const{ + return is_dead; + } + + base_player::base_player(TArray&& team_) : team(MoveTemp(team_)) {}; + + BasicTurnManager::BasicTurnManager(base_player* player1_, base_player* player2_, double points_per_move, double x_min_, double x_max_, double y_min_, double y_max_) : + player1(player1_), player2(player2_), action_points(points_per_move), current_player_action_points(action_points), x_min(x_min_), x_max(x_max_), y_min(y_min_), + y_max(y_max_), motion_number(1), first_player_motion(true), team1_alive((player1->team).Num()), team2_alive((player2->team).Num()) {} + + bool BasicTurnManager::check_correctness(double x, double y) const{ + return x >= x_min && x <= x_max && y >= y_min && y <= y_max; + } + + void BasicTurnManager::next_move() { + current_player_action_points = action_points; + if (!first_player_motion) ++motion_number; + first_player_motion ^= 1; + } + + int BasicTurnManager::get_move_number() const{ + return motion_number; + } + + bool BasicTurnManager::is_first_player_move() const { + return first_player_motion; + } + + size_t BasicTurnManager::first_team_alive() const { + return team1_alive; + } + + size_t BasicTurnManager::second_team_alive() const { + return team2_alive; + } + + void BasicTurnManager::move_command(size_t pers_num, double new_x, double new_y) { + if (!check_correctness(new_x, new_y)) return; + if (first_player_motion) { + if (pers_num >= (player1->team).Num()) return; + (player1->team)[pers_num]->move_to_position(new_x, new_y, current_player_action_points); + } + else { + if (pers_num >= (player2->team).Num()) return; + (player2->team)[pers_num]->move_to_position(new_x, new_y, current_player_action_points); + } + } + + void BasicTurnManager::attack_command(size_t pers_num, size_t abil_num, double attack_x, double attack_y) { + if (!check_correctness(attack_x, attack_y)) return; + if (first_player_motion) { + if (pers_num >= (player1->team).Num()) return; + base_personage* attacker = (player1->team)[pers_num]; + if (!attacker->is_attack_startable(abil_num, attack_x, attack_y, current_player_action_points)) return; + base_ability* attack = (attacker->abilities)[abil_num]; + current_player_action_points -= attack->cost; + for (auto def : player2->team) { + if (def->is_pers_dead()) continue; + if (attack->is_pers_hurt(attacker->get_personage_cords().X, attacker->get_personage_cords().Y, attack_x, attack_y, + def->get_personage_cords().X, def->get_personage_cords().Y)) { + def->accept_damage(attack->damage); + + if (def->is_pers_dead()) --team2_alive; + } + } + } + else { + if (pers_num >= (player2->team).Num()) return; + base_personage* attacker = (player2->team)[pers_num]; + if (!attacker->is_attack_startable(abil_num, attack_x, attack_y, current_player_action_points)) return; + base_ability* attack = (attacker->abilities)[abil_num]; + current_player_action_points -= attack->cost; + for (auto def : player1->team) { + if (def->is_pers_dead()) continue; + if (attack->is_pers_hurt(attacker->get_personage_cords().X, attacker->get_personage_cords().Y, attack_x, attack_y, + def->get_personage_cords().X, def->get_personage_cords().Y)) { + def->accept_damage(attack->damage); + + if (def->is_pers_dead()) --team1_alive; + } + } + } + } +} \ No newline at end of file diff --git a/Source/TurnBasedTutorial/BasicTurnManager.h b/Source/TurnBasedTutorial/BasicTurnManager.h new file mode 100644 index 0000000..8bb9ce2 --- /dev/null +++ b/Source/TurnBasedTutorial/BasicTurnManager.h @@ -0,0 +1,81 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Math/UnrealMathUtility.h" +#include "Containers/Array.h" + +/** + * + */ + +namespace basic_api_classes { + + struct base_ability { + const double cost; + const double damage; + const double splash_radius; + const double linear_width; + const double max_activation_radius; + base_ability(double cost_, double damage_, double max_activation_radius_, double splash_radius_, double linear_width_); + bool is_pers_hurt(double attacker_x, double attacker_y, double activation_x, double activation_y, double defender_x, double defender_y); + ~base_ability(); + }; + + + struct base_personage { + private: + bool is_dead; + double x_coordinate; + double y_coordinate; + double hitpoints; + const double travel_cost; + public: + const TArray abilities; + base_personage(double x_, double y_, double hp, double trav_cost, TArray&& abils); + FVector2D get_personage_cords() const; + double get_hitpoints() const; + void move_to_position(double new_x, double new_y, double& rest_action_points); + void accept_damage(double damage); + bool is_attack_startable(size_t ability_number, double attack_pos_x, double attack_pos_y, double rest_action_points) const; + bool is_pers_dead() const; + ~base_personage(); + }; + + struct base_player { + const TArray team; + base_player(TArray&& team_); + ~base_player(); + }; + + + struct BasicTurnManager + { + private: + bool first_player_motion; + const base_player* player1; + const base_player* player2; + int motion_number; + const double action_points; + double current_player_action_points; + size_t team1_alive; + size_t team2_alive; + const double x_min; + const double x_max; + const double y_min; + const double y_max; + bool check_correctness(double x, double y) const; + public: + BasicTurnManager(base_player* player1_, base_player* player2_, double points_per_move, double x_min_, double x_max_, double y_min_, double y_max_); + void move_command(size_t pers_num, double new_x, double new_y); + void attack_command(size_t pers_num, size_t abil_num, double attack_x, double attack_y); + void next_move(); + int get_move_number() const; + bool is_first_player_move() const; + size_t first_team_alive() const; + size_t second_team_alive() const; + ~BasicTurnManager(); + }; + +}