[Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Learn how to use AAO by reading tutorials, and seek help from the AAO community.

Moderator: EN - Forum Moderators

Post Reply
User avatar
TimeAxis
Posts: 394
Joined: Fri Jan 01, 2021 8:27 pm
Spoken languages: English
Contact:

[Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by TimeAxis »

Better Layout:
Spoiler : :
Keyboard Controls:
Spoiler : Keyboard Control Script :
If you're like me and hate having to use the mouse to click repeatedly to advance text in order to play through AAO cases, this script may be for you. It allows you to press 'enter' or 'space' to advance text. You will still need to use the mouse to select dialogue options or navigate most menus, though. There's also a little bonus feature. Holding 'ctrl' will allow you to rapidly skip forward. (Warning: Skipping could potentially cause bugs or other weird behavior. I tested it a bit and it was fine, especially for straight-forward text sections, but I make no guarantees.)

You can use it in one of two ways.

Method 1: Installing it as a Userscript.
Step 1: Install a User Script Extension for your Browser. (On Firefox there is Tampermonkey, Greasemonkey, or Violentmonkey. To name a few. On Chrome, there is Tampermonkey) Keep in mind that I'm not responsible for any of these extensions and you should be sure to pick one that you personally trust. I also probably can't help you with troubleshooting these extensions as I don't use them very often. I recommend google if you have trouble.
Step 2: Once the extension is installed, either click here and install it (most extensions will allow you to install it from that link) or copy the code below into a new user script.

Method 2: Copying and Pasting it into your browser.
If you don't want to use a Userscript, right-click on the player page, press Inspect, and open the Console tab, then copy and paste the following code into the Console and press Enter. You would have to do this every time you want to use it, as it doesn't save if you leave or refresh the page.

Code: Select all

// ==UserScript==
// @name         AAO Keyboard Controls
// @namespace    AAOKeyboardControls
// @version      1.1
// @description  Allow Enter/Space/Shift to be used in AAO
// @author       TimeAxis
// @match        *://*aaonline.fr/player.php*
// @match        *://aaonline.fr/player.php*
// @grant        none
// ==/UserScript==

//////////////////////////////////////////////////////////
//                   KEYBOARD CONTROLS
//////////////////////////////////////////////////////////


// Define the key codes for arrow keys
const aaokeyboard_keyCodes = {
  enter: 13,
  space: 32,
  shift: 16,
};

// Function to check if an element is visible
function aaokeyboard_isVisible(element) {
  const style = getComputedStyle(element);
  return style.display !== 'none' && style.visibility !== 'hidden';
}

// Define the target image source URLs for each arrow key
const aaokeyboard_targetImageSrcs = {
  enter: ["http://www.aaonline.fr/img/player/proceed.gif","http://www.aaonline.fr/img/player/skip.gif","http://aaonline.fr/img/player/proceed.gif","http://aaonline.fr/img/player/skip.gif","https://aaonline.fr/img/player/proceed.gif","https://aaonline.fr/img/player/skip.gif","https://www.aaonline.fr/img/player/proceed.gif","https://www.aaonline.fr/img/player/skip.gif","https://aaonline.fr/img/player/statement_forwards.gif","http://aaonline.fr/img/player/statement_forwards.gif","https://www.aaonline.fr/img/player/statement_forwards.gif","http://www.aaonline.fr/img/player/statement_forwards.gif","https://aaonline.fr/img/player/statement_skip_forwards.gif","http://aaonline.fr/img/player/statement_skip_forwards.gif","https://www.aaonline.fr/img/player/statement_skip_forwards.gif","http://www.aaonline.fr/img/player/statement_skip_forwards.gif"],
};

// Keep track of the Enter key press state and whether a click has been performed
let aaokeyboard_enterPressed = false;
let aaokeyboard_enterClicked = false;

// Function to simulate click on images with the target source URLs
function aaokeyboard_clickImagesWithSrc(srcArray) {
  const images = document.querySelectorAll('img');
  let clicked = false; // Flag to track if a click has been performed
  images.forEach(img => {
    if (aaokeyboard_isVisible(img) && aaokeyboard_isVisible(img.parentElement) && !clicked) {
      // Perform case-insensitive comparison of URLs
      const imgSrc = img.src.toLowerCase();
      srcArray.forEach(src => {
        if (imgSrc === src.toLowerCase()) {
          img.click();
          clicked = true; // Set the flag to prevent multiple clicks
          return; // Break out of loop after clicking the first visible image
        }
      });
    }
  });
}

document.addEventListener("keydown", event => {
  const keyCode = event.keyCode;
  if ((keyCode === aaokeyboard_keyCodes.enter || keyCode === aaokeyboard_keyCodes.space) && !aaokeyboard_enterClicked && !aaokeyboard_enterPressed) {
    aaokeyboard_enterPressed = true;
    aaokeyboard_clickImagesWithSrc(aaokeyboard_targetImageSrcs.enter);
    aaokeyboard_enterClicked = true;
    event.preventDefault(); // Prevent default behavior
  }
  if (keyCode === aaokeyboard_keyCodes.shift) {
    aaokeyboard_enterPressed = false;
    aaokeyboard_enterClicked = false;
    aaokeyboard_clickImagesWithSrc(aaokeyboard_targetImageSrcs.enter);
    event.preventDefault(); // Prevent default behavior
  }
});

document.addEventListener("keyup", event => {
  const keyCode = event.keyCode;
  if (keyCode === aaokeyboard_keyCodes.enter) {
    aaokeyboard_enterPressed = false;
    aaokeyboard_enterClicked = false;
  }
  if (keyCode === aaokeyboard_keyCodes.space) {
    aaokeyboard_enterPressed = false;
    aaokeyboard_enterClicked = false;
  }
});

console.log("AAOKeyboard Script loaded.");
Disclaimer: This script is not endorsed by Unas or the AAO staff. Always be careful when installing user scripts or running code through your browser. Only install scripts from sources you trust. In this case, the code is right there for anyone to read it, so feel free to review it and check for anything shady.
Backlog Script:
Spoiler : Backlog :
I have a terrible memory when going through cases, so if you're like me, you could probably use this. It adds a backlog that lets you review the last 100 dialogue lines.

Method 1: Installing it as a Userscript.
Step 1: Install a User Script Extension for your Browser. (On Firefox there is Tampermonkey, Greasemonkey, or Violentmonkey. To name a few. On Chrome, there is Tampermonkey) Keep in mind that I'm not responsible for any of these extensions and you should be sure to pick one that you personally trust. I also probably can't help you with troubleshooting these extensions as I don't use them very often. I recommend google if you have trouble.
Step 2: Once the extension is installed, either click here and install it (most extensions will allow you to install it from that link) or copy the code below into a new user script.

Method 2: Copying and Pasting it into your browser.
If you don't want to use a Userscript, right-click on the player page, press Inspect, and open the Console tab, then copy and paste the following code into the Console and press Enter. You would have to do this every time you want to use it, as it doesn't save if you leave or refresh the page.

Code: Select all

// ==UserScript==
// @name         AAO Backlog Script
// @namespace    AAOlogscript
// @version      1.1
// @description  Adds a Backlog button to AAO trials
// @author       TimeAxis
// @match        *://*aaonline.fr/player.php*
// @match        *://aaonline.fr/player.php*
// @grant        none
// ==/UserScript==

    console.log("logscript_init() function started.");

	const logscript_oldproceed = proceed;

	var logscript_lastText = "";
	var logscript_lastName = "";
	var logscript_lastFrameID = -1;
	var logscript_lastMerged = false;

	var logscript_currentFrameData = false; 
	var logscript_currentText = "";
	var logscript_currentName = "";
	var logscript_currentFrameID = -1;
	var logscript_mergedFrame = false;

	var logscript_log = [];

	proceed = function(conditions, backwards){
		logscript_currentFrameData = trial_data.frames[player_status.current_frame_index];

		logscript_currentFrameID = logscript_currentFrameData.id;
		logscript_mergedFrame = logscript_currentFrameData.merged_to_next;
		logscript_currentText = top_screen.text_display.dialogue_box.innerHTML;
		logscript_currentName = top_screen.text_display.name_box.innerHTML;

		//Check for partially completed textbox
		var ls_fake_container = document.createElement('div');
		top_screen.text_display.instantTypeText(ls_fake_container, top_screen.text_display.dialogue_box.textContent);
		var ls_clean_text_contents1 = ls_fake_container.textContent.trim();
		ls_fake_container.remove();
		ls_fake_container = document.createElement('div');
		top_screen.text_display.instantTypeText(ls_fake_container, logscript_currentFrameData.text_content);
		var ls_clean_text_contents2 = ls_fake_container.textContent.trim();
		ls_fake_container.remove();
		ls_fake_container = null;
		
		const logscript_result = logscript_oldproceed.apply(this, arguments);

		if (ls_clean_text_contents1 == ls_clean_text_contents2 || (logscript_lastMerged)){
			if ((!logscript_mergedFrame) && (logscript_currentFrameID != logscript_lastFrameID) && ((player_status.proceed_click_met) || (player_status.proceed_timer_met && player_status.proceed_timer && player_status.proceed_typing) || (player_status.proceed_typing_met) || ((!player_status.proceed_click_met) && (!player_status.proceed_timer_met) && (!player_status.proceed_typing_met))) && (logscript_currentText != "")){
				logscript_addToLog(logscript_currentName,logscript_currentText);
				logscript_refreshLog();

				logscript_lastText = logscript_currentText;
				logscript_lastName = logscript_currentName;
				logscript_lastFrameID = logscript_currentFrameID;
				logscript_lastMerged = logscript_mergedFrame;
			}
		} else {
			console.log("1:" + ls_clean_text_contents1 +"/2:" + ls_clean_text_contents2);
			logscript_lastMerged = logscript_mergedFrame;
		}



		return logscript_result;
	};

	function logscript_addToLog(name, frametext) {
		if (logscript_log.length > 99) {
			// Remove the first element
			logscript_log.shift();
		}
		logscript_log.push([name, frametext]);
	}

	function logscript_refreshLog(){
		const logscript_contentContainer = document.getElementById('backlog_content');
		logscript_contentContainer.innerHTML = ""
		for(let i = 0; i < logscript_log.length; i++){
			let name = logscript_log[i][0];
			let dialogue = logscript_log[i][1];
			if(name != ""){
				logscript_contentContainer.innerHTML = logscript_contentContainer.innerHTML + "<span class='backlog-name'>" + name + "</span><br/><div class='backlog-text'>" + dialogue + "</div>";
			} else {
				logscript_contentContainer.innerHTML = logscript_contentContainer.innerHTML + "<br/><div class='backlog-text'>" + dialogue + "</div>";
			}
		}
		logscript_contentContainer.scrollTop = logscript_contentContainer.scrollHeight;
	}

	// Create a button element
	const logscript_logButton = document.createElement("button");

	// Set the button's CSS style
	logscript_logButton.style.position = 'absolute';
	logscript_logButton.style.top = '-2px';
	logscript_logButton.style.left = '-2px';

	// Find the parent element with the id "screen-meta"
	const logscript_screenMeta = document.getElementById('screen-meta');

	// Append the button to the parent element
	logscript_screenMeta.appendChild(logscript_logButton);
	logscript_logButton.id = "backlog-button";
	logscript_logButton.innerHTML = "Backlog"; 
	logscript_logButton.onclick = toggleBacklog;

	// Create Backlog HTML and CSS
	function logscript_generateBacklog() {
		// Create main container
		const logscript_container = document.createElement('div');
		logscript_container.id = 'backlog';
		logscript_container.className = 'backlog-container';

		// Create header
		const logscript_header = document.createElement('div');
		logscript_header.className = 'backlog-header';
		logscript_header.textContent = 'Backlog:';

		// Create close icon
		const logscript_closeIcon = document.createElement('div');
		logscript_closeIcon.className = 'backlog-close-icon';
		logscript_closeIcon.textContent = '✖';
		logscript_closeIcon.onclick = closeBacklog;

		// Append close icon to the header
		logscript_header.appendChild(logscript_closeIcon);

		// Create content container
		const logscript_contentContainer = document.createElement('div');
		logscript_contentContainer.id = 'backlog_content';
		logscript_contentContainer.className = 'backlog-content';

		// Append header and content to the main container
		logscript_container.appendChild(logscript_header);
		logscript_container.appendChild(logscript_contentContainer);

		// Append the main container to the document body
		const logscript_parentDiv = document.getElementById('screens');
		logscript_parentDiv.insertBefore(logscript_container, logscript_parentDiv.childNodes[2]);
		logscript_container.style.display = 'none';

		// Create style element
		const styleElement = document.createElement('style');
		styleElement.textContent = `
			.backlog-container {
				width: 254px;
				z-index: 999;
				height: 185px;
				position: absolute;
				color: white;
				left: 0px;
				width: 256px;
				min-height: 52px;
				margin: 10px;
				padding: 2px 2px 2px 2px;
				border: 2px ridge rgba(136, 136, 136, 0.75);
				border-radius: 3px;
				resize: none;
				background: rgba(0, 0, 0, 0.85);
				font: 12px aaDialogueText, sans-serif;
				text-align: start;
				line-height: 16px;
			}

			.backlog-header {
				font: 12px sans-serif;
				color: white;
			}

			.backlog-close-icon {
				position: absolute;
				top: 1px;
				right: 2px;
				cursor: pointer;
				font: 12px sans-serif;
				text-align: start;
				white-space: pre-wrap;
				line-height: 16px;
				color: white;
			}

			.backlog-close-icon:hover {
				color: grey;
			}

			.backlog-content {
				overflow-y: auto !important;
				height: 150px;
				text-align: left;
				scrollbar-width: thin;
				padding: 20px 10px 0px 0px;
				position: relative;
				width: 256px;
				color: white;
			}
			
			.backlog-name {
				margin-top: 7px;
				height: 12px;
				min-width: 44px;
				padding: 0 2px;
				overflow: hidden;
				border: 2px ridge rgba(136,136,136,0.75);
				border-radius: 3px;
				background: rgba(27,34,108,0.75);
				white-space: nowrap;
				font-size: 10px;
				line-height: 10px;
				color: white;
			}

			.backlog-text {
				margin-bottom: 0px;
			}
		`;

		// Append style element to the document head
		document.head.appendChild(styleElement);
	}

	// Function to close backlog (example function, replace with your logic)
	function closeBacklog() {
		const logscript_container = document.getElementById('backlog');
		logscript_container.style.display = 'none';
	}

	function openBacklog() {
		const logscript_container = document.getElementById('backlog');
		const logscript_contentContainer = document.getElementById('backlog_content');

		logscript_container.style.display = 'block';
		logscript_contentContainer.scrollTop = logscript_contentContainer.scrollHeight;
	}

	function toggleBacklog() {
		const logscript_container = document.getElementById('backlog');
		if (logscript_container.style.display === 'none' || logscript_container.style.display === '') {
			openBacklog();
		} else {
			closeBacklog();
		}
		logscript_logButton.blur();
	}

	// Call the function to generate HTML and CSS
	logscript_generateBacklog();

Disclaimer: This script is not endorsed by Unas or the AAO staff. Always be careful when installing user scripts or running code through your browser. Only install scripts from sources you trust. In this case, the code is right there for anyone to read it, so feel free to review it and check for anything shady.
If anyone really wants a certain script, I may be willing to do it, but keep in mind the following is either not possible or beyond my ability:
- Keyboard control on examining places, with some kind of cursor. (I tried it, it was a nightmare. Not happening)
- Multiplayer/Amogus/Doom (Yes, they're probably possible, no I'm not doing it.)
- Things that would render a case unplayable without the script. (This would more just be unwise.)
Last edited by TimeAxis on Sat Dec 09, 2023 1:58 pm, edited 9 times in total.
Image
Question Arcs (Threads Coming Eventually)
ImageImageImageImage
Gaiden Episodes
Champion of Turnabouts ★
HALLOWEEN HERO
Other
Phoenix Wright: Ace Attornauts
The Curious Case of the Phantom Limousine (Coming Eventually)
The Imposter's Turnabout (Coming Maybe)
User avatar
SuperAj3
Posts: 1321
Joined: Wed Sep 01, 2010 11:19 am
Spoken languages: English, 日本語(少しだけ)
Location: on the Flip Side

Re: [Tool] AAO Keyboard Controls Script

Post by SuperAj3 »

This is seriously amazing to see! A feature I've wished existed for years now.

Definitely will see how this goes but amazing work Time!
ImageImageImageImage
User avatar
risefromtheashes
Posts: 380
Joined: Wed Apr 04, 2018 2:33 am
Spoken languages: English, Russian, Armenian, Spanish

Re: [Tool] AAO Keyboard Controls Script

Post by risefromtheashes »

Image

Edit: In all seriousness, this made me realize how cool it would be to have arrow key selections for multiple choice prompts and examining/pinpointing locations on a background.
The Mindcastle System
(Don't know what a system is? Play 6-4, and take a look here.)
----------
OUR CASES:
- Athena Cykes ~ Locks on the Heart (synopsis)
- May Your Memory Be a Blessing
- A Little Piece of Healing
- The Killer Turnabout (~70% complete!)
- I guess we made the Looking Back case comp ceremony with Super legenda, but that's not an actual case

----------
Check out our music & art thread here!
User avatar
TimeAxis
Posts: 394
Joined: Fri Jan 01, 2021 8:27 pm
Spoken languages: English
Contact:

Re: [Tool] AAO Keyboard Controls Script

Post by TimeAxis »

While I could theoretically make a hotkey to click on any particular known unique button (like I did manage to make an arrow key movement script for Halloween Hero, and I could add present/press hotkeys, although I don't really feel like it atm), dialogue choice buttons don't have any unique identifiers, so there's no way that I'm aware of to identify which one to click, and making a whole "highlight and select" system would be way beyond me.

The best I could even imagine on that front would be if cases were specifically designed with the script in mind and added their own identifiers to choices, like detecting whether a dialogue option has a number 1-9 at the beginning, and making the number keys automatically click the corresponding option. But that's just spitballing, I have no plans to attempt that currently.
Image
Question Arcs (Threads Coming Eventually)
ImageImageImageImage
Gaiden Episodes
Champion of Turnabouts ★
HALLOWEEN HERO
Other
Phoenix Wright: Ace Attornauts
The Curious Case of the Phantom Limousine (Coming Eventually)
The Imposter's Turnabout (Coming Maybe)
User avatar
TimeAxis
Posts: 394
Joined: Fri Jan 01, 2021 8:27 pm
Spoken languages: English
Contact:

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by TimeAxis »

I've made a script that adds a Backlog button to the left of the Lifebar. This one should be compatible with the keyboard script with no issues. Haven't tested it on any super long cases, so feel free to let me know if anything breaks.

Backlog Script:
Spoiler : Backlog :
I have a terrible memory when going through cases, so if you're like me, you could probably use this. It adds a backlog that lets you review that last 100 dialogue lines.

Method 1: Installing it as a Userscript.
Step 1: Install a User Script Extension for your Browser. (On Firefox there is Tampermonkey, Greasemonkey, or Violentmonkey. To name a few. On Chrome, there is Tampermonkey) Keep in mind that I'm not responsible for any of these extensions and you should be sure to pick one that you personally trust. I also probably can't help you with troubleshooting these extensions as I don't use them very often. I recommend google if you have trouble.
Step 2: Once the extension is installed, either click here and install it (most extensions will allow you to install it from that link) or copy the code below into a new user script.

Method 2: Copying and Pasting it into your browser.
If you don't want to use a Userscript, right-click on the player page, press Inspect, and open the Console tab, then copy and paste the following code into the Console and press Enter. You would have to do this every time you want to use it, as it doesn't save if you leave or refresh the page.

Code: Select all

// ==UserScript==
// @name         AAO Backlog Script
// @namespace    AAOlogscript
// @version      1.1
// @description  Adds a Backlog button to AAO trials
// @author       TimeAxis
// @match        *://*aaonline.fr/player.php*
// @match        *://aaonline.fr/player.php*
// @grant        none
// ==/UserScript==

    console.log("logscript_init() function started.");

	const logscript_oldproceed = proceed;

	var logscript_lastText = "";
	var logscript_lastName = "";
	var logscript_lastFrameID = -1;
	var logscript_lastMerged = false;

	var logscript_currentFrameData = false; 
	var logscript_currentText = "";
	var logscript_currentName = "";
	var logscript_currentFrameID = -1;
	var logscript_mergedFrame = false;

	var logscript_log = [];

	proceed = function(conditions, backwards){
		logscript_currentFrameData = trial_data.frames[player_status.current_frame_index];

		logscript_currentFrameID = logscript_currentFrameData.id;
		logscript_mergedFrame = logscript_currentFrameData.merged_to_next;
		logscript_currentText = top_screen.text_display.dialogue_box.innerHTML;
		logscript_currentName = top_screen.text_display.name_box.innerHTML;

		//Check for partially completed textbox
		var ls_fake_container = document.createElement('div');
		top_screen.text_display.instantTypeText(ls_fake_container, top_screen.text_display.dialogue_box.textContent);
		var ls_clean_text_contents1 = ls_fake_container.textContent.trim();
		ls_fake_container.remove();
		ls_fake_container = document.createElement('div');
		top_screen.text_display.instantTypeText(ls_fake_container, logscript_currentFrameData.text_content);
		var ls_clean_text_contents2 = ls_fake_container.textContent.trim();
		ls_fake_container.remove();
		ls_fake_container = null;
		
		const logscript_result = logscript_oldproceed.apply(this, arguments);

		if (ls_clean_text_contents1 == ls_clean_text_contents2 || (logscript_lastMerged)){
			if ((!logscript_mergedFrame) && (logscript_currentFrameID != logscript_lastFrameID) && ((player_status.proceed_click_met) || (player_status.proceed_timer_met && player_status.proceed_timer && player_status.proceed_typing) || (player_status.proceed_typing_met) || ((!player_status.proceed_click_met) && (!player_status.proceed_timer_met) && (!player_status.proceed_typing_met))) && (logscript_currentText != "")){
				logscript_addToLog(logscript_currentName,logscript_currentText);
				logscript_refreshLog();

				logscript_lastText = logscript_currentText;
				logscript_lastName = logscript_currentName;
				logscript_lastFrameID = logscript_currentFrameID;
				logscript_lastMerged = logscript_mergedFrame;
			}
		} else {
			console.log("1:" + ls_clean_text_contents1 +"/2:" + ls_clean_text_contents2);
			logscript_lastMerged = logscript_mergedFrame;
		}



		return logscript_result;
	};

	function logscript_addToLog(name, frametext) {
		if (logscript_log.length > 99) {
			// Remove the first element
			logscript_log.shift();
		}
		logscript_log.push([name, frametext]);
	}

	function logscript_refreshLog(){
		const logscript_contentContainer = document.getElementById('backlog_content');
		logscript_contentContainer.innerHTML = ""
		for(let i = 0; i < logscript_log.length; i++){
			let name = logscript_log[i][0];
			let dialogue = logscript_log[i][1];
			if(name != ""){
				logscript_contentContainer.innerHTML = logscript_contentContainer.innerHTML + "<span class='backlog-name'>" + name + "</span><br/><div class='backlog-text'>" + dialogue + "</div>";
			} else {
				logscript_contentContainer.innerHTML = logscript_contentContainer.innerHTML + "<br/><div class='backlog-text'>" + dialogue + "</div>";
			}
		}
		logscript_contentContainer.scrollTop = logscript_contentContainer.scrollHeight;
	}

	// Create a button element
	const logscript_logButton = document.createElement("button");

	// Set the button's CSS style
	logscript_logButton.style.position = 'absolute';
	logscript_logButton.style.top = '-2px';
	logscript_logButton.style.left = '-2px';

	// Find the parent element with the id "screen-meta"
	const logscript_screenMeta = document.getElementById('screen-meta');

	// Append the button to the parent element
	logscript_screenMeta.appendChild(logscript_logButton);
	logscript_logButton.id = "backlog-button";
	logscript_logButton.innerHTML = "Backlog"; 
	logscript_logButton.onclick = toggleBacklog;

	// Create Backlog HTML and CSS
	function logscript_generateBacklog() {
		// Create main container
		const logscript_container = document.createElement('div');
		logscript_container.id = 'backlog';
		logscript_container.className = 'backlog-container';

		// Create header
		const logscript_header = document.createElement('div');
		logscript_header.className = 'backlog-header';
		logscript_header.textContent = 'Backlog:';

		// Create close icon
		const logscript_closeIcon = document.createElement('div');
		logscript_closeIcon.className = 'backlog-close-icon';
		logscript_closeIcon.textContent = '✖';
		logscript_closeIcon.onclick = closeBacklog;

		// Append close icon to the header
		logscript_header.appendChild(logscript_closeIcon);

		// Create content container
		const logscript_contentContainer = document.createElement('div');
		logscript_contentContainer.id = 'backlog_content';
		logscript_contentContainer.className = 'backlog-content';

		// Append header and content to the main container
		logscript_container.appendChild(logscript_header);
		logscript_container.appendChild(logscript_contentContainer);

		// Append the main container to the document body
		const logscript_parentDiv = document.getElementById('screens');
		logscript_parentDiv.insertBefore(logscript_container, logscript_parentDiv.childNodes[2]);
		logscript_container.style.display = 'none';

		// Create style element
		const styleElement = document.createElement('style');
		styleElement.textContent = `
			.backlog-container {
				width: 254px;
				z-index: 999;
				height: 185px;
				position: absolute;
				color: white;
				left: 0px;
				width: 256px;
				min-height: 52px;
				margin: 10px;
				padding: 2px 2px 2px 2px;
				border: 2px ridge rgba(136, 136, 136, 0.75);
				border-radius: 3px;
				resize: none;
				background: rgba(0, 0, 0, 0.85);
				font: 12px aaDialogueText, sans-serif;
				text-align: start;
				line-height: 16px;
			}

			.backlog-header {
				font: 12px sans-serif;
				color: white;
			}

			.backlog-close-icon {
				position: absolute;
				top: 1px;
				right: 2px;
				cursor: pointer;
				font: 12px sans-serif;
				text-align: start;
				white-space: pre-wrap;
				line-height: 16px;
				color: white;
			}

			.backlog-close-icon:hover {
				color: grey;
			}

			.backlog-content {
				overflow-y: auto !important;
				height: 150px;
				text-align: left;
				scrollbar-width: thin;
				padding: 20px 10px 0px 0px;
				position: relative;
				width: 256px;
				color: white;
			}
			
			.backlog-name {
				margin-top: 7px;
				height: 12px;
				min-width: 44px;
				padding: 0 2px;
				overflow: hidden;
				border: 2px ridge rgba(136,136,136,0.75);
				border-radius: 3px;
				background: rgba(27,34,108,0.75);
				white-space: nowrap;
				font-size: 10px;
				line-height: 10px;
				color: white;
			}

			.backlog-text {
				margin-bottom: 0px;
			}
		`;

		// Append style element to the document head
		document.head.appendChild(styleElement);
	}

	// Function to close backlog (example function, replace with your logic)
	function closeBacklog() {
		const logscript_container = document.getElementById('backlog');
		logscript_container.style.display = 'none';
	}

	function openBacklog() {
		const logscript_container = document.getElementById('backlog');
		const logscript_contentContainer = document.getElementById('backlog_content');

		logscript_container.style.display = 'block';
		logscript_contentContainer.scrollTop = logscript_contentContainer.scrollHeight;
	}

	function toggleBacklog() {
		const logscript_container = document.getElementById('backlog');
		if (logscript_container.style.display === 'none' || logscript_container.style.display === '') {
			openBacklog();
		} else {
			closeBacklog();
		}
		logscript_logButton.blur();
	}

	// Call the function to generate HTML and CSS
	logscript_generateBacklog();

Disclaimer: This script is not endorsed by Unas or the AAO staff. Always be careful when installing user scripts or running code through your browser. Only install scripts from sources you trust. In this case, the code is right there for anyone to read it, so feel free to review it and check for anything shady.
Image
Question Arcs (Threads Coming Eventually)
ImageImageImageImage
Gaiden Episodes
Champion of Turnabouts ★
HALLOWEEN HERO
Other
Phoenix Wright: Ace Attornauts
The Curious Case of the Phantom Limousine (Coming Eventually)
The Imposter's Turnabout (Coming Maybe)
User avatar
TimeAxis
Posts: 394
Joined: Fri Jan 01, 2021 8:27 pm
Spoken languages: English
Contact:

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by TimeAxis »

AAO Better Layout Script
For people who want a bigger, more centered screen.
Image
Features
  • 1.5x Larger Screen (With option to make it 2x)
  • Toggle image interpolation on or off (For that pixelated effect)
  • Choose between the court record being on the left or right of the screen
  • Toggle Evidence descriptions to always be expanded (You can still only see 3 lines of text and need to hover over them to see the rest)
  • Night mode, for AAO night-owls
  • Fully compatible with the Backlog and Keyboard Control scripts
Get it HERE.
See instruction for other scripts in the OP for how to use it.

Also, since it was requested, here is a small script that changes the font on the nametags.
Image
Question Arcs (Threads Coming Eventually)
ImageImageImageImage
Gaiden Episodes
Champion of Turnabouts ★
HALLOWEEN HERO
Other
Phoenix Wright: Ace Attornauts
The Curious Case of the Phantom Limousine (Coming Eventually)
The Imposter's Turnabout (Coming Maybe)
User avatar
Enthalpy
Community Manager
Posts: 5175
Joined: Wed Jan 04, 2012 4:40 am
Gender: Male
Spoken languages: English, limited Spanish

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by Enthalpy »

That's impressive! I may give this a try myself.
[D]isordered speech is not so much injury to the lips that give it forth, as to the disproportion and incoherence of things in themselves, so negligently expressed. ~ Ben Jonson
User avatar
drvonkitty
Posts: 567
Joined: Sat Apr 14, 2012 12:25 am
Spoken languages: English

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by drvonkitty »

i've been using these scripts for a few weeks now & i just wanted to give major props to timeaxis--thanks for making this. the "pixelated" filter, for example, is such a small thing but a massive improvement to case presentation and feel. i would love to see that become the default for AAO if at all possible!
Image

Image
User avatar
Tilemaxosbra
Posts: 24
Joined: Wed Apr 08, 2015 1:48 am
Gender: Male
Spoken languages: English and Greek

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by Tilemaxosbra »

Would a script for a text "auto-mode" be possible to do? The Great Ace Attorney Chronicles and various other games have it as a feature, and I think it'd benefit this place too.
User avatar
TimeAxis
Posts: 394
Joined: Fri Jan 01, 2021 8:27 pm
Spoken languages: English
Contact:

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by TimeAxis »

Tilemaxosbra wrote: Thu Apr 18, 2024 9:02 pm Would a script for a text "auto-mode" be possible to do? The Great Ace Attorney Chronicles and various other games have it as a feature, and I think it'd benefit this place too.
If it was just a simple "press the button every few seconds" thing, it wouldn't be too hard, but I can think of a few small issues and challenges that would come with it. Actually doing it properly and accounting for when a message has finished displaying and stuff might be a little beyond me.

It's not impossible, though. May consider trying it for the future.
Image
Question Arcs (Threads Coming Eventually)
ImageImageImageImage
Gaiden Episodes
Champion of Turnabouts ★
HALLOWEEN HERO
Other
Phoenix Wright: Ace Attornauts
The Curious Case of the Phantom Limousine (Coming Eventually)
The Imposter's Turnabout (Coming Maybe)
User avatar
eerew
Posts: 212
Joined: Thu Aug 06, 2020 2:14 am
Gender: Male
Spoken languages: English
Location: In your walls
Contact:

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by eerew »

Tilemaxosbra wrote: Thu Apr 18, 2024 9:02 pm Would a script for a text "auto-mode" be possible to do? The Great Ace Attorney Chronicles and various other games have it as a feature, and I think it'd benefit this place too.
Autoclicker :D
ImageImage
Image
♂ + ♂ = ♥
♀ + ♀ = ♥
♀ + ♂ = ♥
Love should be genderless.
If you agree, please add this to your signature.


Legacy K.O.B since 2023

Proud friend of TWO ONE TWO he/theys
Image

Real Women
User avatar
Awsome2464
Posts: 209
Joined: Mon Mar 23, 2020 4:40 am
Gender: Male
Spoken languages: English
Location: United States

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by Awsome2464 »

I don't know how I'm only just now coming across these scripts, but this is absolutely incredible! No more having to zoom in my browser window to get a full screen experience AND enter to continue? Such a game changer. Excellent work!
Image Image
User avatar
Sheika
Posts: 290
Joined: Sat Apr 12, 2014 2:21 am
Spoken languages: Español / English / Peux lire français
Location: Uruguay (consult The Simpsons to know where it is)

Re: [Tool] TimeAxis's Scripts (Keyboard Control, Backlog)

Post by Sheika »

HOLY SHIT this is awesome. Ridiculously awesome. I've been wanting something like this for a long time, but my JavaScript skills aren't up to par. Immense thanks to TimeAxis.

If I may add a recommendation: those who have computer-compatible console controllers (moderately proud of that one) can use JoyToKey, a free app that essentially maps keyboard functions to a controller. It can also map mouse functions to a controller, so, for example, I can command it to instantly move the mouse to the position of the Press button and click at the press of the X button, effectively mapping the Press function or whatever other function to whichever button I want on my controller. You can seamlessly switch through multiple settings (I use one for advancing the game and one for moving through the Court Record, switching back and forth by pressing R) and map mouse movement to the sticks, so you lose nothing. Like TimeAxis, I also hate having to use the mouse for everything, so this made my AAO experience a million times better.

I'm going to have to remap it all now that I know about these scripts xD
Spoiler : @TimeAxis or any other programmers :
While I could theoretically make a hotkey to click on any particular known unique button (like I did manage to make an arrow key movement script for Halloween Hero, and I could add present/press hotkeys, although I don't really feel like it atm), dialogue choice buttons don't have any unique identifiers, so there's no way that I'm aware of to identify which one to click, and making a whole "highlight and select" system would be way beyond me.
Image
The options can be simply identified as #options.children[n].

Image
Tried this and it seems to work perfectly. This can be hotlinked to keys 1-9, one option per key. (Admittedly, you'll rarely ever need more than 4 options.)
If it was just a simple "press the button every few seconds" thing, it wouldn't be too hard, but I can think of a few small issues and challenges that would come with it. Actually doing it properly and accounting for when a message has finished displaying and stuff might be a little beyond me.
Maybe set it to only act when the normal proceed button is enabled? I don't think we'd need auto-advance in any other circumstance, and it provides a good reference for when to start the wait. Also, to anyone who wants to do this this, please make the waiting time configurable in options xD

I'm @runefaustblack.8998 in Discord if anyone wants me to test anything, but please know that my coding knowledge is minimal. Among may other things, I don't actually know how to map functions to keys, and last time I tried to find out I gave up early xD
Two days later, still angry about the smoke detector thing in Two Sides
Post Reply