Config/script.js |
"use strict";
this.name = "ShipRepurchase";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Implements a ship repurchase process for when the player's ship is destroyed.";
this.licence = "CC BY-NC-SA 4.0";
this._debug = true;
this._doRepurchase = false;
this._repurchasePercent = 0.1;
this._baseShipCost = 0;
this._fullShipCost = 0;
this._jamesonPoint = 16;
this._portable = [];
this._roles = [];
this._lastEjectDates = [];
this._ejectDate = 0;
this._simulator = false;
this._insuranceDate = 0;
this._scTimer = null;
this._cargoRecovery = [];
this._cargoRecoverySummary = "";
this._applyPenalty = false;
this._interstellarRecovery = false;
this._interstellarMode = false;
this._interstellarFreeShip = {
key: "cobramk1-player",
name: "Cobra Mark I"
};
this._storedShip = "";
// dictionary of equipment key/min techlevel items to apply as an override when auto-repairing equipment
// additional equipment items could be added here for further restrictions on auto-repair
this._autoRepairMinTL = {
"EQ_CLOAKING_DEVICE": 14,
"EQ_MILITARY_JAMMER": 99,
"EQ_MILITARY_SCANNER_FILTER": 99
};
// used to calculate how far back the premium calculation will look for repurchase events. based on player.score
this._periodLevels = {
"0": 30,
"8": 30,
"16": 30,
"32": 60,
"64": 90,
"128": 120,
"512": 180,
"2560": 270,
"6400": 365
};
// dictionary of min values and key/name dictionary
// used to determine which free ship is available based on the original cost of the players current ship
this._freeShipTrader = {
"650000": {
key: "anaconda-player",
name: "Anaconda"
},
"495000": {
key: "boa-mk2-player",
name: "Boa Class Cruiser"
},
"450000": {
key: "boa-player",
name: "Boa"
},
"200000": {
key: "python-player",
name: "Python"
},
"150000": {
key: "cobra3-player",
name: "Cobra Mark III"
},
"145000": {
key: "morayMED-player",
name: "Moray Medical Boat"
},
"125000": {
key: "moray-player",
name: "Moray Star Boat"
},
"100000": {
key: "cobramk1-player",
name: "Cobra Mark I"
},
"65000": {
key: "adder-player",
name: "Adder"
}
};
this._freeShipHunter = {
"485000": {
key: "ferdelance-player",
name: "Fer-de-Lance"
},
"375000": {
key: "asp-player",
name: "Asp Mark II"
},
"150000": {
key: "cobra3-player",
name: "Cobra Mark III"
},
"125000": {
key: "moray-player",
name: "Moray Star Boat"
},
};
this._freePick1 = null; // ship key of the free ship the player chose
this._freePick2 = null;
// some OXP ship packs change the default price of Cobra Mark III's and Mark I's.
// We're putting overrides in here so we can be consistent.
this._overrideBasePrice = {
"Cobra Mark III": 150000,
"Cobra Mark I": 100000
};
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
var trueValues = ["yes", "1", 1, "true", true];
if (missionVariables.ShipRepurchase_LastEjectDates) this._lastEjectDates = JSON.parse(missionVariables.ShipRepurchase_LastEjectDates);
if (missionVariables.ShipRepurchase_InsuranceDate) this._insuranceDate = missionVariables.ShipRepurchase_InsuranceDate;
if (missionVariables.ShipRepurchase_StoredShip) this._storedShip = missionVariables.ShipRepurchase_StoredShip;
if (missionVariables.ShipRepurchase_InterstellarMode) this._interstellarMode = (trueValues.indexOf(missionVariables.ShipRepurchase_InterstellarMode) >= 0 ? true : false);
/*if (worldScripts.ShipConfiguration_Armour) {
// monkey patch shipconfig armour so we can make sure things get done in the right sequence
var sca = worldScripts.ShipConfiguration_Armour;
sca.$sr_shipLaunchedFromStation = sca.shipLaunchedFromStation;
delete sca.shipLaunchedFromStation;
}*/
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
if (this._lastEjectDates.length > 0) {
missionVariables.ShipRepurchase_LastEjectDates = JSON.stringify(this._lastEjectDates);
} else {
delete missionVariables.ShipRepurchase_LastEjectDates;
}
missionVariables.ShipRepurchase_InsuranceDate = this._insuranceDate;
if (this._storedShip != "") {
missionVariables.ShipRepurchase_StoredShip = this._storedShip;
} else {
delete missionVariables.ShipRepurchase_StoredShip;
}
missionVariables.ShipRepurchase_InterstellarMode = this._interstellarMode;
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedEscapePod = function (pod) {
if (this._simulator) return;
this._ejectDate = clock.adjustedSeconds;
}
//-------------------------------------------------------------------------------------------------------------
// todo: what happens if multiple events turn up simultaneously?
this.shipTakingDamage = function (amount, whom, type) {
if (this._simulator) return;
// are we just about to die?
// award the escape pod and eject
if (this._debug) log(this.name, "shipTakingDamage " + amount + ", " + type + " : current ship energy " + (player.ship ? player.ship.energy : "no player ship!"));
if (player.ship && player.ship.energy <= 0) {
// turn off ship config functions
var sc = worldScripts.ShipConfiguration_Core;
if (sc) {
sc._repairing = true;
sc._adding = true;
}
var p = player.ship;
if (this._debug) log(this.name, "attempting to award escape pod");
var result = p.awardEquipment("EQ_ESCAPE_POD");
if (this._debug) log(this.name, "award escape pod result " + result);
// if the result of adding an escape pod was false, this means the player already had a functional one
this._cargoRecoverySummary = "";
if (result === false) {
var eq;
if (p.equipmentStatus("EQ_ESCAPE_POD") == "EQUIPMENT_OK") {
eq = EquipmentInfo.infoForKey("EQ_ESCAPE_POD");
this._cargoRecoverySummary = "some";
}
if (p.equipmentStatus("EQ_ESCAPE_POD_PLUS") == "EQUIPMENT_OK") {
eq = EquipmentInfo.infoForKey("EQ_ESCAPE_POD_PLUS")
this._cargoRecoverySummary = "most";
}
var tm = parseInt(eq.scriptInfo["max_rescue_time"]);
// set the amount of time for the rescue
if (p.hasOwnProperty("escapePodRescueTime")) p.escapePodRescueTime = ((tm / 2) + (Math.random() * (tm / 2))) * 3600;
this._repurchasePercent = parseFloat(eq.scriptInfo["repurchase_percent"]);
// grab a copy of all the cargo on board
this._cargoRecovery.length = 0;
var cr = parseFloat(eq.scriptInfo["cargo_recovery"]);
if (cr > 0) {
var t = 0;
var m = p.manifest;
if (m.list && m.list.length > 0) {
for (var i = 0; i < m.list.length; i++) {
if (m.list[i].unit == "t" && m.list[i].quantity > 0) {
this._cargoRecovery.push(m.list[i]);
t += m.list[i].quantity;
}
}
}
var rm = parseInt((1 - cr) * t); // amount of cargo to remove
if (rm > 0) {
var pt = 0;
var end = false;
do {
if (this._cargoRecovery[pt].quantity > 0) {
this._cargoRecovery[pt].quantity -= 1;
rm -= 1;
}
pt += 1;
if (pt >= this._cargoRecovery.length) pt = 0;
if (rm <= 0) end = true;
} while (end == false);
} else {
this._cargoRecoverySummary = "";
this._cargoRecovery.length = 0;
}
} else {
this._cargoRecoverySummary = "";
}
} else {
// null out any gold, platinum and gems - they won't fit in the lifesuit
this._cargoRecovery = [];
p.manifest["gold"] = 0;
p.manifest["platinum"] = 0;
p.manifest["gem_stones"] = 0;
// manually remove passengers and parcels
// remove parcels - these won't fit either
for (var i = p.parcels.length - 1; i >= 0; i--) {
// tell player about this via an arrival report
player.addMessageToArrivalReport(expandDescription("[parcel-lost]", {
name: p.parcels[i].name
}));
// send an email message for our special case
var w = worldScripts.EmailSystem;
if (w) {
var sndr = expandDescription("[parcel-contract-sender]");
var msg = expandDescription("[sr-parcel-contract-terminated]", {
contractname: p.parcels[i].name,
systemname: System.systemNameForID(p.parcels[i].destination),
time: global.clock.clockStringForTime(clock.seconds + p.parcels[i].eta)
});
var subj = expandDescription("[sr-parcel-contract-terminated-subject]");
w.$createEmail({
sender: sndr,
subject: subj,
date: global.clock.seconds,
message: msg,
expiryDays: worldScripts.GalCopAdminServices._defaultExpiryDays
});
}
var bb = worldScripts.BulletinBoardSystem;
var cobb = worldScripts.ContractsOnBB;
if (bb && cobb) {
for (var j = 0; j < bb._data.length; j++) {
var itm = bb._data[j];
if (itm != null && itm.accepted === true) {
// is this item the one we're dealing with?
if (itm.destination === p.parcels[i].destination && itm.payment === p.parcels[i].fee && itm.source === p.parcels[i].start) {
bb.$removeBBMission(itm.ID);
break;
}
}
}
}
p.removeParcel(p.parcels[i].name);
player.decreaseParcelReputation();
}
// remove passengers - they won't fit either
var list = "";
var count = p.passengers.length;
if (count >= 1) {
for (var i = count - 1; i >= 0; i--) {
list += (list === "" ? "" : (i === count - 1 ? " and " : ", ")) + p.passengers[i].name;
// send an email message for our special case
var w = worldScripts.EmailSystem;
if (w) {
var sndr = expandDescription("[passenger-contract-sender]");
var msg = expandDescription("[sr-passenger-contract-terminated]", {
contractname: p.passengers[i].name,
systemname: System.systemNameForID(p.passengers[i].destination),
time: clock.clockStringForTime(clock.seconds + p.passengers[i].eta)
});
var subj = expandDescription("[sr-passenger-contract-terminated-subject]");
w.$createEmail({
sender: sndr,
subject: subj,
date: global.clock.seconds,
message: msg,
expiryDays: worldScripts.GalCopAdminServices._defaultExpiryDays
});
}
var bb = worldScripts.BulletinBoardSystem;
var cobb = worldScripts.ContractsOnBB;
if (bb && cobb) {
for (var j = 0; j < bb._data.length; j++) {
var itm = bb._data[j];
if (itm != null && itm.accepted === true) {
// is this item the one we're dealing with?
if (itm.destination === p.passengers[i].destination && itm.payment === p.passengers[i].fee && itm.source === p.passengers[i].start) {
bb.$removeBBMission(itm.ID);
break;
}
}
}
}
p.removePassenger(p.passengers[i].name);
player.decreasePassengerReputation();
}
if (count > 1) {
player.addMessageToArrivalReport(expandDescription("[passengers-lost]", {
names: list
}));
} else {
player.addMessageToArrivalReport(expandDescription("[passenger-lost]", {
name: list
}));
}
}
}
if (this._debug) log(this.name, "auto-ejecting...");
p.abandonShip();
if (sc) {
sc._repairing = false;
sc._adding = false;
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.escapePodSequenceOver = function () {
if (this._simulator) return;
this._doRepurchase = true;
// stop hull repairs from showing up
if (missionVariables.BattleDamage_status != "OK") missionVariables.BattleDamage_status = "OK";
if (system.isInterstellarSpace) {
this._interstellarRecovery = true;
this._cargoRecovery.length = 0; // no cargo recovery in interstellar space
this._cargoRecoverySummary = "";
// only continue if IST is not installed - it will control the recovery chance and end-point
if (!worldScripts["IST_masterScript"]) {
if (system.stations.length > 0) {
// similar logic as for IST
// naval rescue - near
if (this._debug === true || Math.random() <= 0.8) {
var navalCarriers = system.filteredEntities(this, this.$isNavalCarrier, player.ship, 30000);
if (navalCarriers.length > 0) {
player.setEscapePodDestination(navalCarriers[0]);
return;
}
}
// naval rescue - further away
if (this._debug === true || Math.random() <= 0.4) {
navalCarriers = system.filteredEntities(this, this.$isNavalCarrier, player.ship, 100000);
if (navalCarriers.length > 0) {
player.setEscapePodDestination(navalCarriers[0]);
return;
}
}
// other station types (eg Erehwon)
if (this._debug === true || Math.random() <= 0.4) {
var nonNavalCarriers = system.filteredEntities(this, this.$isNotNavalCarrier, player.ship, 200000);
if (nonNavalCarriers.length > 0) player.setEscapePodDestination(nonNavalCarriers[0]);
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
if (equipmentKey === "EQ_REPURCHASE_INSURANCE") this._insuranceDate = clock.adjustedSeconds;
}
//-------------------------------------------------------------------------------------------------------------
this.missionScreenOpportunity = function () {
// check if our insurance has lapsed
if (this._insuranceDate != 0 && (clock.adjustedSeconds - this._insuranceDate) > (86400 * 60) && this._doRepurchase === false) {
player.ship.removeEquipment("EQ_REPURCHASE_INSURANCE");
this._insuranceDate = 0;
mission.runScreen({
screenID: "oolite-insurance-expiry-map",
title: "Repurchase Insurance",
overlay: {
name: "shiprepurchase_logo.png",
height: 546
},
message: expandDescription("[insurance_lapsed]"),
exitScreen: "GUI_SCREEN_STATUS"
});
return;
}
if (this._passengerList && this._passengerList.length > 0) {
if (this._passengerList.length > 1) {
// more than 1 passenger
var list = "";
for (var i = 0; i < this._passengerList.length; i++) {
list += (list === "" ? "" : (i === this._passengerList.length - 1 ? " and " : ", ")) + this._passengerList[i];
player.decreasePassengerReputation();
}
mission.runScreen({
screenID: "oolite-passengers-stranded-map",
title: "Passengers",
message: expandDescription("[passengers-stranded]", {
names: list,
location: system.name
}),
exitScreen: "GUI_SCREEN_STATUS"
});
} else {
// just 1 passenger
player.decreasePassengerReputation();
mission.runScreen({
screenID: "oolite-passenger-stranded-map",
title: "Passengers",
message: expandDescription("[passenger-stranded]", {
name: this._passengerList[0],
location: system.name
}),
exitScreen: "GUI_SCREEN_STATUS"
});
}
this._passengerList.length = 0;
return;
}
// have we been rescued in interstellar space?
if (this._interstellarRecovery === true) {
this._interstellarRecovery = false;
// turn on the interstellar mode
this._interstellarMode = true;
// turn off the standard repurchase screen
this._doRepurchase = false;
var p = player.ship;
var hud = p.hud;
var eq = p.equipment;
// populate the portable list
this._portable.length = 0;
for (var i = 0; i < eq.length; i++) {
var item = eq[i];
if (item.isPortableBetweenShips === true) this._portable.push(item.equipmentKey);
}
this.$rememberPassengers();
// switch to the "loaner"
player.replaceShip(this._interstellarFreeShip.key);
// portable equipment is not automatically transferred if the shipkey changes
this.$addPortable();
p.serviceLevel = 75;
p.hud = hud;
if (p.dockedStation.isPolice) {
mission.runScreen({
screenID: "oolite-naval-recovery-map",
title: "Naval Command",
message: expandDescription("[interstellar_rescue_navy]", {
shiptype: this._interstellarFreeShip.name
}),
exitScreen: "GUI_SCREEN_STATUS"
});
} else {
// a non-police/navy station in interstellar space
mission.runScreen({
screenID: "oolite-interstellar-recovery-map",
title: "Station Control",
message: expandDescription("[interstellar_rescue_normal]", {
shiptype: this._interstellarFreeShip.name
}),
exitScreen: "GUI_SCREEN_STATUS"
});
}
return;
}
// are we doing the repurchase process now?
if (this._doRepurchase === true) {
this._doRepurchase = false;
this.$showRepurchaseScreen();
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = function (station) {
if (this.$simulatorRunning()) {
this._simulator = true;
return;
}
this._simulator = false;
// what's our repurchase percentage? make an initial setting here but we'll recheck before an auto-eject
var p = player.ship;
this._repurchasePercent = 0.1;
if (p.equipmentStatus("EQ_ESCAPE_POD") == "EQUIPMENT_OK") this._repurchasePercent = parseFloat(EquipmentInfo.infoForKey("EQ_ESCAPE_POD").scriptInfo["repurchase_percent"]);
if (p.equipmentStatus("EQ_ESCAPE_POD_PLUS") == "EQUIPMENT_OK") this._repurchasePercent = parseFloat(EquipmentInfo.infoForKey("EQ_ESCAPE_POD_PLUS").scriptInfo["repurchase_percent"]);;
if (worldScripts.ShipConfiguration_Armour) {
this._scTimer = new Timer(this, this.$getSCArmour, 0.5, 0);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$getSCArmour = function $getSCArmour() {
var p = player.ship;
this._holdSCAArmourFrontType = p.script._frontArmourType;
this._holdSCAArmourAftType = p.script._aftArmourType;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
// check if we've been recovered in interstellar space, and if so, turn on the repurchase screen
if (this._interstellarMode === true) {
// in case we have a misjump in interstellar space
if (system.isInterstellarSpace === false) this._doRepurchase = true;
return;
}
// store ship and equipment (but not cargo) in case we need it later
// but only if we're not already in interstellar recovery mode
var shipinfo = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
var data = JSON.parse(shipinfo);
data[8].length = 0; // remove any cargo
data[10].length = 0; // remove any passengers
this._storedShip = JSON.stringify(data);
}
//-------------------------------------------------------------------------------------------------------------
this.$showRepurchaseScreen = function $showRepurchaseScreen() {
// at this point we should have a new ship + equipment (damaged or otherwise) to work with
// calculate cost of replacement ship + equipment
var p = player.ship;
var col1 = 22;
var col2 = 32 - col1;
p.hudHidden = true;
// store the current list of player roles
this._roles = [];
for (var i = 0; i < p.roleWeights.length; i++) {
this._roles.push(p.roleWeights[i]);
}
// check for an interstellar mode recovery
if (system.isInterstellarSpace === false && this._interstellarMode === true && this._storedShip != "") {
var lmss = worldScripts.LMSS_Core;
if (lmss) lmss._switching = true;
// restore the players original ship
worldScripts["Ship_Storage_Helper.js"].restoreStoredShip(this._storedShip);
this._storedShip = "";
if (lmss) lmss._switching = false;
}
// first, repair everything, so the ship price will be accurate
var eq = p.equipment;
this._portable.length = 0;
for (var i = 0; i < eq.length; i++) {
var item = eq[i];
var sts = "";
var count = 0;
var m_sts = p.equipmentStatus(item.equipmentKey, true);
if (m_sts["EQUIPMENT_DAMAGED"] > 0) {
sts = "EQUIPMENT_DAMAGED";
count = m_sts["EQUIPMENT_DAMAGED"];
}
if (sts === "EQUIPMENT_DAMAGED") {
var autoRepair = this._autoRepairMinTL[item.equipmentKey];
if (!autoRepair || parseInt(autoRepair) <= p.dockedStation.equivalentTechLevel) {
for (var j = 1; j <= count; j++) {
p.setEquipmentStatus(item.equipmentKey, "EQUIPMENT_OK");
}
}
}
if (item.isPortableBetweenShips === true) this._portable.push(item.equipmentKey);
}
// repair any ship config armour
if (worldScripts.ShipConfiguration_Armour) {
if (this._holdSCAArmourFrontType != "") {
if (p.equipmentStatus(this._holdSCAArmourFrontType) != "EQUIPMENT_OK") p.awardEquipment(this._holdSCAArmourFrontType);
p.script._armourFront = 100;
}
if (this._holdSCAArmourAftType != "") {
if (p.equipmentStatus(this._holdSCAArmourAftType) != "EQUIPMENT_OK") p.awardEquipment(this._holdSCAArmourAftType);
p.script._armourAft = 100;
}
}
// battle damage OXP
if (worldScripts["Battle Damage"]) {
p.awardEquipment("EQ_HULL_REPAIR");
missionVariables.BattleDamage_status = "OK";
}
// get the cost
this._fullShipCost = p.price;
if (this._overrideBasePrice[p.name]) {
this._baseShipCost = this._overrideBasePrice[p.name];
// if we needed to override the price, we should update the full ship/equipment price as well
var sd = Ship.shipDataForKey(p.dataKey);
if (sd._oo_shipyard) {
var base = sd._oo_shipyard.price;
this._fullShipCost = (this._fullShipCost - base) + this._baseShipCost;
}
} else {
var sd = Ship.shipDataForKey(p.dataKey);
if (sd._oo_shipyard) {
this._baseShipCost = sd._oo_shipyard.price;
} else {
sd = this.$getShipDataEntryWithShipyard(p.name);
if (sd) {
this._baseShipCost = sd._oo_shipyard.price;
} else {
// this should never happen, but, you know...
log(this.name, "!!ERROR: Unable to find valid shipyard price value for shipkey " + p.dataKey);
this._baseShipCost = p.price;
}
}
}
var ins = false;
if (this._repurchasePercent < 0.1) {
if (p.equipmentStatus("EQ_REPURCHASE_INSURANCE") === "EQUIPMENT_OK") ins = true;
}
var repurchase = this._fullShipCost * (this._repurchasePercent * this.$calculatePremium());
if (ins && player.score >= this._jamesonPoint) repurchase = 1000;
if (player.score < this._jamesonPoint) repurchase = 200;
var curChoices = {};
var text = "Current credit balance: " + formatCredits(player.credits, true, true) + "\n\n";
if (this._interstellarMode === false) {
text += "Your ship has been destroyed. ";
} else {
text += "We have received word that your ship was destroyed in interstellar space. ";
}
text += "Please select your preferred ship repurchase option:";
if (this._cargoRecoverySummary != "") {
text += "\n\nNote: All repurchase options include the recovery of " + this._cargoRecoverySummary + " of your cargo.";
}
var label = "Current ship";
if (this._interstellarMode === true) label = "Original ship";
curChoices["01_CURRENT"] = {
text: this.$padTextRight(label + " (" + p.shipClassName + ") with all equipment", col1) +
this.$padTextLeft((repurchase === 0 ? "free" : formatCredits(repurchase, true, true)), col2),
unselectable: (player.credits >= repurchase ? false : true)
};
this._freePick1 = null;
this._freePick2 = null;
var types = Object.keys(this._freeShipTrader);
for (var i = 0; i < types.length; i++) {
if (parseInt(types[i]) < this._baseShipCost && this._freePick1 == null && this._freeShipTrader[types[i]].name != p.shipClassName) {
this._freePick1 = this._freeShipTrader[types[i]];
}
}
// if we didn't get a hit, just choose the lowest value one (Adder)
if (this._freePick1 == null) {
this._freePick1 = this._freeShipTrader[types[types.length - 1]];
} else {
var types = Object.keys(this._freeShipHunter);
for (var i = 0; i < types.length; i++) {
if (parseInt(types[i]) < this._baseShipCost && this._freePick2 == null && this._freeShipHunter[types[i]].name != p.shipClassName) {
this._freePick2 = this._freeShipHunter[types[i]];
}
}
// if they're the same, just show first one
if (this._freePick2 != null && this._freePick2.name == this._freePick1.name) this._freePick2 = null;
}
// if the player is already in an adder, we have to show a free Adder as a replacement
// so don't show a "ship only" repurchase option if we're going to offer a free one anyway
if (p.shipClassName != "Adder") {
var baseRepurchase = this._baseShipCost * (this._repurchasePercent * this.$calculatePremium());
if (ins && player.score >= this._jamesonPoint) baseRepurchase = 500;
if (player.score < this._jamesonPoint) baseRepurchase = 100;
curChoices["01_CURRENT_BASE"] = {
text: this.$padTextRight("Stock model of " + label.toLowerCase() + " (" + p.shipClassName + ")", col1) +
this.$padTextLeft((baseRepurchase === 0 ? "free" : formatCredits(baseRepurchase, true, true)), col2),
unselectable: (player.credits >= baseRepurchase ? false : true)
}
}
// a stock stepdown is always free
curChoices["04_BASE_SHIP"] = {
text: this.$padTextRight("Stock " + this._freePick1.name, col1) +
this.$padTextLeft("free", col2),
unselectable: false
};
if (this._freePick2 != null) {
curChoices["04_BASE_SHIP2"] = {
text: this.$padTextRight("Stock " + this._freePick2.name, col1) +
this.$padTextLeft("free", col2),
unselectable: false
}
}
var opts = {
screenID: "oolite-shiprepurchase-details-map",
title: "Ship Repurchase Options",
overlay: {
name: "shiprepurchase_logo.png",
height: 546
},
allowInterrupt: false,
exitScreen: "GUI_SCREEN_STATUS",
choices: curChoices,
initialChoicesKey: "01_CURRENT",
message: text
};
mission.runScreen(opts, this.$screenHandler, this);
this._interstellarMode = false;
}
//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function $screenHandler(choice) {
var p = player.ship;
var hud = p.hud;
p.hudHidden = false;
var ins = false;
if (this._repurchasePercent < 0.1) {
if (p.equipmentStatus("EQ_REPURCHASE_INSURANCE") === "EQUIPMENT_OK") ins = true;
}
if (choice === "01_CURRENT") {
// nothing to do for this option: current ship and equipment should already be present.
var repurchase = (this._fullShipCost * (this._repurchasePercent * this.$calculatePremium()));
if (ins && player.score >= this._jamesonPoint) {
repurchase = 1000;
p.removeEquipment("EQ_REPURCHASE_INSURANCE");
}
if (player.score < this._jamesonPoint) repurchase = 200;
player.credits -= repurchase;
p.serviceLevel = 95; // replacement ship shouldn't need to be serviced any time soon.
player.consoleMessage(formatCredits(repurchase, true, true) + " has been deducted from your account.");
} else {
// make a note of any passengers who will be getting dumped here.
this.$rememberPassengers();
// remove any secondary lasers
if (worldScripts.LMSS_Core) {
var lmss = worldScripts.LMSS_Core;
if (lmss._forwardAltKey && lmss._forwardAltKey != "EQ_WEAPON_NONE") lmss._forwardAltKey = "EQ_WEAPON_NONE";
if (lmss._aftAltKey && lmss._aftAltKey != "EQ_WEAPON_NONE") lmss._aftAltKey = "EQ_WEAPON_NONE";
if (lmss._portAltKey && lmss._portAltKey != "EQ_WEAPON_NONE") lmss._portAltKey = "EQ_WEAPON_NONE";
if (lmss._starboardAltKey && lmss._starboardAltKey != "EQ_WEAPON_NONE") lmss._starboardAltKey = "EQ_WEAPON_NONE";
}
// do we need to clean up any other 3rd party packs that have data stored in mission or local variables?
// note: some base models come with an escape pod - should we remove it after changing the player ship?
var cost = this._baseShipCost;
if (choice === "01_CURRENT_BASE") {
player.replaceShip(p.dataKey, p.entityPersonality);
var deduct = (cost * (this._repurchasePercent * this.$calculatePremium()));
if (ins && player.score >= this._jamesonPoint) {
deduct = 500;
p.removeEquipment("EQ_REPURCHASE_INSURANCE");
}
if (player.score < this._jamesonPoint) deduct = 100;
player.credits -= deduct;
p.serviceLevel = 95; // replacement ship shouldn't need to be serviced any time soon.
player.consoleMessage(formatCredits(deduct, true, true) + " has been deducted from your account.");
}
if (choice === "04_BASE_SHIP") {
player.replaceShip(this._freePick1.key);
p.serviceLevel = 95; // replacement ship shouldn't need to be serviced any time soon.
// portable equipment is not automatically transferred if the shipkey changes
this.$addPortable();
}
if (choice === "04_BASE_SHIP2") {
player.replaceShip(this._freePick2.key);
p.serviceLevel = 95; // replacement ship shouldn't need to be serviced any time soon.
// portable equipment is not automatically transferred if the shipkey changes
this.$addPortable();
}
p.hud = hud;
}
// restore any recovered cargo
this.$restoreCargo();
// make sure the player has a complimentary fuel load
p.fuel = 7;
// add the date to our array here, so that it's only amended after the replacement is bought
if (player.score >= this._jamesonPoint) this._lastEjectDates.push(this._ejectDate);
// restore the previous list of roles
for (var i = 0; i < p.roleWeights.length; i++) {
if (this._roles.length - 1 >= i) p.setPlayerRole(this._roles[i], i);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$addPortable = function $addPortable() {
if (this._portable.length > 0) {
var p = player.ship;
for (var i = 0; i < this._portable.length; i++) {
p.awardEquipment(this._portable[i]);
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$restoreCargo = function $restoreCargo() {
if (this._cargoRecovery.length > 0) {
var p = player.ship;
var m = p.manifest;
for (var i = 0; i < this._cargoRecovery.length; i++) {
m[this._cargoRecovery[i].commodity] += this._cargoRecovery[i].quantity;
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$calculatePremium = function $calculatePremium() {
if (this._applyPenalty == false) {
return 1;
} else {
// how many times has the player ejected in period?
var period = 365;
// get a period based on the player score.
var keys = Object.keys(this._periodLevels);
for (var i = 0; i < keys.length; i++) {
if (player.score >= parseInt(keys[i])) {
period = parseInt(this._periodLevels[keys[i]]);
}
}
var mth = clock.adjustedSeconds - (86400 * period);
var count = 0;
if (this._lastEjectDates.length > 0) {
for (var i = 0; i > this._lastEjectDates.length; i++) {
if (this._lastEjectDates[i] > mth) count += 1;
}
}
// return a (1.n) value as a multiplier
var result = 1 + ((count * 2) / 10);
return result;
}
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function $padTextRight(currentText, desiredLength, leftSwitch) {
if (currentText == null) currentText = "";
var hairSpace = String.fromCharCode(31);
var ellip = "…";
var currentLength = defaultFont.measureString(currentText.replace(/%%/g, "%"));
var hairSpaceLength = defaultFont.measureString(hairSpace);
// calculate number needed to fill remaining length
var padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
if (padsNeeded < 1) {
// text is too long for column, so start pulling characters off
var tmp = currentText;
do {
tmp = tmp.substring(0, tmp.length - 2) + ellip;
if (tmp === ellip) break;
} while (defaultFont.measureString(tmp.replace(/%%/g, "%")) > desiredLength);
currentLength = defaultFont.measureString(tmp.replace(/%%/g, "%"));
padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
currentText = tmp;
}
// quick way of generating a repeated string of that number
if (!leftSwitch || leftSwitch === false) {
return currentText + new Array(padsNeeded).join(hairSpace);
} else {
return new Array(padsNeeded).join(hairSpace) + currentText;
}
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextLeft = function $padTextLeft(currentText, desiredLength) {
return this.$padTextRight(currentText, desiredLength, true);
}
//-------------------------------------------------------------------------------------------------------------
// routine to check the combat simulator worldscript, to see if it's running or not
this.$simulatorRunning = function $simulatorRunning() {
var w = worldScripts["Combat Simulator"];
if (w && w.$checkFight && w.$checkFight.isRunning) return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$isNavalCarrier = function $isNavalCarrier(e) {
return e.isShip && e.isPolice && e.isStation;
}
//-------------------------------------------------------------------------------------------------------------
this.$isNotNavalCarrier = function $isNotNavalCarrier(e) {
return e.isShip && !e.isPolice && e.isStation && !e.hasRole("generationship") && (e.allegiance == null || e.allegiance != "thargoid");
}
//-------------------------------------------------------------------------------------------------------------
// gets a list of all the current passenger names
this.$rememberPassengers = function $rememberPassengers() {
var p = player.ship;
if (p.passengers.length > 0) {
this._passengerList = [];
for (var i = 0; i < p.passengers.length; i++) {
this._passengerList.push(p.passengers[i].name);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// finds a shipdata entry that has a corresponding shipyard value, so we can get an accurate base ship cost
this.$getShipDataEntryWithShipyard = function $getShipDataEntryWithShipyard(shipName) {
var keys = Ship.keysForRole("player");
for (var i = 0; i < keys.length; i++) {
var sd = Ship.shipDataForKey(keys[i]);
if (sd.name === shipName) {
// did we find a match that has a shipyard entry?
if (sd._oo_shipyard) return sd;
}
}
return null;
} |