Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Weird Red Box

1539468721
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
I am getting this weird red box around one of my repeating rows on just one of my sections. I can't figure out whats happening to cause this. Can anyone shed light on this? /* =========================== Rituals =================================*/ .sheet-rituals { width: calc(100% - 0.4em); height: auto !important;} .sheet-ritualheader .sheet-col0 { width: calc( 100% - 220px) ; } .sheet-ritualheader .sheet-col1 { width: 60px; } .sheet-ritualheader .sheet-col2 { width: 60px; } .sheet-ritualheader .sheet-col3 { width: 60px; } .sheet-ritualheader .sheet-col4 { width: 40px; } .sheet-ritualtable .sheet-row-rituals .sheet-col0 { width: 22px; margin-left: 28px; } /*Button*/ .sheet-ritualtable .sheet-row-rituals .sheet-col1 { width: calc(100% - 270px); } /*Name*/ .sheet-ritualtable .sheet-row-rituals .sheet-col1 input { text-align:left; } .sheet-ritualtable .sheet-row-rituals .sheet-col2 { width: 58px; margin-left: 2px; } .sheet-ritualtable .sheet-row-rituals .sheet-col3 { width: 58px; margin-left: 2px; } .sheet-ritualtable .sheet-row-rituals .sheet-col4 { width: 58px; margin-left: 2px; } .sheet-ritualtable .sheet-row-rituals .sheet-col5 { width: 38px; margin-left: 2px; } .sheet-rituals .sheet-ritualtable .sheet-row-ritualdetails{ overflow: auto; overflow-x: auto; overflow-y: auto; height: inherit; } .sheet-rituals .sheet-ritualtable .sheet-row-ritualdetails .sheet-col0 { width: 400px; margin-left: 20px; } .sheet-rituals .sheet-ritualtable .sheet-row-ritualdetails .sheet-col1 { width: 400px; margin-left: 8px; } .sheet-rituals .sheet-ritualtable .sheet-row-ritualdetails .sheet-col0 textarea.sheet-ritualdesc { width: 390px; height: 60px; min-height: 60px; resize: vertical; } .sheet-rituals .sheet-ritualtable .sheet-row-ritualdetails .sheet-col1 textarea.sheet-ritualcast { width: 390px; height: 60px; min-height: 60px; resize: vertical; }
1539469561
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
This is styling that gets applied by roll20 when an erroneous repeating row is generated. There are many possible reasons why the row might be broken. This doesn't have anything to do with your css though. There may be an error in your html, but it could also just be that a bad row was created at some point.
1539470234
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
What is the best solution to fix this?
1539470684
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
It depends on the cause, if it's a random bad row, just delete it and make a new one. If it's an html error then you'd need to share your code.
1539471710
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
I've deleted bad rows only to have the red box reappear. So I guess it is an html error. Right? <div class='sheet-box sheet-rituals'> <!-- ===== BEGIN SHEET-BOX SHEET-RITUALS ===== --> <div class="sheet-table sheet-ritualtable"> <div class="sheet-header sheet-ritualheader"> <div class="sheet-cell sheet-col0">Ritual Name</div> <div class="sheet-cell sheet-col1">Energy</div> <div class="sheet-cell sheet-col2">Damage</div> <div class="sheet-cell sheet-col3"><div class="sheet-popup">Type</div><span class="sheet-tooltip"> <table> <thead> <tr> <th>Abbr</th> <th>Multiplier</th> <th>Name</th> </tr> </thead> <tbody> <tr><td>cut</td> <td>x1.5</td><td>Cutting</td></tr> <tr><td>imp</td> <td>x2.0</td><td>Impaling</td></tr> <tr><td>cr</td> <td>x1.0</td><td>Crushing</td></tr> <tr><td>pi-</td> <td>x0.5</td><td>Small Piercing</td></tr> <tr><td>pi</td> <td>x1.0</td><td>Piercing</td></tr> <tr><td>pi+</td> <td>x1.5</td><td>Large Piercing</td></tr> <tr><td>pi++</td> <td>x2.0</td><td>Huge Piercing</td></tr> <tr><td>aff</td> <td>-</td><td>Affliction</td></tr> <tr><td>burn</td><td>x1.0</td><td>Burning</td></tr> <tr><td>cor</td> <td>x1.0</td><td>Corrosion</td></tr> <tr><td>fat</td> <td>x1.0</td><td>Fatigue</td></tr> <tr><td>tox</td> <td>x1.0</td><td>Toxic</td></tr> <tr><td>spec</td><td>-</td><td>Special</td></tr> </tbody> </table></span> </div> <div class="sheet-cell sheet-col4">Skill</div> </div> <fieldset class="repeating_rituals"> <input class="sheet-toggle" type="checkbox" /> <span class="sheet-checkbox"></span> <div class="sheet-row sheet-row-rituals"> <div class="sheet-cell sheet-col0"><button type="roll" name="attr_ritualroll" value="!ritual @{character_id} @{rowid} [[3d6]] [[@{skill} + @{modifier}]] [[@{damage}]]" /></div> <div class="sheet-cell sheet-col1"><input type="text" name="attr_ritualname" placeholder="Ritual Name"/></div> <div class="sheet-cell sheet-col2"><input type="number" name="attr_ritualenergy" value="0" placeholder="0"/></div> <div class="sheet-cell sheet-col3"><input type="text" name="attr_damage"placeholder="0"/></div> <div class="sheet-cell sheet-col4"> <select name="attr_type"> <option value="cut">Cutting (cut)</option> <option value="imp">Impaling (imp)</option> <option value="cr">Crushing (cr)</option> <option value="pi-">Small Piercing (pi-)</option> <option value="pi">Piercing (pi)</option> <option value="pi+">Large Piercing (pi+)</option> <option value="pi++">Huge Piercing (pi++)</option> <option value="aff">Affliction (aff)</option> <option value="burn">Burning (burn)</option> <option value="cot">Corrosion (cor)</option> <option value="fat">Fatigue (fat)</option> <option value="tox">Toxic (tox)</option> <option value="spc">Special (spc)</option> </select> </div> <div class="sheet-cell sheet-col5"><input type="number" name="attr_skill" value="10" placeholder="0"/></div> </div> <div class="sheet-row sheet-row-ritualdetails"> <div class="sheet-cell sheet-col0"><textarea class="sheet-ritualdesc" name="attr_ritualdescr" placeholder="Ritual Description"></textarea> </div> <div class="sheet-cell sheet-col1"> <textarea class="sheet-ritualcast" name="attr_ritualcasting" placeholder="Typical Casting"></textarea> </div> </div> </fieldset> </div> </div> <!-- ===== END SHEET-BOX SHEET-RITUALS ===== -->
1539472889
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
When does the bad row appear? And do you have any sheet workers?
1539473443
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
Yes I have sheet workers. The bad row box appears after I enter something in a new row.
1539473754

