Scripts/planetFall_worldScript.js |
this.name = "PlanetFall";
this.author = "Thargoid, with bits from Eric Walch, Frame and Svengali";
this.copyright = "Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license with clauses - see readme.txt.";
this.description = "Enables planetary landing";
this.version = "1.51";
this.startUp = function()
{
this.lastPlanet = system.mainPlanet; // details of the last planet to be landed on, so we know what to move the player away from on launch
this.planetFallLaunch = false; // as in 1.77 the alert condition is still set on launch - need a mask
this.lastPlanetType = "Prime"; // what type of planet/moon we landed on
this.messageBlock = false; // flag to stop request/cancel messages at launch from planet
this.planetCount = 1; // default setting
this.moonCount = 0; // default setting
this.$systemScan(); // set up the initial planet and moon count
this.planetFallOverride = false; // flag to allow other OXPs to override PlanetFall locations
this.overrideRole = "default"; // if other OXPs want to ensure a specific role is used
this.$checkForSpecialPlanets();
/* For convenience of mission writers, access for other OXPs is via "worldScripts.PlanetFall.lastPlanet" and "worldScripts.PlanetFall.lastPlanetType".
Values for lastPlanetType are "Prime" for the main planet, "Sub" for every other planet, "Moon" for any moon and "Sun" / "GasGiant" for a sun or a Solar System OXP
gas giant (for completeness - cannot land on either of the last two). */
}
this.$turnStation = function(tempStation)
{
if(!tempStation) { return; } // just in case the station doesn't survive spawning.
let stationVector = tempStation.position.subtract(this.lastPlanet.position).direction(); // unit vector pointing away from the planet
let angle = tempStation.heading.angleTo(stationVector); // angle between current heading and target heading
let cross = tempStation.heading.cross(stationVector).direction(); // set the plane where we should rotate in
tempStation.orientation = tempStation.orientation.rotate(cross, -angle); // re-orient the station away from the planet
tempStation.position = tempStation.position.add(stationVector.multiply(3000));
tempStation.breakPattern = false;
}
this.shipApproachingPlanetSurface = function(planet)
{
if(!planet || player.ship.equipmentStatus("EQ_PLANETFALL") != "EQUIPMENT_OK" || planet.hasOwnProperty("PFNoLandQuiet"))
{
return;
}
if(planet.hasOwnProperty("PFNoLand"))
{
player.commsMessage(system.name + " Planetary Control - Urgent warning - landing is not possible here!", 6);
return;
}
this.lastPlanet = planet;
if(!this.landingTimer)
{
if(!planet.isSun && !planet.hasOwnProperty("solarGasGiant") && !planet.hasOwnProperty("isGasGiant"))
{
this.messageBlock = true;
if(planet === system.mainPlanet)
{
this.lastPlanetType = "Prime";
this.landingChoice = (Math.random()*10);
if(this.planetFallOverride)
{
if(this.overrideRole === "default")
{ this.overrideRole = "planetFall_mainSurface_externalOXP" };
this.port = player.ship.spawnOne(this.overrideRole);
this.$turnStation(this.port);
this.overrideRole = "default";
}
else
{
if(this.landingChoice < 3) // spawn capital city
{
this.port = player.ship.spawnOne("planetFall_mainSurface_capitalCity");
this.$turnStation(this.port);
}
if(this.landingChoice >= 3 && this.landingChoice < 4.5) // spawn external OXP location, or if none then Capital City
{
if(this.overrideRole !== "default")
{ this.port = player.ship.spawnOne(this.overrideRole); }
else
{ this.port = player.ship.spawnOne("planetFall_mainSurface_externalOXP"); }
if(!this.port)
{
log(this.name, "Main surface external spawn failure");
this.port = player.ship.spawnOne("planetFall_mainSurface_capitalCity");
}
this.$turnStation(this.port);
this.overrideRole = "default";
}
if(this.landingChoice >= 4.5 && this.landingChoice < 6.5) // spawn a shipyard
{
this.port = player.ship.spawnOne("planetFall_mainSurface_shipYard");
this.$turnStation(this.port);
}
if(this.landingChoice >= 6.5 && this.landingChoice < 7.5) // spawn a military base
{
this.port = player.ship.spawnOne("planetFall_mainSurface_militaryBase");
this.$turnStation(this.port);
}
if(this.landingChoice >= 7.5 && this.landingChoice < 8.9) // spawn seedy bar or leisure complex
{
if((system.government == 0 || this.landingChoice < 8.05) && worldScripts["Random_Hits"])
{
this.port = player.ship.spawnOne("planetFall_mainSurface_seedyBar");
this.$turnStation(this.port);
this.barName = expandDescription('[planetFall_barName]');
missionVariables.random_hits_seedy_spacebar_header = worldScripts["Random_Hits"].barDescription(barName);
this.port.displayName = this.barName;
}
else
{
this.port = player.ship.spawnOne("planetFall_mainSurface_leisureComplex");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 8.9 && this.landingChoice < 9.8) // spawn factory or farm
{
if(system.economy < 4)
{
this.port = player.ship.spawnOne("planetFall_mainSurface_factory");
this.$turnStation(this.port);
}
else
{
this.port = player.ship.spawnOne("planetFall_mainSurface_farm");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 9.8) // spawn open fields or waste dump
{
if(system.economy < 4)
{
this.port = player.ship.spawnOne("planetFall_mainSurface_dump");
this.$turnStation(this.port);
}
else
{
this.port = player.ship.spawnOne("planetFall_mainSurface_fields");
this.$turnStation(this.port);
}
}
}
if(this.lastPlanet.name)
{ this.port.displayName = this.lastPlanet.name + " - " + this.port.displayName; }
else
{ this.port.displayName = system.name + " Prime - " + this.port.displayName; } // set the name to the surface of the prime planet in the system
}
else
{
if(planet.hasAtmosphere)
{
this.lastPlanetType = "Sub";
this.landingChoice = (Math.random()*10);
if(this.planetFallOverride)
{
if(this.overrideRole == "default") { this.overrideRole = "planetFall_subSurface_externalOXP"; };
this.port = player.ship.spawnOne(this.overrideRole);
this.$turnStation(this.port);
this.overrideRole = "default";
}
else
{
if(this.landingChoice < 3) // spawn capital city
{
this.port = player.ship.spawnOne("planetFall_subSurface_colony");
this.$turnStation(this.port);
}
if(this.landingChoice >= 3 && this.landingChoice < 4.5) // spawn external OXP location, or if none then a colony
{
if(this.overrideRole !== "default")
{ this.port = player.ship.spawnOne(this.overrideRole); }
else
{ this.port = player.ship.spawnOne("planetFall_subSurface_externalOXP"); }
if(!this.port)
{
log(this.name, "Sub surface external spawn failure");
this.port = player.ship.spawnOne("planetFall_subSurface_colony");
}
this.$turnStation(this.port);
this.overrideRole = "default";
}
if(this.landingChoice >= 4.5 && this.landingChoice < 6.5) // spawn a shipyard
{
this.port = player.ship.spawnOne("planetFall_subSurface_shipYard");
this.$turnStation(this.port);
}
if(this.landingChoice >= 6.5 && this.landingChoice < 7.5) // spawn a military base
{
this.port = player.ship.spawnOne("planetFall_subSurface_militaryBase");
this.$turnStation(this.port);
}
if(this.landingChoice >= 7.5 && this.landingChoice < 8.9) // spawn seedy bar or leisure complex
{
if((system.government == 0 || this.landingChoice < 8.05) && worldScripts["Random_Hits"])
{
this.port = player.ship.spawnOne("planetFall_subSurface_seedyBar");
this.$turnStation(this.port);
this.barName = expandDescription('[planetFall_barName]');
missionVariables.random_hits_seedy_spacebar_header = worldScripts["Random_Hits"].barDescription(barName);
this.port.displayName = this.barName;
}
else
{
this.port = player.ship.spawnOne("planetFall_subSurface_leisureComplex");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 8.9 && this.landingChoice < 9.8) // spawn factory or farm
{
if(system.economy < 4)
{
this.port = player.ship.spawnOne("planetFall_subSurface_factory");
this.$turnStation(this.port);
}
else
{
this.port = player.ship.spawnOne("planetFall_subSurface_farm");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 9.8) // spawn open fields or waste dump
{
if(system.economy < 4)
{
this.port = player.ship.spawnOne("planetFall_subSurface_dump");
this.$turnStation(this.port);
}
else
{
this.port = player.ship.spawnOne("planetFall_subSurface_fields");
this.$turnStation(this.port);
}
}
}
if(this.lastPlanet.name)
{ this.port.displayName = this.lastPlanet.name + " - " + this.port.displayName; }
else
{ this.port.displayName = system.name + " Minor - " + this.port.displayName; } // set the name to just the surface, so we can identify easily the main planet
}
else
{
this.lastPlanetType = "Moon";
this.landingChoice = (Math.random()*10);
if(this.planetFallOverride)
{
if(this.overrideRole == "default") { this.overrideRole = "planetFall_moonSurface_externalOXP" };
this.port = player.ship.spawnOne(this.overrideRole);
this.$turnStation(this.port);
this.overrideRole = "default";
}
else
{
if(this.landingChoice < 3) // spawn capital city
{
this.port = player.ship.spawnOne("planetFall_moonSurface_dome");
this.$turnStation(this.port);
}
if(this.landingChoice >= 3 && this.landingChoice < 4.5) // spawn external OXP location, or if none then a dome
{
if(this.overrideRole !== "default")
{ this.port = player.ship.spawnOne(this.overrideRole); }
else
{ this.port = player.ship.spawnOne("planetFall_moonSurface_externalOXP"); }
if(!this.port)
{
log(this.name, "Moon external spawn failure");
this.port = player.ship.spawnOne("planetFall_moonSurface_dome");
}
this.$turnStation(this.port);
this.overrideRole = "default";
}
if(this.landingChoice >= 4.5 && this.landingChoice < 6.5) // spawn a mine
{
this.port = player.ship.spawnOne("planetFall_moonSurface_mine");
this.$turnStation(this.port);
}
if(this.landingChoice >= 6.5 && this.landingChoice < 8) // spawn a bar or leisure dome
{
if((system.government == 0 || this.landingChoice < 7.5) && worldScripts["Random_Hits"])
{
this.port = player.ship.spawnOne("planetFall_moonSurface_seedyBar");
this.$turnStation(this.port);
this.barName = expandDescription('[planetFall_barName]');
missionVariables.random_hits_seedy_spacebar_header = worldScripts["Random_Hits"].barDescription(barName);
this.port.displayName = this.barName;
}
else
{
this.port = player.ship.spawnOne("planetFall_moonSurface_leisureDome");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 8 && this.landingChoice < 8.9) // spawn a prison
{
this.port = player.ship.spawnOne("planetFall_moonSurface_prison");
this.$turnStation(this.port);
}
if(this.landingChoice >= 8.9 && this.landingChoice < 9.8) // spawn a research complex or factory
{
if(system.techLevel > 11)
{
this.port = player.ship.spawnOne("planetFall_moonSurface_researchComplex");
this.$turnStation(this.port);
}
else
{
this.port = player.ship.spawnOne("planetFall_moonSurface_factory");
this.$turnStation(this.port);
}
}
if(this.landingChoice >= 9.8) // spawn wasteland
{
this.port = player.ship.spawnOne("planetFall_moonSurface_wasteland");
this.$turnStation(this.port);
}
}
if(this.lastPlanet.name)
{ this.port.displayName = this.lastPlanet.name + " - " + this.port.displayName; }
else
{ this.port.displayName = "Moon of " + system.name + " - " + this.port.displayName; } // set the name to the moon, so we can identify it as a moon
}
}
this.fx = system.addVisualEffect("planetFall_landingFX",player.ship.position.add(player.ship.vectorForward.multiply(170)));
this.port.dockPlayer();
}
else
{
if(planet.hasOwnProperty("solarGasGiant") || planet.hasOwnProperty("isGasGiant"))
{
this.lastPlanetType = "GasGiant";
}
else
{
this.lastPlanetType = "Sun";
}
}
}
else
{ // if the PF landing timer is still running
player.commsMessage(system.name + " Planetary Control - Pull up, you have no landing clearance!", 6);
player.commsMessage("Return to orbit and approach again.", 6);
this.landingTimer.stop();
delete this.landingTimer;
}
}
this.shipWillDockWithStation = function(station)
{
if(station.hasRole("planetFall_surface") || station.hasRole("planetFall_mainSurface_externalOXP") || station.hasRole("planetFall_subSurface_externalOXP") || station.hasRole("planetFall_moonSurface_externalOXP") )
{
if(!this.fx) { this.fx = system.addVisualEffect("planetFall_landingFX",player.ship.position.add(player.ship.vectorForward.multiply(170))); }
this.selectTexture = 1 + (Math.floor(Math.random() * 9));
if(station.hasRole("planetFall_moonSurface"))
{ this.fx.setMaterials({"planetFall_planet1.png": {diffuse_map: "planetFall_moon" + this.selectTexture + ".png" }}); }
else
{ this.fx.setMaterials({"planetFall_planet1.png": {diffuse_map: "planetFall_planet" + this.selectTexture + ".png" }}); }
}
if((station.hasRole("planetFall_mainSurface_seedyBar") || station.hasRole("planetFall_subSurface_seedyBar") || station.hasRole("planetFall_moonSurface_seedyBar")) && worldScripts["Random_Hits"])
{ // Player is docked at a planet-side seedy bar
worldScripts["Random_Hits"].random_hits_docked = true;
}
}
this.shipWillLaunchFromStation = function(station)
{
if(station)
{
this.planetFallLaunch = true;
if(station.hasRole("planetFall_surface"))
{
this.fx = system.addVisualEffect("planetFall_launchFX",player.ship.position.add(player.ship.vectorForward.multiply(150)));
this.fx.orientation = player.ship.orientation;
}
}
}
this.alertConditionChanged = function()
{
if(this.planetFallLaunch)
{
this.planetFallLaunch = false;
return;
}
if(player.alertAltitude && !this.lastPlanet.isSun && !this.lastPlanet.hasOwnProperty("solarGasGiant") && !this.lastPlanet.hasOwnProperty("PFNoLand") && !this.lastPlanet.hasOwnProperty("PFNoLandQuiet") && !this.lastPlanet.hasOwnProperty("isGasGiant"))
{
if(player.ship.equipmentStatus("EQ_PLANETFALL") != "EQUIPMENT_OK")
{
player.commsMessage(system.name + " Planetary Control - Your ship is not equipped for planetfall.", 10);
player.commsMessage("Do not attempt landing, your ship will be destroyed!", 10);
}
else
{
if(!this.messageBlock)
{
player.commsMessage(system.name + " Planetary Control - Landing clearance request received.", 6);
player.commsMessage("Please await confirmation before beginning final approach.", 6);
}
this.clearanceDelay = 5 + (Math.ceil(Math.random()*15)); // delay between 6 and 20 seconds
this.landingTimer = new Timer(this, this.$landingClearance, this.clearanceDelay);
}
}
if(player.alertAltitude && (this.lastPlanet.hasOwnProperty("solarGasGiant") || this.lastPlanet.hasOwnProperty("isGasGiant")))
{ player.consoleMessage("ALERT - You are approaching a Gas Giant. Landing here is not possible!", 10); }
if(player.alertAltitude && this.lastPlanet.hasOwnProperty("PFNoLand"))
{
player.consoleMessage("ALERT - Landing here is not possible!", 10);
return;
}
if(!player.alertAltitude && this.landingTimer && this.landingTimer.isRunning && !player.ship.docked && EquipmentInfo.infoForKey("EQ_FRAME_SAVE") == null)
{
this.landingTimer.stop();
delete this.landingTimer;
missionVariables.planetFallBreak += 0.01; // 1% cumulative chance of equipment failure
if(!this.messageBlock)
{
player.commsMessage(system.name + " Planetary Control - Landing clearance request cancelled.", 6);
player.commsMessage("Goodbye Commander " + player.name + ".", 6);
this.messageBlock = false;
}
}
}
this.$landingClearance = function()
{
this.landingTimer.stop();
delete this.landingTimer;
player.commsMessage(system.name + " Planetary Control - Landing clearance granted.",6);
player.commsMessage("Please approach the surface slowly.", 6);
}
this.shipLeavingPlanetSurface = function(planet)
{
this.lastPlanet = planet;
this.messageBlock = false;
}
this.shipDied = function()
{
let ports = system.shipsWithRole("planetFall_surface"); // an array of any rogue "surface stations" in the system
this.portCount = ports.length; // how many rogues we have that need to be removed
if(this.portCount > 0) for (let i=0; i<this.portCount; i++) // if there are any, loop through and remove them
{ this.$removePort(ports[i]); }
if(this.landingTimer && this.landingTimer.isRunning)
{
this.landingTimer.stop();
delete this.landingTimer;
}
}
this.shipEnteredPlanetaryVicinity = function(planet)
{
if(!planet) { return; }
this.lastPlanet = planet;
if(!planet.isSun && !planet.hasOwnProperty("solarGasGiant") && !planet.hasOwnProperty("isGasGiant") && !planet.hasOwnProperty("PFNoLand") && !planet.hasOwnProperty("PFNoLandQuiet") && player.ship.equipmentStatus("EQ_PLANETFALL") == "EQUIPMENT_OK")
{
player.commsMessage(system.name + " Planetary Control - for planetfall please approach and request landing clearance.",5);
}
else
{
if(planet.isSun)
{ player.consoleMessage("ALERT - Approaching the Sun. Temperature monitoring is critical!", 10); }
if(planet.hasOwnProperty("solarGasGiant") || planet.hasOwnProperty("isGasGiant"))
{ player.consoleMessage("ALERT - You are approaching a Gas Giant. Landing here is not possible!", 10); }
if(planet.hasOwnProperty("PFNoLand"))
{ player.commsMessage("ALERT - Landing is not possible here, please pull up!", 10); }
}
}
this.shipExitedPlanetaryVicinity = function()
{
this.messageBlock = false;
this.shipDied(); // clean-up of any unremoved surface stations.
}
this.shipLaunchedFromStation = function(station)
{
if(EquipmentInfo.infoForKey("EQ_FRAME_SAVE") != null) // if launch is for Save Anywhere, don't want to move the player or nuke the station
{ return; }
if(station && station.hasRole("planetFall_surface"))
{
if(this.landingTimer)
{ delete this.landingTimer; }
player.commsMessage(system.name + " Planetary Control - orbital boost complete.",5);
player.commsMessage("Farewell Commander " + player.name + ".",5);
this.$removePort(station); // remove the surface-simulating station
this.messageBlock = false;
missionVariables.planetFallBreak += 0.02; // 2% cumulative chance of equipment failure
if(Math.random() < missionVariables.planetFallBreak) // landing equipment needs maintenance
{
player.ship.setEquipmentStatus("EQ_PLANETFALL", "EQUIPMENT_DAMAGED");
player.consoleMessage("ALERT - Planetary landing modifications require urgent maintenance.", 10);
player.consoleMessage("Do not attempt to land again before they are repaired!", 10);
missionVariables.planetFallBreak = -0.04; // first two launches guaranteed not to break equipment
}
}
this.$systemScan();
}
this.playerBoughtEquipment = function(equipment) // guarantee first two launches won't break equipment
{
if(equipment == "EQ_PLANETFALL")
{ missionVariables.planetFallBreak = -0.04; }
}
this.shipExitedWitchspace = function()
{
this.$checkForSpecialPlanets();
this.overrideRole = "default";
this.$systemScan();
}
this.$systemScan = function()
{
function isMoon(entity) {return (entity.isPlanet && !entity.hasAtmosphere) };
this.systemArray = system.planets;
this.systemCount = this.systemArray.length;
this.moonCount = system.filteredEntities(this.systemArray, isMoon).length;
this.planetCount = this.systemCount - this.moonCount;
}
this.$removePort = function(port)
{
if(port.hasRole("planetFall_surface"))
{ port.remove(); };
}
this.$jailRelease = function()
{
if(player.credits > missionVariables.planetFallFine)
{
player.credits -= missionVariables.planetFallFine;
player.ship.bounty -= (Math.ceil(missionVariables.planetFallFine * 0.05)); // lower bounty corresponding to fine.
}
else
{ player.credits = 10; }
player.ship.launch();
this.jailTime = 21600 + (Math.random() * 43200); // between 6 and 18 hours in the cells
clock.addSeconds(this.jailTime);
}
this.guiScreenChanged = function()
{
if(!player.ship.docked) // for GUI screen changes whilst in flight, which we can ignore
{ return; }
if(!player.ship.dockedStation.hasRole("planetFall_surface")) // if we're at a trunk or other OXP's station
{ return; }
// Player is docked at a military base or penal colony - not somewhere a criminal should make himself known ;)
if(player.ship.bounty > 25) // player is mid-level offender or fugitive
{
if(player.ship.dockedStation.hasRole("planetFall_mainSurface_militaryBase") || player.ship.dockedStation.hasRole("planetFall_subSurface_militaryBase") || player.ship.dockedStation.hasRole("planetFall_moonSurface_prison"))
{
if(guiScreen == "GUI_SCREEN_EQUIP_SHIP" || guiScreen == "GUI_SCREEN_MARKET" || guiScreen == "GUI_SCREEN_SHIPYARD")
{
missionVariables.planetFallFine = 20 + (Math.ceil(Math.random()*480)); // fine of 21-500 credits
if(player.ship.bounty > 50) // if the player is a fugitive
{ // raise fine by another 1-500 credits
missionVariables.planetFallFine += (Math.ceil(Math.random()*500));
}
if(worldScripts.Cabal_Common_Functions)
{
var t1 = expandMissionText("planetFall_prison");
var t2 = t1.split(".");
var obj = {
role:"planetFall_scene_prison",
absolutePos:[0,-5,150],
briefing:[
[1,"walk",[0,-1,6,10,0.15,2,0,0],t2[0].trim()+"."],
[24,"rot",[0,-1,4.5,0.0015,0.0015,0,0,1,1],t2[1].trim()+"."],
[25,"stopVelo",[0,-1]],
[100,"mes",t2[2].trim()+"."],
[101,"kill"],
[102,0]
],
title:"Do not pass GO, do not collect 200cr",
callback:this.name,
callbackf:"$jailRelease"
};
worldScripts.Cabal_Common_Briefing.startBriefing(obj);
return;
}
else
{ mission.runScreen({title:"Do not pass GO, do not collect 200cr", messageKey:"planetFall_prison", background:"planetFall_cell.png"}, this.$jailRelease); }
}
}
}
if(!player.ship.dockedStation.hasRole("planetFall_noTrade")) // if we're at a location where trading is possible
{ return; }
// no-one to trade with on the empty lunar surface
if(player.ship.dockedStation.hasRole("planetFall_moonSurface_wasteLand") )
{
if(guiScreen == "GUI_SCREEN_EQUIP_SHIP" || guiScreen == "GUI_SCREEN_MARKET")
{
mission.runScreen({title:"Lonely on the moon", messageKey:"planetFall_noTrade", background:"planetFall_lunarScape.png"});
}
}
// no-one to trade with in empty fields
if(player.ship.dockedStation.hasRole("planetFall_mainSurface_fields") || player.ship.dockedStation.hasRole("planetFall_subSurface_fields"))
{
if(guiScreen == "GUI_SCREEN_EQUIP_SHIP" || guiScreen == "GUI_SCREEN_MARKET")
{
mission.runScreen({title:"Nothing but fields...", messageKey:"planetFall_noTrade", background:"planetFall_fields.png"});
}
}
// no-one to trade with in refuse dump
if(player.ship.dockedStation.hasRole("planetFall_mainSurface_dump") || player.ship.dockedStation.hasRole("planetFall_subSurface_dump"))
{
if(guiScreen == "GUI_SCREEN_EQUIP_SHIP" || guiScreen == "GUI_SCREEN_MARKET" || guiScreen == "GUI_SCREEN_SHIPYARD")
{
mission.runScreen({title:"All muck, no brass!", messageKey:"planetFall_noTrade", background:"planetFall_dump.png"});
}
}
}
this.$checkForSpecialPlanets = function()
{ this.scriptDelay = new Timer(this, this.$setFlags, 0.25); }
this.$setFlags = function()
{
if(galaxyNumber === 0 && system.ID === 246) // if we're at Tianve (G0, S227), set up the pulsar
{
for (let i=0; i<system.planets.length; i++)
{
if(system.planets[i].texture === "tianve_pulsar.png")
{ system.planets[i].PFNoLand = true; }
}
}
} |