Was wondering why surrendering never seemed to work. Turns out, it's a bug! The $surrenderCheckState_Police timer never gets started.
The variable is initialized like this:
this._surrenderTimer_Police = {}; Then it is checked like this:
if (!this._surrenderTimer_Police || this._surrenderTimer_Police.isRunning === false)
!this._surrenderTimer_Police evaluates as
!{}, which is false because empty {} is
truthy.
this._surrenderTimer_Police.isRunning evaluates as
{}.isRunning, which is undefined, which is !== false, making the OR condition also false.
The same problem applies to _surrenderTimer_Pirate. My sympathies to all the commanders who've tried to surrender. No, the pirates aren't that merciless, they just mixed up their lasers with their comms interface. Initializing the timer variable to null instead of {} would make the first condition true. Also, the $stopAllTimers function seems to expect the value to be null if the timer was never created. So I think the right fix is to initialize both timer variables to null instead of {}.
I tested setting the timer variable to null and sending another surrender message, and the timer fired and the police stopped attacking.
Then their AI looked around for a serious offender, compared my bounty (15) to their threshold (50 - 6 * system.info.government), came up with 15 > 8 = (50 - 42), and went right back to attacking me!
I think if the police accept the player's surrender, Broadcast Comms should
mostly hide the player's bounty (leave a 1 cr token bounty so they still show as offender), to be restored upon
shipWillDockWithStation (so they get fined if they dock at the main station, and if they dock somewhere else first, the bounty comes back) or
shipWillEnterWitchspace (for players not using Bounty System) or if the player deviates too far from the main station (run a timer to check distance from station periodically, require that it trend down but allow some slack in case player stops or tries to bypass a masslock, maybe 2 scanner ranges increased distance from station compared to the nearest they've been so far [compare current distance to saved distance only updated when player is closer to station than the previous saved distance]).
The possibility of the player accumulating additional bounty after surrender also needs to be handled, either because they committed an offence or because a Bounty System scan imported an out-of-system bounty.
If it was not a local offence, and the player's bounty is currently hidden, the out-of-system bounty should be added to the hidden amount instead, which means Bounty System should cooperate with Broadcast Comms. Moreover, if Bounty System is installed, this OXP needs to set Bounty System's _changing flag to true before clearing or restoring the bounty (and to false after), because Bounty System otherwise would act on that change incorrectly (clear local offences, or consider the restoration as an additional offence).
See the Bounty System thread for how I suggest that OXP be modified to avoid re-applying an out-of-system bounty and integrate with this OXP.
Here is some revised code for Broadcast Comms to fix and enhance the surrender feature (as I was coding, I had quite a few other ideas [see my many comments in the code] beyond what I described above):
Code: Select all
this._surrenderWait_Police = 5; // time to wait (in seconds) after surrendering to police before checking if the player has complied (repeats until player reaches main station, jumps out of system, or is declared non-compliant)
...
this.startUp = function() {
this._killedNames = []; // array containing list of ship names killed by the player in this outing
// used to determine how an escape pod will respond
this._escapepodShipNames = []; // array of links between escape pods and ships
this._scoopOffer = []; // keeps track of escape pods we've communicated with
this._selectedMsg = -1; // currently selected message (defaults to no message)
this._holdTarget = -1; // keeps track of the players hyperspace destination
this._lines = []; // available messages as lines on the MFD
this._greeted = []; // keeps track of ships we've greeted
this._bribed = []; // keeps track of ships we're bribed
this._demanded = []; // keeps track of ships we've demanded cargo from
this._alertCond = 1; // keeps track of the current alert condition
this._targetType = ""; // keeps track of the type of target (either npc, police, thargoid)
this._closestAttackerType = ""; // keeps track of the type of closest attacker
this._accuracyChanged = []; // keeps track of ships whose accuracy we've adjusted
this._bribeCurrent = []; // keeps track of the current bribe offered to different targets
this._bribeAmount = this._bribeInitial; // current bribe offering
this._piracyWorked = false; // flag to indicate that the players demand for cargo (piracy) worked
this._checkTimer = null; // timer to check for when the player target disappears (ie through a wormhole)
this._piracyNPCTimer = null; // timer for an NPC telling police about players act of piracy
this._piracyPoliceTimer = null; // timer for a police response to NPC telling them about players act of piracy
this._waitingForPiracyResponse = false; // flag to indicate the player is waiting for a target to respond to a demand for cargo
this._externalMessages = []; // any external messages
this._surrenderCurrent_Pirate = []; // keeps track of the current list of ships surrendered to (will be reset if player docks anywhere)
this._surrenderedTo = []; // keeps track of who we've surrendered to (will be reset if player docks anywhere)
this._surrenderCheck_Pirate = false; // indicates that player has surrendered and that cargo should be getting dumped
this._surrenderTimer_Pirate = null; // timer that will wait for cargo being dumped after surrender
this._surrenderCheck_Police = false; // indicates that player has sent a surrender request to police and has been told to disable weapons
this._surrenderTimer_Police = null; // timer to monitor player compliance after surrendering to police (will run until player docks or leaves system)
this._surrenderPoliceChances = 0; // if player is not complying with police instructions, they have this many timer updates remaining to comply
this._surrenderMainStationDist = 0; // keeps track of how close the player has come to the main station after surrender, in case they go somewhere else
this._surrenderBounty = 0; // "hidden" bounty after surrendering to police, will be restored when leaving system or docking at any station
this._dockingRequest = false;
this._targetStation = null;
this._targetLastComms = null; // holds reference to last transmission source
this._disableInternal = []; // array of flags to keep track of which internal messages have been disabled
for (var i = 0; i <= this._internalMessages; i++) {
this._disableInternal.push(false);
}
this.$updateview(false);
this._lastSource = system.ID;
}
...
//=============================================================================================================
// ship interfaces
//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function _shipWillDockWithStation(station) {
this.$stopAllTimers();
this._dockingRequest = false;
var that = _shipWillDockWithStation; // pointer to this function
var bountysystem = (that.bountysystem = that.bountysystem || worldScripts.BountySystem_Core); // cache worldScript reference in a local property on this function
if (this._surrenderBounty > 0) { // hidden bounty from surrendering to police will be restored when docking with any station (not only the main station!)
if (bountysystem) bountysystem._changing = true; // tell Bounty System OXP to ignore the bounty change we are about to do (so it doesn't get recorded as a new offence)
player.bounty += this._surrenderBounty; // make hidden bounty visible again (add it to current bounty in case the player gained additional bounty meanwhile)
if (bountysystem) bountysystem._changing = false; // tell Bounty System OXP to pay attention to bounty changes again
this._surrenderBounty = 0; // clear our hidden bounty variable (need to do this regardless of whether Bounty System is installed)
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function _shipWillEnterWitchspace(station) {
var that = _shipWillEnterWitchspace; // pointer to this function
var bountysystem = (that.bountysystem = that.bountysystem || worldScripts.BountySystem_Core); // cache worldScript reference in a local property on this function
if (this._surrenderBounty > 0) { // hidden bounty from surrendering to police will be restored when jumping out of the system
if (!bountysystem) { // but do not do this if Bounty System is installed; it will take care of setting the player's bounty including the hidden amount
player.bounty += this._surrenderBounty; // make hidden bounty visible again (add it to current bounty in case the player gained additional bounty meanwhile)
}
this._surrenderBounty = 0; // clear our hidden bounty variable (need to do this regardless of whether Bounty System is installed)
}
}
...
//=============================================================================================================
// surrender
this.$respondToSurrender = function $respondToSurrender() {
// todo: has pirate asked for cargo?
//note: real check will be 48
if (this._debug === true) log(this.name, "responding to surrender");
// pirate have a chance of accepting the surrender, police will always accept it
if (this._source != null && (this._source.isPolice || this.$rand(50) > 45)) {
// remove the player as the primary target from any NPC's targeting the player
if (this._source.isPolice === false) {
this._surrenderCurrent_Pirate = [];
var isGroup = false;
if (this._source.group && this._source.group != "") {
isGroup = true;
var group = this._source.group.ships;
group.forEach(function(ship) {
this.$addShipToArray(ship, this._surrenderedTo);
this.$addShipToArray(ship, this._surrenderCurrent_Pirate);
}, this);
} else {
this.$addShipToArray(this._source, this._surrenderedTo);
this.$addShipToArray(this._source, this._surrenderCurrent_Pirate);
}
this.$buildMessageList();
if (this._debug === true) log(this.name, "pirates accepted surrender");
if (this._source.group != "") {
this.$removePlayerTargetFromPirateGroup(this._source);
} else {
this._source.target = null;
}
if (!this._surrenderTimer_Pirate || this._surrenderTimer_Pirate.isRunning === false) {
this._surrenderTimer_Pirate = new Timer(this, this.$surrenderCheckState_Pirate, this._surrenderWait, 0);
}
this._surrenderCheck_Pirate = true;
// reply should be "Hurry up and dump some cargo, scum"
var pnCap = "We";
var pnLw = "we";
if (isGroup === false) {
pnCap = "I";
pnLw = "I";
}
this.$sendMessageToPlayer(this._source, this.$getRandomItemDescription("response-surrender-pirate", {pronouncap:pnCap, pronoun:pnLw}));
} else {
// police surrender
// only if bounty is less than 50 ie offender status only. Fugitive will not be allowed to surrender
if (player.bounty < 50) {
if (player.bounty > 30 && Math.random() < 0.5) {
if (this._debug === true) log(this.name, "police ignored surrender request from player with high bounty (50% chance)");
return; // no response - player can try sending another surrender
}
this.$sendMessageToPlayer(this._source, this.$getRandomItemDescription("response-surrender-police"));
this.$addShipToArray(this._source, this._surrenderedTo); // add the police ship that responded to list that player can't surrender to again (we also use this to identify who should send rejection if the player doesn't comply)
this._surrenderCheck_Police = true; // a separate variable is needed because the timer keeps running and we want to know if the player surrenders again to new police after gaining additional bounty
if (this._surrenderPoliceChances === 0) this._surrenderPoliceChances = 5; // number of timer updates to tolerate non-compliance (but no extra chances if they send multiple surrender messages)
// start a timer, if it's not already started
if (!this._surrenderTimer_Police || this._surrenderTimer_Police.isRunning === false) {
this._surrenderTimer_Police = new Timer(this, this.$surrenderCheckState_Police, this._surrenderWait_Police, this._surrenderWait_Police); // repeats until stopped
}
} else {
this.$sendMessageToPlayer(this._source, this.$getRandomItemDescription("response-deny-surrender-police")); // fugitive rejection
}
}
} else {
if (this._debug === true) log(this.name, "declined");
if (this._source.isThargoid) {
this.$sendMessageToPlayer(this._source, expandDescription("[thargoid_curses]"));
}
}
}
...
//-------------------------------------------------------------------------------------------------------------
// check if the player is complying with instructions after surrendering to police, and make police stop hostilities if they do
// player has to disable their weapons system ("_" key) initially but can switch them on again after surrender is accepted
// player has to approach the main station without deviating more than 50km (player can take all day to travel the distance, but must not go somewhere else)
// this timer will continue running until the player is declared non-compliant, or docks and pays their fine, or jumps out of the system
this.$surrenderCheckState_Police = function $surrenderCheckState_Police() {
var that = $surrenderCheckState_Police; // pointer to this function
var bountysystem = (that.bountysystem = that.bountysystem || worldScripts.BountySystem_Core); // cache worldScript reference in a local property on this function
var p = player.ship, ms = system.mainStation;
var dist = (ms && ms.isValid) ? p.position.distanceTo(ms) : 0; // player current distance to main station
var hasSurrendered = this._surrenderMainStationDist !== 0, // this._surrenderMainStationDist > 0 implies surrender was accepted and we are tracking their progress
isThreat = p.weaponsOnline && this._surrenderCheck_Police, // we require weapons off when a surrender request is pending, after surrender is accepted they can be re-enabled
isFar = dist > this._surrenderMainStationDist + 50000, // after surrendering, did distance from main station increase by more than 50km since the last time seen by police?
isFugitive = player.bounty > 50; // gained after surrender, otherwise the surrender would be rejected immediately
// begin nearby police/main-station loop
var law = this.$findLawVessels(p);
for (var i = 0; i < law.length; i++)
{
// is the player seen?
if (law[i].hasHostileTarget && law[i].target !== p) {
continue; // skip any police that are occupied with fights against someone other than the player
} else if (dist < this._surrenderMainStationDist) { // for players that have surrendered, if they are near any police that aren't too busy to notice, update distance tracking
this._surrenderMainStationDist = dist; // this is the closest the player has been to the main station since they surrendered (to be used in the next timer update)
}
// check compliance
if (isFugitive) { // player became a fugitive after surrendering earlier and police nearby aren't too busy to notice
hasSurrendered = false; // police AI will handle comms to fugitives...
break; // fall through to restore hidden bounty and stop timer
} else if (!isThreat && !isFar) { // player is compliant (handle this case first so later checks can assume non-compliance)
// check if player has a pending surrender request
if (this._surrenderCheck_Police) {
if (hasSurrendered === false && law[i].target == p) { // must be targeting the player because markTargetForFines uses the ship's target
law[i].markTargetForFines(); // flag player to be fined when they dock at the main station
this._surrenderMainStationDist = dist; // begin tracking player distance to station (and make hasSurrendered true for the next timer update)
hasSurrendered = true; // make it true for the current timer update to skip bounty restoration code after the loop
// hide most of the player's current bounty (police attack offenders with bounty above a threshold, which is lower in higher-government systems)
if (player.bounty > 0) {
this._surrenderBounty += player.bounty - 1; // add current bounty to hidden bounty (player may gain additional bounty after surrender and surrender to a different group of police)
if (bountysystem) bountysystem._changing = true; // tell Bounty System OXP to ignore the bounty change we are about to do (so it doesn't clear local offences)
player.bounty = 1; // leave a token 1 cr visible bounty so player is offender but police won't attack (bounty hunters probably won't either, but who knows?)
if (bountysystem) bountysystem._changing = false; // tell Bounty System OXP to pay attention to bounty changes again
}
this.$sendMessageToPlayer(law[i], this.$getRandomItemDescription("response-accept-surrender-police")); // police ships or main station can send this message
if (this._debug === true) log(this.name, "Police accepted surrender");
// don't break here because we want to record surrender for all nearby police and stop hostilities for all nearby police (and main station if it is nearby)
}
// once per player surrender request, make currently hostile nearby police or main station stop attacking
if (law[i].target === p && law[i].hasHostileTarget) { // police/station is hostile and targeting player
this.$addShipToArray(law[i], this._surrenderedTo); // make sure player can't surrender to them again
law[i].target = null; // de-target the player so they stop attacking and their AI can find something else to do
law[i].removeDefenseTarget(p); // reduce likelihood of police AI re-acquiring the player as a target if police are still in combat with someone else
if (this._debug === true) log(this.name, law[i].displayName + " de-targeting player");
}
// so if the player gets a new bounty on the way to the station, they can surrender again to police they encounter, stopping hostilities
// or if they go off course and are seen by police, their hidden bounty will be restored (code below) and the police probably will attack them
// but as long as the player has not accumulated too much new bounty (still offender), they will be able to surrender again (especially with changes elsewhere to allow repeat surrenders to police that are attacking)
}
} else if (law[i].isStation === false) { // player is non-compliant (implied by previous check), and stations don't interact with non-compliant players, so we are a nearby police ship
if (isThreat && this._surrenderPoliceChances--) { // player has not yet disabled weapons (pre-surrender) and we haven't exhausted our patience yet
this.$sendMessageToPlayer(law[i], this.$getRandomItemDescription("response-surrender-police")); // one police sends another instructions message
return; // take no further action until the next timer update (using return as a do-once and to skip the code that clears this._surrenderCheck_Police after the loop)
} else { // either isThreat with no chances left, or isFar (going off course doesn't receive any tolerance (or warning), but the player may be able to surrender to a new group of police)
hasSurrendered = false; // make sure this is set before the break in the block below so we restore their hidden bounty even if we don't send a message
if (this.$itemIsInArray(law[i], this._surrenderedTo)) { // only police that witnessed the original surrender can send a message
this.$sendMessageToPlayer(law[i], this.$getRandomItemDescription("response-break-surrender-police"));
if (this._debug === true) log(this.name, "Police rejected surrender");
break; // only send one message
}
// fall through to restore hidden bounty and stop timer
// the police AI probably will attack them and send its own messages, since they were attacked by police before (why else did the player surrender?)
}
}
}
// end nearby police/main-station loop
if (hasSurrendered === false) { // surrender was rejected because the player didn't disable weapons in time, or has been broken because player went off course or became a fugitive after surrender was accepted
this._surrenderMainStationDist = 0; // reset distance tracking for future surrender attempts (would have to be addressed to other police than the ones to which the player originally surrendered)
if (this._surrenderBounty > 0) { // player has a hidden bounty
if (bountysystem) bountysystem._changing = true; // tell Bounty System OXP to ignore the bounty change we are about to do (so it doesn't get recorded as a new offence)
player.bounty += this._surrenderBounty; // make hidden bounty visible again (add it to current bounty in case the player gained additional bounty meanwhile)
if (bountysystem) bountysystem._changing = false; // tell Bounty System OXP to pay attention to bounty changes again
this._surrenderBounty = 0; // clear hidden bounty
}
this._surrenderTimer_Police.stop();
} else { // hasSurrendered is true
this._surrenderCheck_Police = false; // any pending request has been handled (we use return to bypass this when needed)
}
}
...
//-------------------------------------------------------------------------------------------------------------
this.$fullResetVariables = function() {
this._escapepodShipNames = [];
this._scoopOffer = [];
this._greeted = [];
this._bribed = [];
this._demanded = [];
this._bribeCurrent = [];
this._surrenderCurrent_Pirate = [];
this._surrenderedTo = [];
this._surrenderCheck_Pirate = false;
this._surrenderCheck_Police = false;
this._surrenderPoliceChances = 0;
this._surrenderMainStationDist = 0;
this._surrenderBounty = 0;
this._bribeAmount = this._bribeInitial;
this._piracyWorked = false;
this._waitingForPiracyResponse = false;
this._killedNames = [];
this._targetLastComms = null;
this.$resetVariables();
}
...
this.$buildMessageList = function() {
// store the currently selected message, so we can reselect it after the list is rebuilt
var stored = "";
if (this._selectedMsg >= 0 && this._selectedMsg < this._lines.length && this._lines[this._selectedMsg] != null) {
stored = this._lines[this._selectedMsg].id;
}
// reset comms log settings
this._lines = [];
var p = player.ship, t = p && p.target, tt = t && t.target;
if(p.equipmentStatus("EQ_BROADCASTCOMMSMFD") === "EQUIPMENT_OK") {
if (this._targetLastComms && this._disableInternal[10] === false) this._lines.push({id:"core_10", text:"(Target last comms message)"});
// add default messages (ie "broadcast" messages)
// if there are hostiles present
if (this._alertCond === 3 && this._disableInternal[2] === false) this._lines.push({id:"core_2", text:"Send distress message"});
// load up any external messages
if (this._externalMessages !== null && this._externalMessages.length > 0) {
var cMsg = {};
var bAdd = false;
for (var i = 0; i < this._externalMessages.length; i++) {
bAdd = false;
cMsg = this._externalMessages[i];
if (cMsg) {
// are we going to display this message?
if (cMsg.transmissionType === "broadcast" ||
(cMsg.transmissionType === "target" && cMsg.ship === null && cMsg.shipDisplayName === "" && t !== null) ||
(cMsg.transmissionType === "target" && cMsg.ship && t === cMsg.ship) ||
(cMsg.transmissionType === "target" && cMsg.shipDisplayName && t.displayName === cMsg.shipDisplayName)) {
bAdd = true;
}
if (this._alertCond === 3 && cMsg.hideOnConditionRed === true) bAdd = false;
if (bAdd === true) this._lines.push({id:cMsg.messageName, text:cMsg.displayText});
}
}
}
// do we have a non-hostile target? add general target messages
// greeting, taunt, drop your cargo,
if (this._alertCond !== 3 && t && t.isPiloted && this._targetType !== "station" && this._targetType !== "escapepod") {
// check who we've greeted before
// only allow greeting to non-greeted ships
if (this.$itemIsInArray(t, this._greeted) === false && this._disableInternal[3] === false) {
this._lines.push({id:"core_3", text:"Send greeting to target"});
}
if (this._disableInternal[4] === false) this._lines.push({id:"core_4", text:"Send taunt to target"});
// only add add a demand for cargo if the ship has cargo capacity
if (t.cargoSpaceCapacity > 0 && this._disableInternal[7] === false) {
// check who we've demanded cargo from before
// only allow demands to ships once
if (this.$itemIsInArray(t, this._demanded) === false) {
this._lines.push({id:"core_7", text:"Demand " + this._demandCargo.toString() + " ton" + ((this._demandCargo === 1) ? "" : "s") + " of cargo from target"});
}
}
}
if (t && t.isPiloted && this._targetType === "escapepod") {
if (this.$itemIsInArray(t, this._scoopOffer) === false && this._disableInternal[9] === false && p.equipmentStatus("EQ_FUEL_SCOOPS") === "EQUIPMENT_OK") {
this._lines.push({id:"core_9", text:"Offer to rescue escape pod"});
}
}
// no target set (or target is not attacking player), but red alert condition
if (this._alertCond === 3 && (!t || tt !== p)) {
if (this._disableInternal[8] === false) this._lines.push({id:"core_8", text:"Surrender to nearest attacker"});
if (this._disableInternal[6] === false) this._lines.push({id:"core_6", text:"Offer bribe to nearest attacker"});
}
// do we have a hostile target? add hostile target messages
// i surrender, taunt, threat, bribe
if (this._alertCond === 3 && t && t.isPiloted && this._targetType !== "station" && this._targetType !== "escapepod") {
// only allow surrender to ships we haven't surrendered to before ... unless they are police attacking us!
if ((t.isPolice && t.hasHostileTarget && tt == p) || (this._disableInternal[8] === false && this.$itemIsInArray(t, this._surrenderedTo) === false)) {
this._lines.push({id:"core_8", text:"Surrender to target"});
}
// only offer bribe option to ship targeting the player
if (tt === p && player.credits >= this._bribeAmount && (this._targetType === "npc" || this._targetType === "pirate" || this._targetType === "hunter" || this._targetType === "police")) {
// check who we've bribed before
// only allow bribing to non-bribed ships
if (this.$itemIsInArray(t, this._bribed) === false && this._disableInternal[6] === false) {
this._lines.push({id:"core_6", text:"Offer bribe of " + this._bribeAmount.toString() + "cr to target"});
}
}
if (this._disableInternal[4] === false) this._lines.push({id:"core_4", text:"Send taunt to target"});
if (this._disableInternal[5] === false) this._lines.push({id:"core_5", text:"Issue threat to target"});
if (this._disableInternal[11] === false) this._lines.push({id:"core_11", text:"Keep away from my target"});
}
// if a target system is set
if (this._alertCond !== 3 && this._holdTarget !== global.system.ID && this._holdTarget >= 0 && this._disableInternal[1] === false) {
this._lines.push({id:"core_1", text:"Is anyone heading to " + System.systemNameForID(this._holdTarget) + "?"});
}
// docking clearance
if (typeof p.requestDockingClearance === "function") {
if (t && t.isValid && t.isStation && t.canDockShip(p) && this._dockingRequest === false && this._disableInternal[12] === false) {
this._lines.push({id:"core_12", text:"Request docking clearance"});
}
if (t && t.isValid && t.isStation && t.canDockShip(p) && this._dockingRequest === true && this._disableInternal[13] === false) {
this._lines.push({id:"core_13", text:"Withdraw docking request"});
}
}
}
if (stored !== null && stored !== "") {
// in our new array, check to see that our stored message still exists
var found = false;
for (var i = 0; i < this._lines.length; i++) {
if (this._lines[i].id === stored) {
// if it does, set the selected message pointer to it
this._selectedMsg = i;
found = true;
}
}
if (found === false) {
// if the selected message isn't there anymore, reset the selected message pointer
this._selectedMsg = -1;
}
}
this.$updateview(false);
}
...
this.$transmit = function() {
var p = player.ship;
var msg = "";
var id = "";
// only allow a transmit if we're not currently waiting for a response to another message
if (this._delay == null || this._delay.isRunning === false) {
// do we have a selected message?
if (this._selectedMsg >= 0 && this._selectedMsg < this._lines.length && this._lines[this._selectedMsg] != null) {
id = this._lines[this._selectedMsg].id;
msg = this._lines[this._selectedMsg].text;
// perform tranmission
switch (id) {
case "core_1": //"Is anyone heading to somewhere?"
this.$sendBroadcastMessage("Is anyone heading to " + System.systemNameForID(this._holdTarget) + "?");
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToRequestForWormhole, this._defaultResponseWait, 0);
break;
case "core_2": //"Send distress message":
this.$sendBroadcastMessage(this.$getRandomItemDescription("transmit-help"));
p.broadcastDistressMessage();
break;
case "core_3": //"Send greeting to target":
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-greeting-" + this._targetType));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToGreeting, this._defaultResponseWait, 0);
break;
case "core_4": //"Send taunt to target":
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-taunt-" + this._targetType));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToTaunt, this._defaultResponseWait, 0);
// add this target to the greeted array - illogical to say Hi after a taunt
this.$addShipToArray(this._source, this._greeted);
// update the MFD straight away, because we might do this in yellow alert status
this.$buildMessageList();
break;
case "core_5": //"Issue threat to target":
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-threat-" + this._targetType));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToThreat, this._defaultResponseWait, 0);
// add this target to the greeted array - illogical to say Hi after a threat
this.$addShipToArray(this._source, this._greeted);
break;
case "core_6": //"Offer bribe to target":
if (msg.indexOf("nearest") === -1) {
if (this.$checkTarget() === false) return;
this._source = p.target;
var crType = "credits";
if (this._bribeAmount === 1) crType = "credit";
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-bribe", {amount:this._bribeAmount.toString(), credittype:crType}));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToBribe, this._defaultResponseWait, 0);
// add this target to the greeted array - illogical to say Hi after a bribe
this.$addShipToArray(this._source, this._greeted);
} else {
this._source = this.$findNearestAttacker();
if (this.$itemIsInArray(this._source, this._bribed) === false) {
// add this target to the greeted array - illogical to say Hi after a bribe
this.$addShipToArray(this._source, this._greeted);
this.$workOutCurrentBribeAmount(this._source);
if (this._bribeAmount < player.credits) {
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-bribe", {amount:this._bribeAmount.toString(), credittype:crType}));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToBribe, this._defaultResponseWait, 0);
} else {
// we shouldn't ever get here, because once you reach beyond your credit balance you are automatically
// added to the bribed array, but still. Just in case.
player.consoleMessage("Insufficient credits to offer");
}
} else {
player.consoleMessage("Closest ship has already been bribed");
}
}
break;
case "core_7": //"Demand cargo":
if (this.$checkTarget() === false) return;
this._source = p.target;
var tons = this._demandCargo.toString() + ((this._demandCargo === 1) ? " ton" : " tons");
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-piracy", {tons:tons}));
this._waitingForPiracyResponse = true;
if (this._targetType === "npc" || this._targetType === "pirate") {
if (this._debug === true) log(this.name, "ship '" + this._source.displayName + "' might be responding");
if (this._source.AIScript.oolite_priorityai) {
if (this._debug === true) log(this.name, "ai found!");
var hold = this._source.target;
this._source.AIScript.oolite_intership.cargodemand = this._demandCargo;
this._source.target = p;
this._source.performAttack();
this._source.AIScript.oolite_priorityai.reconsiderNow();
// de-target the player so any red-alert is removed
this._source.target = hold;
} else {
if (this._debug === true) log(this.name, "no priority AI found!");
}
}
// we can only demand once - after that, if you want cargo, use your lasers!
this.$addShipToArray(this._source, this._demanded);
this.$addShipToArray(this._source, this._greeted);
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToDemandForCargo, this._defaultResponseWait, 0);
this.$buildMessageList();
break;
case "core_8": //"Surrender to target":
if (msg.indexOf("nearest") === -1) {
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-surrender"));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToSurrender, this._defaultResponseWait, 0);
// add this target to the greeted array - illogical to say Hi after a surrender
this.$addShipToArray(this._source, this._greeted);
} else {
this._source = this.$findNearestAttacker();
if ((this._source && this._source.isPolice) || this.$itemIsInArray(this._source, this._surrenderedTo) === false) {
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-surrender"));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToSurrender, this._defaultResponseWait, 0);
// add this target to the greeted array - illogical to say Hi after a surrender
this.$addShipToArray(this._source, this._greeted);
} else {
player.consoleMessage("Closest ship has already been surrendered to");
}
}
break;
case "core_9": //"Offer to rescue escape pod":
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendMessageToTarget(this.$getRandomItemDescription("transmit-escapepod"));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToEscapePodOffer, this._defaultResponseWait, 0);
break;
case "core_10": //"(Target last comms message)":
if (this._targetLastComms) {
// still in range?
var found = false;
var tlc = p.checkScanner(true);
for (var i = 0; i < tlc.length; i++) {
if (tlc[i] === this._targetLastComms) found = true;
}
if (found === false) {
player.consoleMessage("Unable to locate target");
} else {
p.target = this._targetLastComms;
}
}
this._targetLastComms = null;
this.$buildMessageList();
break;
case "core_11": //"Keep away from my target":
if (this.$checkTarget() === false) return;
this._source = p.target;
this.$sendBroadcastMessage(this.$getRandomItemDescription("transmit-keep-away-from-target"));
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToKeepAwayFromTarget, this._defaultResponseWait, 0);
break;
case "core_12": // request docking clearance
case "core_13": // withdraw docking request
if (this.$checkTarget() === false) return;
if (p.target.isStation && p.target.canDockShip(p)) {
if (this._dockingRequest === false) {
this._dockingRequest = true;
this.$sendBroadcastMessage(this.$getRandomItemDescription("request-docking-clearance"));
} else {
this.$sendBroadcastMessage(this.$getRandomItemDescription("withdraw-docking-request"));
this._dockingRequest = false;
}
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, this.$respondToDockingRequest, this._defaultResponseWait, 0);
this._targetStation = p.target;
} else {
player.consoleMessage("Current target is not station or cannot dock ship");
}
break;
default:
// this should be any external messages
var cMsg = {};
// find the message to call
for (var i = 0; i < this._externalMessages.length; i++) {
cMsg = this._externalMessages[i];
if (cMsg) {
if (cMsg.messageName === id) {
// we have a hit
// but only transmit the message if it doesn't start with bracket characters
if (msg.substring(0, 1) != "{" && msg.substring(0, 1) != "(" && msg.substring(0, 1) != "[" && msg.substring(0,1) != "<") {
this.$sendMessageToTarget(cMsg.messageText);
}
if (this._delay && this._delay.isRunning) this._delay.stop();
this._delay = new Timer(this, cMsg.callbackFunction, cMsg.delayCallback, 0);
if (cMsg.deleteOnTransmit === true) {
this._externalMessages[i] = null;
this.$buildMessageList();
}
// break out of the loop once we've found a hit.
break;
}
}
}
break;
}
}
}
}
I discovered that even if you have all of the nearby police de-target the player and you clear the bounty, you will still stay in red alert and be attacked by the police if you are near the main station because it also targets you and the police AI causes its allies (the other police) to re-acquire you. So I included the main station in the de-targeting code. I also added a removeDefenseTarget. It appears the police AI uses defense targets as potential targets when they are in combat, and they might go back into combat after the surrender de-target if you weren't the only hostile around.
The messages when police accept your surrender just say to go to the station, not that you are supposed to keep your weapons off until then, so I tweaked the non-compliance conditions to require weapons offline only for the period between sending a surrender message and the surrender being accepted - or rejected, but in that case you have other problems. We could change the messages, of course, but I think it's better to let players enable weapons again after surrendering: maybe they will need to fight off pirates on the way, which is a perfectly legal thing to do...
Of course, if you use your weapons inappropriately after surrendering, you will gain a new bounty, and may attract hostile police attention again. As it was originally, you could find some other police that had been off-scanner when you surrendered before and surrender to the new ones to pacify the ones currently fighting you, so I decided to simplify it and just make an exception to allow multiple surrenders to police that are attacking you.
Regardless, if you step too far over the line and gain fugitive status, you won't be able to surrender any more, and your hidden bounty will be restored (by the timer) as soon as any police see you. I also decided to only hide the bounty for the first surrender, not for subsequent ones, so further crimes will add up and may attract laser fire from police.