I (not an NPC but a player) can detect all sorts of things beyond my scanner range - I can see laser fire in the distance, I can see icesteroids, I can see large ships, et cetera. I can also see stuff silhouetted against the sun, and see things better when the sun shines on them.
Telescope Extender OXP formalises this, with ships of various sizes being detectable at various distances beyond scanner length.
For example you can see:
Adders at 32 km,
Vipers and escort ships around 50 km (2x scanner range),
Anacondas, Boas, Cobra MkIIIs and Pythons about 100 km (4x scanner range),
Rock Hermits in almost 500 km (if not visible from the Main Station then fly around),
Coriolis Stations at 1000 km (right from the witchpoint).
But what about NPCs?
The impression I've formed is that they can detect nothing beyond scanner range unless it has a beacon which they can pick up (eg Rock Hermits, whose beacons I can't pick up!).
Is my presumption true?
And if it is, is there any way to increase the detection distance of NPCs?
I've found nothing relevant either here or on our wiki, but then I don't know the technical jargon for any of this, sorry!
"NPC detection" range
Moderators: winston, another_commander
- Cholmondely
- Archivist
- Posts: 6212
- Joined: Tue Jul 07, 2020 11:00 am
- Location: The Delightful Domains of His Most Britannic Majesty (industrial? agricultural? mainly anything?)
- Contact:
"NPC detection" range
Comments wanted:
•Missing OXPs? What do you think is missing?
•Lore: The economics of ship building How many built for Aronar?
•Lore: The Space Traders Flight Training Manual: Cowell & MgRath Do you agree with Redspear?
•Missing OXPs? What do you think is missing?
•Lore: The economics of ship building How many built for Aronar?
•Lore: The Space Traders Flight Training Manual: Cowell & MgRath Do you agree with Redspear?
- phkb
- Impressively Grand Sub-Admiral
- Posts: 5265
- Joined: Tue Jan 21, 2014 10:37 pm
- Location: Writing more OXPs, because the world needs more OXPs.
Re: "NPC detection" range
Looks like it. See wiki: Shipdata.plist - scanner_range
Making it bigger would definitely require (a) a source code change, and probably (b) AI routine changes.Sets a custom scanner range. Standard is 25.6 km, thargoids have 50 km. Only applies to NPCs. However, at least since oolite 1.65 all defined scanner ranges are limited to 25.6 km, even for thargoids. This means it only makes sense defining shorter ranges than the maximum range.
- Redspear
- ---- E L I T E ----
- Posts: 2845
- Joined: Thu Jun 20, 2013 10:22 pm
- Location: On the moon Thought, orbiting the planet Ignorance, looking through a telescope with the lens cap on
Re: "NPC detection" range
Is this because if an NPC is fired upon by a ship not on its scanner then it does nothing?
If so then that's unfortunate as some interesting stuff could be done by restricting faster ships in particular to smaller scanners.
- Cholmondely
- Archivist
- Posts: 6212
- Joined: Tue Jul 07, 2020 11:00 am
- Location: The Delightful Domains of His Most Britannic Majesty (industrial? agricultural? mainly anything?)
- Contact:
Re: "NPC detection" range
So!
This is really all about my incessant moaning about Ethics in Oolite. Wanting to lead Refugee Adders and Commie slave-miner-minnows to freedom and safety.
DGill was incredibly decent and put together a test OXP for me to try out.
A Feudal Lance who can be contacted via BCC and will then follow me wherever!
Observations
1) BCC'd the Feudal Lance and told him to "Follow Me"
He did.
I then injected away from him to outside scanner range and turned 90° to starboard and whizzed along a bit.
He still followed me! Despite never coming into scanner range.
So there is something else going on here, meseems. Can anybody explain it to me?
2) Docked at a Rock Hermit.
He didn't. But he was still mooching about outside it when I relaunched shortly afterwards. I forgot to check to see if he was still following me, and just BCC'd him again. Explanation?
3) Jumped from Larais to Onrira.
He didn't. Or he didn't seem to.
Admittedly I did run into a zillion-and-one pirates and then legged it to the nearest posse of GalCops. By the time that the scrum was over, there was no sign of him. Maybe he never jumped? Maybe he misjumped? Maybe he did, but got scragged? Maybe he did but legged it? Maybe I'm just getting blind in my dotage? Sadly, I've lost the relevant latest.log. Explanation?
References:
1) DGill's "feudal-BCCregroupAI.plist" (as yet unbutchered by yours truly)
2) DGill's feudalAItest.js
This is really all about my incessant moaning about Ethics in Oolite. Wanting to lead Refugee Adders and Commie slave-miner-minnows to freedom and safety.
DGill was incredibly decent and put together a test OXP for me to try out.
A Feudal Lance who can be contacted via BCC and will then follow me wherever!
Observations
1) BCC'd the Feudal Lance and told him to "Follow Me"
He did.
I then injected away from him to outside scanner range and turned 90° to starboard and whizzed along a bit.
He still followed me! Despite never coming into scanner range.
So there is something else going on here, meseems. Can anybody explain it to me?
2) Docked at a Rock Hermit.
He didn't. But he was still mooching about outside it when I relaunched shortly afterwards. I forgot to check to see if he was still following me, and just BCC'd him again. Explanation?
3) Jumped from Larais to Onrira.
He didn't. Or he didn't seem to.
Admittedly I did run into a zillion-and-one pirates and then legged it to the nearest posse of GalCops. By the time that the scrum was over, there was no sign of him. Maybe he never jumped? Maybe he misjumped? Maybe he did, but got scragged? Maybe he did but legged it? Maybe I'm just getting blind in my dotage? Sadly, I've lost the relevant latest.log. Explanation?
References:
1) DGill's "feudal-BCCregroupAI.plist" (as yet unbutchered by yours truly)
Code: Select all
{
"INITIALISE" = {
ENTER = ("scanForNearestShipWithRole: player", "commsMessage: [feudal-lance-wing]");
"TARGET_FOUND" = (setTargetToFoundTarget, "setStateTo: FOLLOW_PLAYER");
"NOTHING_FOUND" = ("setStateTo: LOCATE_PLAYER");
UPDATE = ("scanForNearestShipWithRole: player", "pauseAI: 3.0");
};
"FIND_PLAYER" = {
ENTER = ("scanForNearestShipWithRole: player");
ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"TARGET_FOUND" = (setTargetToFoundTarget, "setStateTo: FOLLOW_PLAYER");
"NOTHING_FOUND" = ("setStateTo: LOCATE_PLAYER");
"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
UPDATE = ("scanForNearestShipWithRole: player", "pauseAI: 3.0");
};
"LOCATE_PLAYER" = {
ENTER = ("sendScriptMessage: locatePlayer");
"PLAYER_FOUND" = ("setDesiredRangeTo: 12800.0", setDestinationToTarget, checkCourseToDestination);
"COURSE_OK" = ("sendScriptMessage: checkPlayerDistance");
"PLAYER_FAR" = ("setSpeedFactorTo: 50.0", performFlyToRangeFromDestination);
"PLAYER_MID" = ("setSpeedFactorTo: 10.0", performFlyToRangeFromDestination);
"PLAYER_NEAR" = ("setSpeedFactorTo: 5.0", performFlyToRangeFromDestination);
"DESIRED_RANGE_ACHIEVED" = ("setStateTo: FIND_PLAYER");
ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
UPDATE = ("addFuel: 2.0", "sendScriptMessage: locatePlayer", "pauseAI: 5.0");
};
"FOLLOW_PLAYER" = {
ENTER = ("setDesiredRangeTo: 3000", setDestinationToTarget, checkCourseToDestination);
ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"COURSE_OK" = ("setSpeedFactorTo: 1.0", performFlyToRangeFromDestination);
"TARGET_LOST" = ("setStateTo: FIND_PLAYER");
"DESIRED_RANGE_ACHIEVED" = ("setSpeedFactorTo: 1.0", performIdle, "setStateTo: LOOK_FOR_TARGETS");
"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"OFFENCE_COMMITTED" = (setTargetToFoundTarget, "setStateTo: ATTACK_SHIP");
UPDATE = ("addFuel: 1.0", checkCourseToDestination, "pauseAI: 3.0");
};
"LOOK_FOR_TARGETS" = {
"ATTACKED" = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"TARGET_FOUND" = (setTargetToFoundTarget, "setStateTo: ATTACK_SHIP");
"NOTHING_FOUND" = ("setStateTo: FIND_PLAYER");
ENTER = ("setSpeedTo: 0.0", "scanForNearestShipHavingAnyRole: feudal-madmonk communist-cobra", "pauseAI: 1.0");
EXIT = ();
UPDATE = ("scanForNearestShipHavingAnyRole: feudal-madmonk communist-cobra", "pauseAI: 1.0");
};
"ATTACK_SHIP" = {
ENTER = (performAttack);
"ENEMY_FIRE" = ("setSpeedFactorTo: 1.0", performAttack);
"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
"TARGET_DESTROYED" = ("setSpeedFactorTo: 0.75", "setStateTo: FIND_PLAYER");
"TARGET_LOST" = ("setSpeedFactorTo: 0.75", "setStateTo: FIND_PLAYER");
"TARGET_EJECTED" = ("setSpeedFactorTo: 0.75", "setStateTo: FIND_PLAYER");
UPDATE = ("scanForNearestShipHavingAnyRole: feudal-madmonk communist-cobra", "pauseAI: 1.0");
};
GLOBAL = {
ENTER = ("setStateTo: INITIALISE");
};
}
Code: Select all
"use strict";
/*
feudalAItest.js
Script for creating and handling Feudal Carriers.
Oolite
Copyright © 2003-2012 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
thargoid_carrier.oxp
Copyright © 2006-2012 "Selezen", scripting by "Commander McLane"
This work is licensed under the Creative Commons
Attribution-Noncommercial-Share Alike 3.0 Unported License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter
to Creative Commons, 171 Second Street, Suite 300, San Francisco,
California, 94105, USA.
*/
this.name = "feudalAItest";
this.description = "Script for testing an AI";
this.author = "DG";
this.copyright = "© 2012 Selezen and Commander McLane";
this.license = "CC-by-nc-sa 3.0";
this.version = "1.0";
this.startUp = function () {
}
this.broadcastcontrol = function() {
var w = worldScripts.BroadcastCommsMFD;
w.$createMessage({
messageName:this.name + "myMessage1",
callbackFunction:this.$broadcastCallback.bind(this),
displayText:"Regroup",
messageText:"Follow Me.",
transmissionType:"broadcast",
deleteOnTransmit:true,
delayCallback:4});
}
this.$broadcastCallback = function () {
this.ship = player.ship.target;
this.ship.switchAI("feudal-BCCregroupAI.plist");
};
this.shipWillLaunchFromStation = function() {
this.broadcastcontrol();
}
this.shipLaunchedFromStation = function()
{
system.addShipsToRoute("feudal-LanceTest", 1, 0.95);
player.commsMessage("press Shift N to activate Broadcast Comm - press ; to view multi-function display - Target ship - press B to select required command - press N to issue command.");
}
this.locatePlayer = function() {
this.playerArray = system.shipsWithPrimaryRole("player");
if(this.playerArray.length > 0)
{
this.ship.target = this.playerArray[0];
this.ship.reactToAIMessage("PLAYER_FOUND");
}
}
this.checkPlayerDistance = function() {
if(!player.ship)
{
return;
}
this.playerDistance = this.ship.position.distanceTo(player.ship.position);
if(this.playerDistance > 51200) // if the escort is more than 2 scanner ranges from the player, move it just off-scanner
{
let playerDirection = player.ship.position.subtract(this.ship.position).direction();
let newPosition = player.ship.position.subtract(playerDirection.multiply(30000));
if (oolite.compareVersion('1.73') <= 0)
{
this.ship.position = newPosition;
}
else
{
this.ship.setPosition(newPosition);
}
this.ship.reactToAIMessage("PLAYER_MID");
return;
}
if(this.playerDistance < 25600)
{
this.ship.reactToAIMessage("PLAYER_NEAR");
}
else
{
if(this.playerDistance > 38400 || player.ship.speed > 2000)
{
this.ship.reactToAIMessage("PLAYER_FAR");
}
else
{
this.ship.reactToAIMessage("PLAYER_MID");
}
}
}
Comments wanted:
•Missing OXPs? What do you think is missing?
•Lore: The economics of ship building How many built for Aronar?
•Lore: The Space Traders Flight Training Manual: Cowell & MgRath Do you agree with Redspear?
•Missing OXPs? What do you think is missing?
•Lore: The economics of ship building How many built for Aronar?
•Lore: The Space Traders Flight Training Manual: Cowell & MgRath Do you agree with Redspear?
- phkb
- Impressively Grand Sub-Admiral
- Posts: 5265
- Joined: Tue Jan 21, 2014 10:37 pm
- Location: Writing more OXPs, because the world needs more OXPs.
Re: "NPC detection" range
In the code, the Feudal Lance will be teleported to just outside scanner range if the distance to the player goes above 51200 (twice the scanner range). So you would never have to wait long for him to "catch up".Cholmondely wrote: ↑Sun Jul 13, 2025 7:49 pmHe still followed me! Despite never coming into scanner range.
The code does a lot of things past scanner range. There is a difference between "detection" (ie the ability of the AI to react to things) and "control" (ie telling the AI to do something specifically). In this case the code is quite happy to find the player anywhere in the local system. You could torus away from the ship for an hour, and when you stop, the ship would appear shortly afterwards, having tracked you all the way. That's because it's been specifically told to do something past scanner range.
There is no logic in the AI to cover docking. And if it did, that ship would cease to exist from the game engine's perspective.
There is no logic in the AI to cover entering a wormhole. It wouldn't be hard to add it, but it's not there right now.
Note: there is a logical fault in the code. Every time you launch from a station, no matter what station, a new Feudal Lance will be spawned. So, when you launched from the Rock Hermit, there would have been two of them, the one you left outside, and a new one near the main station. The new one wouldn't follow you, as you need to initiate the process with BCC, but it would be present in system. Obviously this is test code, but it's worth noting what to expect.