167 lines
4.0 KiB
Perl
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;
|