diff --git a/js-src/components/bottom-panel.tsx b/js-src/components/bottom-panel.tsx index 4747d8a..0a8e83f 100644 --- a/js-src/components/bottom-panel.tsx +++ b/js-src/components/bottom-panel.tsx @@ -11,7 +11,12 @@ export default function BottomPanel (): JSX.Element { return ( - hola + + + + + + ) diff --git a/js-src/components/game.tsx b/js-src/components/game.tsx index 4994a86..a005345 100644 --- a/js-src/components/game.tsx +++ b/js-src/components/game.tsx @@ -63,12 +63,15 @@ export default function Game (props: GameProps): JSX.Element { new OutputPacketInit(selectedPJ.uuid).send(webSocket) let interval: number = 0 interval = window.setInterval(() => { + if (webSocket.readyState === WebSocket.CONNECTING) { + return + } if (webSocket.readyState === WebSocket.OPEN) { new OutputPacketPing().send(webSocket) return } window.clearInterval(interval) - }, 250000) + }, 1000) } const inputPackets = new InputPackets(setTeamPJs, setEnemyTeamPJs, setIsBattling, @@ -91,7 +94,7 @@ export default function Game (props: GameProps): JSX.Element { } return websocket }) - }, 100) + }, 10) return ( <> } - return <>
+ const image = pj.health > 0 ? pj.image : '/img/skull.png' + return <>
} function printExperience (): JSX.Element { if (pj.experience_to_next_level_current === undefined || pj.experience_to_next_level_complete === undefined) { diff --git a/lib/LasTres/Area.pm b/lib/LasTres/Area.pm index 45777a3..60263a7 100644 --- a/lib/LasTres/Area.pm +++ b/lib/LasTres/Area.pm @@ -20,51 +20,72 @@ has children => ( ); ## OVERRIDE +# If true the entire map will be discovered when you step into the Area. sub get_auto_discover ($self) { return 0; } ## OVERRIDE +# The number of intervals of 10 seconds until you can reach +# other location. sub frames_to_move ($self) { return 5; } ## OVERRIDE +# The number of intervals of 10 seconds until you can +# possibly discover a new location when exploring. sub frames_to_explore ($self) { return 7; } ## OVERRIDE +# Whenever wild enemies will appear on explore or move. sub has_movement_auto_combat ($self) { return 0; } ## OVERRIDE +# The minimum number of enemies that will appear for every PJ +# when a battle is determined to take place on movement. +# Adjustable to the $pj, you should be careful with it being undef. sub min_enemies_per_head ($self, $pj = undef) { return 1; } ## OVERRIDE +# The maximum number of enemies that will appear for every PJ +# when a battle is determined to take place on movement. +# Adjustable to the $pj, you should be careful with it being undef. sub max_enemies_per_head ($self, $pj = undef) { return 1; } ## OVERRIDE +# The list of possible enemies on random encounter exploring or moving. +# You can adjust them to the level of the player using the $pj variable. +# Beware that this can be undef. sub list_of_enemies ( $self, $pj = undef ) { return []; } ## OVERRIDE +# The percentual chance of random combat encounter on movement or explore. sub chance_combat ($self) { return 50; } -## OVERRIDE (Always use $self->SUPER::on_move_explore_frame.) +## OVERRIDE (Always use $self->SUPER::on_move_explore_frame($self, $team).) +# What to on movement and explore frame. +# You can use this to make the user encounter drops for example, but if you +# do not call the SUPER function you will lose functionality. sub on_move_explore_frame ( $self, $team ) { return if $self->_try_to_start_battle($team); } sub _try_to_start_battle ( $self, $team ) { + require LasTres::Redis; + my $redis = LasTres::Redis->new; if ( !$self->has_movement_auto_combat ) { ## Combat not enabled. return 0; @@ -77,53 +98,27 @@ sub _try_to_start_battle ( $self, $team ) { ## Creating enemy team. my $battle = LasTres::Battle->new( team1 => $team, last_frame => 0 ); my $team2 = LasTres::EnemyTeam->new( current_battle => $battle->uuid ); - my @enemy_members; - $self->_generate_enemies_team($team2, \@enemy_members, $team); + my @enemy_members = @{$self->_generate_enemies_team($team)}; if ( !scalar @enemy_members ) { ## No enemies generated. return 0; } - $team2->members( \@enemy_members ); - $battle->team2($team2); - $battle->save_redis; - $team->current_battle( $battle->uuid ); - my @enemy_log_list; - my $first = 1; - for my $member ($team2->combat_members->@*) { - if (!$first) { - push @enemy_log_list, { text => ', ' }; - } - $first = 0; - push @enemy_log_list, { - color => 'red', - text => $member->nick, - }; - push @enemy_log_list, { - text => " NIVEL @{[$member->level]} VIDA @{[$member->health]}/@{[$member->max_health]}" - }; - } - for my $member ($team->members) { - $member->append_log_line([ - { - text => 'Empieza un combate contra: ' - }, - @enemy_log_list - ]); - } - $team->update; + LasTres::Battle->start_battle_machine($team, \@enemy_members); return 1; } -sub _generate_enemies_team ($self, $enemy_team, $enemy_members_array, $team) { +sub _generate_enemies_team ($self, $team) { + my @enemy_members_array; for my $pj ( @{$team->combat_members} ) { my $number_of_enemies = LasTres::Util::rand_range_int( $self->min_enemies_per_head($pj), $self->max_enemies_per_head($pj) ); - $self->_generate_n_enemies_pj( $enemy_team, $number_of_enemies, $enemy_members_array, $pj ); + $self->_generate_n_enemies_pj( $number_of_enemies, \@enemy_members_array, $pj ); } + return \@enemy_members_array; } -sub _generate_n_enemies_pj ( $self, $enemy_team, $number_of_enemies, +sub _generate_n_enemies_pj ( $self, $number_of_enemies, $enemy_members_array, $pj ) { my @list_possible_enemies = @{ $self->list_of_enemies($pj) }; @@ -135,11 +130,12 @@ sub _generate_n_enemies_pj ( $self, $enemy_team, $number_of_enemies, my $choice_enemy_index = LasTres::Util::rand_range_int( 0, $#list_possible_enemies ); my $choice_enemy = $list_possible_enemies[$choice_enemy_index]; - push @$enemy_members_array, $choice_enemy->generate($enemy_team); + push @$enemy_members_array, $choice_enemy; } } ## OVERRIDE +# Determines if the explore functionality is enabled for this area. sub can_explore { return 1; } diff --git a/lib/LasTres/Battle.pm b/lib/LasTres/Battle.pm index b4d52aa..90229cb 100644 --- a/lib/LasTres/Battle.pm +++ b/lib/LasTres/Battle.pm @@ -47,53 +47,58 @@ sub sanity_check ($self) { } sub winner ($self) { - if ($self->team2->is_defeated) { + if ( $self->team2->is_defeated ) { return $self->team1; } - if ($self->team1->is_defeated) { + 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}; +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) { + 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; + 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]; } - $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); + } + 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) { +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) { + if ( $self->team2->is_defeated ) { return $self->team2; } - if ($self->team1->is_defeated) { + if ( $self->team1->is_defeated ) { return $self->team1; } return; @@ -130,15 +135,16 @@ 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)); + 3600 * 6, JSON::to_json( $self->to_json ) ); } sub get_redis ( $class, $uuid ) { require LasTres::Redis; - my $redis = LasTres::Redis->new; + my $redis = LasTres::Redis->new; my $hash_self; eval { - $hash_self = JSON::from_json($redis->db->get( $redis->battle_key($uuid) )); + $hash_self = + JSON::from_json( $redis->db->get( $redis->battle_key($uuid) ) ); }; if ($@) { return; @@ -151,8 +157,8 @@ 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}), + team1 => $class->deserialize_team( $hash->{team1} ), + team2 => $class->deserialize_team( $hash->{team2} ), last_frame => $hash->{last_frame}, ); } @@ -163,4 +169,45 @@ sub deserialize_team ( $class, $team_hash ) { } return LasTres::EnemyTeam->from_serializable($team_hash); } + +sub start_battle_machine ( $class, $team, $enemy_area_array ) { + my @enemy_area_array = @$enemy_area_array; + my $battle = LasTres::Battle->new( team1 => $team, last_frame => 0 ); + my $team2 = LasTres::EnemyTeam->new( current_battle => $battle->uuid ); + my @enemies_array = ( map { $_->generate($team2) } @$enemy_area_array ); + my @enemy_log_list; + my $first_log = 1; + + $team2->members( \@enemies_array ); + $battle->team2($team2); + $battle->save_redis; + $team->current_battle( $battle->uuid ); + for my $member ( $team2->combat_members->@* ) { + if ( !$first_log ) { + push @enemy_log_list, { text => ', ' }; + } + $first_log = 0; + push @enemy_log_list, + { + color => 'red', + text => $member->nick, + }; + push @enemy_log_list, + { text => +" Nivel @{[$member->level]} Salud @{[$member->health]}/@{[$member->max_health]}" + }; + } + for my $member ( $team->members ) { + $member->append_log_line( + [ + { + text => 'Empieza un combate contra: ' + }, + @enemy_log_list + ] + ); + } + $team->update; + return $battle; +} 1; diff --git a/lib/LasTres/CombatCapableEntity.pm b/lib/LasTres/CombatCapableEntity.pm index 52a1c10..04d4554 100644 --- a/lib/LasTres/CombatCapableEntity.pm +++ b/lib/LasTres/CombatCapableEntity.pm @@ -14,8 +14,8 @@ use JSON qw/to_json from_json/; requires( 'uuid', 'race_string', 'nick', 'born_stats', 'health', 'mana', 'training_stats', 'experience', - 'combat_action', 'combat_target', 'team', 'update', - 'gain_experience', 'update_team_sprites' + 'combat_action', 'combat_target', 'team', + 'gain_experience', 'update_team_sprites', 'get_from_storage', ); sub append_log_line { @@ -34,6 +34,14 @@ sub race ($self) { return $race; } +## OVERRIDE (Call super) +sub update($self) { + $self = $self->get_from_storage; + if ( $self->health < 1 ) { + $self->on_faint; + } +} + sub attack ( $self, $enemy_entity ) { my $defense = $enemy_entity->resistance; my $attack = $self->strength; @@ -95,22 +103,11 @@ sub attack ( $self, $enemy_entity ) { ] ); } - if ( $enemy_entity->health == 0 ) { - $enemy_entity->on_faint($self); - } + $enemy_entity->update; } -sub on_faint($self, $attacker) { +sub on_faint($self) { my $team2 = $self->team; - my $team1 = $attacker->team; - for my $member ( $team1->combat_members->@* ) { - $member->append_log_line( - [ - { color => 'red', text => "@{[$self->nick]}" }, - { text => " se ha debilitado." }, - ] - ); - } for my $member ( $team2->combat_members->@* ) { $member->append_log_line( [ @@ -119,7 +116,21 @@ sub on_faint($self, $attacker) { ] ); } - $attacker->gain_experience((($self->race->experience_drop_base * $self->level)/7)*1.5); + my $battle = $team2->battle; + if (!defined $battle) { + return; + } + my $team1 = $battle->get_enemy_team($team2); + for my $member ( $team1->combat_members->@* ) { + $member->append_log_line( + [ + { color => 'red', text => "@{[$self->nick]}" }, + { text => " se ha debilitado." }, + ] + ); + $member->gain_experience((($self->race->experience_drop_base * $self->level)/7)); + } + } sub level ($self) { diff --git a/lib/LasTres/Controller/PJ.pm b/lib/LasTres/Controller/PJ.pm index 140a2cb..9c03292 100644 --- a/lib/LasTres/Controller/PJ.pm +++ b/lib/LasTres/Controller/PJ.pm @@ -152,7 +152,7 @@ sub _insert_new_player ( $self, $owner, $full_name, $short_name, $nick, $race ) intelligence => $self->_get_random_born_stat, }); $born_stats->insert; - my $training_stats = $schema->resultset->new({ + my $training_stats = $schema->resultset('Stats')->new({ uuid => $uuid_training_stats, health => 0, strength => 0, diff --git a/lib/LasTres/Enemy.pm b/lib/LasTres/Enemy.pm index e5ed32f..8dc7fa7 100644 --- a/lib/LasTres/Enemy.pm +++ b/lib/LasTres/Enemy.pm @@ -162,10 +162,6 @@ sub to_hash_display ($self) { sub gain_experience { } -sub update ($self) { - return $self; -} - sub to_hash ($self) { return { kind => 'NPCEnemy', @@ -192,5 +188,9 @@ sub from_hash ( $class, $hash ) { zmana => $hash->{mana}, ); } + +sub get_from_storage($self) { + return $self; +} with 'LasTres::RedisEnemy'; 1; diff --git a/lib/LasTres/EventLoop.pm b/lib/LasTres/EventLoop.pm index 0e10e17..afe6f44 100644 --- a/lib/LasTres/EventLoop.pm +++ b/lib/LasTres/EventLoop.pm @@ -96,7 +96,7 @@ sub _increment_frame_for_combat($self, $battle_uuid) { for my $entity (@combat_members) { $battle->try_turn($entity); if (my $winner = $battle->winner) { - next; + last; } $battle->save_redis; } diff --git a/lib/LasTres/Location.pm b/lib/LasTres/Location.pm index 9116847..0f355f7 100644 --- a/lib/LasTres/Location.pm +++ b/lib/LasTres/Location.pm @@ -15,39 +15,74 @@ use utf8; requires qw/identifier name description parent actions npcs/; +## Implement action($self, $pj); +## Implement npcs($self, $pj); +## Implement description($self, $pj = undef); +## Implement name($self, $pj = undef); +## Implement identifier($self, $pj = undef); + my $planets = LasTres::Planets->new; ## OVERRIDE +# Whenever a player can visit this place. +# The player to compute will always be the leader. sub can_visit ( $self, $pj ) { return 1; } ## OVERRIDE +# Whenever a player can discover this location with explore. +# The player will be always the leader. +# Alternative methods to explore will be able to discover this place +# for the pj. sub can_discover ( $self, $pj ) { return 1; } ## OVERRIDE +# The percentual chance to discover this place with explore. sub chance_discover ( $self, $pj ) { return 50; } ## OVERRIDE +# Whenever this can be the last discovery option in explore to let the +# player discover at least something. sub allow_forced_discovery ( $self, $pj ) { return 1; } ## OVERRIDE +# The order for the percentual random calculation, the higher the less priority +# it has for discover and the later it will be forcedfully discovered. sub order ($self) { return 1000; } ## OVERRIDE +# A place that is a spawn will have a healing action that can be changed +# and if a team faints they will be teleported there and the action will +# be triggered, the healing action may cost some resource when the action +# is triggered manually by the user, if the player cannot pay it the +# action may appear as disabled. sub is_spawn($self) { return 0; } +## OVERRIDE +# Return object should ideally extend LasTres::PJAction::DefaultHeal +# following the advice in this file. +sub healing_action($self) { + if ($self->is_spawn) { + require LasTres::PJAction::DefaultHeal; + return LasTres::PJAction::DefaultHeal->new; + } +} + ## OVERRIDE (Always use $self->SUPER::on_team_arrival.) +# The code to be executed when a team reachs this location. +# It is important that you call super or you will lose +# REALLY important behaviour such as knows_location. sub on_team_arrival ( $self, $team ) { $team = $team->get_from_storage; for my $pj ( $team->members ) { @@ -56,6 +91,9 @@ sub on_team_arrival ( $self, $team ) { } ## OVERRIDE (Always use $self->SUPER::on_pj_arrival.) +# The code to be executed when a pj reachs this location. +# Call super or bad things will happen such as losing +# knows_location and update-location. sub on_pj_arrival ( $self, $pj ) { require LasTres::Redis; $pj = $pj->get_from_storage; @@ -68,18 +106,20 @@ sub on_pj_arrival ( $self, $pj ) { to_json( { command => 'update-location' } ) ); } +## DO NOT EXTEND NOT SUPPORTED. sub show_intro ( $self, $pj ) { $pj->append_log_line( [ { text => 'Estas en ' }, - { color => 'red', text => $self->parent->name }, + { color => 'red', text => $self->parent->name($pj) }, { text => '/' }, - { color => 'green', text => $self->name }, + { color => 'green', text => $self->name($pj) }, ] ); $pj->append_log_line( [ { text => $pj->location->description }, ] ); } +## DO NOT EXTEND NOT SUPPORTED. sub move ( $self, $team ) { $team = $team->get_from_storage; my $current_location = $team->location; @@ -103,6 +143,8 @@ sub move ( $self, $team ) { } ## OVERRIDE (Always use $self->SUPER::on_team_moving.) +# This is called when a team starts their travel +# to this location, always call SUPER. sub on_team_moving ( $self, $team ) { $team = $team->get_from_storage; for my $pj ( $team->members ) { @@ -111,6 +153,9 @@ sub on_team_moving ( $self, $team ) { $team->send_frame_to_members; } +## OVERRIDE (Always use $self->SUPER::on_pj_moving.) +# This is called when a pj is approaching this location +# via move. It is really important to call super. sub on_pj_moving ( $self, $pj ) { require LasTres::Redis; my $redis = LasTres::Redis->new; @@ -118,15 +163,16 @@ sub on_pj_moving ( $self, $pj ) { $pj->append_log_line( [ { text => 'Tu equipo se está moviendo a ' }, - { color => 'red', text => $self->parent->name }, + { color => 'red', text => $self->parent->name($pj) }, { text => '/' }, - { color => 'green', text => $self->name }, + { color => 'green', text => $self->name($pj) }, ] ); $redis->publish( $redis->pj_subscription($pj), to_json( { command => 'update-location' } ) ); } +## DO NOT EXTEND NOT SUPPORTED. sub place_team ( $self, $team ) { $team = $team->get_from_storage; if ($self->is_spawn) { @@ -137,6 +183,7 @@ sub place_team ( $self, $team ) { $self->on_team_arrival($team); } +## DO NOT EXTEND NOT SUPPORTED. sub to_array ($self) { my $hash = $self->hash; return [ @@ -145,10 +192,12 @@ sub to_array ($self) { ]; } +## DO NOT EXTEND NOT SUPPORTED. sub to_json_array ($self) { return to_json( $self->to_array ); } +## DO NOT EXTEND NOT SUPPORTED. sub is_connected_by_move ( $self, $otherLocation, $pj = undef ) { if ( !defined $otherLocation ) { die '$otherLocation must be defined in is_connected.'; @@ -162,6 +211,7 @@ sub is_connected_by_move ( $self, $otherLocation, $pj = undef ) { return 0; } +## DO NOT EXTEND NOT SUPPORTED. sub get_available_locations_to_move_to ( $self, $pj = undef ) { if ( defined $pj ) { $pj = $pj->get_from_storage; @@ -185,6 +235,7 @@ sub get_available_locations_to_move_to ( $self, $pj = undef ) { return $connected_places; } +## DO NOT EXTEND NOT SUPPORTED. sub pj_is_moving ( $self, $pj = undef ) { if ( defined $pj ) { $pj = $pj->get_from_storage; @@ -192,6 +243,7 @@ sub pj_is_moving ( $self, $pj = undef ) { return defined $pj && $pj->team->is_moving; } +## DO NOT EXTEND NOT SUPPORTED. sub _get_neighbour_locations_accesible ( $self, $pj ) { my $places = []; @$places = @{ $self->parent->children }; @@ -202,6 +254,7 @@ sub _get_neighbour_locations_accesible ( $self, $pj ) { return $places; } +## DO NOT EXTEND NOT SUPPORTED. sub get ( $planet_id, $super_area_id, $area_id, $location_id ) { my $planet = $planets->hash->{$planet_id}; if ( !defined $planet ) { @@ -225,6 +278,7 @@ sub get ( $planet_id, $super_area_id, $area_id, $location_id ) { return $location; } +## DO NOT EXTEND NOT SUPPORTED. sub hash ($self) { my $location = $self; if ( !Moo::Role::does_role( $location, 'LasTres::Location' ) ) { diff --git a/lib/LasTres/PJAction/.exists b/lib/LasTres/PJAction/.exists new file mode 100644 index 0000000..e69de29 diff --git a/lib/LasTres/Planet/Bahdder.pm b/lib/LasTres/Planet/Bahdder.pm index 9396c2f..f987de7 100644 --- a/lib/LasTres/Planet/Bahdder.pm +++ b/lib/LasTres/Planet/Bahdder.pm @@ -15,37 +15,13 @@ use Module::Pluggable search_path => ['LasTres::Planet::Bahdder'], die $error; }; -has super_areas => ( - is => 'ro', - lazy => 1, - builder => \&_build_super_areas, -); - -has identifier => ( - is => 'ro', - lazy => 1, - builder => \&_build_identifier, -); - -has name => ( - is => 'ro', - lazy => 1, - builder => \&_build_name, -); - -has description => ( - is => 'ro', - lazy => 1, - builder => \&_build_description, -); - with 'LasTres::Planet'; -sub _build_identifier { +sub identifier { return 'bahdder', } -sub _build_super_areas { +sub super_areas { my $self = shift; my $hash = {}; my @super_areas = $self->plugins(); @@ -55,11 +31,11 @@ sub _build_super_areas { return $hash; } -sub _build_name { +sub name { return 'Bahdder'; } -sub _build_description { +sub description { return 'Archivo de la Patrulla Galáctica: Bahdder es uno de los planetas con mayor población de la galaxia con una población estimada ' . 'de tres mil millones de individuos pertenecientes a especies consideradas inteligentes. ' . 'Es conocido como el planeta origen de los Yaren; no obstante la presencia de los mismos en este planeta es actualmente simbólica. ' diff --git a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe.pm b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe.pm index 61d8b30..dbf539c 100644 --- a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe.pm +++ b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe.pm @@ -19,27 +19,6 @@ use Module::Pluggable search_path => ['LasTres::Planet::Bahdder::BosqueDelHeroe' use LasTres::Planet::Bahdder; -has areas => ( - is => 'ro', - builder => \&_build_areas, - lazy => 1, -); - -has identifier => ( - is => 'ro', - builder => \&_build_identifier, -); - -has name => ( - is => 'ro', - builder => \&_build_name, -); - -has description => ( - is => 'ro', - builder => \&_build_description, -); - has parent => ( is => 'ro', builder => \&_build_parent, @@ -47,11 +26,11 @@ has parent => ( with 'LasTres::SuperArea'; -sub _build_identifier { +sub identifier { return 'bosque_del_heroe'; } -sub _build_areas { +sub areas { my $self = shift; my $hash = {}; my @areas = $self->plugins(); @@ -61,11 +40,11 @@ sub _build_areas { return $hash; } -sub _build_name { +sub name { return 'Bosque del Héroe'; } -sub _build_description { +sub description { return 'El Bosque del Héroe es el pulmón del planeta Bahdder. ' . 'Se cree que solo una pequeña parte de las especies que viven en el mismo han sido catalogadas. ' . 'Los áldimor viven en este bosque en armonía con la naturaleza. ' diff --git a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI.pm b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI.pm index cd21e1a..d034d82 100644 --- a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI.pm +++ b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI.pm @@ -19,22 +19,6 @@ use Moo; use LasTres::Planet::Bahdder::BosqueDelHeroe; -has locations => ( - is => 'ro', - builder => \&_build_locations, - lazy => 1, -); - -has identifier => ( - is => 'ro', - builder => \&_build_identifier, -); - -has name => ( - is => 'ro', - builder => \&_build_name, -); - has parent => ( is => 'ro', builder => \&_build_parent, @@ -42,11 +26,11 @@ has parent => ( with 'LasTres::Area'; -sub _build_identifier { +sub identifier { return 'bosque_del_heroe_i'; } -sub _build_locations { +sub locations { my $self = shift; my $hash = {}; my @locations = $self->plugins(); @@ -56,7 +40,7 @@ sub _build_locations { return $hash; } -sub _build_name { +sub name { return 'Bosque del Héroe (I)'; } diff --git a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI/TribuDeLaLima.pm b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI/TribuDeLaLima.pm index cebe16d..bcfdf20 100644 --- a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI/TribuDeLaLima.pm +++ b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/BosqueDelHeroeI/TribuDeLaLima.pm @@ -10,61 +10,31 @@ use Moo; use LasTres::Planet::Bahdder::BosqueDelHeroe::BosqueDelHeroeI; -has identifier => ( - is => 'ro', - builder => \&_build_identifier, -); - -has name => ( - is => 'ro', - builder => \&_build_name, -); - -has description => ( - is => 'ro', - builder => \&_build_description, -); - -has parent => ( - is => 'ro', - builder => \&_build_parent, -); - -has actions => ( - is => 'ro', - builder => \&_build_actions, -); - -has npcs => ( - is => 'ro', - builder => \&_build_npcs, -); - with 'LasTres::Location'; -sub _build_identifier { +sub identifier { return 'tribu_de_la_lima'; } -sub _build_name { +sub name { return 'Tribu de la Lima (Exterior)'; } -sub _build_description { +sub description { return 'La Tribu de la Lima se siente como un hogar seas o no de aquí. ' . 'Las casitas están improvisadas con paja que los aldeanos intercambian con otras tribus. ' . 'Los cultivos de lima están siempre buscando trabajadores, el sueldo es una parte de lo cosechado. '; } -sub _build_parent { +sub parent { return LasTres::Planet::Bahdder::BosqueDelHeroe::BosqueDelHeroeI->instance; } -sub _build_actions { +sub actions { return []; } -sub _build_npcs { +sub npcs { return []; } diff --git a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/ArbolCentral.pm b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/ArbolCentral.pm index 5c9ac67..5be8f58 100644 --- a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/ArbolCentral.pm +++ b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/ArbolCentral.pm @@ -51,4 +51,8 @@ sub instance { } return $singleton; } + +sub is_spawn { + return 1; +} 1; diff --git a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/Entrada.pm b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/Entrada.pm index 2556e23..6f9a60f 100644 --- a/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/Entrada.pm +++ b/lib/LasTres/Planet/Bahdder/BosqueDelHeroe/TribuDeLaLima/Entrada.pm @@ -13,51 +13,26 @@ use Moo; use LasTres::Planet::Bahdder::BosqueDelHeroe::TribuDeLaLima; -has identifier => ( - is => 'ro', - builder => \&_build_identifier, -); - -has name => ( - is => 'ro', - builder => \&_build_name, -); - -has description => ( - is => 'ro', - builder => \&_build_description, -); - has parent => ( is => 'ro', builder => \&_build_parent, ); -has actions => ( - is => 'ro', - builder => \&_build_actions, -); - -has npcs => ( - is => 'ro', - builder => \&_build_npcs, -); - with 'LasTres::Location'; sub is_spawn { return 1; } -sub _build_identifier { +sub identifier { return 'entrada'; } -sub _build_name { +sub name { return 'Entrada'; } -sub _build_description { +sub description { return 'Un cartel reza. "Tribu de la Lima. Considerate bienvenido si ' . 'no eres un ladrón o un maleante, ' . 'en caso contrario recorre en sentido inverso el sendero de tus pisadas."'; @@ -67,11 +42,11 @@ sub _build_parent { return LasTres::Planet::Bahdder::BosqueDelHeroe::TribuDeLaLima->instance; } -sub _build_actions { +sub actions { return []; } -sub _build_npcs { +sub npcs { return []; } diff --git a/lib/LasTres/Race.pm b/lib/LasTres/Race.pm index c09cfc1..ed3e66b 100644 --- a/lib/LasTres/Race.pm +++ b/lib/LasTres/Race.pm @@ -9,15 +9,16 @@ use feature 'signatures'; use Moo::Role; -requires qw/spawn identifier name name_selection description is_playable base_stats experience_drop_base/; +requires + qw/spawn identifier name name_selection description is_playable base_stats experience_drop_base/; -sub hash($self) { +sub hash ($self) { return { - identifier => $self->identifier, - name => $self->name, + identifier => $self->identifier, + name => $self->name, name_selection => $self->name_selection, - description => $self->description, - is_playable => $self->is_playable, - } + description => $self->description, + is_playable => $self->is_playable, + }; } 1; diff --git a/lib/LasTres/Race/Aldimor.pm b/lib/LasTres/Race/Aldimor.pm index fc427a6..837cdd2 100644 --- a/lib/LasTres/Race/Aldimor.pm +++ b/lib/LasTres/Race/Aldimor.pm @@ -12,7 +12,7 @@ use Moo; use UUID::URandom qw/create_uuid_string/; use LasTres::Stats; -use LasTres::Planet::Bahdder::BosqueDelHeroe::BosqueDelHeroeI::TribuDeLaLima; +use LasTres::Planet::Bahdder::BosqueDelHeroe::TribuDeLaLima::ArbolCentral; has base_stats => ( is => 'ro', @@ -57,7 +57,7 @@ sub image { sub _build_spawn { return - LasTres::Planet::Bahdder::BosqueDelHeroe::BosqueDelHeroeI::TribuDeLaLima + LasTres::Planet::Bahdder::BosqueDelHeroe::TribuDeLaLima::ArbolCentral ->instance; } diff --git a/lib/LasTres/Schema/Result/PJ.pm b/lib/LasTres/Schema/Result/PJ.pm index 94858a1..dd95842 100644 --- a/lib/LasTres/Schema/Result/PJ.pm +++ b/lib/LasTres/Schema/Result/PJ.pm @@ -234,12 +234,21 @@ sub update_team_sprites ($self) { to_json( { command => 'update-team-sprites' } ) ); } +sub update ($self) { + $self->SUPER::update(); + if ( !defined $self->team->battle && $self->team->is_defeated ) { + + # Out of combat blackout. + $self->team->on_blackout(); + } +} + sub on_level_up ( $self, $old_level ) { my $old_experience = $self->experience; my $team = $self->team; my $enemy_team = $self->_enemy_team; $self = $self->get_from_storage; - $self->health($self->max_health); + $self->health( $self->max_health ); $self->update; for my $member ( $team->combat_members->@* ) { $member->update_team_sprites; @@ -299,6 +308,7 @@ sub gain_experience ( $self, $experience_to_gain ) { my $current_battle = $team->current_battle; $self->experience( $old_experience + $experience_to_gain ); $self->update; + for my $member ( $team->combat_members->@* ) { $member->append_log_line( [ @@ -453,5 +463,37 @@ sub mana { return $self->_mana; } +sub update_location ($self) { + require LasTres::Redis; + my $redis = LasTres::Redis->new; + $redis->publish( $redis->pj_subscription($self), + to_json( { command => 'update-location' } ) ); +} + +sub actions ($self) { + my @actions; + $self = $self->get_from_storage; + my $team = $self->team; + my $location = $team->location; + if ( defined $team->battle ) { + + # There should go the battle actions. + return; + } + if ( $team->is_moving ) { + + # Probably there should go the actions still doable when moving. + return; + } + + # TODO: Handle explore when implemented. + # These are static actions. + if ( $location->is_spawn ) { + push @actions, $location->healing_action; + } + my $location_actions = $location->actions($self); + @actions = ( @actions, @$location_actions ); + return \@actions; +} with 'LasTres::CombatCapableEntity'; 1; diff --git a/lib/LasTres/Schema/Result/Team.pm b/lib/LasTres/Schema/Result/Team.pm index 107799e..74ce178 100644 --- a/lib/LasTres/Schema/Result/Team.pm +++ b/lib/LasTres/Schema/Result/Team.pm @@ -4,6 +4,7 @@ use v5.36.0; use strict; use warnings; +use utf8; use parent 'DBIx::Class::Core'; @@ -81,7 +82,14 @@ __PACKAGE__->add_columns( }, ); +sub append_log_line ( $self, $line ) { + for my $member ( $self->combat_members->@* ) { + $member->append_log_line($line); + } +} + sub is_defeated ($self) { + $self = $self->get_from_storage; my @members = $self->members; my @alive_members = grep { $_->health > 0 } @members; if ( !scalar @alive_members ) { @@ -103,9 +111,19 @@ sub combat_members_serializable ( $self, $pj = undef ) { sub on_win_combat ($self) { } -sub on_lose_combat ($self) { +sub on_blackout ($self) { + for my $pj ( $self->members ) { + $pj->append_log_line( + [ + { + text => +'No queda nadie en el equipo que pueda luchar, volvéis al último punto de aparición.' + } + ] + ); + } require LasTres::Redis; - my $redis = LasTres::Redis->new; + my $redis = LasTres::Redis->new; my $last_spawn = $self->get_spawn; $last_spawn->place_team($self); $self->is_moving(0); @@ -117,10 +135,13 @@ sub on_lose_combat ($self) { } $self->update; for my $pj ( $self->members ) { - $redis->publish( $redis->pj_subscription($pj), - to_json( { command => 'update-team-sprites' } ) ); + $pj->update_team_sprites; + $pj->update_location; } +} +sub on_lose_combat ($self) { + $self->on_blackout; } sub update ($self) { @@ -188,7 +209,7 @@ sub combat_members ($self) { return [@members]; } -sub on_end_combat($self) { +sub on_end_combat ($self) { require LasTres::Redis; my $redis = LasTres::Redis->new; for my $pj ( $self->members ) { @@ -219,7 +240,6 @@ sub from_serializable ( $class, $hash ) { } __PACKAGE__->set_primary_key('uuid'); -__PACKAGE__->add_unique_constraint( u_name => ['name'] ); __PACKAGE__->has_many( 'members', 'LasTres::Schema::Result::PJ', 'team' ); __PACKAGE__->belongs_to( 'leader', 'LasTres::Schema::Result::PJ' ); diff --git a/public/img/skull.png b/public/img/skull.png new file mode 100644 index 0000000..92d5a34 Binary files /dev/null and b/public/img/skull.png differ diff --git a/public/js/bundle.js b/public/js/bundle.js index 7757dda..367282b 100644 --- a/public/js/bundle.js +++ b/public/js/bundle.js @@ -86,7 +86,7 @@ eval("\n\nif (false) {} else {\n module.exports = __webpack_require__(/*! ./cjs \********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ BottomPanel)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/presentation-item */ \"./js-src/components/presentation-item.tsx\");\n/* harmony import */ var _lastres_components_presentation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/presentation */ \"./js-src/components/presentation.tsx\");\n\n\n\nfunction BottomPanel() {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null, \"hola\")));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/bottom-panel.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ BottomPanel)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/presentation-item */ \"./js-src/components/presentation-item.tsx\");\n/* harmony import */ var _lastres_components_presentation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/presentation */ \"./js-src/components/presentation.tsx\");\n\n\n\nfunction BottomPanel() {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_presentation_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/bottom-panel.tsx?"); /***/ }), @@ -96,7 +96,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n/* harmony import */ var _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @lastres/output-packet/init */ \"./js-src/output-packet/init.ts\");\n/* harmony import */ var _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @lastres/output-packet/ping */ \"./js-src/output-packet/ping.ts\");\n/* harmony import */ var _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @lastres/input-packets */ \"./js-src/input-packets.ts\");\n\n\n\n\n\n\n\nfunction Game(props) {\n const selectedPJ = props.selectedPJ;\n if (selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n const [teamPJs, setTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [enemyTeamPJs, setEnemyTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [isBattling, setIsBattling] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [currentLocation, setCurrentLocation] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [connectedLocations, setConnectedLocations] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [logLines, setLogLines] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [error, setError] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [scrollLog, setScrollLog] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [movingTo, setMovingTo] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [remainingFrames, setRemainingFrames] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const logPresentationRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(null);\n const websocket = props.websocket;\n const setWebsocket = props.setWebsocket;\n window.setTimeout(() => {\n setWebsocket((websocket) => {\n if (websocket === null) {\n const locationProtocol = window.location.protocol;\n if (locationProtocol == null) {\n return null;\n }\n const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws';\n const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`);\n webSocket.onopen = () => {\n new _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__[\"default\"](selectedPJ.uuid).send(webSocket);\n let interval = 0;\n interval = window.setInterval(() => {\n if (webSocket.readyState === WebSocket.OPEN) {\n new _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__[\"default\"]().send(webSocket);\n return;\n }\n window.clearInterval(interval);\n }, 250000);\n };\n const inputPackets = new _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__[\"default\"](setTeamPJs, setEnemyTeamPJs, setIsBattling, setCurrentLocation, setConnectedLocations, logLines, setLogLines, setError, setScrollLog, logPresentationRef, setMovingTo, setRemainingFrames);\n webSocket.onmessage = (event) => {\n const packet = JSON.parse(event.data);\n inputPackets.handle(packet);\n };\n webSocket.onerror = (event) => {\n console.log(event);\n };\n webSocket.onclose = (event) => {\n console.log('Websocket closed');\n setWebsocket(null);\n };\n return webSocket;\n }\n return websocket;\n });\n }, 100);\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { teamPJs: teamPJs, enemyTeamPJs: enemyTeamPJs, isBattling: isBattling, currentLocation: currentLocation, connectedLocations: connectedLocations, logLines: logLines, websocket: websocket, logPresentationRef: logPresentationRef, movingTo: movingTo, remainingFrames: remainingFrames }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n/* harmony import */ var _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @lastres/output-packet/init */ \"./js-src/output-packet/init.ts\");\n/* harmony import */ var _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @lastres/output-packet/ping */ \"./js-src/output-packet/ping.ts\");\n/* harmony import */ var _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @lastres/input-packets */ \"./js-src/input-packets.ts\");\n\n\n\n\n\n\n\nfunction Game(props) {\n const selectedPJ = props.selectedPJ;\n if (selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n const [teamPJs, setTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [enemyTeamPJs, setEnemyTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [isBattling, setIsBattling] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [currentLocation, setCurrentLocation] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [connectedLocations, setConnectedLocations] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [logLines, setLogLines] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [error, setError] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [scrollLog, setScrollLog] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [movingTo, setMovingTo] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [remainingFrames, setRemainingFrames] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const logPresentationRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(null);\n const websocket = props.websocket;\n const setWebsocket = props.setWebsocket;\n window.setTimeout(() => {\n setWebsocket((websocket) => {\n if (websocket === null) {\n const locationProtocol = window.location.protocol;\n if (locationProtocol == null) {\n return null;\n }\n const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws';\n const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`);\n webSocket.onopen = () => {\n new _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__[\"default\"](selectedPJ.uuid).send(webSocket);\n let interval = 0;\n interval = window.setInterval(() => {\n if (webSocket.readyState === WebSocket.CONNECTING) {\n return;\n }\n if (webSocket.readyState === WebSocket.OPEN) {\n new _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__[\"default\"]().send(webSocket);\n return;\n }\n window.clearInterval(interval);\n }, 1000);\n };\n const inputPackets = new _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__[\"default\"](setTeamPJs, setEnemyTeamPJs, setIsBattling, setCurrentLocation, setConnectedLocations, logLines, setLogLines, setError, setScrollLog, logPresentationRef, setMovingTo, setRemainingFrames);\n webSocket.onmessage = (event) => {\n const packet = JSON.parse(event.data);\n inputPackets.handle(packet);\n };\n webSocket.onerror = (event) => {\n console.log(event);\n };\n webSocket.onclose = (event) => {\n console.log('Websocket closed');\n setWebsocket(null);\n };\n return webSocket;\n }\n return websocket;\n });\n }, 10);\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { teamPJs: teamPJs, enemyTeamPJs: enemyTeamPJs, isBattling: isBattling, currentLocation: currentLocation, connectedLocations: connectedLocations, logLines: logLines, websocket: websocket, logPresentationRef: logPresentationRef, movingTo: movingTo, remainingFrames: remainingFrames }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?"); /***/ }), @@ -156,7 +156,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJListItem)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-health-like-bar */ \"./js-src/components/pj-health-like-bar.tsx\");\n\n\nfunction PJListItem(props) {\n const pj = props.pj;\n function avatar() {\n if (pj.image === undefined) {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null);\n }\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"img\", { src: pj.image }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"shadow\" }));\n }\n function printExperience() {\n if (pj.experience_to_next_level_current === undefined || pj.experience_to_next_level_complete === undefined) {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null);\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n \"Experiencia: \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'red' } }, pj.experience_to_next_level_current),\n \"/\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'green' } }, pj.experience_to_next_level_complete)));\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-list-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"avatar\" }, avatar()),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"data\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n pj.nick,\n \" Nivel \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'red' } },\n pj.level,\n \".\")),\n printExperience(),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", { className: \"bar-container\" },\n \"Salud\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: pj.health, max: pj.max_health })),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", { className: \"bar-container\" },\n \"Mana\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: pj.mana, max: pj.max_mana })))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-list-item.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJListItem)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-health-like-bar */ \"./js-src/components/pj-health-like-bar.tsx\");\n\n\nfunction PJListItem(props) {\n const pj = props.pj;\n function avatar() {\n if (pj.image === undefined) {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null);\n }\n const image = pj.health > 0 ? pj.image : '/img/skull.png';\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"img\", { src: image }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"shadow\" }));\n }\n function printExperience() {\n if (pj.experience_to_next_level_current === undefined || pj.experience_to_next_level_complete === undefined) {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null);\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n \"Experiencia: \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'red' } }, pj.experience_to_next_level_current),\n \"/\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'green' } }, pj.experience_to_next_level_complete)));\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-list-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"avatar\" }, avatar()),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"data\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n pj.nick,\n \" Nivel \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { style: { color: 'red' } },\n pj.level,\n \".\")),\n printExperience(),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", { className: \"bar-container\" },\n \"Salud\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: pj.health, max: pj.max_health })),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", { className: \"bar-container\" },\n \"Mana\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: pj.mana, max: pj.max_mana })))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-list-item.tsx?"); /***/ }),