LasTres/lib/LasTres/Battle.pm

167 lines
4.0 KiB
Perl

package LasTres::Battle;
use v5.36.0;
use strict;
use warnings;
use feature 'signatures';
use Moo;
use UUID::URandom qw/create_uuid_string/;
use LasTres::Util;
use LasTres::EnemyTeam;
use JSON qw//;
has uuid => (
is => 'rw',
default => \&_build_uuid,
);
has team1 => (
is => 'rw',
required => 1,
);
has team2 => ( is => 'rw', );
has last_frame => (
is => 'rw',
required => 1,
);
sub sanity_check ($self) {
my $team1 = $self->team1;
my $team2 = $self->team2;
if ( !defined $team2 ) {
return 0;
}
if ( !defined $team1->current_battle
|| !defined $team2->current_battle
|| $team1->current_battle ne $self->uuid
|| $team2->current_battle ne $self->uuid )
{
return 0;
}
return 1;
}
sub winner ($self) {
if ($self->team2->is_defeated) {
return $self->team1;
}
if ($self->team1->is_defeated) {
return $self->team2;
}
return;
}
sub try_turn ($self, $entity) {
my $combat_target = $entity->combat_target;
my $enemy_team = $self->get_enemy_team($entity->team);
my @combat_members_enemy = @{$enemy_team->combat_members};
@combat_members_enemy = grep { $_->health > 0 } @combat_members_enemy;
if ($entity->health <= 0) {
# This entity is out of the battle.
return;
}
if (defined $entity->combat_target) {{
my @target_list_only_one_should_match = grep { $combat_target eq $_->uuid } @combat_members_enemy;
if (!scalar @target_list_only_one_should_match) {
undef($combat_target);
next;
}
$combat_target = $target_list_only_one_should_match[0];
}}
if (!defined $combat_target) {
$combat_target = $combat_members_enemy[LasTres::Util::rand_range_int(0, $#combat_members_enemy)];
$entity->combat_target($combat_target->uuid);
$entity->update;
}
$entity->attack($combat_target);
$combat_target->update;
}
sub get_enemy_team ($self, $team) {
if ($self->team1->uuid ne $team->uuid) {
return $self->team1;
}
return $self->team2;
}
sub loser ($self) {
if ($self->team2->is_defeated) {
return $self->team2;
}
if ($self->team1->is_defeated) {
return $self->team1;
}
return;
}
sub end ($self) {
require LasTres::Redis;
my $redis = LasTres::Redis->new;
$self->team1->on_end_combat;
$self->team2->on_end_combat;
$self->team1->current_battle(undef);
$self->team1->update;
if ( defined $self->team2 ) {
$self->team2->current_battle(undef);
$self->team2->update;
}
$redis->db->expire( $redis->battle_key( $self->uuid ), 0 );
}
sub _build_uuid {
return create_uuid_string();
}
sub to_json ($self) {
return {
uuid => $self->uuid,
team1 => $self->team1->to_serializable,
team2 => $self->team2->to_serializable,
last_frame => $self->last_frame,
};
}
sub save_redis ($self) {
require LasTres::Redis;
my $redis = LasTres::Redis->new;
$redis->db->setex( $redis->battle_key( $self->uuid ),
3600 * 6, JSON::to_json($self->to_json));
}
sub get_redis ( $class, $uuid ) {
require LasTres::Redis;
my $redis = LasTres::Redis->new;
my $hash_self;
eval {
$hash_self = JSON::from_json($redis->db->get( $redis->battle_key($uuid) ));
};
if ($@) {
return;
}
return $class->from_json( $uuid, $hash_self );
}
sub from_json ( $class, $uuid, $hash ) {
# I do not take the hash uuid since if redis lies that could be really bad.
return $class->new(
uuid => $uuid,
team1 => $class->deserialize_team($hash->{team1}),
team2 => $class->deserialize_team($hash->{team2}),
last_frame => $hash->{last_frame},
);
}
sub deserialize_team ( $class, $team_hash ) {
if ( $team_hash->{is_db} ) {
return LasTres::Schema::Result::Team->from_serializable($team_hash);
}
return LasTres::EnemyTeam->from_serializable($team_hash);
}
1;