Addding initial support for listing enemies.
This commit is contained in:
parent
08f539bf42
commit
58c30c1059
@ -100,6 +100,7 @@ sub startup ($self) {
|
||||
$r->get('/conquer/teams')->to('ConquerTeam#getAll');
|
||||
$r->put('/conquer/node')->to('ConquerNode#create');
|
||||
$r->get('/conquer/node/near')->to('ConquerNode#nearbyNodes');
|
||||
$r->get('/conquer/user/enemies/global')->to('ConquerUserCurrentEnemy#listEnemiesGlobal');
|
||||
$r->get('/conquer/node/<uuid>')->to('ConquerNode#get');
|
||||
$r->post('/conquer/node/<uuid>/try-conquer')->to('ConquerNode#tryConquer');
|
||||
$r->get('/conquer/user')->to('UserConquer#get_self');
|
||||
|
103
lib/BurguillosInfo/Controller/ConquerUserCurrentEnemy.pm
Normal file
103
lib/BurguillosInfo/Controller/ConquerUserCurrentEnemy.pm
Normal file
@ -0,0 +1,103 @@
|
||||
package BurguillosInfo::Controller::ConquerUserCurrentEnemy;
|
||||
|
||||
use v5.34.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use utf8;
|
||||
|
||||
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
||||
|
||||
use UUID::URandom qw/create_uuid_string/;
|
||||
use JSON;
|
||||
|
||||
use BurguillosInfo::Schema;
|
||||
use BurguillosInfo::Species;
|
||||
|
||||
sub listEnemiesGlobal ($self) {
|
||||
my $user = $self->current_user;
|
||||
if ( !defined $user ) {
|
||||
return $self->render(
|
||||
status => 401,
|
||||
json => {
|
||||
error => 'Debes estar autenticado.',
|
||||
}
|
||||
);
|
||||
}
|
||||
my $current_enemies = $self->_get_enemies($user);
|
||||
if ( scalar @$current_enemies ) {
|
||||
return $self->_return_enemies($current_enemies);
|
||||
}
|
||||
$self->_generate_enemies_global($user);
|
||||
$current_enemies = $self->_get_enemies($user);
|
||||
return $self->_return_enemies($current_enemies);
|
||||
}
|
||||
|
||||
sub _return_enemies ( $self, $current_enemies ) {
|
||||
return $self->render( json => [ map { $_->serialize } @$current_enemies ] );
|
||||
}
|
||||
|
||||
sub _get_enemies ( $self, $user ) {
|
||||
my $resultset_current_enemies =
|
||||
BurguillosInfo::Schema->Schema->resultset('ConquerUserCurrentEnemy');
|
||||
my @current_enemies = $resultset_current_enemies->search(
|
||||
{
|
||||
'user_object.uuid' => $user->uuid,
|
||||
},
|
||||
{
|
||||
join => 'user_object',
|
||||
}
|
||||
);
|
||||
return \@current_enemies;
|
||||
}
|
||||
|
||||
sub _generate_enemies_global ( $self, $user ) {
|
||||
my $minimum_number_enemies = 2;
|
||||
my $maximum_number_enemies = 6;
|
||||
my $number_enemies =
|
||||
$self->_calculate_number_of_enemies( $minimum_number_enemies,
|
||||
$maximum_number_enemies );
|
||||
for ( my $i = 0 ; $i < $number_enemies ; $i++ ) {
|
||||
$self->_generate_enemy_global($user);
|
||||
}
|
||||
}
|
||||
|
||||
sub _generate_enemy_global ( $self, $user ) {
|
||||
my $resultset_current_enemies =
|
||||
BurguillosInfo::Schema->Schema->resultset('ConquerUserCurrentEnemy');
|
||||
my $uuid = create_uuid_string();
|
||||
my $species = BurguillosInfo::Species->new;
|
||||
my @species = @{ $species->list_can_be_global };
|
||||
my $selected_species = $species[int( rand( scalar @species ) )];
|
||||
my $enemy = $resultset_current_enemies->new(
|
||||
{
|
||||
uuid => $uuid,
|
||||
species => $selected_species->id,
|
||||
level => $self->_get_level_enemy($user),
|
||||
user => $user->uuid,
|
||||
}
|
||||
);
|
||||
$enemy->insert;
|
||||
}
|
||||
|
||||
sub _get_level_enemy ( $self, $user ) {
|
||||
my $max_enemy_level = int( $user->level / 2 ) + 1;
|
||||
if ( $max_enemy_level < $user->level - 10 ) {
|
||||
$max_enemy_level = $user->level - 10;
|
||||
}
|
||||
if ( $max_enemy_level < 3 ) {
|
||||
$max_enemy_level = 3;
|
||||
}
|
||||
my $min_enemy_level = $max_enemy_level - 5;
|
||||
if ( $min_enemy_level < 2 ) {
|
||||
$min_enemy_level = 2;
|
||||
}
|
||||
return $min_enemy_level +
|
||||
int( rand( $max_enemy_level - $min_enemy_level + 1 ) );
|
||||
}
|
||||
|
||||
sub _calculate_number_of_enemies ( $self, $min, $max ) {
|
||||
return $min + int( rand( $max - $min + 1 ) );
|
||||
}
|
||||
1;
|
@ -88,6 +88,17 @@ sub MIGRATIONS {
|
||||
'ALTER TABLE conquer_node ALTER COLUMN geometry SET NOT NULL;',
|
||||
'ALTER TABLE conquer_node DROP COLUMN coordinate_1;',
|
||||
'ALTER TABLE conquer_node DROP COLUMN coordinate_2;',
|
||||
'ALTER TABLE conquer_user ADD COLUMN experience INTEGER NOT NULL DEFAULT 125;',
|
||||
'ALTER TABLE conquer_user ADD COLUMN current_hp INTEGER NOT NULL DEFAULT 999;',
|
||||
'CREATE TABLE conquer_user_current_enemy (
|
||||
uuid UUID NOT NULL PRIMARY KEY,
|
||||
"user" UUID NOT NULL REFERENCES conquer_user(uuid),
|
||||
species INTEGER NOT NULL,
|
||||
is_battled BOOLEAN DEFAULT false,
|
||||
is_selected_to_battle BOOLEAN DEFAULT false,
|
||||
level INTEGER NOT NULL
|
||||
);',
|
||||
'ALTER TABLE conquer_user_current_enemy ALTER COLUMN species TYPE TEXT;',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,8 @@ sub Schema ($class) {
|
||||
shift->do('set timezone = UTC');
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
quote_char => '"',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -56,8 +56,72 @@ __PACKAGE__->add_columns(
|
||||
is_nullable => 0,
|
||||
default_value => \'0',
|
||||
},
|
||||
experience => {
|
||||
data_type => 'integer',
|
||||
is_nullable => 0,
|
||||
default_value => \'125',
|
||||
},
|
||||
current_hp => {
|
||||
data_type => 'integer',
|
||||
is_nullable => 0,
|
||||
default_value => \'999',
|
||||
}
|
||||
);
|
||||
|
||||
sub max_health($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return int(
|
||||
(($base * 2 + $born_value) * $self->level)
|
||||
/ 100 + $self->level + 10
|
||||
);
|
||||
}
|
||||
|
||||
sub level($self) {
|
||||
$self = $self->get_from_storage();
|
||||
return int($self->experience ** (1/3) + 0.0000000000001);
|
||||
}
|
||||
|
||||
sub attack($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return int(
|
||||
(($base * 2 + $self->level)*$self->level)
|
||||
/100
|
||||
);
|
||||
}
|
||||
|
||||
sub defense($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return int(
|
||||
(($base * 2 + $self->level)*$self->level)
|
||||
/100
|
||||
);
|
||||
}
|
||||
|
||||
sub health($self, $health = undef) {
|
||||
$self = $self->get_from_storage();
|
||||
my $hp = $self->current_hp;
|
||||
if ($hp > $self->max_health) {
|
||||
$self->current_hp($self->max_health);
|
||||
$self->update;
|
||||
$self = $self->get_from_storage();
|
||||
}
|
||||
if (defined $health) {
|
||||
if ($health > $self->max_health) {
|
||||
$health = $self->max_health;
|
||||
}
|
||||
$self->current_hp($health);
|
||||
$self->update;
|
||||
$self = $self->get_from_storage();
|
||||
}
|
||||
return $self->current_hp;
|
||||
}
|
||||
|
||||
sub coordinates ( $self, $coordinates = undef ) {
|
||||
if ( defined $coordinates ) {
|
||||
if ( ref $coordinates ne 'ARRAY' || scalar $coordinates->@* != 2 ) {
|
||||
|
101
lib/BurguillosInfo/Schema/Result/ConquerUserCurrentEnemy.pm
Normal file
101
lib/BurguillosInfo/Schema/Result/ConquerUserCurrentEnemy.pm
Normal file
@ -0,0 +1,101 @@
|
||||
package BurguillosInfo::Schema::Result::ConquerUserCurrentEnemy;
|
||||
|
||||
use v5.36.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent 'DBIx::Class::Core';
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use JSON;
|
||||
use BurguillosInfo::Species;
|
||||
|
||||
__PACKAGE__->table('conquer_user_current_enemy');
|
||||
__PACKAGE__->load_components("TimeStamp");
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
uuid => {
|
||||
data_type => 'uuid',
|
||||
is_nullable => 0,
|
||||
},
|
||||
user => {
|
||||
data_type => 'uuid',
|
||||
is_nullable => 0,
|
||||
},
|
||||
species => {
|
||||
data_type => 'text',
|
||||
is_nullable => 0,
|
||||
},
|
||||
is_selected_to_battle => {
|
||||
data_type => 'boolean',
|
||||
is_nullable => 0,
|
||||
default_value => \'false',
|
||||
},
|
||||
is_battled => {
|
||||
data_type => 'boolean',
|
||||
is_nullable => 0,
|
||||
default_value => \'false',
|
||||
},
|
||||
level => {
|
||||
data_type => 'integer',
|
||||
is_nullable => 0,
|
||||
},
|
||||
);
|
||||
|
||||
sub serialize ($self) {
|
||||
my $species = BurguillosInfo::Species->new;
|
||||
my $specie = $species->get( $self->species );
|
||||
return {
|
||||
uuid => $self->uuid,
|
||||
species => $specie->serialize,
|
||||
level => $self->level,
|
||||
max_health => $self->max_health,
|
||||
};
|
||||
}
|
||||
|
||||
sub max_health ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return
|
||||
int( ( ( $base * 2 + $born_value ) * $self->level ) / 100 +
|
||||
$self->level +
|
||||
10 );
|
||||
}
|
||||
|
||||
sub experience_drop ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
return int( $self->level / 7 * 179 );
|
||||
}
|
||||
|
||||
sub experience ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
return int( $self->level**(3) );
|
||||
}
|
||||
|
||||
sub attack ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return int( ( ( $base * 2 + $self->level ) * $self->level ) / 100 );
|
||||
}
|
||||
|
||||
sub defense ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
my $base = 50;
|
||||
my $born_value = 31;
|
||||
return int( ( ( $base * 2 + $self->level ) * $self->level ) / 100 );
|
||||
}
|
||||
|
||||
sub health ($self) {
|
||||
|
||||
# Combat result is decided from the start of battle.
|
||||
return $self->max_health;
|
||||
}
|
||||
|
||||
__PACKAGE__->set_primary_key('uuid');
|
||||
__PACKAGE__->belongs_to( 'user_object',
|
||||
'BurguillosInfo::Schema::Result::ConquerUser', 'user' );
|
||||
1;
|
24
lib/BurguillosInfo/Specie.pm
Normal file
24
lib/BurguillosInfo/Specie.pm
Normal file
@ -0,0 +1,24 @@
|
||||
package BurguillosInfo::Specie;
|
||||
|
||||
use v5.36.0;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use Moo::Role;
|
||||
|
||||
sub can_be_global {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub serialize ($self) {
|
||||
return {
|
||||
id => $self->id,
|
||||
name => $self->name,
|
||||
image => $self->image,
|
||||
};
|
||||
}
|
||||
|
||||
requires 'id name image';
|
||||
1;
|
58
lib/BurguillosInfo/Species.pm
Normal file
58
lib/BurguillosInfo/Species.pm
Normal file
@ -0,0 +1,58 @@
|
||||
package BurguillosInfo::Species;
|
||||
|
||||
use v5.36.0;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Moo;
|
||||
|
||||
use Module::Pluggable
|
||||
search_path => ['BurguillosInfo::Species'],
|
||||
instantiate => 'new',
|
||||
on_require_error => sub ( $plugin, $error ) {
|
||||
die $error;
|
||||
};
|
||||
|
||||
{
|
||||
my %hash_species;
|
||||
|
||||
sub _hash ($self) {
|
||||
if ( !scalar keys %hash_species ) {
|
||||
$self->_populate_hash;
|
||||
}
|
||||
return {%hash_species};
|
||||
}
|
||||
|
||||
sub _populate_hash ($self) {
|
||||
my @species = $self->plugins();
|
||||
print Data::Dumper::Dumper \@species;
|
||||
for my $specie (@species) {
|
||||
$self->_check_specie_valid($specie);
|
||||
if (exists $hash_species{$specie->id}) {
|
||||
die "Duplicated species id @{[$specie->id]}.";
|
||||
}
|
||||
$hash_species{$specie->id} = $specie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _check_specie_valid ( $self, $specie ) {
|
||||
if ( !$specie->does('BurguillosInfo::Specie') ) {
|
||||
die "$specie does not implement BurguillosInfo::Specie.";
|
||||
}
|
||||
}
|
||||
|
||||
sub get($self, $id) {
|
||||
return $self->_hash->{$id};
|
||||
}
|
||||
|
||||
sub list($self) {
|
||||
my @species_keys = keys %{$self->_hash};
|
||||
my $species = [ sort { $a->id cmp $b->id } map { $self->_hash->{$_} } @species_keys ];
|
||||
return $species;
|
||||
}
|
||||
|
||||
sub list_can_be_global($self) {
|
||||
return [ grep { $_->can_be_global } $self->list->@* ];
|
||||
}
|
||||
1;
|
28
lib/BurguillosInfo/Species/Murcielago.pm
Normal file
28
lib/BurguillosInfo/Species/Murcielago.pm
Normal file
@ -0,0 +1,28 @@
|
||||
package BurguillosInfo::Species::Murcielago;
|
||||
|
||||
use v5.34.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
||||
use Moo;
|
||||
|
||||
use parent 'BurguillosInfo::Specie';
|
||||
|
||||
sub id {
|
||||
return 'murcielago';
|
||||
}
|
||||
|
||||
sub name {
|
||||
return 'Murcielago';
|
||||
}
|
||||
|
||||
sub image {
|
||||
return '/img/conquer/species/murcielago.png';
|
||||
}
|
||||
|
||||
sub can_be_global {
|
||||
return 1;
|
||||
}
|
||||
1;
|
92
public/img/arrow-player-killed.svg
Normal file
92
public/img/arrow-player-killed.svg
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="180"
|
||||
height="180"
|
||||
viewBox="0 0 180 180"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="arrow-player-killed.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.1722222"
|
||||
inkscape:cx="114.39898"
|
||||
inkscape:cy="58.925831"
|
||||
inkscape:window-width="1499"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-x="26"
|
||||
inkscape:window-y="23"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer2" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Layer 3"
|
||||
style="stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:0.99906439">
|
||||
<ellipse
|
||||
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.22896;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path1514"
|
||||
cy="90"
|
||||
cx="90"
|
||||
rx="87.179558"
|
||||
ry="88.385521" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2"
|
||||
style="stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:0.99906439">
|
||||
<path
|
||||
style="display:inline;fill:#000000;fill-opacity:0.999064;stroke:none;stroke-width:3.42195;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.1872,145.48336 c -0.325678,6.59573 4.86944,13.81584 14.628956,9.61774 38.996707,-20.08168 63.312444,-21.05373 94.835564,1.87477 9.98034,4.08129 14.61469,-3.036 15.90751,-6.76847 C 153.79696,107.06667 118.11757,6.5875149 90,1.6144791 63.092475,7.5716541 26.88641,91.183358 27.1872,145.48336 Z"
|
||||
id="path1682"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.805;stroke-dasharray:none;stroke-opacity:0"
|
||||
d="m 109.99321,42.936903 5.25546,0.250702 -11.87761,18.116623 -5.190631,-0.233775 z"
|
||||
id="path16212"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.805;stroke-dasharray:none;stroke-opacity:0"
|
||||
d="m 98.180429,45.18702 4.515381,-0.518513 12.68756,15.571862 -5.93341,0.608601 z"
|
||||
id="path16538"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.805;stroke-dasharray:none;stroke-opacity:0"
|
||||
d="m 75.170413,42.936903 5.25546,0.250702 -11.87761,18.116623 -5.190631,-0.233775 z"
|
||||
id="path16212-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.805;stroke-dasharray:none;stroke-opacity:0"
|
||||
d="m 63.357632,45.18702 4.515381,-0.518513 12.68756,15.571862 -5.93341,0.608601 z"
|
||||
id="path16538-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.39555;stroke-dasharray:none;stroke-opacity:0.997527"
|
||||
d="m 60.222542,111.59197 2.432165,2.37521 7.776952,-12.17573 5.48651,12.67675 7.484611,-13.49323 6.616088,13.42642 5.917787,-12.95044 6.241525,15.681 7.16239,-16.32398 3.56976,17.01614 7.0569,-13.92744 -1.49286,-2.20634 -5.24564,9.43495 -3.04735,-15.193902 -7.75217,14.476702 -6.68575,-13.508063 -5.724592,11.749843 -6.278623,-12.941158 -7.663829,12.631268 -5.33589,-11.255318 z"
|
||||
id="path16739" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/img/conquer/species/murcielago.png
Normal file
BIN
public/img/conquer/species/murcielago.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 956 B |
BIN
public/img/missingicon.gif
Normal file
BIN
public/img/missingicon.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 B |
Loading…
Reference in New Issue
Block a user