Remove abrupt game over
[wgj58.git] / wgj58.js
index 2183a22bb06ca18cc155e25e6ecb4ad4d161494b..9405c5af7a3d14e3ed6860ebf91134ce03ba2aea 100644 (file)
--- a/wgj58.js
+++ b/wgj58.js
@@ -159,6 +159,8 @@ class Player extends Phaser.Sprite {
        takeMe(npc) {
                this.loadTexture(npc.key);
                npc.kill();
+               this.disguise = npc;
+               logic.gameinterface.dropNoticeTimeout(Phaser.Timer.SECOND * 5, "You are now identified as " + npc.fullname + "!");
        }
 }
 
@@ -171,11 +173,13 @@ class GameNPC extends Phaser.Sprite {
                this.interaction_distance = interaction_distance;
                this.interactable = false;
                this.talkcount = 0;
+               this.happy = false;
        }
 
        kill() {
                super.kill();
                this.exists = false;
+               this.happy = false;                     // Dead people are not happy.
        }
 
        update() {
@@ -190,6 +194,11 @@ class GameNPC extends Phaser.Sprite {
                        logic.player.offerInteraction(null);
                        this.interactable = false;
                }
+               if ((this.teleport_instructions) && (game.physics.arcade.distanceBetween(this, logic.player) > (game.width + 200))) {
+                       this.position = this.teleport_instructions.newPosition;
+                       this.teleport_instructions.callback(this.teleport_instructions.callbackValue);
+                       this.teleport_instructions = null;
+               }
        }
 
        actionTalk() {
@@ -208,6 +217,16 @@ class GameNPC extends Phaser.Sprite {
        endTalk() {
                return true;
        }
+
+       makeHappy() {
+               this.happy = true;
+               console.log(this.shortname, "is happy!");
+       }
+
+       offscreenTeleportation(newPosition, callback, callbackValue) {
+               this.teleport_instructions = { newPosition: newPosition, callback: callback, callbackValue: callbackValue };
+               console.log("Offscreen teleport request registered:", this.teleport_instructions);
+       }
 }
 
 class NPC_Clara extends GameNPC {
@@ -222,7 +241,8 @@ class NPC_Clara extends GameNPC {
                                        { actor: logic.player, text: "Well, maybe if we dare to joke about it, it won't happen to us..." },
                                        { actor: this, text: "Wish it worked like that... Is it some superstition like the belief that having an umbrella with you prevents rain?" },
                                        { actor: logic.player, text: "Nah, that actually works; it's not a superstition, but Murphy's Law!" },
-                                       { actor: this, text: "If you say so..." } ] ));
+                                       { actor: this, text: "If you say so..." },
+                                       { actor: this, text: "Anyway, I logged you in and opened the door for you." } ] ));
                                logic.openDoor("cutedoor");
                                break;
                        case 1:
@@ -261,6 +281,8 @@ class NPC_Clara extends GameNPC {
                                        { actor: logic.player, text: "Would you go out on a date with me?" },
                                        { actor: this, text: "..." },
                                        { actor: this, text: "No." } ] ));
+                               // FIXME: Clara should have another happy condition.
+                               this.makeHappy();
                                break;
                        default:
                                logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "..." } ] ));
@@ -311,7 +333,7 @@ class NPC_Carlos extends GameNPC {
                                        logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "You know, generally, I think it sucks being a child. One thing I miss though, if you're a child, you're allowed to be silly." },
                                                { actor: this, text: "..." },
                                                { actor: this, text: "For example, when my Dad told me that semen is the seed of animals, I theoretized, if I'd bury some pig semen in the garden, a pig would grow out of it..." },
-                                               { actor: this, text: "I was totally fascinated by the thought, because I really wanted to have a pet pig, but Dad wouldn't let me to have one." },
+                                               { actor: this, text: "I was totally fascinated by the thought, because I really wanted to have a pet pig, but Dad wouldn't let me have one." },
                                                { actor: this, text: "So I thought I could grow my own pig in the garden from pig seeds!" },
                                                { actor: logic.player, text: "Interesting. Where are you going with this?" },
                                                { actor: this, text: "I don't know... sometimes I feel like I'd rather sell pig semen to our clients, heh!" },
