mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
879 lines
34 KiB
JavaScript
879 lines
34 KiB
JavaScript
/// <reference path="../../definitions.d.ts" />
|
|
// @ts-check
|
|
const shardName = GetServerSetting( "ServerName" );
|
|
const shardURL = "https://myshard.example.com";
|
|
const maxSafeTeleportsPerDay = GetServerSetting( "MaxSafeTeleportsPerDay" ); // Determines amount of "safe teleports" players get per day
|
|
const teleportToNearestSafeLocation = GetServerSetting( "teleportToNearestSafeLocation" ); // If enabled, teleports to nearest safe location. If disabled, random safe location
|
|
const murderersCanTeleport = false; // If enabled, murderers can make use of the stuck teleport feature, which will teleport them to a Chaos shrine/another "safe" location for murderers
|
|
const instantTeleport = false; // If enabled, players who use the stuck teleport feature will be instantly teleported. Otherwise, they need to wait ~30 seconds
|
|
|
|
// Website links
|
|
const ShardWebsite = shardName + ' - <A HREF=' + shardURL + '>' + shardURL + '</a>';
|
|
const UOX3Website = 'Ultima Offline eXperiment 3- <A HREF="https://www.uox3.org">https://www.uox3.org</a>';
|
|
const UOWebsite = 'Ultima Online - <A HREF="https://www.uo.com">UO Website</a>';
|
|
|
|
// Triggered through onHelpButton() Event in global.js
|
|
function DisplayHelpMenu( pUser )
|
|
{
|
|
var pSock = pUser.socket;
|
|
if( pSock == null )
|
|
return;
|
|
|
|
// Avoid multiple gumps in official UO client
|
|
var gumpID = this.script_id + 0xffff;
|
|
pSock.CloseGump( gumpID, 0 );
|
|
|
|
var sLanguage = pSock.language;
|
|
|
|
// Set up dictionary messages
|
|
// Gump Header
|
|
const gumpTitle = "<BIG><CENTER><U>" + shardName + " " + GetDictionaryEntry( 17000, sLanguage ) + "</U></CENTER></BIG>"; // Help Menu
|
|
|
|
// General Gameplay Questions
|
|
const generalTitle = "<H3>" + GetDictionaryEntry( 17001, sLanguage ) + "</H3>"; // General Gameplay Questions
|
|
const generalText = "<H3>" + GetDictionaryEntry( 17002, sLanguage ) + "</H3>"; // Select this option if you have general gameplay questions, which are normally answered by Counselors.
|
|
|
|
// Character stuck
|
|
const stuckTitle = "<H3>" + GetDictionaryEntry( 17003, sLanguage ) + "</H3>"; // Character is Stuck and Unable to Move
|
|
const stuckText = "<H3>" + GetDictionaryEntry( 17004, sLanguage ) + "</H3>"; // Select this option if your character is physically stuck in a location they cannot move out of.
|
|
|
|
// GM Page main selection
|
|
const assistanceTitle = "<h3>" + GetDictionaryEntry( 17005, sLanguage ) + "</H3>"; // Help! I need GM assistance!
|
|
const assistanceText = "<H3>" + GetDictionaryEntry( 17006, sLanguage ) + "</H3>"; // Select this option if you need assistance from GMs to deal with harassment, bugged items, or other problems.
|
|
|
|
// Harassment-related GM Page
|
|
const harassmentTitle = "<H3>" + GetDictionaryEntry( 17007, sLanguage ) + "</H3>"; // Another player is harassing me
|
|
const harassmentText = "<H3>" + GetDictionaryEntry( 17008, sLanguage ) + "</H3>"; // Another player is harassing me verbally/physically in-game!
|
|
|
|
// Item-related GM Page
|
|
const itemProblemTitle = "<H3>" + GetDictionaryEntry( 17009, sLanguage ) + "</H3>"; // I'm having item-related trouble
|
|
const itemProblemText = "<H3>" + GetDictionaryEntry( 17010, sLanguage ) + "</H3>"; // I have an item-related issue, which requires GM assistance.
|
|
|
|
// Exploit-related GM Page
|
|
const exploitTitle = "<H3>" + GetDictionaryEntry( 17011, sLanguage ) + "</H3>"; // I wish to report a shard exploit
|
|
const exploitText = "<H3>" + GetDictionaryEntry( 17012, sLanguage ) + "</H3>"; // I've come across an exploit that I'd like to report to GMs!
|
|
|
|
// Additional options
|
|
const otherTitle = "<H3>" + GetDictionaryEntry( 17013, sLanguage ) + "</H3>"; // Other
|
|
const otherText = "<H3>" + GetDictionaryEntry( 17014, sLanguage ) + "</H3>"; // Select to see additional options for bug reports/suggestions, to change your password or to view shard information.
|
|
|
|
// Reporting bugs
|
|
const reportBugTitle = "<H3>" + GetDictionaryEntry( 17015, sLanguage ) + "</H3>"; // Report a Bug
|
|
const reportBugText = '<H3>' + GetDictionaryEntry( 17016, sLanguage ) + '</H3>'; // Submit a short and quick bug report from in-game. For more detailed bug reports, post <a href="https://www.uox3.org">in the forums</a> instead.
|
|
|
|
// Making suggestions
|
|
const suggestionTitle = "<H3>" + GetDictionaryEntry( 17017, sLanguage ) + "</H3>"; // Provide a Gameplay Suggestion
|
|
const suggestionText = "<H3>" + GetDictionaryEntry( 17018, sLanguage ) + "<H3>"; // If you'd like to make a suggestion for the game, Choosing this option will take you to the Discussion Forums.
|
|
|
|
// Password management
|
|
const accManagementTitle = "<H3>" + GetDictionaryEntry( 17019, sLanguage ) + "</H3>"; // Password Management
|
|
const accManagementText = "<H3>" + GetDictionaryEntry( 17020, sLanguage ) + "</H3>"; // Change your account password to something else
|
|
|
|
// Server info
|
|
const serverInfoTitle ="<H3>" + GetDictionaryEntry( 17027, sLanguage ) + "</H3>"; // Server Info
|
|
const serverInfoText = "<H3>" + GetDictionaryEntry( 17028, sLanguage ) + "</H3>"; // Here you will find the server information
|
|
|
|
// Other problem
|
|
const otherProblemTitle = GetDictionaryEntry( 17030, sLanguage ); //Other Problem
|
|
const otherProblemText = GetDictionaryEntry( 17031, sLanguage ); // I've got another problem that doesn't fit any of these categories.
|
|
|
|
const serverStatus = GetDictionaryEntry( 17048, sLanguage ); // SERVER STATUS
|
|
|
|
// Return to previous menu
|
|
const wrongProblem = GetDictionaryEntry( 17029, sLanguage );
|
|
|
|
var helpGump = new Gump();
|
|
|
|
// Add shared background
|
|
helpGump.AddBackground( 50, 25, 540, 430, 5054 );
|
|
helpGump.AddCheckerTrans( 50, 25, 540, 430 );
|
|
helpGump.AddPage( 0 );
|
|
helpGump.AddGump( 50, 25, 5545 );
|
|
helpGump.AddGump( 530, 25, 5545 );
|
|
helpGump.AddHTMLGump( 50, 25, 540, 40, false, false, "<center> <BASEFONT color=#ffffff>" + gumpTitle + "</BASEFONT> </center>");
|
|
|
|
// A different button must be shown if connected client is of version 4.x or lower
|
|
if( pSock.clientMajorVer < 5 )
|
|
{
|
|
helpGump.AddButton( 425, 415, 2073, 2072, 1, 0, 0 );// Close Button
|
|
}
|
|
else
|
|
{
|
|
helpGump.AddButton( 425, 415, 12006, 12007, 1, 0, 0 );// Close Button
|
|
}
|
|
|
|
// Add first page
|
|
helpGump.AddPage( 1 );
|
|
|
|
helpGump.AddButton( 80, 90, 5540, 5541, 1, 0, 1 );
|
|
helpGump.AddHTMLGump( 110, 90, 450, 74, false, false, "<BASEFONT color=#ffffff>" + generalTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 110, 450, 45, true, false, generalText );
|
|
|
|
helpGump.AddButton( 80, 170, 5540, 5541, 1, 0, 2 );
|
|
helpGump.AddHTMLGump( 110, 170, 450, 74, false, false, "<BASEFONT color=#ffffff>" + stuckTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 190, 450, 45, true, false, stuckText );
|
|
|
|
helpGump.AddPageButton( 80, 250, 5540, 5541, 3 );
|
|
helpGump.AddHTMLGump( 110, 250, 450, 74, false, false, "<BASEFONT color=#ffffff>" + assistanceTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 270, 450, 45, true, false, assistanceText );
|
|
|
|
helpGump.AddPageButton( 80, 330, 5540, 5541, 2 );
|
|
helpGump.AddHTMLGump( 110, 330, 450, 74, false, false, "<BASEFONT color=#ffffff>" + otherTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 350, 450, 45, true, false, otherText );
|
|
|
|
// Add second page
|
|
helpGump.AddPage( 2 );
|
|
|
|
helpGump.AddButton( 80, 90, 5540, 5541, 1, 0, 3 );
|
|
helpGump.AddHTMLGump( 110, 90, 450, 74, false, false, "<BASEFONT color=#ffffff>" + reportBugTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 110, 450, 45, true, false, reportBugText );
|
|
|
|
helpGump.AddButton( 80, 170, 5540, 5541, 1, 0, 4 );
|
|
helpGump.AddHTMLGump( 110, 170, 450, 74, false, false, "<BASEFONT color=#ffffff>" + suggestionTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 190, 450, 45, true, false, suggestionText );
|
|
|
|
helpGump.AddButton( 80, 250, 5540, 5541, 1, 0, 9 );
|
|
helpGump.AddHTMLGump( 110, 250, 450, 74, false, false, "<BASEFONT color=#ffffff>" + accManagementTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 270, 450, 30, true, false, accManagementText );
|
|
|
|
helpGump.AddPageButton( 80, 330, 5540, 5541, 4 );
|
|
helpGump.AddHTMLGump( 110, 330, 450, 74, false, false, "<BASEFONT color=#ffffff>" + serverInfoTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 350, 450, 30, true, false, serverInfoText );
|
|
|
|
helpGump.AddPageButton( 150, 390, 5537, 5538, 1 );
|
|
helpGump.AddHTMLGump( 180, 390, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
// Add third page
|
|
helpGump.AddPage( 3 );
|
|
|
|
helpGump.AddButton( 80, 90, 5540, 5541, 1, 0, 5 );
|
|
helpGump.AddHTMLGump( 110, 90, 450, 20, false, false, "<BASEFONT color=#ffffff>" + harassmentTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 110, 450, 30, true, false, harassmentText );
|
|
|
|
helpGump.AddButton( 80, 170, 5540, 5541, 1, 0, 6 );
|
|
helpGump.AddHTMLGump( 110, 170, 450, 20, false, false, "<BASEFONT color=#ffffff>" + itemProblemTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 190, 450, 30, true, false, itemProblemText );
|
|
|
|
helpGump.AddButton( 80, 250, 5540, 5541, 1, 0, 7 );
|
|
helpGump.AddHTMLGump( 110, 250, 450, 20, false, false, "<BASEFONT color=#ffffff>" + exploitTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 270, 450, 30, true, false, exploitText );
|
|
|
|
helpGump.AddButton( 80, 330, 5540, 5541, 1, 0, 8 );
|
|
helpGump.AddHTMLGump( 110, 330, 450, 20, false, false, "<BASEFONT color=#ffffff>" + otherProblemTitle + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 350, 450, 30, true, false, otherProblemText );
|
|
|
|
helpGump.AddPageButton( 150, 390, 5537, 5538, 1 );
|
|
helpGump.AddHTMLGump( 180, 390, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
// Add fourth page
|
|
helpGump.AddPage( 4 );
|
|
|
|
helpGump.AddHTMLGump( 110, 90, 250, 145, false, false, "<BASEFONT color=#ffffff>" + serverStatus + "</BASEFONT>" );
|
|
// Server Version
|
|
var serverVersionString = GetServerVersionString();
|
|
helpGump.AddHTMLGump( 110, 130, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "UOX3 Version:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 130, 200, 145, false, false, "<BASEFONT color=#abcdef>" + serverVersionString + "</BASEFONT>" );
|
|
|
|
// Uptime
|
|
var uptimeInSeconds = Math.floor( GetCurrentClock() / 1000 ) - Math.floor( GetStartTime() / 1000 );
|
|
var d = Math.floor( uptimeInSeconds / ( 3600 * 24 ));
|
|
var h = Math.floor( uptimeInSeconds % ( 3600 * 24 ) / 3600 );
|
|
var m = Math.floor( uptimeInSeconds % 3600 / 60 );
|
|
var dDisplay = d > 0 ? d + "d : " : "0d : ";
|
|
var hDisplay = h > 0 ? h + "h : " : "0h : ";
|
|
var mDisplay = m + "m";
|
|
|
|
helpGump.AddHTMLGump( 110, 150, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Uptime:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 150, 200, 145, false, false, "<BASEFONT color=#abcdef>" + dDisplay + hDisplay + mDisplay + "</BASEFONT>" );
|
|
|
|
// Accounts
|
|
helpGump.AddHTMLGump( 110, 170, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Accounts:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 170, 200, 145, false, false, "<BASEFONT color=#abcdef>" + GetAccountCount().toString() + "</BASEFONT>" );
|
|
|
|
// Items
|
|
helpGump.AddHTMLGump( 110, 190, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Items:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 190, 200, 145, false, false, "<BASEFONT color=#abcdef>" + GetItemCount().toString() + "</BASEFONT>" );
|
|
|
|
// Multis
|
|
helpGump.AddHTMLGump( 110, 210, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Multis:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 210, 200, 145, false, false, "<BASEFONT color=#abcdef>" + GetMultiCount().toString() + "</BASEFONT>" );
|
|
|
|
// Characters
|
|
helpGump.AddHTMLGump( 110, 230, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Characters:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 230, 200, 145, false, false, "<BASEFONT color=#abcdef>" + GetCharacterCount().toString() + "</BASEFONT>" );
|
|
|
|
// Players Online
|
|
helpGump.AddHTMLGump( 110, 250, 250, 145, false, false, "<BASEFONT color=#ffffff>" + "Players Online:" + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 250, 250, 200, 145, false, false, "<BASEFONT color=#abcdef>" + GetPlayerCount().toString() + "</BASEFONT>" );
|
|
|
|
// Useful websites
|
|
helpGump.AddHTMLGump( 110, 300, 450, 74, false, false, "<BASEFONT color=#ffffff>" + ShardWebsite + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 325, 450, 74, false, false, "<BASEFONT color=#ffffff>" + UOX3Website + "</BASEFONT>" );
|
|
helpGump.AddHTMLGump( 110, 350, 450, 74, false, false, "<BASEFONT color=#ffffff>" + UOWebsite + "</BASEFONT>" );
|
|
|
|
// Go back
|
|
helpGump.AddPageButton( 150, 390, 5537, 5538, 1 );
|
|
helpGump.AddHTMLGump( 180, 390, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
helpGump.Send( pSock );
|
|
helpGump.Free();
|
|
}
|
|
|
|
function ChangePasswordGump( pSock )
|
|
{
|
|
var sLanguage = pSock.language;
|
|
|
|
const gumpTitle = "<BIG><CENTER><U>" + shardName + " " + GetDictionaryEntry( 17000, sLanguage ) + "</U></CENTER></BIG>"; // Help Menu
|
|
const passwordManageTitle = GetDictionaryEntry( 17049, sLanguage ); // PASSWORD MANAGEMENT
|
|
const passwordManageText = GetDictionaryEntry( 17032, sLanguage ); // You can change the password to your shard account from this page. Take note that the password must be between 5 and 17 characters long, and should be unique to this shard. Don't reuse passwords you already used elsewhere! Also, don't share your account credentials with anyone!
|
|
const newPasswordText = GetDictionaryEntry( 17021, sLanguage ); // Enter New Password
|
|
const confirmNewPasswordText = GetDictionaryEntry( 17022, sLanguage ); // Confirm New Password
|
|
const wrongProblem = GetDictionaryEntry( 17029, sLanguage ); // Previous Menu
|
|
|
|
var changePassGump = new Gump();
|
|
|
|
// Add shared background
|
|
changePassGump.AddBackground( 50, 25, 540, 430, 5054 );
|
|
changePassGump.AddCheckerTrans( 50, 25, 540, 430 );
|
|
changePassGump.AddPage( 0 );
|
|
changePassGump.AddGump( 50, 25, 5545 );
|
|
changePassGump.AddGump( 530, 25, 5545 );
|
|
changePassGump.AddHTMLGump( 50, 25, 540, 40, false, false, "<center> <BASEFONT color=#ffffff>" + gumpTitle + "</BASEFONT> </center>");
|
|
|
|
// A different button must be shown if connected client is of version 4.x or lower
|
|
if( pSock.clientMajorVer < 5 )
|
|
{
|
|
changePassGump.AddButton( 425, 415, 2073, 2072, 1, 0, 0 );// Close Button
|
|
}
|
|
else
|
|
{
|
|
changePassGump.AddButton( 425, 415, 12006, 12007, 1, 0, 0 );// Close Button
|
|
}
|
|
|
|
changePassGump.AddText( 147, 90, 2727, passwordManageTitle ); // Account Management - Password Change
|
|
changePassGump.AddHTMLGump( 147, 120, 400, 100, false, false, "<BASEFONT color=#abcdef>" + passwordManageText + "</BASEFONT>");
|
|
|
|
changePassGump.AddButton( 150, 390, 5537, 5538, 1, 0, 100 );
|
|
changePassGump.AddHTMLGump( 180, 390, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
changePassGump.AddText( 147, 228, 2727, newPasswordText ); // New Password:
|
|
changePassGump.AddText( 149, 256, 2727, confirmNewPasswordText ); // Confirm New Password:
|
|
changePassGump.AddBackground( 335, 229, 200, 20, 9200);
|
|
changePassGump.AddTextEntry( 335, 229, 200, 20, 1175, 1, 40, " " );
|
|
changePassGump.AddBackground( 334, 255, 200, 20, 9200 );
|
|
changePassGump.AddTextEntry( 334, 255, 200, 20, 1175, 1, 41, " " );
|
|
changePassGump.AddButton( 144, 291, 247, 248, 1, 0, 20 ); // Okay Button
|
|
|
|
changePassGump.Send( pSock );
|
|
changePassGump.Free();
|
|
}
|
|
|
|
function BugReportGump( pSock )
|
|
{
|
|
var sLanguage = pSock.language;
|
|
|
|
const gumpTitle = "<BIG><CENTER><U>" + shardName + " " + GetDictionaryEntry( 17000, sLanguage ) + "</U></CENTER></BIG>"; // Help Menu
|
|
const reportBugHeader = GetDictionaryEntry( 17033, sLanguage ); // REPORT BUG
|
|
const reportBugMainText = GetDictionaryEntry( 17034, sLanguage ); // Please describe the bug you're experiencing with as much detail as the character limit of 240 characters allows. If your problem requires a more lengthy explanation, please post in the shard forums and/or discord instead.
|
|
const enterBugReportText = GetDictionaryEntry( 17035, sLanguage ); // Enter your bug-report below (max 240 chars):
|
|
const wrongProblem = GetDictionaryEntry( 17029, sLanguage );
|
|
|
|
var bugreportGump = new Gump();
|
|
|
|
// Add shared background
|
|
bugreportGump.AddBackground( 50, 25, 540, 430, 5054 );
|
|
bugreportGump.AddCheckerTrans( 50, 25, 540, 430 );
|
|
bugreportGump.AddPage( 0 );
|
|
bugreportGump.AddGump( 50, 25, 5545 );
|
|
bugreportGump.AddGump( 530, 25, 5545 );
|
|
bugreportGump.AddHTMLGump( 50, 25, 540, 40, false, false, "<center> <BASEFONT color=#ffffff>" + gumpTitle + "</BASEFONT> </center>");
|
|
|
|
// A different button must be shown if connected client is of version 4.x or lower
|
|
if( pSock.clientMajorVer < 5 )
|
|
{
|
|
bugreportGump.AddButton( 425, 415, 2073, 2072, 1, 0, 0 );// Close Button
|
|
}
|
|
else
|
|
{
|
|
bugreportGump.AddButton( 425, 415, 12006, 12007, 1, 0, 0 );// Close Button
|
|
}
|
|
|
|
bugreportGump.AddText( 147, 90, 2727, reportBugHeader ); // Report Bug
|
|
bugreportGump.AddHTMLGump( 147, 120, 400, 100, false, false, "<BASEFONT color=#abcdef>" + reportBugMainText + "</BASEFONT>");
|
|
|
|
bugreportGump.AddButton( 150, 390, 5537, 5538, 1, 0, 100 );
|
|
bugreportGump.AddHTMLGump( 180, 390, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
bugreportGump.AddText( 147, 228, 2727, enterBugReportText );
|
|
bugreportGump.AddBackground( 147, 248, 400, 80, 9200 );
|
|
bugreportGump.AddTextEntry( 147, 248, 400, 80, 0, 1, 40, " " ); // Bug Report
|
|
bugreportGump.AddButton( 144, 340, 247, 248, 1, 0, 50 ); // Okay Button
|
|
bugreportGump.AddButton( 425, 340, 2073, 2072, 1, 0, 0 );// Close Button
|
|
|
|
bugreportGump.Send( pSock );
|
|
bugreportGump.Free();
|
|
}
|
|
|
|
/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */
|
|
function onGumpPress( pSock, pButton, gumpData )
|
|
{
|
|
var pUser = pSock.currentChar;
|
|
|
|
// Password rules
|
|
const passwordRule1 = GetDictionaryEntry( 17023, pSock.language ); // Passwords may only consist of letters (a-z, A-Z) and digits (0-9).
|
|
const passwordRule2 = GetDictionaryEntry( 17037, pSock.language ); // Your password must be 5 (min) to 17 (max) characters long.
|
|
const passwordRule3 = GetDictionaryEntry( 17038, pSock.language ); // Confirm New Password' does not match 'New Password'! Note that passwords are cAsE sEnSiTiVe.
|
|
const passwordStatus = GetDictionaryEntry( 17039, pSock.language ); // The new password has been saved to your account.
|
|
|
|
switch( pButton )
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1: // General question for Counselors
|
|
pSock.Page( 0 );
|
|
break;
|
|
case 2: // Stuck
|
|
HandleStuckCharacter( pSock );
|
|
break;
|
|
case 3: // Report a bug
|
|
BugReportGump( pSock );
|
|
break;
|
|
case 4: // Make suggestion
|
|
pSock.OpenURL( shardURL );
|
|
break;
|
|
case 5: // Harassment
|
|
pSock.Page( 4 ); // Harassment Page
|
|
break;
|
|
case 6: // Item Problem
|
|
pSock.Page( 3 ); // Item Problem Page
|
|
break;
|
|
case 7: // Report exploit
|
|
pSock.Page( 5 ); // Report Exploit Page
|
|
break;
|
|
case 8: // Other Problem
|
|
pSock.Page( 1 ); // Free text
|
|
break;
|
|
case 9: // Account Management Gump
|
|
ChangePasswordGump( pSock );
|
|
break;
|
|
case 20: // Change account password
|
|
{
|
|
var userAccount = pUser.account;
|
|
var password = gumpData.getEdit( 0 );
|
|
var confirmpassword = gumpData.getEdit( 1 );
|
|
var letterNumber = /^[0-9a-zA-Z]+$/;
|
|
var passwordmatch = password.match( letterNumber );
|
|
|
|
if( !passwordmatch )
|
|
{
|
|
pUser.SysMessage( passwordRule1 ) // Passwords may only consist of letters (a-z, A-Z) and digits (0-9).
|
|
DisplayHelpMenu( pUser )
|
|
break;
|
|
}
|
|
if( password.length < 5 || password.length > 17 )
|
|
{
|
|
pUser.SysMessage( passwordRule2 ); // Your password must be 5 (min) to 17 (max) characters long.
|
|
DisplayHelpMenu( pUser )
|
|
break;
|
|
}
|
|
if( password != confirmpassword )
|
|
{
|
|
pUser.SysMessage( passwordRule3 ); // 'Confirm New Password' does not match 'New Password'! Note that passwords are cAsE sEnSiTiVe.
|
|
DisplayHelpMenu( pUser )
|
|
break;
|
|
}
|
|
if( password == confirmpassword )
|
|
{
|
|
pUser.SysMessage( passwordStatus ); // The new password has been saved to your account.
|
|
userAccount.password = password;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 30: // Teleport to random safe location
|
|
TeleportToRandomSafeLocation( pSock );
|
|
break;
|
|
case 31: // Page GM about being stuck
|
|
pSock.Page( 2 ) // Stuck
|
|
break;
|
|
case 50: // Submit bug report
|
|
var bugreportText = gumpData.getEdit( 0 );
|
|
pUser.ExecuteCommand( "reportbug " + bugreportText );
|
|
break;
|
|
case 100: // Reopen main help gump
|
|
DisplayHelpMenu( pUser );
|
|
break;
|
|
}
|
|
}
|
|
|
|
function HandleStuckCharacter( pSock )
|
|
{
|
|
var sLanguage = pSock.language;
|
|
var pUser = pSock.currentChar;
|
|
var stuckTeleEnabled = false;
|
|
var stuckTeleExhausted = false;
|
|
|
|
const gumpTitle = "<BIG><CENTER><U>" + shardName + " " + GetDictionaryEntry( 17000, sLanguage ) + "</U></CENTER></BIG>"; // Help Menu
|
|
const teleToRndSafeLoc = GetDictionaryEntry( 17040, sLanguage ); // Teleport to Random Safe Location
|
|
var teleToRndSafeLocText = GetDictionaryEntry( 17042, sLanguage ); // Selecting this option will teleport you to a random safe location (town or shrine) within your current facet. This can only be used a limited amount of times (%i) per day.
|
|
teleToRndSafeLocText = ( teleToRndSafeLocText.replace( /%i/gi, maxSafeTeleportsPerDay.toString() ));
|
|
const teleToNearestSafeLoc = GetDictionaryEntry( 17041, sLanguage ); // Teleport to Nearest Safe Location
|
|
var teleToNearestSafeLocText = GetDictionaryEntry( 17043, sLanguage ); //Selecting this option will teleport you to the nearest safe location (town or shrine) within your current facet. This can only be used a limited amount of times (%i) per day.
|
|
teleToNearestSafeLocText = ( teleToNearestSafeLocText.replace( /%i/gi, maxSafeTeleportsPerDay.toString() ));
|
|
const submitStuckPage = GetDictionaryEntry( 17044, sLanguage ); // Submit GM Page about Being Stuck
|
|
const submitStuckPageText = GetDictionaryEntry( 17045, sLanguage ); // Selecting this option will submit a support ticket about your situation. Please note that response time might vary depending on the number of GMs available.
|
|
const safeTeleExhausted = GetDictionaryEntry( 17046, sLanguage ); // Automatic teleports exhausted for today. Please rely on GM support system for now.
|
|
const wrongProblem = GetDictionaryEntry( 17029, sLanguage );
|
|
|
|
// Check if auto-teleport system is enabled
|
|
if( maxSafeTeleportsPerDay > 0 )
|
|
{
|
|
if( pUser.innocent || ( pUser.murderer && murderersCanTeleport ))
|
|
{
|
|
// Mark auto-teleport system as enabled
|
|
stuckTeleEnabled = true;
|
|
|
|
// Check when player's last teleport happened
|
|
var lastStuckTeleTime = new Date( parseInt( pUser.GetTag( "lastStuckTeleTime" )) * 1000 );
|
|
var today = new Date();
|
|
if( lastStuckTeleTime.getUTCDate() != today.getUTCDate() )
|
|
{
|
|
// Last teleport happened on some day in the past. Reset teleport count!
|
|
pUser.SetTag( "stuckTeleCount", null );
|
|
}
|
|
else
|
|
{
|
|
// Check if player has exhausted the available teleports for the day
|
|
var stuckTeleCount = pUser.GetTag( "stuckTeleCount" );
|
|
if( stuckTeleCount >= maxSafeTeleportsPerDay )
|
|
{
|
|
stuckTeleExhausted = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Display gump allowing player to choose between teleporting to a random safe
|
|
// location within their facet, or calling a GM for assistance
|
|
var stuckCharGump = new Gump();
|
|
|
|
// Add shared background
|
|
stuckCharGump.AddBackground( 50, 25, 540, 240, 5054 );
|
|
stuckCharGump.AddCheckerTrans( 50, 25, 540, 240 );
|
|
stuckCharGump.AddPage( 0 );
|
|
stuckCharGump.AddGump( 50, 25, 5545 );
|
|
stuckCharGump.AddGump( 530, 25, 5545 );
|
|
stuckCharGump.AddHTMLGump( 50, 25, 540, 40, false, false, "<center> <BASEFONT color=#ffffff>" + gumpTitle + "</BASEFONT> </center>");
|
|
|
|
// A different button must be shown if connected client is of version 4.x or lower
|
|
if( pSock.clientMajorVer < 5 )
|
|
{
|
|
stuckCharGump.AddButton( 425, 230, 2073, 2072, 1, 0, 0 );// Close Button
|
|
}
|
|
else
|
|
{
|
|
stuckCharGump.AddButton( 425, 230, 12006, 12007, 1, 0, 0 );// Close Button
|
|
}
|
|
|
|
stuckCharGump.AddButton( 150, 220, 5537, 5538, 1, 0, 100 );
|
|
stuckCharGump.AddHTMLGump( 180, 220, 335, 40, false, false, "<BASEFONT color=#ffffff>" + wrongProblem + "</BASEFONT>" );
|
|
|
|
if( stuckTeleEnabled && !stuckTeleExhausted )
|
|
{
|
|
// Auto-teleport option
|
|
stuckCharGump.AddButton( 80, 110, 5540, 5541, 1, 0, 30 );
|
|
if( teleportToNearestSafeLocation )
|
|
{
|
|
stuckCharGump.AddHTMLGump( 110, 110, 450, 74, false, false, "<BASEFONT color=#ffffff>" + teleToNearestSafeLoc + "</BASEFONT>" );
|
|
stuckCharGump.AddHTMLGump( 110, 130, 450, 67, true, false, teleToNearestSafeLocText );
|
|
}
|
|
else
|
|
{
|
|
stuckCharGump.AddHTMLGump( 110, 110, 450, 74, false, false, "<BASEFONT color=#ffffff>" + teleToRndSafeLoc + "</BASEFONT>" );
|
|
stuckCharGump.AddHTMLGump( 110, 130, 450, 67, true, false, teleToRndSafeLocText );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stuckCharGump.AddButton( 80, 110, 5540, 5541, 1, 0, 31 );
|
|
stuckCharGump.AddHTMLGump( 110, 110, 450, 74, false, false, "<BASEFONT color=#ffffff>" + submitStuckPage + "</BASEFONT>" );
|
|
stuckCharGump.AddHTMLGump( 110, 130, 450, 67, true, false, submitStuckPageText );
|
|
|
|
if( stuckTeleEnabled )
|
|
{
|
|
// Player has exhausted daily teleports, show GM Page option only
|
|
stuckCharGump.AddHTMLGump( 110, 90, 450, 18, false, false, "<BASEFONT color=red>" + safeTeleExhausted + "</BASEFONT>" );
|
|
}
|
|
}
|
|
|
|
stuckCharGump.Send( pSock );
|
|
stuckCharGump.Free();
|
|
}
|
|
|
|
function CanPlayerTeleport( pSock, pUser )
|
|
{
|
|
var sLanguage = pSock.language;
|
|
if( pUser.criminal )
|
|
{
|
|
pSock.SysMessage( GetDictionaryEntry( 17050, sLanguage )); // You cannot use safe teleport while flagged as a criminal!
|
|
return false;
|
|
}
|
|
else if( pUser.atWar )
|
|
{
|
|
pSock.SysMessage( GetDictionaryEntry( 17051, sLanguage )); // You cannot use safe teleport while engaged in combat!
|
|
return false;
|
|
}
|
|
else if( pUser.isJailed )
|
|
{
|
|
pSock.SysMessage( GetDictionaryEntry( 17052, sLanguage )); // You cannot use safe teleport while in jail!
|
|
return false;
|
|
}
|
|
|
|
// Are any of the user's pets in combat?
|
|
var followerList = pUser.GetFollowerList();
|
|
for( let i = 0; i < followerList.length; i++ )
|
|
{
|
|
var tempFollower = followerList[i];
|
|
if( ValidateObject( tempFollower ) && tempFollower.atWar )
|
|
{
|
|
pSock.SysMessage( GetDictionaryEntry( 17053, sLanguage )); // You cannot use safe teleport while your followers are engaged in combat!
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function TeleportToRandomSafeLocation( pSock )
|
|
{
|
|
var pUser = pSock.currentChar;
|
|
if( !ValidateObject( pUser ))
|
|
return;
|
|
|
|
if( pUser.GetTempTag( "waitingForTeleport" ))
|
|
{
|
|
pSock.SysMessage( GetDictionaryEntry( 17053, pSock.language )); // You have already activated safe teleport! Please wait...
|
|
return;
|
|
}
|
|
|
|
if( CanPlayerTeleport( pSock, pUser ))
|
|
{
|
|
pUser.frozen = true;
|
|
if( instantTeleport )
|
|
{
|
|
// Instant teleport, so call onTimer directly
|
|
onTimer( pUser, 1 );
|
|
}
|
|
else
|
|
{
|
|
// Delayed teleport, start some timers
|
|
pUser.SetTempTag( "waitingForTeleport", true );
|
|
pUser.TextMessage( GetDictionaryEntry( 17054, pSock.language ), false, 0x3b2, 0, pUser.serial ); // [Teleporting to safety in about half a minute...]
|
|
pUser.StartTimer( RandomNumber( 27000, 33000 ), 1, true );
|
|
pUser.StartTimer( RandomNumber( 13000, 17000 ), 2, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
/** @type { ( tObject: BaseObject, timerId: number ) => void } */
|
|
function onTimer( timerObj, timerID )
|
|
{
|
|
if( !ValidateObject( timerObj ))
|
|
return;
|
|
|
|
var pSock = timerObj.socket;
|
|
if( pSock == null )
|
|
return;
|
|
|
|
// Re-run the checks from before start of timer
|
|
if( !CanPlayerTeleport( pSock, timerObj, true ))
|
|
{
|
|
timerObj.frozen = false;
|
|
return;
|
|
}
|
|
|
|
if( timerID == 2 )
|
|
{
|
|
timerObj.TextMessage( GetDictionaryEntry( 17055, pSock.language ), false, 0x3b2, 0, timerObj.serial ); // [Teleporting to safety in about 15 seconds...]
|
|
return;
|
|
}
|
|
|
|
// Everything seems to be in order, teleport the player to safety!
|
|
PerformTeleportation( pSock, timerObj );
|
|
}
|
|
|
|
function PerformTeleportation( pSock, pUser )
|
|
{
|
|
if( !ValidateObject( pUser ))
|
|
return;
|
|
|
|
pSock.SysMessage( GetDictionaryEntry( 17047, pSock.language )); // Teleporting you to safe location...
|
|
pUser.SetTempTag( "waitingForTeleport", null );
|
|
pUser.frozen = false;
|
|
var dateNow = ( Date.now() / 1000 | 0 );
|
|
pUser.SetTag( "lastStuckTeleTime", dateNow.toString() );
|
|
pUser.SetTag( "stuckTeleCount", pUser.GetTag( "stuckTeleCount" ) + 1 );
|
|
|
|
var worldNum = pUser.worldnumber;
|
|
var closestDist = 0;
|
|
var closestLoc = null;
|
|
|
|
// Handle T2A and Dungeons in Felucca/Trammel
|
|
if( worldNum == 0 || worldNum == 1 )
|
|
{
|
|
if( pUser.x >= 5120 )
|
|
{
|
|
if( pUser.x <= 6144 && pUser.y >= 2304 )
|
|
{
|
|
// User is in Lost Lands, teleport them to either Papua or Delucia
|
|
var teleToPapua = true;
|
|
if( teleportToNearestSafeLocation )
|
|
{
|
|
// Check distance to Inn in Papua
|
|
var distance = DistanceBetween( pUser.x, pUser.y, 5575, 3175 );
|
|
closestDist = distance;
|
|
|
|
// Now check distance to Inn in Delucia, and if it's closer, use that instead
|
|
distance = DistanceBetween( pUser.x, pUser.y, 5207, 4066 );
|
|
if( distance < closestDist )
|
|
{
|
|
closestDist = distance;
|
|
teleToPapua = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Randomize which town to teleport to
|
|
teleToPapua = ( RandomNumber( 0, 1 ) ? true : false );
|
|
}
|
|
|
|
if( teleToPapua )
|
|
{
|
|
// Inn in Papua
|
|
closestLoc[0] = 5575;
|
|
closestLoc[1] = 3175;
|
|
closestLoc[2] = -3;
|
|
}
|
|
else
|
|
{
|
|
// Inn in Delucia
|
|
closestLoc[0] = 5207;
|
|
closestLoc[1] = 4066;
|
|
closestLoc[2] = 36;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Is player in a dungeon?
|
|
if( pUser.region != null && pUser.region.isDungeon )
|
|
{
|
|
if( pUser.murderer )
|
|
{
|
|
// Teleport murderers in dungeons to a random chaos shrine/out-of-town-area
|
|
closestLoc = safeChaosShrineLocations[worldNum][RandomNumber( 0, safeChaosShrineLocations.length - 1 )];
|
|
}
|
|
else
|
|
{
|
|
// Teleport players in dungeons to a random shrine/out-of-town area
|
|
closestLoc = safeShrineLocations[worldNum][RandomNumber( 0, safeShrineLocations.length - 1 )];
|
|
}
|
|
}
|
|
|
|
// Player is neither in T2A, nor in a dungeon
|
|
var validSafeLocations = safeTownLocations[worldNum];
|
|
if( teleportToNearestSafeLocation )
|
|
{
|
|
if( pUser.murderer )
|
|
{
|
|
// Teleport murderers to a random chaos shrine/out-of-town-area
|
|
closestLoc = safeChaosShrineLocations[worldNum][RandomNumber( 0, safeChaosShrineLocations.length - 1 )];
|
|
}
|
|
else
|
|
{
|
|
for( let i = 0; i < validSafeLocations.length; i++ )
|
|
{
|
|
// Loop through all valid safe locations and determine which one is closer to the player
|
|
var distance = DistanceBetween( pUser.x, pUser.y, validSafeLocations[i][0], validSafeLocations[i][1] );
|
|
if( closestDist == 0 || distance < closestDist )
|
|
{
|
|
// New nearest location found! Update variables
|
|
closestDist = distance;
|
|
closestLoc = validSafeLocations[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( pUser.murderer )
|
|
{
|
|
// Teleport murderers to a random chaos shrine/out-of-town-area
|
|
closestLoc = safeChaosShrineLocations[worldNum][RandomNumber( 0, safeChaosShrineLocations.length - 1 )];
|
|
}
|
|
else
|
|
{
|
|
// Teleport player to random safe location
|
|
var safeLoc = validSafeLocations[RandomNumber( 0, validSafeLocations.length - 1 )];
|
|
pUser.Teleport( safeLoc[0], safeLoc[1], safeLoc[2] );
|
|
}
|
|
}
|
|
|
|
if( closestLoc != null )
|
|
{
|
|
// Teleport player to nearest safe location
|
|
pUser.Teleport( closestLoc[0], closestLoc[1], closestLoc[2] );
|
|
}
|
|
|
|
// Play a sound effect
|
|
pSock.SoundEffect( 0x01FC, true );
|
|
|
|
// Player is unable to engage in fights for the next 10 minutes after making use of the
|
|
// safe teleport option
|
|
pUser.setPeace = 10;
|
|
pUser.AddScriptTrigger( 7000 ); // Attach script that prevents entering combat mode
|
|
|
|
// Also teleport the player's pets/followers
|
|
var followerList = pUser.GetFollowerList();
|
|
for( let i = 0; i < followerList.length; i++ )
|
|
{
|
|
var tempFollower = followerList[i];
|
|
// Only teleport player's pets if they are set to follow and are within range
|
|
if( ValidateObject( tempFollower ) && tempFollower.wandertype == 1 && tempFollower.InRange( pUser, 24 ))
|
|
{
|
|
tempFollower.Teleport( pUser.x, pUser.y, pUser.z );
|
|
tempFollower.setPeace = 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
const safeTownLocations = [
|
|
// Felucca Britannia Towns
|
|
[
|
|
[1501, 1627, 10], // Britain
|
|
[2250, 1235, 0], // Cove
|
|
[2474, 408, 15], // Minoc
|
|
[626, 2243, 0], // Skara Brae
|
|
[1837, 2745, 0], // Trinsic
|
|
[2778, 985, 0], // Vesper
|
|
[629, 858, 0] // Yew
|
|
],
|
|
|
|
// Trammel Britannia Towns
|
|
[
|
|
[1501, 1627, 10], // Britain
|
|
[2250, 1235, 0], // Cove
|
|
[2474, 408, 15], // Minoc
|
|
[626, 2243, 0], // Skara Brae
|
|
[1837, 2745, 0], // Trinsic
|
|
[2778, 985, 0], // Vesper
|
|
[629, 858, 0] // Yew
|
|
],
|
|
|
|
// Ilshenar "Towns"
|
|
[
|
|
//[947, 641, -80] // Ver Lor Reg (Inaccessible in modern clients, but existed in 7.0.15.x and earlier)
|
|
[1564, 1058, -6], // Twin Oaks Tavern
|
|
[1518, 625, -16], // Desert Outpost (West)
|
|
[1625, 550, -19] // Desert Outpost (East)
|
|
],
|
|
|
|
// Malas Towns
|
|
[
|
|
[1012, 513, -70], // Luna
|
|
[2055, 1320, -90] // Umbra
|
|
],
|
|
|
|
// Tokuno Islands Towns
|
|
[
|
|
[672, 1221, 25] // Zento (Makoto-Jima)
|
|
],
|
|
|
|
// Ter Mur Towns
|
|
[
|
|
[729, 3488, -20] // Royal City
|
|
]
|
|
];
|
|
|
|
const safeShrineLocations = [
|
|
// Felucca Britannia Shrines
|
|
[
|
|
[1856, 872, -1], // Compassion
|
|
[1730, 3528, 0], // Honor
|
|
[1301, 639, 15], // Justice
|
|
[3355, 299, 9], // Sacrifice
|
|
[1602, 2486, 4] // Spirituality
|
|
],
|
|
|
|
// Trammel Britannia Shrines
|
|
[
|
|
[1856, 872, -1], // Compassion
|
|
[1730, 3528, 0], // Honor
|
|
[1301, 639, 15], // Justice
|
|
[3355, 299, 9], // Sacrifice
|
|
[1602, 2486, 4] // Spirituality
|
|
],
|
|
|
|
// Ilshenar Shrines
|
|
[
|
|
[1210, 477, -13], // Compassion
|
|
[1106, 404, -80], // Gargoyle
|
|
[722, 1354, -60], // Honesty
|
|
[747, 730, -29], // Honor
|
|
[287, 1013, 0], // Humility
|
|
[986, 1004, -35], // Justice
|
|
[1173, 1288, -30], // Sacrifice
|
|
[1526, 1340, 0], // Spirituality
|
|
[529, 213, -41] // Valor
|
|
],
|
|
|
|
// Malas Shrines
|
|
[
|
|
[1066, 1437, -90] // Only shrine in Malas is inside the city of Luna, so let's teleport players to Hansel's hostel instead
|
|
],
|
|
|
|
// Tokuno Islands Shrines
|
|
[
|
|
[296, 711, 55], // Homare
|
|
[1045, 517, 15], // Isamu
|
|
[718, 1160, 25] // Makoto
|
|
],
|
|
|
|
// Ter Mur Shrines
|
|
[
|
|
// Only shrine in Ter Mur is inside the Royal City, so teleport player to some beach in the north instead
|
|
[693, 2917, 39]
|
|
]
|
|
];
|
|
|
|
const safeChaosShrineLocations = [
|
|
// Felucca Britannia Chaos Shrines
|
|
[
|
|
[1456, 852, 0] // Chaos
|
|
],
|
|
|
|
// Trammel Britannia Chaos Shrines
|
|
[
|
|
[1456, 852, 0] // Chaos
|
|
],
|
|
|
|
// Ilshenar Chaos Shrines
|
|
[
|
|
[1749, 234, 58] // Chaos
|
|
],
|
|
|
|
// Malas Chaos Shrines
|
|
[
|
|
[2418, 258, -90] // No Chaos shrines, so just teleport player to a remote area on the map
|
|
],
|
|
|
|
// Tokuno Islands Chaos Shrines
|
|
[
|
|
[278, 699, 44] // No Chaos shrines, so just teleport player to a remote area on the map
|
|
],
|
|
|
|
// Ter Mur Chaos Shrines
|
|
[
|
|
[674, 4013, -43] // No Chaos shrines, so just teleport player to a remote area on the map
|
|
]
|
|
];
|