### Version 1.1.12

- Added Salvage tab to Trade to allow for free stuff Travellers get
- Fixed Consolidate button in Manifest for Trade to only consolidate where price paid and commodity match (and ensure salvage does not get consolidated)
This commit is contained in:
Simon Brooke
2026-02-09 09:20:39 +00:00
parent 69f4370a2f
commit 5c1216a3f4
4 changed files with 328 additions and 32 deletions
@@ -57,6 +57,7 @@ p {
.sheet-passengers,
.sheet-freight,
.sheet-speculative,
.sheet-salvage,
.sheet-tradelog,
.sheet-trade,
.sheet-help,
@@ -197,6 +198,14 @@ p {
opacity: 1;
}
.sheet-tradetoggle[value="salvage"] ~ .sheet-salvage {
display: block;
margin-left: 3px;
animation-name: slide-in;
animation-duration: 1s;
opacity: 1;
}
.sheet-tradetoggle[value="tradelog"] ~ .sheet-tradelog {
display: block;
margin-left: 3px;
@@ -1366,6 +1375,7 @@ input.sheet-vehicletypeshow[value="vehiclenotes"] ~ .sheet-type-vehiclenotes,
input.sheet-tradetypeshow[value="passengers"] ~ .sheet-type-passengers,
input.sheet-tradetypeshow[value="freight"] ~ .sheet-type-freight,
input.sheet-tradetypeshow[value="speculative"] ~ .sheet-type-speculative,
input.sheet-tradetypeshow[value="salvage"] ~ .sheet-type-salvage,
input.sheet-tradetypeshow[value="tradelog"] ~ .sheet-type-tradelog,
input.sheet-typeshow[value="trade"] ~ .sheet-type-trade,
input.sheet-typeshow[value="help"] ~ .sheet-type-help,
@@ -1542,6 +1552,7 @@ button.btn.repcontrol_edit::after {
.sheet-passengers,
.sheet-freight,
.sheet-speculative,
.sheet-salvage,
.sheet-tradelog{
font-size: 1.1em !important;
}
@@ -1657,6 +1668,33 @@ div[data-groupname=repeating_speculative-freight-goods].repcontrol {
display: none;
}
/* Hide the buttons for repeating group as salvage list is preset */
.sheet-salvage > .repcontrol {
display: none;
}
.sheet-salvage-control {
width: 50%;
display: grid;
grid-template-columns: 4fr 1fr;
}
.sheet-salvage-control > button {
height: 28px;
}
.sheet-salvage-control > input {
margin-top: 2px;
}
div.sheet-salvage-row {
/* width: 50%;*/
display: grid;
grid-template-columns: 0.25fr 2fr 1fr 0.1fr 0.25fr 2fr 1fr;
column-gap: 5px;
font-size: 1.1em;
}
.sheet-rolltemplate-alt:has(.sheet-template-hazard-border) div:before,
.sheet-rolltemplate-alt:has(.sheet-template-hazard-border) div:after {
border-top: 0;
@@ -11554,11 +11554,15 @@
data-i18n="speculative-u">
Speculative
</button>
<button type="action" name="act_salvage" class="sheet-type sheet-type-salvage"
data-i18n="salvage-u">
Speculative
</button>
<button type="action" name="act_tradelog" class="sheet-type sheet-type-tradelog">
Log
</button>
<button class="sheet-floating_compendium_info sheet-floating_compendium_button" type="compendium"
value="Rules:CR-TRADE"></button>
value="Rules:CR-TRADE-1"></button>
</div>
<!-- Cargo Manifest-->
<span class="sheet-bold">(It is recommended using the Purchase and Sale UWPs as these will auto-fill attributes across all Trade types)</span>
@@ -11633,8 +11637,7 @@
<span class="sheet-textright">Total Tons: <span name="attr_speculative_tons_total"></span></span>
</div>
<hr class="sheet-hr">
<h4>
Speculative Goods</h4>
<h4>Speculative Goods (⛏ = Salvage)</h4>
<fieldset class="repeating_speculative-sale-goods">
<div class="sheet-speculativegoods-row-pg">
<span name="attr_speculative_sg_key"></span>
@@ -11734,8 +11737,7 @@
</div>
</div>
<div class="sheet-tab-content sheet-passengers">
<h4>
Passengers</h4>
<h4>Passengers</h4>
<br>
<div class="sheet-redborder">
<span>Broker, Carouse or Streetwise Check Effect</span>
@@ -11918,8 +11920,7 @@
</div>
</div>
<div class="sheet-tab-content sheet-freight">
<h4>
Freight</h4>
<h4>Freight</h4>
<br>
<p class="sheet-bold">
Freight (Note<span class="sheet-mail-attrs">coloured</span> parameters only applicable to
@@ -12260,8 +12261,7 @@
</div>
</div>
<div class="sheet-tab-content sheet-speculative">
<h4>
Speculative</h4>
<h4>Speculative</h4>
<br>
<button type="action" class="sheet-redborder sheet-bordered-width" name="act_speculative-reset">
<span class="sheet-speculativebutton">9&nbsp;</span>Reset Speculative To Defaults
@@ -12704,8 +12704,7 @@
<input type="text" class="sheet-hidden" name="attr_speculative_sale_warning">
<span class="sheet-warning" name="attr_speculative_sale_warning"></span>
<div class="sheet-speculative-subpanel">
<h4>
7. Sell Goods</h4>
<h4>7. Sell Goods (⛏ = Salvage)</h4>
<br>
<div>
<div class="sheet-speculativegoods-row">
@@ -12722,7 +12721,7 @@
<h5>
(Multiplier)</h5>
<h5>
Base Px</h5>
Bought Px</h5>
<h5>
P/L</h5>
<h5>
@@ -12799,6 +12798,168 @@
</button>
</div>
</div>
<div class="sheet-tab-content sheet-salvage">
<h4>Salvage</h4>
<br>
<div class="sheet-salvage-control">
<button type="action" name="act_apply-salvage" class="sheet-redborder sheet-bordered-width">Apply Salvage
</button>
</div>
<div class="sheet-salvage-row">
<span>Key</span>
<span>Type</span>
<span>Tons</span>
<span></span>
<span>Key</span>
<span>Type</span>
<span>Tons</span>
<span>11</span>
<span>Common Electronics</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_11" min="0" value="0">
<span></span>
<span>12</span>
<span>Common Industrial Goods</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_12" min="0" value="0">
<span>13</span>
<span>Common Manufactured Goods</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_13" min="0" value="0">
<span></span>
<span>14</span>
<span>Common Raw Materials</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_14" min="0" value="0">
<span>15</span>
<span>Common Consumables</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_15" min="0" value="0">
<span></span>
<span>16</span>
<span>Common Ore</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_16" min="0" value="0">
<span>21</span>
<span>Advanced Electronics</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_21" min="0" value="0">
<span></span>
<span>22</span>
<span>Advanced Machine Parts</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_22" min="0" value="0">
<span>23</span>
<span>Advanced Manufactured Goods</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_23" min="0" value="0">
<span></span>
<span>24</span>
<span>Advanced Weapons</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_24" min="0" value="0">
<span>25</span>
<span>Advanced Vehicles</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_25" min="0" value="0">
<span></span>
<span>26</span>
<span>Biochemicals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_26" min="0" value="0">
<span>31</span>
<span>Crystals & Gems</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_31" min="0" value="0">
<span></span>
<span>32</span>
<span>Cybernetics</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_32" min="0" value="0">
<span>33</span>
<span>Live Animals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_33" min="0" value="0">
<span></span>
<span>34</span>
<span>Luxury Consumables</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_34" min="0" value="0">
<span>35</span>
<span>Luxury Goods</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_35" min="0" value="0">
<span></span>
<span>36</span>
<span>Medical Supplies</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_36" min="0" value="0">
<span>41</span>
<span>Petrochemicals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_41" min="0" value="0">
<span></span>
<span>42</span>
<span>Pharmaceuticals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_42" min="0" value="0">
<span>43</span>
<span>Polymers</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_43" min="0" value="0">
<span></span>
<span>44</span>
<span>Precious Metals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_44" min="0" value="0">
<span>45</span>
<span>Radioactives</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_45" min="0" value="0">
<span></span>
<span>46</span>
<span>Robots</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_46" min="0" value="0">
<span>51</span>
<span>Spices</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_51" min="0" value="0">
<span></span>
<span>52</span>
<span>Textiles</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_52" min="0" value="0">
<span>53</span>
<span>Uncommon Ore</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_53" min="0" value="0">
<span></span>
<span>54</span>
<span>Uncommon Raw Materials</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_54" min="0" value="0">
<span>55</span>
<span>Wood</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_55" min="0" value="0">
<span></span>
<span>56</span>
<span>Vehicles</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_56" min="0" value="0">
<span>61</span>
<span>Illegal Biochemicals</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_61" min="0" value="0">
<span></span>
<span>62</span>
<span>Cybernetics, Illegal</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_62" min="0" value="0">
<span>63</span>
<span>Drugs, Illegal</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_63" min="0" value="0">
<span></span>
<span>64</span>
<span>Luxuries, Illegal</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_64" min="0" value="0">
<span>65</span>
<span>Weapons, Illegal</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_65" min="0" value="0">
<span></span>
<span>66</span>
<span>Exotics</span>
<input class="sheet-input" type="number" name="attr_salvage_tons_66" min="0" value="0">
</div>
</div>
<div class="sheet-tab-content sheet-tradelog">
<h3 class="sheet-bold">
Trade Log</h3>
@@ -12813,12 +12974,13 @@
</div>
</div>
<div class="sheet-tab-content sheet-help">
<h3>Character Sheet Version 1.1.11</h3>
<h3>Character Sheet Version 1.1.12</h3>
<br>
<h4>Assigning Attributes To Tokens</h4>
<p style="margin-left: 10px; margin-top: 5px;">To represent the core character attributes on a token so they can be
edited via the 'bubbles' use:<br>
currwithmax-&lt;Characteristic&gt;, e.g. currwithmax-Strength.<br><br>This works for the core characteristics, Psionic
currwithmax-&lt;Characteristic&gt;, e.g. currwithmax-Strength.<br><br>This works for the core characteristics,
Psionic
Strength and also the Morale characteristic found on the Ship -> Combat tab.
</p>
<p style="margin-left: 10px; margin-top: 5px;">
@@ -14210,7 +14372,7 @@
});
});
const buttonlist_sheettradetype = ["passengers", "freight", "speculative", "tradelog"];
const buttonlist_sheettradetype = ["passengers", "freight", "speculative", "salvage", "tradelog"];
buttonlist_sheettradetype.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
@@ -16641,35 +16803,46 @@
repSpeculativeSaleGoodsChanged();
}
else {
getSectionIDs("repeating_speculative-sale-goods", function(idArray) {
getSectionIDs("speculative-sale-goods", function(idArray) {
addTradeLogMessage("- Consolidating hold goods", true);
var keyAttrs = [];
for(var i=0; i < idArray.length; i++) {
// Create attribute names for keys
var key = "repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_key";
var key = "repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_type";
keyAttrs.push(key);
key = "repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_tons_display";
keyAttrs.push(key);
key = "repeating_speculative-sale-goods_" + idArray[i] + "_speculative_pg_price";
keyAttrs.push(key);
}
// Get the rows
var updates = {};
var tradeKeyInfo = {};
var tradeTypeInfo = {};
getAttrs(keyAttrs, function (value) {
for(var i=0; i < idArray.length; i++) {
var tradeKey = value["repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_key"];
var tons = +value["repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_tons_display"];
if(tradeKeyInfo[tradeKey] === undefined) {
// Note that we are keying on type of commodity ('Common Electronics'), not key ('11'), this
// is because salvage is appended with an icon and we don't want to match on salvaged goods...
// We also have to match on price as we cannot consolidate multiple entries for the same
// commodity with different prices
for(var i=0; i < idArray.length; i++) {
var tradeType = value["repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_type"];
var tons = +value["repeating_speculative-sale-goods_" + idArray[i] + "_speculative_sg_tons_display"];
var price = +value["repeating_speculative-sale-goods_" + idArray[i] + "_speculative_pg_price"];
if(tradeTypeInfo[tradeType] === undefined) {
// First time seen
tradeKeyInfo[tradeKey] = { tons: tons, id: idArray[i] }
tradeTypeInfo[tradeType] = { tons: tons, id: idArray[i], price: price }
}
else {
// We have a duplicate, create/update a setAttr object key...
updates["repeating_speculative-sale-goods_" + tradeKeyInfo[tradeKey].id + "_speculative_sg_tons_display"] = tradeKeyInfo[tradeKey].tons + tons;
// ...and delete this duplicate row
removeRepeatingRow("repeating_speculative-sale-goods_" + idArray[i]);
repSpeculativeSaleGoodsChanged();
// We have a duplicate, create/update a setAttr object key if price is the same
if(tradeTypeInfo[tradeType].price === price) {
updates["repeating_speculative-sale-goods_" + tradeTypeInfo[tradeType].id + "_speculative_sg_tons_display"] = tradeTypeInfo[tradeType].tons + tons;
// ...and delete this duplicate row
removeRepeatingRow("repeating_speculative-sale-goods_" + idArray[i]);
repSpeculativeSaleGoodsChanged();
}
}
}
setAttrs(updates);
@@ -16761,7 +16934,9 @@
// So the above does a bit of a switcheroo, if we lose the 0x freight codes, we have to recombobulate rowIdsArray as we index into both
// to find the key, and then the unique row id corresponding to that key, ergh!
rowIdsArray = tmpRowIdsArray;
saleGoodsKeys = [...new Set(saleGoodsKeys)];
// NOTE: Previously we made this a unique set, but with salvage we need to allow duplicate goods keys as they were bought for 'free'
// so are pure profit...Got to be VERY careful with these changes as trade is so complicated!
//saleGoodsKeys = [...new Set(saleGoodsKeys)];
addTradeLogMessage("- Unique trade code keys: " + JSON.stringify(saleGoodsKeys), true);
// We also will need to roll 3D6 for each UNIQUE goods key for price, may as well do it now and pluck off the rolls we need
@@ -16931,7 +17106,7 @@
priceAttrs["repeating_speculative-sale-goods_" + rowIdsArray[i] + "_speculative_sg_pl_neg"] = " ";
priceAttrs["repeating_speculative-sale-goods_" + rowIdsArray[i] + "_speculative_sg_pl"] = pl;
}
console.log("- PriceAttrs: " + JSON.stringify(priceAttrs));
//console.log("- PriceAttrs: " + JSON.stringify(priceAttrs));
}
});
finishRoll(qtyResults.rollId, {});
@@ -17298,7 +17473,7 @@
// Calculate fee, I used the locale string to format so need to unformat by replacing commas, hacky but safe as we specify en-US on our toLocaleString()
// We also add a total total, e.g. supplier total plus fee showing the actual final amount the Traverllers have to pay
console.log("- About to info.newValue.replaceAll");
// For some reason info.newValue can be undefined occasionally so the replaceAll fails, check and zero I guess...
var total = info.newValue ? +info.newValue.replaceAll(",", "") : 0;
var fee = Math.round(total * brokerFeeMultiplier);
@@ -17556,6 +17731,84 @@
});
}
/*
* Populate salvage on sheet open, this could be hardcoded but hmmm...
*/
on("xxxxxsheet:opened", (info) => {
//console.log("MgT2E: Show salvage");
// Clear out salvage rows
deleteRepeatingRows("repeating_salvage");
// Repopulate salvage rows
let newAttrs = {};
rowIdCnt=0;
let tradeGoodKeys = Object.keys(tradeGoods).sort();
tradeGoodKeys.forEach(tradeGoodKey => {
const tradeGood = tradeGoods[tradeGoodKey];
let newId = generateRowID();
newAttrs["repeating_salvage_" + newId + "_salvage_key"] = tradeGoodKey;
newAttrs["repeating_salvage_" + newId + "_salvage_type"] = tradeGood.type;
newAttrs["repeating_salvage_" + newId + "_salvage_tons"] = 0;
console.log(tradeGoodKey + " " + tradeGood.type);
});
// Now do the illegals
tradeGoodKeys = Object.keys(tradeGoodsIllegal).sort()
tradeGoodKeys.forEach(tradeGoodKey => {
const tradeGood = tradeGoodsIllegal[tradeGoodKey];
let newId = generateRowID();
newAttrs["repeating_salvage_" + newId + "_salvage_key"] = tradeGoodKey;
newAttrs["repeating_salvage_" + newId + "_salvage_type"] = tradeGood.type;
newAttrs["repeating_salvage_" + newId + "_salvage_tons"] = 0;
console.log(tradeGoodKey + " " + tradeGood.type);
});
setAttrs(newAttrs);
});
/*
* Apply salvage
*/
on("clicked:apply-salvage", (info) => {
const tradeKeys = ["11", "12", "13", "14", "15", "16", "21", "22", "23", "24", "25", "26", "31", "32", "33",
"34", "35", "36", "41", "42", "43", "44", "45", "46", "51", "52", "53", "54", "55", "56", "61", "62",
"63", "64", "65", "66", ];
let attrs = [];
tradeKeys.forEach(key => {
attrs.push("salvage_tons_" + key);
});
getAttrs(attrs, function (values) {
let newAttrs = {};
tradeKeys.forEach(key => {
let tons = parseFloat(values["salvage_tons_" + key]);
if(tons > 0) {
let tradeGoodsObj = tradeGoods[key];
if(!tradeGoodsObj) {
tradeGoodsObj = tradeGoodsIllegal[key];
}
var newId = generateRowID();
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_sg_key"] = key;
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_sg_type"] = tradeGoodsObj.type + " ⛏";
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_sg_tons"] = tons;
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_sg_tons_display"] = tons;
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_sg_baseprice"] = tradeGoodsObj.basePrice
newAttrs["repeating_speculative-sale-goods_" + newId + "_speculative_pg_price"] = 0;
// Reset the salvage row
newAttrs["salvage_tons_" + key] = 0;
}
});
setAttrs(newAttrs);
});
});
on("clicked:repeating_animalskills:animalskill", (info) => {
console.log("MgT2E: Animal skill: " + JSON.stringify(info))
+5 -1
View File
@@ -131,6 +131,10 @@ This is the Official Mongoose Traveller 2nd Edition Character Sheet
### Version 1.1.11
- Added STR modifier when weapon range is 'Melee' as per rules
- Added repeating groups under all ship sheet components to allow for extended/custom/2300AD entries
-
### Version 1.1.12
- Added Salvage tab to Trade to allow for free stuff Travellers get
- Fixed Consolidate button in Manifest for Trade to only consolidate where price paid and commodity match (and ensure salvage does not get consolidated)
![Image](Official%20Mongoose%20Publishing%20Traveller%202nd%20Edition.png)
@@ -216,6 +216,7 @@
"passengers-u": "Passengers",
"freight-u": "Freight",
"speculative-u": "Speculative",
"salvage-u": "Salvage",
"trade-u": "Trade",
"sheettype-u": "Sheet Type:",
"rollbehaviour-u": "Roll behaviour:",