diff --git a/css/custom.css b/css/custom.css index 7e9203c..25a011b 100644 --- a/css/custom.css +++ b/css/custom.css @@ -8,3 +8,51 @@ input:invalid { border: 2px solid red; } + +/* Dropdown Content (Hidden by Default) */ +.damage-monitor { + display: none; + position: absolute; + z-index: 20; + + top: 40px; + right: -8px; + width: 60px; +} + +.damage-monitor th { + width: 30px; + height: 30px; + background-color: white; + border: solid darkgray 1px; + padding: 3px; +} + +.damage-monitor td { + width: 30px; + height: 24px; + border: solid darkgray 1px; + font-size: smaller; + user-select: none; + +} +.damage-monitor td::selection { background: none; } +.damage-monitor td::-moz-selection { background: none; } + +td.damage-stun { background-color: cornflowerblue; } +/*td.damage-stun:hover { background-color: steelblue; }*/ +td.damage-stun.selected { background-color: dodgerblue; } +td.damage-physical { background-color: indianred; } +/*td.damage-physical:hover { background-color: coral; }*/ +td.damage-physical.selected { background-color: tomato; } + +/* bgcolors: default, active, hover + phys: darkred, red, tomato, coral, lightcoral, indianred, orangered + stun: cornflowerblue, lightskyblue, mediumlateblue, steelblue, royalblue +*/ + +/* Change color of dropdown links on hover */ +.damage-monitor td:hover { + background-color: gray; +} + diff --git a/img/002-dead-body.png b/img/002-dead-body.png deleted file mode 100644 index 20b4a7b..0000000 Binary files a/img/002-dead-body.png and /dev/null differ diff --git a/img/003-shooting.png b/img/003-shooting.png deleted file mode 100644 index 4296651..0000000 Binary files a/img/003-shooting.png and /dev/null differ diff --git a/img/005-add.png b/img/add.png similarity index 100% rename from img/005-add.png rename to img/add.png diff --git a/img/check.png b/img/check.png new file mode 100644 index 0000000..3ed7a18 Binary files /dev/null and b/img/check.png differ diff --git a/img/006-dice.png b/img/dice.png similarity index 100% rename from img/006-dice.png rename to img/dice.png diff --git a/img/004-edit-button.png b/img/edit.png similarity index 100% rename from img/004-edit-button.png rename to img/edit.png diff --git a/img/explosion.png b/img/explosion.png new file mode 100644 index 0000000..ad6862a Binary files /dev/null and b/img/explosion.png differ diff --git a/img/001-refresh.png b/img/refresh.png similarity index 100% rename from img/001-refresh.png rename to img/refresh.png diff --git a/img/skull.png b/img/skull.png new file mode 100644 index 0000000..86d3c84 Binary files /dev/null and b/img/skull.png differ diff --git a/img/zzz.png b/img/zzz.png new file mode 100644 index 0000000..da68fa8 Binary files /dev/null and b/img/zzz.png differ diff --git a/index.html b/index.html index 19a2199..afee95f 100644 --- a/index.html +++ b/index.html @@ -27,18 +27,18 @@
-
+
- + @@ -81,12 +81,11 @@
-
-
- - D+ - -
+
+ + D+ + +
diff --git a/js/sr2ini.js b/js/sr2ini.js index d0e33e9..84baf6e 100644 --- a/js/sr2ini.js +++ b/js/sr2ini.js @@ -2,6 +2,28 @@ * helper functions */ +const penalty = [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4]; + +const damageMonitorHTML = ['
Name Ini+R+R Actions
\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', + '\n', +'
00
LL
MM
SS
DD
'].join(""); + + // roll for initiative with the given reaction and number of ini dice function rollForInitiative(dice, rea) { let ini = 0; @@ -62,6 +84,28 @@ function sortTable() { } +// returns a combatant's effective ini value (modified by wound penalties) +function getEffectiveIni(value, dmgLvl1, dmgLvl2) { + let effectiveIni; + + // was function called with 1 argument (tr jQuery object)? + if ( arguments.length == 1 && $(value).is("tr.combatantRow") ) { + let trueIni = parseInt($(value).attr("data-true-ini")); + let dmgStun = parseInt($(value).attr("data-damage-stun")) || 0; + let dmgPhysical = parseInt($(value).attr("data-damage-physical")) || 0; + effectiveIni = trueIni - penalty[dmgStun] - penalty[dmgPhysical]; + } + // or with 3 arguments (ini and dmg levels)? + else if ( arguments.length == 3 ) { + effectiveIni = parseInt(value) - penalty[parseInt(dmgLvl1)] - penalty[parseInt(dmgLvl2)]; + } + // + else { return NaN; } +console.log("effectiveIni is ", effectiveIni); + return effectiveIni < 0 ? 0 : effectiveIni; +} + + /* * Event handler functions */ @@ -70,13 +114,14 @@ function sortTable() { function handleActButtonClick (e) { // find current table row let $tr = $(e.target).parents(".combatantRow"); - let ini = $tr.find(".combatantIni").text(); + let ini = $tr.attr("data-true-ini"); // reduce ini by 10 but not lower than 0 ini = Math.max(parseInt(ini) - 10, 0); // set new ini value - $tr.find(".combatantIni").text(ini); + $tr.attr("data-true-ini", ini); + $tr.find(".combatantIni").text(getEffectiveIni($tr)); // resort table sortTable(); @@ -103,12 +148,49 @@ function handleAddButtonClick (e) { $("#combatantModal").modal("show"); } - -function handleDamageButtonHover (e) { - +// click handler for damage buttons +function handleDamageButtonClick (e) { + let display = $(e.target).parents(".damage-dropdown").find(".damage-monitor").css("display"); + $(e.target).parents(".damage-dropdown").find(".damage-monitor").css("display", display == "block" ? "none" : "block"); + return false; } +// click handler for damage monitor fields +function handleDamageMonitorClick (e) { + let $td = $(e.target); + let $tr = $td.parents("tr.combatantRow"); + let damageType; + let otherDamageLevel + + // calculate new damage level and type + let damageLevel = $td.parent().index(); + if ( $td.hasClass("damage-stun") ) { + damageType = "stun"; + otherDamageLevel = $tr.attr("data-damage-physical") ? parseInt($tr.attr("data-damage-physical")) : 0; + } else if ( $td.hasClass("damage-physical") ) { + damageType = "physical"; + otherDamageLevel = $tr.attr("data-damage-stun") ? parseInt($tr.attr("data-damage-stun")) : 0; + } else { + return false; + } + + // add damage level to table row as as data attribute + $tr.attr("data-damage-" + damageType, damageLevel); + + // select/unselect damage boxes + $td.addClass("selected"); + $td.parent().nextAll().children("td.damage-" + damageType).removeClass("selected"); + $td.parent().prevAll().children("td.damage-" + damageType).addClass("selected"); + + // recalculate effective ini and resort + $tr.find(".combatantIni").text(getEffectiveIni($tr)); + sortTable(); + + + return false; +} + // click handler for edit buttons function handleEditButtonClick (e) { // find current table row @@ -123,7 +205,8 @@ function handleEditButtonClick (e) { $("#combatantModalName").val($tr.find(".combatantName").text()); $("#combatantModalDice").val($tr.find(".combatantDice").text()); $("#combatantModalRea").val($tr.find(".combatantRea").text()); - $("#combatantModalIni").val($tr.find(".combatantIni").text()); + $("#combatantModalIni").val($tr.attr("data-true-ini")); + //TODO: show effective ini in modal // mark which row is being edited $("#combatantModal").attr("data-row", $(".combatantRow").index($tr)); @@ -223,34 +306,48 @@ function addCombatant (e) { let ini = $("#combatantModalIni").val().trim(); let dice = $("#combatantModalDice").val().trim(); let rea = $("#combatantModalRea").val().trim(); + //TODO: retrieve initial damage levels - // roll for initiative if ini is empty + // roll for initiative if necessary ini = (ini != "") ? ini : rollForInitiative(dice, rea); + // TODO: actually calculate effective ini + let effectiveIni = getEffectiveIni(ini, 0, 0); +console.log("effective ini = ", effectiveIni); + // construct jQuery object for table row let $tr = $($.parseHTML( [ - '\n', - '', name, '\n', - '', ini, '\n', - '', dice, 'D+', rea, '\n', - '\n', - '
\n', - '\n', - '\n', - '\n', - '
\n', - '\n', - ''].join("") +'\n', //TODO: add data-damage-* attributes with initial damage levels + '', name, '\n', + '', effectiveIni, '\n', + '', dice, 'D+', rea, '\n', + '\n', + '
\n', + '\n', + '\n', + '
\n', + '\n', + damageMonitorHTML + "\n", + '
\n', + '
\n', + '\n', +''].join("") )); +//TODO: mark initial damage levels with .selected class + // add handlers to table row buttons $tr.find("button.edit-button").on("click", handleEditButtonClick); $tr.find("button.act-button").on("click", handleActButtonClick); $tr.find("button.remove-button").on("click", handleRemoveButtonClick); + $tr.find("button.damage-button").on("click", handleDamageButtonClick); - // add handlers to table cells (click to edit) + // add handler to table cells (click to edit) $tr.find(".combatantName, .combatantIni, .combatantDiceAndRea").on("click", handleEditButtonClick); + // add handler to damage monitor + $tr.find(".damage-stun, .damage-physical").on("click", handleDamageMonitorClick); + // add row to table and sort $("#combatantsTable").append($tr); sortTable(); @@ -286,7 +383,8 @@ function editCombatant (e) { $tr.find(".combatantName").text(name); $tr.find(".combatantDice").text(dice); $tr.find(".combatantRea").text(rea); - $tr.find(".combatantIni").text(ini); + $tr.attr("data-true-ini", ini); + $tr.find(".combatantIni").text(getEffectiveIni($tr)); // sort table sortTable(); @@ -305,13 +403,14 @@ function newRound() { // reset ini values $(".combatantRow").each( function() { - let $ini = $(this).find(".combatantIni"); - let $dice = $(this).find(".combatantDice"); - if ( $dice.text() == "" ) { - $ini.text(1); + let effectiveIni = $(this).find(".combatantIni").text(); + let dice = $(this).find(".combatantDice").text(); + if ( dice == "" ) { + $(this).attr("data-true-ini", "1"); } else { - $ini.text(rollForInitiative($dice.text(), $(this).find(".combatantRea").text())); + $(this).attr("data-true-ini", rollForInitiative(dice, $(this).find(".combatantRea").text())); } + $(this).find(".combatantIni").text(getEffectiveIni($(this))); }); // resort table @@ -348,12 +447,16 @@ $(document).ready(function(){ // always focus name input field when combatant modal appears $('#combatantModal').on('shown.bs.modal', function() { $('#combatantModalName').focus(); - }) - + }); // always empty input fields when combatant modal disappears $("#combatantModal").on('hidden.bs.modal', function (e) { $("#combatantModal input[id*='combatantModal']").val(""); - }) + }); + + // Hide damage monitors if mouse is clicked outside + $("html").on("click", function(e) { + $(".damage-monitor:visible").css("display", "none"); + }); addTestCombatant();