Scripts/bountysystem_core.js |
"use strict";
this.name = "BountySystem_Core";
this.author = "phkb";
this.copyright = "2016 phkb";
this.description = "Core routines for New Bounty System.";
this.license = "CC BY-NC-SA 4.0";
/*
What this OXP attempts to do is to keep track of offences committed by the player. Based on the type of offence and where the offence was committed,
different things will occur.
For "severity 1"-classed offences, the bounty will be local systems only. That is, you will only have a bounty within 5LY of the system you committed the crime.
For "severity 2"-classed offences, the bounty is chart-wide. That is, you will have a bounty no matter where you go in the chart, but they don't follow you to a new chart
For "severity 3"-classed offences, the bounty is across all charts.
Severity 1 crimes are invisible in the current system, but can be transferred if within a 5ly radius of the original offence when scanned with warrant scanner
Severity 2 and 3 crimes are invisible in the current system (if they didn't originate there) but will be transferred if you are scanned with the warrant scanner.
You can pay off fines at GalCopHQ or at the system where the crime was committed, but only after a certain time period.
Paying for fines long distance will incur a 10% increase in fine
TODO: check the order in which events fire: does shipAttackedOther occur before the bountyChange event?
If so, we need to check if the player already has a bounty delta in play. If not, we need to skip adding the offence via shipAttackedOther
If not, we need to send a flag to the shipAttacked other
Ideas:
- Statute of limitations on severity 1 crimes: 12 months and then they disappear
- Appeals process? Give player opportunity to appeal a particular offence (eg if the police see you attacking an assassin and decide you must be the offender)
*/
this._disabled = false;
this._debug = false; // turns on/off debug messages in log file
this._severity1Transfer = true; // indicates whether severity 1 crimes can be transferred over distance
this._offences = []; // holds list of all players offences
this._galCopHQ = [7, 33, 26, 49, 102, 85, 202, 184]; // galcop hq locations in each sector
this._galCopHQFineSurcharge = 0.1; // increase to fine amount when paid at GalCop HQ (currently 10%)
this._lastOffenceDate = 0;
this._changing = false; // flag to indicate that a change to the players bounty is happening internally
this._holding = []; // holding array of offences incurred in the current system
this._holdingDate = 0; // date of first offence of the holding array
this._bountyDelta = 0; // how much the bounty has changed while in the current system
this._system = -1; // system ID where offences held in this._holding occurred
this._severity = 1; // how serious were the offences in this._holding
this._escapePod = false; // flag to indicate the player has just used an escape pod
this._displayType = 0; // which screen is currently being displayed
this._page = 0; // which page is currently being displayed
this._selectedItem = 0; // the index of the item selected fine item from the menu
this._selectedGalaxy = 0; // the galaxy number selected from the menu
this._selectedIndex = -1; // the index of the selected most wanted item
this._lastChoice = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]; // array to store last choice on menus
this._routeMode = "SHORTEST"; // default mode for long range chart
this._itemColor = "yellowColor";
this._menuColor = "orangeColor";
this._exitColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._anarchies = false; // flag indicating "Anarchies.OXP" is installed
this._bountyScreen = false; // flag indicating the bounty screen is open
this._holdingItem = {}; // used by the mission screen as the holding spot for offences in the current system
this._markers = [];
this._appeals = [];
this._registrars = ["", "", "", "", "", "", "", ""];
this._appealMessage = "";
this._doAppealScreen = false;
this._secOffClerk = "";
this._warrantScannerMode = 0;
this._alreadyScannedPlayerInThisSystem = false; // do-once-per-system (not cleared when docked, only when jumping out) for importing out-of-system bounties so if player pays off the locals, they don't get a bounty again from a subsequent scan
this._deferredBounties = {
enabled: false,
range: 0,
};
// configuration settings for use in Lib_Config
this._bountySystemConfig = {
Name: this.name,
Alias: "Bounty System",
Display: "Config",
Alive: "_bountySystemConfig",
Notify: "$changeSettings",
Bool: {
B0: { Name: "_severity1Transfer", Def: true, Desc: "Sev 1 bounty transfer" },
B1: { Name: "_deferredBounties.enabled", Def: false, Desc: "Bounty payments deferred" },
Info: "0: When true, severity 1 bounties can be discovered up to 5 LY from point of origin. When false, severity 1 bounties are not transferable;\n" +
"1: Bounty payments are deferred until collected from Sec Offices."
},
SInt: {
S0: { Name: "_warrantScannerMode", Def: 0, Min: 0, Max: 2, Desc: "Warrant scanner mode" },
S1: { Name: "_deferredBounties.range", Def: 0, Min: 0, Max: 3, Desc: "Deferred bounty range" },
Info: "0: Scanner mode - 0 = manual scan, 1 = automatic scan (offenders only), 2 = automatic scan (all ships);\n" +
"1: Bounty collection range - 0 = local system only, 1 = 7LY range, 2 = 25LY range, 3 = Whole chart"
},
};
this._trueValues = ["yes", "1", 1, "true", true];
// list of different offences and details thereof
this._offenceTypes = {
"killed police": {
description: "Murder of GalCop law enforcement officer by means of aggravated use of spacecraft weaponry.",
severity: 3
},
"killed innocent": {
description: "Murder of innocent pilot by means of aggravated use of spacecraft weaponry.",
severity: 3
},
"theft of ship": {
description: "Grand theft of spacecraft within GalCop space.",
severity: 3
},
"attacked police": {
description: "Apprehended violence against GalCop law enforcement officer with spacecraft weaponry.",
severity: 2
},
"attacked main station": {
description: "Apprehended violence against GalCop orbital space station with spacecraft weaponry.",
severity: 2
},
"attacked innocent": {
description: "Apprehended violence against innocent pilot with spacecraft weaponry.",
severity: 2
},
"illegal exports": {
description: "Exportation of illegal commodities for personal gain within GalCop-controlled orbital space stations.",
severity: 1
},
"illegal imports": {
description: "Importation of illegal commodities for personal gain within GalCop-controlled orbital space stations.",
severity: 1
},
"illegal equipment": {
description: "Installation and/or use of illegal and/or unregistered equipment in GalCop-controlled space.",
severity: 1
},
"assisting offenders": {
description: "Aiding and abetting known offenders with use of spacecraft weaponry against innocent third parties.",
severity: 1
},
"attempted bribe": {
description: "Attempting to influence the actions of an official of GalCop by offering money.",
severity: 1
},
"underworld activity": {
description: "Collusion with known underworld entities to deceive and/or defraud GalCop officials in order to bypass GalCop law, for personal gain.",
severity: 1
},
"act of piracy": {
description: "Coercing a non-combatant to relinquish materials for personal gain.",
severity: 1
},
"unspecified_small": {
description: "Unspecified minor offences.",
severity: 1
},
"unspecified_medium": {
description: "Unspecified serious offences.",
severity: 2
},
"unspecified_large": {
description: "Unspecified major offences, warranting use of lethal force.",
severity: 3
},
"unspecified_undefined": {
description: "Unspecified offences.",
severity: 1
},
};
// bountyMin is greater than or equal to
// bountyMax is less than or equal to
// degrade rate is rate in decimal credits fine will degrade per day
// transferLimit controls applicability range of sev 1 crimes (this._severity1Transfer must be true for this to apply)
// payableIn is how many days must pass before fine can be paid
// appeal is whether the crime can be appealed
// appealTime is how many days after the crime can it be appealed
this._severityMatrix = {
1: {
label: "Minor",
bountyMin: 1,
bountyMax: 14,
degradeRate: 0.8,
transferLimit: 5,
payableIn: 1,
appeal: true,
appealTime: 10
},
2: {
label: "Serious",
bountyMin: 15,
bountyMax: 49,
degradeRate: 0.5,
transferLimit: 0,
payableIn: 10,
appeal: true,
appealTime: 5
},
3: {
label: "Major",
bountyMin: 50,
bountyMax: -1,
degradeRate: 0.1,
transferLimit: 0,
payableIn: 30,
appeal: false,
appealTime: 0
}
};
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
if (this._disabled) {
delete this.playerWillSaveGame;
delete this.shipBountyChanged;
delete this.shipLaunchedEscapePod;
delete this.playerBoughtNewShip;
delete this.shipLaunchedFromStation;
delete this.shipWillDockWithStation;
delete this.shipDockedWithStation;
delete this.shipWillEnterWitchspace;
delete this.shipExitedWitchspace;
delete this.shipKilledOther;
delete this.shipAttackedOther;
delete this.shipFiredMissile;
delete this.guiScreenChanged;
delete this.startUpComplete;
delete this.infoSystemChanged;
return;
}
// load up player data
if (missionVariables.BountySystem_Offences) {
this._offences = JSON.parse(missionVariables.BountySystem_Offences);
delete missionVariables.BountySystem_Offences;
}
if (missionVariables.BountySystem_Holding) {
this._holding = JSON.parse(missionVariables.BountySystem_Holding);
delete missionVariables.BountySystem_Holding;
}
if (missionVariables.BountySystem_HoldingDate) {
this._holdingDate = missionVariables.BountySystem_HoldingDate;
delete missionVariables.BountySystem_HoldingDate;
}
if (missionVariables.BountySystem_Severity) {
this._severity = parseInt(missionVariables.BountySystem_Severity);
delete missionVariables.BountySystem_Severity;
}
if (missionVariables.BountySystem_Delta) {
this._bountyDelta = missionVariables.BountySystem_Delta;
delete missionVariables.BountySystem_Delta;
}
if (missionVariables.BountySystem_LastOffenceDate) {
this._lastOffenceDate = missionVariables.BountySystem_LastOffenceDate;
delete missionVariables.BountySystem_LastOffenceDate;
}
if (missionVariables.BountySystem_Appeals) {
this._appeals = JSON.parse(missionVariables.BountySystem_Appeals);
delete missionVariables.BountySystem_Appeals;
}
if (missionVariables.BountySystem_AppealRegistrars) {
this._registrars = JSON.parse(missionVariables.BountySystem_AppealRegistrars);
delete missionVariables.BountySystem_AppealRegistrars;
}
if (missionVariables.BountySystem_DeferredSetup) {
this._deferredBounties = JSON.parse(missionVariables.BountySystem_DeferredSetup);
}
this.$resetBogusData();
this._system = system.ID;
// the Anarchies OXP also plays around with bounty processing. Rather than make that OXP incompatible with this one,
// we're going to override Anarchies and essentially nullify what it does, so that all the bounty processing is contained here.
if (worldScripts.Anarchies) {
this._anarchies = true;
// monkey patch the this.$newBountyCalculation2 function so we can override the calculations and apply our own logic
if (this._debug) log(this.name, "Monkey patching Anarchies...");
var w = worldScripts.Anarchies;
w.$saved_newBountyCalculation2 = w.$newBountyCalculation2;
w.$newBountyCalculation2 = this.$anarchiesBountyCalcOverride;
// we also don't want the anarchies "shipLaunchedEscapePod" routine.
delete w.shipLaunchedEscapePod;
}
// if the player has a bounty we don't know about, add some generic offences to the array
// this would happen the first time the player loads a game after installing the OXP.
if (player.bounty > 0 && this.$calculateBounty(system.ID) === 0) {
this.shipBountyChanged(player.bounty, "scripted");
}
// add a mission screen exception to Xenon UI
if (worldScripts.XenonUI) {
var wx = worldScripts.XenonUI;
wx.$addMissionScreenException("oolite-galcopsecoffice-screen4-map");
wx.$addMissionScreenException("oolite-galcopsecoffice-screen8-map");
wx.$addMissionScreenException("oolite-galcopsecoffice-screen9-map");
}
// add a mission screen exception to Xenon Redux UI
if (worldScripts.XenonReduxUI) {
var wxr = worldScripts.XenonReduxUI;
wxr.$addMissionScreenException("oolite-galcopsecoffice-screen4-map");
wxr.$addMissionScreenException("oolite-galcopsecoffice-screen8-map");
wxr.$addMissionScreenException("oolite-galcopsecoffice-screen9-map");
}
// add screen 9 to the display current course OXP
var dcc = worldScripts.DisplayCurrentCourse;
if (dcc) dcc._screenIDList.push("oolite-galcopsecoffice-screen9-map");
this._suspendedDestination = null;
this.$initInterface(player.ship.dockedStation);
// clear this flag after the game has been loaded and any starting bounty applied
this._changing = false;
if (missionVariables.BountySystem_Sev1Transfer) this._severity1Transfer = (this._trueValues.indexOf(missionVariables.BountySystem_Sev1Transfer) >= 0 ? true : false);
// register our settings, if Lib_Config is present
if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._bountySystemConfig);
if (missionVariables.BountySystem_alreadyScannedPlayerInThisSystem) {
this._alreadyScannedPlayerInThisSystem = missionVariables.BountySystem_alreadyScannedPlayerInThisSystem;
delete missionVariables.BountySystem_alreadyScannedPlayerInThisSystem;
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
if (this._offences.length > 0) {
missionVariables.BountySystem_Offences = JSON.stringify(this._offences);
} else {
delete missionVariables.BountySystem_Offences;
}
if (this._bountyDelta > 0) {
missionVariables.BountySystem_Holding = JSON.stringify(this._holding);
missionVariables.BountySystem_HoldingDate = this._holdingDate;
missionVariables.BountySystem_Severity = this._severity;
missionVariables.BountySystem_Delta = this._bountyDelta;
}
missionVariables.BountySystem_Sev1Transfer = this._severity1Transfer;
if (this._appeals.length > 0) {
missionVariables.BountySystem_Appeals = JSON.stringify(this._appeals);
}
missionVariables.BountySystem_AppealRegistrars = JSON.stringify(this._registrars);
missionVariables.BountySystem_LastOffenceDate = this._lastOffenceDate;
missionVariables.BountySystem_alreadyScannedPlayerInThisSystem = this._alreadyScannedPlayerInThisSystem;
missionVariables.BountySystem_DeferredSetup = JSON.stringify(this._deferredBounties);
}
//-------------------------------------------------------------------------------------------------------------
this.shipBountyChanged = function (delta, reason) {
/*
Because of the way this event fires, there could be lots of messages with a delta of 0.
Rather than try to work out the difference, I'm just adding all offences to a run-sheet, but each different type is only added once.
If the severity of the crimes increases, the overall severity of the run-sheet will also increase.
What this means is that you could have severity 1 crimes listed with severity 3.
*/
// check to see if we're setting the bounty ourselves - in which case skip this process
if (this._changing === true) return;
// otherwise, check the reason for the change
switch (reason) {
case "distress call":
case "setup actions":
case "new system":
case "new galaxy":
return;
case "illegal exports":
case "illegal imports":
case "illegal equipment":
// "illegal exports" events will happen with a delta value of zero, so check first
if (delta > 0) this.$addOffence(reason);
break;
case "killed innocent":
case "killed police":
case "attempted bribe":
case "attacked police":
case "attacked main station":
case "attacked innocent":
case "assisting offenders":
// only add the office if (a) the delta is positive, or (b) we currently have a holding bounty delta that's greater than zero, and we haven't seen this offence yet
if (delta > 0 || (this._bountyDelta > 0 && this._holding.indexOf(reason) === -1)) {
this.$addOffence(reason);
}
break;
// removed the seen by police element, in case a crime is noted (ie delta > 0) with this reason
//case "seen by police":
// for the moment I'm assuming this reason will always be accompanied by another event, so we don't need to record it separately
//break;
default:
// we should get here for "scripted" and any other unrecognised reason
// but we only want to do something if there is a positive delta
if (delta > 0) {
if (this._debug) log(this.name, "adding unspecified for '" + reason + "', delta " + delta);
if (this._offenceTypes[reason]) {
this.$addOffence(reason);
} else {
if (delta >= this._severityMatrix[1].bountyMin && delta <= this._severityMatrix[1].bountyMax) this.$addOffence("unspecified_small");
if (delta >= this._severityMatrix[2].bountyMin && delta <= this._severityMatrix[2].bountyMax) this.$addOffence("unspecified_medium");
if (delta >= this._severityMatrix[3].bountyMin) this.$addOffence("unspecified_large");
}
}
break;
}
if (this._debug) log(this.name, "bounty " + player.bounty + ", change " + delta + ", reason " + reason);
if (delta > 0) this._bountyDelta += delta;
// we're reducing our bounty or we're setting it to zero
if ((delta < 0 && reason !== "escape pod") || (delta === 0 && reason === "scripted")) {
// if the bounty was reset to 0, clear out all bounties - something has reset the players bounty
// if a reason other than "paid fine" has been provided, then it's likely a local bounty issue
// if no reason has been provided, then it's likely an OXP trying to fully clear the player's bounty
if (player.bounty === 0 && this.$calculateBounty(system.ID) != 0 && (reason == "" || reason !== "paid fine")) {
if (this._debug) log(this.name, "full bounty reset occurred");
this._offences.length = 0;
this._holding.length = 0;
this._holdingDate = 0;
this._bountyDelta = 0;
// exit at this point so it doesn't flow into the next sections.
return;
}
// player was marked for fines by a police ship
// note: if the player was scanned and offences were transferred to the current system, and then they were marked for fines
// paying the fine will only remove the transferred fine from the current system - not the original crime. If the player comes back to
// the system again and is scanned again they might have to pay for the fines again.
if (player.bounty === 0 && this.$calculateBounty(system.ID) != 0 && reason === "paid fine") {
if (this._debug) log(this.name, "player paid fine");
// clear out any offences that would apply in the current system
var tfrlist = [];
var found = false;
for (var i = this._offences.length - 1; i >= 0; i--) {
var itm = this._offences[i];
// theoretically, the only time this would happen is for severity 1 offences, but we'll check for the others as well
//if ((itm.severity === 1 && itm.galaxy === galaxyNumber && itm.system === system.ID) || (itm.severity >= 2 && itm.transferred === false)) {
if (itm.galaxy === galaxyNumber && itm.system === system.ID) {
// take a copy of the relevant data for transferred offence removal, but only if this is the original offence
// to catch instances where a bounty has been transferred to another system (not this one), but because we've paid the original, the transferred bounty should also be removed
// that is, if we're deleting the parent offence, all child offences should be removed as well.
if (itm.transferred === false) {
tfrlist.push({
bounty: itm.bounty,
severity: itm.severity,
galaxy: itm.galaxy,
system: itm.system,
systemName: itm.systemName,
government: itm.government,
date: itm.date
});
}
// the item is paid, so we can remove it.
if (itm.transferred === true || (itm.originatingGalaxy === galaxyNumber && itm.originatingSystem === system.ID)) {
this._offences.splice(i, 1);
found = true;
}
}
}
// remove any transferred offences
if (tfrlist.length > 0) {
for (var i = 0; i < tfrlist.length; i++) {
this.$removeTransferredOffences(tfrlist[i]);
}
}
// exit at this point so it doesn't flow into the next sections, but only if we found and removed some bounties from the master list and there's nothing on the current run sheet
if (found === true && this._bountyDelta === 0) return;
// if we didn't find any bounties in the master list, we might be paying a fine for current offences - we deal with that in the next bit
if (this._debug) log(this.name, "fine paid on current run sheet - continuing..." + this._bountyDelta);
}
// we've already recorded some bounty in this system, so reduce it
if (this._bountyDelta > Math.abs(delta)) {
if (this._debug) log(this.name, "adjusting current run sheet");
this._bountyDelta += delta;
// exit at this point so it doesn't flow into the next sections.
return;
}
// the reduction will clear out the current run sheet - remove the data.
if (this._bountyDelta <= Math.abs(delta)) {
if (this._debug) log(this.name, "current run sheet cleared");
delta -= this._bountyDelta;
this._bountyDelta = 0;
this._holding.length = 0;
this._holdingDate = 0;
this._severity = 0;
// exit at this point so it doesn't flow into the next section.
//return;
}
// we have no pending bounties in this system
if (this._bountyDelta === 0 && delta != 0) {
// reduce any recorded bounties for the player, local first
var amount = this.$reduceBounty(Math.abs(delta), 1, system.ID);
if (amount > 0) amount = this.$reduceBounty(amount, 2, system.ID);
if (amount > 0) amount = this.$reduceBounty(amount, 3, system.ID);
this.$cleanUp();
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedEscapePod = function (escapepod) {
this._escapePod = true;
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function (ship, price) {
this._changing = true;
player.bounty = this.$calculateBounty(system.ID);
this._changing = false;
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = function (station) {
delete missionVariables.BountySystem_Offences;
delete missionVariables.BountySystem_Holding;
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
if (this._escapePod === true) {
this._changing = true;
player.bounty += this.$calculateBounty(system.ID); // add instead of setting so other OXPs can update it (currently known: Broadcast Comms restores hidden bounty for players who surrendered to police)
this._changing = false;
this._escapePod = false;
}
if (station.allegiance === "galcop" && this._appeals.length > 0) {
this._appealMessage = "";
for (var i = this._appeals.length - 1; i >= 0; i--) {
var appeal = this._appeals[i];
if (appeal.completedBy < clock.adjustedSeconds) {
var result = "";
if (this._offences.length > 1) result = "other-offences";
if (this._offences.length === 1 && this._offences[0].date == appeal.data.date && this._offences[0].system === appeal.data.system && this._offences[0].severity == 3) result = "severity-3";
if (this._offences.length === 0) result = "already-paid";
if (appeal.data.date - appeal.data.lastOffenceDate < 30) "too-soon";
if (result === "") {
for (var j = 0; j < appeal.roles.length; j++) {
if (appeal.roles[j].indexOf("pirate") >= 0) {
result = "pirate";
break;
}
if (appeal.roles[j].indexOf("assassin") >= 0) {
result = "assassin";
break;
}
}
}
if (result === "") result = "success";
var appeal = expandDescription("[galcop-appealresult-" + result + "]", {
system: appeal.data.systemName,
date: this.$setDateSince(appeal.data.date * 86400)
});
this._appealMessage += (this._appealMessage === "" ? "" : "\n\n") + appeal;
// send an email confirmation
var ga = worldScripts.GalCopAdminServices;
if (ga) {
if (this._registrars[galaxyNumber] === "") this._registrars[galaxyNumber] = expandDescription("%N [nom]");
var msg = expandDescription("[galcop-appealresult-email]", {
result: appeal,
sender: this._registrars[galaxyNumber]
});
var w = worldScripts.EmailSystem;
w.$createEmail({
sender: "Appeals Registrar",
subject: "Appeal Result",
date: global.clock.adjustedSeconds,
sentFrom: this._galCopHQ[galaxyNumber],
message: msg,
expiryDays: ga._defaultExpiryDays
});
}
// if the appeal was successful, remove the offence
if (result === "success") {
for (var j = this._offences.length - 1; j >= 0; j--) {
var itm = this._offences[j];
if (itm.galaxy === galaxyNumber && itm.system === appeal.data.system && itm.date === appeal.data.date) {
// we want to remove all instances of this bounty, regardless of whether it's transferred or not.
this._offences.splice(j, 1);
}
}
}
// we'll remove this appeal now that it's been finished
this._appeals.splice(i, 1);
}
}
if (this._appealMessage !== "") this._doAppealScreen = true;
}
}
//-------------------------------------------------------------------------------------------------------------
this.missionScreenOpportunity = function () {
if (this._doAppealScreen === true) {
this._doAppealScreen = false;
mission.runScreen({
screenID: "oolite-bountysystem-appeal-map",
title: "Appeal Submission Response",
overlay: {
name: "galcop_logo.png",
height: 546
},
message: this._appealMessage,
exitScreen: "GUI_SCREEN_STATUS"
});
this._appealMessage = "";
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
this.$initInterface(station);
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function (cause, destination) {
this._secOffClerk = "";
// push data into the array, but only if there is a bounty delta
if (this._bountyDelta != 0 && system.ID >= 0) {
// for case where we are about to add an offence but no description has been added
if (this._holding.length === 0) {
if (this._bountyDelta >= this._severityMatrix[1].bountyMin && this._bountyDelta <= this._severityMatrix[1].bountyMax) this.$addOffence("unspecified_small");
if (this._bountyDelta >= this._severityMatrix[2].bountyMin && this._bountyDelta <= this._severityMatrix[2].bountyMax) this.$addOffence("unspecified_medium");
if (this._bountyDelta >= this._severityMatrix[3].bountyMin) this.$addOffence("unspecified_large");
}
this._offences.push({
offenceList: JSON.stringify(this._holding),
bounty: this._bountyDelta,
severity: this._severity,
galaxy: galaxyNumber,
system: this._system,
systemName: System.infoForSystem(galaxyNumber, this._system).name,
government: System.infoForSystem(galaxyNumber, this._system).government,
date: this._holdingDate, //global.clock.days,
transferred: false,
originatingSystem: this._system,
originatingGalaxy: galaxyNumber,
priorOffenceDate: this._lastOffenceDate
});
this._lastOffenceDate = this._holdingDate;
}
// clean up for next system
this._holding.length = 0;
this._holdingDate = 0;
this._bountyDelta = 0;
this._severity = 0;
this._alreadyScannedPlayerInThisSystem = false;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
this.$resetBogusData();
// calculate the player's bounty in this system
this._changing = true;
player.bounty = this.$calculateBounty(system.ID);
this._changing = false;
this._system = system.ID;
}
//-------------------------------------------------------------------------------------------------------------
this.shipKilledOther = function (whom, damageType) {
this.$targetAttacked(whom, damageType, true);
}
//-------------------------------------------------------------------------------------------------------------
this.shipAttackedOther = function (whom) {
// only send the targetAttacked message if the player has a current bounty delta
if (this._bountyDelta > 0) this.$targetAttacked(whom, "energy damage", false);
}
//-------------------------------------------------------------------------------------------------------------
this.shipFiredMissile = function (missile, whom) {
this.$targetAttacked(whom, "energy damage", false);
}
//-------------------------------------------------------------------------------------------------------------
// processes all the variations on attacking and killing other ships
this.$targetAttacked = function (whom, damageType, killed) {
// don't record anything if this is a simulator run
if (this.$simulatorRunning()) return;
var msgType = "attacked";
if (killed) msgType = "killed";
// player shot and killed other with lasers, q-bomb, or by ramming them
if (whom.isPiloted && !whom.isDerelict && !whom.isThargoid) {
if (damageType === "energy damage" || damageType === "cascade weapon" || damageType === "scrape damage") {
// who did we just kill?
if (whom.isPolice) {
this.$addOffence(msgType + " police");
} else {
// is there a police ship/station in range
// (check the holding array first though, so we can avoid doing "findLawVessels" with every laser shot)
if (whom.bounty === 0 && this._holding.indexOf(msgType + "innocent") === -1) {
var police = this.$findLawVessels(player.ship);
if (police.length > 0) this.$addOffence(msgType + " innocent");
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
if (to === "GUI_SCREEN_SYSTEM_DATA" && from != "GUI_SCREEN_SYSTEM_DATA") this.$updateSystemInfo();
if (from === "GUI_SCREEN_MISSION" && this._bountyScreen) {
this._bountyScreen = false;
if (this._hudHidden === false && player.ship.hudHidden === true) player.ship.hudHidden = this._hudHidden;
if (this._suspendedDestination) player.ship.targetSystem = this._suspendedDestination;
this._suspendedDestination = null;
// clean up all the marks on the chart
this.$removeChartData();
}
}
//-------------------------------------------------------------------------------------------------------------
this.infoSystemChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA") this.$updateSystemInfo();
}
//--------------------------------------------------------------------------------------------------------------
this.$updateSystemInfo = function () {
var sysID = player.ship.targetSystem;
if (player.ship.hasOwnProperty("infoSystem")) sysID = player.ship.infoSystem;
var bounty = this.$calculateBounty(sysID);
var criminal = this.$playerIsCriminal(sysID);
if (bounty > 0 && bounty < 50) mission.addMessageText("This system considers you " + (criminal === true ? "a criminal" : "an") + " offender.");
if (bounty > 50) mission.addMessageText("This system considers you " + (criminal === true ? "a criminal" : "a") + " fugitive.");
}
//-------------------------------------------------------------------------------------------------------------
this.$initInterface = function (station) {
if (station.allegiance === "galcop") {
station.setInterface(this.name, {
title: (station.isMainStation ? "GalCop Security Office" : "GalCop Security Kiosk"),
category: "Station Interfaces",
summary: "Accesses the GalCop security office services at this station.",
callback: this.$startSecOfficeScreen.bind(this)
});
} else {
station.setInterface(this.name, null);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$startSecOfficeScreen = function () {
this._lastChoice = ["", "", "", "", "", "", "", "", "", "", ""];
this._displayType = 0;
this._page = 0;
this.$showSecOffice();
}
//-------------------------------------------------------------------------------------------------------------
this.$showSecOffice = function () {
function compare(a, b) {
if (a.date < b.date) return -1;
if (a.date > b.date) return 1;
return 0;
}
function compareBounty(a, b) {
return (b.bounty - a.bounty);
}
function compareDateDesc(a, b) {
if (a.createdDate > b.createdDate) return -1;
if (a.createdDate < b.createdDate) return 1;
return 0;
}
var p = player.ship;
var text = "";
var opts;
var curChoices = {};
var def = "";
var rows = 21;
this._hudHidden = p.hudHidden;
if (this.$isBigGuiActive() === false) p.hudHidden = true;
this._bountyScreen = true;
var jmpIndent = 6.45;
var govs = new Array();
for (var i = 0; i < 8; i++)
govs.push(String.fromCharCode(i));
var spc = String.fromCharCode(31);
if (this._displayType === 0) {
text = expandDescription("[galcop-office-welcome]", {
officetype: (system.ID === this._galCopHQ[galaxyNumber] ? "HQ" : "Local")
});
var itemcount = 2;
curChoices["01_VIEWSTD"] = {
text: "[galcop-local-fines]",
color: this._menuColor
};
curChoices["02_VIEWINTER"] = {
text: "[galcop-inter-fines]",
color: this._menuColor
};
if (this._deferredBounties.enabled) {
curChoices["03_PAYMENTS"] = {
text: "[galcop-payments]",
color: this._menuColor
};
itemcount += 1;
}
if (worldScripts.BountySystem_MostWanted) {
curChoices["03_WANTED"] = {
text: "[galcop-mostwanted]",
color: this._menuColor
};
itemcount += 1;
if (p.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
curChoices["09_BOUNTY_TIPS"] = {
text: "[galcop-mostwanted-tips]",
color: this._menuColor
};
itemcount += 1;
}
if (worldScripts.BountySystem_MostWanted._completed.length > 0) {
curChoices["03_WANTED_BONUS"] = {
text: "[galcop-mostwanted-bonus-menu]",
color: this._menuColor
};
itemcount += 1;
}
}
if (system.ID != this._galCopHQ[galaxyNumber]) {
curChoices["04_GALCOPHQ"] = {
text: "[galcop-hq]",
color: this._menuColor
};
itemcount += 1;
}
curChoices["99_EXIT"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var def = "99_EXIT";
for (var i = 0; i < (rows - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
var opts = {
screenID: "oolite-galcopsecoffice-screen0-map",
title: "GalCop " + (system.ID === this._galCopHQ[galaxyNumber] ? "HQ" : "Local") + " Security Office",
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
overlay: {
name: "galcop_logo.png",
height: 546
},
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 1) { // outstanding fines
text = this.$padTextRight(expandDescription("[galcop-fine-hdr-system]"), 6) +
this.$padTextRight(expandDescription("[galcop-fine-hdr-date]"), 6) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-incidents]"), 5) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-bounty]"), 4) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-fine]"), 5) + " " + expandDescription("[galcop-fine-hdr-payable]");
var list = [];
for (var i = 0; i < this._offences.length; i++) {
var offence = this._offences[i];
if (offence.transferred === false && offence.galaxy === galaxyNumber) {
if (this.$calculateItemBounty(offence, offence.system) > 0) {
var subitems = JSON.parse(offence.offenceList);
var days = 0;
if (this.$itemIsPayable(offence) === false) days = this.$daysUntilPayable(offence);
var st = this.$setDateSince(parseFloat(offence.date) * 86400);
list.push({
text: this.$padTextRight(offence.systemName, 6) +
this.$padTextRight(st, 6) + // offence.date
this.$padTextLeft(subitems.length, 5) +
this.$padTextLeft(formatCredits(this.$calculateItemBounty(offence, offence.system), false, true), 4) +
(this.$itemIsPayable(offence) ? this.$padTextLeft(formatCredits(this.$calculateFine(offence), false, true), 5) : this.$padTextLeft(" ", 5)) +
(days === 0 ? " Yes" : " " + days + " day" + (days > 1 ? "s" : "")),
date: offence.date,
index: i
});
}
}
}
// add in any active offences that haven't been added to the main offence list
if (this._holding.length > 0) {
this._holdingItem = {
offenceList: JSON.stringify(this._holding),
bounty: this._bountyDelta,
severity: this._severity,
galaxy: galaxyNumber,
system: system.ID,
systemName: system.name,
government: system.info.government,
date: this._holdingDate, //global.clock.days,
transferred: false
};
list.push({
text: this.$padTextRight(this._holdingItem.systemName, 6) +
this.$padTextRight(this.$setDateSince(this._holdingItem.date * 86400), 6) + // this._holdingItem.date
this.$padTextLeft(this._holding.length, 5) +
this.$padTextLeft(formatCredits(this._bountyDelta, false, true), 4) +
this.$padTextLeft(" ", 5) +
" ",
date: global.clock.days,
index: 9999
});
}
def = "98_CLOSE";
if (list.length > 0) {
list.sort(compare);
var maxpage = Math.ceil(list.length / (rows + 1));
var end = ((this._page * (rows + 1)) + (rows + 1));
var itemcount = 0;
if (end > list.length) end = list.length;
for (var i = (this._page * (rows + 1)); i < end; i++) {
curChoices["01_FINE-" + (i < 10 ? "0" : "") + i + "~" + list[i].index] = {
text: list[i].text,
alignment: "LEFT",
color: this._itemColor
};
itemcount += 1;
}
curChoices["94_SPACER"] = "";
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
for (var i = 0; i < (rows - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
//if (this._lastChoice != "") def = this._lastChoice;
} else {
text = expandDescription("[galcop-no-warrants]");
}
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen1-map",
title: "Outstanding Fines",
overlay: {
name: "bounty-gavel.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 2) { // outstanding intergalactic fines
// for this we summarise all the bounties from other sectors
var hq = System.infoForSystem(galaxyNumber, this._galCopHQ[galaxyNumber]);
var itemcount = 0;
for (var i = 0; i <= 7; i++) {
if (i != galaxyNumber) {
var bounty = this.$calculateIntergalacticBounty(i);
if (bounty > 0) {
var fineamt = 0;
for (var j = 0; j < this._offences.length; j++) {
if (this._offences[i].transferred === false && this._offences[j].galaxy === i && this.$itemIsPayable(this._offences[j]) === true) fineamt += this.$calculateFine(this._offences[j]);
}
curChoices["05_GAL~" + i] = {
text: this.$padTextRight("Sector " + (i + 1), 10) + this.$padTextLeft(formatCredits(bounty, false, true), 10) + this.$padTextLeft(formatCredits(fineamt, false, true), 10),
alignment: "LEFT",
color: this._itemColor
};
itemcount += 1;
}
}
}
if (itemcount > 0) {
text = this.$padTextRight(expandDescription("[galcop-sector]"), 10) + this.$padTextLeft(expandDescription("[galcop-bounty]"), 10) + this.$padTextLeft(expandDescription("[galcop-payable]"), 10) + "\n";
curChoices["06_SPACER"] = "";
for (var i = 0; i < ((rows + 2) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
} else {
text = expandDescription("[galcop-no-inter-warrants]");
}
def = "98_CLOSE";
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen2-map",
title: "Outstanding Intergalactic Fines",
overlay: {
name: "bounty-gavel.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 14) { // outstanding bounty claims (normal)
var df = worldScripts.BountySystem_Deferred;
var subList = df.$checkScope();
var lines = [];
var total = 0;
if (subList.length == 0) {
text += "You have no bounty claims outstanding.";
} else {
text += this.$padTextRight("System", 7) + this.$padTextRight("Ship", 17) + this.$padTextLeft("Payment", 7) + "\n\n";
for (var i = 0; i < subList.length; i++) {
var item = subList[i].split(" ");
var shps = df._deferred[subList[i]];
for (var j = 0; j < shps.length; j++) {
var sys = System.infoForSystem(parseInt(item[0]), parseInt(item[1]));
lines.push(this.$padTextRight(sys.name, 7) + this.$padTextRight(shps[j].ship, 17) + this.$padTextLeft(formatCredits(shps[j].credits, false, true), 7));
total += shps[j].credits;
}
}
if (lines.length > 0) {
var maxpage = Math.ceil(lines.length / (rows + 1));
var end = ((this._page * (rows + 1)) + (rows + 1));
var itemcount = 0;
if (end > lines.length) end = lines.length;
for (var i = (this._page * (rows + 1)); i < end; i++) {
text += lines[i] + "\n";
itemcount += 1;
}
curChoices["94_SPACER"] = "";
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
curChoices["97A_CLAIM"] = {
text: expandDescription("[galcop-bounty-claim]", {
amount: formatCredits(total, true, true),
score: score
}),
color: this._menuColor
};
}
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "98_CLOSE";
var opts = {
screenID: "oolite-galcopsecoffice-screen14-map",
title: "Bounty Claim Receipts",
overlay: {
name: "galcop_logo.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 3) { // most wanted list
// pilot name, bounty, last seen, updated
text = this.$padTextRight(expandDescription("[galcop-mostwanted-hdr-pilot]"), 10) +
this.$padTextRight(expandDescription("[galcop-mostwanted-hdr-lastseen]"), 10) +
this.$padTextRight(expandDescription("[galcop-mostwanted-hdr-updated]"), 7.25) +
this.$padTextLeft(expandDescription("[galcop-mostwanted-hdr-bounty]"), 4.5);
var list = [];
var mw = worldScripts.BountySystem_MostWanted;
if (mw._constantUpdates == true) mw.$updateDisplayList();
var dl = mw._displayList;
for (var i = 0; i < dl.length; i++) {
if (dl[i].lastVisibleSystem != -1) {
list.push({
pilotName: dl[i].pilotName,
bounty: dl[i].bounty,
lastSeen: System.systemNameForID(dl[i].lastVisibleSystem),
lastVisibleSystem: dl[i].lastVisibleSystem,
updated: dl[i].updated,
index: i,
ref: dl[i].index
});
} else {
list.push({
pilotName: dl[i].pilotName,
bounty: dl[i].bounty,
lastSeen: "--unknown--",
lastVisibleSystem: -1,
updated: "",
index: i,
ref: dl[i].index
});
}
}
def = "98_CLOSE";
if (list.length > 0) {
list.sort(compareBounty);
var maxpage = Math.ceil(list.length / rows);
var end = ((this._page * rows) + rows);
var itemcount = 0;
if (end > list.length) end = list.length;
for (var i = (this._page * rows); i < end; i++) {
var lastseen = "";
var updated = "";
if (list[i].lastVisibleSystem >= 0) {
var info = System.infoForSystem(galaxyNumber, list[i].lastVisibleSystem);
var rt = system.info.routeToSystem(info);
if (rt) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(info);
}
lastseen = list[i].lastSeen + " (" + govs[info.government] + spc + dist.toFixed(1) + "ly)";
updated = this.$adjustTime(clock.clockStringForTime(list[i].updated));
} else {
lastseen = "--unknown--";
updated = "";
}
curChoices["50_MOSTWANTED-" + (i < 10 ? "0" : "") + i + "~" + list[i].index] = {
text: this.$padTextRight((mw._missionList.indexOf(list[i].ref) >= 0 ? "• " : "") + list[i].pilotName, 10) +
this.$padTextRight(lastseen, 10) +
this.$padTextRight(updated, 7.25) +
this.$padTextLeft(formatCredits(list[i].bounty, false, true), 4.5),
alignment: "LEFT",
color: this._itemColor
};
itemcount += 1;
}
curChoices["94_SPACER"] = "";
for (var i = 0; i < (rows - itemcount); i++) {
curChoices["94_SPACER_" + i] = "";
}
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
def = "98_CLOSE";
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen3-map",
title: "GalCop Most Wanted" + (maxpage > 1 ? ": Page " + (this._page + 1) + " of " + maxpage : ""),
overlay: {
name: "mw_badge.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 4) { // galcop hq location
// hold the player's destination
var rtCurr = system.info.routeToSystem(System.infoForSystem(galaxyNumber, p.targetSystem));
this._suspendedDestination = p.targetSystem;
// override it for the display
p.targetSystem = this._galCopHQ[galaxyNumber];
var bg = "LONG_RANGE_CHART";
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
if (this._galCopHQ[galaxyNumber] != system.ID) {
var rt = system.info.routeToSystem(System.infoForSystem(galaxyNumber, this._galCopHQ[galaxyNumber]), (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt && rt.route.length > 1) {
text = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + this.$padTextRight("", jmpIndent) + expandDescription("[galcop-jumps]") + " " + (rt.route.length - 1);
}
}
if (this._routeMode === "SHORTEST") {
bg += "_SHORTEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._disabledColor,
unselectable: true
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._menuColor
};
} else {
bg += "_QUICKEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._menuColor
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._disabledColor,
unselectable: true
};
}
}
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && (!rtCurr || rtCurr.route.indexOf(p.targetSystem) === -1)) {
curChoices["96_SETCOURSE~" + p.targetSystem] = {
text: expandDescription("[galcop-set-course]", {
destination: System.systemNameForID(p.targetSystem)
}),
color: this._menuColor
};
}
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "98_CLOSE";
var opts = {
screenID: "oolite-galcopsecoffice-screen4-map",
title: "GalCop HQ in Sector " + (galaxyNumber + 1),
backgroundSpecial: bg,
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 5) { // fine detail
if (this._selectedItem === 9999) {
var itm = this._holdingItem;
} else {
var itm = this._offences[this._selectedItem];
}
var subitems = JSON.parse(itm.offenceList);
var tl = 0;
if (itm.galaxy === galaxyNumber) {
var info = System.infoForSystem(galaxyNumber, itm.system);
tl = info.techlevel + 1;
} else {
var info = null;
}
var hq = System.infoForSystem(galaxyNumber, this._galCopHQ[galaxyNumber]);
text = this.$padTextRight(expandDescription("[galcop-offence-system]"), 10) + itm.systemName + " (" + govs[itm.government] + spc + (itm.galaxy != galaxyNumber ? "G" + (itm.galaxy + 1) + ")" : "TL" + tl + ")") + "\n";
text += this.$padTextRight(expandDescription("[galcop-offence-date]"), 10) + this.$setDateSince(itm.date * 86400) + "\n";
text += this.$padTextRight(expandDescription("[galcop-offence-severity]"), 10) + itm.severity + " (" + this._severityMatrix[itm.severity].label + ")\n";
var bounty = 0;
if (itm.galaxy != galaxyNumber) {
bounty = this.$calculateIntergalacticItemBounty(itm);
} else {
bounty = this.$calculateItemBounty(itm, itm.system);
}
text += this.$padTextRight(expandDescription("[galcop-offence-bounty]"), 10) + formatCredits(bounty, false, true) + "\n";
var linecount = 0;
if (this.$itemAlreadyTransferred(itm) === true) {
text += this.$padTextRight(expandDescription("[galcop-offence-applied]"), 10) + "Yes\n";
linecount += 1;
}
if (itm.system != system.ID) linecount += 1;
for (var i = 0; i < subitems.length; i++) {
if (this._offenceTypes[subitems[i]]) {
var textItems = "- " + this._offenceTypes[subitems[i]].description;
} else {
var textItems = "- " + this._offenceTypes["unspecified_undefined"].description;
}
var colItems = this.$columnText(textItems, 21);
for (var j = 0; j < colItems.length; j++) {
if (i === 0 && j === 0) {
text += this.$padTextRight(expandDescription("[galcop-offence-charges]"), 10);
} else {
text += this.$padTextRight(" ", 10);
}
text += colItems[j] + "\n";
linecount += 1;
if (linecount >= rows - 1) {
text += this.$padTextRight(" ", 10) + "<< list overflow >>\n";
break;
}
}
if (linecount >= rows - 1) break;
}
if (itm.system != system.ID) {
curChoices["53_VIEWCHART"] = {
text: "[galcop-view-course]",
color: this._menuColor
};
}
if (this.$itemIsPayable(itm) === false || this._selectedItem === 9999) {
var days_until = this.$daysUntilPayable(itm);
if (this._selectedItem === 9999) {
text += this.$padTextRight(expandDescription("[galcop-offence-days]"), 10) + days_until + " day" + (days_until === 1 ? "" : "s") + " after leaving system\n";
} else {
text += this.$padTextRight(expandDescription("[galcop-offence-days]"), 10) + days_until + " day" + (days_until === 1 ? "" : "s") + "\n";
}
curChoices["90_PAYFINE"] = {
text: expandDescription("[galcop-payfine]", {
fine: "(not available)"
}),
color: this._disabledColor,
unselectable: true
};
} else {
text += this.$padTextRight(expandDescription("[galcop-offence-fine]"), 10) + formatCredits(this.$calculateFine(itm), false, true);
if (system.ID === this._galCopHQ[galaxyNumber] || (itm.galaxy === galaxyNumber && system.ID === itm.system)) {
curChoices["90_PAYFINE"] = {
text: expandDescription("[galcop-payfine]", {
fine: "(" + formatCredits(this.$calculateFine(itm) * (itm.system != system.ID ? (1 + this._galCopHQFineSurcharge) : 1), true, true) + ")"
}) + (p.dockedStation.isMainStation ? "" : " (only at main station)"),
unselectable: (p.dockedStation.isMainStation ? false : true),
color: this._menuColor
};
} else {
var hqJumps = 0;
// calc distance to HQ
var rt1 = system.info.routeToSystem(hq, (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt1 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
var dist1 = rt1.distance;
hqJumps = rt1.route.length - 1;
} else {
var dist1 = system.info.distanceToSystem(hq);
}
var offJumps = 0;
// calc distance to offence planet (if available)
if (info) {
var rt2 = system.info.routeToSystem(info, (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt2 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
var dist2 = rt2.distance;
offJumps = rt2.route.length - 1;
} else {
var dist2 = system.info.distanceToSystem(info);
}
}
if (itm.galaxy === galaxyNumber) {
if (itm.system != this._galCopHQ[galaxyNumber]) {
text += expandDescription("[galcop-offence-payable-at-both]", {
destination: info.name
});
var warn = expandDescription("[galcop-offence-hq-warning]");
if (defaultFont.measureString(warn) > 21) {
var warnItems = this.$columnText(warn, 21);
for (var i = 0; i < warnItems.length; i++) {
text += "\n" + this.$padTextRight(" ", 10) + warnItems[i];
}
} else {
text += "\n" + this.$padTextRight(" ", 10) + warn;
}
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && this.$systemInCurrentPlot(this._galCopHQ[galaxyNumber]) === false) {
curChoices["96_SETCOURSE~" + this._galCopHQ[galaxyNumber]] = {
text: expandDescription("[galcop-hq-set-course-dist]", {
distance: dist1.toFixed(1),
jumps: (hqJumps > 0 ? ", " + hqJumps + " jump" + (hqJumps > 1 ? "s" : "") : "")
}),
color: this._menuColor
};
}
} else {
text += expandDescription("[galcop-offence-payable-at-local]", {
destination: info.name
});
}
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && this.$systemInCurrentPlot(itm.system) === false) {
curChoices["96_SETCOURSE~" + itm.system] = {
text: expandDescription("[galcop-set-course-dist]", {
destination: info.name,
distance: dist2.toFixed(1),
jumps: (offJumps > 0 ? ", " + offJumps + " jump" + (offJumps > 1 ? "s" : "") : "")
}),
color: this._menuColor
};
}
} else {
text += " (payable at GalCop HQ)";
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && this.$systemInCurrentPlot(this._galCopHQ[galaxyNumber]) === false) {
curChoices["96_SETCOURSE~" + this._galCopHQ[galaxyNumber]] = {
text: expandDescription("[galcop-hq-set-course-dist]", {
distance: dist1.toFixed(1),
jumps: (hqJumps > 0 ? ", " + hqJumps + " jump" + (hqJumps > 1 ? "s" : "") : "")
}),
color: this._menuColor
};
}
}
}
text += "\n";
}
// if we're at a main station, we can offer an appeal process
if (player.ship.dockedStation && player.ship.dockedStation.isMainStation) {
if (this._selectedItem !== 9999 &&
(itm.hasOwnProperty("lastOffenceDate") === false || (clock.days - itm.date) <= this._severityMatrix[itm.severity].appealTime) &&
this.$checkAppealStatus(itm) === "none" &&
this._severityMatrix[itm.severity].appeal === true) {
curChoices["97_APPEAL"] = {
text: "[galcop-submit-appeal]",
color: this._menuColor
};
}
if (this.$checkAppealStatus(itm) === "in progress") {
curChoices["97_APPEAL"] = {
text: "[galcop-appeal-inprogress]",
color: this._disabledColor,
unselectable: true
};
}
}
if (itm.galaxy === galaxyNumber) {
curChoices["97_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "97_CLOSE";
} else {
curChoices["97A_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "97A_CLOSE";
}
var opts = {
screenID: "oolite-galcopsecoffice-screen5-map",
title: "Outstanding Fine",
overlay: {
name: "bounty-gavel.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 6) { // outstanding intergalactic fines
text = this.$padTextRight(expandDescription("[galcop-fine-hdr-system]"), 6) +
this.$padTextRight(expandDescription("[galcop-fine-hdr-date]"), 6) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-incidents]"), 5) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-bounty]"), 4) +
this.$padTextLeft(expandDescription("[galcop-fine-hdr-fine]"), 5) + " " + expandDescription("[galcop-fine-hdr-payable]");
var list = [];
for (var i = 0; i < this._offences.length; i++) {
if (this._offences[i].transferred === false && this._offences[i].galaxy === this._selectedGalaxy) {
if (this.$calculateIntergalacticItemBounty(this._offences[i]) > 0) {
var subitems = JSON.parse(this._offences[i].offenceList);
list.push({
text: this.$padTextRight(this._offences[i].systemName, 6) +
this.$padTextRight(this.$setDateSince(this._offences[i].date * 86400), 6) +
this.$padTextLeft(subitems.length, 5) +
this.$padTextLeft(formatCredits(this.$calculateIntergalacticItemBounty(this._offences[i]), false, true), 4) +
(this.$itemIsPayable(this._offences[i]) ? this.$padTextLeft(formatCredits(this.$calculateFine(this._offences[i]), false, true), 5) : this.$padTextLeft(" ", 5)) +
(this.$itemIsPayable(this._offences[i]) ? " Yes" : " " + this.$daysUntilPayable(this._offences[i]) + " days"),
date: this._offences[i].date,
index: i
});
}
}
}
def = "97B_CLOSE";
if (list.length > 0) {
list.sort(compare);
var maxpage = Math.ceil(list.length / (rows + 1));
var end = ((this._page * (rows + 1)) + (rows + 1));
var itemcount = 0;
if (end > list.length) end = list.length;
for (var i = (this._page * (rows + 1)); i < end; i++) {
curChoices["01_FINE-" + (i < 10 ? "0" : "") + i + "~" + list[i].index] = {
text: list[i].text,
alignment: "LEFT",
color: this._itemColor
};
itemcount += 1;
}
curChoices["94_SPACER"] = "";
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
for (var i = 0; i < ((rows) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
if (this._lastChoice != "") def = this._lastChoice;
} else {
text = expandDescription("[galcop-no-warrants]");
}
curChoices["97B_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen6-map",
title: "Outstanding Fines in Sector " + (this._selectedGalaxy + 1),
overlay: {
name: "bounty-gavel.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 7) { // most wanted detail
var mw = worldScripts.BountySystem_MostWanted;
var dl = mw._displayList;
var itm = dl[this._selectedIndex];
text = this.$padTextRight(expandDescription("[galcop-mostwanted-pilot]"), 10);
var colText = this.$columnText("Cmdr. " + itm.pilotName + ", " + itm.pilotDescription, 21);
for (var i = 0; i < colText.length; i++) {
if (i != 0) text += this.$padTextRight("", 10);
text += colText[i] + "\n";
}
text += this.$padTextRight(expandDescription("[galcop-mostwanted-shiptype]"), 10) + itm.shipType + "\n";
text += this.$padTextRight(expandDescription("[galcop-mostwanted-shipname]"), 10) + itm.shipName + "\n";
text += this.$padTextRight(expandDescription("[galcop-mostwanted-bounty]"), 10) + formatCredits(itm.bounty, false, true) + "\n\n";
if (itm.lastVisibleSystem >= 0) {
var jmps = 0;
var info = System.infoForSystem(galaxyNumber, itm.lastVisibleSystem);
var rt = system.info.routeToSystem(info, (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
var dist = rt.distance;
jmps = rt.route.length - 1;
} else {
var dist = system.info.distanceToSystem(info);
}
var jmps2 = 0;
var info2 = System.infoForSystem(galaxyNumber, itm.lastVisibleDestination);
var rt2 = system.info.routeToSystem(info2, (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt2 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
var dist2 = rt2.distance;
jmps2 = rt2.route.length - 1;
} else {
var dist2 = system.info.distanceToSystem(info2);
}
var rt3 = info.routeToSystem(info2, (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
text += this.$padTextRight(expandDescription("[galcop-mostwanted-lastseen]"), 10) +
System.systemNameForID(itm.lastVisibleSystem) + " (" + govs[info.government] + spc +
"TL" + (info.techlevel + 1) + ", " + dist.toFixed(1) + "ly" + (jmps > 0 ? ", " + jmps + " jump" + (jmps > 1 ? "s" : "") : "") +
(rt && jmps > 0 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") ? ", " + rt.time.toFixed(1) + " hrs" : "") +
")\n";
var upd = this.$getTimeSince(itm.updated, false);
//log(this.name, "check time " + itm.updated + " -- " + clock.clockStringForTime(itm.updated));
text += this.$padTextRight(expandDescription("[galcop-mostwanted-updated]"), 10) + this.$adjustTime(clock.clockStringForTime(itm.updated)) +
" (" + (upd !== "" ? upd + " ago" : "just now") + ")\n";
if (player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK" && itm.departureTime < clock.adjustedSeconds) {
var arr = itm.departureTime + (rt3.time * 3600);
text += this.$padTextRight(expandDescription("[galcop-mostwanted-lastseendest]"), 10) +
System.systemNameForID(itm.lastVisibleDestination) + " (" + govs[info2.government] + spc +
"TL" + (info2.techlevel + 1) + ", " + dist2.toFixed(1) + "ly" + (jmps2 > 0 ? ", " + jmps2 + " jump" + (jmps2 > 1 ? "s" : "") : "") +
(rt2 && jmps2 > 0 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") ? ", " + rt2.time.toFixed(1) + " hrs" : "") +
")\n";
if (rt3) {
text += this.$padTextRight(expandDescription("[galcop-mostwanted-arrivetime]"), 10) + this.$adjustTime(clock.clockStringForTime(arr));
var timeIn = ""
if (arr < clock.adjustedSeconds) {
timeIn = this.$getTimeSince(arr, false) + " ago";
} else {
timeIn = "In " + this.$getTimeSince(clock.adjustedSeconds - (arr - clock.adjustedSeconds), false);
}
text += " (" + timeIn + ")\n";
}
}
if (player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
if (mw._missionList.indexOf(itm.index) === -1) {
curChoices["60_ADD~" + itm.index] = {
text: "[galcop-mostwanted-add]",
color: this._menuColor
};
} else {
curChoices["61_REMOVE~" + itm.index] = {
text: "[galcop-mostwanted-remove]",
color: this._menuColor
};
}
}
} else {
text += this.$padTextRight(expandDescription("[galcop-mostwanted-updated]"), 10) + "N/A\n";
text += this.$padTextRight(expandDescription("[galcop-mostwanted-lastseen]"), 10) + "--unknown--\n";
}
text += "\n";
var hist = "";
if (player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
for (var i = 0; i < itm.lastVisibleHistory.length; i++) {
if (itm.lastVisibleHistory[i] != null && itm.lastVisibleHistory[i].hasOwnProperty("system") === true) {
if (hist === "") {
hist = this.$padTextRight(expandDescription("[galcop-mostwanted-history]"), 10);
} else {
hist += this.$padTextRight("", 10);
}
hist += System.systemNameForID(itm.lastVisibleHistory[i].system) + ", " + this.$getTimeSince(itm.lastVisibleHistory[i].updated, false) + " ago\n";
hist += this.$padTextRight("", 11) + "Destination: " + System.systemNameForID(itm.lastVisibleHistory[i].destination) + "\n";
}
}
if (hist !== "") text += hist;
}
if (itm.lastVisibleSystem >= 0 && itm.lastVisibleSystem != system.ID) {
if (itm.departureTime < clock.adjustedSeconds && player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
curChoices["52_VIEWCHART"] = {
text: "[galcop-mostwanted-next]",
color: this._menuColor
};
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && this.$systemInCurrentPlot(itm.lastVisibleDestination) === false) {
curChoices["96_SETCOURSE~" + itm.lastVisibleDestination] = {
text: expandDescription("[galcop-set-course]", {
destination: System.systemNameForID(itm.lastVisibleDestination)
}),
color: this._menuColor
};
}
} else {
curChoices["52_VIEWCHART"] = {
text: "[galcop-mostwanted-last]",
color: this._menuColor
};
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") && this.$systemInCurrentPlot(itm.lastVisibleSystem) === false) {
curChoices["96_SETCOURSE~" + itm.lastVisibleSystem] = {
text: expandDescription("[galcop-set-course]", {
destination: System.systemNameForID(itm.lastVisibleSystem)
}),
color: this._menuColor
};
}
}
}
if (player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
curChoices["80_WAIT"] = {
text: "[galcop-wait]",
color: this._menuColor
};
}
def = "97C_CLOSE";
curChoices["97C_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen7-map",
title: "Most Wanted - Details",
overlay: {
name: "mw_badge.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 8) { // most wanted last seen map
var mw = worldScripts.BountySystem_MostWanted;
var dl = mw._displayList;
var itm = dl[this._selectedIndex];
// hold the player's destination
var rtCurr = system.info.routeToSystem(System.infoForSystem(galaxyNumber, p.targetSystem));
this._suspendedDestination = p.targetSystem;
// override it for the display
if (itm.lastVisibleDestination >= 0 && itm.lastVisibleDestination <= 255 &&
itm.departureTime < clock.adjustedSeconds &&
player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
p.targetSystem = itm.lastVisibleDestination;
} else {
p.targetSystem = itm.lastVisibleSystem;
}
// put markers on the map
mission.markSystem({
system: itm.lastVisibleSystem,
name: this.name,
markerShape: "MARKER_SQUARE",
markerColor: "whiteColor",
markerScale: 2
});
this._markers.push(itm.lastVisibleSystem);
if (player.ship.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK") {
if (itm.departureTime < clock.adjustedSeconds) {
mission.markSystem({
system: itm.lastVisibleDestination,
name: this.name,
markerShape: "MARKER_SQUARE",
markerColor: "whiteColor",
markerScale: 3
});
this._markers.push(itm.lastVisibleDestination);
}
var colrs = ["lightGrayColor", "grayColor", "darkGrayColor"];
for (var i = 0; i < itm.lastVisibleHistory.length; i++) {
if (itm.lastVisibleHistory[i] && itm.lastVisibleHistory[i].hasOwnProperty("system") && this._markers.indexOf(itm.lastVisibleHistory[i].system) === -1) {
mission.markSystem({
system: itm.lastVisibleHistory[i].system,
name: this.name,
markerShape: "MARKER_SQUARE",
markerColor: colrs[i],
markerScale: 2
});
this._markers.push(itm.lastVisibleHistory[i].system);
}
}
}
text = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
var bg = "LONG_RANGE_CHART";
var info = System.infoForSystem(galaxyNumber, p.targetSystem);
if (system.info.distanceToSystem(info) < 7.4) {
bg = "SHORT_RANGE_CHART";
text += "\n\n";
}
var rt = system.info.routeToSystem(info, (bg === "SHORT_RANGE_CHART" ? p.routeMode : (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME")));
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
if (p.targetSystem != system.ID) {
if (rt && rt.route.length > 1) {
text += this.$padTextRight("", jmpIndent) + expandDescription("[galcop-jumps]") + " " + (rt.route.length - 1);
}
}
if (bg === "LONG_RANGE_CHART") {
if (this._routeMode === "SHORTEST") {
bg = "LONG_RANGE_CHART_SHORTEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._disabledColor,
unselectable: true
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._menuColor
};
} else {
bg = "LONG_RANGE_CHART_QUICKEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._menuColor
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._disabledColor,
unselectable: true
};
}
}
}
if (p.targetSystem != system.ID && (!rtCurr || rtCurr.route.indexOf(p.targetSystem) === -1) && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
curChoices["96_SETCOURSE~" + p.targetSystem] = {
text: expandDescription("[galcop-set-course]", {
destination: System.systemNameForID(p.targetSystem)
}),
color: this._menuColor
};
}
curChoices["97D_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "97D_CLOSE";
var opts = {
screenID: "oolite-galcopsecoffice-screen8-map",
title: "Course to Last Known Location",
backgroundSpecial: bg,
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 9) { // location of fine system
var itm = this._offences[this._selectedItem];
// hold the player's destination
var rtCurr = system.info.routeToSystem(System.infoForSystem(galaxyNumber, p.targetSystem));
this._suspendedDestination = p.targetSystem;
// override it for the display
p.targetSystem = itm.system;
var bg = "LONG_RANGE_CHART";
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
if (itm.system != system.ID) {
var rt = system.info.routeToSystem(System.infoForSystem(galaxyNumber, itm.system), (this._routeMode === "SHORTEST" ? "OPTIMIZED_BY_JUMPS" : "OPTIMIZED_BY_TIME"));
if (rt && rt.route.length > 1) {
text = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + this.$padTextRight("", jmpIndent) + expandDescription("[galcop-jumps]") + " " + (rt.route.length - 1);
}
}
if (this._routeMode === "SHORTEST") {
bg = "LONG_RANGE_CHART_SHORTEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._disabledColor,
unselectable: true
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._menuColor
};
} else {
bg = "LONG_RANGE_CHART_QUICKEST";
curChoices["90_SHORTEST"] = {
text: "[galcop-short-route]",
color: this._menuColor
};
curChoices["91_QUICKEST"] = {
text: "[galcop-quick-route]",
color: this._disabledColor,
unselectable: true
};
}
}
if (itm.system != system.ID && (!rtCurr || rtCurr.route.indexOf(itm.system) === -1) && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
curChoices["96_SETCOURSE~" + itm.system] = {
text: expandDescription("[galcop-set-course]", {
destination: System.systemNameForID(itm.system)
}),
color: this._menuColor
};
}
curChoices["97E_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "97E_CLOSE";
var opts = {
screenID: "oolite-galcopsecoffice-screen9-map",
title: "Course to Offence System",
backgroundSpecial: bg,
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 10) { // collect bounty receipts
var mw = worldScripts.BountySystem_MostWanted;
var lines = [];
var total = 0;
text += this.$padTextRight("Name", 23) + this.$padTextLeft("Bonus Payment", 8) + "\n\n";
// work out the amount of the receipts
// bonus for difficulty (based on accuracy)
for (var i = 0; i < mw._completed.length; i++) {
var itm = mw._completed[i];
var amt = 0;
var pct = 0;
switch (itm.primaryRole) {
case "trader":
case "trader-courier":
case "trader-smuggler":
pct = 0.05;
break;
case "hunter":
case "hunter-medium":
case "hunter-heavy":
pct = 0.1;
break;
case "pirate":
case "pirate-light-freighter":
case "pirate-medium-freighter":
case "pirate-heavy-freighter":
pct = 0.2;
break;
case "assassin-light":
case "assassin-medium":
case "assassin-heavy":
pct = 0.15;
break;
}
pct += itm.accuracy / 50;
amt = parseInt(itm.realBounty * pct);
total += amt;
var colText = this.$columnText(itm.pilotName + ", " + itm.pilotDescription, 21);
for (var j = 0; j < colText.length; j++) {
var lineText = this.$padTextRight(colText[j], 21);
if (j === 0) lineText += this.$padTextLeft(formatCredits(amt, true, true), 10);
lines.push(lineText);
}
}
if (lines.length > 0) {
var maxpage = Math.ceil(lines.length / (rows + 1));
var end = ((this._page * (rows + 1)) + (rows + 1));
var itemcount = 0;
if (end > lines.length) end = lines.length;
for (var i = (this._page * (rows + 1)); i < end; i++) {
text += lines[i] + "\n";
itemcount += 1;
}
curChoices["94_SPACER"] = "";
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
if (system.ID === this._galCopHQ[galaxyNumber]) {
curChoices["97_CLAIM"] = {
text: expandDescription("[galcop-bounty-bonus-claim]", {
amount: formatCredits(total, true, true)
}),
color: this._menuColor
};
} else {
curChoices["97_CLAIM"] = {
text: expandDescription("[galcop-bounty-bonus-claim]", {
amount: formatCredits(total, true, true)
}) + " (Only at GalCop HQ)",
color: this._disabledColor,
unselectable: true
};
}
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
def = "98_CLOSE";
var opts = {
screenID: "oolite-galcopsecoffice-screen10-map",
title: "Bounty Claim Receipts",
overlay: {
name: "mw_badge.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 11) { // confirm appeal submission
var itm = this._offences[this._selectedItem];
var subitems = JSON.parse(itm.offenceList);
var bounty = 0;
if (itm.galaxy != galaxyNumber) {
bounty = this.$calculateIntergalacticItemBounty(itm);
} else {
bounty = this.$calculateItemBounty(itm, itm.system);
}
var cost = (itm.severity * 2) * 400 + (subitems.length * 200);
var hq = System.infoForSystem(galaxyNumber, this._galCopHQ[galaxyNumber]);
var dist = system.info.distanceToSystem(hq);
var time = Math.pow(dist / 2, 2);
text = expandDescription("[galcop-appeal-confirm]", {
amount: formatCredits(bounty, false, true),
system: itm.systemName,
date: this.$setDateSince(itm.date * 86400),
eta: parseInt(time),
cost: formatCredits(cost, false, true)
});
curChoices["01_YES"] = {
text: "[galcop-appeal-yes]",
color: this._menuColor
};
curChoices["02_NO"] = {
text: "[galcop-appeal-no]",
color: this._menuColor
};
def = "02_NO";
var opts = {
screenID: "oolite-galcopsecoffice-screen11-map",
title: "Confirm Appeal Submission",
overlay: {
name: "galcop_logo.png",
height: 546
},
allowInterrupt: false,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 12) { // bounty hunters noticeboard
// bounty name, source name, date
text = this.$padTextRight(expandDescription("[galcop-mostwanted-tips-bountyname]"), 10) +
this.$padTextRight(expandDescription("[galcop-mostwanted-tips-sourcename]"), 10) +
this.$padTextRight(expandDescription("[galcop-mostwanted-tips-date]"), 7.25) + "\n";
var mw = worldScripts.BountySystem_MostWanted;
var list = mw._hunterTips;
list.sort(compareDateDesc);
def = "98_CLOSE";
if (list.length > 0) {
var maxpage = Math.ceil(list.length / rows);
var end = ((this._page * rows) + rows);
var itemcount = 0;
if (end > list.length) end = list.length;
for (var i = (this._page * rows); i < end; i++) {
curChoices["70_TIPS-" + (i < 10 ? "0" : "") + i + "~" + i] = {
text: this.$padTextRight((mw._missionList.indexOf(list[i].index) >= 0 ? "• " : "") + list[i].bountyName, 10) +
this.$padTextRight(list[i].source, 10) +
this.$padTextRight(this.$adjustTime(clock.clockStringForTime(list[i].createdDate)), 7.25),
alignment: "LEFT",
color: this._itemColor
};
itemcount += 1;
}
curChoices["94_SPACER"] = "";
for (var i = 0; i < (rows - itemcount); i++) {
curChoices["94_SPACER_" + i] = "";
}
if (maxpage > 1 && this._page < (maxpage - 1)) {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._menuColor
};
} else {
curChoices["95_NEXT"] = {
text: "[galcop-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._page > 0) {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._menuColor
};
} else {
curChoices["96_PREV"] = {
text: "[galcop-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
def = "98_CLOSE";
curChoices["98_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen12-map",
title: "Bounty Hunter Noticeboard" + (maxpage > 1 ? ": Page " + (this._page + 1) + " of " + maxpage : ""),
overlay: {
name: "mw_badge.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
if (this._displayType === 13) { // bounty hunter notice details
var mw = worldScripts.BountySystem_MostWanted;
var itm = mw._hunterTips[this._selectedIndex];
text = this.$padTextRight(expandDescription("[galcop-mostwanted-tips-bountyname]") + ":", 10);
text += "Cmdr. " + itm.bountyName + "\n";
text += this.$padTextRight(expandDescription("[galcop-mostwanted-tips-sourcename]") + ":", 10) + itm.source + "\n";
var upd = this.$getTimeSince(itm.createdDate, false);
text += this.$padTextRight(expandDescription("[galcop-mostwanted-tips-date]") + ":", 10) + this.$adjustTime(clock.clockStringForTime(itm.createdDate)) + " (" + (upd != "" ? upd + " ago" : "just now") + ")\n\n";
text += this.$padTextRight("Notice:", 10);
var colText = this.$columnText(itm.text, 21);
for (var i = 0; i < colText.length; i++) {
if (i != 0) text += this.$padTextRight("", 10);
text += colText[i] + "\n";
}
def = "97F_CLOSE";
if (this._selectedIndex < mw._hunterTips.length - 1) {
curChoices["71_NEXTTIP"] = {
text: "Next notice",
color: this._itemColor
};
} else {
curChoices["71_NEXTTIP"] = {
text: "Next notice",
color: this._disabledColor,
unselectable: true
};
}
if (this._selectedIndex > 0) {
curChoices["72_PREVTIP"] = {
text: "Previous notice",
color: this._itemColor
};
} else {
curChoices["72_PREVTIP"] = {
text: "Previous notice",
color: this._disabledColor,
unselectable: true
};
}
curChoices["97F_CLOSE"] = {
text: "[galcop-exit]",
color: this._exitColor
};
var opts = {
screenID: "oolite-galcopsecoffice-screen13-map",
title: "Bounty Hunter Noticeboard - Details",
overlay: {
name: "mw_badge.png",
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: (this._lastChoice[this._displayType] && this._lastChoice[this._displayType] != "" ? this._lastChoice[this._displayType] : def),
message: text
};
}
mission.runScreen(opts, this.$secOfficeHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$secOfficeHandler = function (choice) {
if (this._suspendedDestination) player.ship.targetSystem = this._suspendedDestination;
this._suspendedDestination = null;
this.$removeChartData();
if (!choice) return;
switch (mission.screenID) {
case "oolite-galcopsecoffice-screen0-map":
this._lastChoice[0] = choice;
break;
case "oolite-galcopsecoffice-screen1-map":
this._lastChoice[1] = choice;
break;
case "oolite-galcopsecoffice-screen2-map":
this._lastChoice[2] = choice;
break;
case "oolite-galcopsecoffice-screen3-map":
this._lastChoice[3] = choice;
break;
case "oolite-galcopsecoffice-screen4-map":
this._lastChoice[4] = choice;
break;
case "oolite-galcopsecoffice-screen5-map":
this._lastChoice[5] = choice;
break;
case "oolite-galcopsecoffice-screen6-map":
this._lastChoice[6] = choice;
break;
case "oolite-galcopsecoffice-screen7-map":
this._lastChoice[7] = choice;
break;
case "oolite-galcopsecoffice-screen8-map":
this._lastChoice[8] = choice;
break;
case "oolite-galcopsecoffice-screen9-map":
this._lastChoice[9] = choice;
break;
case "oolite-galcopsecoffice-screen10-map":
this._lastChoice[10] = choice;
break;
case "oolite-galcopsecoffice-screen11-map":
this._lastChoice[11] = choice;
break;
case "oolite-galcopsecoffice-screen12-map":
this._lastChoice[12] = choice;
break;
case "oolite-galcopsecoffice-screen13-map":
this._lastChoice[13] = choice;
break;
case "oolite-galcopsecoffice-screen14-map":
this._lastChoice[14] = choice;
break;
}
if (choice === "01_VIEWSTD") {
this._displayType = 1;
this._page = 0;
}
if (choice === "02_VIEWINTER") this._displayType = 2;
if (choice === "03_PAYMENTS") {
this._displayType = 14;
this._page = 0;
}
if (choice === "03_WANTED") {
this._displayType = 3;
this._page = 0;
}
if (choice === "03_WANTED_BONUS") {
this._displayType = 10;
this._page = 0;
}
if (choice === "04_GALCOPHQ") this._displayType = 4;
if (choice === "09_BOUNTY_TIPS") {
this._displayType = 12;
this._page = 0;
}
if (choice === "02_NO") this._displayType = 5;
if (choice === "01_YES") {
this._displayType = 5;
var itm = this._offences[this._selectedItem];
var subitems = JSON.parse(itm.offenceList);
var cost = (itm.severity * 2) * 400 + (subitems.length * 200);
var apl = {};
var hq = System.infoForSystem(galaxyNumber, this._galCopHQ[galaxyNumber]);
var dist = system.info.distanceToSystem(hq);
apl["status"] = "in progress";
apl["initiatedOn"] = clock.adjustedSeconds;
apl["completedBy"] = clock.adjustedSeconds + (Math.pow(dist / 2, 2) * 3600); // a rough calculation of the time based on distance to HQ
apl["data"] = JSON.parse(JSON.stringify(itm)); // make a copy of the bounty details for reference
apl["roles"] = JSON.parse(JSON.stringify(player.roleWeights)); // grab a current copy of the player's roles
this._appeals.push(apl);
player.credits -= cost;
player.consoleMessage("You appeal has been lodged. " + formatCredits(cost, false, true) + " has been deducted from your account.");
// send an email confirmation
var ga = worldScripts.GalCopAdminServices;
if (ga) {
//if (this._registrars[galaxyNumber] === "") this._registrars[galaxyNumber] = expandDescription("%N [nom]");
if (this._secOffClerk === "") this._secOffClerk = expandDescription("%N [nom]");
var msg = expandDescription("[galcop-appeal-email]", {
system: itm.systemName,
date: this.$setDateSince(itm.date * 86400),
hq: System.systemNameForID(this._galCopHQ[galaxyNumber]),
cost: formatCredits(cost, true, true),
sender: this._secOffClerk
});
var w = worldScripts.EmailSystem;
w.$createEmail({
sender: "GalCop Security Office",
subject: "Appeal Submission",
date: global.clock.adjustedSeconds,
message: msg,
expiryDays: ga._defaultExpiryDays
});
}
}
if (choice.indexOf("01_FINE") >= 0) {
this._selectedItem = parseInt(choice.substring(choice.indexOf("~") + 1));
this._displayType = 5;
}
if (choice.indexOf("05_GAL") >= 0) {
this._selectedGalaxy = parseInt(choice.substring(choice.indexOf("~") + 1));
this._displayType = 6;
this._page = 0;
}
if (choice.indexOf("50_MOSTWANTED") >= 0) {
this._selectedIndex = parseInt(choice.substring(choice.indexOf("~") + 1));
this._displayType = 7;
}
if (choice === "52_VIEWCHART") this._displayType = 8;
if (choice === "53_VIEWCHART") this._displayType = 9;
if (choice.indexOf("60_ADD") >= 0) {
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
var mw = worldScripts.BountySystem_MostWanted;
mw._missionList.push(idx);
player.consoleMessage("Record has been added to manifest screen");
}
if (choice.indexOf("61_REMOVE") >= 0) {
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
var mw = worldScripts.BountySystem_MostWanted;
var lookup = mw._missionList.indexOf(idx);
mw._missionList.splice(lookup, 1);
player.consoleMessage("Record has been removed from manifest screen");
}
if (choice.indexOf("70_TIPS") >= 0) {
this._selectedIndex = parseInt(choice.substring(choice.indexOf("~") + 1));
this._displayType = 13;
}
if (choice === "71_NEXTTIP") {
this._selectedIndex += 1;
}
if (choice === "72_PREVTIP") {
this._selectedIndex -= 1;
}
if (choice === "80_WAIT") {
var mw = worldScripts.BountySystem_MostWanted;
mw.$askWaitTime();
return;
}
if (choice === "90_PAYFINE") {
var itm = this._offences[this._selectedItem];
// calculate what the fine is
var calc_fine = this.$calculateFine(itm);
if (itm.system != system.ID) calc_fine *= (1 + this._galCopHQFineSurcharge);
// set which screen will be shown on return
this._displayType = 1;
if (itm.galaxy != galaxyNumber) this._displayType = 6;
if (player.credits >= calc_fine) {
// send a fine email
var ga = worldScripts.GalCopAdminServices;
if (ga) {
var msg = expandDescription("[marked-for-fines-intro]", {
fine: formatCredits(calc_fine, true, true)
});
if (itm.galaxy === galaxyNumber) {
if (this.$calculateItemBounty(itm) >= 50) {
msg += expandDescription("[marked-for-fines-fugitive]");
}
} else {
if (this.$calculateIntergalacticItemBounty(itm) >= 50) {
msg += expandDescription("[marked-for-fines-fugitive]");
}
}
var w = worldScripts.EmailSystem;
msg += expandDescription("[marked-for-fines-end]");
w.$createEmail({
sender: expandDescription("[marked-for-fines-sender]"),
subject: "Fine payment",
date: global.clock.adjustedSeconds,
message: msg,
expiryDays: ga._defaultExpiryDays
});
}
player.credits -= calc_fine;
// are there any transferred items that match this one? take a copy of the relevant data before we delete it
var tfr = {
bounty: itm.bounty,
severity: itm.severity,
galaxy: itm.galaxy,
system: itm.system,
systemName: itm.systemName,
government: itm.government,
date: itm.date
};
// delete the record
this._offences.splice(this._selectedItem, 1);
// remove any transferred offences
this.$removeTransferredOffences(tfr);
// update the players bounty
this._changing = true;
player.bounty = this.$calculateBounty(system.ID);
this._changing = false;
} else {
player.consoleMessage("Insufficient credit to pay fine.");
}
}
if (choice.indexOf("96_SETCOURSE") >= 0) {
var dest = parseInt(choice.substring(choice.indexOf("~") + 1));
if (dest >= 0 && dest <= 255) {
player.ship.targetSystem = dest;
player.ship.infoSystem = player.ship.targetSystem;
}
player.consoleMessage("Course set for " + System.systemNameForID(dest));
switch (this._displayType) {
case 5:
this._displayType = 1;
break;
case 7:
this._displayType = 3;
break;
case 8:
this._displayType = 7;
break;
case 9:
this._displayType = 5;
break;
default:
this._displayType = 0;
break;
}
}
if (choice === "97_APPEAL") this._displayType = 11;
if (choice === "97_CLAIM") {
var mw = worldScripts.BountySystem_MostWanted;
var total = 0;
// work out the amount of the receipts
// bonus for difficulty (based on accuracy)
var txt = "";
for (var i = 0; i < mw._completed.length; i++) {
var itm = mw._completed[i];
var amt = 0;
var pct = 0;
switch (itm.primaryRole) {
case "trader":
case "trader-courier":
case "trader-smuggler":
pct = 0.05;
break;
case "hunter":
case "hunter-medium":
case "hunter-heavy":
pct = 0.1;
break;
case "pirate":
case "pirate-light-freighter":
case "pirate-medium-freighter":
case "pirate-heavy-freighter":
pct = 0.2;
break;
case "assassin-light":
case "assassin-medium":
case "assassin-heavy":
pct = 0.15;
break;
}
pct += itm.accuracy / 50;
amt = parseInt(itm.realBounty * pct);
total += amt;
txt += " " + formatCredits(amt, true, true) + " for " + itm.pilotName + ", " + itm.pilotDescription + "\n";
}
player.credits += total;
player.consoleMessage("You have been awarded " + formatCredits(total, true, true))
// send a fine email
var w = worldScripts.EmailSystem;
if (w) {
var ga = worldScripts.GalCopAdminServices;
ga.$setupRepNames(player.ship.dockedStation);
var msg = expandDescription("[galcop-bounty-bonus-email]", {
amount: formatCredits(total, true, true),
data: txt,
sender: ga._galCopBountyOfficer
});
w.$createEmail({
sender: expandDescription("[galcop-bounty-sender]"),
subject: "Bounty Bonus Claim",
date: global.clock.adjustedSeconds,
message: msg,
expiryDays: ga._defaultExpiryDays
});
}
mw._completed.length = 0;
this._displayType = 0;
}
if (choice === "97A_CLAIM") {
var df = worldScripts.BountySystem_Deferred;
var subList = df.$checkScope();
var total = 0;
for (var i = 0; i < subList.length; i++) {
var shps = df._deferred[subList[i]];
for (var j = 0; j < shps.length; j++) {
total += shps[j].credits;
}
}
player.credits += total;
player.consoleMessage("You have been awarded " + formatCredits(total, true, true));
df.$clearData();
// send a fine email
var w = worldScripts.EmailSystem;
if (w) {
var ga = worldScripts.GalCopAdminServices;
ga.$setupRepNames(player.ship.dockedStation);
var msg = expandDescription("[galcop-bounty-email]", {
amount: formatCredits(total, true, true),
sender: ga._galCopBountyOfficer
});
w.$createEmail({
sender: expandDescription("[galcop-bounty-sender]"),
subject: "Bounty Claim",
date: global.clock.adjustedSeconds,
message: msg,
expiryDays: ga._defaultExpiryDays
});
}
df._deferred = {};
this._displayType = 0;
}
if (choice === "90_SHORTEST") this._routeMode = "SHORTEST";
if (choice === "91_QUICKEST") this._routeMode = "QUICKEST";
if (choice === "95_NEXT") this._page += 1;
if (choice === "96_PREV") this._page -= 1;
if (choice === "97_CLOSE") this._displayType = 1;
if (choice === "97A_CLOSE") this._displayType = 6;
if (choice === "97B_CLOSE") this._displayType = 2;
if (choice === "97C_CLOSE") this._displayType = 3;
if (choice === "97D_CLOSE") this._displayType = 7;
if (choice === "97E_CLOSE") this._displayType = 5;
if (choice === "97F_CLOSE") this._displayType = 12;
if (choice === "98_CLOSE") this._displayType = 0;
if (choice != "99_EXIT") this.$showSecOffice();
}
//-------------------------------------------------------------------------------------------------------------
// adds an offence to the current run sheet
this.$addOffence = function (offenceType) {
if (this._debug) log(this.name, "adding offence: " + offenceType);
// have we added this offence already?
if (this._holdingDate === 0) this._holdingDate = clock.days;
if (this._holding.indexOf(offenceType) === -1) {
this._holding.push(offenceType);
// update the severity of the current set of offences
var sev = this._offenceTypes[offenceType].severity;
if (sev && sev > this._severity) {
this._severity = sev;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// removes any transferred bounties when the original one is paid off
this.$removeTransferredOffences = function (offenceItem) {
for (var i = this._offences.length - 1; i >= 0; i--) {
var itm = this._offences[i];
if (itm.date === offenceItem.date &&
itm.severity === offenceItem.severity &&
itm.bounty === offenceItem.bounty &&
itm.transferred === true)
this._offences.splice(i, 1);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$anarchiesBountyCalcOverride = function () {
// this function intentionally left blank...
}
//-------------------------------------------------------------------------------------------------------------
this.$simulatorRunning = function () {
var w = worldScripts["Combat Simulator"];
var result = false;
if (w && w.$checkFight && w.$checkFight.isRunning) result = true;
return result;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if item can be paid off, otherwise false
this.$itemIsPayable = function (offenceItem) {
var payableIn = this._severityMatrix[offenceItem.severity].payableIn;
if ((offenceItem.date + payableIn) <= global.clock.days) return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns the number of days left until the item can be paid off
this.$daysUntilPayable = function (offenceItem) {
var payableIn = this._severityMatrix[offenceItem.severity].payableIn;
return parseInt((offenceItem.date + payableIn) - global.clock.days);
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player has committed a crime in a given system, otherwise false
this.$playerIsCriminal = function (systemID) {
for (var i = 0; i < this._offences.length; i++) {
if (this._offences[i].transferred === false && this._offences[i].galaxy === galaxyNumber && this._offences[i].system === systemID) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// adds transferable bounties to the current system
this.$uncoverBounties = function (source) {
for (var i = 0; i < this._offences.length; i++) {
if (((this._offences[i].severity === 2 && this._offences[i].galaxy === galaxyNumber) || this._offences[i].severity === 3) && this._offences[i].transferred === false) {
// make sure we haven't already transferred this offence locally
if (this.$itemAlreadyTransferred(this._offences[i]) === false) {
var itm = this._offences[i];
this._offences.push({
offenceList: itm.offenceList,
bounty: itm.bounty,
severity: itm.severity,
galaxy: galaxyNumber,
system: system.ID,
systemName: system.info.name,
government: system.info.government,
date: itm.date,
transferred: true,
originatingSystem: itm.system,
originatingGalaxy: itm.galaxy
});
}
}
// severity 1 crimes can be transferred at certain distances
if (this._severity1Transfer === true && this._offences[i].severity === 1 && this._offences[i].galaxy === galaxyNumber && this._offences[i].transferred === false) {
var tfr = false;
// check if the distance to the original offence is within the acceptable range
var maxdist = this._severityMatrix[this._offences[i].severity].transferLimit;
var info = System.infoForSystem(galaxyNumber, this._offences[i].system);
var dist = System.infoForSystem(galaxyNumber, system.ID).distanceToSystem(info);
if (dist <= maxdist) tfr = true;
if (tfr === true) {
// make sure we haven't already transferred this offence locally
if (this.$itemAlreadyTransferred(this._offences[i]) === false) {
var itm = this._offences[i];
this._offences.push({
offenceList: itm.offenceList,
bounty: itm.bounty,
severity: itm.severity,
galaxy: galaxyNumber,
system: system.ID,
systemName: system.info.name,
government: system.info.government,
date: itm.date,
transferred: true,
originatingSystem: itm.system,
originatingGalaxy: itm.galaxy
});
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
// checks if the item we're about the transfer has already be transferred to the current system
this.$itemAlreadyTransferred = function (offenceItem) {
var result = false;
for (var i = 0; i < this._offences.length; i++) {
if (this._offences[i].transferred === true &&
this._offences[i].bounty === offenceItem.bounty &&
this._offences[i].severity === offenceItem.severity &&
this._offences[i].system === system.ID &&
this._offences[i].galaxy === offenceItem.galaxy &&
this._offences[i].date === offenceItem.date &&
this._offences[i].offenceList === offenceItem.offenceList) {
result = true;
break;
}
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// removes any zero bounty items from the array
this.$cleanUp = function () {
for (var i = this._offences.length - 1; i >= 0; i--) {
if (this._offences[i].bounty === 0) this._offences.splice(i, 1);
}
}
//-------------------------------------------------------------------------------------------------------------
// removes any bogus data that might end up hanging around
this.$resetBogusData = function () {
// reset bogus data - holding items without any bountyDelta
if ((this._holding.length > 0 || this._severity > 1) && this._bountyDelta === 0) {
this._holding.length = 0;
this._holdingDate = 0;
this._severity = 1;
}
// reset bogus data - bountyDelta without any holding item offences
if (this._bountyDelta != 0 && this._holding.length === 0) {
this._bountyDelta = 0;
this._severity = 1;
}
for (var i = this._offences.length - 1; i >= 0; i--) {
/*log(this.name, "bounty " + this._offences[i].bounty +
", tfr = " + this._offences[i].transferred +
", severity = " + this._offences[i].severity +
", orig sys = " + this._offences[i].originatingSystem +
", sys = " + this._offences[i].system +
", orig gal = " + this._offences[i].originatingGalaxy +
", gal = " + this._offences[i].galaxy);*/
// make sure we don't have any dodgy entries in the list
if (this._offences[i].severity === 0 || this._offences[i].offenceList === "[]") this._offences.splice(i, 1);
}
}
//-------------------------------------------------------------------------------------------------------------
// reduces bounty by an amount
this.$reduceBounty = function (amount, severity, systemID) {
var remain = amount;
for (var i = 0; i < this._offences.length; i++) {
var itm = this._offences[i];
// only update non-transferred bounties
if (itm.transferred === false) {
if (severity === 1 && itm.galaxy === galaxyNumber && itm.system === systemID) {
if (itm.severity === severity) {
if (itm.bounty < remain) {
remain = remain - itm.bounty;
itm.bounty = 0;
this.$updateTransferredBounty(itm);
} else {
itm.bounty -= remain;
this.$updateTransferredBounty(itm);
remain = 0;
}
}
}
if (severity === 2 && itm.galaxy === galaxyNumber) {
if (itm.severity === severity) {
if (itm.bounty < remain) {
remain = remain - itm.bounty;
itm.bounty = 0;
this.$updateTransferredBounty(itm);
} else {
itm.bounty -= remain;
remain = 0;
this.$updateTransferredBounty(itm);
}
}
}
if (severity === 3) {
if (itm.severity === severity) {
if (itm.bounty < remain) {
remain = remain - itm.bounty;
itm.bounty = 0;
this.$updateTransferredBounty(itm);
} else {
itm.bounty -= remain;
this.$updateTransferredBounty(itm);
remain = 0;
}
}
}
}
}
return remain;
}
//-------------------------------------------------------------------------------------------------------------
// updates any transferred bounties to match the original
this.$updateTransferredBounty = function (offenceItem) {
for (var i = 0; i < this._offences.length; i++) {
var itm = this._offences[i];
if (itm.date === offenceItem.date &&
itm.severity === offenceItem.severity &&
itm.bounty != offenceItem.bounty &&
itm.transferred === true)
itm.bounty = offenceItem.bounty;
}
}
//-------------------------------------------------------------------------------------------------------------
// returns the calculated bounty value for the player in the current system
this.$calculateBounty = function (systemID) {
var total = 0;
for (var i = 0; i < this._offences.length; i++) {
var itm = this._offences[i];
total += this.$calculateItemBounty(itm, systemID);
}
// check to see if the player has any active bounties in the current system
if (systemID === this._system && this._bountyDelta != 0) total += this._bountyDelta;
return parseInt(total);
}
//-------------------------------------------------------------------------------------------------------------
// returns the calculated bounty value for a particular offence
this.$calculateItemBounty = function (offenceItem, systemID) {
var bounty = 0;
var sysID = (systemID ? systemID : system.ID);
// because we making a copy of warrants when the player is scanned, basically if the galaxy and system ID match, this is visible
if (offenceItem.system === sysID && offenceItem.galaxy === galaxyNumber && (offenceItem.transferred === false ||
(offenceItem.transferred === true && (offenceItem.originatingSystem != sysID || offenceItem.originatingGalaxy != galaxyNumber))))
bounty = offenceItem.bounty;
return bounty;
}
//-------------------------------------------------------------------------------------------------------------
// calculates the intergalactic bounty on a particular item
this.$calculateIntergalacticItemBounty = function (offenceItem) {
if (offenceItem.severity === 3) {
return offenceItem.bounty;
} else {
return 0;
}
}
//-------------------------------------------------------------------------------------------------------------
// returns the calculated intergalactic bounty value for the player
this.$calculateIntergalacticBounty = function (galNum) {
var total = 0;
for (var i = 0; i < this._offences.length; i++) {
var itm = this._offences[i];
if (itm.galaxy === galNum && itm.transferred === false) {
total += this.$calculateIntergalacticItemBounty(itm);
}
}
return parseInt(total);
}
//-------------------------------------------------------------------------------------------------------------
// calculates the bounty fine to pay on a particular item
this.$calculateFine = function (offenceItem) {
var gov = 0;
var calc_fine = 0;
if (offenceItem.system === -1) {
gov = 1;
} else {
gov = offenceItem.government;
}
calc_fine = 50 + ((gov < 2 || gov > 5) ? 50 : 0);
calc_fine *= this.$degradeBounty(offenceItem);
// check for a minimum fine payment
if (calc_fine < 50) calc_fine = 50;
return calc_fine;
}
//-------------------------------------------------------------------------------------------------------------
// degrade the bounty for fine calculations
this.$degradeBounty = function (offenceItem) {
var b = offenceItem.bounty;
// degrade the bounty by time since offence
var degrade = this._severityMatrix[offenceItem.severity].degradeRate;
var timeframe = (global.clock.days - offenceItem.date);
b -= (timeframe * degrade);
return (parseInt(b) > 0 ? parseInt(b) : 0);
}
//-------------------------------------------------------------------------------------------------------------
this.$clearTransferredBounties = function () {
for (var i = this._offences.length - 1; i >= 0; i--) {
var item = this._offences[i];
if (item.transferred === true && item.originatingGalaxy != galaxyNumber) {
this._offences.splice(i, 1);
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$checkAppealStatus = function (item) {
var result = "none";
if (this._appeals.length > 0) {
for (var i = 0; i < this._appeals.length; i++) {
if (this._appeals[i].data.system === item.system && this._appeals[i].data.date === item.date) result = this._appeals[i].status;
}
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// find all police or main stations in range of ship
this.$findLawVessels = function (npc) {
function _ships(entity) {
return entity.isShip && !(entity.isPlayer) && (entity.isPolice || (entity.isStation && entity.isMainStation));
}
return system.filteredEntities(this, _ships, npc, npc.scannerRange);
}
//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function () {
if (oolite.compareVersion("1.83") <= 0) {
return player.ship.hudAllowsBigGui;
} else {
var bigGuiHUD = ["XenonHUD.plist", "coluber_hud_ch01-dock.plist"]; // until there is a property we can check, I'll be listing HUD's that have the allow_big_gui property set here
if (bigGuiHUD.indexOf(player.ship.hud) >= 0) {
return true;
} else {
return false;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function (currentText, desiredLength, leftSwitch) {
if (currentText == null) currentText = "";
var hairSpace = String.fromCharCode(31);
var ellip = "…";
var currentLength = defaultFont.measureString(currentText);
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) > desiredLength);
currentLength = defaultFont.measureString(tmp);
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 (currentText, desiredLength) {
return this.$padTextRight(currentText, desiredLength, true);
}
//-------------------------------------------------------------------------------------------------------------
// arranges text into a array of strings with a particular column width
this.$columnText = function (originalText, columnWidth) {
var returnText = [];
if (defaultFont.measureString(originalText) > columnWidth) {
var hold = originalText;
do {
var newline = "";
var remain = "";
var point = hold.length;
do {
point = hold.lastIndexOf(" ", point - 1);
newline = hold.substring(0, point).trim();
remain = hold.substring(point + 1).trim();
} while (defaultFont.measureString(newline) > columnWidth);
returnText.push(newline);
if (remain != "") {
if (defaultFont.measureString(remain) <= columnWidth) {
returnText.push(remain);
hold = "";
} else {
hold = remain;
}
} else {
hold = "";
}
} while (hold != "");
} else {
returnText.push(originalText);
}
return returnText;
}
//-------------------------------------------------------------------------------------------------------------
this.$adjustTime = function (itemTime) {
return itemTime.substring(0, itemTime.length - 3);
}
//-------------------------------------------------------------------------------------------------------------
// returns a string containing the days, hours, minutes (and possibly seconds) since a particular time
this.$getTimeSince = function (lastTime, hoursOnly) {
var diff = clock.adjustedSeconds - lastTime;
var result = "";
if (diff > 0) {
var days = (hoursOnly && hoursOnly === true ? 0 : Math.floor(diff / 86400));
var hours = Math.floor((diff - (days * 86400)) / 3600);
var mins = Math.floor((diff - (days * 86400 + hours * 3600)) / 60);
var secs = Math.floor(diff - (days * 86400) - (hours * 3600) - (mins * 60));
// special case - reduce 1 hour down to mins
if (days === 0 && hours === 1 && mins < 40) {
hours = 0;
mins += 60;
}
// special case - reduce 1 min down to secs
if (days === 0 && hours === 0 && mins === 1 && secs < 40) {
mins = 0;
secs += 60;
}
if (hoursOnly && hoursOnly === true && mins > 30 && hours > 1) hours += 1;
if (days > 0) result += days + " days";
if (hours > 0) result += (result === "" ? "" : " ") + hours + " hours";
if ((hoursOnly == null || hoursOnly === false) || (hours === 0 && mins > 0)) {
if (mins > 0) result += (result === "" ? "" : " ") + mins + " mins";
}
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
this.$removeChartData = function () {
if (this._markers.length > 0) {
for (var i = 0; i < this._markers.length; i++) {
mission.unmarkSystem({
system: this._markers[i],
name: this.name
});
}
}
this._markers.length = 0;
}
//-------------------------------------------------------------------------------------------------------------
this.$setDateSince = function (checkDate) {
var testDate = new Date();
testDate.setFullYear(3142, 2, 21);
var secondsPassedTotal = checkDate - 2084004 * 86400.0;
var hoursPassed = Math.floor(secondsPassedTotal / 3600);
var minutesPassed = Math.floor((secondsPassedTotal % 3600) / 60);
var secondsPassed = Math.floor(secondsPassedTotal % 60);
testDate.setHours(hoursPassed);
testDate.setMinutes(minutesPassed);
testDate.setSeconds(secondsPassed);
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return testDate.getDay() + " " + months[testDate.getMonth()] + " " + testDate.getFullYear();
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the passes System ID is in the player's currently plotted course, otherwise false
this.$systemInCurrentPlot = function (sysID) {
var result = false;
var target = player.ship.targetSystem;
if (oolite.compareVersion("1.81") < 0) {
// in 1.81 or greater, the target system could be more than 7 ly away. It becomes, essentially, the final destination.
// there could be multiple interim stop points between the current system and the target system.
// the only way to get this info is to recreate a route using the same logic as entered on the ANA, and pick item 1
// from the list. That should be the next destination in the list.
var myRoute = System.infoForSystem(galaxyNumber, global.system.ID).routeToSystem(System.infoForSystem(galaxyNumber, target), player.ship.routeMode);
if (myRoute) {
if (myRoute.route.indexOf(sysID) >= 0) result = true;
}
} else {
if (target === sysID) result = true;
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
this.$changeSettings = function () {
worldScripts.BountySystem_WarrantScanner._scannerMode = this._warrantScannerMode;
// switch to passive (ie no hands!)
var p = player.ship;
var eqsts = p.equipmentStatus("EQ_WARRANT_SCANNER");
if (eqsts && (eqsts == "EQUIPMENT_OK" || eqsts == "EQUIPMENT_DAMAGED")) {
if (this._warrantScannerMode >= 1) {
p.removeEquipment("EQ_WARRANT_SCANNER");
p.awardEquipment("EQ_WARRANT_SCANNER_PASSIVE");
p.setEquipmentStatus("EQ_WARRANT_SCANNER_PASSIVE", eqsts);
}
return;
}
eqsts = p.equipmentStatus("EQ_WARRANT_SCANNER_PASSIVE");
if (eqsts && (eqsts == "EQUIPMENT_OK" || eqsts == "EQUIPMENT_DAMAGED")) {
if (this._warrantScannerMode < 1) {
p.removeEquipment("EQ_WARRANT_SCANNER_PASSIVE");
p.awardEquipment("EQ_WARRANT_SCANNER");
p.setEquipmentStatus("EQ_WARRANT_SCANNER", eqsts);
}
return;
}
eqsts = p.equipmentStatus("EQ_WARRANT_SCANNER_POLICE");
if (eqsts && (eqsts == "EQUIPMENT_OK" || eqsts == "EQUIPMENT_DAMAGED")) {
if (this._warrantScannerMode >= 1) {
p.removeEquipment("EQ_WARRANT_SCANNER_POLICE");
p.awardEquipment("EQ_WARRANT_SCANNER_POLICE_PASSIVE");
p.setEquipmentStatus("EQ_WARRANT_SCANNER_POLICE_PASSIVE", eqsts);
}
return;
}
eqsts = p.equipmentStatus("EQ_WARRANT_SCANNER_POLICE_PASSIVE");
if (eqsts && (eqsts == "EQUIPMENT_OK" || eqsts == "EQUIPMENT_DAMAGED")) {
if (this._warrantScannerMode < 1) {
p.removeEquipment("EQ_WARRANT_SCANNER_POLICE_PASSIVE");
p.awardEquipment("EQ_WARRANT_SCANNER_POLICE");
p.setEquipmentStatus("EQ_WARRANT_SCANNER_POLICE", eqsts);
}
return;
}
}
|