@@ -385,8 +407,122 @@ class NPC_Carlos extends GameNPC {
 
 class NPC_Saiki extends GameNPC {
        actionTalk() {
+               if (logic.carlos.alive) {
+                       switch (this.talkcount) {
+                               case 0:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "Hi Saiki!" },
+                                               { actor: this, text: "Hi John! Glad you arrived, here's some work for you!" },
+                                               { actor: logic.player, text: "Awesome! What is it?" },
+                                               { actor: this, text: "Haha, joking! Actually, our queue is suspiciously empty for today." },
+                                               { actor: logic.player, text: "Yeah... That's really suspicious!" },
+                                               { actor: logic.player, text: "Maybe I can get home today in time?" },
+                                               { actor: this, text: "You mean, you wouldn't spend the mandatory free extra working hours?" },
+                                               { actor: this, text: "You steal from the company! The company needs your unpaid hours of work! Otherwise, how would we finance the trash can I ordered for the department?" },
+                                               { actor: this, text: "*Whispers with wink.* I hope you get my sarcasm." },
+                                               { actor: logic.player, text: "Haha! I always get it, Saiki!" } ] ));
+                                       logic.closeDoor("carlosdoor");
+                                       logic.openDoor("saikidoor");
+                                       break;
+                               case 1:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "Now that I think about it, there's still one thing. You could look into why the access control system is acting so funny today." },
+                                               { actor: this, text: "Clara has to enter people manually." },
+                                               { actor: logic.player, text: "Yeah, I'll definitely check that." } ] ));
+                                       break;
+                               case 2:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "So... what's up with the trash can?" },
+                                               { actor: this, text: "I'm always up for such deep conversation" },
+                                               { actor: this, text: "about trash cans." },
+                                               { actor: this, text: "While we only have one trash can, other departments seem to be abundant of them. And ours is always filled. So I requested an additional trash can." },
+                                               { actor: this, text: "Now the ticket is in PENDING status. The latest work note is from two months ago, telling there is no budget at the moment." },
+                                               { actor: logic.player, text: "Hmm... Maybe it's too much to ask. Can we take one from another department?" },
+                                               { actor: this, text: "No, everyone holds on to their trash cans." },
+                                               { actor: logic.player, text: "You certainly did your research." },
+                                               { actor: this, text: "Of course. It's an important subject." } ] ));
+                                       break;
+                               case 3:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "My parents named me after a Japanese rock singer." },
+                                               { actor: logic.player, text: "Cool! Which band?" },
+                                               { actor: this, text: "I don't remember the band name. But the particular singer has a blue rose in her hair most of the time." } ] ));
+                                       break;
+                               default:
+                                       if ((logic.carlos.pigsemen) && (this.talkcount == 4)) {
+                                               logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "Did you know that Carlos thought he can grow a pig by burying pig semen in the ground? What do you think about this?" },
+                                                       { actor: this, text: "Hmm..." },
+                                                       { actor: this, text: "I guess it didn't work." },
+                                                       { actor: this, text: "So do you want to know what I think about this?" },
+                                                       { actor: this, text: "..." },
+                                                       { actor: this, text: "IT'S BRILLIANT!!!" },
+                                                       { actor: this, text: "You know, it really sparkled my artistic vision! Now I must draw a pig with its legs rooted into the ground!" },
+                                                       { actor: logic.player, text: "That's gross. Poor pig." },
+                                                       { actor: this, text: "Indeed. But this is the point. He's stuck in one place, cannot move. Like you in life. So you feel sympathy for him." },
+                                                       { actor: logic.player, text: "You have a point." },
+                                                       { actor: this, text: "I think I'll catch Carlos and talk to him. I always liked that guy but I didn't know he's such imaginative." } ] ));
+                                               this.offscreenTeleportation(new Phaser.Point(logic.carlos.x, logic.carlos.y + 64), this.tpDone, this);
+                                       }
+                                       else {
+                                               if (Phaser.Math.random() < 0.5) {
+                                                       logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "I've found an orchestrated rendition of „Potential for Anything”. You'll have to check it out, it's breathtaking!" } ] ));
+                                               }
+                                               else {
+                                                       logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "I don't like that our department is green. The blue one, where Carlos works, looks much better." } ] ));
+                                               }
+                                       }
+                       }
+               }
+               else {
+                       switch (this.talkcount) {
+                               case 0:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "I love you, Saiki!" },
+                                               { actor: this, text: "Hi Carlos..." },
+                                               { actor: logic.player, text: "I'm infatuated by the mere thought of you." },
+                                               { actor: this, text: "Well... it sounds pretty much creepy." },
+                                               { actor: logic.player, text: "Will you go out on a date with me?" },
+                                               { actor: this, text: "..." },
+                                               { actor: this, text: "Sorry to hurt your feelings, but... even though I like you... Your sudden, unprecedented confession makes me scared." },
+                                               { actor: this, text: "Especially with that facial expression." },
+                                               { actor: this, text: "I mean... you're not even joking." },
+                                               { actor: this, text: "So sorry... I won't date you." } ] ));
+                                       break;
+                               case 1:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "I thought I could impress you." },
+                                               { actor: this, text: "I'm sorry." } ] ));
+                                       break;
+                               case 2:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: logic.player, text: "You will give me your card." },
+                                               { actor: this, text: "Geez, what for? Go back to your department and work!" },
+                                               { actor: logic.player, text: "I need it." },
+                                               { actor: this, text: "..." } ] ));
+                                       break;
+                               default:
+                                       logic.gameinterface.talk(new Dialogue( [ { actor: this, text: "Don't you have anything better to do, Carlos?" } ] ));
+                       }
+               }
                super.actionTalk();
