You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
404 lines
12 KiB
JavaScript
404 lines
12 KiB
JavaScript
/*
|
|
WARNING: THIS IS STILL EXPERIMENTAL STUFF
|
|
I want to have the ability to assign specific behaviors to each room without messing with the main engine
|
|
So this is a file for client-side modifications (mods). There is one for the server side as well.
|
|
Their naming convention is roomIdFunction.
|
|
The functions are called by the engine at crucial points, only if they exist.
|
|
*/
|
|
|
|
//when my players joins the game for the first time, after everything in the room is initialized
|
|
//called also for lurk mode (nickName == "")
|
|
|
|
var familyRoles;
|
|
var familyIntro = "The Family Room is for roleplay.\n"
|
|
var rolesInfo = {
|
|
wife: ["Emily", "You are Emily, a restless housewife."],
|
|
husband: ["Dick", "You are Richard and you are back from work."],
|
|
child1: ["Sam", "You are Samuel and you are upset"],
|
|
child2: ["Grace", "You are Grace, a princess."],
|
|
child3: ["Phoebe", "You are Phoebe, and life sucks."],
|
|
uncle: ["Uncle", "You are the Uncle and you don't remember what you were doing."],
|
|
milkman: ["Milkman", "You are the Milkman, and you are delivering milk."],
|
|
boyfriend: ["Jamal", "You are Jamal, Phoebe's new boyfriend."],
|
|
fly: ["Fly", "You are just a fly on the wall."],
|
|
}
|
|
|
|
function initMod(playerId, roomId) {
|
|
print("Mod: " + players[playerId].nickName + " (you) joined the game at " + roomId);
|
|
|
|
//prevent duplicate listeners
|
|
if (!socket.hasListeners('musicOn')) {
|
|
|
|
socket.on('musicOn', function (beat) {
|
|
|
|
SOUNDS["beat" + beat].loop();
|
|
bg.play();
|
|
});
|
|
|
|
//music is playing
|
|
socket.on('musicEnter', function (beat) {
|
|
//start from random
|
|
SOUNDS["beat" + beat].loop();
|
|
bg.play();
|
|
});
|
|
|
|
socket.on('musicOff', function (beat) {
|
|
print("The MOD module communicates with a custom socket event: music off");
|
|
//just to be sure I stop all the beats
|
|
SOUNDS["beat1"].stop();
|
|
SOUNDS["beat2"].stop();
|
|
SOUNDS["beat3"].stop();
|
|
SOUNDS.DJStop.play();
|
|
bg.rewind();
|
|
bg.stop();
|
|
});
|
|
|
|
|
|
//music is playing stop all bit without record scratch
|
|
socket.on('musicExit', function (beat) {
|
|
SOUNDS["beat1"].stop();
|
|
SOUNDS["beat2"].stop();
|
|
SOUNDS["beat3"].stop();
|
|
});
|
|
|
|
|
|
|
|
socket.on('updateRoles', function (newcomerId, fr) {
|
|
|
|
//keep track of the roles
|
|
familyRoles = fr;
|
|
var newcomerAssigned = false;
|
|
|
|
|
|
//change all the sprites just to be sure
|
|
for (var roleId in familyRoles) {
|
|
var rolePlayer = familyRoles[roleId];
|
|
|
|
//role assigned
|
|
if (rolePlayer != "") {
|
|
print(rolePlayer + " is roleplaying as " + roleId);
|
|
if (players[rolePlayer] != null) //player exists
|
|
{
|
|
//newcomer has a role
|
|
if (newcomerId == rolePlayer)
|
|
newcomerAssigned = true;
|
|
|
|
changeCharacter(rolePlayer, roleId, roleId + "Walk", roleId + "Emote");
|
|
|
|
//newcomer is me > intro text
|
|
if (newcomerId == me.id) {
|
|
longText = familyIntro + rolesInfo[roleId][1];
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//server doesn't bother to keep track of spectators so all newcomers without roles are flies
|
|
if (!newcomerAssigned) {
|
|
|
|
changeCharacter(newcomerId, "fly", "flyWalk", "flyEmote");
|
|
|
|
if (newcomerId == me.id) {
|
|
longText = familyIntro + rolesInfo.fly[1];
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//roomnameEnter: called when a player enters a room, after all the normal operations
|
|
//called also for lurk mode (nickName == "")
|
|
function experimentsEnter(playerId, roomId) {
|
|
print("MOD: " + players[playerId].nickName + " entered room " + roomId);
|
|
|
|
//a full screen welcome text appears
|
|
longText = "Welcome " + players[playerId].nickName;
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
|
|
//roomnameExit: called right before a player exits or disconnects
|
|
function experimentsExit(playerId) {
|
|
print("MOD: " + players[playerId].nickName + " exited room " + roomId);
|
|
}
|
|
|
|
//called every frame in a specific room - beware: this is client side, everything non deterministic and non server-driven
|
|
//may misalign the players clients
|
|
function experimentsUpdate() {
|
|
//print("MOD: updating experiments");
|
|
}
|
|
|
|
//roomnameTalk: called when somebody in the room talks, passes player object and the new bubble (before it's added to the stack and before the sound is made)
|
|
function experimentsTalk(playerId, bubble) {
|
|
print("MOD: " + players[playerId].nickName + " said " + bubble.message);
|
|
|
|
//overwrites the color
|
|
bubble.color = color("#FFFFFF");
|
|
//all bubbles show up in the center and lines are not drawn
|
|
/*
|
|
bubble.x = WIDTH / 2 - bubble.w / 2;
|
|
bubble.y = HEIGHT / 2;
|
|
bubble.px = 0;
|
|
bubble.py = 0;
|
|
*/
|
|
}
|
|
|
|
//this can override or modify the normal player drawing function
|
|
function experimentsDrawSprite(playerId, sprite, drawingFunction) {
|
|
//print("MOD: " + players[playerId].nickName + " being drawn experimentally " + sprite.width); //let's not call this at every frame
|
|
|
|
//the normal drawing function comment this out to see the examples below
|
|
drawingFunction();
|
|
|
|
/*
|
|
//don't try this
|
|
tint(random(0, 255), random(0, 255), random(0, 255));
|
|
drawingFunction();
|
|
noTint();
|
|
*/
|
|
|
|
//draw a square
|
|
/*
|
|
fill(0);
|
|
rect(0, 0, 10, 10);
|
|
*/
|
|
|
|
/*
|
|
//sprites drawn horizontally and 20 pixel above the grund
|
|
push();
|
|
translate(0, -20);
|
|
angleMode(DEGREES);
|
|
rotate(90);
|
|
//the original drawing function
|
|
drawingFunction();
|
|
pop();
|
|
*/
|
|
|
|
}
|
|
|
|
function mirrorRoomDrawSprite(playerId, sprite, drawingFunction) {
|
|
|
|
if (players[playerId] != null) {
|
|
//original
|
|
//sprite.mirrorX(1);
|
|
drawingFunction();
|
|
|
|
//mirrored
|
|
push();
|
|
scale(-1, 1);
|
|
|
|
if (sprite.mirrorX() == 1) {
|
|
translate(players[playerId].x - WIDTH / 2, 0);
|
|
}
|
|
else {
|
|
translate(WIDTH / 2 - players[playerId].x, 0);
|
|
}
|
|
//the original drawing function
|
|
drawingFunction();
|
|
pop();
|
|
}
|
|
}
|
|
|
|
function mirrorRoomTalk(playerId, bubble) {
|
|
var p = players[playerId];
|
|
var bx = (WIDTH - p.x);//(p.x < WIDTH / 2) ? (WIDTH - p.x) : (p.x - WIDTH / 2);
|
|
|
|
var messageReverse = bubble.message.split("").reverse().join("");
|
|
var mirrorBubble = new Bubble(bubble.pid, messageReverse, p.labelColor, bx, p.y, bubble.offY);
|
|
mirrorBubble.color = bubble.color;
|
|
pushBubbles(mirrorBubble);
|
|
bubbles.push(mirrorBubble);
|
|
|
|
//remove lines
|
|
bubble.px = -1;
|
|
bubble.py = -1;
|
|
|
|
}
|
|
|
|
function censorshipRoomEnter(playerId, roomId) {
|
|
if (playerId == me.id) {
|
|
longText = "In the Censorship Room each word can only be uttered once and never again.";
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
}
|
|
|
|
function darkRoomEnter(playerId, roomId) {
|
|
if (playerId == me.id) {
|
|
longText = "The Dark Room is only for cybersex. You must be 18 years or older to enter.";
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
}
|
|
|
|
|
|
function rhymeRoomEnter(playerId, roomId) {
|
|
if (playerId == me.id) {
|
|
longText = "In the Rhyme Room you can only rhyme with the sentences in the air.\nNo repeats, no made-up words. The best poet wins.";
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
bg.rewind();
|
|
bg.stop();
|
|
}
|
|
}
|
|
|
|
function VIPRoomEnter(playerId, roomId) {
|
|
if (playerId == me.id) {
|
|
longText = "Only 3 visitors are allowed in the VIP room. First in, first out.";
|
|
longTextLines = -1;
|
|
longTextAlign = "center";
|
|
}
|
|
}
|
|
|
|
function VIPRoomExit(playerId) {
|
|
//stop music before you leave, if any
|
|
//if (ROOMS.VIProom.musicLoop != null) {
|
|
ROOMS.VIProom.musicLoop.stop();
|
|
//}
|
|
}
|
|
|
|
|
|
|
|
//when ANYBODY Enters
|
|
function thirdFloorEnter(playerId, sprite, drawingFunction) {
|
|
//somebody else is entering - turn into sheep
|
|
if (playerId != me.id) {
|
|
turnToSheep(playerId);
|
|
}
|
|
}
|
|
|
|
|
|
//called when I receive data from a player already in the room
|
|
function thirdFloorIntro(playerId, roomId) {
|
|
turnToSheep(playerId);
|
|
}
|
|
|
|
function turnToSheep(playerId) {
|
|
var p = players[playerId];
|
|
|
|
//sheepIdle has been preloaded via DATA
|
|
p.sheepWalkAnimation = loadAnimation(loadSpriteSheet(IMAGES.sheepWalk, 11, 18, 3));
|
|
p.sheepIdleAnimation = loadAnimation(loadSpriteSheet(IMAGES.sheepIdle, 11, 18, 2));
|
|
removeSprite(p.sprite);
|
|
p.sprite = createSprite(10, 10);
|
|
p.sprite.scale = ASSET_SCALE;
|
|
p.sprite.depthOffset = 18 / 2;
|
|
p.sprite.addAnimation('walk', p.sheepWalkAnimation);
|
|
p.sprite.addAnimation('emote', p.sheepIdleAnimation);
|
|
}
|
|
|
|
//BAAA AAA AAAAA
|
|
function thirdFloorTalk(playerId, bubble) {
|
|
if (playerId != me.id) {
|
|
|
|
var l = bubble.message.length - 1;
|
|
var baa = "B";
|
|
for (var i = 0; i < l; i++) {
|
|
if (bubble.message[i] != " ")
|
|
baa += "A";
|
|
else
|
|
baa += " ";
|
|
}
|
|
|
|
bubble.message = baa;
|
|
bubble.tw = textWidth(bubble.message);
|
|
bubble.w = round(bubble.tw + TEXT_PADDING * 2);
|
|
|
|
bubble.x = round(bubble.px - bubble.w / 2);
|
|
if (bubble.x + bubble.w + BUBBLE_MARGIN > width) {
|
|
bubble.x = width - bubble.w - BUBBLE_MARGIN
|
|
}
|
|
if (bubble.x < BUBBLE_MARGIN) {
|
|
bubble.x = BUBBLE_MARGIN;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//called when I receive data from a player already in the room
|
|
//should arrive
|
|
function familyRoomIntro(playerId, roomId) {
|
|
var assigned = false;
|
|
//must override the normal intros
|
|
//check this person's role
|
|
for (var roleId in familyRoles) {
|
|
var rolePlayer = familyRoles[roleId];
|
|
|
|
//role assigned
|
|
if (rolePlayer == playerId) {
|
|
//print("Ah ha " + playerId + " is " + roleId);
|
|
changeCharacter(rolePlayer, roleId, roleId + "Walk", roleId + "Emote");
|
|
assigned = true;
|
|
}
|
|
|
|
}
|
|
|
|
if (!assigned)
|
|
changeCharacter(playerId, "fly", "flyWalk", "flyEmote");
|
|
}
|
|
|
|
|
|
//changes the appearance of the character, only for this room
|
|
function changeCharacter(playerId, roleId, walkSS, emoteSS) {
|
|
var p = players[playerId];
|
|
|
|
print(playerId + " changes appearance becoming " + roleId);
|
|
//spritesheet have been preloaded, standard size and animation avatar
|
|
p.altWalkAnimation = loadAnimation(loadSpriteSheet(IMAGES[walkSS], AVATAR_W, AVATAR_H, 4));
|
|
p.altEmoteAnimation = loadAnimation(loadSpriteSheet(IMAGES[emoteSS], AVATAR_W, AVATAR_H, 2));
|
|
|
|
removeSprite(p.sprite);
|
|
|
|
p.sprite = createSprite(10, 10, 10, 10);
|
|
p.sprite.scale = ASSET_SCALE;
|
|
p.sprite.addAnimation('walk', p.altWalkAnimation);
|
|
p.sprite.addAnimation('emote', p.altEmoteAnimation);
|
|
p.sprite.label = rolesInfo[roleId][0];
|
|
p.sprite.depthOffset = AVATAR_H / 2;
|
|
|
|
if (roleId != "fly") {
|
|
p.sprite.onMouseOver = function () {
|
|
rolledSprite = this;
|
|
};
|
|
|
|
p.sprite.onMouseOut = function () {
|
|
if (rolledSprite == this)
|
|
rolledSprite = null;
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
//the sculpture in my first floor is randomize between the 4 variations
|
|
//appears differently to different users but always the same in the same browser
|
|
function firstFloorEnter(playerId, roomId) {
|
|
if (playerId == me.id) {
|
|
|
|
var s = localStorage.getItem("sculpture");
|
|
|
|
if (s == null) {
|
|
s = floor(random(1, 5));
|
|
window.localStorage.setItem("sculpture", s);
|
|
}
|
|
|
|
//getSprites is a p5 play function
|
|
var roomSprites = getSprites();
|
|
|
|
for (var i = 0; i < roomSprites.length; i++) {
|
|
if (roomSprites[i].id != null)
|
|
if (roomSprites[i].id == "sculpture" + s) {
|
|
roomSprites[i].visible = true;
|
|
}
|
|
}
|
|
}
|
|
} |