diff --git a/bazaar/Tearel.pl b/bazaar/Tearel.pl index 6ea36c10..84e822c0 100644 --- a/bazaar/Tearel.pl +++ b/bazaar/Tearel.pl @@ -1,221 +1,11 @@ sub EVENT_SAY { - my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; - my $eom_link = quest::varlink(46779); - - my $bind_loc = $client->GetBucket("baz_and_back_bind") || 'bazaar'; - my $revind_text = ""; - - plugin::AddDefaultAttunement($client); - - if ($text=~/hail/i) { - if (!$group_flg) { - $group_flg = " However, that magic, like teleporting an entire group, will require [special reagents]." - } else { - $group_flg = "" - }; - - if (!($bind_loc eq $zonesn)) { - $rebind_text = " I see that you are not personally attuned to this location, though! Would you like to [".quest::saylink("attune your Bazaar and Back", 1)."] ability to return you here?"; - } else { - $rebind_text = ""; - } - - plugin::NPCTell("Greetings, $name. I am Tearel, the Keeper of the Map. I can [attune the map] to any rune circles you have previously discovered. If you are part of - [an expedition] I can also help you return to the heat of the battle.". $group_flg . $rebind_text); - - return; - } - - if ($text =~ /attune your Bazaar and Back/i) { - plugin::NPCTell("Excellent! You will now return to this vicinity whenever you use your Bazaar and Back ability!"); - $client->SetBucket("baz_and_back_bind", $zonesn); - return; - } - - if ($text =~ /attune the map/i) { - # Get eligible continent names - my @continent_names = get_eligible_continent_names($client); - - # Formulate a grammatically correct list - my $location_append = ""; - if (@continent_names == 1) { - $location_append = $continent_names[0]; - } elsif (@continent_names == 2) { - $location_append = $continent_names[0] . " or " . $continent_names[1]; - } elsif (@continent_names > 2) { - $location_append = join(', ', @continent_names[0..$#continent_names-1]) . ", or " . $continent_names[-1]; - } - - # NPC dialogue response - plugin::NPCTell("If you look closely, you'll see circles of rune-stones scattered throughout Norrath, and beyond. These serve as anchors for travel, and the map can be attuned to any of them. - Let's narrow down where you want to go? $location_append?"); - - return; - } - - if ($text=~/special reagents/i) { - if ($group_flg) { - plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); - } else { - plugin::NPCTell("If you can provide me with Five [".$eom_link."], I will [perform this ritual] for you."); - plugin::YellowText("Once unlocked, the group transport and instance return abilities will be available to all characters on this account."); - } - return; - } - - if ($text=~/perform this ritual/i) { - if ($group_flg) { - plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); - } else { - if (plugin::SpendEOM($client, 5)) { - quest::set_data($client->AccountID() ."-group-ports-enabled", 1); - plugin::NPCTell("$name, forevermore you and yours can transport your entire group to anywhere you have [attuned]."); - } else { - plugin::NPCTell("I'm sorry, $name, you do not have enough [".$eom_link."] available to you right now. When you have more..."); - } - } - } - - if ($text=~/an expedition/i || $text=~/instance/i) { - if ($group_flg) { - my $dz = $client->GetExpedition(); - if ($dz) { - plugin::NPCTell("I can sense that you are attuned to a particular time and place. I have attuned the map to it!"); - plugin::YellowText("The Magic Map has been attuned to your instance: ". $dz->GetName()); - $client->SetEntityVariable("magic_map_attune", 'instance'); - } else { - plugin::NPCTell("I do not sense any particular expedition affinity with you."); - } - } else { - plugin::NPCTell("Unfortunately, I will need some [special reagents] in order to transport you in this way."); - } - } - - my ($continent_pattern, $continent_map) = plugin::GetContinentCapturePattern(); - - if ($text =~ $continent_pattern) { - my $matched_continent = $1; # $1 contains the captured match - - if (exists $continent_map->{$matched_continent}) { - my $continent_id = $continent_map->{$matched_continent}; - my %waypoints = plugin::GetWaypoints($continent_id, $client); - - # Collect the long names for the waypoints with quest::saylink - my @waypoint_links; - foreach my $key (sort {$a cmp $b} keys %waypoints) { - if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { - my $long_name = $waypoints{$key}->[0]; # Get the long name - my $short_name = $key; # The key is the short name - push @waypoint_links, "[".quest::saylink($short_name, 0, $long_name)."]"; # Create a clickable link - } - } - - # Send each waypoint as a separate line - plugin::NPCTell("$matched_continent... Let's see... I can send you to a number of places there..."); - foreach my $link (@waypoint_links) { - plugin::PurpleText("---". $link); - } - } - } - - my ($waypoint_pattern, $eligible_waypoints) = plugin::GetWaypointCapturePattern(-1, $client); - if ($text =~ $waypoint_pattern) { - my $matched_waypoint_key = $1; # $1 contains the captured waypoint key (shortname), e.g., 'rivervale' - - if ($matched_waypoint_key) { - # Use the $eligible_waypoints hash to get the full waypoint data - my $waypoint_name = $eligible_waypoints->{$matched_waypoint_key}->[0]; # Get the long name for the matched waypoint - if (plugin::is_eligible_for_zone($client, $matched_waypoint_key, 1)) { - plugin::NPCTell("Perfect. I will attune the map to $waypoint_name, immediately!"); - plugin::YellowText("The Magic Map has been attuned to $waypoint_name!"); - $client->SetEntityVariable("magic_map_attune", $matched_waypoint_key); - } - } - } -} - -sub has_eligible_waypoints { - my ($continent_id, $client) = @_; - my %waypoints = plugin::GetWaypoints($continent_id, $client); - - foreach my $key (keys %waypoints) { - if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { - return 1; # Return true if at least one eligible waypoint is found - } - } - - return 0; # Return false if no eligible waypoints are found -} - -sub get_eligible_continent_names { - my ($client) = @_; - my @eligible_continent_names; - - foreach my $continent_id (sort { $a <=> $b } plugin::GetContinents($client)) { - if (has_eligible_waypoints($continent_id, $client)) { - push @eligible_continent_names, "[" . plugin::GetContinentName($continent_id) . "]"; - } - } - - return @eligible_continent_names; + plugin::HandleTeleporterSay(); } sub EVENT_ITEM { - plugin::return_items(\%itemcount); + plugin::return_items(\%itemcount); } sub EVENT_TICK { - return; # Disable this Feature - quest::debug("How did we get here?"); - my @clientlist = $entity_list->GetClientList(); - my $clientcount = @clientlist; - - my $max_idle_seconds = 60 * 15; # Set your max idle threshold here (e.g., 60 seconds) - my $idle_ticks = $max_idle_seconds / 6; - - my $warning_50_percent = int($idle_ticks * 0.5); - my $warning_80_percent = int($idle_ticks * 0.8); - - - foreach my $client (@clientlist) { - if (!$client || $client->IsTrader() || $client->GetGM()) { - next; - } - - my $last_x = int($client->GetEntityVariable("last_x") || 0); - my $last_y = int($client->GetEntityVariable("last_y") || 0); - my $last_h = int($client->GetEntityVariable("last_h") || 0); - - - my $cur_x = int($client->GetX()); - my $cur_y = int($client->GetY()); - my $cur_h = int($client->GetHeading()); - - if (defined $last_x && defined $last_y && defined $last_h) { - if ($last_x == $cur_x && $last_y == $cur_y && $last_h == $cur_h) { - my $idle_counter = $client->GetEntityVariable("idle_counter") // 0; - $idle_counter++; - - my $idle_seconds = $idle_counter * 6; - my $idle_minutes = sprintf("%.1f", $idle_seconds / 60); - my $max_idle_minutes = sprintf("%.1f", $max_idle_seconds / 60); - - if ($idle_counter == $warning_50_percent || $idle_counter == $warning_80_percent) { - $client->Message(15, "Warning: You have been idle for $idle_minutes minutes. You will be returned to character select in ". sprintf("%.1f", (($max_idle_seconds - $idle_seconds) / 60) ) . " minutes,"); - } - - if ($idle_counter >= $idle_ticks) { - $client->Kick(); - } - - $client->SetEntityVariable("idle_counter", $idle_counter); - } else { - $client->SetEntityVariable("idle_counter", 0); - } - } - - $client->SetEntityVariable("last_x", $cur_x); - $client->SetEntityVariable("last_y", $cur_y); - $client->SetEntityVariable("last_h", $cur_h); - } + plugin::HandleTeleporterTick(); } \ No newline at end of file diff --git a/bazaar/player.pl b/bazaar/player.pl deleted file mode 100644 index 39ac73da..00000000 --- a/bazaar/player.pl +++ /dev/null @@ -1,141 +0,0 @@ -sub EVENT_CLICKDOOR { - if ($doorid == 146) { # Magic Map - my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); - my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); - if ($waypoint_data || ($attuned_shortname eq 'instance' && $client->GetExpedition())) { - my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) - my $continent = $waypoint_data->[1]; # Access the continent ID - my $x = $waypoint_data->[2]; # X coordinate - my $y = $waypoint_data->[3]; # Y coordinate - my $z = $waypoint_data->[4]; # Z coordinate - my $heading = $waypoint_data->[5]; # Heading - - if ($attuned_shortname eq 'instance') { - $dz = $client->GetExpedition(); - $long_name = $dz->GetName(); - } - - my $popup_title = "Travel with the Magic Map"; - my $popup_text = "Would you like to travel to $long_name?"; - my $popup_self = 1460; - my $popup_group = 1461; - my $popup_btns = 2; - my $popup_btn_1 = "Self"; - my $popup_btn_2 = "Group"; - my $popup_dur = 30; - - $client->Popup2($popup_title, $popup_text, $popup_self, $popup_group, $popup_btns, $popup_dur, $popup_btn_1, $popup_btn_2); - } else { - plugin::YellowText("The Magic Map has not been attuned to you. Talk to Tearel to continue."); - } - } -} - -sub EVENT_POPUPRESPONSE { - if ($popupid == 1460 || $popupid == 1461) { - my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; - my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); - my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); - my $group = $client->GetGroup(); - my $dz = $client->GetExpedition(); - - # Group option locked behind EoM - if ($popupid == 1461 && !$group_flg) { - plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); - return; - } - - if ($attuned_shortname eq 'instance') { - if (!$group_flg) { - plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); - return; - } - - if (!$dz) { - plugin::YellowText("You are not a member of an expedition."); - return; - } - - if (!plugin::is_eligible_for_zone($client, quest::GetZoneShortName($dz->GetZoneID()))) { - plugin::YellowText("You are not eligible to enter that zone."); - return; - } - - if ($popupid == 1461 && $group) { - my $expedition_members_ref = $dz->GetMembers(); - my %expedition_members = %{$expedition_members_ref}; - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - # Check if the player is a member of the expedition - # TODO - Collect all failure modes and output at once instead of breaking on first one - my $player_name = $player->GetName(); - if (!exists $expedition_members{$player_name}) { - plugin::YellowText("$player_name is not a member of this expedition."); - return; - } - - if (!plugin::is_eligible_for_zone($player, quest::GetZoneShortName($dz->GetZoneID()))) { - plugin::YellowText("$player_name is not eligible to enter that zone."); - return; - } - } - } - - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - $player->SpellEffect(218,1); - $player->MovePCDynamicZone($dz->GetZoneID()); - } - } - } - - $client->SpellEffect(218,1); - $client->MovePCDynamicZone($dz->GetZoneID()); - } else { - # Not moving to a DZ - if (!$waypoint_data) { - plugin::YellowText("You have selected an invalid destination."); - return; - } - - my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) - my $continent = $waypoint_data->[1]; # Access the continent ID - my $x = $waypoint_data->[2]; # X coordinate - my $y = $waypoint_data->[3]; # Y coordinate - my $z = $waypoint_data->[4]; # Z coordinate - my $heading = $waypoint_data->[5]; # Heading - - if (!plugin::is_eligible_for_zone($client, $attuned_shortname)) { - plugin::YellowText("You are not eligible to enter that zone."); - return; - } - - if ($popupid == 1461 && $group) { - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - # TODO - Collect all failure modes and output at once instead of breaking on first one - my $player_name = $player->GetName(); - if (!plugin::is_eligible_for_zone($player, $attuned_shortname)) { - plugin::YellowText("$player_name is not eligible to enter that zone."); - return; - } - } - } - - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - $player->SpellEffect(218,1); - $player->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); - } - } - } - - $client->SpellEffect(218,1); - $client->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); - } - } -} \ No newline at end of file diff --git a/ecommons/Son_of_Tearel.pl b/ecommons/Son_of_Tearel.pl index 27242fc9..84e822c0 100644 --- a/ecommons/Son_of_Tearel.pl +++ b/ecommons/Son_of_Tearel.pl @@ -1,165 +1,11 @@ sub EVENT_SAY { - my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; - my $eom_link = quest::varlink(46779); - - my $bind_loc = $client->GetBucket("baz_and_back_bind") || 'bazaar'; - my $revind_text = ""; - - plugin::AddDefaultAttunement($client); - - if ($text=~/hail/i) { - if (!$group_flg) { - $group_flg = " However, that magic, like teleporting an entire group, will require [special reagents]." - } else { - $group_flg = "" - }; - - if (!($bind_loc eq $zonesn)) { - $rebind_text = " I see that you are not personally attuned to this location, though! Would you like to [".quest::saylink("attune your Bazaar and Back", 1)."] ability to return you here?"; - } else { - $rebind_text = ""; - } - - plugin::NPCTell("Greetings, $name. I am Timmy, Son of Tearel, the Keeper of the Other Map. I can [attune the map] to any rune circles you have previously discovered. If you are part of - [an expedition] I can also help you return to the heat of the battle.". $group_flg . $rebind_text); - - return; - } - - if ($text =~ /attune your Bazaar and Back/i) { - plugin::NPCTell("Excellent! You will now return to this vicinity whenever you use your Bazaar and Back ability!"); - $client->SetBucket("baz_and_back_bind", $zonesn); - return; - } - - if ($text =~ /attune the map/i) { - # Get eligible continent names - my @continent_names = get_eligible_continent_names($client); - - # Formulate a grammatically correct list - my $location_append = ""; - if (@continent_names == 1) { - $location_append = $continent_names[0]; - } elsif (@continent_names == 2) { - $location_append = $continent_names[0] . " or " . $continent_names[1]; - } elsif (@continent_names > 2) { - $location_append = join(', ', @continent_names[0..$#continent_names-1]) . ", or " . $continent_names[-1]; - } - - # NPC dialogue response - plugin::NPCTell("If you look closely, you'll see circles of rune-stones scattered throughout Norrath, and beyond. These serve as anchors for travel, and the map can be attuned to any of them. - Let's narrow down where you want to go? $location_append?"); - - return; - } - - if ($text=~/special reagents/i) { - if ($group_flg) { - plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); - } else { - plugin::NPCTell("If you can provide me with Five [".$eom_link."], I will [perform this ritual] for you."); - plugin::YellowText("Once unlocked, the group transport and instance return abilities will be available to all characters on this account."); - } - return; - } - - if ($text=~/perform this ritual/i) { - if ($group_flg) { - plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); - } else { - if (plugin::SpendEOM($client, 5)) { - quest::set_data($client->AccountID() ."-group-ports-enabled", 1); - plugin::NPCTell("$name, forevermore you and yours can transport your entire group to anywhere you have [attuned]."); - } else { - plugin::NPCTell("I'm sorry, $name, you do not have enough [".$eom_link."] available to you right now. When you have more..."); - } - } - } - - if ($text=~/an expedition/i || $text=~/instance/i) { - if ($group_flg) { - my $dz = $client->GetExpedition(); - if ($dz) { - plugin::NPCTell("I can sense that you are attuned to a particular time and place. I have attuned the map to it!"); - plugin::YellowText("The Magic Map has been attuned to your instance: ". $dz->GetName()); - $client->SetEntityVariable("magic_map_attune", 'instance'); - } else { - plugin::NPCTell("I do not sense any particular expedition affinity with you."); - } - } else { - plugin::NPCTell("Unfortunately, I will need some [special reagents] in order to transport you in this way."); - } - } - - my ($continent_pattern, $continent_map) = plugin::GetContinentCapturePattern(); - - if ($text =~ $continent_pattern) { - my $matched_continent = $1; # $1 contains the captured match - - if (exists $continent_map->{$matched_continent}) { - my $continent_id = $continent_map->{$matched_continent}; - my %waypoints = plugin::GetWaypoints($continent_id, $client); - - # Collect the long names for the waypoints with quest::saylink - my @waypoint_links; - foreach my $key (sort {$a cmp $b} keys %waypoints) { - if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { - my $long_name = $waypoints{$key}->[0]; # Get the long name - my $short_name = $key; # The key is the short name - push @waypoint_links, "[".quest::saylink($short_name, 0, $long_name)."]"; # Create a clickable link - } - } - - # Send each waypoint as a separate line - plugin::NPCTell("$matched_continent... Let's see... I can send you to a number of places there..."); - foreach my $link (@waypoint_links) { - plugin::PurpleText("---". $link); - } - } - } - - my ($waypoint_pattern, $eligible_waypoints) = plugin::GetWaypointCapturePattern(-1, $client); - if ($text =~ $waypoint_pattern) { - my $matched_waypoint_key = $1; # $1 contains the captured waypoint key (shortname), e.g., 'rivervale' - - if ($matched_waypoint_key) { - # Use the $eligible_waypoints hash to get the full waypoint data - my $waypoint_name = $eligible_waypoints->{$matched_waypoint_key}->[0]; # Get the long name for the matched waypoint - if (plugin::is_eligible_for_zone($client, $matched_waypoint_key, 1)) { - plugin::NPCTell("Perfect. I will attune the map to $waypoint_name, immediately!"); - plugin::YellowText("The Magic Map has been attuned to $waypoint_name!"); - $client->SetEntityVariable("magic_map_attune", $matched_waypoint_key); - } - } - } -} - -sub has_eligible_waypoints { - my ($continent_id, $client) = @_; - my %waypoints = plugin::GetWaypoints($continent_id, $client); - - foreach my $key (keys %waypoints) { - if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { - return 1; # Return true if at least one eligible waypoint is found - } - } - - return 0; # Return false if no eligible waypoints are found -} - -sub get_eligible_continent_names { - my ($client) = @_; - my @eligible_continent_names; - - foreach my $continent_id (sort { $a <=> $b } plugin::GetContinents($client)) { - if (has_eligible_waypoints($continent_id, $client)) { - push @eligible_continent_names, "[" . plugin::GetContinentName($continent_id) . "]"; - } - } - - return @eligible_continent_names; + plugin::HandleTeleporterSay(); } sub EVENT_ITEM { - plugin::return_items(\%itemcount); + plugin::return_items(\%itemcount); } + +sub EVENT_TICK { + plugin::HandleTeleporterTick(); +} \ No newline at end of file diff --git a/ecommons/player.pl b/ecommons/player.pl deleted file mode 100644 index 39ac73da..00000000 --- a/ecommons/player.pl +++ /dev/null @@ -1,141 +0,0 @@ -sub EVENT_CLICKDOOR { - if ($doorid == 146) { # Magic Map - my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); - my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); - if ($waypoint_data || ($attuned_shortname eq 'instance' && $client->GetExpedition())) { - my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) - my $continent = $waypoint_data->[1]; # Access the continent ID - my $x = $waypoint_data->[2]; # X coordinate - my $y = $waypoint_data->[3]; # Y coordinate - my $z = $waypoint_data->[4]; # Z coordinate - my $heading = $waypoint_data->[5]; # Heading - - if ($attuned_shortname eq 'instance') { - $dz = $client->GetExpedition(); - $long_name = $dz->GetName(); - } - - my $popup_title = "Travel with the Magic Map"; - my $popup_text = "Would you like to travel to $long_name?"; - my $popup_self = 1460; - my $popup_group = 1461; - my $popup_btns = 2; - my $popup_btn_1 = "Self"; - my $popup_btn_2 = "Group"; - my $popup_dur = 30; - - $client->Popup2($popup_title, $popup_text, $popup_self, $popup_group, $popup_btns, $popup_dur, $popup_btn_1, $popup_btn_2); - } else { - plugin::YellowText("The Magic Map has not been attuned to you. Talk to Tearel to continue."); - } - } -} - -sub EVENT_POPUPRESPONSE { - if ($popupid == 1460 || $popupid == 1461) { - my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; - my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); - my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); - my $group = $client->GetGroup(); - my $dz = $client->GetExpedition(); - - # Group option locked behind EoM - if ($popupid == 1461 && !$group_flg) { - plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); - return; - } - - if ($attuned_shortname eq 'instance') { - if (!$group_flg) { - plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); - return; - } - - if (!$dz) { - plugin::YellowText("You are not a member of an expedition."); - return; - } - - if (!plugin::is_eligible_for_zone($client, quest::GetZoneShortName($dz->GetZoneID()))) { - plugin::YellowText("You are not eligible to enter that zone."); - return; - } - - if ($popupid == 1461 && $group) { - my $expedition_members_ref = $dz->GetMembers(); - my %expedition_members = %{$expedition_members_ref}; - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - # Check if the player is a member of the expedition - # TODO - Collect all failure modes and output at once instead of breaking on first one - my $player_name = $player->GetName(); - if (!exists $expedition_members{$player_name}) { - plugin::YellowText("$player_name is not a member of this expedition."); - return; - } - - if (!plugin::is_eligible_for_zone($player, quest::GetZoneShortName($dz->GetZoneID()))) { - plugin::YellowText("$player_name is not eligible to enter that zone."); - return; - } - } - } - - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - $player->SpellEffect(218,1); - $player->MovePCDynamicZone($dz->GetZoneID()); - } - } - } - - $client->SpellEffect(218,1); - $client->MovePCDynamicZone($dz->GetZoneID()); - } else { - # Not moving to a DZ - if (!$waypoint_data) { - plugin::YellowText("You have selected an invalid destination."); - return; - } - - my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) - my $continent = $waypoint_data->[1]; # Access the continent ID - my $x = $waypoint_data->[2]; # X coordinate - my $y = $waypoint_data->[3]; # Y coordinate - my $z = $waypoint_data->[4]; # Z coordinate - my $heading = $waypoint_data->[5]; # Heading - - if (!plugin::is_eligible_for_zone($client, $attuned_shortname)) { - plugin::YellowText("You are not eligible to enter that zone."); - return; - } - - if ($popupid == 1461 && $group) { - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - # TODO - Collect all failure modes and output at once instead of breaking on first one - my $player_name = $player->GetName(); - if (!plugin::is_eligible_for_zone($player, $attuned_shortname)) { - plugin::YellowText("$player_name is not eligible to enter that zone."); - return; - } - } - } - - for (my $count = 0; $count < $group->GroupCount(); $count++) { - my $player = $group->GetMember($count); - if ($player) { - $player->SpellEffect(218,1); - $player->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); - } - } - } - - $client->SpellEffect(218,1); - $client->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); - } - } -} \ No newline at end of file diff --git a/global/global_player.pl b/global/global_player.pl index 11a23f88..5526ab55 100644 --- a/global/global_player.pl +++ b/global/global_player.pl @@ -1,21 +1,21 @@ sub EVENT_SIGNAL { - # Signals; - # 666 = EoM Dead Drop - # 100 = Title Flags - - if ($signal == 666) { - plugin::UpdateEoMAward($client); - return; - } - - if ($signal == 100) { - my $semaphore_title = $client->GetBucket('flag-semaphore'); - if ($semaphore_title) { - plugin::AddTitleFlag($semaphore_title, $client); - $client->DeleteBucket('flag-semaphore'); - } - plugin::EnableTitles($client); - } + # Signals; + # 666 = EoM Dead Drop + # 100 = Title Flags + + if ($signal == 666) { + plugin::UpdateEoMAward($client); + return; + } + + if ($signal == 100) { + my $semaphore_title = $client->GetBucket('flag-semaphore'); + if ($semaphore_title) { + plugin::AddTitleFlag($semaphore_title, $client); + $client->DeleteBucket('flag-semaphore'); + } + plugin::EnableTitles($client); + } } #test commit please ignore @@ -26,246 +26,382 @@ sub EVENT_ENTERZONE { if (!plugin::is_eligible_for_zone($client, $zonesn)) { $client->Message(4, "Your vision blurs. You lose conciousness and wake up in a familiar place."); $client->MovePC(151, 185, -835, 4, 390); # Bazaar Safe Location. - } - - # Only THJ Stuff after this point - if (!plugin::IsTHJ()) { - return; - } - - if (!$client->IsTaskCompleted(3) && !$client->IsTaskActive(3)) { - $client->AssignTask(3); - } elsif ($client->IsTaskCompleted(3) && (!$client->IsTaskCompleted(4) && !$client->IsTaskActive(4))) { - $client->AssignTask(4); - } - - my $entity_list = plugin::val('$entity_list'); - my @npcs = $entity_list->GetNPCList(); - if (plugin::IsTHJ() && $instanceid) { - foreach my $npc (@npcs) { - my $expedition = quest::get_expedition(); - if ($expedition) { - plugin::ScaleInstanceNPC($npc, $expedition->GetMemberCount()); - } - } - } + } + + # Only THJ Stuff after this point + if (!plugin::IsTHJ()) { + return; + } + + if (!$client->IsTaskCompleted(3) && !$client->IsTaskActive(3)) { + $client->AssignTask(3); + } elsif ($client->IsTaskCompleted(3) && (!$client->IsTaskCompleted(4) && !$client->IsTaskActive(4))) { + $client->AssignTask(4); + } + + my $entity_list = plugin::val('$entity_list'); + my @npcs = $entity_list->GetNPCList(); + if (plugin::IsTHJ() && $instanceid) { + foreach my $npc (@npcs) { + my $expedition = quest::get_expedition(); + if ($expedition) { + plugin::ScaleInstanceNPC($npc, $expedition->GetMemberCount()); + } + } + } } sub EVENT_EQUIP_ITEM_CLIENT { - if ($slot_id == 21) { - # Simple Ring of the Hero, for Tutorial Quest 2 - if ($client->IsTaskActivityActive(4, 0) && $item_id == 150000) { - $client->UpdateTaskActivity(4, 0, 1); - return; - } - if ($client->IsTaskActivityActive(4, 1) && $item_id == 1150000) { - $client->UpdateTaskActivity(4, 01, 1); - return; - } - if ($client->IsTaskActivityActive(4, 2) && $item_id == 2150000) { - $client->UpdateTaskActivity(4, 2, 1); - return; - } - if ($item_id == 2150000) { - plugin::dispatch_popup("symp_tutorial"); - } { - plugin::dispatch_popup("power_source"); - } - } - - symp_proc_tutorial_helper($item_id, $client); + if ($slot_id == 21) { + # Simple Ring of the Hero, for Tutorial Quest 2 + if ($client->IsTaskActivityActive(4, 0) && $item_id == 150000) { + $client->UpdateTaskActivity(4, 0, 1); + return; + } + if ($client->IsTaskActivityActive(4, 1) && $item_id == 1150000) { + $client->UpdateTaskActivity(4, 01, 1); + return; + } + if ($client->IsTaskActivityActive(4, 2) && $item_id == 2150000) { + $client->UpdateTaskActivity(4, 2, 1); + return; + } + if ($item_id == 2150000) { + plugin::dispatch_popup("symp_tutorial"); + } { + plugin::dispatch_popup("power_source"); + } + } + + symp_proc_tutorial_helper($item_id, $client); } sub EVENT_DESTROY_ITEM_CLIENT { - if ($item_id == 2827) { - my $account_key = $client->AccountID() . "-ess-items-destroyed"; - quest::set_data($account_key, (quest::get_data($account_key) || 0) + 1); - } + if ($item_id == 2827) { + my $account_key = $client->AccountID() . "-ess-items-destroyed"; + quest::set_data($account_key, (quest::get_data($account_key) || 0) + 1); + } } sub EVENT_CONNECT { - if (plugin::GetSoulmark($client)) { - plugin::DisplayWarning($client); - } + if (plugin::GetSoulmark($client)) { + plugin::DisplayWarning($client); + } - plugin::CommonCharacterUpdate($client); + plugin::CommonCharacterUpdate($client); - if (!$client->GetBucket("First-Login")) { - $client->SetBucket("First-Login", 1); + if (!$client->GetBucket("First-Login")) { + $client->SetBucket("First-Login", 1); $client->SummonItem(18471); #A Faded Writ - $client->Message(263, "You find a small note in your pocket."); + $client->Message(263, "You find a small note in your pocket."); $client->SetBucket('FirstLogin', 1); - my $name = $client->GetCleanName(); - my $full_class_name = plugin::GetPrettyClassString($client); + my $name = $client->GetCleanName(); + my $full_class_name = plugin::GetPrettyClassString($client); - plugin::WorldAnnounce("$name ($full_class_name) has logged in for the first time."); - plugin::AwardSeasonalItems($client); - } + plugin::WorldAnnounce("$name ($full_class_name) has logged in for the first time."); + plugin::AwardSeasonalItems($client); + } - if (plugin::MultiClassingEnabled()) { - if (!$client->IsTaskCompleted(3) && !$client->IsTaskActive(3)) { - $client->AssignTask(3); - } elsif ($client->IsTaskCompleted(3) && (!$client->IsTaskCompleted(4) && !$client->IsTaskActive(4))) { - $client->AssignTask(4); - } + if (plugin::MultiClassingEnabled()) { + if (!$client->IsTaskCompleted(3) && !$client->IsTaskActive(3)) { + $client->AssignTask(3); + } elsif ($client->IsTaskCompleted(3) && (!$client->IsTaskCompleted(4) && !$client->IsTaskActive(4))) { + $client->AssignTask(4); + } - plugin::dispatch_popup("welcome"); - } + plugin::dispatch_popup("welcome"); + } - if (!plugin::is_eligible_for_zone($client, $zonesn)) { + if (!plugin::is_eligible_for_zone($client, $zonesn)) { $client->Message(4, "Your vision blurs. You lose conciousness and wake up in a familiar place."); $client->MovePC(151, 185, -835, 4, 390); # Bazaar Safe Location. } } sub EVENT_DISCONNECT { - # Removes invulnerability effects when disconnecting from the server. - $client->BuffFadeByEffect(40); + # Removes invulnerability effects when disconnecting from the server. + $client->BuffFadeByEffect(40); } sub EVENT_POPUPRESPONSE { - plugin::check_tutorial_popup_response($popupid, $client); - - if ($popupid == 58240) { - my $x = $client->GetEntityVariable("bazaar_x") + int(rand(11)) - 5; - my $y = $client->GetEntityVariable("bazaar_y") + int(rand(11)) - 5; - my $z = $client->GetEntityVariable("bazaar_z"); - my $h = $client->GetEntityVariable("bazaar_h"); - my $bind_loc = $client->GetEntityVariable("bazaar_zone"); - - $client->SetBucket("Return-X", $client->GetX()); - $client->SetBucket("Return-Y", $client->GetY()); - $client->SetBucket("Return-Z", $client->GetZ()); - $client->SetBucket("Return-H", $client->GetHeading()); - $client->SetBucket("Return-Zone", $zoneid); - $client->SetBucket("Return-Instance", $instanceid); - - $client->SpellEffect(218,1); - $client->MovePC($bind_loc, $x, $y, $z, rand(512)); - } + plugin::check_tutorial_popup_response($popupid, $client); + + if ($popupid == 58240) { + my $x = $client->GetEntityVariable("bazaar_x") + int(rand(11)) - 5; + my $y = $client->GetEntityVariable("bazaar_y") + int(rand(11)) - 5; + my $z = $client->GetEntityVariable("bazaar_z"); + my $h = $client->GetEntityVariable("bazaar_h"); + my $bind_loc = $client->GetEntityVariable("bazaar_zone"); + + $client->SetBucket("Return-X", $client->GetX()); + $client->SetBucket("Return-Y", $client->GetY()); + $client->SetBucket("Return-Z", $client->GetZ()); + $client->SetBucket("Return-H", $client->GetHeading()); + $client->SetBucket("Return-Zone", $zoneid); + $client->SetBucket("Return-Instance", $instanceid); + + $client->SpellEffect(218,1); + $client->MovePC($bind_loc, $x, $y, $z, rand(512)); + } elsif ($popupid == 1460 || $popupid == 1461) { + my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; + my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); + my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); + my $group = $client->GetGroup(); + my $dz = $client->GetExpedition(); + + # Group option locked behind EoM + if ($popupid == 1461 && !$group_flg) { + plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); + return; + } + + if ($attuned_shortname eq 'instance') { + if (!$group_flg) { + plugin::YellowText("Your account does not have the ability to transport your group this way unlocked."); + return; + } + + if (!$dz) { + plugin::YellowText("You are not a member of an expedition."); + return; + } + + if (!plugin::is_eligible_for_zone($client, quest::GetZoneShortName($dz->GetZoneID()))) { + plugin::YellowText("You are not eligible to enter that zone."); + return; + } + + if ($popupid == 1461 && $group) { + my $expedition_members_ref = $dz->GetMembers(); + my %expedition_members = %{$expedition_members_ref}; + for (my $count = 0; $count < $group->GroupCount(); $count++) { + my $player = $group->GetMember($count); + if ($player) { + # Check if the player is a member of the expedition + # TODO - Collect all failure modes and output at once instead of breaking on first one + my $player_name = $player->GetName(); + if (!exists $expedition_members{$player_name}) { + plugin::YellowText("$player_name is not a member of this expedition."); + return; + } + + if (!plugin::is_eligible_for_zone($player, quest::GetZoneShortName($dz->GetZoneID()))) { + plugin::YellowText("$player_name is not eligible to enter that zone."); + return; + } + } + } + + for (my $count = 0; $count < $group->GroupCount(); $count++) { + my $player = $group->GetMember($count); + if ($player) { + $player->SpellEffect(218,1); + $player->MovePCDynamicZone($dz->GetZoneID()); + } + } + } + + $client->SpellEffect(218,1); + $client->MovePCDynamicZone($dz->GetZoneID()); + } else { + # Not moving to a DZ + if (!$waypoint_data) { + plugin::YellowText("You have selected an invalid destination."); + return; + } + + my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) + my $continent = $waypoint_data->[1]; # Access the continent ID + my $x = $waypoint_data->[2]; # X coordinate + my $y = $waypoint_data->[3]; # Y coordinate + my $z = $waypoint_data->[4]; # Z coordinate + my $heading = $waypoint_data->[5]; # Heading + + if (!plugin::is_eligible_for_zone($client, $attuned_shortname)) { + plugin::YellowText("You are not eligible to enter that zone."); + return; + } + + if ($popupid == 1461 && $group) { + for (my $count = 0; $count < $group->GroupCount(); $count++) { + my $player = $group->GetMember($count); + if ($player) { + # TODO - Collect all failure modes and output at once instead of breaking on first one + my $player_name = $player->GetName(); + if (!plugin::is_eligible_for_zone($player, $attuned_shortname)) { + plugin::YellowText("$player_name is not eligible to enter that zone."); + return; + } + } + } + + for (my $count = 0; $count < $group->GroupCount(); $count++) { + my $player = $group->GetMember($count); + if ($player) { + $player->SpellEffect(218,1); + $player->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); + } + } + } + + $client->SpellEffect(218,1); + $client->MovePC(quest::GetZoneID($attuned_shortname), $x, $y, $z, $heading); + } + } } sub EVENT_TASK_COMPLETE { - if ($task_id == 3 && !$client->IsTaskCompleted(4)) { - $client->AssignTask(4); - } + if ($task_id == 3 && !$client->IsTaskCompleted(4)) { + $client->AssignTask(4); + } } sub EVENT_LEVEL_UP { - plugin::CommonCharacterUpdate($client); + plugin::CommonCharacterUpdate($client); - if ($client->GetGM()) { - return; - } - - my $new_level = $client->GetLevel(); - if (($new_level % 10 == 0) || $new_level == 5 || $new_level == $client->GetBucket("CharMaxLevel")) { - my $name = $client->GetCleanName(); - my $full_class_name = plugin::GetPrettyClassString($client); + if ($client->GetGM()) { + return; + } + + my $new_level = $client->GetLevel(); + if (($new_level % 10 == 0) || $new_level == 5 || $new_level == $client->GetBucket("CharMaxLevel")) { + my $name = $client->GetCleanName(); + my $full_class_name = plugin::GetPrettyClassString($client); - my $capped = ($new_level == ($client->GetBucket("CharMaxLevel") || 0) ? " (Level Cap)" : ""); + my $capped = ($new_level == ($client->GetBucket("CharMaxLevel") || 0) ? " (Level Cap)" : ""); - plugin::WorldAnnounce("$name ($full_class_name) has reached Level $new_level$capped."); - } + plugin::WorldAnnounce("$name ($full_class_name) has reached Level $new_level$capped."); + } } sub EVENT_CLICKDOOR { my $target_zone = plugin::get_target_door_zone($zonesn, $doorid, $version); - if (!plugin::is_eligible_for_zone($client, $target_zone, 1)) { + if (!plugin::is_eligible_for_zone($client, $target_zone, 1)) { return 1; - } + } + + if ($doorid == 146 && ($zonesn eq "bazaar" || $zonesn eq "ecommons")) { # Magic Map + my $attuned_shortname = $client->GetEntityVariable("magic_map_attune"); + my $waypoint_data = plugin::GetWaypoint($attuned_shortname, $client); + if ($waypoint_data || ($attuned_shortname eq 'instance' && $client->GetExpedition())) { + my $long_name = $waypoint_data->[0]; # Access the long name (first element in the array) + my $continent = $waypoint_data->[1]; # Access the continent ID + my $x = $waypoint_data->[2]; # X coordinate + my $y = $waypoint_data->[3]; # Y coordinate + my $z = $waypoint_data->[4]; # Z coordinate + my $heading = $waypoint_data->[5]; # Heading + + if ($attuned_shortname eq "instance") { + $dz = $client->GetExpedition(); + $long_name = $dz->GetName(); + } + + my $popup_title = "Travel with the Magic Map"; + my $popup_text = "Would you like to travel to $long_name?"; + my $popup_self = 1460; + my $popup_group = 1461; + my $popup_btns = 2; + my $popup_btn_1 = "Self"; + my $popup_btn_2 = "Group"; + my $popup_dur = 30; + + $client->Popup2($popup_title, $popup_text, $popup_self, $popup_group, $popup_btns, $popup_dur, $popup_btn_1, $popup_btn_2); + } else { + plugin::YellowText("The Magic Map has not been attuned to you. Talk to Tearel to continue."); + } + } } sub EVENT_WARP { - my $name = $client->GetCleanName(); - my $current_x = $client->GetX(); - my $current_y = $client->GetY(); - my $current_z = $client->GetZ(); - my $distance = sqrt(($current_x - $from_x) ** 2 + ($current_y - $from_y) ** 2 + ($current_z - $from_z) ** 2); - my $account_key = $client->AccountID() . "-WarpCount"; - my $soulmark = quest::get_data($client->AccountID() . "-CheaterFlag"); + my $name = $client->GetCleanName(); + my $current_x = $client->GetX(); + my $current_y = $client->GetY(); + my $current_z = $client->GetZ(); + my $distance = sqrt(($current_x - $from_x) ** 2 + ($current_y - $from_y) ** 2 + ($current_z - $from_z) ** 2); + my $account_key = $client->AccountID() . "-WarpCount"; + my $soulmark = quest::get_data($client->AccountID() . "-CheaterFlag"); - my @warp_events = plugin::DeserializeList(quest::get_data($account_key)); + my @warp_events = plugin::DeserializeList(quest::get_data($account_key)); - # Enqueue the current warp event with timestamp - push @warp_events, time(); + # Enqueue the current warp event with timestamp + push @warp_events, time(); - # Clean up array elements older than 30 days - my $thirty_days_in_seconds = 30 * 24 * 60 * 60; - @warp_events = grep { time() - $_ <= $thirty_days_in_seconds } @warp_events; + # Clean up array elements older than 30 days + my $thirty_days_in_seconds = 30 * 24 * 60 * 60; + @warp_events = grep { time() - $_ <= $thirty_days_in_seconds } @warp_events; - # Count recent warp events - my $recent_warp_count = scalar(@warp_events); + # Count recent warp events + my $recent_warp_count = scalar(@warp_events); - my $enforcement = 0; + my $enforcement = 0; - quest::set_data($account_key, plugin::SerializeList(@warp_events)); + quest::set_data($account_key, plugin::SerializeList(@warp_events)); - if ($distance > 100 || $soulmark) { - my $admin_message = "Large Warp Detected. Character: $name Zone: $zonesn From: $from_x, $from_y, $from_z To: $current_x, $current_y, $current_z Distance: $distance"; + if ($distance > 100 || $soulmark) { + my $admin_message = "Large Warp Detected. Character: $name Zone: $zonesn From: $from_x, $from_y, $from_z To: $current_x, $current_y, $current_z Distance: $distance"; - if ($soulmark) { - $admin_message .= "\nAccount has Soulmark. Reason: $soulmark"; - } + if ($soulmark) { + $admin_message .= "\nAccount has Soulmark. Reason: $soulmark"; + } - if ($recent_warp_count) { - $admin_message .= "\nPrevious 30-day Warp Count: $recent_warp_count"; - } + if ($recent_warp_count) { + $admin_message .= "\nPrevious 30-day Warp Count: $recent_warp_count"; + } - if ($soulmark && $recent_warp_count > 10) { - $admin_message .= "\nHigh 30-day Warp Count. Enforcement Engaged."; - $enforcement = 1; - } + if ($soulmark && $recent_warp_count > 10) { + $admin_message .= "\nHigh 30-day Warp Count. Enforcement Engaged."; + $enforcement = 1; + } - # Send the admin message - quest::discordsend("admin", $admin_message); - quest::debug($admin_message); + # Send the admin message + quest::discordsend("admin", $admin_message); + quest::debug($admin_message); - if ($enforcement) { - $client->WorldKick(); - } - } + if ($enforcement) { + $client->WorldKick(); + } + } } sub EVENT_DISCOVER_ITEM { - my $name = $client->GetCleanName(); - - # Only announce upgraded items - if ($itemid >= 700000) { - plugin::WorldAnnounceItem("$name has discovered: {item}.",$itemid); - } + my $name = $client->GetCleanName(); + + # Only announce upgraded items + if ($itemid >= 700000) { + plugin::WorldAnnounceItem("$name has discovered: {item}.",$itemid); + } } sub symp_proc_tutorial_helper { - my $item_id = shift; - my $client = shift; - - if ($item_id) { - #pre-computed list of symp proc item ID bases - my @sym_clicks = ( - 6307, 6309, 6313, 7305, 900012, 900014, 1113, 1117, 1156, 1173, - 1904, 2404, 5203, 5214, 5730, 5764, 6017, 6020, 6024, 6036, - 6310, 6315, 6323, 6324, 6332, 6335, 6343, 6350, 6359, 6382, - 6383, 6402, 6404, 6408, 6616, 6626, 7036, 7318, 7372, 7405, - 10333, 10383, 10404, 10994, 11028, 11906, 11973, 12375, 13168, - 13380, 13400, 13500, 13743, 13744, 13815, 13987, 13988, 13991, - 14338, 14746, 14762, 20627, 21798, 21863, 21885, 21886, 21892, - 22819, 22890, 23498, 24745, 24779, 24789, 24793, 25566, 25577, - 25980, 25998, 26000, 26001, 26009, 26553, 27280, 27717, 28812, - 28813, 28814, 28815, 28817, 28908, 29248, 29430, 29442, 30511, - 31210, 31212, 31373, 62269, 68444, 68744, 68775, 68837, 69044, - 69047, 69049, 69051, 69054, 69055, 69095, 69112, 69113, 69116, - 69155 - ); - - my $item_root = ($item_id % 1000000); - - if (grep { $_ == $item_root } @sym_clicks) { - plugin::dispatch_popup("symp_tutorial", $client); - } - } + my $item_id = shift; + my $client = shift; + + if ($item_id) { + #pre-computed list of symp proc item ID bases + my @sym_clicks = ( + 6307, 6309, 6313, 7305, 900012, 900014, 1113, 1117, 1156, 1173, + 1904, 2404, 5203, 5214, 5730, 5764, 6017, 6020, 6024, 6036, + 6310, 6315, 6323, 6324, 6332, 6335, 6343, 6350, 6359, 6382, + 6383, 6402, 6404, 6408, 6616, 6626, 7036, 7318, 7372, 7405, + 10333, 10383, 10404, 10994, 11028, 11906, 11973, 12375, 13168, + 13380, 13400, 13500, 13743, 13744, 13815, 13987, 13988, 13991, + 14338, 14746, 14762, 20627, 21798, 21863, 21885, 21886, 21892, + 22819, 22890, 23498, 24745, 24779, 24789, 24793, 25566, 25577, + 25980, 25998, 26000, 26001, 26009, 26553, 27280, 27717, 28812, + 28813, 28814, 28815, 28817, 28908, 29248, 29430, 29442, 30511, + 31210, 31212, 31373, 62269, 68444, 68744, 68775, 68837, 69044, + 69047, 69049, 69051, 69054, 69055, 69095, 69112, 69113, 69116, + 69155 + ); + + my $item_root = ($item_id % 1000000); + + if (grep { $_ == $item_root } @sym_clicks) { + plugin::dispatch_popup("symp_tutorial", $client); + } + } } sub EVENT_COMBINE_VALIDATE { @@ -281,97 +417,97 @@ sub EVENT_COMBINE_VALIDATE { } sub EVENT_COMBINE_SUCCESS { - if ($recipe_id =~ /^1090[4-7]$/) { - $client->Message(1, - "The gem resonates with power as the shards placed within glow unlocking some of the stone's power. ". - "You were successful in assembling most of the stone but there are four slots left to fill, ". - "where could those four pieces be?" - ); - } - elsif ($recipe_id =~ /^10(903|346|334)$/) { - my %reward = ( - melee => { - 10903 => 67665, - 10346 => 67660, - 10334 => 67653 - }, - hybrid => { - 10903 => 67666, - 10346 => 67661, - 10334 => 67654 - }, - priest => { - 10903 => 67667, - 10346 => 67662, - 10334 => 67655 - }, - caster => { - 10903 => 67668, - 10346 => 67663, - 10334 => 67656 - } - ); - my $type = plugin::ClassType($class); - quest::summonfixeditem($reward{$type}{$recipe_id}); - quest::summonfixeditem(67704); # Item: Vaifan's Clockwork Gemcutter Tools - $client->Message(1,"Success"); - } + if ($recipe_id =~ /^1090[4-7]$/) { + $client->Message(1, + "The gem resonates with power as the shards placed within glow unlocking some of the stone's power. ". + "You were successful in assembling most of the stone but there are four slots left to fill, ". + "where could those four pieces be?" + ); + } + elsif ($recipe_id =~ /^10(903|346|334)$/) { + my %reward = ( + melee => { + 10903 => 67665, + 10346 => 67660, + 10334 => 67653 + }, + hybrid => { + 10903 => 67666, + 10346 => 67661, + 10334 => 67654 + }, + priest => { + 10903 => 67667, + 10346 => 67662, + 10334 => 67655 + }, + caster => { + 10903 => 67668, + 10346 => 67663, + 10334 => 67656 + } + ); + my $type = plugin::ClassType($class); + quest::summonfixeditem($reward{$type}{$recipe_id}); + quest::summonfixeditem(67704); # Item: Vaifan's Clockwork Gemcutter Tools + $client->Message(1,"Success"); + } } sub EVENT_ITEM_CLICK_CAST_CLIENT { - plugin::swap_items($client, $item_id, $slot_id); + plugin::swap_items($client, $item_id, $slot_id); } sub EVENT_CAST_ON { - # Check for mutually-exclusive elemental form spells. - my @spell_ids = ( - 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, - 38329, 38330, 38331, 38333, 38334, 38335, 38336, 38337, 38338, 38340, 38341, 38342 - ); - if (grep { $_ == $spell_id } @spell_ids) { - foreach my $id (@spell_ids) { - next if $id == $spell_id; # Skip the matched spell_id - $client->BuffFadeBySpellID($id); - } - } - - if ($caster_id && $spell) { - my @global_buffs = ( 43002, 43003, 43004, 43005, 43006, 43007, 43008, 17779 ); - # Check if spell_id IS in @global_buffs array - if (grep { $_ == $spell_id } @global_buffs) { - # no operation - } elsif ($caster_id == $client->GetID() && $spell->GetBuffDuration() > 0) { - plugin::dispatch_popup("self_buff", $client); - } - } + # Check for mutually-exclusive elemental form spells. + my @spell_ids = ( + 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, + 38329, 38330, 38331, 38333, 38334, 38335, 38336, 38337, 38338, 38340, 38341, 38342 + ); + if (grep { $_ == $spell_id } @spell_ids) { + foreach my $id (@spell_ids) { + next if $id == $spell_id; # Skip the matched spell_id + $client->BuffFadeBySpellID($id); + } + } + + if ($caster_id && $spell) { + my @global_buffs = ( 43002, 43003, 43004, 43005, 43006, 43007, 43008, 17779 ); + # Check if spell_id IS in @global_buffs array + if (grep { $_ == $spell_id } @global_buffs) { + # no operation + } elsif ($caster_id == $client->GetID() && $spell->GetBuffDuration() > 0) { + plugin::dispatch_popup("self_buff", $client); + } + } } sub EVENT_SAY { - if ($client->GetGM()) { - if ($text=~/#awardtitle\s*(.*)/i) { - $client->Message(13, "Disregard the command not recognized error."); - my $arguments = $1; # Captures everything after #awardtitle - - my $tar_client = $client->GetTarget(); - if ($tar_client->IsClient()) { - $tar_client = $tar_client->CastToClient(); - } - if ($tar_client && $tar_client->IsClient()) { - # Validate that there is exactly one argument which is a number - if ($arguments =~ /^\s*(\d+)\s*$/) { - my $number = $1; # Captures the number - # Proceed with awarding the title using $number - - $client->Message(13, "Awarding TitleSet $number to " . $tar_client->GetName()); - plugin::AddTitleFlag($number, $tar_client->CastToClient()); - plugin::CommonCharacterUpdate($tar_client->CastToClient()); - $tar_client->Signal(1); - } else { - $client->Message(13, "Invalid input. Please provide a single numeric argument."); - } - } else { - $client->Message(13, "You must target a client to issue this command."); - } - } - } + if ($client->GetGM()) { + if ($text=~/#awardtitle\s*(.*)/i) { + $client->Message(13, "Disregard the command not recognized error."); + my $arguments = $1; # Captures everything after #awardtitle + + my $tar_client = $client->GetTarget(); + if ($tar_client->IsClient()) { + $tar_client = $tar_client->CastToClient(); + } + if ($tar_client && $tar_client->IsClient()) { + # Validate that there is exactly one argument which is a number + if ($arguments =~ /^\s*(\d+)\s*$/) { + my $number = $1; # Captures the number + # Proceed with awarding the title using $number + + $client->Message(13, "Awarding TitleSet $number to " . $tar_client->GetName()); + plugin::AddTitleFlag($number, $tar_client->CastToClient()); + plugin::CommonCharacterUpdate($tar_client->CastToClient()); + $tar_client->Signal(1); + } else { + $client->Message(13, "Invalid input. Please provide a single numeric argument."); + } + } else { + $client->Message(13, "You must target a client to issue this command."); + } + } + } } \ No newline at end of file diff --git a/plugins/cata_teleporter_utils.pl b/plugins/cata_teleporter_utils.pl new file mode 100644 index 00000000..0269968a --- /dev/null +++ b/plugins/cata_teleporter_utils.pl @@ -0,0 +1,218 @@ +sub HandleTeleporterSay { + my $text = plugin::val('text'); + my $client = plugin::val('client'); + my $npc = plugin::val('npc'); + + my $group_flg = quest::get_data($client->AccountID() ."-group-ports-enabled") || ""; + my $eom_link = quest::varlink(46779); + + my $bind_loc = $client->GetBucket("baz_and_back_bind") || 'bazaar'; + my $revind_text = ""; + + plugin::AddDefaultAttunement($client); + + my ($continent_pattern, $continent_map) = plugin::GetContinentCapturePattern(); + my ($waypoint_pattern, $eligible_waypoints) = plugin::GetWaypointCapturePattern(-1, $client); + + if ($text=~/hail/i) { + my $name_string = $npc->GetCleanName() eq "Tearal" ? "Tearel, the Keeper of the Map" : "Timmy, Son of Tearel, the Keeper of the Other Map"; + + my $attune_map_link = quest::silent_saylink("attune the map"); + my $expedition_link = quest::silent_saylink("an expedition"); + my $reagents_link = quest::silent_saylink("special reagents"); + + if (!$group_flg) { + $group_flg = " However, that magic, like teleporting an entire group, will require [$reagents_link]." ; + } else { + $group_flg = ""; + } + + if (!($bind_loc eq $zonesn)) { + my $attune_link = quest::silent_saylink("attune your Bazaar and Back"); + $rebind_text = " I see that you are not personally attuned to this location, though! Would you like to [$attune_link] ability to return you here?"; + } else { + $rebind_text = ""; + } + + plugin::NPCTell("Greetings, $name. I am $name_string . I can [$attune_map_link] to any rune circles you have previously discovered. If you are part of + [$expedition_link] I can also help you return to the heat of the battle.$group_flg$rebind_text"); + + return; + } elsif ($text =~ /attune your Bazaar and Back/i) { + plugin::NPCTell("Excellent! You will now return to this vicinity whenever you use your Bazaar and Back ability!"); + $client->SetBucket("baz_and_back_bind", $zonesn); + } elsif ($text =~ /attune the map/i) { + # Get eligible continent names + my @continent_names = GetEligibleContinentNames($client); + + # Formulate a grammatically correct list + my $location_append = ""; + if (@continent_names == 1) { + $location_append = $continent_names[0]; + } elsif (@continent_names == 2) { + $location_append = $continent_names[0] . " or " . $continent_names[1]; + } elsif (@continent_names > 2) { + $location_append = join(', ', @continent_names[0..$#continent_names-1]) . ", or " . $continent_names[-1]; + } + + # NPC dialogue response + plugin::NPCTell("If you look closely, you'll see circles of rune-stones scattered throughout Norrath, and beyond. These serve as anchors for travel, and the map can be attuned to any of them. + Let's narrow down where you want to go? $location_append?"); + } elsif ($text=~/special reagents/i) { + if ($group_flg) { + plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); + } else { + my $ritual_link = quest::silent_saylink("perform this ritual"); + plugin::NPCTell("If you can provide me with Five [$eom_link], I will [$ritual_link] for you."); + plugin::YellowText("Once unlocked, the group transport and instance return abilities will be available to all characters on this account."); + } + } elsif ($text=~/perform this ritual/i) { + if ($group_flg) { + plugin::NPCTell("You already have performed this ritual, and have these abilities available to you."); + } else { + if (plugin::SpendEOM($client, 5)) { + my $attuned_link = quest::silent_saylink("attuned", 1); + quest::set_data($client->AccountID() ."-group-ports-enabled", 1); + plugin::NPCTell("$name, forevermore you and yours can transport your entire group to anywhere you have [$attuned_link]."); + } else { + plugin::NPCTell("I'm sorry, $name, you do not have enough [$eom_link] available to you right now. When you have more..."); + } + } + } elsif ($text=~/an expedition/i || $text=~/instance/i) { + if ($group_flg) { + my $dz = $client->GetExpedition(); + if ($dz) { + my $dz_name = $dz->GetName(); + plugin::NPCTell("I can sense that you are attuned to a particular time and place. I have attuned the map to it!"); + plugin::YellowText("The Magic Map has been attuned to your instance: $dz_name"); + $client->SetEntityVariable("magic_map_attune", 'instance'); + } else { + plugin::NPCTell("I do not sense any particular expedition affinity with you."); + } + } else { + my $reagents_link = quest::silent_saylink("special reagents"); + plugin::NPCTell("Unfortunately, I will need some [$reagents_link] in order to transport you in this way."); + } + } elsif ($text =~ $continent_pattern) { + my $matched_continent = $1; # $1 contains the captured match + + if (exists $continent_map->{$matched_continent}) { + my $continent_id = $continent_map->{$matched_continent}; + my %waypoints = plugin::GetWaypoints($continent_id, $client); + + # Collect the long names for the waypoints with quest::saylink + my @waypoint_links; + foreach my $key (sort {$a cmp $b} keys %waypoints) { + if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { + my $long_name = $waypoints{$key}->[0]; # Get the long name + my $short_name = $key; # The key is the short name + my $zone_link = quest::silent_saylink($short_name, $long_name); + push @waypoint_links, "[$zone_link]"; # Create a clickable link + } + } + + # Send each waypoint as a separate line + plugin::NPCTell("$matched_continent... Let's see... I can send you to a number of places there..."); + foreach my $link (@waypoint_links) { + plugin::PurpleText("---$link"); + } + } + } elsif ($text =~ $waypoint_pattern) { + my $matched_waypoint_key = $1; # $1 contains the captured waypoint key (shortname), e.g., 'rivervale' + + if ($matched_waypoint_key) { + # Use the $eligible_waypoints hash to get the full waypoint data + my $waypoint_name = $eligible_waypoints->{$matched_waypoint_key}->[0]; # Get the long name for the matched waypoint + if (plugin::is_eligible_for_zone($client, $matched_waypoint_key, 1)) { + plugin::NPCTell("Perfect. I will attune the map to $waypoint_name, immediately!"); + plugin::YellowText("The Magic Map has been attuned to $waypoint_name!"); + $client->SetEntityVariable("magic_map_attune", $matched_waypoint_key); + } + } + } +} + +sub HandleTeleporterTick { + return; # Disable this Feature + + my $entity_list = plugin::val('entity_list'); + quest::debug("How did we get here?"); + my @clientlist = $entity_list->GetClientList(); + my $clientcount = @clientlist; + + my $max_idle_seconds = 60 * 15; # Set your max idle threshold here (e.g., 60 seconds) + my $idle_ticks = $max_idle_seconds / 6; + + my $warning_50_percent = int($idle_ticks * 0.5); + my $warning_80_percent = int($idle_ticks * 0.8); + + + foreach my $client (@clientlist) { + if (!$client || $client->IsTrader() || $client->GetGM()) { + next; + } + + my $last_x = int($client->GetEntityVariable("last_x") || 0); + my $last_y = int($client->GetEntityVariable("last_y") || 0); + my $last_h = int($client->GetEntityVariable("last_h") || 0); + + + my $cur_x = int($client->GetX()); + my $cur_y = int($client->GetY()); + my $cur_h = int($client->GetHeading()); + + if (defined $last_x && defined $last_y && defined $last_h) { + if ($last_x == $cur_x && $last_y == $cur_y && $last_h == $cur_h) { + my $idle_counter = $client->GetEntityVariable("idle_counter") // 0; + $idle_counter++; + + my $idle_seconds = $idle_counter * 6; + my $idle_minutes = sprintf("%.1f", $idle_seconds / 60); + my $max_idle_minutes = sprintf("%.1f", $max_idle_seconds / 60); + + if ($idle_counter == $warning_50_percent || $idle_counter == $warning_80_percent) { + $client->Message(15, "Warning: You have been idle for $idle_minutes minutes. You will be returned to character select in ". sprintf("%.1f", (($max_idle_seconds - $idle_seconds) / 60) ) . " minutes,"); + } + + if ($idle_counter >= $idle_ticks) { + $client->Kick(); + } + + $client->SetEntityVariable("idle_counter", $idle_counter); + } else { + $client->SetEntityVariable("idle_counter", 0); + } + } + + $client->SetEntityVariable("last_x", $cur_x); + $client->SetEntityVariable("last_y", $cur_y); + $client->SetEntityVariable("last_h", $cur_h); + } +} + +sub HasEligibleWaypoints { + my ($continent_id, $client) = @_; + my %waypoints = plugin::GetWaypoints($continent_id, $client); + + foreach my $key (keys %waypoints) { + if (plugin::is_eligible_for_zone($client, $key, 1) && $key ne $zonesn) { + return 1; # Return true if at least one eligible waypoint is found + } + } + + return 0; # Return false if no eligible waypoints are found +} + +sub GetEligibleContinentNames { + my ($client) = @_; + my @eligible_continent_names; + + foreach my $continent_id (sort { $a <=> $b } plugin::GetContinents($client)) { + if (HasEligibleWaypoints($continent_id, $client)) { + my $continent_name = GetContinentName($continent_id); + push @eligible_continent_names, "[$continent_name]"; + } + } + + return @eligible_continent_names; +} \ No newline at end of file