From 4b9c83715f6a32865c68d27d7502e67d66a72c32 Mon Sep 17 00:00:00 2001 From: ReformCopyright <magnus@kibibyte.se> Date: Tue, 24 Jul 2018 00:26:41 +0200 Subject: [PATCH] Clean up and simplify epilogue code * Make loadEpilogueData() take, and the player attribute of created epilogue objects be, a player object reference instead of an index. * Use .forEach(), .some(), and .every() to shorten code and avoid dereferencing undefined. * Implement alsoPlaying and playerStartingLayers condition attributes. * No need to figure out who won, only whether HUMAN_PLAYER won or not. * Whitespace fixes. --- js/spniEpilogue.js | 199 ++++++++++++++++----------------------------- js/spniTitle.js | 1 + 2 files changed, 70 insertions(+), 130 deletions(-) diff --git a/js/spniEpilogue.js b/js/spniEpilogue.js index 3fa3bc44be8..b136286dcb2 100644 --- a/js/spniEpilogue.js +++ b/js/spniEpilogue.js @@ -28,7 +28,7 @@ var winEpiloguesDisabledStr = "You won... but epilogues have been disabled."; var lossEpiloguesDisabledStr = "You lost... but epilogues have been disabled."; /* NPC chosen for epilogue */ -var epilogueCharacter = -1; //the character whose epilogue is playing +var epilogueCharacter; //the character whose epilogue is playing var epilogueScreen = 0; //screen in the epilogue var epilogueTextCount = 0; //current latest text box in the current screen of the epilogue @@ -58,14 +58,11 @@ function getCenteredPosition(width){ /************************************************************ * Load the Epilogue data for a character ************************************************************/ -function loadEpilogueData(player){ - if (!players[player]) { +function loadEpilogueData(player) { + if (!player || !player.xml) { //return an empty list if a character doesn't have an XML variable. (Most likely because they're the player.) return []; } - var xml = players[player].xml; - if (!xml) {return [];} //return an empty list if a character doesn't have an XML variable. (Most likely because they're the player.) - var playerGender = players[HUMAN_PLAYER].gender; //get the XML tree that relates to the epilogue, for the specific player gender @@ -73,138 +70,92 @@ function loadEpilogueData(player){ var epilogues = []; - var all_epilogues = xml.find('epilogue').filter(function (index) { + var all_epilogues = player.xml.find('epilogue').filter(function (index) { /* Returning true from this function adds the current epilogue to the list of selectable epilogues. * Conversely, returning false from this function will make the current epilogue not selectable. */ /* 'gender' attribute: the epilogue will only be selectable if the player character has the given gender, or if the epilogue is marked for 'any' gender. */ var epilogue_gender = $(this).attr('gender'); - if(epilogue_gender) { - if(epilogue_gender !== playerGender && epilogue_gender !== 'any') { - // if the gender doesn't match, don't make this epilogue selectable - return false; - } + if (epilogue_gender && epilogue_gender !== playerGender && epilogue_gender !== 'any') { + // if the gender doesn't match, don't make this epilogue selectable + return false; + } + + var alsoPlaying = $(this).attr('alsoPlaying'); + if (alsoPlaying !== undefined && !(players.some(function(p) { return p.id == alsoPlaying; }))) { + return false; + } + + var playerStartingLayers = parseInterval($(this).attr('playerStartingLayers')); + if (playerStartingLayers !== undefined && !inInterval(players[HUMAN_PLAYER].startingLayers, playerStartingLayers)) { + return false; } /* 'markers' attribute: the epilogue will only be selectable if the character has ALL markers listed within the attribute set. */ var all_marker_attr = $(this).attr('markers'); - if(all_marker_attr) { - var must_match_markers = all_marker_attr.split(' '); - for(var i=0;i<must_match_markers.length;i++) { - if(!(must_match_markers[i] in players[player].markers)) { - // if the given marker is not present, don't make this epilogue selectable - return false; - } - } + if (all_marker_attr !== undefined + && !all_marker_attr.trim().split(/\s+/).every(function(marker) { + return marker in player.markers; + })) { + // not every marker set + return false; } /* 'not-markers' attribute: the epilogue will only be selectable if the character has NO markers listed within the attribute set. */ var no_marker_attr = $(this).attr('not-markers'); - if(no_marker_attr) { - var must_not_match_markers = no_marker_attr.split(' '); - for(var i=0;i<must_not_match_markers.length;i++) { - if(must_not_match_markers[i] in players[player].markers) { - // if the given marker is present, don't make this epilogue selectable - return false; - } - } + if (no_marker_attr !== undefined + && no_marker_attr.trim().split(/\s+/).some(function(marker) { + return marker in player.markers; + })) { + // some disallowed marker set + return false; } /* 'any-markers' attribute: the epilogue will only be selectable if the character has at least ONE of the markers listed within the attribute set. */ var any_marker_attr = $(this).attr('any-markers'); - if(any_marker_attr) { - var one_must_match_markers = any_marker_attr.split(' '); - var match_found = false; - for(var i=0;i<one_must_match_markers.length;i++) { - if(one_must_match_markers[i] in players[player].markers) { - match_found = true; - break; - } - } - - if(!match_found) { - /* if no markers in the list matched, don't make this epilogue selectable. */ - return false; - } - - /* if any marker within the attribute is set, then this condition passes-- fall through and check the other conditions though */ + if (any_marker_attr !== undefined + && !any_marker_attr.trim().split(/\s+/).some(function(marker) { + return marker in player.markers; + })) { + // none of the markers set + return false; } /* 'alsoplaying-markers' attribute: this epilogue will only be selectable if ALL markers within the attribute are set for any OTHER characters in the game. */ var alsoplaying_marker_attr = $(this).attr('alsoplaying-markers'); - if(alsoplaying_marker_attr) { - var markers = alsoplaying_marker_attr.split(' '); - for(var i=0;i<markers.length;i++) { - var marker_set = false; - - for(var pl_idx=0;pl_idx<players.length;pl_idx++) { - if(pl_idx !== player) { - if(markers[i] in players[pl_idx].markers) { - marker_set = true; - break; - } - } - } - - /* if any marker within the attribute is not set, don't make this epilogue selectable */ - if(!marker_set) { - return false; - } - } + if (alsoplaying_marker_attr !== undefined + && !alsoplaying_marker_attr.trim().split(/\s+/).every(function(marker) { + return players.some(function(p) { + return p !== player && marker in p.markers; + }); + })) { + // not every marker set by some other character + return false; } /* 'alsoplaying-not-markers' attribute: this epilogue will only be selectable if NO markers within the attribute are set for other characters in the game. */ var alsoplaying_not_marker_attr = $(this).attr('alsoplaying-not-markers'); - if(alsoplaying_not_marker_attr) { - var markers = alsoplaying_not_marker_attr.split(' '); - for(var i=0;i<markers.length;i++) { - var marker_set = false; - - for(var pl_idx=0;pl_idx<players.length;pl_idx++) { - if(pl_idx !== player) { - if(markers[i] in players[pl_idx].markers) { - marker_set = true; - break; - } - } - } - - /* If any marker within the attribute is set, then don't make the epilogue selectable */ - if(marker_set) { - return false; - } - } + if (alsoplaying_not_marker_attr !== undefined + && alsoplaying_not_marker_attr.trim().split(/\s+/).some(function(marker) { + return players.some(function(p) { + return p !== player && marker in p.markers; + }); + })) { + // some disallowed marker set by some other character + return false; } /* 'alsoplaying-any-markers' attribute: this epilogue will only be selectable if at least one marker within the attribute are set for any OTHER character in the game. */ var alsoplaying_any_marker_attr = $(this).attr('alsoplaying-any-markers'); - if(alsoplaying_any_marker_attr) { - var markers = alsoplaying_any_marker_attr.split(' '); - var match_found = false; - - for(var i=0;i<markers.length;i++) { - for(var pl_idx=0;pl_idx<players.length;pl_idx++) { - if(pl_idx !== player) { - if(markers[i] in players[pl_idx].markers) { - match_found = true; - break; - } - } - } - - if(match_found) { - /* break out of all loops */ - break; - } - } - - /* if any marker within the attribute is set, then this condition passes-- fall through and check other conditions (if there are any). - * Otherwise, don't make this epilogue selectable. - */ - if(!match_found) { - return false; - } + if (alsoplaying_any_marker_attr !== undefined + && !alsoplaying_any_marker_attr.trim().split(/\s+/).some(function(marker) { + return players.some(function(p) { + return p !== player && marker in p.markers; + }); + })) { + // none of the markers set by any other player + return false; } // if we made it this far the epilogue must be selectable @@ -218,7 +169,7 @@ function loadEpilogueData(player){ var screens = []; //the list of screens for the epilogue $(this).find("screen").each(function() { - var image = players[player].folder + $(this).attr("img").trim(); //get the full path for the screen's image + var image = player.folder + $(this).attr("img").trim(); //get the full path for the screen's image //use an attribute rather than a tag because IE doesn't like parsing XML //get the information for all the text boxes @@ -346,7 +297,8 @@ function clearEpilogueBoxes(){ function addEpilogueEntry(epilogue){ var num = epilogues.length; //index number of the new epilogue - var player = players[epilogue.player] + epilogues.push(epilogue); + var player = epilogue.player var nameStr = player.first+" "+player.last; if (player.first.length <= 0 || player.last.length <= 0){ @@ -399,34 +351,21 @@ function doEpilogueModal(){ chosenEpilogue = null; //reset any currently-chosen epilogue $epilogueAcceptButton.prop("disabled", true); //don't let the player accept an epilogue until they've chosen one - //identify the winning player - var winner = -1; - for (var i = 0; i < players.length; i++){ - if (players[i] && !players[i].out){ - winner = i; - break; - } - } - //whether or not the human player won - var playerWon = (winner == HUMAN_PLAYER); + var playerWon = !players[HUMAN_PLAYER].out; if (EPILOGUES_ENABLED && playerWon) { //all the epilogues are for when the player wins, so don't allow them to choose one if they lost //load the epilogue data for each player - for (var i = 0; i < players.length; i++){ - var playerIEpilogues = loadEpilogueData(i); - for (var j = 0; j < playerIEpilogues.length; j++){ - addEpilogueEntry(playerIEpilogues[j]); - epilogues.push(playerIEpilogues[j]); - } - } + players.forEach(function(p) { + loadEpilogueData(p).forEach(addEpilogueEntry); + }); } //are there any epilogues available for the player to see? var haveEpilogues = (epilogues.length >= 1); //whether or not there are any epilogues available $epilogueAcceptButton.css("visibility", haveEpilogues ? "visible" : "hidden"); - if(EPILOGUES_ENABLED) { + if (EPILOGUES_ENABLED) { //decide which header string to show the player. This describes the situation. var headerStr = ''; if (playerWon){ @@ -438,7 +377,7 @@ function doEpilogueModal(){ headerStr = lossStr; //player lost } } else { - if(playerWon) { + if (playerWon) { headerStr = winEpiloguesDisabledStr; } else { headerStr = lossEpiloguesDisabledStr; @@ -453,7 +392,7 @@ function doEpilogueModal(){ * Start the Epilogue ************************************************************/ function doEpilogue(){ - save.addEnding(players[chosenEpilogue.player].id, chosenEpilogue.title); + save.addEnding(chosenEpilogue.player.id, chosenEpilogue.title); //just in case, clear any open text boxes clearEpilogueBoxes(); diff --git a/js/spniTitle.js b/js/spniTitle.js index 8ef86996f4a..e39e0b93725 100644 --- a/js/spniTitle.js +++ b/js/spniTitle.js @@ -295,6 +295,7 @@ function wearClothing () { for (var i = 0; i < position[2].length; i++) { players[HUMAN_PLAYER].clothing.push(position[2][i]); } + players[HUMAN_PLAYER].startingLayers = players[HUMAN_PLAYER].clothing.length; /* update the visuals */ displayHumanPlayerClothing(); -- GitLab