|
|
|
@ -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<base_ability*>&& 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<float>(x_coordinate), static_cast<float>(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<base_personage*>&& 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|