Guest User

Al Bhed Translation Script

a guest
Jan 20th, 2022
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* Al Bhed Translator script
  2. * Generates mysterious languages, then allows players to gradually learn them over time. Inspired by the Al Bhed language system in Final Fantasy X.
  3. * Usage (single language):
  4. * !generate         Generates a new secret language cipher.
  5. * !say "Hello"      Says "Hello" in the secret language.
  6. * !learn            Increase language knowledge by 1. Knowledge goes from 0 to 26, each point translating one letter.
  7. * !learn 10         Set language knowledge to 10.
  8. *
  9. * Usage (multiple languages):
  10. * !generate Elvish          Generates a new language cipher for Elvish.
  11. * !say Elvish "Hello"       Says "Hello" in Elvish.
  12. * !learn Elvish             Increases language knowledge for Elvish by 1.
  13. * !learn Elvish 10          Sets Elvish language knowledge to 10.
  14. *
  15. * Created by Quinn Gordon
  16. */
  17.  
  18. on('ready', () => {
  19.     // Config:
  20.     const config = {
  21.         enabled: true,                          // Set to false to disable script
  22.         multipleLanguages: true,                // Track multiple languages
  23.         enforceVowels: true,                    // Ensures the langugae has vowels in the same places as original text
  24.         learnedColor: 'orange',                 // Color of known letters
  25.         letters: 'abcdefghijklmnopqrstuvwxyz',
  26.         consonants: 'bcdfghjklmnpqrstvwxz',
  27.         vowels: 'aeiouy'
  28.     }
  29.    
  30.     on('chat:message', function(msg) {
  31.         if(msg.type == 'api' && msg.content.indexOf('!generate') == 0
  32.             && playerIsGM(msg.playerid)) {
  33.             if(!config.enabled) return;
  34.  
  35.             let language = 'common';
  36.            
  37.             if(config.multipleLanguages) {
  38.                 let args = msg.content.split(/\s+/);
  39.                 if(args.length > 1) {
  40.                     language = args[1].toLowerCase();
  41.                 }
  42.             }
  43.  
  44.             state.cipher[language] = {};
  45.             // Generate random-order character list
  46.             let baseList = '';
  47.             let charlist = '';
  48.             if(config.enforceVowels) {
  49.                 let shuffledVowels = shuffle(config.vowels);
  50.                 let shuffledConsonants = shuffle(config.consonants);
  51.                 baseList = config.vowels + config.consonants;
  52.                 charList = shuffledVowels + shuffledConsonants;
  53.             } else {
  54.                 charList = shuffle(letters);
  55.             }
  56.            
  57.             // Generate a learning order
  58.             let learningOrder = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26];
  59.             for(let i = 25; i > 0; i--) {
  60.                 let j = Math.floor(Math.random() * (i + 1));
  61.                 let tmp = learningOrder[i];
  62.                 learningOrder[i] = learningOrder[j];
  63.                 learningOrder[j] = tmp;
  64.             }
  65.            
  66.             // Generate the Cipher
  67.             for(let i = 0; i < 26; i++) {
  68.                 state.cipher[language][baseList[i]] = {
  69.                     char: charList[i],
  70.                     order: learningOrder[i]
  71.                 };
  72.             }
  73.            
  74.             // Reset language knowledge
  75.             if(!state.knowledge) state.knowledge = {};
  76.             state.knowledge[language] = 0;
  77.            
  78.             if(config.multipleLanguages) {
  79.                 const displayLanguage = language.substring(0, 1).toUpperCase() + language.substring(1);
  80.                 sendChat('Translator', `/w gm New cipher generated for language ${displayLanguage}.`);
  81.             } else {
  82.                 sendChat('Translator', '/w gm New cipher generated.');
  83.             }
  84.         }
  85.     });
  86.    
  87.     // Say a message in the encoded language.
  88.     on('chat:message', function(msg) {
  89.         if(msg.type == 'api' && msg.content.indexOf('!say') == 0) {
  90.             if(!config.enabled) return;
  91.             if(!state.cipher) return;
  92.            
  93.             let language = 'common';
  94.             let input = '';
  95.             let displayInput = '';
  96.            
  97.             let args = msg.content.split(/\s+/);
  98.             if(config.multipleLanguages) {
  99.                 if(args.length > 1) {
  100.                     language = args[1].toLowerCase();
  101.                 }
  102.                 input = args.slice(2).join(' ');
  103.             } else {
  104.                 input = args.slice(1).join(' ');
  105.             }
  106.            
  107.             if(!language) language = 'common';
  108.  
  109.             const knowledge = state.knowledge[language];
  110.             let output = '';
  111.             let properNoun = false;
  112.            
  113.             for(let i = 0; i < input.length; i++) {
  114.                 // If a word starts with !, don't translate it
  115.                 if(i > 0) {
  116.                     log(`${input[i]} | ${input[i-1].match(/[^a-zA-Z0-9]/g)}`);
  117.                 }
  118.                 if(input[i] == '!' &&
  119.                     (i == 0 ||
  120.                     input[i-1].match(/[^a-zA-Z0-9]/g))) {
  121.                     properNoun = true;
  122.                     continue;
  123.                 }
  124.                
  125.                 if(properNoun) {
  126.                     if(input[i].match(/[^a-zA-Z0-9]/g)) {
  127.                         properNoun = false;
  128.                     }
  129.                 }
  130.                
  131.                 let lowerCase = input[i].toLowerCase() == input[i];
  132.                 let inputLetter = input[i].toLowerCase();
  133.                 let outputLetter = '';
  134.                
  135.                 let c = state.cipher[language][inputLetter];
  136.                 if(c == null) {
  137.                     outputLetter = input[i];
  138.                 } else {
  139.                     if(c.order <= knowledge || properNoun) {
  140.                         outputLetter = `<span style="color:${config.learnedColor}">${input[i]}</span>`;
  141.                     } else {
  142.                         outputLetter = c.char;
  143.                     }
  144.                 }
  145.                 outputLetter = lowerCase ? outputLetter.toLowerCase() : outputLetter.toUpperCase();
  146.                 output += outputLetter;
  147.                 displayInput += lowerCase ? inputLetter.toLowerCase() : inputLetter.toUpperCase();
  148.             }
  149.            
  150.             if(config.multipleLanguages) {
  151.                 const displayLanguage = language.substring(0, 1).toUpperCase() + language.substring(1);
  152.                 sendChat(msg.who, `[${displayLanguage}] ${output}`);
  153.             } else {
  154.                 sendChat(msg.who, output);
  155.             }
  156.             sendChat(msg.who, `/w gm ${displayInput}`);
  157.         }
  158.     });
  159.    
  160.     // Say a message in the encoded language.
  161.     on('chat:message', function(msg) {
  162.         if(!config.enabled) return;
  163.         if(msg.type == 'api' && msg.content.indexOf('!learn') == 0) {
  164.             log(state.knowledge);
  165.             if(!state.cipher) {
  166.                 return;
  167.             }
  168.  
  169.             if(!state.knowledge) state.knowledge = {};
  170.             let args = msg.content.split(/\s+/);
  171.    
  172.             let language = 'common';
  173.            
  174.             if(config.multipleLanguages) {
  175.                 if(args.length > 1) {
  176.                     language = args[1].toLowerCase();
  177.                 }
  178.             }
  179.  
  180.             let newKnowledge = state.knowledge[language] + 1;
  181.            
  182.             if(args.length > 1) {
  183.                 let input = parseInt(args[1]);
  184.                 if (input == input) {
  185.                     newKnowledge = input;
  186.                 } else if(args.length > 2) {
  187.                     input = parseInt(args[2]);
  188.                     if (input == input) {
  189.                         newKnowledge = input;
  190.                     }
  191.                 }
  192.             }
  193.            
  194.             state.knowledge[language] = newKnowledge;
  195.  
  196.             if(config.multipleLanguages) {
  197.                 const displayLanguage = language.substring(0, 1).toUpperCase() + language.substring(1);
  198.                 sendChat('Translator', `/w gm Knowledge set to ${state.knowledge[language]} for language ${displayLanguage}.`);
  199.             } else {
  200.                 sendChat('Translator', `/w gm Knowledge set to ${state.knowledge[language]}.`);
  201.             }
  202.         }
  203.     });
  204.    
  205.     // Input: A string of characters
  206.     // Output: The same string in random order
  207.     function shuffle(input) {
  208.         if(input.length < 2) return input;
  209.        
  210.         let a = input.split("");
  211.         let b = [];
  212.         let count = 0;
  213.        
  214.         // Not using the Fisher–Yates shuffle because it can land a letter in the same spot it used to be, and we never want that
  215.         while(a.length > 0) {
  216.             let id = Math.floor(Math.random() * a.length);
  217.             while(id == count) {
  218.                 id = Math.floor(Math.random() * a.length);
  219.             }
  220.             b.push(a[id]);
  221.             a.splice(id, 1);
  222.             count++;
  223.         }
  224.        
  225.         return b.join("");
  226.     }
  227. });
Advertisement
Add Comment
Please, Sign In to add comment