aboutsummaryrefslogtreecommitdiff
path: root/webAO/client.js
diff options
context:
space:
mode:
Diffstat (limited to 'webAO/client.js')
-rw-r--r--webAO/client.js177
1 files changed, 156 insertions, 21 deletions
diff --git a/webAO/client.js b/webAO/client.js
index 84bd9bd..76ced68 100644
--- a/webAO/client.js
+++ b/webAO/client.js
@@ -26,6 +26,7 @@ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phon
oldLoading = true;
}
+let selectedEffect = 0;
let selectedShout = 0;
let lastICMessageTime = new Date(0);
@@ -37,6 +38,8 @@ class Client {
this.serv.onclose = (evt) => this.onClose(evt);
this.serv.onmessage = (evt) => this.onMessage(evt);
this.serv.onerror = (evt) => this.onError(evt);
+
+ this.flip = false;
this.playerID = 1;
this.charID = -1;
@@ -111,11 +114,11 @@ class Client {
* @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect
* @param {string} objection the number of the shout to play
*/
- sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) {
+ sendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, flip, flash, color) {
this.serv.send(
`MS#chat#${speaking}#${name}#${silent}` +
`#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` +
- `#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%`
+ `#${this.charID}#${ssfxdelay}#${selectedShout}#0#${flip}#${flash}#${color}#%`
);
}
@@ -243,7 +246,7 @@ class Client {
if (args[4] != viewport.chatmsg.content) {
document.getElementById("client_inner_chat").innerHTML = "";
let chatmsg = {
- pre: escape(args[2]),
+ // pre: escape(args[2]),
character: -1, // Will do a linear search
preanim: escape(args[2]), // XXX: why again?
nameplate: args[3], // TODO: parse INI to get this info
@@ -258,7 +261,7 @@ class Client {
snddelay: args[10],
objection: args[11],
evidence: args[12],
- // flip: args[13],
+ flip: args[13],
flash: args[14],
color: args[15],
isnew: true,
@@ -569,10 +572,12 @@ class Viewport {
"content": "",
"objection": "0",
"sound": "",
+ "startpreanim": false,
"startspeaking": false,
"side": null,
"color": "0",
- "snddelay": 0
+ "snddelay": 0,
+ "preanimdelay": 0
};
this.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');
this.blip.volume = 0.5;
@@ -641,7 +646,61 @@ class Viewport {
this.textTimer = 0;
this._animating = true;
clearTimeout(this.updater);
- this.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);
+ //If preanim existed then determine the length
+ if (chatmsg.preanim != "-") {
+ chatmsg.preanimdelay = this.getAnimLength(AO_HOST + 'characters/' + escape(chatmsg.name) + '/' + chatmsg.preanim + '.gif',this.initUpdater);
+ } else {
+ this.initUpdater(0)
+ }
+ }
+
+ /**
+ * Intialize updater
+ * @param {int} animdelay the length of pre-animation
+ */
+ initUpdater(animdelay){
+ console.log(animdelay);
+ viewport.chatmsg.preanimdelay = parseInt(animdelay);
+ viewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL);
+ }
+
+ /**
+ * Gets animation length.
+ * @param {string} filename the animation file name
+ * @param {function} callback the callback function
+ */
+ getAnimLength(filename,callback) {
+ //Source (Thanks to Ryman): https://codepen.io/Ryman/pen/wzioA
+ var request = new XMLHttpRequest();
+ request.open('GET', filename, true);
+ request.responseType = 'arraybuffer';
+ request.addEventListener('load', function () {
+ var arr = new Uint8Array(request.response),
+ // Thanks to http://justinsomnia.org/2006/10/gif-animation-duration-calculation/
+ // And http://www.w3.org/Graphics/GIF/spec-gif89a.txt
+ bin = '',
+ duration = 0;
+
+ for (var i = 0; i < arr.length; i++) {
+ bin += String.fromCharCode( arr[i] )
+
+ // Find a Graphic Control Extension hex(21F904__ ____ __00)
+ if (arr[i] == 0x21
+ && arr[i + 1] == 0xF9
+ && arr[i + 2] == 0x04
+ && arr[i + 7] == 0x00) {
+ // Swap 5th and 6th bytes to get the delay per frame
+ let delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF)
+
+ // Should be aware browsers have a minimum frame delay
+ // e.g. 6ms for IE, 2ms modern browsers (50fps)
+ duration += delay < 2 ? 10 : (delay+2)
+ }
+ }
+ // Return animation length
+ callback(duration * 10);
+ });
+ request.send();
}
/**
@@ -650,41 +709,78 @@ class Viewport {
* XXX: This relies on a global variable `this.chatmsg`!
*/
updateText() {
- if (this.chatmsg.content.trim() == "") {
- document.getElementById("client_name").style.display = "none";
- document.getElementById("client_chat").style.display = "none";
+ // Flip the character
+ if (this.chatmsg.flip == 1){
+ document.getElementById("client_char").style.transform = "scaleX(-1)";
} else {
- document.getElementById("client_name").style.display = "block";
- document.getElementById("client_chat").style.display = "block";
+ document.getElementById("client_char").style.transform = "scaleX(1)";
}
-
+
if (this._animating) {
this.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);
}
if (this.chatmsg.isnew) {
+ // Reset screen background
+ document.getElementById("client_background").style.backgroundColor = "transparent";
+ //Hide message window
+ document.getElementById("client_name").style.display = "none";
+ document.getElementById("client_chat").style.display = "none";
+
const shouts = {
"1": "holdit",
- "2": "takethat",
- "3": "objection"
+ "2": "objection",
+ "3": "takethat"
};
let shout = shouts[this.chatmsg.objection];
if (typeof shout !== "undefined") {
- document.getElementById("client_char").src = AO_HOST + "misc/" + shout + ".gif";
+ document.getElementById("client_shout").src = AO_HOST + "misc/" + shout + ".gif";
(new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play();
- this.shoutTimer = 800;
+ this.shoutTimer = 850;
} else {
this.shoutTimer = 0;
}
this.chatmsg.isnew = false;
- this.chatmsg.startspeaking = true;
+ this.chatmsg.startpreanim = true;
}
- if (this.textTimer >= this.shoutTimer) {
- if (this.chatmsg.startspeaking) {
+ if(this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) {
+ // Effect stuff
+ if (this.chatmsg.flash == 2){
+ //Shake screen
+ this.sfxaudio.pause();
+ this.sfxplayed = 1;
+ this.sfxaudio.src = AO_HOST + "sounds/general/sfx-stab.wav";
+ this.sfxaudio.play();
+ $('#client_gamewindow').effect( "shake",{"direction":"up"});
+ } else if (this.chatmsg.flash == 1) {
+ //Flash screen
+ document.getElementById("client_background").style.backgroundColor = "white";
+ this.sfxaudio.pause();
+ this.sfxplayed = 1;
+ this.sfxaudio.src = AO_HOST + "sounds/general/sfx-realization.wav";
+ this.sfxaudio.play();
+ $('#client_gamewindow').effect("pulsate");
+ }
+
+ //Pre-animation stuff
+ if(this.chatmsg.preanimdelay > 0){
+ document.getElementById("client_shout").src = "";
changeBackground(this.chatmsg.side);
+ document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.preanim + ".gif";
+ }
+ this.chatmsg.startpreanim = false;
+ this.chatmsg.startspeaking = true;
+ } else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) {
+ if (this.chatmsg.startspeaking) {
+ $("#client_name").toggle( "fade" );
+ $("#client_chat").toggle("drop",{"direction":"down"});
+ if(this.chatmsg.preanimdelay == 0){
+ document.getElementById("client_shout").src = "";
+ changeBackground(this.chatmsg.side);
+ }
document.getElementById("client_char").src = AO_HOST + "characters/" + escape(this.chatmsg.name) + "/" + this.chatmsg.speaking + ".gif";
document.getElementById("client_name").style.fontSize = (document.getElementById("client_name").offsetHeight * 0.7) + "px";
document.getElementById("client_chat").style.fontSize = (document.getElementById("client_chat").offsetHeight * 0.25) + "px";
@@ -726,6 +822,7 @@ class Viewport {
}
}
}
+
if (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) {
this.sfxaudio.pause();
this.sfxplayed = 1;
@@ -790,13 +887,15 @@ export function onEnter(event) {
if (event.keyCode == 13) {
let mychar = client.me();
let myemo = client.myEmote();
+ let myflip = ((client.flip)? 1:0);
+ let mycolor = document.getElementById("textcolor").value;
let ssfxname = "0";
let ssfxdelay = "0";
if (document.getElementById("sendsfx").checked) {
ssfxname = myemo.sfx;
ssfxdelay = myemo.sfxdelay;
}
- client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout);
+ client.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById("client_inputbox").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout, myflip, selectedEffect, mycolor);
}
}
window.onEnter = onEnter;
@@ -808,10 +907,14 @@ window.onEnter = onEnter;
*/
function resetICParams() {
document.getElementById("client_inputbox").value = "";
+ if (selectedEffect) {
+ document.getElementById("button_effect_" + selectedEffect).className = "client_button";
+ selectedEffect = 0;
+ }
if (selectedShout) {
document.getElementById("button_" + selectedShout).className = "client_button";
selectedShout = 0;
- }
+ }
}
/**
@@ -1025,6 +1128,38 @@ export function pickemotion(emo) {
window.pickemotion = pickemotion;
/**
+ * Highlights and selects an effect for in-character chat.
+ * If the same effect button is selected, then the effect is canceled.
+ * @param {string} effect the new effect to be selected
+ */
+export function toggleaffect(effect) {
+ if (effect == selectedEffect) {
+ document.getElementById("button_effect_" + effect).className = "client_button";
+ selectedEffect = 0;
+ } else {
+ document.getElementById("button_effect_" + effect).className = "client_button dark";
+ if (selectedEffect) {
+ document.getElementById("button_effect_" + selectedEffect).className = "client_button";
+ }
+ selectedEffect = effect;
+ }
+}
+window.toggleaffect = toggleaffect;
+
+/**
+ * Toggle flip for in-character chat.
+ */
+export function toggleflip() {
+ if (client.flip) {
+ document.getElementById("button_flip").className = "client_button";
+ } else {
+ document.getElementById("button_flip").className = "client_button dark";
+ }
+ client.flip = !client.flip;
+}
+window.toggleflip = toggleflip;
+
+/**
* Highlights and selects a shout for in-character chat.
* If the same shout button is selected, then the shout is canceled.
* @param {string} shout the new shout to be selected