Edited 1539473791
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, can you share your sheetworker code as well. I think this is probably a bad argument getting sent to setAttrs. EDIT: and, is the row that you are editing the one that gets the bad row box, or does it make a new bad row?
1539474209
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
So I deleted the bad rows. then mad a new row. Everything normal so far. Its creating a new empty bad row after I enter data into the clean no error row and turning the row I am working in bad too. My sheet worker code is extensive. However; the console is not throwing any errors.
1539474600
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
var noop = function () {}; // do nothing. var version = '1.5.1'; var modCascade = true; var modCascadeAll = true; /* Due to the change from auto-calc fields to helper scrips, * I'm running a "on open" to set various fields. At some point * in the future this might no longer be needed. */ on('sheet:opened', function() { console.log('********* Sheet Opened *********'); getAttrs(['sheet_version', 'mod_cascade', 'modCascade', 'modCascadeAll'], function(v) { if (v.modCascade && v.modCascadeAll) { modCascade = v.modCascade; modCascadeAll = v.modCascadeAll; } if (!v.sheet_version || v.sheet_version != version) { // Set sheet version: setAttrs({ sheet_version: version }); // initalize any empty fields in repeating sections since the default values were removed. loadRepeating('repeating_languages', 'spoken', 0); loadRepeating('repeating_languages', 'written', 0); loadRepeating('repeating_skills', 'points', 1); loadRepeating('repeating_cultures', 'points', 1); loadRepeating('repeating_techniques', 'points', 1); loadRepeating('repeating_spells', 'points', 1); // initalize all calculated stats resetAll(v.mod_cascade); } }); }); on('change:mod_cascade', function (e) { getAttrs(['mod_cascade'], function (v) { resetAll(v.mod_cascade); }) }); function resetAll(mod_cascade) { switch(mod_cascade) { case 'all': modCascade = true; modCascadeAll = true; break; case 'some': modCascade = true; modCascadeAll = false; break; default: modCascade = false; modCascadeAll = false; } setAttrs({ modCascade: modCascade, modCascadeAll: modCascadeAll }); // After move, dodge, encumbrance, HP, and FP var thenCurrentMoveDodge = _.after(5, function () { updateMoveDodge(); }); // After DX and HT var thenSpeedMoveDodge = _.after(2, function () { updateBasicSpeed(function () { // After Basic Speed... updateBasicMove(thenCurrentMoveDodge); updateDodge(thenCurrentMoveDodge); }); }); // After Lift and weight... var thenEncumbrance = _.after(2, function () { updateEncLevel(thenCurrentMoveDodge); }); sumRepeating('repeating_item', 'weighttotal', function (v) { setAttrs({ total_weight: (v * 100) / 100 }, {silent: false}, thenEncumbrance); }); // Update attributes, then secondary characteristics, and so on... updateST(function () { // After ST... updateHP(thenCurrentMoveDodge); updateLift(thenEncumbrance); updateStrikingST(); }); updateDX(thenSpeedMoveDodge); updateIQ(function () { // After IQ... updateWill(); updatePer(function () { // After Per... updateSense(); }); }); updateHT(function () { updateFP(thenCurrentMoveDodge); thenSpeedMoveDodge(); }); } // Sum values, used in reduce function getSum(total, num) { return (+total || 0) + (+num || 0); } // function to sum a field from a repeating section function sumRepeating(sectionName, fieldName, callback) { getSectionIDs(sectionName, function (ids) { if (ids.length === 0 ) { callback(0); return; } var fieldArray = []; for (var i = 0; i < ids.length; i++) { fieldArray.push(sectionName + '_' + ids[i] + '_' + fieldName); } getAttrs(fieldArray, function (fieldValues) { var vals = Object.values(fieldValues); vals.push(0); var total = vals.reduce(getSum); callback(total); }); }); } // load values of a repeating section function loadRepeating(sectionName, fieldName, defaultValue) { console.log('********* loadRepeating ' + sectionName + '.' + fieldName + '*********'); getSectionIDs(sectionName, function (ids) { if (ids.length === 0 ) { return; } var fieldArray = []; var update = {}; for (var i = 0; i < ids.length; i++) { var propName = sectionName + '_' + ids[i] + '_' + fieldName; fieldArray.push(propName); update[propName] = defaultValue; } getAttrs(fieldArray, function (fieldValues) { Object.assign(update, fieldValues); setAttrs(update); }); }); } // Strength Change on('change:strength_points change:strength_mod', function (e) { updateST(); }); // Update Strength function updateST(callback) { callback = callback || noop; console.log('********* updateST *********'); getAttrs(['strength_points', 'strength_mod'], function(v) { var base = 10 + ((+v.strength_points || 0) / 10 | 0); var mod = +v.strength_mod || 0; setAttrs({ strength_base: base, strength: base + mod }, {silent: false}, callback); }); } // Dexterity Change on('change:dexterity_points change:dexterity_mod', function (e) { updateDX(); }); // Update Dexterity function updateDX(callback) { callback = callback || noop; console.log('********* updateDX *********'); getAttrs(['dexterity_points', 'dexterity_mod'], function(v) { var base = 10 + ((+v.dexterity_points || 0) / 20 | 0); var mod = +v.dexterity_mod || 0; setAttrs({ dexterity_base: base, dexterity: base + mod }, {silent: false}, callback); }); } // Intelligence on('change:intelligence_points change:intelligence_mod', function (e) { updateIQ(); }); // Update Intelligence function updateIQ(callback) { callback = callback || noop; console.log('********* updateIQ *********'); getAttrs(['intelligence_points', 'intelligence_mod'], function(v) { var base = 10 + ((+v.intelligence_points || 0) / 20 | 0); var mod = +v.intelligence_mod || 0; setAttrs({ intelligence_base: base, intelligence: base + mod }, {silent: false}, callback); }); } // Health on('change:health_points change:health_mod', function (e) { updateHT(); }); // Update Health function updateHT(callback) { callback = callback || noop; console.log('********* updateHT *********'); getAttrs(['health_points', 'health_mod'], function(v) { var base = 10 + ((+v.health_points || 0) / 10 | 0); var mod = +v.health_mod || 0; setAttrs({ health_base: base, health: base + mod }, {silent: false}, callback); }); } // HP on('change:strength change:hit_points_points change:hit_points_mod', function (e) { updateHP(); }); // Update HP function updateHP(callback) { console.log('********* updateHP *********'); callback = callback || noop; getAttrs(['strength', 'strength_base', 'hit_points_points', 'hit_points_mod'], function(v) { var base = (modCascadeAll ? +v.strength : +v.strength_base) + ((+v.hit_points_points || 0) / 2 | 0); var mod = +v.hit_points_mod; setAttrs({ hit_points_max: base + mod }, {silent: false}, function () { getAttrs(['hit_points'], function(v2) { if (v2.hit_points == null) { setAttrs({ hit_points: base }, {silent: false}, callback); } else { callback(); } }); }); }); } // FP on('change:health change:fatigue_points_points change:fatigue_points_mod', function (e) { updateFP(); }); // Update FP function updateFP(callback) { console.log('********* updateFP *********'); callback = callback || noop; getAttrs(['health', 'health_base', 'fatigue_points_points', 'fatigue_points_mod'], function(v) { var base = (modCascadeAll ? +v.health : +v.health_base) + ((+v.fatigue_points_points || 0) / 3 | 0); var mod = +v.fatigue_points_mod; setAttrs({ fatigue_points_max: base + mod }, {silent: false}, function () { getAttrs(['fatigue_points'], function(v2) { if (v2.fatigue_points == null) { setAttrs({ fatigue_points: base }, {silent: false}, callback); } else { callback(); } }); }); }); } // Perception on('change:intelligence change:perception_points change:perception_mod', function (e) { updatePer(); }); // Update Perception function updatePer(callback) { console.log('********* updatePer *********'); callback = callback || noop; getAttrs(['intelligence', 'intelligence_base', 'perception_points', 'perception_mod'], function(v) { var base = (modCascade ? +v.intelligence : +v.intelligence_base) + ((+v.perception_points || 0) / 5 | 0); var mod = +v.perception_mod || 0; setAttrs({ perception_base: base, perception: base + mod }, {silent: false}, callback); }); } // Vision, Hearing, Smell, Touch on('change:perception change:vision_points change:vision_mod change:hearing_points change:hearing_mod change:taste_smell_points change:taste_smell_mod change:touch_points change:touch_mod', function (e) { updateSense(); }); // Update Vision, Hearing, Smell, Touch function updateSense() { console.log('********* updateSense *********'); getAttrs(['perception', 'perception_base', 'vision_points', 'vision_mod', 'hearing_points', 'hearing_mod', 'taste_smell_points', 'taste_smell_mod', 'touch_points', 'touch_mod'], function(v) { var base = (modCascade ? +v.perception : +v.perception_base); var visionBase = base + ((+v.vision_points || 0) / 2 | 0); var visionMod = +v.vision_mod || 0; var hearingBase = base + ((+v.hearing_points || 0) / 2 | 0); var hearingMod = +v.hearing_mod || 0; var tasteSmellBase = base + ((+v.taste_smell_points || 0) / 2 | 0); var tasteSmellMod = +v.taste_smell_mod || 0; var touchBase = base + ((+v.touch_points || 0) / 2 | 0); var touchMod = +v.touch_mod || 0; setAttrs({ vision_base: visionBase, vision: visionBase + visionMod, hearing_base: hearingBase, hearing: hearingBase + hearingMod, taste_smell_base: tasteSmellBase, taste_smell: tasteSmellBase + tasteSmellMod, touch_base: touchBase, touch: touchBase + touchMod }); }); } // consciousness, death on('change:health change:consciousness_points change:consciousness_mod change:death_points change:death_mod', function (e) { updateDeath(); }); // Update consciousness, death function updateDeath() { console.log('********* updateDeath *********'); getAttrs(['health', 'health_base', 'consciousness_points', 'consciousness_mod', 'death_points', 'death_mod'], function(v) { var base = (modCascade ? +v.health : +v.health_base); var consciousnessBase = base + ((+v.consciousness_points || 0) / 2 | 0); var consciousnessMod = +v.consciousness_mod || 0; var deathBase = base + ((+v.death_points || 0) / 2 | 0); var deathMod = +v.death_mod || 0; setAttrs({ consciousness_base: consciousnessBase, consciousness: consciousnessBase + consciousnessMod, death_base: deathBase, death: deathBase + deathMod, }); }); } // Update Willpower, Fear on('change:intelligence change:willpower_points change:willpower_mod change:fear_check_points change:fear_check_mod', function (e) { updateWill(); }); // Updage Willpower, Fear -- Updated to reflect 'Rule of 14' for fright checks pg. 360 function updateWill() { console.log('********* updateWill *********'); getAttrs(['intelligence', 'intelligence_base', 'willpower_points', 'willpower_mod', 'fear_check_points', 'fear_check_mod'], function(v) { var wBase = (modCascade ? +v.intelligence : +v.intelligence_base) + ((+v.willpower_points || 0) / 5 | 0); var wMod = +v.willpower_mod || 0; var fBase = wBase + (modCascade ? +wMod : 0) + ((+v.fear_check_points || 0) / 2 | 0); var fMod = +v.fear_check_mod || 0; var fCheck = (Math.min(13, Math.max(-99, fBase + fMod))); setAttrs({ willpower_base: wBase, willpower: wBase + wMod, fear_check_base: fBase, fear_check: fCheck }); }); } // Speed on('change:dexterity change:health change:basic_speed_points change:basic_speed_mod', function (e) { updateBasicSpeed(); }); // Update Speed function updateBasicSpeed(callback) { console.log('********* updateBasicSpeed *********'); callback = callback || noop; getAttrs(['dexterity', 'dexterity_base', 'health', 'health_base', 'basic_speed_points', 'basic_speed_mod'], function(v) { var dx = (modCascade ? +v.dexterity : +v.dexterity_base); var ht = (modCascade ? +v.health : +v.health_base); var base = (dx + ht) / 4 + (((+v.basic_speed_points || 0) / 5 | 0) * 0.25); var mod = +v.basic_speed_mod || 0; setAttrs({ basic_speed_base: base, basic_speed: base + mod }, {silent: false}, callback); }); } // ====== MOVE MODES ============ // Basic Move on('sheet:opened change:basic_speed change:basic_move_points change:basic_move_mod', function (e) { updateBasicMove(); }); // Update Move function updateBasicMove(callback) { console.log('********* updateBasicMove *********'); callback = callback || noop; getAttrs(['basic_speed', 'basic_speed_base', 'basic_move_points', 'basic_move_mod'], function(v) { var speed = (modCascade ? +v.basic_speed : +v.basic_speed_base); var base = Math.floor(speed) + ((+v.basic_move_points || 0) / 5 | 0); var mod = +v.basic_move_mod || 0; setAttrs({ basic_move_base: base, basic_move: base + mod }, {silent: false}, callback); }); } // Ground Move on('change:basic_speed change:basic_move_points change:basic_move_mod change:ground_move_points change:ground_move_mod', function (e) { updateGroundMove(); }); // Update Ground Move function updateGroundMove(callback) { console.log('********* updateGroundMove *********'); callback = callback || noop; getAttrs(['basic_move', 'basic_speed', 'basic_speed_base', 'ground_speed_base', 'ground_move_points', 'ground_move_mod'], function(v) { var speed = (modCascade ? +v.basic_speed : +v.basic_speed_base); var base = Math.floor(speed) + ((+v.ground_move_points || 0) / 5 | 0); var mod = +v.ground_move_mod || 0; setAttrs({ ground_move_base: base, ground_move: base + mod }, {silent: false}, callback); }); } // Air Move on('change:basic_speed change:basic_move_points change:basic_move_mod change:air_move_points change:air_move_mod', function (e) { updateAirMove(); }); // Update Air Move function updateAirMove(callback) { console.log('********* updateAirMove *********'); callback = callback || noop; getAttrs(['basic_move', 'basic_speed', 'basic_speed_base', 'air_speed_base', 'air_move_points', 'air_move_mod'], function(v) { var ground = +v.basic_move var speed = ground * 2; var base = Math.floor(speed) + ((+v.air_move_points || 0) / 2 | 0); var mod = +v.air_move_mod || 0; setAttrs({ air_move_base: base, air_move: base + mod }, {silent: false}, callback); }); } // Space Move on('change:basic_speed change:basic_move_points change:basic_move_mod change:space_move_points change:space_move_mod', function (e) { updateSpaceMove(); }); // Update Space Move function updateSpaceMove(callback) { console.log('********* updateSpaceMove *********'); callback = callback || noop; getAttrs(['basic_move', 'basic_speed', 'basic_speed_base', 'space_speed_base', 'space_move_points', 'space_move_mod'], function(v) { var ground = +v.basic_move var speed = ground * 2; var base = Math.floor(speed) + ((+v.space_move_points || 0) / 2 | 0); var mod = +v.space_move_mod || 0; setAttrs({ space_move_base: base, space_move: base + mod }, {silent: false}, callback); }); } // Water Move on('change:basic_move change:basic_speed change:water_move_points change:water_move_mod', function (e) { updateWaterMove(); }); // Update Water Move function updateWaterMove(callback) { console.log('********* updateWaterMove *********'); callback = callback || noop; getAttrs(['basic_move', 'basic_speed', 'basic_speed_base', 'water_speed_base', 'water_move_points', 'water_move_mod'], function(v) { var move = +v.basic_move var speed = Math.floor(move /5); var base = Math.floor(speed) + ((+v.water_move_points || 0) / 5 | 0); var mod = +v.water_move_mod || 0; setAttrs({ water_move_base: base, water_move: base + mod }, {silent: false}, callback); }); } // Jump on('sheet:opened change:basic_move', function (e) { updateJump(); }); // Jump function updateJump(callback) { console.log('********* updateJump *********'); callback = callback || noop; getAttrs(['basic_move', 'high_jump', 'broad_jump'], function(v) { var move = v.basic_move var hjump = Math.round(((((move)*6)-10)/36)*100)/100; var bjump = Math.round(((((move)*2)-3)/3)); setAttrs({ high_jump: hjump, broad_jump: bjump }, {silent: false}, callback); }); } // Dodge on('change:basic_speed change:dodge_mod', function (e) { updateDodge(); }); // Update Dodge function updateDodge(callback) { console.log('********* updateDodge *********'); callback = callback || noop; getAttrs(['basic_speed', 'basic_speed_base', 'dodge_mod'], function(v) { var speed = (modCascade ? +v.basic_speed : +v.basic_speed_base); var base = Math.floor(speed) + 3; var mod = +v.dodge_mod || 0; setAttrs({ dodge_base: base, dodge: base + mod }, {silent: false}, callback); }); } // Encumbered/injured move and dodge on('change:encumbrance_level change:dodge change:basic_move change:hit_points change:fatigue_points', function (e) { updateMoveDodge(); }); // Update encumbered/injured move and dodge function updateMoveDodge() { console.log('***** UPDATE MOVE/DODGE *****'); getAttrs(['encumbrance_level', 'dodge', 'basic_move', 'hit_points', 'hit_points_max', 'fatigue_points', 'fatigue_points_max', 'strength_base', 'strength_mod'], function(v) { var dodge = +v.dodge; var move = +v.basic_move; var strength = +v.strength_base + +v.strength_mod; if (v.encumbrance_level === 5) { dodge = 1; move = 1; } else { dodge = dodge - +v.encumbrance_level; // There is some math error when calculating Encumbrance which requires the modifier of 1.01 instead of 1 below move = Math.floor(+v.basic_move * (1.01 - (0.2 * +v.encumbrance_level))); dodge = dodge < 1 ? 1 : dodge; move = move < 1 ? 1 : move; } if (+v.hit_points < +v.hit_points_max / 3) { dodge = Math.ceil(dodge / 2); move = Math.ceil(move / 2); } if (+v.fatigue_points < +v.fatigue_points_max / 3 ) { dodge = Math.ceil(dodge / 2); move = Math.ceil(move / 2); strength = Math.ceil(strength / 2); } setAttrs({ current_move: move, current_dodge: dodge, strength: strength }); }); } // Lifting ST on('change:strength change:lift_st_points change:lift_st_mod', function (e) { updateLift(); }); // Update Lift function updateLift(callback) { console.log('********* updateLift *********'); callback = callback || noop; getAttrs(['strength', 'strength_base', 'lift_st_points', 'lift_st_mod'], function(v) { var base = (modCascade ? +v.strength : +v.strength_base) + ((+v.lift_st_points || 0) / 3 | 0); var modded = base + +v.lift_st_mod; var basicLift = (modded * modded) / 5; if (basicLift >= 10) { basicLift = Math.round(basicLift); } setAttrs({ lift_st_base: base, lift_st: modded, basic_lift: basicLift }, {silent: false}, callback); }); } // Striking ST on('change:strength change:striking_st_points change:striking_st_mod', function (e) { updateStrikingST(); }); // Update Striking function updateStrikingST() { console.log('********* updateStrikingST *********'); getAttrs(['strength', 'strength_base', 'striking_st_points', 'striking_st_mod'], function(v) { var base = (modCascade ? +v.strength : +v.strength_base) + ((+v.striking_st_points || 0) / 5 | 0); var mod = +v.striking_st_mod; setAttrs({ striking_st_base: base, striking_st: base + mod }); }); } // Update Attributes on('change:strength_points change:dexterity_points change:intelligence_points change:health_points change:perception_points change:vision_points change:hearing_points change:taste_smell_points change:touch_points change:willpower_points change:fear_check_points change:hit_points_points change:fatigue_points_points change:energy_points_points change:user_pool1_points change:user_pool2_points change:basic_speed_points change:basic_move_points change:striking_st_points change:lift_st_points', function (e) { getAttrs(['strength_points', 'dexterity_points', 'intelligence_points', 'health_points', 'perception_points', 'vision_points', 'hearing_points', 'taste_smell_points', 'touch_points', 'willpower_points', 'fear_check_points', 'hit_points_points', 'fatigue_points_points', 'energy_points_points', 'user_pool1_points', 'user_pool2_points', 'basic_speed_points', 'basic_move_points', 'striking_st_points', 'lift_st_points' ], function(v) { var vals = Object.values(v); vals.push(0); setAttrs({ att_points: vals.reduce(getSum) }); }); }); // Update the total cost of Languages on('change:repeating_languages:spoken change:repeating_languages:written remove:repeating_languages', function (e) { var total = 0; var tally = _.after(2, function () { setAttrs({ languages_points: total }); }); sumRepeating('repeating_languages', 'spoken', function(v) { console.log('Spoken: ' + v); total += +v; tally(); }); sumRepeating('repeating_languages', 'written', function(v) { console.log('Written: ' + v); total += +v; tally(); }); }); // Update the total cost of Cultural Familiarities on('change:repeating_cultures:points remove:repeating_cultures', function (e) { sumRepeating('repeating_cultures', 'points', function(v) { setAttrs({ cf_points: v }); }); }); // Update the total cost of Advantages on('change:repeating_traits:points remove:repeating_traits', function (e) { sumRepeating('repeating_traits', 'points', function(v) { setAttrs({ advantages_points: v }); }); }); // Update the total cost of Perks on('change:repeating_perks:points remove:repeating_perks', function (e) { sumRepeating('repeating_perks', 'points', function(v) { setAttrs({ perks_points: v }); }); }); // Update the total cost of Disadvantages on('change:repeating_disadvantages:points remove:repeating_disadvantages', function (e) { sumRepeating('repeating_disadvantages', 'points', function(v) { setAttrs({ disadvantages_points: v }); }); }); // Update the total cost of Quirks on('change:repeating_quirks:points remove:repeating_quirks', function (e) { sumRepeating('repeating_quirks', 'points', function(v) { setAttrs({ quirks_points: v }); }); }); // Update the total cost of Racial Traits on('change:repeating_racial:points remove:repeating_racial', function (e) { sumRepeating('repeating_racial', 'points', function(v) { setAttrs({ racial_points: v }); }); }); // Update the total cost of Skills on('change:repeating_skills:points remove:repeating_skills', function (e) { sumRepeating('repeating_skills', 'points', function(v) { setAttrs({ skills_points: v }); }); }); // Update the total cost of Techniques on('change:repeating_techniques:points remove:repeating_techniques', function (e) { sumRepeating('repeating_techniques', 'points', function(v) { setAttrs({ techniques_points: v }); }); }); // Update the total cost of Spells on('change:repeating_spells:points remove:repeating_spells', function (e) { sumRepeating('repeating_spells', 'points', function(v) { setAttrs({ spells_points: v }); }); }); // Update Misc on('change:tl_pts change:appearance change:languages_points change:cf_points', function (e) { getAttrs(['tl_pts', 'appearance', 'languages_points', 'cf_points'], function(v) { var vals = Object.values(v); vals.push(0); setAttrs({ misc_points: vals.reduce(getSum) }); }); }); // Update Spent Points on('change:att_points change:misc_points change:advantages_points change:perks_points change:disadvantages_points change:quirks_points change:racial_points change:skills_points change:techniques_points', function (e) { getAttrs(['att_points', 'misc_points', 'advantages_points', 'perks_points', 'disadvantages_points', 'quirks_points', 'racial_points', 'skills_points', 'techniques_points'], function(v) { var vals = Object.values(v); vals.push(0); setAttrs({ total_spent_points: vals.reduce(getSum) }); }); }); // ----------------------------------encumbrance----------------------------------------------- // Update the line LOADOUT A total weight and cost on('change:repeating_item:count change:repeating_item:cost change:repeating_item:loadoutacarried change:repeating_item:weight', function (e) { getAttrs(['repeating_item_count', 'repeating_item_cost', 'repeating_item_weight', 'repeating_item_loadoutacarried'], function (item) { setAttrs({ repeating_item_loadoutaweighttotal: Math.round(item.repeating_item_count * item.repeating_item_weight * item.repeating_item_loadoutacarried * 100) / 100, repeating_item_loadoutacosttotal: Math.round(item.repeating_item_count * item.repeating_item_cost * item.repeating_item_loadoutacarried * 100) / 100 }); }); }); // Update the total weight of LOADOUT A carried items. on('change:repeating_item:loadoutaweighttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutaweighttotal', function(v) { setAttrs({ loadouta_total_weight: (v * 100) / 100 }); }); }); // Update the total cost of LOADOUT A carried items. on('change:repeating_item:loadoutacosttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutacosttotal', function(v) { setAttrs({ loadouta_total_cost: (v * 100) / 100 }); }); }); // Update the line LOADOUT B total weight and cost on('change:repeating_item:count change:repeating_item:cost change:repeating_item:loadoutbcarried change:repeating_item:weight', function (e) { getAttrs(['repeating_item_count', 'repeating_item_cost', 'repeating_item_weight', 'repeating_item_loadoutbcarried'], function (item) { setAttrs({ repeating_item_loadoutbweighttotal: Math.round(item.repeating_item_count * item.repeating_item_weight * item.repeating_item_loadoutbcarried * 100) / 100, repeating_item_loadoutbcosttotal: Math.round(item.repeating_item_count * item.repeating_item_cost * item.repeating_item_loadoutbcarried * 100) / 100 }); }); }); // Update the total weight of LOADOUT B carried items. on('change:repeating_item:loadoutbweighttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutbweighttotal', function(v) { setAttrs({ loadoutb_total_weight: (v * 100) / 100 }); }); }); // Update the total cost of LOADOUT B carried items. on('change:repeating_item:loadoutbcosttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutbcosttotal', function(v) { setAttrs({ loadoutb_total_cost: (v * 100) / 100 }); }); }); // Update the line LOADOUT C total weight and cost on('change:repeating_item:count change:repeating_item:cost change:repeating_item:loadoutccarried change:repeating_item:weight', function (e) { getAttrs(['repeating_item_count', 'repeating_item_cost', 'repeating_item_weight', 'repeating_item_loadoutccarried'], function (item) { setAttrs({ repeating_item_loadoutcweighttotal: Math.round(item.repeating_item_count * item.repeating_item_weight * item.repeating_item_loadoutccarried * 100) / 100, repeating_item_loadoutccosttotal: Math.round(item.repeating_item_count * item.repeating_item_cost * item.repeating_item_loadoutccarried * 100) / 100 }); }); }); // Update the total weight of LOADOUT C carried items. on('change:repeating_item:loadoutcweighttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutcweighttotal', function(v) { setAttrs({ loadoutc_total_weight: (v * 100) / 100 }); }); }); // Update the total cost of LOADOUT C carried items. on('change:repeating_item:loadoutccosttotal remove:repeating_item', function (e) { sumRepeating('repeating_item', 'loadoutccosttotal', function(v) { setAttrs({ loadoutc_total_cost: (v * 100) / 100 }); }); }); // Get Encumbrance Level: on('sheet:opened change:total_weight change:loadout_total_weight change:repeating_item:loadoutaweighttotal change:repeating_item:loadoutbweighttotal change:repeating_item:loadoutcweighttotal change:basic_lift change:loadoutchoice', function (e) { updateEncLevel(); }); function updateEncLevel(callback) { getAttrs(['basic_lift', 'total_weight'], function(v) { callback = callback || noop; var basicLift = +v.basic_lift; var encumbranceLevel = Math.floor(v.total_weight / basicLift); if (encumbranceLevel > 0 && (v.total_weight % basicLift) === 0) { encumbranceLevel--; } if (encumbranceLevel >= 10) { encumbranceLevel = 5; } else if (encumbranceLevel >= 6) { encumbranceLevel = 4; } else if (encumbranceLevel >= 3) { encumbranceLevel = 3; } setAttrs( { encumbrance_level: encumbranceLevel }, {silent: false}, callback ); }); } // Get Loadout Choice: on('sheet:opened change:loadoutchoice', updateloadout); //Update Loadout function updateloadout(callback) { console.log('****updateloadoutchoice****'); getAttrs(['loadoutchoice', 'loadouta_total_weight', 'loadoutb_total_weight', 'loadoutc_total_weight', 'total_weight'], function(v) { callback = callback || noop; if (v.loadoutchoice === "1") { var loadout_totalweight = v.loadouta_total_weight; } else if (v.loadoutchoice === "2") { var loadout_totalweight = v.loadoutb_total_weight; } else if (v.loadoutchoice === "3") { var loadout_totalweight = v.loadoutc_total_weight; } setAttrs({ total_weight: loadout_totalweight }, { silent: false }, callback ); }); } on('sheet:opened change:manuever', function () { getAttrs(["manuever"], function (values) { let manuever = values.manuever; let description = ""; active_defense = ""; movement = ""; page = ""; switch(manuever){ case "DoNoth": description = "Take no action but recover from stun."; active_defense = "Any‡"; movement = "None"; page = "364"; break; case "Mov": description = "Do nothing but move."; active_defense = "Any"; movement = "Full"; page = "364"; break; case "CP": description = "Stand up, sit down, etc."; active_defense = "Any"; movement = "None"; page = "364"; break; case "Aim": description = "Aim a ranged weapon to get its Accuracy bonus."; active_defense = "Any*"; movement = "Step"; page = "364"; break; case "Eval": description = "Study a foe prior to a melee attack."; active_defense = "Any"; movement = "Step"; page = "364"; break; case "Atk": description = "Attack unarmed or with a weapon."; active_defense = "Any"; movement = "Step"; page = "365"; break; case "AtkDa": description = "every -2 you accept to your own skill, enemy suffers a -1 penalty on active defenses"; active_defense = "Any"; movement = "Step"; page = "369"; break; case "Atkr": description = "Make two attacks (with a ready hand/weapon), both at -6"; active_defense = "Any"; movement = "Step"; page = "370"; break; case "Feint": description = "Fake a melee attack."; active_defense = "Any"; movement = "Step"; page = "365"; break; case "AoAdt": description = "+4 to hit"; active_defense = "None"; movement = "Half"; page = "365"; break; case "AoAdb": description = "2 attacks on same foe with ready hand/weapon (weapon attacks -4 to off-hand)"; active_defense = "None"; movement = "Half"; page = "365"; break; case "AoAft": description = "Make one feint and one attack on same foe"; active_defense = "None"; movement = "Half"; page = "365"; break; case "AoAlg": description = "Increase reach by 1 yard"; active_defense = "None"; movement = "Half"; page = "MA87"; break; case "AoAst": description = "+2 to damage (or +1 per damage die)"; active_defense = "None"; movement = "Half"; page = "365"; break; case "AoArd": description = "Make a single attack at +1 to hit."; active_defense = "None"; movement = "Half"; page = "365"; break; case "AoArs": description = "Spray an area with automatic fire."; active_defense = "None"; movement = "Half"; page = "365"; break; case "Atkmv": description = "Full move & attack @ - bulk rating"; active_defense = "Any"; movement = "Full"; page = "365"; break; case "AoDi": description = "Add +2 to one active defense. This bonus persists until your next turn"; active_defense = "Any"; movement = "Varies"; page = "366"; break; case "AoDd": description = " Apply two different active defenses against the same attack."; active_defense = "Any"; movement = "Varies"; page = "366"; break; case "Conc": description = "Focus on a mental task"; active_defense = "Any*"; movement = "Step"; page = "366"; break; case "Ready": description = "Prepare a weapon or other item."; active_defense = "Any"; movement = "Step"; page = "366"; break; case "Wait": description = "Hold yourself in readiness to act."; active_defense = "Any"; movement = "Varies"; page = "366"; break; // Advanced Manuevers Below To be added later case "Atkw": description = "Use both hands to make two attacks (including pistols), both at -4"; active_defense = "Any"; movement = "Step"; page = "369"; break; } setAttrs({ "description": description, "active_defense": active_defense, "movement": movement, "page": page }); }); }); on('sheet:opened change:repeating_advantages', function(){ TAS.repeating('advantages') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_perks', function(){ TAS.repeating('perks') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_disadvantages', function(){ TAS.repeating('disadvantages') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_quirks', function(){ TAS.repeating('quirks') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_skills', function(){ TAS.repeating('skills') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_techniques', function(){ TAS.repeating('techniques') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_ranged', function(){ TAS.repeating('ranged') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_defense', function(){ TAS.repeating('defense') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_spells', function(){ TAS.repeating('spells') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); }); on('sheet:opened change:repeating_rituals', function(){ TAS.repeating('rituals') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); });
1539474643
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
This isn't something that would throw a console error. Where I've run into this is that I've forced the creation of a new row during the setting of current rows. The new row is set incorrectly (usually without a row ID) and so is broken.
1539474911
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, what does this code do: on('sheet:opened change:repeating_rituals', function(){ TAS.repeating('rituals') .fields('rowid') .map(function(r,a,id){ r.rowid = id; }) .execute(); });
1539475936
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
It provides a rowid to an API I have one for each of my repeating rows that the API needs a row id to pull data
1539479863
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, so, I think what's going on is that for some reason TAS is grabbing an extra row, that doesn't have an id. Change it to this: on('sheet:opened change:repeating_rituals', function(){ TAS.repeating('rituals') .fields('rowid') .map(function(r,a,id){             TAS.log(`r: ${JSON.stringify(r)}`);             TAS.log(`a: ${a}`);             TAS.log(`id:${id}`); r.rowid = id; }) .execute(); }); And then, I'm going to ping Aaron to look for what that logs.
1539480421
The Aaron
Pro
API Scripter
Do you have the hidden field for rowid in the rituals repeating section? I don't see it in the HTML above.