Newer
Older
$groupButton.attr('disabled', false);
}
/************************************************************
* This is the callback for the random buttons.
************************************************************/

ReformCopyright
committed
function updateRandomSelection (playerObject, slot) {
players[slot] = playerObject;
updateBehaviour(slot, SELECTED);
updateSelectionVisuals();
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
}
/************************************************************
* Hides the table on the single selection screen.
************************************************************/
function hideSelectionTable() {
mainSelectHidden = !mainSelectHidden;
if (mainSelectHidden) {
$selectTable.hide();
}
else {
$selectTable.show();
}
}
/************************************************************
* Hides the table on the single selection screen.
************************************************************/
function hideSingleSelectionTable() {
singleSelectHidden = !singleSelectHidden;
if (singleSelectHidden) {
$individualSelectTable.hide();
}
else {
$individualSelectTable.show();
}
}
/************************************************************
* Hides the table on the single group screen.
************************************************************/
function hideGroupSelectionTable() {
groupSelectHidden = !groupSelectHidden;
if (groupSelectHidden) {
$groupSelectTable.hide();
}
else {
$groupSelectTable.show();
}
}
function openSearchModal() {
$searchModal.modal('show');
}
function closeSearchModal() {
Chase Southwood
committed
// perform the search and sort logic
updateSelectableOpponents();
// update
updateIndividualSelectScreen();
updateIndividualCountStats();
function clearSearch() {
$searchName.val(null);
$searchTag.val(null);
$searchSource.val(null);
closeSearchModal();
}
function changeSearchGender(gender) {
chosenGender = gender;
setActiveOption($searchGenderOptions, gender);
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
function openGroupSearchModal() {
$groupSearchModal.modal('show');
}
function closeGroupSearchModal() {
// perform the search and sort logic
updateSelectableGroups(groupSelectScreen);
// update
updateGroupSelectScreen();
updateGroupCountStats();
}
function clearGroupSearch() {
$groupSearchName.val(null);
$groupSearchGroupName.val(null);
$groupSearchTag.val(null);
$groupSearchSource.val(null);
closeGroupSearchModal();
}
function changeGroupSearchGender(gender) {
chosenGroupGender = gender;
setActiveOption($groupSearchGenderOptions, gender);
}
/************************************************************
* Sorting Functions
************************************************************/
* Callback for Arrays.sort to sort an array of objects by the given field.
* Prefixing "-" to a field will cause the sort to be done in reverse.
* Examples:
* // sorts myArr by each element's first name (A-Z)
* myArr.sort(sortOpponentsByField("first"));
* // sorts myArr by each element's last name (Z-A)
* myArr.sort(sortOpponentsByField("-last"));
*/
function sortOpponentsByField(field) {
// check for prefix
var order = 1; // 1 = forward, -1 = reversed
order = -1;
field = field.substr(1);
}
return function(opp1, opp2) {
var compare = 0;
if (opp1[field] < opp2[field]) {
compare = -1;
}
else if (opp1[field] > opp2[field]) {
compare = 1;
}
return order * compare;
}
}
/**
* Callback for Arrays.sort to sort an array of objects over multiple given fields.
* Prefixing "-" to a field will cause the sort to be done in reverse.
* This should allow more flexibility in the sorting order.
* Example:
* // sorts myArr by each element's number of layers (low to high),
* // and for elements whose layers are equivalent, sort them by first name (Z-A)
* myArr.sort(sortOpponentsByMultipleFields("layers", "-first"));
*/
function sortOpponentsByMultipleFields() {
var fields = arguments; // retrieve the args passed in
return function(opp1, opp2) {
var i = 0;
var compare = 0;
// if both elements have the same field, check the next ones
while (compare === 0 && i < fields.length) {
compare = sortOpponentsByField(fields[i])(opp1, opp2);
i++;
}
return compare;
}
}
ReformCopyright
committed
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
/**
* Special Callback for Arrays.sort to sort an array of opponents on
* the total number of lines targeting them the currently selected
* opponents have.
*/
function sortOpponentsByMostTargeted() {
return function(opp1, opp2) {
counts = [opp1, opp2].map(function(opp) {
return players.reduce(function(sum, p) {
if (p.targetedLines && opp.id in p.targetedLines) {
sum += p.targetedLines[opp.id].count;
}
return sum;
}, 0);
});
if (counts[0] > counts[1]) return -1;
if (counts[0] < counts[1]) return 1;
return 0;
}
}
/** Event handler for the sort dropdown options. Fires when user clicks on a dropdown item. */
$sortingOptionsItems.on("click", function(e) {
sortingMode = $(this).find('a').html();
$("#sort-dropdown-selection").html(sortingMode); // change the dropdown text to the selected option
});
/************************************************************
* Word wrapping Functions
************************************************************/
/**
* Inserts a fixed-size HTML element with the specified text to allow the content
* to be either word-wrapped (if the text is long and spaces are present)
* or word-broken (if text is long and no spaces are present).
*/
function wordWrapHtml(text) {
return "<table class=\"wrap-text\"><tr><td>" + text + "</td></tr></table>";
/************************************************************
* Dynamic dialogue and image counting functions
************************************************************/
/** Event handler for the individual selection screen credits button. */
$individualCreditsButton.on('click', function(e) {
updateIndividualCountStats()
/** Event handler for the group selection screen credits button. */
$groupCreditsButton.on('click', function(e) {
updateGroupCountStats();
* Loads and displays the number of unique dialogue lines and the number of pose images
* into the character's player object for those currently on the selection screen.
* Only loads if the unique line count or image count is not known.
*/
function updateOpponentCountStats(opponentArr, uiElements) {
opponentArr.forEach(function(opp, idx) {
// load behaviour file if line/image count is not known
if (opp && (opp.uniqueLineCount === undefined || opp.posesImageCount === undefined)) {
uiElements.countBoxes[idx].css("visibility", "visible");
// retrieve line and image counts
if (DEBUG) {
console.log("[LineImageCount] Fetching counts for " + opp.label + " in slot " + idx);
var countsPromise = Promise.resolve(fetchBehaviour(opp.folder));
countsPromise.then(countLinesImages).then(function(response) {
opp.uniqueLineCount = response.numUniqueLines;
opp.posesImageCount = response.numPoses;
// show line and image counts
if (DEBUG) {
console.log("[LineImageCount] Loaded " + opp.label + " from behaviour: " +
opp.uniqueLineCount + " lines, " + opp.posesImageCount + " images");
uiElements.lineLabels[idx].html(opp.uniqueLineCount);
uiElements.poseLabels[idx].html(opp.posesImageCount);
// this character's counts were previously loaded
if (DEBUG) {
console.log("[LineImageCount] Loaded previous count for " + opp.label + ": " +
opp.uniqueLineCount + " lines, " + opp.posesImageCount + " images)");
uiElements.countBoxes[idx].css("visibility", "visible");
uiElements.lineLabels[idx].html(opp.uniqueLineCount);
uiElements.poseLabels[idx].html(opp.posesImageCount);
// there is no character in the slot
uiElements.countBoxes[idx].css("visibility", "hidden");
uiElements.lineLabels[idx].html("");
uiElements.poseLabels[idx].html("");
/** Dialogue/image count update function for the individual selection screen. */
function updateIndividualCountStats() {
if (individualCreditsShown) {
var individualUIElements = {
countBoxes : $individualCountBoxes,
lineLabels : $individualLineCountLabels,
poseLabels : $individualPoseCountLabels
};
updateOpponentCountStats(shownIndividuals, individualUIElements);
}
}
/** Dialogue/image count update function for the group selection screen. */
function updateGroupCountStats() {
if (groupCreditsShown) {
var groupUIElements = {
countBoxes : $groupCountBoxes,
lineLabels : $groupLineCountLabels,
poseLabels : $groupPoseCountLabels
};
updateOpponentCountStats(shownGroup, groupUIElements);
/**
* Fetches the behaviour.xml file of the specified opponent directory.
*/
function fetchBehaviour(path) {
return $.ajax({
type: "GET",
url: path + "behaviour.xml",
dataType: "text"
});
}
/**
* Callback to parse the number of lines of dialogue and number of images
* given a character's behaviour XML. Returns the counts as an object with
* properties numTotalLines, numUniqueLines, and numPoses.
*/
function countLinesImages(xml) {
// parse all lines of dialogue and all images

ReformCopyright
committed
var numTotalLines = 0;
var numUniqueDialogueLines = 0;
var numUniqueUsedPoses = 0;
var lines = {};
var poses = {};
$(xml).find('state').each(function(idx, data) {

ReformCopyright
committed
numTotalLines++;
// count only unique lines of dialogue
if (lines[data.textContent.trim()] === undefined) numUniqueDialogueLines++;
lines[data.textContent.trim()] = 1;
// count unique number of poses used in dialogue
// note that this number may differ from actual image count if some images
// are never used, or if images that don't exist are used in the dialogue
if (poses[data.getAttribute("img")] === undefined) numUniqueUsedPoses++;
poses[data.getAttribute("img")] = 1;

ReformCopyright
committed
numTotalLines : numTotalLines,
numUniqueLines : numUniqueDialogueLines,
numPoses : numUniqueUsedPoses