Scripts/thecollector.js |
"use strict";
this.name = "thecollector";
this.author = "mossfoot, Norby";
this.copyright = "2014 Norby";
this.description= "Missions from The Collector";
this.version = "0.4";
this.licence = "CC BY-NC-SA 4.0";
this.$TheCollectorBuoyDistance = 20000; //distance between two buoys before the collector's station
this.$TheCollectorMinBuoys = 5; //minimum how many buoys created
//internal properties, should not touch
this.$TheCollectorMissionStage = 0; //Where the player stay in the missions
this.$TheCollectorMissionSub = null; //Where the player stay within a MissionStage
this.$TheCollectorMSO = true; //flag for the first missionScreenOpportunity after landing
this.$TheCollectorStation = null; //store the station to detect if spawned
this.$TheCollectorStationKey = "thecollector_adck_coriolis-station"; //dataKey of collector's station
this.$TheCollectorTimes = []; //When the stages started
//worldscript events
this.startUp = function() {
this.$TheCollectorMissionStage = missionVariables.$TheCollectorMissionStage;
if(!(this.$TheCollectorMissionStage)) this.$TheCollectorMissionStage = 0;
if(this.$TheCollectorMissionStage > 0) this.$TheCollectorInstructions(0); //set the F5F5 info only
this.$TheCollectorTimes = JSON.parse(missionVariables.$TheCollectorTimes); //destringify
if( !this.$TheCollectorTimes ) this.$TheCollectorTimes = []; //When the stages started
this.$TheCollectorSound1 = new SoundSource;
if( worldScripts["BGS-M"] ) this.$TheCollectorSound1.sound = "bgs-c_buy.ogg";
else this.$TheCollectorSound1.sound = "buy.ogg";
this.$TheCollectorSound1.loop = false;
this.$TheCollectorSound1.repeatCount = 1;
}
this.systemWillPopulate = function() { //for Oolite 1.79 and above
this.$TheCollectorCreateStation(true);
}
this.missionScreenOpportunity = function() {
var p = player.ship;
// log(this.name, p.dockedStation);//debug
if( p && p.docked && this.$TheCollectorMSO && system ) {
this.$TheCollectorMSO = false; //only in the first missionScreenOpportunity after landing
if( this.$TheCollectorMissionStage < 2 && Math.random() < 0.1 ) { //10% chance
this.$TheCollectorInstructions( 1 ); //galaxy hint talk until stage 2
return;
} else if( galaxyNumber > 0 ) return; //nothing more in other galaxies
if( p.dockedStation == system.mainStation ) {
if( system.ID == 119 && this.$TheCollectorMissionStage < 4 //Rarere
&& p.dockedStation.dataKey != this.$TheCollectorStationKey ) {
this.$TheCollectorInstructions( 3 ); //local rumor until stage 4
} else if( system.ID == 160 && ( this.$TheCollectorMissionStage == 5 //Leritean
|| this.$TheCollectorMissionStage == 6 ) ) {
var h = 0; //elapsed time in hours
var s = this.$TheCollectorTimes[5];
if( s > 0 ) h = ( clock.seconds - s ) / 3600;
var tt = Math.ceil( h * 10 ) / 10 + " hours";
// log(this.name, tct+" "+h+" "+s);//debug
if( s && h < 63 ) { //arrived in time (63h)
this.$TheCollectorInstructions( 7, tt );
} else this.$TheCollectorInstructions( 6, tt ); //too late
} else if( system.ID == 65 && this.$TheCollectorMissionStage < -1 ) { //Sori
this.$TheCollectorInstructions( -1 ); //todo: a ship is delivered
} else if( system.ID == 66 && this.$TheCollectorMissionStage < -1 ) { //Aate
this.$TheCollectorInstructions( -1 ); //todo: a ship is delivered
}
} else if( p.dockedStation.dataKey == this.$TheCollectorStationKey ) {
if( this.$TheCollectorMissionStage < 5 ) { //offer Leritean mission
this.$TheCollectorInstructions( 4 );
} else if( this.$TheCollectorMissionStage == 6 ) { //Leritean mission failed
this.$TheCollectorInstructions( 4 ); //back to stage 4
} else if( this.$TheCollectorMissionStage == 7 ) { //Leritean mission done
this.$TheCollectorInstructions( 8 );
}
}
}
}
this.playerWillSaveGame = function( message ) {
missionVariables.$TheCollectorMissionStage = this.$TheCollectorMissionStage;
missionVariables.$TheCollectorTimes = JSON.stringify(this.$TheCollectorTimes);
}
this.shipWillDockWithStation = function( station ) {
this.$TheCollectorMSO = true; //flag for the first missionScreenOpportunity after landing
}
this.shipWillEnterWitchspace = function() {
this.$TheCollectorStation = null; //clear the station storage
}
this.shipWillExitWitchspace = function() { //use this event due to shipExitedWitchspace is not called for player ship
this.$TheCollectorCreateStation();
if( galaxyNumber == 0 && system ) {
if( this.$TheCollectorMissionStage > 3 //trap setup after met Mr. Smith
&& ( system.ID == 122 || system.ID == 181 ) ) { //in Bibe and Bioris
var n = Math.floor( 1 + 3 * Math.random() ); //1-3 attackers
var s = system.addShips("pirate", n, player.ship.position, 25000);
if( s ) for(var i=0; i < s.length; i++ ) {
if( s[i] ) {
s[i].setAI("thecollector_trapAI.plist");
s[i].awardEquipment("EQ_FUEL_INJECTION");
s[i].fuel = 7;
s[i].target = player.ship;
}
}
}
}
}
this.shipWillLaunchFromStation = function( station ) {
this.$TheCollectorCreateStation(false); //for Oolite v1.77
}
//TheCollector methods
this.$TheCollectorCreateStation = function( populator ) {
if( galaxyNumber == 0 && system && system.ID == 119 && !this.$TheCollectorStation ) {
var dist = 1656000; //how far is the collector's station in the main station to sun lane
var mpos = system.mainStation.position;
var msvector = system.sun.position.subtract(mpos); //mainStation to current sun vector
var mlen = (this.$TheCollectorMinBuoys+1) * this.$TheCollectorBuoyDistance; //min. length of the buoy line
var apos = mpos.add( msvector.direction().multiply( dist - mlen ) ); //asteroids position
// var p = system.sun.position; log(this.name, "Sunpos:"+p.x+" "+p.y+" "+p.z);//get orig. sunpos
// var osp = Vector3D(-1679104.3673211336, -1513520.786781907, -43617.31031984091);//original sun
// var movector = osp.subtract(mpos); //mainStation to original sun vector
// var spos = mpos.add( movector.direction().multiply( dist ) ) //station position
// .add( mpos.direction().multiply( 40000 ) );
// log(this.name, "spos:"+spos.x+" "+spos.y+" "+spos.z);//get the following coordinates
var spos = Vector3D(-1219441.8670473576, -1134372.290313594, 113154.84710425357); //fix for sure
if(populator) { //for Oolite 1.79 and above
system.setPopulator("thecollector_station", {
callback: function(pos) {
this.$TheCollectorCreateSGB( apos, spos );
}.bind(this),
location: "COORDINATES",
coordinates: spos,
deterministic: true
});
system.setPopulator("thecollector_asteroids", {
callback: function(pos) {
this.$TheCollectorCreateAF( apos, spos );
}.bind(this),
location: "COORDINATES",
coordinates: spos
});
} else { //for Oolite v1.77
this.$TheCollectorCreateSGB( apos, spos ); //create station, gate and buoys
//create asteroid fields after(!) buoys to do not prevent an aseroid the creation of buoys
this.$TheCollectorCreateAF( apos, spos );
}
}
}
this.$TheCollectorCreateAF = function( apos, spos ) {//create asteroid fields
//call after buoys to do not prevent an aseroid the creation of a buoy
system.addShips("asteroid", 32, apos, 30000);
var v = apos.subtract(spos);
system.addShips("asteroid", 64, spos.add(v.direction().multiply(v.magnitude()/2)), 40000);
system.addShips("asteroid", 32, spos, 30000);
}
this.$TheCollectorCreateSGB = function( apos, spos ) { //create station, gate and buoys
var s = system.addShips("[" + this.$TheCollectorStationKey + "]", 1, spos, 0);
var v = apos.subtract(spos); //targetVector from the collector's station to the asteroids
var bd = this.$TheCollectorBuoyDistance; //buoy distance
var d = v.direction(); //targetVector from the collector's station to the asteroids
if(s) this.$TheCollectorStation = s[0];
if( this.$TheCollectorStation ) { //rotate to the asteroids
var a = this.$TheCollectorStation.heading.angleTo(d); //angle
var c = this.$TheCollectorStation.heading.cross(d).direction(); //cross
this.$TheCollectorStation.orientation = this.$TheCollectorStation.orientation.rotate(c, -a);
var gpos = spos.add( d.multiply( this.$TheCollectorBuoyDistance ) ); //gate position
var r = system.addShips("thecollector_gate", 1, gpos, 0);
if(r && r[0]) r[0].orientation = this.$TheCollectorStation.orientation;
else log(this.name, "Warning: The Collector's Gate is not created");
} else log(this.name, "Error: The Collector's Station is not created!");
//the trick of the buoy line is if the sun is in an unortodox position then make a very long guide line
var l = Math.round((v.magnitude())/this.$TheCollectorBuoyDistance); //length of the buoy line
for( var i = 2; i <= l; i++ ) { //create buoys along the line except the nearest to the station (the gate)
var p = spos.add( d.multiply( this.$TheCollectorBuoyDistance * i ) ); //buoy position
var b = system.addShips("thecollector_buoy", 1, p, 0);
if(b && b[0]) b[0].displayName += " "+(i-1);
if( l > 500 && i == 496 ) i = l - 5; //do not make too much buoys
}
if( l > 500 ) {
if( r && r[0] ) {
r[0].beaconCode = r[0].name; //last resort: the gate is a beacon
log(this.name, "Warning: The Collector's Station is too far so the gate is the beacon");
} else log(this.name, "Error: The Collector's Station is too far and the gate is not created");
}
}
this.$TheCollectorInstructions = function( stage, tt ) {
var t = worldScripts.thecollector;
if( stage > 0 ) { //step to the new stage and display missionscreen
t.$TheCollectorMissionStage = stage;
t.$TheCollectorMissionSub = "_"; //start
t.$TheCollectorMissionScreen(t, tt);
if(msg) player.commsMessage(msg, 10);
} //if stage is 0 then set the F5F5 message to the current missionstage and do not change it
var msg = expandMissionText(t.name+t.$TheCollectorMissionStage);
if( msg ) {
mission.setInstructions( msg+" (#"+t.$TheCollectorMissionStage+")", t.name);//show in F5-F5 screen
t.$TheCollectorTimes[t.$TheCollectorMissionStage] = clock.seconds; //save the start of the stage
}
}
this.$TheCollectorMissionScreen = function( t, tt ) {
var mt = t.$TheCollectorMissionStage+t.$TheCollectorMissionSub;
var todo = expandMissionText(t.name+t.$TheCollectorMissionStage);
var m = expandMissionText(t.name+mt, {thecollectortime: tt, thecollectortodo: todo});
if( !m || !(m.length>0) ) return;
var c = [];
var cr = 0;
for( var j = 1; j < 10; j++ ) {
var mj = t.name+mt+j;
var txt = null;
cr = expandMissionText(mj+"cr"); //must pay for this choice?
if( !cr || !(cr>0) || player.credits >= cr ) //do not show if not enough money
txt = expandMissionText(mj);
if( txt && txt.length > 0 ) c[ j ] = txt;
}
if( c.length < 1 ) c[0] = "OK"; //default choice if none is defined
// log(t.name, "Stage #"+mt+" c.length: "+c.length+" "+c[0]);//debug
mission.runScreen({
title: "The Collector (#"+t.$TheCollectorMissionStage+")",
message: m,
background: "thecollector_background.png",
exitScreen: "GUI_SCREEN_MANIFEST",
choices: { "_0" : c[0],
"_1" : c[1],
"_2" : c[2],
"_3" : c[3],
"_4" : c[4],
"_5" : c[5],
"_6" : c[6],
"_7" : c[7],
"_8" : c[8],
"_9" : c[9]
}
},function( choice ) {
var o = 0;
if( choice ) o = choice.substr(1); //cut starting "_"
var cr = expandMissionText(t.name+mt+o+"cr"); //must pay for this choice?
var r = expandMissionText(t.name+mt+o+"redir");
var redir = false;
if( r && r.length > 0 ) {
redir = true;
if( 1*r == r ) { //redir to a single number mean new stage
t.$TheCollectorMissionStage = r;
t.$TheCollectorInstructions(0);
t.$TheCollectorMissionSub = "_"; //begin of a new stage
} else if( r.indexOf("_") == 0 ) { //redir begin with underscore mean new sub within this stage
t.$TheCollectorMissionSub = r + "_";
} else { //redir into a new stage lower than the first subpage
var i = r.indexOf("_");
t.$TheCollectorMissionStage = r.substr(0, i);
t.$TheCollectorInstructions(0);
t.$TheCollectorMissionSub = r.substr(i) + "_";
// log(t.name, r+" "+t.$TheCollectorMissionStage+" "+t.$TheCollectorMissionSub);//debug
}
}
log(t.name, "Stage:"+mt+" choice:"+o+" "+c[o]+" cr:"+cr+" redir:"+r);//debug
if( o > 0 ) {
if( cr > 0 ) { //must pay for this choice!
player.credits -= cr;
t.$TheCollectorSound1.play();
}
if( !redir ) t.$TheCollectorMissionSub += o + "_";
t.$TheCollectorMissionScreen(t); //recursive, so do not use too much level
} else return; //exit
// if( !isValidFrameCallback( h.$HUDSelectorFCB2 ) )
// h.$HUDSelectorFCB2 = addFrameCallback( h.$HUDSelector_FCB2 );
});
}
|