-               logic.endTalk();
+       }
+
+       actionLeave() {
+               if (logic.carlos.alive) {
+                       logic.gameinterface.dropNotice(this.shortname + ": It was nice talking to you!");
+               }
+       }
+
+       actionTake() {
+               logic.closeDoor("carlosdoor");
+               logic.openDoor("saikidoor");
+               logic.carlos.kill();
+               return super.actionTake();
+       }
+
+       endTalk() {
+               return (logic.carlos.alive);
+       }
+
+       tpDone(value) {
+               console.log("Woot-woot! Teleport complete:", value);
+               value.makeHappy();
+               logic.carlos.makeHappy();
+               // FIXME: Need to find a prettier way than this.
+               logic.carlos.update = function() { };           // Disable Carlos' interaction. (Saiki will talk for him.)
        }
 }
 
@@ -438,9 +574,14 @@ class GameInterface extends Phaser.Group {
                this.back_talk.lineTo(this.back_talk.width - 10, 35);
                this.add(this.back_talk);
                style = { align: 'left', fill: 'yellow', font: 'Ubuntu Mono', fontSize: 22, fontWeight: 'bold' };
-               this.text_talktitle = new Phaser.Text(game, this.back_talk.x, this.back_talk.y, null, style);
-               this.text_talktitle.anchor.setTo(-0.2, -0.2);
+               this.text_talktitle = new Phaser.Text(game, this.back_talk.x + 15, this.back_talk.y + 6, null, style);
+               //this.text_talktitle.anchor.setTo(-0.2, -0.2);
                this.add(this.text_talktitle);
+               this.strikethrough_talktitle = new Phaser.Graphics(game, this.back_talk.x, this.back_talk.y);
+               this.strikethrough_talktitle.lineStyle(3, Phaser.Color.RED, 1);
+               this.strikethrough_talktitle.moveTo(12, 20);
+               this.strikethrough_talktitle.lineTo(67, 20);
+               this.add(this.strikethrough_talktitle);
                style = { align: 'left', fill: 'white', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' };
                this.text_talk = new Phaser.Text(game, this.back_talk.x + 35, this.back_talk.y + 40, null, style);
                this.text_talk.wordWrap = true;
@@ -457,6 +598,11 @@ class GameInterface extends Phaser.Group {
                this.text_notice.visible = true;
        }
 
+       dropNoticeTimeout(timeout, text) {
+               this.dropNotice(text);
+               game.time.events.add(timeout, this.clearNotice, this);
+       }
+
        clearNotice() {
                this.back_notice.visible = false;
                this.text_notice.visible = false;
@@ -503,6 +649,7 @@ class GameInterface extends Phaser.Group {
                this.dialogue = null;
                this.back_talk.visible = false;
                this.text_talktitle.visible = false;
+               this.strikethrough_talktitle.visible = false;
                this.text_talk.visible = false;
        }
 
@@ -511,7 +658,14 @@ class GameInterface extends Phaser.Group {
                console.log(this.dialogue.actual());
                var actualdialogue = this.dialogue.actual();
                if (actualdialogue) {
-                       this.text_talktitle.text = actualdialogue.actor.shortname;
+                       if (actualdialogue.actor.disguise) {
+                               this.text_talktitle.text = actualdialogue.actor.shortname + " " + actualdialogue.actor.disguise.shortname;
+                               this.strikethrough_talktitle.visible = true;
+                       }
+                       else {
+                               this.text_talktitle.text = actualdialogue.actor.shortname;
+                               this.strikethrough_talktitle.visible = false;
+                       }
                        this.text_talk.text = actualdialogue.text;
                        this.dialogue.advance();
                }
@@ -587,7 +741,7 @@ class GameLogic {
                                this.carlos = newChar;
                                break;
                        case 'saiki':
-                               newChar = new NPC_Saiki(object.x, object.y, 'saiki', "Saiki", "Saiki Ytpme", 200);
+                               newChar = new NPC_Saiki(object.x, object.y, 'saiki', "Saiki", "Saiki Ytpme", 150);
                                this.saiki = newChar;
                                break;
                        default:
@@ -651,6 +805,10 @@ class GameLogic {
                this.doors.children.forEach(function(o) { if (o.name == doorname) o.close(); });
        }
 
+       checkAllHappy() {
+               return (this.clara.happy) && (this.carlos.happy) && (this.saiki.happy);
+       }
+
        update() {
                if ((game.input.keyboard.isDown(Phaser.Keyboard.ENTER)) && (hasTimePassed(this.last_menuselect, WAIT_MENUSTEP))) {
                        if ((this.player.interactablenpc) && (this.player.interactablenpc.interactable) && (!this.gameinterface.inMenu) && (!this.gameinterface.inTalk)) {
@@ -670,7 +828,7 @@ class GamePlay extends Phaser.State {
                super();
                logic = new GameLogic();
                game.world.updateOnlyExistingChildren = true;
-               //game.state.add('GameOver', GameOver, false);
+               game.state.add('GameOver', GameOver, false);
 
        }
 
@@ -723,3 +881,50 @@ class GamePlay extends Phaser.State {
 
        }
 }
+
+class GameOver extends Phaser.State {
+
+       create() {
+
+               console.log("Entered GameOver state.");
+               game.stage.removeChildren(1);
+               game.camera.follow(logic.player);
+               logic.player.freeze();
+
+               var g = game.add.group(game.stage, "GAMEOVER");
+               this.back_gameover = new Phaser.Graphics(game, 100, game.height / 2 - 200);
+               this.back_gameover.beginFill(0x000000);
+               this.back_gameover.drawRect(0, 0, game.width - 200, 400);
+               this.back_gameover.endFill();
+               this.back_gameover.lineStyle(3, Phaser.Color.YELLOW, 1);
+               this.back_gameover.moveTo(10, 35);
+               this.back_gameover.lineTo(this.back_gameover.width - 10, 35);
+               g.add(this.back_gameover);
+               var style = { align: 'left', fill: 'yellow', font: 'Ubuntu Mono', fontSize: 22, fontWeight: 'bold' };
+               this.text_title = new Phaser.Text(game, this.back_gameover.x + 15, this.back_gameover.y + 6, "ABRUPT GAME OVER", style);
+               g.add(this.text_title);
+               style = { align: 'left', fill: 'white', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' };
+               this.text_gameover = new Phaser.Text(game, this.back_gameover.x + 35, this.back_gameover.y + 60, null, style);
+               this.text_gameover.wordWrap = true;
+               this.text_gameover.wordWrapWidth = this.back_gameover.width - 70;
+               this.text_gameover.lineSpacing = -5;
+               g.add(this.text_gameover);
+
+               this.text_gameover.text = this.assess();
+
+       }
+
+       assess() {
+               if (logic.checkAllHappy()) {
+                       return "You listened to all of your colleagues' and affected them to make their day a little better. Next day, the company fired Clara, Carlos, Saiki, and you, to comply with its productivity requirements. The company's internal code demand unconditional and illimitable loyalty from employees to maximize productivity. This includes requisites for employees not to exercise human qualities or express personal needs within and outside the corporate environment. The company has determined that neither of the mentioned people complied to these guidelines, due to the amount of socialization they pursued during the work day.\n\nIronically, the layoffs turned everyone's life for the better.";
+               }
+               else if (logic.player.disguise) {
+                       this.text_gameover.style.fill = 'red';
+                       return "You went on your day to accomplish your tasks without caring about anyone. Where are your colleagues now? Clara, Carlos, Saiki? You don't know. But you don't even care. You have never seen them after they served your needs.\n\nNext day, the company promoted you for your effectiveness and loyalty.";
+               }
+               else {
+                       return "The company is concerned that you may develop other needs (like wanting to pursue hobbies, spend time with friends and family) those compete for the time you devote for your job. The company reminds you that they demand your entire being to exclusively serve the company's interests. Socializing with your colleagues outside the dedicated team building occasions may hurt your performance. To comply with the productivity requirements, the company has terminated your employment.\n\nClara, Carlos, Saiki are still loyal employees of the company. Probably you could have done something different to find a better outcome.";
+               }
+       }
+
+}