Path |
Scripts/Cabal_Common_Briefing.js |
"use strict";
this.name = "Cabal_Common_Briefing";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Helper for Mission - Briefings.";
this.version = "1.7";
this.startUp = function()
{
delete this.startUp;
this.helper = new this.Cabal_Common_ScreenFCB();
this.briefingSoundA = new SoundSource();
this.briefingSoundB = new SoundSource();
}
// Can be called via worldScripts.Cabal_Common_Briefing.startBriefing(obj);
this.startBriefing = function(obj)
{
if(!player.ship.docked || !obj) return(false);
if(!obj.capture){
if(!obj.title) obj.title = "Briefing";
if(!obj.background) obj.background = null;
if(!obj.fadeIn){
if(!obj.overlay){
var check = expandMissionText('BGS-IMAGESWITCH');
if(check==="Yes") obj.overlay = "bgs-i_overlay_none.png";
else obj.overlay = null;
}
} else obj.overlay = {name:"cabal_common_briefing_blend10.png",width:1024,height:480};
if(!obj.music) obj.music = null;
this.briefing = obj.briefing;
if(obj.callbackc) this.briefing.cbc = obj.callbackc;
else obj.callbackc = null;
mission.runScreen({title:obj.title,model:obj.role,spinModel:false,background:obj.background,overlay:obj.overlay,music:obj.music,choicesKey:obj.callbackc},this.choiceEval);
if(obj.cornerPos) this.helper.screenCornerPos(obj.cornerPos[0],obj.cornerPos[1],obj.cornerPos[2],obj.cornerPos[3]);
if(obj.absolutePos) mission.displayModel.position = [obj.absolutePos[0],obj.absolutePos[1],obj.absolutePos[2]];
if(obj.ori) mission.displayModel.orientation = obj.ori;
if(obj.getOri) mission.displayModel.orientation = mission.displayModel.scriptInfo[obj.getOri].split(",");
if(obj.getPos) mission.displayModel.position = mission.displayModel.scriptInfo[obj.getPos].split(",");
if(obj.prepareProps){
var prop;
for(prop in obj.prepareProps){
mission.displayModel[prop] = obj.prepareProps[prop];
if(mission.displayModel.subEntities){
for(var i=0;i<mission.displayModel.subEntities.length;i++) mission.displayModel.subEntities[i][prop] = obj.prepareProps[prop];
}
}
}
if(obj.prepareBindings) for(var b=0;b<obj.prepareBindings.length;b++) this.helper.fcbSetBinding(obj.prepareBindings[b][0],obj.prepareBindings[b][1],obj.prepareBindings[b][2],obj.prepareBindings[b][3],obj.prepareBindings[b][4],obj.prepareBindings[b][5],obj.prepareBindings[b][6]);
if(obj.preparePositions) for(var p=0;p<obj.preparePositions.length;p++) this.helper.rePosition(obj.preparePositions[p][0],obj.preparePositions[p][1],obj.preparePositions[p][2]);
if(obj.prepareOrientations) for(var o=0;o<obj.prepareOrientations.length;o++) this.helper.reOrient(obj.prepareOrientations[o][0],obj.prepareOrientations[o][1],obj.prepareOrientations[o][2]);
} else this.helper.fcbRemoveAll();
if(obj.repRelative){ // relativePosition is meaningless for missionscreens
var ar = [mission.displayModel],flagM,flag;
if(mission.displayModel.subEntities && mission.displayModel.subEntities.length){
for(var i=0;i<mission.displayModel.subEntities.length;i++) ar.push(mission.displayModel.subEntities[i]);
}
for(var s=0;s<ar.length;s++){
flag = 0;
flagM = 0;
var a = ar[s].getShaders();
var b = Object.keys(a);
if(!b.length){
a = ar[s].getMaterials();
b = Object.keys(a);
flagM = 1;
}
if(b.length){
if(a[b[0]].hasOwnProperty("uniforms")){
var prop;
for(prop in a[b[0]].uniforms){
if(a[b[0]].uniforms[prop]==="relativePosition"){
a[b[0]].uniforms[prop]="position";
flag = 1;
}
}
}
if(flag){
if(flagM) ar[s].setMaterials(a);
else ar[s].setShaders(a);
}
}
}
}
if(obj.fadeIn) this.briefingFadeIn = obj.fadeIn;
else this.briefingFadeIn = null;
if(obj.screenHUD){
player.ship.hud = obj.screenHUD;
player.ship.hudHidden = false;
}
this.briefingCounter = 0;
this.briefingIndex = 0;
this.briefing = obj.briefing;
if(obj.callback && obj.callbackf){
this.briefing.cb = obj.callback;
this.briefing.cbf = obj.callbackf;
}
if(obj.delta) this.helper.ccl_defaultDelta = obj.delta;
else this.helper.ccl_defaultDelta = 0.015;
if(!this.briefingTimer) this.briefingTimer = new Timer(this,this.doBriefingTimer,0,0.25);
else this.briefingTimer.start();
return(true);
}
this.cleanUp = function()
{
if(this.briefingTimer){
this.briefingTimer.stop();
delete this.briefingTimer;
}
}
this.choiceEval = function(choice){worldScripts.Cabal_Common_Briefing.delayChoice(choice); return;}
this.delayChoice = function(choice)
{
this.cleanUp();
this.helper.fcbRemoveAll();
if(this.briefing.cb && this.briefing.cbf) worldScripts[this.briefing.cb][this.briefing.cbf](choice);
if(this.briefingSoundA.isPlaying) this.briefingSoundA.stop();
if(this.briefingSoundB.isPlaying) this.briefingSoundB.stop();
this.helper.ccl_defaultDelta = 0.015;
delete this.briefing;
player.ship.hud = null;
return;
}
this.doBriefingTimer = function()
{
if(!this.briefing.length || !mission.displayModel || !mission.displayModel.isValid || this.briefingIndex>=this.briefing.length){
this.cleanUp();
this.helper.fcbRemoveAll();
return;
}
if(this.soundStopper && this.briefingCounter >= this.soundStopper[0]){
if(this.soundStopper[1]) if(this.briefingSoundB.isPlaying) this.briefingSoundB.stop();
else if(this.briefingSoundA.isPlaying) this.briefingSoundA.stop();
delete this.soundStopper;
}
var current = this.briefing[this.briefingIndex];
if(this.briefingCounter >= current[0]){
// Action commands
switch(current[1]){
case "bgzoom":
this.helper.fcbZoomBackground(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
case "bind":
this.helper.fcbSetBinding(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
case "check":
this.helper.fcbCheckAll();
break;
case "clean":
this.helper.fcbRemoveAll();
break;
case "continue":
var checked=false;
if(this.briefing.cb){
if(worldScripts[this.briefing.cb][current[2][0]]){
checked = worldScripts[this.briefing.cb][current[2][0]](current[2][1]);
if(typeof(checked)==='number'){ // Goto
this.helper.fcbRemoveAll();
this.briefingCounter = checked-1;
this.briefingIndex = checked-1;
}
}
}
if(!checked && typeof(checked)!=='number'){
this.cleanUp();
this.helper.fcbRemoveAll();
if(this.briefingSoundA.isPlaying && (this.briefingSoundA.repeatCount>1 || this.briefingSoundA.loop)) this.briefingSoundA.stop()
if(this.briefingSoundB.isPlaying && (this.briefingSoundB.repeatCount>1 || this.briefingSoundB.loop)) this.briefingSoundB.stop()
}
break;
case "face":
this.helper.fcbFace(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7]);
break;
case "flightTo":
this.helper.fcbFlightTo(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7]);
break;
case "revolution":
this.helper.fcbKIRevolution(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4]);
break;
case "kill":
this.cleanUp();
this.helper.fcbRemoveAll();
if(this.briefingSoundA.isPlaying) this.briefingSoundA.stop();
if(this.briefingSoundB.isPlaying) this.briefingSoundB.stop();
if(this.briefing.cb && this.briefing.cbf) worldScripts[this.briefing.cb][this.briefing.cbf](current[2]);
break;
case "shadeprop":
this.helper.reShaderProps(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4]);
break;
case "mes":
mission.addMessageText(current[2]);
break;
case "mSpeed":
this.helper.fcbModelSpeed(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
case "mVelo":
this.helper.fcbModelVelo(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7],current[2][8]);
break;
case "mVeloTo":
this.helper.fcbModelVeloTo(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7],current[2][8],current[2][9],current[2][10]);
break;
case "prop":
this.helper.fcbSetProp(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
case "reback":
this.helper.reBackground(current[2][0]);
break;
case "reover":
this.helper.reOverlay(current[2][0]);
break;
case "reori":
this.helper.reOrient(current[2][0],current[2][1],current[2][2]);
break;
case "repos":
this.helper.rePosition(current[2][0],current[2][1],current[2][2]);
break;
case "retex":
this.helper.reTexture(current[2][0],current[2][1],current[2][2],current[2][3]);
break;
case "rot":
this.helper.fcbRotation(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7],current[2][8]);
break;
case "stopSound":
if(this.briefingSoundA.isPlaying) this.briefingSoundA.stop();
if(this.briefingSoundB.isPlaying) this.briefingSoundB.stop();
break;
case "stopVelo":
this.helper.stopVelo(current[2][0],current[2][1]);
break;
case "turn":
this.helper.fcbFlight(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
case "walk":
this.helper.fcbWalk(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6],current[2][7]);
break;
case "zoom":
this.helper.fcbZoom(current[2][0],current[2][1],current[2][2],current[2][3],current[2][4],current[2][5],current[2][6]);
break;
}
if(current[3]) mission.addMessageText(current[3]);
if(current[4]){
if(!this.briefingSoundA.isPlaying){
this.briefingSoundA.sound = current[4];
if(current[5]) this.briefingSoundA.repeatCount = current[5];
else this.briefingSoundA.repeatCount = 0;
this.briefingSoundA.play();
if(current[6]){
if(!current[7]) this.briefingSoundB.stop();
else this.soundStopper = [current[6],0]
}
} else {
this.briefingSoundB.sound = current[4];
if(current[5]) this.briefingSoundB.repeatCount = current[5];
else this.briefingSoundB.repeatCount = 0;
this.briefingSoundB.play();
if(current[6]){
if(!current[7]) this.briefingSoundA.stop();
else this.soundStopper = [current[6],1]
}
}
}
this.briefingIndex++;
}
if(this.briefingCounter<11 && this.briefingFadeIn){
var ind = 10-this.briefingCounter;
var ovn = "cabal_common_briefing_blend"+ind+".png";
setScreenOverlay({name:ovn,width:1024,height:480});
}
this.briefingCounter++;
return;
}
this.shipWillLaunchFromStation = function()
{
this.cleanUp();
if(this.helper.ccl_briefing_fcbs.length) this.helper.fcbRemoveAll();
if(this.briefingSoundA.isPlaying) this.briefingSoundA.stop();
if(this.briefingSoundB.isPlaying) this.briefingSoundB.stop();
delete this.briefing;
}
// API
this.Cabal_Common_ScreenFCB = function(){}
Cabal_Common_ScreenFCB.prototype = {
constructor: Cabal_Common_ScreenFCB,
internalVersion: 15,
ccl_briefing_fcb: 0,
ccl_briefing_fcbs: [],
ccl_briefing_bg: 1,
ccl_defaultDelta: 0.015,
/* Face target.
ent Entity. To be reoriented. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
tar Entity. Target entity. If -1 player.ship is used.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for rotation start.
dampb Number. Linear dampening duration for rotation end.
away Number. Multiplier to head away from target. -1...1. */
fcbFace: function(ent,sub,last,tar,basez,dampa,dampb,away){
var ccl_sum = 0,ccl_ent = ent,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_tar = tar,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb,ccl_away = away;
if(!ent){
if(ccl_sub===-1) ccl_ent = mission.displayModel;
else ccl_ent = mission.displayModel.subEntities[ccl_sub];
if(tar===-1) ccl_tar = player.ship;
else ccl_tar = mission.displayModel.subEntities[tar];
} else {
if(tar===-1) ccl_tar = player.ship;
}
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_tar || !ccl_ent.isValid || !ccl_tar.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1;
if(ccl_basez) bz = 1-1/Math.sqrt(Math.max(Math.abs(ccl_ent.position.z),0.001));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
var targetVector = ccl_tar.heading.subtract(ccl_ent.position).direction();
var angle = (ccl_ent.heading.angleTo(targetVector)*bz*da*db/ccl_last/8)*ccl_away*f;
var cross = ccl_ent.heading.cross(targetVector).direction();
ccl_ent.orientation = ccl_ent.orientation.rotate(cross,-angle);
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Flight.
ent Entity. To be reoriented and/or accelerated. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
rU Number. Rotate vectorUp by rU (radians).
rR Number. Rotate vectorRight by rR /radians).
rF Number. Rotate vectorForward by rF (radians).
velo Number. Multiply vectorForward and set velocity. If -1 no velocity set. */
fcbFlight: function(ent,sub,last,rU,rR,rF,velo){
var ccl_sum = 0,ccl_ent = ent,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_rU = rU,ccl_rR = rR,ccl_rF = rF,ccl_velo = velo;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
if(ccl_sub>-1){
if(ccl_rU) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotate(ccl_ent.subEntities[ccl_sub].vectorUp,ccl_rU*f);
if(ccl_rR) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotate(ccl_ent.subEntities[ccl_sub].vectorRight,ccl_rR*f);
if(ccl_rF) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotate(ccl_ent.subEntities[ccl_sub].vectorForward,ccl_rF*f);
if(ccl_velo!==-1) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorForward.multiply(ccl_velo*f);
} else {
if(ccl_rU) ccl_ent.orientation = ccl_ent.orientation.rotate(ccl_ent.vectorUp,ccl_rU*f);
if(ccl_rR) ccl_ent.orientation = ccl_ent.orientation.rotate(ccl_ent.vectorRight,ccl_rR*f);
if(ccl_rF) ccl_ent.orientation = ccl_ent.orientation.rotate(ccl_ent.vectorForward,ccl_rF*f);
if(ccl_velo!==-1) ccl_ent.velocity = ccl_ent.vectorForward.multiply(ccl_velo*f);
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* FlightTo.
ent mission.displayModel.subentity. To be reoriented and/or accelerated.
tar mission.displayModel.subentity. Target.position
last Number. Duration for fcb.
dampa Number. Linear dampening duration for rotation start.
dampb Number. Linear dampening duration for rotation end.
mul Number. Multiplier for rotation.
velo Number. Multiply vectorForward and set velocity.
offset Vector/Array. Offset position for target. */
fcbFlightTo: function(ent,tar,last,dampa,dampb,mul,velo,offset){
var ccl_sum = 0,ccl_ent = mission.displayModel.subEntities[ent],ccl_tar = mission.displayModel.subEntities[tar],ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_dampa = dampa,ccl_dampb = dampb,ccl_mul = mul,ccl_velo = velo,ccl_offset = new Vector3D(offset);
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_tar || !ccl_ent.isValid || !ccl_tar.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var da = 1,db = 1;
if(ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
var targetVector = ccl_tar.position.add(ccl_offset).subtract(ccl_ent.position).direction();
var angle = (ccl_ent.heading.angleTo(targetVector)*da*db/ccl_mul)*f;
var cross = ccl_ent.heading.cross(targetVector).direction();
ccl_ent.orientation = ccl_ent.orientation.rotate(cross,-angle);
if(ccl_velo!==-1){
var s = ccl_tar.position.add(ccl_offset).distanceTo(ccl_ent.position);
if(s<ccl_ent.collisionRadius){ccl_sum=9999999; return;}
var c = ccl_tar.collisionRadius*2;
var m = 1;
if(s<c) m = 1/Math.sqrt(c/s);
ccl_ent.velocity = ccl_ent.vectorForward.multiply(ccl_velo*m*f);
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Forward KI for revolution joints
start Number. Subentity #
end Number. Subentity #
last Number. Duration for fcb.
joints Array. Vectors for connection points
angles Array. Max angle (dot product) before reorientation starts
*/
fcbKIRevolution: function(start,end,last,joints,angles){
var ccl_sum=0,ccl_substart=start+1,ccl_subend=end+1,ccl_last=last,ccl_delta=this.ccl_defaultDelta,ccl_joints=joints,ccl_angles=angles;
var ccl_ent = mission.displayModel,ccl_stepBack = [];
for(var o=0;o<ccl_subend-ccl_substart;o++) ccl_stepBack.push(0);
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var vtr;
for(var i=ccl_substart;i<ccl_subend;i++){
var offset = new Vector3D(ccl_joints[i-1]),n0 = ccl_ent.subEntities[i-1],n1=ccl_ent.subEntities[i];
var vt0 = n0.vectorForward,vt1=n1.vectorForward;
var dt = vt0.dot(vt1);
if(dt<ccl_angles[i-1] || ccl_stepBack[i]){
var vt = n0.position.subtract(n1.position).direction();
var angle = vt1.angleTo(vt)*0.01*f;
var cross = vt1.cross(vt).direction();
n1.orientation = n1.orientation.rotate(cross,angle);
ccl_stepBack[i] = 1;
}
if(dt>0.999) ccl_stepBack[i] = 0;
vtr = offset.rotateBy(n0.orientation);
n1.position = vtr.add(n0.position);
if(n0.velocity.magnitude()) n1.velocity=n0.velocity;
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Pseudospeed.
ent Entity. To be accelerated. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
velo Number. Multiply vectorForward and set velocity.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for velo start.
dampb Number. Linear dampening duration for velo end. */
fcbModelSpeed: function(ent,sub,last,velo,basez,dampa,dampb){
var ccl_sum = 0,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_ent = ent,ccl_velo = velo,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1;
if(ccl_basez) bz = Math.sqrt(Math.abs(ccl_ent.position.z));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_sub>-1) ccl_ent.subEntities[sub].velocity = ccl_ent.vectorForward.multiply((ccl_velo*bz*da*db)*f);
else ccl_ent.velocity = ccl_ent.vectorForward.multiply((ccl_velo*bz*da*db)*f);
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Velocities.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
mU Number. Multiplier vectorUp.
mR Number. Multiplier vectorRight.
mF Number. Multiplier vectorForward.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbModelVelo: function(ent,sub,last,mU,mR,mF,basez,dampa,dampb){
var ccl_sum = 0,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_mU = mU,ccl_mR = mR,ccl_mF = mF,ccl_ent = ent,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1;
if(ccl_basez) bz = Math.sqrt(Math.abs(ccl_ent.position.z));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_sub>-1){
if(ccl_mU) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorUp.multiply((ccl_mU*bz*da*db)*f);
if(ccl_mR) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorRight.multiply((ccl_mR*bz*da*db)*f);
if(ccl_mF) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorForward.multiply((ccl_mF*bz*da*db)*f);
} else {
if(ccl_mU) ccl_ent.velocity = ccl_ent.vectorUp.multiply((ccl_mU*bz*da*db)*f);
if(ccl_mR) ccl_ent.velocity = ccl_ent.vectorRight.multiply((ccl_mR*bz*da*db)*f);
if(ccl_mF) ccl_ent.velocity = ccl_ent.vectorForward.multiply((ccl_mF*bz*da*db)*f);
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Velocities.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
mU Number. Multiplier vectorUp.
mR Number. Multiplier vectorRight.
mF Number. Multiplier vectorForward.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end.
tar SubEntity.
offset Vector/Array. Offset for target position. */
fcbModelVeloTo: function(ent,sub,last,mU,mR,mF,basez,dampa,dampb,tar,offset){
var ccl_sum = 0,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_mU = mU,ccl_mR = mR,ccl_mF = mF,ccl_ent = ent,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb,ccl_tar = mission.displayModel.subEntities[tar],ccl_offset=offset;
if(!ent) ccl_ent = mission.displayModel;
else ccl_ent = mission.displayModel.subEntity[ent];
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1;
if(ccl_basez) bz = Math.sqrt(Math.abs(ccl_ent.position.z));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_sub>-1){
if(ccl_mU) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorUp.multiply((ccl_mU*bz*da*db)*f);
if(ccl_mR) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorRight.multiply((ccl_mR*bz*da*db)*f);
if(ccl_mF) ccl_ent.subEntities[ccl_sub].velocity = ccl_ent.subEntities[ccl_sub].vectorForward.multiply((ccl_mF*bz*da*db)*f);
} else {
if(ccl_mU) ccl_ent.velocity = ccl_ent.vectorUp.multiply((ccl_mU*bz*da*db)*f);
if(ccl_mR) ccl_ent.velocity = ccl_ent.vectorRight.multiply((ccl_mR*bz*da*db)*f);
if(ccl_mF) ccl_ent.velocity = ccl_ent.vectorForward.multiply((ccl_mF*bz*da*db)*f);
}
var s = ccl_tar.position.add(ccl_offset).distanceTo(ccl_ent.subEntities[ccl_sub].position);
if(s<ccl_ent.subEntities[ccl_sub].collisionRadius*2){ccl_sum=9999999;}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Rotation.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
rX Number. Radians X.
rY Number. Radians Y.
rZ Number. Radians Z.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbRotation: function(ent,sub,last,rX,rY,rZ,basez,dampa,dampb){
var ccl_sum = 0,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_rX = rX,ccl_rY = rY,ccl_rZ = rZ,ccl_ent = ent,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1;
if(ccl_basez) bz = Math.sqrt(Math.abs(ccl_ent.position.z));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_sub>-1){
if(ccl_rX) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotateX((ccl_rX*bz*da*db)*f);
if(ccl_rY) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotateY((ccl_rY*bz*da*db)*f);
if(ccl_rZ) ccl_ent.subEntities[ccl_sub].orientation = ccl_ent.subEntities[ccl_sub].orientation.rotateZ((ccl_rZ*bz*da*db)*f);
} else {
if(ccl_rX) ccl_ent.orientation = ccl_ent.orientation.rotateX((ccl_rX*bz*da*db)*f);
if(ccl_rY) ccl_ent.orientation = ccl_ent.orientation.rotateY((ccl_rY*bz*da*db)*f);
if(ccl_rZ) ccl_ent.orientation = ccl_ent.orientation.rotateZ((ccl_rZ*bz*da*db)*f);
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Preserve orientation/position.
ent Entity. To be reoriented. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
tar Entity. Target subEntity.
dist Boolean. Keep its distance.
inheritFE Boolean. Bind fuel and energy too.
swap Boolean. Flip orientation. */
fcbSetBinding: function(ent,sub,last,tar,dist,inheritFE,swap){
var ccl_sum = 0,ccl_ent = ent,ccl_sub = sub,ccl_last = last,ccl_tar = tar,ccl_dist = new Vector3D(),ccl_inherit = inheritFE,ccl_swap = swap;
if(ccl_sub===-1) ccl_ent = mission.displayModel;
else ccl_ent = mission.displayModel.subEntities[ccl_sub];
if(tar===-1) ccl_tar = mission.displayModel;
else ccl_tar = mission.displayModel.subEntities[tar];
if(swap) ccl_swap = ccl_ent.orientation;
if(dist) ccl_dist = ccl_tar.position.subtract(ccl_ent.position);
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_tar || !ccl_ent.isValid || !ccl_tar.isValid) return;
ccl_sum += delta;
if(ccl_sum>=ccl_last) return;
var p = ccl_tar.position;
var o = ccl_tar.orientation;
if(ccl_dist) p = p.subtract(ccl_dist.rotateBy(o));
if(ccl_swap) o = o.rotate(ccl_tar.vectorUp,-Math.PI);
ccl_ent.orientation = o;
ccl_ent.position = p;
if(ccl_inherit){
ccl_ent.energy = ccl_tar.energy;
ccl_ent.fuel = ccl_tar.fuel;
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Set Property
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
prop String. Property name.
value Value for the property. If last specified current value added last times.
last Number. Duration for fcb.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbSetProp: function(ent,sub,prop,value,last,dampa,dampb){
var ccl_ent = ent;
if(!ent) ccl_ent = mission.displayModel;
if(!last){
if(sub>-1) ccl_ent.subEntities[sub][prop] = value;
else ccl_ent[prop] = value;
} else {
var ccl_sum = 0,ccl_sub = sub,ccl_last = last,ccl_prop = prop,ccl_value = value,ccl_dampa = dampa,ccl_dampb = dampb,ccl_delta=this.ccl_defaultDelta;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var da = 1,db = 1;
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_sub>-1) ccl_ent.subEntities[ccl_sub][ccl_prop] += ccl_value;
else ccl_ent[ccl_prop] += ccl_value*f;
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
}
return;
},
/* Walk.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
steps Number. Divider for duration.
movez Number.
friction Number. Modifier for Y movement
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbWalk: function(ent,sub,last,steps,movez,friction,dampa,dampb){
var ccl_sum = 0,ccl_ent = ent,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_dampa = dampa,ccl_dampb = dampb,ccl_fac = last/steps,ccl_movez = movez,ccl_friction = friction;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var friction = 0,da = 1,db = 1,mf = 1;
if(ccl_friction){
friction = Math.cos(ccl_last*ccl_fac*ccl_sum*ccl_friction);
var abs = Math.abs(friction);
abs = abs/((1/0.9-2)*(1-abs)+1); // Bias
friction *= abs*0.065;
}
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
mf = 1+(da*db);
if(ccl_sub>-1) ccl_ent.subEntities[ccl_sub].position = ccl_ent.subEntities[ccl_sub].position.subtract([0,friction,ccl_movez*mf*f]);
else ccl_ent.position = ccl_ent.position.subtract([0,friction,ccl_movez*mf*f]);
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Zoom.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
last Number. Duration for fcb.
amz Number. Multiplier for Z.
basez Boolean. If true Z position will be taken into account.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbZoom: function(ent,sub,last,amz,basez,dampa,dampb){
var ccl_sum = 0,ccl_ent = ent,ccl_sub = sub,ccl_last = last,ccl_delta=this.ccl_defaultDelta,ccl_amz = amz,ccl_basez = basez,ccl_dampa = dampa,ccl_dampb = dampb;
if(!ent) ccl_ent = mission.displayModel;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_ent || !ccl_ent.isValid) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var bz = 1,da = 1,db = 1,mf = 1;
if(ccl_basez) bz = 1-1/Math.sqrt(Math.max(Math.abs(ccl_ent.position.z),0.001));
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_amz>1) mf = 1+(da*db*bz*(ccl_amz%1));
else mf = 1-(f*da*db*bz*(1%ccl_amz));
if(ccl_sub>-1){
var pos = ccl_ent.subEntities[ccl_sub].position.multiply(mf);
ccl_ent.subEntities[ccl_sub].position = pos;
} else {
var pos = ccl_ent.position.multiply(mf);
ccl_ent.position = pos;
}
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Zoom background.
bg String. Filename with extension
last Number. Duration for fcb.
w Number. Dimension width.
h Number. Dimension height.
factor Number. Multiplier Z.
dampa Number. Linear dampening duration for start.
dampb Number. Linear dampening duration for end. */
fcbZoomBackground: function(bg,last,w,h,factor,dampa,dampb){
var ccl_bgf = this.ccl_briefing_bg;
var ccl_sum = 0,ccl_bg = bg,ccl_delta=this.ccl_defaultDelta,ccl_w = w*ccl_bgf,ccl_h = h*ccl_bgf,ccl_last = last,ccl_factor = factor,ccl_dampa = dampa,ccl_dampb = dampb;
this.ccl_briefing_bg *= factor;
this.ccl_briefing_fcb = addFrameCallback(function(delta){
if(!delta || !ccl_bg) return;
var f=1-(ccl_delta-delta);
ccl_sum += (delta*f);
if(ccl_sum>=ccl_last) return;
var da = 1,db = 1,mf = 1;
if(ccl_dampa && ccl_sum<ccl_dampa) da = 1-((ccl_dampa-ccl_sum)/ccl_dampa);
if(ccl_dampb && ccl_sum>ccl_last-ccl_dampb) db = (ccl_last-ccl_sum)/ccl_dampb;
if(ccl_factor>1) mf = 1+(da*db*(ccl_factor%1));
else mf = 1-(f*da*db*(1%ccl_factor));
setScreenBackground({name:bg,width:ccl_w*mf,height:ccl_h*mf});
return;
});
this.ccl_briefing_fcbs.push(this.ccl_briefing_fcb);
return;
},
/* Check fcbs and log them. */
fcbCheckAll: function(){
if(!this.ccl_briefing_fcbs.length) return(false);
for(var i=0;i<this.ccl_briefing_fcbs.length;i++){
if(isValidFrameCallback(this.ccl_briefing_fcbs[i])) log("fcbCheck","valid i:"+i+" fcb:"+this.ccl_briefing_fcbs[i]+" typeof:"+typeof(this.ccl_briefing_fcbs[i]));
else log("fcbCheck","invalid i:"+i);
}
return(true);
},
/* Clean fcbs. */
fcbRemoveAll: function(){
if(!this.ccl_briefing_fcbs.length) return(false);
for(var i=0;i<this.ccl_briefing_fcbs.length;i++){
if(isValidFrameCallback(this.ccl_briefing_fcbs[i])) removeFrameCallback(this.ccl_briefing_fcbs[i]);
}
this.ccl_briefing_fcb = 0;
this.ccl_briefing_fcbs = [];
this.ccl_briefing_bg = 1;
return(true);
},
/* Stop velocity.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub]. */
stopVelo: function(ent,sub){
var ccl_ent = ent;
if(!ent) ccl_ent = mission.displayModel;
if(sub>-1) ccl_ent.subEntities[sub].velocity = [0,0,0];
else ccl_ent.velocity = [0,0,0];
return;
},
/* Set background image.
png Filename. */
reBackground: function(png){
setScreenBackground(png);
return;
},
/* Set overlay image.
png Filename. */
reOverlay: function(png){
setScreenOverlay(png);
return;
},
/* Set position.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
pos Vector. */
rePosition: function(ent,sub,pos){
var ccl_ent = ent;
if(!ent) ccl_ent = mission.displayModel;
if(sub>-1) ccl_ent.subEntities[sub].position = pos;
else ccl_ent.position = pos;
return;
},
/* Set orientation.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
ori Quaternion. */
reOrient: function(ent,sub,ori){
var ccl_ent = ent;
if(!ent) ccl_ent = mission.displayModel;
if(sub>-1) ccl_ent.subEntities[sub].orientation = ori;
else ccl_ent.orientation = ori;
return;
},
/* Set materials and/or shaders.
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
mat materials object.
sha shader object. */
reTexture: function(ent,sub,mat,sha){
var ccl_ent = ent;
if(!ent) ccl_ent = mission.displayModel;
if(sub>-1) ccl_ent.subEntities[sub].setMaterials(mat,sha);
else ccl_ent.setMaterials(mat,sha);
return;
},
/* Set Shader properties
ent Entity. If not specified mission.displayModel.
sub SubEntity. If -1 main entity is used, otherwise ent.subEntities[sub].
tex Array. Textures.
uni Array. Property names.
values Array. Values for the property. */
reShaderProps: function(ent,sub,tex,uni,values){
var ccl_ent = ent,a,b,flagM;
if(!ent) ccl_ent = mission.displayModel;
if(sub>-1) a = ccl_ent.subEntities[sub].getShaders();
else a = ccl_ent.getShaders();
b = Object.keys(a);
if(!b.length){
if(sub>-1) a = ccl_ent.subEntities[sub].getMaterials();
else a = ccl_ent.getMaterials();
flagM = 1;
b = Object.keys(a);
}
if(!b.length) return;
if(tex.length) for(var i=0;i<tex.length;i++) a[b[0]].textures=tex;
if(uni.length) for(var i=0;i<uni.length;i++) a[b[0]].uniforms[uni[i]].value=values[i];
if(flagM){
if(sub>-1) ccl_ent.subEntities[sub].setMaterials(a);
else ccl_ent.setMaterials(a);
} else {
if(sub>-1) ccl_ent.subEntities[sub].setShaders(a);
else ccl_ent.setShaders(a);
}
return;
},
/* Missionscreen model corner positioning
level Number. Works best with values between 0 and 0.35.
signx Number. Used as sign mantissa (-1...1) for X axis.
signy Number. Used as sign mantissa (-1...1) for Y axis.
further Number. Multiplier for Z axis. Defaults to 1.3. */
screenCornerPos: function(level,signx,signy,further){
var pos = mission.displayModel.position,w = 1024/oolite.gameSettings.gameWindow.width,h = 768/oolite.gameSettings.gameWindow.height;
pos.x = level*pos.z*signx;
pos.y = level*pos.z*0.75*signy;
if(further) pos.z *= further;
else pos.z *= 1.3;
var wh = w/h;
pos = pos.add([w*wh-1,h*wh-1,0]);
mission.displayModel.position=pos;
return;
}
};
|
Scripts/Cabal_Common_Comms.js |
"use strict";
this.name = "Cabal_Common_Comms";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Secure comms channels - controlling script.";
this.version = "1.7.2";
this.startUp = function()
{
delete this.startUp;
this.helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
this.commChannels = [{display:"Discard"},{display:"Open channel"}];
this.commChannelChanged = true;
this.patchedIDs = [];
};
/* function: addToComm()
Parameters:
display - String. Used for onscreen display.
who - Entity/String. The entity or worldScript.
ent - Boolean. Must be true for entities, blank for worldScripts.
pID - Number/String. Must be entityPersonality for entities and this.name for worldScripts.
callback - String. The function that handles the actions.
noDist - Boolean. Optional. If true keep entity entry if out of scanner range.
react - Array. Holds the names of the actions.
*/
this.addToComm = function(obj)
{
if(obj){
if(!obj.who || !obj.display || !obj.callback || !obj.react || !obj.hasOwnProperty("pID")){
log(this.name,this.name+" **ERROR: Script has passed invalid settings!");
var prop;
for(prop in obj){log(this.name,"Settings: "+prop+" : "+obj[prop]);}
return(false);
}
this.commChannels.push(obj);
if(obj.pID) this.patchedIDs.push(obj.pID);
this.commChannelChanged = true;
this.checkEQ('EQ_CABAL_COMMON_COMM');
return(true);
}
return(false);
};
this.commsMessageReceived = function(message,sender)
{
if(sender && sender.scriptInfo && sender.scriptInfo.ccl_secureChannel){
if(this.patchedIDs.indexOf(sender.entityPersonality)===-1){
var channel = sender.scriptInfo.ccl_secureChannel;
if(sender.script[channel]) this.checkEQ('EQ_CABAL_COMMON_COMM');
}
}
};
/* function: removeFromComm()
Removes object from the list.
> worldScripts.Cabal_Common_Comms.removeFromComm(this.myComm);
*/
this.removeFromComm = function(obj)
{
if(obj){
this.patchedIDs = this.helper.arrRemoveByValue(this.patchedIDs,obj.pID);
this.commChannels = this.helper.arrRemoveByValue(this.commChannels,obj);
this.commChannelChanged = true;
return(true);
}
return(false);
};
/* function: changeChoicesComm()
Changes the stored actions for a specific entry.
*/
this.changeChoicesComm = function(pID,newSet)
{
if(this.patchedIDs.indexOf(pID)===-1) return(false);
var l = this.commChannels.length;
if(l>2){
while(l--){
if(this.commChannels[l].pID===pID){
this.commChannels[l].react=newSet;
this.commChannelChanged = true;
this.checkEQ('EQ_CABAL_COMMON_COMM');
return(true);
}
}
}
return(false);
};
this.shipWillEnterWitchspace = function()
{
this.cleanTimer(); // Avoid eating time
this.commChannels = [{display:"Discard"},{display:"Open channel"}];
this.commChannelChanged = false;
if(player.ship.equipmentStatus('EQ_CABAL_COMMON_COMM')!=='EQUIPMENT_UNAVAILABLE') player.ship.removeEquipment('EQ_CABAL_COMMON_COMM');
};
this.doCleanUpTimer = function()
{
if(!player.ship.isValid) return;
var l = this.commChannels.length;
if(l>2){
while(l--){
if(this.commChannels[l].noDist) continue;
if(this.commChannels[l].ent){
if(this.commChannels[l].who.isValid && this.commChannels[l].who.position.distanceTo(player.ship.position)<25600) continue;
else {
if(this.commChannels[l].pID) this.patchedIDs = this.helper.arrRemoveByValue(this.patchedIDs,this.commChannels[l].pID);
this.commChannels = this.helper.arrRemoveByValue(this.commChannels,this.commChannels[l]);
this.commChannelChanged = true;
break; // Avoid eating time
}
} else if(this.commChannels[l].eID){
if(this.commChannels[l].eID.isValid && this.commChannels[l].eID.position.distanceTo(player.ship.position)<25600) continue;
else {
if(this.commChannels[l].pID) this.patchedIDs = this.helper.arrRemoveByValue(this.patchedIDs,this.commChannels[l].pID);
this.commChannels = this.helper.arrRemoveByValue(this.commChannels,this.commChannels[l]);
this.commChannelChanged = true;
break; // Avoid eating time
}
}
}
} else this.cleanTimer(); // Avoid eating time
return;
};
this.equipmentDamaged = this.equipmentDestroyed = function(equipmentKey)
{
if(!player.ship.isValid) return;
if(equipmentKey==='EQ_CABAL_COMMON_COMM') this.checkEQ('EQ_CABAL_COMMON_COMM');
};
this.checkEQ = function()
{
if(player.ship.equipmentStatus('EQ_CABAL_COMMON_COMM')==='EQUIPMENT_UNAVAILABLE') player.ship.awardEquipment('EQ_CABAL_COMMON_COMM');
else if(player.ship.equipmentStatus('EQ_CABAL_COMMON_COMM')==='EQUIPMENT_DAMAGED') player.ship.setEquipmentStatus('EQ_CABAL_COMMON_COMM','EQUIPMENT_OK');
if(!this.cleanUpTimer) this.cleanUpTimer = new Timer(this,this.doCleanUpTimer,0,25);
else this.cleanUpTimer.start();
return;
};
this.shipDied = function()
{
this.cleanTimer();
};
this.cleanTimer = function()
{
if(this.cleanUpTimer){
this.cleanUpTimer.stop();
delete this.cleanUpTimer;
}
return;
};
|
Scripts/Cabal_Common_Functions.js |
"use strict";
this.name = "Cabal_Common_Functions";
this.author = "Cmd.Cheyd, PhantorGorth and Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Libraryscript";
this.version = "1.7";
/* class: Cabal_Common
This is the main class for the helper library with its members. Scripts can instantiate a copy, e.g.
> this.myHelper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
*/
this.Cabal_Common = function(){}
Cabal_Common.prototype = {
constructor: Cabal_Common,
// Property to give OXPs a chance to check the required lib min. version easily.
internalVersion: 15,
// v1.77 spacer
spacer: String.fromCharCode(31),
spacerWidth: defaultFont.measureString(String.fromCharCode(31)),
spacerStandard: String.fromCharCode(32),
spacerWidthStandard: defaultFont.measureString(String.fromCharCode(32)),
/* method: baseChange(). Changes the base of n.
Parameters:
n - Number. To be changed.
to - Number. Base which should be used to convert to. Usually 2,10 or 16.
from - Number. Optional. Base from which should be converted. Usually 2,10 or 16.
Returns:
str - String. Base changed.
Author: Dr.J R Stockton.
*/
baseChange: function(n,to,from){
return(parseInt(n,from || 10).toString(to));
},
/* method: clamp()
Clamps value to max...min.
Paramaters:
value - Number. To be clamped.
max - Number. Maximum.
min - Number. Minimum.
Returns:
n - Number. Clamped.
*/
clamp: function(value,max,min){
return(((value>max)?max:(value<min)?min:value));
},
/* method: msbPos()
Returns position of most significant bit of n.
Paramaters:
n - Number. To be evaluated.
Returns:
n - Number. The position of the most significant bit or 0 (zero).
Author: Dr.J R Stockton.
*/
msbPos: function(n){
var e = 15;
for(var r=8;r>0;r>>=1){
e = (n<1<<e)?e-r:e+r;
}
return((n<1<<e)?e:e+1);
},
/* method: nBitsUsed()
Returns number of bits set in n. If n<0 a bitwise NOT will be applied before execution.
Parameters:
n - Number. To be evaluated.
Returns:
e - Number. The counted number of bits set to 1.
*/
nBitsUsed: function(n){
var e = 0;
if(n<0) n = ~n;
while(n>0){
if((n&1)) e++;
n>>=1;
}
return(e);
},
/* method: num2Prec()
Returns rounded number with specified precision. Unlike .toFixed() or .toPrecision() trailing zeros are capped.
Parameters:
x - Number. To be evaluated.
p - Number. Decimals.
Returns:
e - Number. The rounded number.
*/
num2Prec: function(x,p){
if(!x) return 0;
var n = Math.pow(10,p);
return Math.round(x*n)/n;
},
/* method: pseudoRand()
LCG (Linear congruential generator) pseudo-random number generator with salt (and pepper).
Can be used to generate deterministic unique values, e.g. to decide if a specific entity should be spawned.
Parameters:
salt - Number. This is used to generate a pseudo random number.
mode - Boolean. Optional. If specified and true the returned value is integer (Math.floor(n*100)).
Returns:
n - Number. If no mode specified in range [0...1] otherwise [0...100].
Author: Jens Ayrton (Ahruman).
*/
pseudoRand: function(salt,mode){
var n = system.scrambledPseudoRandomNumber(salt);
if(mode) n = Math.floor(n*100);
return(n);
},
/* method: rand()
Random number in range 0...n.
Parameters:
n - Number. Maximum value.
Returns:
n - Number. Returns the random Number.
Author: Dr.J R Stockton.
*/
rand: function(n){
return(n*(Math.random()%1) | 0);
},
/* method: randSpan()
Random number in range minN...maxN.
Paramaters:
minN - Number. Minimum.
maxN - Number. Maximum.
Returns:
n - Number. The newly generated random Number.
Author: Dr.J R Stockton.
*/
randSpan: function(minN,maxN){
return minN+this.rand(maxN-minN+1);
},
/* method: strAddAlignedText()
Returns padded text for a single line.
Parameters:
text - String.
alignment - String. Optional. Either L, C or R. Default L.
Returns:
str - String. Padded text.
Author: Thargoid */
strAddAlignedText: function(text,alignment){
if(!text) return("");
var validAlignment = "LCR",textWidth,padCount,padString;
if(!alignment || validAlignment.indexOf(alignment)===-1) alignment = "L";
alignment = alignment.toUpperCase();
textWidth = defaultFont.measureString(text);
if(textWidth>32 || alignment==="L") return(text);
padCount = Math.floor((32-textWidth)/this.spacerWidth);
if(alignment==="C") padCount = Math.floor(padCount/2);
padString = this.strCreatePadString(padCount);
return(padString+text);
},
/* method: strAddEdgeText()
Returns two edge-aligned columns, one on the left and the other on the right for a single line.
Parameters:
leftText - String.
rightText - String.
Returns:
str - String. Aligned text.
Author: Thargoid */
strAddEdgeText: function(leftText,rightText){
if(!rightText){
if(leftText) return(leftText);
}
var textWidth = defaultFont.measureString(leftText)+defaultFont.measureString(rightText);
if(textWidth>32){
log("CCL strAdEdgeText","Text "+leftText+" plus "+rightText+" is too long for a single screen line!");
return("");
}
var padCount = Math.floor((32-textWidth)/this.spacerWidth);
var padString = this.strCreatePadString(padCount);
return(leftText+padString+rightText);
},
/* method: strAddIndentedText()
Returns indented line of text by the given distance (in ems) from the left.
Parameters:
text - String.
indent - Number.
Returns:
str - String. Indented text.
Author: Thargoid */
strAddIndentedText: function(text,indent){
if(!text) return("");
var textWidth = defaultFont.measureString(text);
if(textWidth>32 || typeof(indent)!=='number' || indent<0 || indent>31.8) return(text);
var padCount = Math.floor(indent/this.spacerWidth);
var padString = this.strCreatePadString(padCount);
return(padString+text);
},
/* method: strAdd2Columns()
Returns line of text with two columns indented from the left margin by the given amount (in ems, 0-32).
Parameters:
leftText - String.
leftIndent - Number.
rightText - String.
rightIndent - Number.
Returns:
str - String. Text with 2 columns.
Author: Thargoid */
strAdd2Columns: function(leftText,leftIndent,rightText,rightIndent){
if(!leftText || !rightText || typeof(leftIndent)!=='number' || typeof(rightIndent)!=='number' || leftIndent>rightIndent || leftIndent<0 || leftIndent>31.8 || rightIndent<0 || rightIndent>31.8) return("");
var textWidth = defaultFont.measureString(leftText)+defaultFont.measureString(rightText);
if(textWidth>32){
log("CCL strAdd2Columns","2 column text is too long for a single screen line!");
return("");
}
var leftPad = this.strCreatePadString(Math.floor(leftIndent/this.spacerWidth));
var rightCount = rightIndent-(leftIndent+defaultFont.measureString(rightText));
var rightPad;
if(rightCount<=0){
log("CCL strAdd2Columns","Left column overrun!");
rightPad = "";
} else rightPad = this.strCreatePadString(Math.floor(rightCount/this.spacerWidth));
return(leftPad+leftText+rightPad+rightText);
},
/* method: strAdd3Columns()
Returns text with three columns, left, centre and right.
Parameters:
leftText - String.
leftIndent - Number.
centreText - String.
centreIndent- Number.
rightText - String.
rightIndent - Number.
Returns:
str - String. Text with 3 columns.
Author: Thargoid */
strAdd3Columns: function(leftText,leftIndent,centreText,centreIndent,rightText,rightIndent){
if(!leftText || !centreText || !rightText || typeof(leftIndent)!=='number' || typeof(centreIndent)!=='number' || typeof(rightIndent)!=='number' || leftIndent>centreIndent || centreIndent>rightIndent || leftIndent<0 || leftIndent>32 || centreIndent<0 || centreIndent>32 || rightIndent<0 || rightIndent>32) return("");
var textWidth = defaultFont.measureString(leftText)+defaultFont.measureString(centreText)+defaultFont.measureString(rightText);
if(textWidth>32){
log("CCL atrAdd3Columns","3 column text is too long for a single screen line!");
return("");
}
var leftPad = this.strCreatePadString(Math.floor(leftIndent/this.spacerWidth));
var centreCount = centreIndent-(leftIndent+defaultFont.measureString(centreText));
var centrePad,rightPad;
if(centreCount<=0){
log("CCL strAdd3Columns","Left column overrun!");
centrePad = "";
} else centrePad = this.strCreatePadString(Math.floor(centreCount/this.spacerWidth));
var rightCount = rightIndent-(centreIndent+defaultFont.measureString(rightText));
if(rightCount<=0){
log("CCL strAdd3Columns","Centre column overrun!");
rightPad = "";
} else rightPad = this.strCreatePadString(Math.floor(rightCount/this.spacerWidth));
return(leftPad+leftText+centrePad+centreText+rightPad+rightText);
},
/* method: strCompareVersion()
Compares version strings (like "2.0.3") against each other and returns number.
It also strips pre/suffixes like "Build" or "Beta".
Parameters:
strA - String. Actual version.
strB - String. Version to be compared against.
Returns:
0 - Number. If strA < strB
1 - Number. If strA = strB
2 - Number. If strA > strB
*/
strCompareVersion: function(strA,strB){
var x = strA.split('.'),y = strB.split('.');
if(isNaN(parseInt(x[0],null))){
var n = x[0].search(/\d+/);
if(n!==-1) x[0] = parseFloat(x[0].substr(n),null);
else x.shift();
}
var xl = x.length,yl = y.length;
if(!xl) return(0);
for(var i=0;i<yl;i++){
if(xl<=i) return(0);
if(parseInt(x[i],null)>y[i]) return(2);
if(parseInt(x[i],null)<y[i]) return(0);
}
return(1);
},
/* Internal method
Author: Thargoid */
strCreatePadString: function(count){
var padString = "";
if(!count || count<=0) return(padString);
var counter = 0;
for(counter=0;counter<count;counter++){
padString = padString+this.spacer;
}
return(padString);
},
/* method: strEncrypt()
Encrypts string.
Parameters:
str - String. To be encrypted. Minimum length 6 chars.
pwd - String. Password. Minimum length 4 chars.
Returns:
enc_str - String/Boolean. Encrypted string or false.
Author: Terry Yuen.
*/
strEncrypt: function(str,pwd){
if(!str || !pwd || str.length<6 || pwd.length<4){log("Cabal_Common","Parameters error in encrypt."); return(false);}
var prand = "";
for(var i=0;i<pwd.length;i++) prand += pwd.charCodeAt(i).toString();
var sPos = Math.floor(prand.length/5);
var mult = parseInt(prand.charAt(sPos)+prand.charAt(sPos*2)+prand.charAt(sPos*3)+prand.charAt(sPos*4)+prand.charAt(sPos*5),null);
var incr = Math.ceil(pwd.length/2);
var modu = Math.pow(2,31)-1;
if(mult<2){log("Cabal_Common","Algorithm cannot find a suitable hash."); return(false);}
var salt = Math.round(Math.random()*1000000000)%100000000;
prand += salt;
while(prand.length>10) prand = (parseInt(prand.substring(0,10),null)+parseInt(prand.substring(10,prand.length),null)).toString();
prand = (mult*prand+incr)%modu;
var enc_chr = "",enc_str = "";
for(var i=0;i<str.length;i++){
enc_chr = parseInt(str.charCodeAt(i)^Math.floor((prand/modu)*255),null);
if(enc_chr<16) enc_str += "0"+enc_chr.toString(16);
else enc_str += enc_chr.toString(16);
prand = (mult*prand+incr)%modu;
}
salt = salt.toString(16);
while(salt.length<8) salt = "0"+salt;
enc_str += salt;
return(enc_str);
},
/* method: strDecrypt()
Decrypts string.
Parameters:
str - String. To be decrypted. Minimum length 6 chars.
pwd - String. Password. Minimum length 4 chars.
Returns:
dec_str - String/Boolean. Decrypted string or false.
Author: Terry Yuen.
*/
strDecrypt: function(str,pwd){
if(!str || !pwd || str.length<6 || pwd.length<4){log("Cabal_Common","Parameters error."); return(false);}
var prand = "";
for(var i=0;i<pwd.length;i++) prand += pwd.charCodeAt(i).toString();
var sPos = Math.floor(prand.length/5);
var mult = parseInt(prand.charAt(sPos)+prand.charAt(sPos*2)+prand.charAt(sPos*3)+prand.charAt(sPos*4)+prand.charAt(sPos*5),null);
var incr = Math.round(pwd.length/2);
var modu = Math.pow(2,31)-1;
var salt = parseInt(str.substring(str.length-8,str.length),16);
str = str.substring(0,str.length-8);
prand += salt;
while(prand.length>10) prand = (parseInt(prand.substring(0,10),null)+parseInt(prand.substring(10,prand.length),null)).toString();
prand = (mult*prand+incr)%modu;
var enc_chr = "",dec_str = "";
for(var i=0;i<str.length;i+=2){
enc_chr = parseInt(parseInt(str.substring(i,i+2),16)^Math.floor((prand/modu)*255),null);
dec_str += String.fromCharCode(enc_chr);
prand = (mult*prand+incr)%modu;
}
return(dec_str);
},
/* method: strGetCRC()
Simple CRC from string. Does not create unique checksums. It uses Unicodes, but limits every char via &0xff and the output via &0x3fff.
Parameters:
str - String. Which should be used to create a CRC.
Returns:
crc - Number. The CRC.
*/
strGetCRC: function(str){
var crc = 0, i = str.length;
while(i--) crc += (str.charCodeAt(i)&0xff);
return((crc&0x3fff));
},
/* method: strDateFromMinutes()
Takes an integer number of minutes and converts it into a string.
The returned string has the form 'd' days, 'h' hours and 'm' minutes, accomodating all cases of singular, plural, and 0.
Parameters:
minutes - Number. The time in minutes.
Returns:
timeString - String.
Author: Commander McLane.
*/
strDateFromMinutes: function(minutes){
var ago = false;
if(minutes<0) ago = true;
minutes = Math.abs(minutes);
var daysComponent = Math.floor(minutes/24/60);
var hoursComponent = Math.floor((minutes%(24*60))/60);
var minutesComponent = minutes%60;
var timeString = "";
if(daysComponent>0) timeString += daysComponent + " day";
if(daysComponent>1) timeString += "s";
if(timeString!==""){
if(hoursComponent>0 && minutesComponent>0) timeString += ", ";
else if(hoursComponent>0) timeString += " and ";
}
if(hoursComponent>0) timeString += hoursComponent + " hour";
if(hoursComponent>1) timeString += "s";
if(timeString!=="" && minutesComponent>0) timeString += " and ";
if(minutesComponent>0) timeString += minutesComponent + " minute";
if(minutesComponent>1) timeString += "s";
if(timeString==="") timeString = "no time";
if(ago) timeString += " ago";
return timeString;
},
/* method: strDateRelative()
Returns string (e.g. '4 minutes ago').
Parameters:
inSec - Number. In seconds.
Returns:
str - String.
*/
strDateRelative: function(inSec){
var reference = clock.absoluteSeconds,delta,formats,format,i,len;
var sec = 1; var min = 60*sec; var hour = 60*min; var day = 24*hour; var week = 7*day; var year = day*365; var month = year/12;
if(inSec<=0){
delta = reference-(clock.absoluteSeconds+inSec);
formats = [[0.7*min,'just now'],[1.5*min,'a minute ago'],[60*min,'minutes ago',min],[1.5*hour,'an hour ago'],
[0.7*day,'hours ago',hour],[day,'today'],[2*day,'yesterday'],[7*day,'days ago',day],[1.5*week,'a week ago'],
[month,'weeks ago',week],[1.5*month,'a month ago'],[year,'months ago',month],[1.5*year,'a year ago'],
[Number.MAX_VALUE,'years ago',year]];
} else {
delta = (clock.absoluteSeconds+inSec)-reference;
formats = [[0.7*min,'just now'],[1.5*min,'a minute'],[60*min,'minutes',min],[1.5*hour,'an hour'],
[0.7*day,'hours',hour],[day,'today'],[2*day,'tomorrow'],[7*day,'days',day],[1.5*week,'a week'],
[month,'weeks',week],[1.5*month,'a month'],[year,'months',month],[1.5*year,'a year'],
[Number.MAX_VALUE,'years',year]];
}
for(i=-1,len=formats.length;++i<len;){
format = formats[i];
if(delta<format[0]) return format[2] == undefined?format[1]:Math.round(delta/format[2])+' '+format[1];
}
},
/* method: strLZ()
Returns string with a leading zero if n<10.
Parameters:
n - Number. To be evaluated.
Returns:
str - String. With leading zero if necessary.
Author: Dr.J R Stockton.
*/
strLZ: function(n){
return (n!=null&&n<10&&n>=0?"0":"")+n;
},
/* method: strLZZ()
Returns string with a leading zeros if n<100. Uses <strLZ()> as subfunction.
Parameters:
n - Number. To be evaluated.
Returns:
str - String. With leading zeros if necessary.
Author: Dr.J R Stockton.
*/
strLZZ: function(n){
return(n!=null&&n<100&&n>=0?"0"+this.strLZ(n):""+n);
},
/* method: strNLZ()
Returns string with length of len filled with leading zeros.
Parameters:
n - Number. To be evaluated.
len - Number. Length. Maximum is 10.
Returns:
str - String. Filled up with leading zeros.
*/
strNLZ: function(n,len){
var s = n.toString();
if(!len || len<s.length) len = s.length;
if(len && len>10) len = 10;
if(s.length<len) s = ("0000000000"+s).slice(-len);
return s;
},
/* method: strRandom()
Returns random string with length of l.
Parameters:
l - Number. Length.
Returns:
str - String.
*/
strRandom: function(l){
var str = "";
for(var j=0;j<l;j++) str += String.fromCharCode(97+this.rand(26));
return str;
},
/* method: strRandomInt()
Returns random numbered string with length of l.
Parameters:
l - Number. Length in range of 1...9.
Returns:
str - String.
*/
strRandomInt: function(l){
var str = String(1000000000+Math.random()*1000000000 | 0);
return str.substr(0,l);
},
/* method: strScreenSubString()
Formats the string str into lines of at most chrs characters in length.
Parameters:
str - String. To be used.
chrs - Number. The length.
Returns:
out - String. With specified length.
*/
strScreenSubString: function(str,chrs){
var out = "";
for(var d=0;d<(str.length/chrs);d++) out += str.substr(d*chrs,chrs)+"\n";
return(out);
},
/* method: strScreenString()
Splits string in pieces of chrs, with intermediate linebreaks for missionscreens and fills up current line.
If splitting is not possible or a word is longer than chrs, <strScreenSubString()> will be used.
Parameters:
str - String. To be used.
mode - Boolean. Optional. If mode is false or not specified it replaces special signs like linebreaks with spaces.
chrs - Number. Optional. Length. If not specified default of 70 is used.
Returns:
display - String. With linebreaks.
*/
strScreenString: function(str,mode,chrs){
if(!mode) str = str.replace(/[\t\r\f\n\v]/g," ");
if(!chrs) chrs = 70;
var display = "", splob = str.split(" ");
var l = splob.length, temp = "";
if(l<2) display = this.strScreenSubString(str,chrs);
else {
for(var o=0;o<l;o++){
if(splob[o].length>chrs){
display += temp+"\n";
display += this.strScreenSubString(splob[o],chrs);
temp = "";
continue;
}
if(!o && splob[o].length<chrs){
temp = splob[o];
continue;
}
if((temp.length+splob[o].length)<chrs){
if(temp!=="") temp += " "+splob[o];
else temp += splob[o];
} else {
display += temp+"\n";
temp = splob[o];
}
}
if(temp!=="") display += temp;
}
return(display);
},
/* method: strSplitToPhrases()
Splits string into n words phrases.
Parameters:
str - String. To be used.
n - Number. Words.
Returns:
out - Array. Containing Strings with n words per element.
*/
strSplitToPhrases: function(str,n){
var arr = str.split(" ");
var l = arr.length, out = [], sub = "";
for(var o=0;o<l;o++){
if(!arr[o] || arr[o]==="") continue;
if(o>l-n) break;
sub = "";
for(var i=o;i<Math.min(o+n,l);i++){
if(!arr[i] || arr[i]=="") continue;
sub += arr[i]+" ";
}
sub = sub.substr(0,sub.length-1);
out.push(sub);
}
return(out);
},
/* method: strToWidth()
Returns string with specific length based on Oolites font size.
If stringwidth > max it is truncated, otherwise filled up with space or specified chr.
Parameters:
str - String. To be used.
max - Number. Maximum width.
chr - String. Char to be used to fill up if stringwidth < max.
Returns:
str - String. With specified width.
*/
strToWidth: function(str,max,chr){
var l = defaultFont.measureString(str),c,d;
if(chr) c = defaultFont.measureString(chr);
if(l>max){
while(l>max){
str = str.substr(0,str.length-1);
d = defaultFont.measureString(str[str.length-1]);
l -= d;
}
} else {
while(l<max){
if(chr && chr!==" "){
str += chr;
l += c;
} else {
if(max-l>1.7){
str += this.spacerStandard;
l += this.spacerWidthStandard;
} else {
if(max-l>0.1){
str += this.spacer;
l += this.spacerWidth;
} else break;
}
}
}
}
return(str);
},
/* method: strTrim()
Returns trimmed string.
Parameters:
str - String.
Returns:
str - String.
*/
strTrim: function(str){
return(str.replace(/[\b\f\r\n]/g,"").toString().replace(/\s+$|^\s+/g,""));
},
/* method: arrDiff()
Returns difference between two arrays.
Parameters:
ar1 - Array. First.
ar2 - Array. Second.
Returns:
diff - Array. Difference between two arrays.
*/
arrDiff: function(ar1,ar2){
var a=[], diff=[];
for(var i=0;i<ar1.length;i++) a[ar1[i]]=true;
for(var i=0;i<ar2.length;i++){
if(a[ar2[i]]) delete a[ar2[i]];
else a[ar2[i]]=true;
}
return diff;
},
/* method: arrRemoveByValue()
Removes specific entry from array.
Parameters:
arr - Array. From which things should be removed.
val - Object. Value that has to be removed.
Returns:
arr - Array. The cleaned array.
*/
arrRemoveByValue: function(arr,val){
for(var i=0;i<arr.length;i++){
if(arr[i]===val){
arr.splice(i,1);
break;
}
}
return(arr);
},
/* method: arrShuffle()
Returns shuffled array.
Parameters:
arr - Array.
Returns:
SHU - Array.
Author: Dr.J R Stockton.
*/
arrShuffle: function(arr){
var J,K,T,SHU=[].concat(arr);
for(J=SHU.length-1;J>0;J--){
K = this.rand(J+1);
T = SHU[J];
SHU[J] = SHU[K];
SHU[K] = T;
}
return SHU;
},
/* method: arrSortByProperty()
Sort array containing objects by specific property.
Parameters:
arr - Array. To be sorted.
prop - String. Propertyname.
Returns:
what - Array. Sorted by specified property.
*/
arrSortByProperty: function(arr,prop){
function sortByPropName(a,b){
var x = a[prop];
var y = b[prop];
return((x<y)?-1:((x>y)?1:0));
}
arr.sort(sortByPropName);
return(arr);
},
/* method: arrUnique()
Removes duplicates from array.
Parameters:
arr - Array. The input array, from which duplicates are to be removed.
Returns:
r - Array. The cleaned array.
*/
arrUnique: function(arr){
var r = [];
o:for(var i=0,n=arr.length;i<n;i++){
for(var x=0,y=r.length;x<y;x++) if(r[x]==arr[i]) continue o;
r[r.length] = arr[i];
}
return r;
},
/* method: mapCoordsDirection()
Returns the general direction of the target coordinates compared to the current (or specified) system coordinates.
Parameters:
posA - Vector/ID. Map coordinates in LYs or simply a system.ID.
posB - Vector/ID. Optional. Map coordinates in LYs or simply a system.ID. Defaults to current system coordinates.
Returns:
str - String.
Author: Eric Walch.
*/
mapCoordsDirection: function(posA,posB){
if(typeof(posA)==='undefined' || (typeof(posA)==='object' && !posA)) return("current system");
var pos1,pos2,dx,dy,x2,y2;
if(typeof(posA)==='number') pos2 = System.infoForSystem(galaxyNumber,posA).coordinates;
else pos2 = new Vector3D(posA);
if(typeof(posB)==='number') pos1 = System.infoForSystem(galaxyNumber,posB).coordinates;
else if(!posB) pos1 = system.info.coordinates;
else pos1 = new Vector3D(posB);
if(pos1.distanceTo(pos2)<0.00001) return("current system");
dx = pos2.x-pos1.x;
dy = pos2.y-pos1.y;
x2 = Math.abs(dx);
y2 = Math.abs(dy);
if(x2>2.41421*y2) return(dx>0?"east":"west");
if(y2>1.732*x2) return(dy<0?"north":"south");
if(dx>0) return(dy<0?"north-east":"south-east");
return(dy<0?"north-west":"south-west");
},
/* method: oxpVersionTest()
Checks required OXPs and versions. The array is expected to contain two elements for each script and version must be null for legacy scripts!
Parameters:
who - String. Actual scriptname. It's only used to log for which OXP the requirements are not fullfilled.
requires - Array. Holds for every required OXP the scriptname and version. To check only for existance set version to null.
quiet - Boolean. Optional. If true don't log, only check.
Returns:
checked - Boolean.
- false - If a requirement is not fullfilled or OXP is deactivated,
- true - Otherwise.
Note:
The method checks for a property 'deactivated' in OXPs to determine if they are deactived.
*/
oxpVersionTest: function(who,requires,quiet){
var checked = true;
for(var i=0;i<requires.length;i+=2){
if(typeof(worldScripts[requires[i]])==='undefined'){
if(!requires[i+1]){checked = false; if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" not installed.");}
else {checked = false; if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" min. version "+requires[i+1]+" not installed.");}
continue;
} else {
if(requires[i+1] && !this.strCompareVersion(worldScripts[requires[i]].version,requires[i+1])){checked = false;
if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" required min. version "+requires[i+1]+" not found.");
continue;
}
}
if(worldScripts[requires[i]].deactivated) checked = false;
}
return(checked);
},
/* method: oxpVersionTest2Array()
Checks required OXPs and versions. The array is expected to contain two elements for each script and version must be null for legacy scripts!
Parameters:
who - String. Actual scriptname. It's only used to log for which OXP the requirements are not fullfilled.
requires - Array. Holds for every required OXP the scriptname and version. To check only for existance set version to null.
quiet - Boolean. Optional. If true don't log, only check.
Returns:
checked - Array. With values for checked elements of requires.
- 2 - version is greater,
- 1 - version is equal,
- 0 - not installed,
- -1 - OXP is deactivated,
- -2 - version is lower.
*/
oxpVersionTest2Array: function(who,requires,quiet){
var checked = [],check = 0,loop = requires.length;
for(var i=0;i<loop;i+=2){
if(typeof(worldScripts[requires[i]])==='undefined'){
checked.push(0);
if(!requires[i+1]){if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" not installed.");}
else {if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" min. version "+requires[i+1]+" not installed.");}
continue;
} else {
if(worldScripts[requires[i]].deactivated) checked.push(-1);
else if(requires[i+1]){
check = this.strCompareVersion(worldScripts[requires[i]].version,requires[i+1]);
if(!check){
checked.push(-2);
if(!quiet) log("Check",who+" requirement not matched : "+requires[i]+" required min. version "+requires[i+1]+" not found.");
continue;
} else checked.push(check);
}
}
}
return(checked);
},
/* method: entModelView()
Spawns or resets the modelview entity and returns it.
Parameters:
which - String. Optional. Role to be used for modelview. If not specified defaults to 'cabal_common_modelview'.
Returns:
mv - Entity. Returns modelview Entity or null.
*/
entModelView: function(which){
if(!player.ship.docked) return(false);
var mv = null;
if(!which) which = 'cabal_common_modelview';
if(!system.countShipsWithRole(which)) mv = system.addShips(which,1,player.ship.position,5000.0)[0];
else mv = system.shipsWithPrimaryRole(which)[0];
if(mv) mv.AIState = 'GLOBAL';
return(mv);
},
/* method: entFaceEntity()
This function causes ent1 to be reorientated such that it faces ent2. A common use-case is when spawning stations whose docking
tunnel should face another entity, typically the main planet. Reorienting is instantly.
Parameters:
ent1 - Entity. To be reoriented.
ent2 - Entity. To which ent1 should be oriented.
Returns:
nothing.
*/
entFaceEntity: function(ent1,ent2){
var targetVector = ent2.position.subtract(ent1.position).direction();
var angle = ent1.heading.angleTo(targetVector);
var cross = ent1.heading.cross(targetVector).direction();
ent1.orientation = ent1.orientation.rotate(cross,-angle);
return;
},
/* method: entScreenCornerPos()
Missionscreen model corner positioning.
Parameters:
level - Number. Works best with values between 0 and 0.35.
signx - Number. Used as sign mantissa (-1...1) for X axis.
signy - Number. Used as sign mantissa (-1...1) for Y axis.
further - Number. Multiplier for Z axis. Defaults to 1.3.
Returns:
nothing.
*/
entScreenCornerPos: function(level,signx,signy,further){
var pos = mission.displayModel.position,w = 1024/oolite.gameSettings.gameWindow.width,h = 768/oolite.gameSettings.gameWindow.height;
pos.x = level*pos.z*signx;
pos.y = level*pos.z*0.75*signy;
if(further) pos.z *= further;
else pos.z *= 1.3;
var wh = w/h;
pos = pos.add([w*wh-1,h*wh-1,0]);
mission.displayModel.position=pos;
return;
},
/* method: screenGCD()
Returns greatest common denominator. Subfunction.
Parameters:
a - Number.
b - Number.
Returns:
n - Number.
*/
screenGCD: function(a,b){
return((b==0)?a:this.screenGCD(b,a%b));
},
/* method: screenAspect()
Returns aspect ratio. Subfunction.
Parameters:
w - Number. Width.
h - Number. Height.
d - Number. Denominator.
Returns:
n - Number.
*/
screenAspect: function(w,h,d){
if(!d) d = this.screenGCD(w,h);
return((w/d)/(h/d));
},
/* method: screenChecks()
Returns array with width,height,denominator and aspect ratio.
Parameters:
w - Number. Width. Optional.
h - Number. Height. Optional.
Returns:
a - Array.
*/
screenChecks: function(w,h){
if(!w) w = oolite.gameSettings.gameWindow.width;
if(!h) h = oolite.gameSettings.gameWindow.height;
var d = this.screenGCD(w,h);
var a = this.screenAspect(w,h,d);
return([w,h,d,a]);
}
};
/* class: Cabal_Common_BinSearch
This is the main class for the binary search tree with its members. This search tree uses two corresponding entries.
*/
this.Cabal_Common_BinSearch = function(){this._cclbinsearch = null;}
Cabal_Common_BinSearch.prototype = {
constructor: Cabal_Common_BinSearch,
/* property: internalVersion
Property to give OXPs a chance to check the required lib min. version easily.
*/
internalVersion: 15,
/* method: add()
Adds nodes to the search tree with the corresponding entry.
Parameters:
key - String. Add node with key.
value - Object. Corresponding entry
Returns:
nothing
*/
add: function(key,value){
var node = {key: key,left: null,right: null, value: value},current;
if(this._cclbinsearch === null) this._cclbinsearch = node;
else {
current = this._cclbinsearch;
while(true){
if(key < current.key){
if(current.left === null){
current.left = node;
break;
} else current = current.left;
} else if(key > current.key){
if(current.right === null){
current.right = node;
break;
} else current = current.right;
} else break;
}
}
return;
},
/* method: contains()
Returns corresponing entry or false.
Parameters:
key - String. Search for entry.
Returns:
value - Object. Corresponding entry or false.
*/
contains: function(key){
var found = false,current = this._cclbinsearch;
while(!found && current){
if(key < current.key) current = current.left;
else if(key > current.key) current = current.right;
else found = true;
}
if(!found) return (false);
return (current.value);
},
// Internal
traverse: function(process){
function inOrder(node){
if(node){
if(node.left !== null) inOrder(node.left);
process.call(this, node);
if(node.right !== null) inOrder(node.right);
}
}
inOrder(this._cclbinsearch);
},
/* method: size()
Returns the number of nodes in the search tree.
Parameters:
none
Returns:
length - Number. Number of nodes in searchtree.
*/
size: function(){
var length = 0;
this.traverse(function(node){length++;});
return length;
},
/* method: toArray()
Returns an array conaining all nodes in the search tree. The nodes are processed in-order.
Parameters:
none
Returns:
result - Array. Entries in search tree.
*/
toArray: function(){
var result = [];
this.traverse(function(node){result.push(node.key,node.value);});
return result;
},
/* method: toString()
Returns a comma-separated string consisting of all entries. The nodes are processed in-order.
Parameters:
separator - String. Optional. If specified separator is used to separate the elements instead of a commata.
Returns:
result - String. Concatenation of all entries in search tree.
*/
toString: function(separator){
if(separator) return this.toArray().join(separator);
else return this.toArray().toString();
}
};
/* class: Cabal_Common_2DCollision
This is the main class for the 2D checks with its members.
*/
this.Cabal_Common_2DCollision = function(){}
Cabal_Common_2DCollision.prototype = {
constructor: Cabal_Common_2DCollision,
/* property: internalVersion
Property to give OXPs a chance to check the required lib min. version easily.
*/
internalVersion: 15,
/* method: boundingBox()
Checks if point is inside the bounding box.
Parameters:
minmax - Array. 4 positions in a.x,a.y,b.x,b.y
pos - Vector. Position to be checked.
Returns:
inside - Boolean. True if inside.
*/
boundingBox: function(minmax,pos){
if(pos.x<minmax[0] || pos.x>minmax[1] || pos.y<minmax[2] || pos.y>minmax[3]) return(false);
return(true);
},
/* method: pointInPoly()
Checks if a point is inside a polygon.
Parameters:
nvert - Number of vertices in the polygon.
vertx, verty - Arrays containing the x- and y-coordinates of the polygon's vertices.
pos - Vector. x- and y-coordinate of the test point.
con - Boolean. Concave shapes may need to set it.
Return:
inside - Boolean. True if inside.
*/
pointInPoly: function(nvert,vertx,verty,pos,con){
var i,j,c = false,r1=0;
for(i=0,j=nvert-1;i<nvert;j=i++){
if(((verty[i]>pos.y)!==(verty[j]>pos.y)) && (pos.x<(vertx[j]-vertx[i])*(pos.y-verty[i])/(verty[j]-verty[i])+vertx[i])){
c = !c;
r1++;
}
if(!con && r1>1) break;
}
return(c);
},
/* method: pointOnLine()
Checks if point is on a specified line with a tolerance of 0.4.
This method has a problem with vertical lines. If it needs to be more accurate use .pointOnLineB()
Parameters:
pa - Vector. Starting point of the line.
pb - Vector. End point of the line.
pos - Vector. Position to be checked.
Return:
online - Boolean. True if on line (within tolerance).
*/
pointOnLine: function(pa,pb,pos){
var f = function(somex){return(pb.y-pa.y)/(pb.x-pa.x)*(somex-pa.x)+pa.y;};
if((pa.x>pos.x+0.4 && pb.x>pos.x+0.4) || (pa.x<pos.x-0.4 && pb.x<pos.x-0.4)) return(false);
if(pb.x<pa.x){var t = pa; pa = pb; pb = t;} //Switch
if(pa.x>pb.x+0.4 || pa.x<pb.x-0.4) return(Math.abs(f(pos.x)-pos.y)<0.4 && pos.x>=pa.x && pos.x<=pb.x);
return(((pos.y>=pa.y && pos.y<=pb.y) || (pos.y<=pa.y && pos.y>=pb.y)) && (pos.x>=pa.x && pos.x<=pb.x) || (pos.x<=pa.x && pos.x>=pb.x));
},
/* method: pointOnLineB()
Checks if point is on a specified line.
Parameters:
p1 - Vector. Starting point of the line.
p2 - Vector. End point of the line.
p3 - Vector. Position to be checked.
tol - Number. Tolerance. Default 0.01.
Return:
online - Boolean. True if on line (within tolerance).
Author: Paul Bourke
*/
pointOnLineB: function(p1,p2,p3,tol){
var s,rnum,denom,check,distanceLine,distanceSegment,dist1,dist2;
if(typeof(tol)!=='number') tol = 0.01;
rnum = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
denom = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
check = rnum / denom;
s = ((p1.y-p3.y) * (p2.x - p1.x) - (p1.x - p3.x) * (p2.y - p1.y) ) / denom;
distanceLine = Math.abs(s) * Math.sqrt(denom);
if(check >= 0 && check <= 1) distanceSegment = distanceLine;
else {
dist1 = (p3.x - p1.x) * (p3.x - p1.x) + (p3.y - p1.y) * (p3.y - p1.y);
dist2 = (p3.x - p2.x) * (p3.x - p2.x) + (p3.y - p2.y) * (p3.y - p2.y);
if(dist1 < dist2) distanceSegment = Math.sqrt(dist1);
else distanceSegment = Math.sqrt(dist2);
}
return((distanceSegment<tol));
}
};
// Functionality to check systems and get more infos about the session
this.moreInfo = {
jumpCount: 0,
lastJumpTime: clock.absoluteSeconds,
lastJumpDiff: 0,
avgEnts: system.allShips.length,
conEnts: [system.allShips.length],
avgEntsOXP: system.allShips.length,
conEntsOXP: [system.allShips.length],
galaxyStats : null,
connected : null
};
this.startUp = function()
{
delete this.startUp;
this.getGalaxy(); // planetinfo.plist is already processed
this.consTimer = new Timer(this,this.checkConnection,0.1);
};
this.playerEnteredNewGalaxy = function()
{
this.getGalaxy();
this.consTimer = new Timer(this,this.checkConnection,0.1);
};
this.shipWillEnterWitchspace = function()
{
if(this.delayedTimer){this.delayedTimer.stop(); delete this.delayedTimer;}
this.moreInfo.lastJumpDiff = clock.absoluteSeconds-this.moreInfo.lastJumpTime;
this.moreInfo.lastJumpTime = clock.absoluteSeconds;
this.moreInfo.jumpCount++;
this.updateGalaxyStats();
};
this.shipWillExitWitchspace = function()
{
this.updateGalaxyStats();
};
this.shipExitedWitchspace = function()
{
if(!system.isInterstellarSpace && this.moreInfo.jumpCount<30){
this.moreInfo.conEnts.push(system.allShips.length);
var n=0;
for(var a=0;a<this.moreInfo.conEnts.length;a++) n+=this.moreInfo.conEnts[a];
this.moreInfo.avgEnts = Math.ceil(n/this.moreInfo.conEnts.length);
if(this.moreInfo.lastJumpDiff>10) this.delayedTimer = new Timer(this,this.delayedShipExitedWitchspace,10);
}
};
this.delayedShipExitedWitchspace = function()
{
if(this.moreInfo.jumpCount<30){
this.moreInfo.conEntsOXP.push(system.allShips.length);
var n=0;
for(var a=0;a<this.moreInfo.conEntsOXP.length;a++) n+=this.moreInfo.conEntsOXP[a];
this.moreInfo.avgEntsOXP = Math.ceil(n/this.moreInfo.conEntsOXP.length);
}
delete this.delayedTimer;
};
this.updateGalaxyStats = function()
{
if(system.isInterstellarSpace) return;
var inf = this.moreInfo.galaxyStats.contains(system.ID),what = ["coordinates","description","economy","government","inhabitant","inhabitants",["market","market"],"name","population","productivity","radius",["sun","sun_gone_nova"],"techlevel"];
var l = what.length,temp;
for(var i=0;i<l;i++){
temp = what[i];
if(typeof(temp)!=="string"){
if(inf[temp[0]]===system.info[temp[1]]) continue;
if(typeof(inf[temp[0]])!=="undefined") inf[temp[0]] = (system.info[temp[1]]?false:true);
} else {
if(inf[temp]===system.info[temp]) continue;
inf[temp] = system.info[temp];
}
}
return;
};
this.getGalaxy = function()
{
this.moreInfo.galaxyStats = new this.Cabal_Common_BinSearch(); // Binary tree by ID
var c,gn=galaxyNumber,sy,r;
this.gInfo = [];
// Accessing system properties adds >250 ms
// except coordinates - this adds only ~4 ms
for(var i=0;i<256;i++){
c=System.infoForSystem(gn,i);
sy = {
coordinates: {
x:c.coordinates.x,
y:c.coordinates.y,
z:c.coordinates.z
},
description: c.description,
economy: c.economy,
government: c.government,
ID: i,
inhabitant: c.inhabitant,
inhabitants: c.inhabitants,
market: c.market,
name: c.name,
population: c.population,
productivity: c.productivity,
radius: c.radius,
sun: (c.sun_gone_nova?false:true),
techlevel: c.techlevel
};
r = {
x: c.coordinates.x,
y: c.coordinates.y,
id: i,
done: 0
};
this.gInfo.push(r);
this.moreInfo.galaxyStats.add(i,sy);
}
return;
};
// Find connections
this.checkConnection = function()
{
var helper = new this.Cabal_Common();
var m = 1.0214285714285714285714285714286;
var check = [],cur = [],cpp = player.ship.galaxyCoordinatesInLY,dist,temp;
var cp = {
x: cpp.x,
y: cpp.y,
z: 0
};
this.gInfo = helper.arrSortByProperty(this.gInfo,"x");
this.moreInfo.connected = [];
// Start loop
for(var i=0;i<256;i++){
temp = this.gInfo[i];
if(temp.x>cp.x+7.15) break;
if(temp.x<cp.x-7.15 || temp.y<cp.y-7.15 || temp.y>cp.y+7.15) continue;
dist = Math.sqrt(((cp.x-temp.x)*(cp.x-temp.x)*m)+(cp.y-temp.y)*(cp.y-temp.y));
if(dist<7.341) cur.push(temp);
}
// Grow
while(cur.length){
check = check.concat(cur);
cur = [];
for(var o=0;o<check.length;o++){
cp = check[o];
if(cp.id===system.ID || cp.done) continue;
for(var i=0;i<256;i++){
temp = this.gInfo[i];
if(temp.x>cp.x+7.15) break;
if(temp.x<cp.x-7.15 || temp.y<cp.y-7.15 || temp.y>cp.y+7.15) continue;
dist = Math.sqrt(((cp.x-temp.x)*(cp.x-temp.x)*m)+(cp.y-temp.y)*(cp.y-temp.y));
if(dist<7.341 && check.indexOf(temp)===-1 && cur.indexOf(temp)===-1) cur.push(temp);
}
}
for(var m=0;m<check.length;m++){
temp = this.gInfo.indexOf(check[m]);
this.gInfo[temp].done = 1;
}
}
for(var t=0;t<check.length;t++) this.moreInfo.connected.push(check[t].id);
if(this.consTimer) delete this.consTimer;
delete this.gInfo;
return;
};
|
Scripts/Cabal_Common_Keyboard.js |
"use strict";
this.name = "Cabal_Common_Keyboard";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Libraryscript Keyboard";
this.version = "1.7";
/* function: start()
Parameters:
who - String. The name of a worldScript which implements the keyboard callback.
min - Number. Optional - minimum length for completion, default(4).
mode - Number. Optional - 1(only alphabetical), 2(only numeric), 3(hexadecimal), default 4(alphanumeric).
scpic - String. Optional. Name for screenbackground build upon scpic + suffix. The mode defines which one will be used.
scovl - String. Optional. Filename for screenoverlay (with fileextension). Default null.
scmod - String. Optional. Role for the used model. Default 'cabal_common_key'.
Returns:
nothing
> worldScripts.Cabal_Common_Keyboard.start(this.name,5,1);
Suffixes are :
- 1 - '_keyboard_alpha.png'
- 2 - '_keyboard_nums.png'
- 3 - '_keyboard_hex.png'
- 4 - '_keyboard.png'
*/
this.start = function(who,min,mode,scpic,scovl,scmod)
{
if(!player.ship.docked) return;
this.keyboard = new Object({ini: true,input: "",keyboardSound: new SoundSource(),loop: false,sound: 'cabal_common_key.ogg',
maxRows: 4,model: 'cabal_common_key',modelSC: null,pic: 'cabal_common_keyboard.png',overlay: null,ratioX: 1,ratioY: 1,
rowsT: [],rowsX: [],rowsY: [],toCall: null,toMin: 4,X: 4,Y: 2});
if(who) this.keyboard.toCall = who;
if(min && !isNaN(min) && min>0) this.keyboard.toMin = min;
else this.keyboard.toMin = 4;
var rowsY_c = [69,46,23,-1],rowsX_c = [[-109,-85,-61,-36,-12.5,12,36.5,61,85,110],[-109.5,-85,-60.5,-36,-12.5,12.5,36.5,61,85,110],[-99.5,-75,-51,-26,-2,22,46.5,71,95],[-86,-61.5,-37.5,-13,12,36,61]];
var rowsT_c = [["1","2","3","4","5","6","7","8","9","0"],["Q","W","E","R","T","Y","U","I","O","P"],["A","S","D","F","G","H","J","K","L"],["Z","X","C","V","B","N","M"]];
var rowsY_ch = [69,46],rowsX_ch = [[-109,-85,-61,-36,-12.5,12,36.5,61,85,110],[-60.5,-36,-12.5,12.5,36.5,61]];
var rowsT_ch = [["1","2","3","4","5","6","7","8","9","0"],["A","B","C","D","E","F"]];
switch(mode){
case 1: this.keyboard.rowsX = [rowsX_c[1],rowsX_c[2],rowsX_c[3]];
this.keyboard.rowsY = [rowsY_c[1],rowsY_c[2],rowsY_c[3]];
this.keyboard.rowsT = [rowsT_c[1],rowsT_c[2],rowsT_c[3]];
this.keyboard.Y = 1;
this.keyboard.maxRows = 2;
if(scpic) this.keyboard.pic = scpic+'_keyboard_alpha.png';
else this.keyboard.pic = 'cabal_common_keyboard_alpha.png';
break;
case 2: this.keyboard.rowsX = [rowsX_c[0]];
this.keyboard.rowsY = [rowsY_c[0]];
this.keyboard.rowsT = [rowsT_c[0]];
this.keyboard.Y = 0;
this.keyboard.maxRows = 0;
if(scpic) this.keyboard.pic = scpic+'_keyboard_nums.png';
else this.keyboard.pic = 'cabal_common_keyboard_nums.png';
break;
case 3: this.keyboard.rowsX = rowsX_ch;
this.keyboard.rowsY = rowsY_ch;
this.keyboard.rowsT = rowsT_ch;
this.keyboard.Y = 0;
this.keyboard.maxRows = 1;
if(scpic) this.keyboard.pic = scpic+'_keyboard_hex.png';
else this.keyboard.pic = 'cabal_common_keyboard_hex.png';
break;
default: this.keyboard.rowsX = rowsX_c;
this.keyboard.rowsY = rowsY_c;
this.keyboard.rowsT = rowsT_c;
this.keyboard.Y = 2;
this.keyboard.maxRows = 3;
if(scpic) this.keyboard.pic = scpic+'_keyboard.png';
else this.keyboard.pic = 'cabal_common_keyboard.png';
}
this.keyboard.X = 4;
var r = (oolite.gameSettings.gameWindow.width/oolite.gameSettings.gameWindow.height),c = 1024/768;
if(r>c){
var ccX = (r%c)/1.5,ccY = (r%c)/2;
this.keyboard.ratioX = 1-ccX;
this.keyboard.ratioY = 1-ccY;
} else {
this.keyboard.ratioX = 1;
this.keyboard.ratioY = 1;
}
if(!player.ship.docked){
if(this.keyboard) delete this.keyboard;
return;
}
if(scovl) this.keyboard.overlay = scovl;
if(scmod) this.keyboard.model = scmod;
this.keyboard.keyboardSound.loop = false;
this.keyboard.keyboardSound.sound = 'cabal_common_key.ogg';
this.keyboardShow();
this.keyboard.modelSC.lightsActive = true;
return;
};
/* function: keyboardEval()
Workaround to change the context of this!!!
*/
this.keyboardEval = function(choice){worldScripts.Cabal_Common_Keyboard.keyboardChoice(choice); return;};
/* function: keyboardChoice()
Evaluates the user choice.
When <keyboard.toCall> is specified and user confirms or aborts the keyboard input.
Callback:
- "" - String. if user aborts.
- <keyboard.input> - String. If user confirmed input.
> worldScripts[this.keyboard.toCall].Cabal_Common_Keyboard_Output(this.keyboard.input);
*/
this.keyboardChoice = function(choice)
{
switch(choice){
case 'CABAL_COMMON_KEYBOARDA':
this.keyboard.X--;
if(this.keyboard.X<0) this.keyboard.X = this.keyboard.rowsX[this.keyboard.Y].length-1;
this.keyboardShow(); break;
case 'CABAL_COMMON_KEYBOARDB':
this.keyboard.Y--;
if(this.keyboard.Y<0) this.keyboard.Y = this.keyboard.maxRows;
if(this.keyboard.X>this.keyboard.rowsX[this.keyboard.Y].length-1) this.keyboard.X = this.keyboard.rowsX[this.keyboard.Y].length-1;
this.keyboardShow(); break;
case 'CABAL_COMMON_KEYBOARDC':
this.keyboard.Y++;
if(this.keyboard.Y>this.keyboard.maxRows) this.keyboard.Y = 0;
if(this.keyboard.X>this.keyboard.rowsX[this.keyboard.Y].length-1) this.keyboard.X = this.keyboard.rowsX[this.keyboard.Y].length-1;
this.keyboardShow(); break;
case 'CABAL_COMMON_KEYBOARDD':
this.keyboard.input += this.keyboard.rowsT[this.keyboard.Y][this.keyboard.X];
this.keyboardShow(); break;
case 'CABAL_COMMON_KEYBOARDE':
if(this.keyboard.input.length) this.keyboard.input = this.keyboard.input.substr(0,this.keyboard.input.length-1);
this.keyboardShow(); break;
case 'CABAL_COMMON_KEYBOARDY':
if(this.keyboard.toCall) worldScripts[this.keyboard.toCall].Cabal_Common_Keyboard_Output("");
this.killModelview(); break;
case 'CABAL_COMMON_KEYBOARDZ':
if(this.keyboard.toCall) worldScripts[this.keyboard.toCall].Cabal_Common_Keyboard_Output(this.keyboard.input);
this.killModelview(); break;
}
return;
};
this.keyboardShow = function()
{
this.keyboard.keyboardSound.play();
if(this.keyboard.input.length<this.keyboard.toMin){
if(this.keyboard.overlay) mission.runScreen({title:"Terminal",choicesKey:'CABAL_COMMON_KEYBOARD_A',model:this.keyboard.model,spinModel:false,background:this.keyboard.pic,overlay:this.keyboard.overlay},this.keyboardEval);
else mission.runScreen({title:"Terminal",choicesKey:'CABAL_COMMON_KEYBOARD_A',model:this.keyboard.model,spinModel:false,background:this.keyboard.pic},this.keyboardEval);
} else {
if(this.keyboard.overlay) mission.runScreen({title:"Terminal",choicesKey:'CABAL_COMMON_KEYBOARD_B',model:this.keyboard.model,spinModel:false,background:this.keyboard.pic,overlay:this.keyboard.overlay},this.keyboardEval);
else mission.runScreen({title:"Terminal",choicesKey:'CABAL_COMMON_KEYBOARD_B',model:this.keyboard.model,spinModel:false,background:this.keyboard.pic},this.keyboardEval);
}
this.keyboard.modelSC = mission.displayModel;
this.keyboard.modelSC.orientation = [1,-1,0,0]; // Makes the model invisible
if(this.keyboard.ini){
this.keyboard.modelSC.position = [this.keyboard.rowsX[this.keyboard.Y][4]*this.keyboard.ratioX,this.keyboard.rowsY[this.keyboard.Y]*this.keyboard.ratioY,500];
delete this.keyboard.ini;
} else this.keyboard.modelSC.position = [this.keyboard.rowsX[this.keyboard.Y][this.keyboard.X]*this.keyboard.ratioX,this.keyboard.rowsY[this.keyboard.Y]*this.keyboard.ratioY,500];
mission.addMessageText("\n User input: "+this.keyboard.input+"\n\n\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\fMinimum length: "+this.keyboard.toMin+" signs.");
this.keyboard.modelSC.lightsActive = true;
return;
};
this.killModelview = this.shipWillLaunchFromStation = function()
{
if(this.keyboard) delete this.keyboard;
return;
};
|
Scripts/Cabal_Common_MissionHandling.js |
"use strict";
this.name = "Cabal_Common_MissionHandling";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Coordinate mission offerings based on system descriptions.";
this.version = "1.7";
this.mPool = [];
this.startUp = function()
{
delete this.startUp;
this.helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
this.binSearch = new worldScripts.Cabal_Common_Functions.Cabal_Common_BinSearch();
this.checked = false;
this.runningMission = false;
this.logging = false;
};
this.prepare = function()
{
var s = [],r = this.mPool.length;
if(r){
var merged = [],pos=0;
for(var m=0;m<r;m++){
s = this.mPool[m];
if(s.length!==2 || !s[1].name || typeof(s[1].name)!=='string' || !s[1].func || typeof(s[1].func)!=='string') continue;
if(s[1].hasOwnProperty("incOXP")){
var temp = s[1].incOXP;
for(var i=0;i<temp.length;i++){
if(worldScripts[temp[i]]!=='undefined'){
log(this.name,"Dropping token "+s[0]+" : "+s[1].name+"."+s[1].func+" because of incompatibility with "+temp[i]+".");
continue;
}
}
}
if(!s[1].hasOwnProperty("mutalEx") || typeof(s[1].mutalEx)!=='number') s[1].mutalEx = 0;
pos = merged.indexOf(s[0]);
if(pos===-1) merged.push(s[0],{0:s[1]});
else {
var q = merged[pos+1];
for(var p=1;p<10;p++){
if(q.hasOwnProperty(p)) continue;
q[p] = s[1];
break;
}
}
}
r = merged.length;
for(var i=0;i<r;i+=2){
this.binSearch.add(merged[i],merged[i+1]);
}
if(this.logging) log(this.name,"merged: "+JSON.stringify(merged));
} else {
delete this.performCheck;
delete this.shipWillExitWitchspace;
delete this.shipWillLaunchFromStation;
this.checked = true;
}
delete this.alertConditionChanged;
delete this.guiScreenChanged;
delete this.prepare;
return;
};
this.performCheck = function(early)
{
this.checked = true;
if(this.runningMission) return;
var test = system.description,prop;
var pRand = this.helper.pseudoRand(system.ID,true);
var rest = test.replace(/[^a-zA-Z]/g,' ');
rest = rest.split(" ");
rest = this.helper.arrUnique(rest);
var fflag = false, l = rest.length, muteGroup = [];
for(var s=0;s<l;s++){
fflag = this.binSearch.contains(rest[s]);
if(fflag && typeof(fflag)!=='false'){
for(prop in fflag){
var c = fflag[prop];
if((early && !c.early) || (!early && c.early)) continue;
if(muteGroup.indexOf(c.mutalEx)!==-1) continue;
if(c.chance && Math.random()>c.chance) continue;
if(c.gal && c.gal.indexOf(galaxyNumber)===-1) continue;
if(c.ID && c.ID.indexOf(system.ID)===-1) continue;
if(c.gov && c.gov.indexOf(system.government)===-1) continue;
if(c.seeds && c.seeds.indexOf(pRand)===-1) continue;
if(c.exToken && rest.indexOf(c.exToken)!==-1) continue;
if(this.logging) log(this.name,"check: "+c.name+" - muteGroup: "+c.mutalEx+" rest[s]:"+rest[s]);
if(worldScripts[c.name]){
var act = false;
if(c.func && worldScripts[c.name][c.func]) act = worldScripts[c.name][c.func](rest[s]);
if(act){
muteGroup.push(c.mutalEx);
this.runningMission = true;
}
}
}
}
}
return;
};
this.alertConditionChanged = this.guiScreenChanged = function()
{
if(this.prepare) this.prepare();
if(!this.checked && this.performCheck) this.performCheck();
};
this.shipWillExitWitchspace = function()
{
this.runningMission = false;
if(this.performCheck) this.performCheck(1);
};
this.shipExitedWitchspace = function()
{
if(this.performCheck) this.performCheck();
};
this.shipWillLaunchFromStation = function()
{
if(this.prepare) this.prepare();
if(!this.checked && this.performCheck) this.performCheck(1);
};
this.shipLaunchedFromStation = function()
{
if(!this.checked && this.performCheck) this.performCheck();
};
|
Scripts/Cabal_Common_Music.js |
"use strict";
this.name = "Cabal_Common_Music";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Music helper for missions";
this.version = "1.7";
this.startUp = function()
{
delete this.startUp;
this.helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
this.mediaFade = new SoundSource();
this.mediaFade.sound = "[cabal_common_music_fade1]";
this.mediaQueue = null;
this.mediaPool = {
allListed:[],
aegis:{enter:[],exit:[]},
alert:{red:[],yellow:[],green:[]},
destroyed:{ent:[]},
exitWS:{inter:[],goneNova:[],doNova:[],standard:[],any:[]},
launch:{ent:[],inter:[],goneNova:[],doNova:[],main:[],any:[]},
planet:{ent:[],enterMain:[],enterSun:[],exitMain:[],exitSun:[]},
scooped:{ent:[],fuel:[]},
track:{byName:[],byRole:[]}
};
this.currentFile = null;
this.currentTrack = null;
this.requestHandlerSet = [];
this.blockAlert = 1;
this.blockPlanet = 1;
this.blockFuel = 1;
var handler = Object.keys(this.mediaPool);
handler.shift();
for(var i=0;i<handler.length;i++){
var c = Object.keys(this.mediaPool[handler[i]]);
c.unshift(handler[i]);
this.requestHandlerSet.push(c);
}
};
// Register events
this.addMedia = function(obj)
{
if(this.startUp) this.startUp();
if(!obj || !Object.isExtensible(obj) || !obj.who || !worldScripts[obj.who] || !obj.hasOwnProperty("start")) return(false);
var pid = -1;
if(this.mediaPool.allListed.length){
for(var i=0;i<this.mediaPool.allListed.length;i++){
if(obj.who===this.mediaPool.allListed[i][0]){
pid = i;
break;
}
}
}
if(pid===-1){
pid = this.mediaPool.allListed.length;
this.mediaPool.allListed.push([obj.who,obj.start]);
}
for(var handler in this.mediaPool){
if(handler==="allListed") continue;
if(obj.hasOwnProperty(handler)){
for(var what in this.mediaPool[handler]){
if(obj[handler].hasOwnProperty(what)){
var cur = obj[handler][what];
for(var i=0;i<cur.length;i++){
cur[i].sid = pid;
this.mediaPool[handler][what].push(cur[i]);
}
}
}
}
}
if(!player.ship.docked) this.checkTrack();
return(true);
};
// Unregister events
this.removeMedia = function(who)
{
if(!who) return(false);
var pid;
for(var i=0;i<this.mediaPool.allListed.length;i++){
if(who===this.mediaPool.allListed[i][0]){
pid = i;
this.mediaPool.allListed = this.helper.arrRemoveByValue(this.mediaPool.allListed,this.mediaPool.allListed[pid]);
break;
}
}
if(typeof(pid)==="undefined") return(false);
for(var handler in this.mediaPool){
if(handler==="allListed") continue;
for(var what in this.mediaPool[handler]){
for(var i=0;i<this.mediaPool[handler][what].length;i++){
if(this.mediaPool[handler][what][i].sid===pid){
this.mediaPool[handler][what] = this.helper.arrRemoveByValue(this.mediaPool[handler][what],this.mediaPool[handler][what][i]);
if(i>-1) i--;
} else if(this.mediaPool[handler][what][i].sid>pid) this.mediaPool[handler][what][i].sid--;
}
}
}
return(true);
};
// Change status flag
this.changeStatus = function(who,status)
{
for(var i=0;i<this.mediaPool.allListed.length;i++){
if(who===this.mediaPool.allListed[i][0]){
this.mediaPool.allListed[i][1] = status;
if(!player.ship.docked) this.checkTrack();
return(true);
}
}
return(false);
};
this.cclm_findActive = function(element){return(this.mediaPool.allListed[element.sid][1]);};
this.performMedia = function(handler,specifier,followup)
{
var cur,found=false;
// Handle ent + followup
if(followup && this.mediaPool[handler].hasOwnProperty("ent")){
cur = this.mediaPool[handler].ent.filter(this.cclm_findActive,this);
if(cur.length) found = this.loopChecks(cur,followup);
if(found && (handler==="aegis" || handler==="planet")) this.blockPlanet = clock.absoluteSeconds+10;
return;
}
// Handle standard specifier
if(!found){
cur = this.mediaPool[handler][specifier].filter(this.cclm_findActive,this);
if(cur.length) found = this.loopChecks(cur);
if(found && handler==="scooped" && specifier==="fuel") this.blockFuel = clock.absoluteSeconds+10;
if(!found){
// Handle - any
if(this.mediaPool[handler].hasOwnProperty("any")){
cur = this.mediaPool[handler].any.filter(this.cclm_findActive,this);
if(!cur.length) return;
found = this.loopChecks(cur);
}
}
}
if(found && (handler==="aegis" || handler==="planet")) this.blockPlanet = clock.absoluteSeconds+10;
this.blockAlert = clock.absoluteSeconds;
return;
};
this.isClose = function(entity)
{
return(entity.isShip && entity.isValid);
};
this.performTracker = function()
{
if(!player.ship.isValid){
this.trackerTimer.stop();
return;
}
var ents = system.filteredEntities(this,this.isClose,player.ship,25600);
var cur = this.mediaPool.track.byName.filter(this.cclm_findActive,this),disable = true;
for(var i=0;i<cur.length;i++){
var sub = cur[i];
if(!this.mediaPool.allListed[sub.sid][1]) continue;
disable = false;
var ws = this.mediaPool.allListed[sub.sid][0];
if(sub.hasOwnProperty("prop") && !worldScripts[ws][sub.prop]) continue;
for(var e=0;e<ents.length;e++){
if(sub.ent!==ents[e].name || sub.ent===this.currentTrack) continue;
if(sub.dist<player.ship.position.distanceTo(ents[e].position)) continue;
if(sub.fadeQ){
this.mediaFade.sound = "[cabal_common_music_fade"+sub.fadeQ+"]";
this.mediaFade.play();
}
var cl = 1, bp = 0, rp = 0, nq = 0;
if(sub.bypassQ){
bp = sub.bypassQ;
cl = 0;
}
if(sub.leaveQ) cl = 0;
if(sub.onlyRepQ) rp = 1;
if(sub.forceQ) nq = 1;
this.runMedia(sub.music,cl,bp,rp,nq);
this.currentTrack = sub.ent;
return(true);
}
}
// If all OXPs are off stop - re-enabling via changeStatus
if(disable){
this.trackerTimer.stop();
delete this.trackerTimer;
}
return(false);
};
this.loopChecks = function(cur,followup)
{
for(var i=0;i<cur.length;i++){
var sub = cur[i];
if(!this.mediaPool.allListed[sub.sid][1]) continue;
var ws = this.mediaPool.allListed[sub.sid][0];
if(sub.hasOwnProperty("prop") && !worldScripts[ws][sub.prop]) continue;
if(followup && followup!==sub.ent) continue;
if(sub.fadeQ){
this.mediaFade.sound = "[cabal_common_music_fade"+sub.fadeQ+"]";
this.mediaFade.play();
}
var cl = 1, bp = 0, rp = 0, nq = 0;
if(sub.bypassQ){
bp = sub.bypassQ;
cl = 0;
}
if(sub.leaveQ) cl = 0;
if(sub.onlyRepQ) rp = 1;
if(sub.forceQ) nq = 1;
this.runMedia(sub.music,cl,bp,rp,nq);
return(true);
}
return(false)
};
this.runMedia = function(list,clear,bypass,replace,force)
{
if(typeof(list)==="string"){
Sound.playMusic(list);
this.currentFile = list;
if(clear) this.mediaQueue = null;
else if(bypass){
if(this.mediaTimer){
if(this.mediaTimer.isRunning){
this.mediaTimer.stop();
this.mediaTimer.nextTime = clock.absoluteSeconds+bypass;
this.mediaTimer.start();
}
}
}
} else {
var flag=false;
if((replace && !this.mediaQueue) || force) flag=true;
this.mediaQueue = list;
if(flag){
if(force) this.doMediaTimer(1);
else if(replace) this.doMediaTimer();
}
}
return;
};
this.doMediaTimer = function(force)
{
if(this.mediaTimer){
if(this.mediaTimer.isRunning) this.mediaTimer.stop();
delete this.mediaTimer;
}
if(!this.mediaQueue) return;
var entry = 0;
if(!force) entry = Math.floor(Math.random()*this.mediaQueue.length);
var dura = this.mediaQueue[entry].duration;
var rep = this.mediaQueue[entry].repeat;
var delay = (dura+1)*(rep?rep:1);
Sound.playMusic(this.mediaQueue[entry].file,rep);
this.currentFile = this.mediaQueue[entry].file;
this.mediaTimer = new Timer(this,this.doMediaTimer,delay);
return;
};
this.shipWillDockWithStation = this.shipWillEnterWitchspace = this.shipDied = function()
{
if(this.mediaTimer){
if(this.mediaTimer.isRunning) this.mediaTimer.stop();
delete this.mediaTimer;
}
if(this.trackerTimer){
if(this.trackerTimer.isRunning) this.trackerTimer.stop();
delete this.trackerTimer;
}
this.mediaQueue = null;
this.currentTrack = null;
this.currentFile = null;
};
this.shipWillLaunchFromStation = this.shipWillExitWitchspace = function()
{
this.checkTrack();
};
this.shipTargetLost = function(target)
{
if(!player.ship.isValid) return;
if(target && target.name && target.name===this.currentTrack && target.position.distanceTo(player.ship)>25600) this.currentTrack = null;
};
this.checkTrack = function()
{
if(!this.trackerTimer && this.mediaPool.track.byName.filter(this.cclm_findActive,this).length) this.trackerTimer = new Timer(this,this.performTracker,0,10);
return;
};
this.alertConditionChanged = function(to)
{
if(!player.ship.isValid || player.ship.status!=="STATUS_IN_FLIGHT") return;
switch(to){
case 3: this.performMedia("alert","red"); break;
case 2: if(clock.absoluteSeconds>this.blockAlert) this.performMedia("alert","yellow"); break;
case 1: if(clock.absoluteSeconds>this.blockAlert) this.performMedia("alert","green"); break;
}
this.blockAlert = clock.absoluteSeconds+10;
};
this.shipEnteredPlanetaryVicinity = function(planet)
{
if(!player.ship.isValid || !planet || clock.absoluteSeconds<this.blockPlanet) return;
if(planet.isMainPlanet) this.performMedia("planet","enterMain");
else if(planet.isSun) this.performMedia("planet","enterSun");
else this.performMedia("planet","ent",planet.radius);
};
this.shipEnteredStationAegis = function(station)
{
if(!player.ship.isValid || !station || clock.absoluteSeconds<this.blockPlanet) return;
this.performMedia("aegis","enter");
};
this.shipExitedPlanetaryVicinity = function(planet)
{
if(!player.ship.isValid || !planet || clock.absoluteSeconds<this.blockPlanet) return;
if(planet.isMainPlanet) this.performMedia("planet","exitMain");
if(planet.isSun) this.performMedia("planet","exitSun");
};
this.shipExitedStationAegis = function(station)
{
if(!player.ship.isValid || !station || clock.absoluteSeconds<this.blockPlanet) return;
this.performMedia("aegis","exit");
};
this.shipExitedWitchspace = function()
{
if(!player.ship.isValid) return;
if(system.isInterstellarSpace) this.performMedia("exitWS","inter");
else if(system.sun.hasGoneNova) this.performMedia("exitWS","goneNova");
else if(system.sun.isGoingNova) this.performMedia("exitWS","doNova");
else this.performMedia("exitWS","standard");
this.checkTrack();
};
this.shipLaunchedFromStation = function(station)
{
if(!player.ship.isValid || !station) return;
if(station.isMainStation) this.performMedia("launch","main");
else this.performMedia("launch","ent",station.name);
};
this.shipScoopedOther = function(whom)
{
if(!player.ship.isValid || !whom || !whom.name) return;
this.performMedia("scooped","ent",whom.name);
};
this.shipScoopedFuel = function()
{
if(!player.ship.isValid || clock.absoluteSeconds<this.blockFuel) return;
this.performMedia("scooped","fuel");
};
this.shipTargetDestroyed = function(target)
{
if(!player.ship.isValid || !target || !target.name) return;
this.performMedia("destroyed","ent",target.name);
};
|
Scripts/Cabal_Common_OXPStrength.js |
"use strict";
this.name = "Cabal_Common_OXPStrength";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Checks and/or cleans out entities and suspends OXPs.";
this.version = "1.7.1";
this.ccl_strengthExclEntByName = []; // Array of entity names to be excluded
this.startUp = function()
{
delete this.startUp; // PhantorGorth' chain handling
this.checkOXPStrength = new this.Cabal_Common_OXPStrengthAPI(); // Get instance
this.helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
this.gJump = false; // Flag for galactic jump
this.current = null; // Holds current settings object or null
this.watchLocations = [[],[],[],[],[],[],[],[]]; // Storage for settings splitted in galaxies to keep loops small
this.resetValues(); // Default settings
this.leftSystem = system.ID; // For interstellar checks
this.suspendedOXPs = []; // Holds suspended OXPs
for(var w in worldScripts){
if(!w) continue;
var s = worldScripts[w];
if(!s) continue;
for(var prop in s){
var p = s[prop];
if(!prop || !p) continue;
if(typeof(p)==="function"){
var temp = p.toString();
if(temp.search(/restoreSubEntities/gi)!==-1) this.checkOXPStrength.wayoff.push(w.toLowerCase());
if(temp.search(/EQ_RENOVATION/gi)!==-1) this.checkOXPStrength.wayoff.push(w.toLowerCase());
}
}
}
};
this.guiScreenChanged = this.alertConditionChanged = this.missionScreenOpportunity = function()
{
delete this.guiScreenChanged;
delete this.alertConditionChanged;
delete this.missionScreenOpportunity;
// Excluded entities?
if(this.ccl_strengthExclEntByName.length){
for(var i=0;i<this.ccl_strengthExclEntByName.length;i++){
if(typeof(this.ccl_strengthExclEntByName[i])==="string") this.checkOXPStrength.binAdd(this.ccl_strengthExclEntByName[i],true);
else {
for(var j=0;j<this.ccl_strengthExclEntByName[i].length;j++){
this.checkOXPStrength.binAdd(this.ccl_strengthExclEntByName[i][j],true);
}
}
}
}
this.checkWatchLocations(system.ID,false);
};
// Interface for other OXPS to register settings
this.registerLocation = function(obj)
{
if(obj && obj.hasOwnProperty("Gal") && obj.hasOwnProperty("ID") && obj.hasOwnProperty("ISS") && obj.CSS && obj.CSP){
this.watchLocations[obj.Gal].push(obj);
return(true);
}
return(false);
};
// Oktis approach - callback
this.suspendOXP = function()
{
if(this.current && this.suspendedOXPs.length) return(true);
return(false);
};
this.playerWillSaveGame = function()
{
this.tempS = missionVariables.CCL_OXPStrength;
missionVariables.CCL_OXPStrength = 9; //Save only default
this.guiScreenChanged = function(){
missionVariables.CCL_OXPStrength = this.tempS;
delete this.guiScreenChanged;
}
};
// Defaults
this.resetValues = function(full)
{
this.checkOXPStrength.checkCoef = 999999; // Minimum coef
this.checkOXPStrength.checkKill = 999999; // Minimum coef for removing
this.checkOXPStrength.logIt = false; // Logging flag
this.checkOXPStrength.checkLocation = 0; // Location to be checked
missionVariables.CCL_OXPStrength = 9; // For conditions in shipdata
this.current = null;
if(full) this.suspendedOXPs = [];
return;
};
this.playerStartedJumpCountdown = function(jump)
{
if(jump==="galactic") this.gJump = true;
};
this.playerCancelledJumpCountdown = this.playerJumpFailed = function()
{
this.gJump = false;
};
// Interstellar and normal space checks
this.shipWillExitWitchspace = this.shipWillLaunchFromStation = function()
{
this.gJump = false;
if(system.isInterstellarSpace) this.checkWatchLocations(this.leftSystem,true);
else this.checkWatchLocations(system.ID,false);
if(this.current) this.startCleaning(this.current);
else this.resetValues(1);
};
// Reset and prepare next checks. MV has to be set before jumping to prevent spawning by populator
this.shipWillEnterWitchspace = function()
{
if(this.repeatTimer){
this.repeatTimer.stop();
delete this.repeatTimer;
}
this.leftSystem = system.ID;
if(this.current && !this.current.Permanent) this.watchLocations[galaxyNumber] = this.checkOXPStrength.arrRemoveByValue(this.watchLocations[galaxyNumber],this.current);
this.resetValues();
if(!this.gJump){
if(player.ship.scriptedMisjump) this.checkWatchLocations(this.leftSystem,true);
else this.checkWatchLocations(player.ship.targetSystem,false);
this.current = null;
} else {
var loc = player.ship.galacticHyperspaceFixedCoordsInLY.toArray(); // Rounding!!!
for(var r=0;r<3;r++){
loc[r] = parseFloat(loc[r].toFixed(1));
}
this.checkWatchLocations(loc,false);
}
};
// Check if it should be activated
this.checkWatchLocations = function(ID,ISS)
{
var c=[],temp;
// Grab subset
if(this.gJump){
if(galaxyNumber<7) c = this.watchLocations[galaxyNumber+1];
else c = this.watchLocations[0];
} else c = this.watchLocations[galaxyNumber];
for(var i=0;i<c.length;i++){
if(c[i].ID===ID || (this.gJump && c[i].GJump && c[i].GJump[0]===ID[0] && c[i].GJump[1]===ID[1])){
temp = null;
if(c[i].CSS && c[i].CSP && !worldScripts[c[i].CSS][c[i].CSP]) continue; // Check status
if((system.isInterstellarSpace || player.ship.scriptedMisjump) && ISS && c[i].ISS) temp = c[i];
else if(!system.isInterstellarSpace && !player.ship.scriptedMisjump && !ISS && !c[i].ISS) temp = c[i];
else if(system.isInterstellarSpace && !player.ship.scriptedMisjump && !ISS && !c[i].ISS) temp = c[i];
if(temp){
if(!this.current) this.current = temp;
else {
if(temp.Strength && temp.Strength<this.current.Strength || !this.current.hasOwnProperty("Strength")) this.current.Strength = temp.Strength;
if(temp.checkC && temp.checkC<this.current.checkC || !this.current.hasOwnProperty("checkC")) this.current.checkC = temp.checkC;
if(temp.checkK && temp.checkK<this.current.checkK || !this.current.hasOwnProperty("checkK")) this.current.checkK = temp.checkK;
if(temp.delay && temp.delay<this.current.delay || !this.current.hasOwnProperty("delay")) this.current.delay = temp.delay;
if(temp.repeat && temp.repeat>this.current.repeat || !this.current.hasOwnProperty("repeat")) this.current.repeat = temp.repeat;
if(temp.locate && temp.locate!==this.current.locate || !this.current.hasOwnProperty("locate")) this.current.locate = 0;
if(temp.logging && !this.current.logging) this.current.logging = 1;
if(temp.Suspend) this.current.Suspend = this.suspendedOXPs.concat(temp.Suspend);
}
}
}
}
if(this.current){
if(this.current.Strength) missionVariables.CCL_OXPStrength = this.current.Strength; // Set mV for strength
if(this.current.Suspend && this.current.Suspend.length){
for(var s=0;s<this.current.Suspend.length;s++){
c = this.current.Suspend[s];
if(this.suspendedOXPs.indexOf(c)!==-1) continue;
if(worldScripts[c] && worldScripts[c].addToCallbacks){
worldScripts[c].addToCallbacks({worldScript:this.name,callBack:"suspendOXP"});
this.suspendedOXPs.push(this.current.Suspend[s]);
}
}
}
} else {
if(this.infoTimer){this.infoTimer.stop(); delete this.infoTimer;}
if(this.repeatTimer){this.repeatTimer.stop(); delete this.repeatTimer;}
if(this.suspendedOXPs.length){
for(var s=0;s<this.suspendedOXPs.length;s++){
c = this.suspendedOXPs[s];
if(worldScripts[c] && worldScripts[c].removeFromCallbacks){
worldScripts[c].removeFromCallbacks({worldScript:this.name,callBack:"suspendOXP"});
}
}
this.suspendedOXPs = [];
}
}
return;
};
// Set cleaning params
this.startCleaning = function(obj)
{
if(!obj.checkC) return;
else {
this.checkOXPStrength.checkCoef = obj.checkC;
if(obj.checkK) this.checkOXPStrength.checkKill = obj.checkK;
}
if(obj.logging) this.checkOXPStrength.logIt = obj.logging;
// One shot timer
if(!this.infoTimer){
if(obj.delay) this.infoTimer = new Timer(this,this.checkAll,obj.delay);
else this.infoTimer = new Timer(this,this.checkAll,10);
}
if(obj.locate) this.checkOXPStrength.checkLocation = obj.locate;
// Repeat timer
if(obj.repeat){
if(!this.repeatTimer){
if(obj.delay) this.repeatTimer = new Timer(this,this.checkAll,0,10+obj.delay);
else this.repeatTimer = new Timer(this,this.checkAll,0,10);
}
}
return;
};
this.checkAll = function()
{
if(guiScreen==="GUI_SCREEN_LOAD"){
if(this.infoTimer){this.infoTimer.stop(); delete this.infoTimer;}
if(this.repeatTimer){this.repeatTimer.stop(); delete this.repeatTimer;}
return;
}
this.checkOXPStrength.checkPower();
if(this.infoTimer){this.infoTimer.stop(); delete this.infoTimer;}
if(this.current.repeat) this.current.repeat--;
else if(this.repeatTimer){this.repeatTimer.stop(); delete this.repeatTimer;}
return;
};
// API
this.Cabal_Common_OXPStrengthAPI = function(){this._cclstrength = null;}
Cabal_Common_OXPStrengthAPI.prototype = {
// Threshold distance to MainStation, WP or the lanes WP,WS,PS
maxDist: 50000,
// Threshold energy
checkE: 800,
// Threshold speed
checkS: 500,
// Threshold standard missiles
checkM: 6,
// Threshold escorts
checkEsc: 4,
// Threshold for putting in list
checkCoef: 999999,
// Threshold for killing
checkKill: 999999,
// Act only for location
checkLocation: 0,
logIt: false,
weapons: ["EQ_WEAPON_PULSE_LASER",1,"EQ_WEAPON_BEAM_LASER",3,"EQ_WEAPON_MILITARY_LASER",5,"EQ_WEAPON_MINING_LASER",4,"EQ_WEAPON_THARGOID_LASER",8,"EQ_WEAPON_TWIN_PLASMA_CANNON",4],
smissile: ["EQ_MISSILE",0,"EQ_HARDENED_MISSILE",0.6,"EQ_ARMOURY_STANDARD_MISSILE",0.1,"EQ_ARMOURY_HARD_MISSILE",0.7,"EQ_MILITARY_MISSILE",0.8,"EQ_RMB_CASCADE_MISSILE",0.6,
"EQ_RMB_FRAG_MISSILE",0.4,"EQ_RMB_LAW_MISSILE",0.5,"EQ_RMB_THARGOID_MISSILE",0.1,"EQ_RMB_INTERCEPT_MISSILE",0.3,"EQ_RMB_OVERRIDE_MISSILE",0.3,"EQ_HARPOON_NUKE1_MISSILE",0.7,
"EQ_HARPOON_ABM_MISSILE",0.5,"EQ_MANCHI_MISSILE",0.4,"EQ_VECTOR_FUNA_MISSILE",1.1,"EQ_VECTOR_FUNB_MISSILE",1.1,"EQ_VECTOR_FUNC_MISSILE",1.1,"EQ_KILLIT_MISSILE",2.0,
"EQ_CT_MINE",1.2,"EQ_ECD_MINE",1.1],
srole: ["sunskim-trader",0.6,"trader",0.6,"hunter",1.1,"police",1.1,"wingman",1.1,"interceptor",1.1,"pirate",1.1,"blackdog",1.1,"scavenger",0.3,"shuttle",0.2,"miner",0.2,
"hermit-ship",0.4,"escort",0.9,"thargoid",0.9,"tharglet",0.9],
storage: [],
wayoff : [],
checkSpaceLane: function(entity){
if(system.isInterstellarSpace){
if(this.checkLocation){
var d = this.maxDist+1;
return([0,d,entity.position.distanceTo(new Vector3D([0,0,0])),d,d,d]);
} else return([-1,0,0,0,0,0]);
}
if(!system.sun || system.sun.isGoingNova || system.sun.hasGoneNova) return([1,0,0,0,0,0]);
var distMS = entity.position.distanceTo(system.mainStation.position);
var distWP = entity.position.distanceTo(new Vector3D([0,0,0]));
var distLWP = Math.sqrt(entity.position.x*entity.position.x+entity.position.y*entity.position.y);
var lanePS = new Vector3D(system.mainPlanet.position.subtract(system.sun.position));
var SEV = new Vector3D(entity.position.subtract(system.sun.position));
var distS = SEV.magnitude();
var distLPS = distS*Math.sin(lanePS.angleTo(SEV));
var laneWS = new Vector3D(new Vector3D([0,0,0]).subtract(system.sun.position));
var distLWS = distS*Math.sin(laneWS.angleTo(SEV));
if(distMS>this.maxDist && distWP>this.maxDist && distLWP>this.maxDist && distLPS>this.maxDist && distLWS>this.maxDist) return([2,Math.floor(distMS),Math.floor(distWP),Math.floor(distLWP),Math.floor(distLPS),Math.floor(distLWS)]);
return([0,Math.floor(distMS),Math.floor(distWP),Math.floor(distLWP),Math.floor(distLPS),Math.floor(distLWS)]);
},
checkSubs: function(entity){
var tur=0,wea=0,slots=0,w=0,wtype="",s=0,subwtype="",temp;
if(entity.forwardWeapon){slots++; temp = this.weapons[this.weapons.indexOf(entity.forwardWeapon.equipmentKey)+1]; wtype += ""+temp; w += temp;}
if(entity.aftWeapon){slots++; temp = this.weapons[this.weapons.indexOf(entity.aftWeapon.equipmentKey)+1]; wtype += ""+temp; w += temp;}
if(entity.portWeapon){slots++; temp = this.weapons[this.weapons.indexOf(entity.portWeapon.equipmentKey)+1]; wtype += ""+temp; w += temp;}
if(entity.starboardWeapon){slots++; temp = this.weapons[this.weapons.indexOf(entity.starboardWeapon.equipmentKey)+1]; wtype += ""+temp; w += temp;}
if(entity.isPlayer && !slots){slots=4; w=32; wtype="0000";} // All null, treat as highest
if(!entity.subEntityCapacity) return([slots,0,0,w,wtype,0,0]);
for(var prop in entity.subEntities){
if(entity.subEntities[prop].status==="STATUS_ACTIVE") tur += 4;
if(entity.subEntities[prop].forwardWeapon){wea++; temp = this.weapons[this.weapons.indexOf(entity.subEntities[prop].forwardWeapon.equipmentKey)+1]; subwtype += ""+temp; s += temp;}
if(entity.subEntities[prop].aftWeapon){wea++; temp = this.weapons[this.weapons.indexOf(entity.subEntities[prop].aftWeapon.equipmentKey)+1]; subwtype += ""+temp; s += temp;}
if(entity.subEntities[prop].portWeapon){wea++; temp = this.weapons[this.weapons.indexOf(entity.subEntities[prop].portWeapon.equipmentKey)+1]; subwtype += ""+temp; s += temp;}
if(entity.subEntities[prop].starboardWeapon){wea++; temp = this.weapons[this.weapons.indexOf(entity.subEntities[prop].starboardWeapon.equipmentKey)+1]; subwtype += ""+temp; s += temp;}
}
if(!tur && entity.subEntityCapacity>2 && entity.subEntities && entity.subEntities.length<3) tur = entity.subEntityCapacity*4; // no cheats
return([slots,tur,wea,w,wtype,s,subwtype]);
},
checkMissiles: function(entity){
if(!entity.missileCapacity) return(0);
var slot,mtype=0;
for(var prop in entity.missiles){
if(entity.missiles[prop].equipmentKey){
slot = this.smissile.indexOf(entity.missiles[prop].equipmentKey+1);
if(slot===-1) mtype += 2;
else mtype += slot;
}
}
if(!mtype){
if(entity.missileCapacity>this.checkM) return([1,entity.missileCapacity]);
else return(0);
}
return([(1+mtype)*entity.missileCapacity,entity.missileCapacity]);
},
checkRole: function(entity){
var r = entity.primaryRole,mul=1;
var ind = this.srole.indexOf(r);
if(ind!==-1) mul = this.srole[ind+1];
return(mul);
},
checkPower: function(p){
if(!player.ship.isValid) return(0);
function isBad(entity){return(entity.isShip && entity.isValid && (!entity.isStation || (entity.isStation && !entity.isMainStation)) && entity.maxEnergy>this.checkE || entity.maxSpeed>this.checkS || this.checkSubs(entity) || this.checkMissiles(entity) || (entity.escorts && entity.escorts.length>this.checkEsc));}
var ents,temp,en,sp,wep,def,coef,mis,esc,dist,rol,bomb=false;
this.storage = [];
if(p){
if(p.isPlayer) ents = [player.ship];
else if(p.isValid) ents =[p];
else return(0);
} else ents = system.filteredEntities(this,isBad,player.ship);
if(ents.length){
for(var i=0;i<ents.length;i++){
if(!ents[i].name) continue;
if(!p || (p && !p.isPlayer)){
var exFlag=this.binContains(ents[i].name);
if(exFlag) continue;
}
en = ents[i].maxEnergy;
if(ents[i].isStation && !ents[i].maxSpeed) coef = Math.log(en);
else {
if(en>256) en += Math.sqrt(en);
if(p && p.isPlayer){
en += ents[i].maxAftShield*ents[i].aftShieldRechargeRate;
en += ents[i].maxForwardShield*ents[i].forwardShieldRechargeRate;
} else if(en>800) en *= 2;
coef = Math.sqrt(en);
}
sp = ents[i].maxSpeed;
if(ents[i].equipmentStatus("EQ_FUEL_INJECTION")==="EQUIPMENT_OK") sp *= 4;
if(ents[i].isPiloted && !ents[i].isStation && ents[i].maxSpeed && ents[i].maxThrust>40) sp *= Math.log(ents[i].maxThrust);
if(sp) coef += Math.sqrt(sp);
else sp = 0;
temp = this.checkSubs(ents[i]);
if(typeof(temp)!=="number"){
if(this.logIt) wep = "L:"+temp[0]+" T:"+temp[1]+" S:"+temp[2]+" "+temp[4]+","+temp[6];
if(temp[0]) coef += Math.pow(1.4,temp[0])*Math.log(temp[3]); // Standard Laser
if(temp[1]) coef += Math.min(Math.pow(1.4,temp[1])*2,0xfffff); // Turrets
if(temp[2]) coef += Math.min(Math.pow(1.5,temp[2])*(2*Math.log(temp[5])),0xfffff); // Subent Laser
} else if(this.logIt) wep = "L:0 T:0 S:0 -,-";
temp = this.checkMissiles(ents[i]);
if(temp[0]){
coef += Math.pow(temp[1],1.7);
mis = temp[1];
} else mis = 0;
if(ents[i].escorts && ents[i].escorts.length) esc = ents[i].escorts.length;
else esc = 0;
coef += Math.pow(esc,1.8);
if(ents[i].isStation){
def = ents[i].dockedDefenders;
} else def = 0;
coef += Math.pow(def,1.8);
if(p && p.isPlayer){
coef *= 1.5;
if(missionVariables.targetAutolock==="TRUE") coef += 5;
var eq = ["EQ_ECM","EQ_ENERGY_BOMB","EQ_TARGET_AUTOLOCK","EQ_ENERGY_UNIT","EQ_NAVAL_ENERGY_UNIT","EQ_CLOAKING_DEVICE","EQ_QC_MINE","EQ_SHIELD_BOOSTER","EQ_NAVAL_SHIELD_BOOSTER","EQ_MILITARY_JAMMER",
"EQ_MILITARY_SCANNER_FILTER","EQ_SHIELD_ENHANCER","EQ_AMS","EQ_EEU","EQ_IRONHIDE_FORWARD","EQ_IRONHIDE_AFT","EQ_VORTEX_TURRET"];
var eqi = eq.length;
while(eqi--){if(EquipmentInfo.infoForKey(eq[eqi])!==null && player.ship.equipmentStatus(eq[eqi])==="EQUIPMENT_OK") coef += 5;}
dist = "-";
rol = 1;
} else {
dist = this.checkSpaceLane(ents[i]);
if(dist[0]===0){
if(this.checkLocation && dist[this.checkLocation]>this.maxDist) continue;
if(dist[1]<this.maxDist) coef *= 1.5; // Main Station
else if(dist[2]<this.maxDist) coef *= 1.5; // WP
else if(dist[3]<this.maxDist) coef *= 1.3; // Lane WP
else if(dist[4]<this.maxDist) coef *= 1.1; // Lane PS
else if(dist[5]<this.maxDist) coef *= 1.2; // Lane WS
}
if(dist[0]===2) coef *= 1/Math.log(dist[3]-this.maxDist);
rol = this.checkRole(ents[i]);
coef *= rol;
}
var eq = ents[i].equipment,eqpoints=1;
for(var eqq=0;eqq<eq.length;eqq++){
var reg = eq[eqq].equipmentKey;
var des = eq[eqq].description;
if(reg.search(/TARGET/gi)!==-1) eqpoints *= 1.15;
if(reg.search(/MISSILE/gi)!==-1) eqpoints *= 1.15;
if(reg.search(/ENERGY/gi)!==-1) eqpoints *= 1.25;
if(reg.search(/SHIELD/gi)!==-1) eqpoints *= 1.25;
if(reg.search(/BOOST/gi)!==-1) eqpoints *= 1.4;
if(reg.search(/NAVAL/gi)!==-1) eqpoints *= 1.4;
if(reg.search(/TURRET/gi)!==-1) eqpoints *= 1.5;
if(des.search(/ARMOUR/gi)!==-1) eqpoints *= 1.5;
if(reg.search(/LASER/gi)!==-1 || des.search(/LASER/gi)!==-1) coef *= 2.5;
if(reg.search(/LAZER/gi)!==-1 || des.search(/LAZER/gi)!==-1) coef *= 2.5;
}
coef += eqpoints;
if(ents[i].equipmentStatus("EQ_CLOAKING_DEVICE")==="EQUIPMENT_OK") coef *= 1.3;
if(ents[i].equipmentStatus("EQ_MILITARY_JAMMER")==="EQUIPMENT_OK") coef *= 1.5;
if(ents[i].equipmentStatus("EQ_MILITARY_SCANNER_FILTER")==="EQUIPMENT_OK") coef *= 1.5;
coef = Math.floor(coef);
if(coef>this.checkCoef){
if(this.logIt) this.storage.push("COEF:"+this.pad(coef,6)+" E:"+this.pad(en,7)+" : S:"+this.pad(sp,5)+" : C:"+ents[i].scanClass+" : "+ents[i].name+" ("+ents[i].primaryRole+") : W:"+wep+" : M:"+mis+" : Esc:"+esc+" : Def:"+def+" : dist:"+dist+" : roleMul:"+rol);
if(!p && coef>this.checkKill && ents[i].isValid){
if(ents[i].scriptInfo && ents[i].scriptInfo.ccl_missionShip==="true") continue;
if(ents[i].script && ents[i].script.ccl_missionShip) continue;
if(ents[i].AI && ents[i].AI==="cabal_common_leaveHotspotAI.plist") continue;
if(ents[i].isMainStation || (ents[i].isStation && !ents[i].distanceTravelled)) continue;
var custSc = false;
if(!ents[i].script || (ents[i].script && (ents[i].script.hasOwnProperty("shipRemoved") || ents[i].script.hasOwnProperty("entityDestroyed")))) custSc = true;
if(ents[i].status!=="STATUS_IN_FLIGHT") continue; // Avoid early calls resulting in undefined properties
var rDist = ents[i].position.distanceTo(player.ship.position);
if(rDist>Math.pow(ents[i].collisionRadius,2) && rDist>25600){
if(ents[i].escorts && ents[i].escorts.length){
var es = ents[i].escorts.length;
while(es--){
if(!ents[i].escorts[es].isValid) continue;
if(!ents[i].escorts[es].script || ents[i].escorts[es].script.hasOwnProperty("shipRemoved") || ents[i].escorts[es].script.hasOwnProperty("entityDestroyed")) ents[i].escorts[es].remove(true);
else ents[i].escorts[es].remove();
}
}
if(custSc) ents[i].remove(true);
else ents[i].remove();
if(this.logIt) log("KILL","Kill: "+ents[i].name);
} else {
if(rDist>3000){
if(this.logIt) log("KILL","Bomb: "+ents[i].name);
if(!bomb){
ents[i].spawn("cabal_common_oxps_mine",2);
bomb = true;
} else ents[i].spawn("cabal_common_oxps_minesub",2);
if(custSc) ents[i].remove(true);
else ents[i].remove();
} else {
if(ents[i].maxSpeed>100){
ents[i].setScript("oolite-default-ship-script.js");
ents[i].switchAI("cabal_common_leaveHotspotAI.plist");
if(this.logIt) log("KILL","Switching Script/AI for: "+ents[i].name);
} else if(this.logIt) log("KILL","Not possible. Player close to: "+ents[i].name);
}
}
}
}
}
}
if(!p){
if(this.logIt){
if(system.isInterstellarSpace) log("Check","System: Interstellar.");
else log("Check","System: "+system.name+" ID:"+system.ID+" Gov:"+system.government+" Eco:"+system.economy);
log("Check","COEF=coefficient, E=energy, S=speed, C=scanClass, name(role), W=weapons (Lasers,Turrets,SubentLaser), M=missiles, Esc=escorts, Def=Defenders, dist=distance Station,WP,Lanes(WP,WS,PS), roleMul:multiplier.");
var list = this.storage.sort();
for(var i=0;i<list.length;i++){log("Check",list[i]);}
}
} else {
var boo = player.ship.name.toLowerCase();
if(this.wayoff.length){
var patt1 = new RegExp(boo);
for(var i=0;i<this.wayoff.length;i++){
if(patt1.test(this.wayoff[i])) coef *= 2;
}
}
if(this.logIt){
if(p.isPlayer) log("Check","Playership checked in with coef: "+coef);
else log("Check","Entity "+p.name+" checked in with coef: "+coef);
log("Check","COEF=coefficient, E=energy, S=speed, C=scanClass, name(role), W=weapons (Lasers,Turrets,SubentLaser), M=missiles, Esc=escorts, Def=Defenders, dist=distance Station,WP,Lanes(WP,WS,PS), roleMul:multiplier.");
log("Check",this.storage);
}
return(parseFloat(coef));
}
return(0);
},
pad: function(n,len){
n = n.toFixed(0);
var s = n.toString();
if(s.length<len) s = ("0000000000"+s).slice(-len);
return s;
},
arrRemoveByValue: function(arr,val){
for(var i=0;i<arr.length;i++){
if(arr[i]===val){
arr.splice(i,1);
break;
}
}
return(arr);
},
binAdd: function(key,value){
var node = {key: key,left: null,right: null, value: value},current;
if(this._cclstrength === null) this._cclstrength = node;
else {
current = this._cclstrength;
while(true){
if(key<current.key){
if(current.left===null){current.left = node; break;}
else current = current.left;
} else if(key>current.key){
if(current.right===null){current.right = node; break;}
else current = current.right;
} else break;
}
}
return;
},
binContains: function(key){
var found = false,current = this._cclstrength;
while(!found && current){
if(key<current.key) current = current.left;
else if(key>current.key) current = current.right;
else found = true;
}
if(!found) return (false);
return (current.value);
}
};
|
Scripts/Cabal_Common_Overlay.js |
"use strict";
this.name = "Cabal_Common_Overlay";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Overlay handling";
this.version = "1.7";
this.startUp = function()
{
delete this.startUp;
this.ovList = [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0]];
this.ovListObj = [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0]];
this.ovInstrumentPos = [[8,8,9],[6,8,9],[4,8,9],[2,8,9],[0,8,9],[-2,8,9],[-4,8,9],[-6,8,9],[-8,8,9]];
this.ovCharacterPos = [[8,5,9],[8,3,9],[8,1,9],[8,-1,9],[8,-3,9],[-8,5,9],[-8,3,9],[-8,1,9],[-8,-1,9],[-8,-3,9]];
this.ovDeadSpotPos = [[0,0,1]];
this.ovPredicate = null;
if(oolite.gameSettings.shaderEffectsLevel==='SHADERS_OFF' || oolite.gameSettings.shaderEffectsLevel==='SHADERS_NOT_SUPPORTED') this.ovShadersOff = true;
};
this.shipWillLaunchFromStation = this.shipWillExitWitchspace = function()
{
this.doAdd();
};
this.shipLaunchedFromStation = this.shipExitedWitchspace = function()
{
this.cleanupTimer = new Timer(this,this.doCleanup,0,2);
};
this.shipWillDockWithStation = this.shipWillEnterWitchspace = function()
{
if(this.cleanupTimer){this.cleanupTimer.stop(); delete this.cleanupTimer;}
this.ovRemoveAll();
};
this.doCleanup = function()
{
for(var c=0;c<3;c++){
for(var cc=0;cc<this.ovList[c].length;cc++){
if(!this.ovList[c][cc].isValid){
this.ovList[c][cc] = 0;
this.ovListObj[c][cc] = 0;
}
}
}
return;
};
this.doAdd = function()
{
for(var o=0;o<3;o++){
for(var i=0;i<this.ovListObj[o].length;i++) if(this.ovListObj[o][i]) this.ovAdd(this.ovListObj[o][i],1);
}
for(var c=0;c<3;c++){
for(var cc=0;cc<this.ovList[c].length;cc++) if(!this.ovList[c][cc]) this.ovListObj[c][cc] = 0;
}
return;
};
// API
/* worldScripts.Cabal_Common_Overlay.ovAdd(obj,off)
obj Object. see below
off Boolean. If true overlay is added, but offscreen
obj:
cclov_id String. Identifier.
cclov_type Number. 0=Notification, 1=Character, 2=Fullscreen
cclov_autoremove Boolean. Removes effect after cclov_blend seconds
cclov_blend Number. Duration for effect.
cclov_fx Entity. VisualEffect to be used instead.
cclov_png Texture. Must be specified if cclov_fx is not used.
cclov_color Array. RGB values in range 0...3 for character overlays.
Returns:
Visual Effect (when docked true) or false */
this.ovAdd = function(obj,off){
if(!obj || typeof(obj.cclov_type)!=='number' || !obj.cclov_id) return(false);
if(!obj.whom) obj.whom = player.ship;
if(!obj.whom.isValid) return(false);
if(!obj.cclov_type) obj.cclov_type = 0;
var where = obj.whom.position,ind = -1,result,f,ents,lookup="ovList";
// Check if exists already
this.ovPredicate = obj.cclov_id;
if(player.ship.docked){
ents = this.ovFindDocked(0).concat(this.ovFindDocked(1));
lookup = "ovListObj";
} else ents = this.ovFind(0).concat(this.ovFind(1));
if(ents.length) return(false);
for(var i=0;i<this[lookup][obj.cclov_type].length;i++){
if(this[lookup][obj.cclov_type][i]===0){
ind = i;
break;
}
}
if(ind!==-1){
if(player.ship.docked){
this.ovListObj[obj.cclov_type][ind] = obj; // Store
return(true);
} else {
if(obj.cclov_fx){
f = system.addVisualEffect(obj.cclov_fx,where);
} else {
if(obj.cclov_color) f = system.addVisualEffect("ccl_overlay_color",where);
else f = system.addVisualEffect("ccl_overlay",where);
}
if(f){
if(obj.cclov_png) this.ovTexChange(f,obj.cclov_png);
f.script.cclov_tar = obj.whom;
if(this.ovShadersOff) f.script.cclov_noShade = true;
this.ovList[obj.cclov_type][ind] = f;
switch(obj.cclov_type){
case 0: result = this.ovInstrumentPos[ind]; break;
case 1: result = this.ovCharacterPos[ind]; break;
case 2: result = this.ovDeadSpotPos[ind]; break;
}
f.shaderVector1 = result;
if(obj.cclov_blend && obj.cclov_blend>0){
if(obj.cclov_type===0) f.script.cclov_blendI = clock.absoluteSeconds+obj.cclov_blend;
if(obj.cclov_type===1) f.script.cclov_blendC = clock.absoluteSeconds+obj.cclov_blend;
if(obj.cclov_type===2) f.script.cclov_blendA = clock.absoluteSeconds+obj.cclov_blend;
}
f.script.cclov_id = obj.cclov_id;
f.script.cclov_type = obj.cclov_type;
this.ovListObj[obj.cclov_type][ind] = obj; // Store
if(off && obj.cclov_blend!==-1){
if(obj.cclov_type===0) f.shaderInt2 = 20;
if(obj.cclov_type===1) f.shaderInt1 = 20;
}
if(obj.cclov_autoremove) f.script.cclov_autoremove = true;
if(obj.cclov_type===1){
if(obj.cclov_color) f.shaderVector2 = obj.cclov_color;
}
return(f);
}
}
}
return(false);
};
this.ovTexChange = function(what,cclov_png){
var mat = what.getMaterials();
var k = Object.keys(mat);
if(typeof(mat[k[0]].textures[0])==='string') mat[k[0]].textures[0] = cclov_png;
else mat[k[0]].textures[0].name = cclov_png;
mat[k[0]].emission_map = cclov_png;
mat[k[0]].ambient_color = [0,0,0,0];
mat[k[0]].diffuse_color = [0,0,0,0];
mat[k[0]].shininess = 0;
what.setMaterials(mat);
return(true);
};
this.ovSearch = function(element){
return(element.isVisualEffect && element.script.cclov_id===this.ovPredicate);
};
this.ovFind = function(cclov_type,who){
if(who) this.ovPredicate = who;
return(this.ovList[cclov_type].filter(this.ovSearch,this));
};
this.ovFindDocked = function(cclov_type,who){
if(who) this.ovPredicate = who;
return(this.ovListObj[cclov_type].filter(this.ovSearch,this));
};
/* worldScripts.Cabal_Common_Overlay.ovSpeak(who,cclov_blend,message,whom,autoremove)
who String. Identifier.
cclov_blend Number. Duration for effect.
message String.
whom Entity.
autoremove Boolean. Removes effect after cclov_blend seconds. */
this.ovSpeak = function(who,cclov_blend,message,whom,autoremove){
if(!who || !cclov_blend || !player.ship.isValid || player.ship.docked) return(false);
this.ovPredicate = who;
var ents = this.ovFind(0).concat(this.ovFind(1));
if(!ents.length) return(false);
var sc = ents[0].script;
ents[0].shaderFloat2 = cclov_blend;
if(message){
if(whom){
if(whom.isValid && whom.isShip) whom.commsMessage(message);
} else {
if(sc.cclov_type===1) player.commsMessage(who+": "+message,cclov_blend);
else player.consoleMessage(who+": "+message,cclov_blend);
}
var snd = new SoundSource();
snd.sound = "[cabal_common_commbeep]";
snd.play();
}
if(cclov_blend){
if(sc.cclov_type===0 && sc.cclov_blendI!==-1) sc.cclov_blendI = clock.absoluteSeconds+cclov_blend;
if(sc.cclov_type===1 && sc.cclov_blendC!==-1) sc.cclov_blendC = clock.absoluteSeconds+cclov_blend;
}
if(sc.valueUpdate) sc.valueUpdate();
if(autoremove) sc.cclov_autoremove = true;
return(true);
};
this.ovLog = function(){
for(var o=0;o<3;o++){
for(var i=0;i<this.ovList[o].length;i++) if(this.ovList[o][i]) log("CCL_FX","List: cclov_type:"+o+" index:"+i+" : "+this.ovList[o][i].script.cclov_id);
for(var i=0;i<this.ovListObj[o].length;i++) if(this.ovListObj[o][i]) for(var prop in this.ovListObj[o][i]) log("CCL_FX",prop+" : "+this.ovListObj[o][i][prop]);
}
return;
};
/* worldScripts.Cabal_Common_Overlay.ovRemove(who)
who String. Identifier. */
this.ovRemove = function(who){
if(!player.ship.isValid) return(false);
var ind = -1, li = 0,lookup = "ovList";
if(player.ship.docked){
lookup = "ovListObj";
for(var i=0;i<this[lookup][0].length;i++) if(this[lookup][0][i] && this[lookup][0][i].cclov_id===who){
ind = i; li = 0; break;
}
if(ind===-1){
for(var i=0;i<this[lookup][1].length;i++) if(this[lookup][1][i] && this[lookup][1][i].cclov_id===who){
ind = i; li = 1; break;
}
}
} else {
for(var i=0;i<this[lookup][0].length;i++) if(this[lookup][0][i] && this[lookup][0][i].script.cclov_id===who){
ind = i; li = 0; break;
}
if(ind===-1){
for(var i=0;i<this[lookup][1].length;i++) if(this[lookup][1][i] && this[lookup][1][i].script.cclov_id===who){
ind = i; li = 1; break;
}
}
}
if(ind===-1) return(false);
if(!player.ship.docked){
this.ovList[li][ind].remove();
this.ovList[li][ind] = 0;
}
this.ovListObj[li][ind] = 0;
return(true);
};
this.ovRemoveAll = function(){
var ar = 0;
for(var o=0;o<3;o++){
for(var i=0;i<this.ovList[o].length;i++){
ar = 0;
if(this.ovList[o][i]){
if(!this.ovList[o][i].isValid){
this.ovListObj[o][i] = 0;
this.ovList[o][i] = 0;
} else {
if(this.ovList[o][i].script.cclov_autoremove) ar = 1;
this.ovList[o][i].remove();
this.ovList[o][i] = 0;
if(ar) this.ovListObj[o][i] = 0;
}
}
}
}
return(true);
};
|
Scripts/Cabal_Common_SpecialMarkets.js |
"use strict";
this.name = "Cabal_Common_SpecialMarkets";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Additional Market for special goods";
this.version = "1.7";
this.registerLocation = function(obj)
{
if(this.startUp || !obj || !Object.isExtensible(obj)) return(0);
var req = ["item","galaxy","buyID","sellID","cb","cbb","priceclass","refresh","desc","stationID"];
var typ = ["string","object","object","object","string","string","number","number","string","object"];
var ctyp = ["gemStones","gold","platinum","alienItems","alloys","computers","firearms","food","furs","liquorWines","luxuries","machinery","minerals","narcotics","radioactives","slaves","textiles"];
for(var i=0;i<req.length;i++) if(!obj.hasOwnProperty(req[i]) || typeof(obj[req[i]])!=typ[i]) return(0);
for(var id=0;id<obj.buyID.length;id++) if(obj.sellID.indexOf(obj.buyID[id])!==-1) return(0);
var item,galaxy,buyID,sellID,stationID,cb,cbb,priceclass,refresh,desc,block,contract,contractUnit,contractDesc,offset,avail,times,decrease,blackFriday,legal,model,oneShot,blend;
item = obj.item.substr(0,40);
galaxy = obj.galaxy;
buyID = obj.buyID;
sellID = obj.sellID;
stationID = obj.stationID;
cb = obj.cb;
cbb = obj.cbb;
desc = obj.desc;
priceclass = this.helper.clamp(obj.priceclass,100,5);
refresh = this.helper.clamp(obj.refresh,1,0.06);
if(!obj.hasOwnProperty("block") || typeof(obj.block)!=="boolean") block=false;
else block = true;
if(block || !obj.hasOwnProperty("contract") || typeof(obj.contract)!=="string") contract=false;
else contract=true;
if(contract){
var c = ctyp.indexOf(obj.contract);
if(c===-1) contract=false;
else {
if(!c) contractUnit = "g";
else if(c===1 || c===2) contractUnit = "kg";
else contractUnit = "t";
contractDesc = displayNameForCommodity(ctyp[c]);
stationID=[["main"],["main"]];
}
}
if(!obj.hasOwnProperty("offset") || typeof(obj.offset)!=="number") offset=1.3;
else offset = this.helper.clamp(obj.offset,5,1.3);
if(!obj.hasOwnProperty("avail") || typeof(obj.avail)!=="number") avail=0;
else avail = this.helper.clamp(obj.avail,25,0);
if(!obj.hasOwnProperty("times") || typeof(obj.times)!=="number") times=clock.days;
else times = this.helper.clamp(obj.times,clock.days,clock.days-900);
if(!obj.hasOwnProperty("decrease") || typeof(obj.decrease)!=="number") decrease=0.1;
else decrease = this.helper.clamp(obj.decrease,0.5,0.1);
if(!obj.hasOwnProperty("blackFriday") || typeof(obj.blackFriday)!=="number") blackFriday=0;
else blackFriday = this.helper.clamp(obj.blackFriday,0.2,0);
if(!obj.hasOwnProperty("legal") || typeof(obj.legal)!=="boolean") legal=true;
else legal=false;
if(!obj.hasOwnProperty("model") || typeof(obj.model)!=="string") model="cargopod";
else model = obj.model;
if(!obj.hasOwnProperty("oneShot") || typeof(obj.oneShot)!=="boolean") oneShot=null;
else oneShot = obj.oneShot;
for(var goc=0;goc<galaxy.length;goc++){
for(var loc=0;loc<buyID.length;loc++){
if(this.hold){
for(var o=0;o<8;o++){
for(var i=0;i<this.hold[o].length;i++){
if(item===this.hold[o][i].item && buyID[loc]===this.hold[o][i].buyID){
times = this.hold[o][i].times;
if(this.hold[o][i].hasOwnProperty("blend")) blend = this.hold[o][i].blend;
if(this.hold[o][i].hasOwnProperty("hold") && !legal){
this.inspection++;
this.rockOn.push(item);
}
break;
}
}
}
}
var place = {item:item,galaxy:galaxy[goc],buyID:buyID[loc],sellID:sellID,stationID:stationID,cb:cb,cbb:cbb,priceclass:priceclass,refresh:refresh,
desc:desc,block:block,contract:contract,contractUnit:contractUnit,contractDesc:contractDesc,offset:offset,avail:avail,times:times,
decrease:decrease,blackFriday:blackFriday,legal:legal,model:model,oneShot:oneShot,blend:blend};
this.marketLocations[galaxy[goc]].push(place);
}
}
return(1);
};
// Removes item from lists
this.removeTradeItem = function(item,immediate)
{
if(!immediate && this.delayRemove && player.ship.docked) this.delayRemove.push(item);
else {
for(var o=0;o<8;o++){
for(var i=0;i<this.marketLocations[o].length;i++){
if(item===this.marketLocations[o][i].item){
this.marketLocations[o] = this.helper.arrRemoveByValue(this.marketLocations[o],this.marketLocations[o][i]);
--i;
}
}
}
}
return;
};
// Check players hold and return amount
this.checkPSHold = function(item)
{
if(this.psHold.length){
for(var i=0;i<this.psHold.length;i++){
if(this.psHold[i].item===item) return(this.psHold[i].store);
}
}
return(0);
};
this.cleanHold = function()
{
if(this.psHold.length){
for(var i=0;i<this.psHold.length;i++){
if(!this.psHold[i].stored){
this.psHold = this.helper.arrRemoveByValue(this.psHold,this.psHold[i]);
--i;
}
}
}
return;
};
this.startUp = function()
{
delete this.startUp;
this.helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
this.marketLocations = [[],[],[],[],[],[],[],[]];
this.rockOn = [];
this.psHold = [];
this.holdPage = 0;
this.prep(1);
this.mso = false;
this.inspection = 0;
if(missionVariables.ccl_markets){
this.hold = JSON.parse(missionVariables.ccl_markets);
for(var o=0;o<8;o++){
for(var i=0;i<this.hold[o].length;i++){
if(this.hold[o][i].hasOwnProperty("hold")) this.psHold.push({item:this.hold[o][i].item,stored:this.hold[o][i].hold});
}
}
missionVariables.ccl_markets = null;
}
};
this.playerWillSaveGame = function()
{
this.shipWillLaunchFromStation();
var data = [[],[],[],[],[],[],[],[]],temp,check,ind;
for(var o=0;o<8;o++){
for(var i=0;i<this.marketLocations[o].length;i++){
this.curItem = this.marketLocations[o][i];
temp = {item:this.curItem.item,buyID:this.curItem.buyID,times:this.curItem.times};
check = this.psHold.filter(this.ccls_findPSHold,this);
if(!check.length) continue;
ind = this.psHold.indexOf(check[0]);
if(ind!==-1) temp.hold = check[0].stored;
if(this.curItem.hasOwnProperty("blend")) temp.blend = this.curItem.blend;
data[o].push(temp);
}
}
missionVariables.ccl_markets = JSON.stringify(data);
this.saved = true;
};
this.guiScreenChanged = function()
{
if(!player.ship.docked) return;
if(this.saved){
missionVariables.ccl_markets = null;
delete this.saved;
}
};
this.shipWillExitWitchspace = function()
{
this.prep(1);
};
this.guiScreenWillChange = function(to)
{
if(to!=="GUI_SCREEN_EQUIP_SHIP") return;
var buys = this.marketLocations[galaxyNumber].filter(this.ccls_findBuy,this);
var sells = this.marketLocations[galaxyNumber].filter(this.ccls_findSell,this);
var temp;
sells = this.helper.arrSortByProperty(sells,"times");
for(var w=0;w<sells.length;w++){
if(temp && temp===sells[w].item){
sells = this.helper.arrRemoveByValue(sells,sells[w]);
--w;
} else temp = sells[w].item;
}
this.trades = buys.concat(sells);
if(this.trades.length){
this.prep();
EquipmentInfo.infoForKey("EQ_CABAL_COMMON_SPECIALMARKETS").effectiveTechLevel = 1;
} else missionVariables.TL_FOR_EQ_CABAL_COMMON_SPECIALMARKETS = null;
};
this.prep = function(n)
{
var temp = 0;
if(!n) temp = this.store.rnd
this.store = {diffTime:0,avail:0,totUnits:0,totBuy:0,totSell:0};
this.snd = new SoundSource();
if(n) this.store.rnd=this.helper.clamp(Math.random(),0.81,0.6);
else this.store.rnd = temp;
return;
};
this.ccls_findBuy = function(element){return(element.buyID===system.ID && ((player.ship.dockedStation.isMainStation && element.stationID[0].indexOf("main")!==-1) || (!player.ship.dockedStation.isMainStation && element.stationID[0].indexOf(player.ship.dockedStation.name)!==-1)));};
this.ccls_findSell = function(element){return(!element.contract && element.sellID.indexOf(system.ID)!==-1 && ((player.ship.dockedStation.isMainStation && element.stationID[1].indexOf("main")!==-1) || (!player.ship.dockedStation.isMainStation && element.stationID[1].indexOf(player.ship.dockedStation.name)!==-1)));};
this.ccls_findPSHold = function(element){return(element.item==this.curItem.item);};
this.shipWillLaunchFromStation = function()
{
if(this.delayRemove){
for(var i=0;i<this.delayRemove.length;i++) this.removeTradeItem(this.delayRemove[i],1);
delete this.delayRemove;
}
missionVariables.TL_FOR_EQ_CABAL_COMMON_SPECIALMARKETS = null;
delete this.curItem;
delete this.curIndex;
delete this.curPSHold;
delete this.scr;
delete this.snd;
delete this.buy;
this.mso = false;
this.cleanHold();
};
this.shipWillEnterWitchspace = function()
{
delete this.store;
};
this.playerBoughtEquipment = function(equipmentKey)
{
if(equipmentKey==="EQ_CABAL_COMMON_SPECIALMARKETS"){
player.ship.removeEquipment("EQ_CABAL_COMMON_SPECIALMARKETS");
if(!this.delayRemove) this.delayRemove = [];
this.cycleScreens();
}
return;
};
this.cycleScreens = function(){worldScripts.Cabal_Common_SpecialMarkets.cycler(); return;};
this.cycler = function()
{
if(typeof(this.scr)==="undefined") this.scr=0;
var chc = 0,txt = "",temp,l,blendOut=false;
this.curItem = this.trades[this.scr];
if(this.curItem.hasOwnProperty("blend") && clock.days<this.curItem.blend) blendOut=true;
if(this.trades.length>1) chc += 4;
if(this.curItem.buyID===system.ID) chc += 1;
if(this.curItem.sellID.indexOf(system.ID)!==-1) chc += 2;
if(this.curItem.model) this.showScreen("CABAL_COMMON_SPECIALMARKET_"+chc,this.curItem.model);
else this.showScreen("CABAL_COMMON_SPECIALMARKET_"+chc,null);
txt += this.curItem.item+(this.curItem.contract?" ("+this.curItem.contractDesc+")":"")+"\n-----------------------------------------------------\n";
if(this.curItem.contract){
this.store.tarSys = this.curItem.sellID[Math.floor(Math.random()*this.curItem.sellID.length)];
this.store.tarSysName = System.systemNameForID(this.store.tarSys);
}
this.store.diffTime = this.helper.clamp(clock.days-this.curItem.times,1000,0);
var dec = Math.log((1+this.curItem.decrease*this.store.diffTime)+(this.curItem.avail?Math.log(this.curItem.avail):0));
var prod = this.curItem.refresh*this.store.diffTime;
var prodTot = prod/(dec>1?1/dec:1);
var us = (this.store.diffTime?(this.curItem.avail+(prod?prod:0.1)/(prodTot?prodTot:1)*(this.store.diffTime-dec)/(dec>1?dec:1))/(this.curItem.offset>1?this.curItem.offset:1.3)/Math.log(this.curItem.priceclass*0.3)*this.curItem.refresh:0);
this.store.totUnits = Math.floor(us);
if((chc&1) && blendOut) this.store.totUnits = 0;
var pricernd = Math.sqrt(this.curItem.priceclass*this.store.rnd);
this.store.totBuy = (((Math.random()>0,5?this.curItem.priceclass-pricernd:this.curItem.priceclass+pricernd)/(Math.log(us+3)*this.store.rnd)/(dec>1?dec:1))/this.curItem.decrease*(this.curItem.refresh?1/this.curItem.refresh:1))/Math.sqrt(this.curItem.offset);
this.store.totBuy = parseFloat(this.store.totBuy.toFixed(1));
this.store.totSell = this.store.totBuy*(this.curItem.offset-(1/(1/this.curItem.decrease)*this.store.rnd));
this.store.totSell = parseFloat(this.store.totSell.toFixed(1));
if(chc&1){
temp=this.store.totUnits+" "+(this.curItem.block?"t":(this.curItem.contract?this.curItem.contractUnit:"g"))+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Units:",14-l," ")+temp;
temp=global.formatCredits(this.store.totBuy,1,1)+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Buy:",14-l," ")+temp;
temp=global.formatCredits(0,1,1)+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Sell:",14-l," ")+temp;
} else {
temp=this.store.totUnits+" "+(this.curItem.block?"t":(this.curItem.contract?this.curItem.contractUnit:"g"))+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Units:",14-l," ")+temp;
temp=global.formatCredits(0,1,1)+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Buy:",14-l," ")+temp;
temp=global.formatCredits(this.store.totSell,1,1)+"\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Sell:",14-l," ")+temp;
}
this.curPSHold = this.psHold.filter(this.ccls_findPSHold,this);
this.curIndex = this.psHold.indexOf(this.curPSHold[0]);
if(this.curPSHold.length) temp=this.curPSHold[0].stored+" "+(this.curItem.block?"t":(this.curItem.contract?this.curItem.contractUnit:"g"))+" / ("+player.ship.cargoSpaceAvailable+")\n";
else temp="0 "+(this.curItem.block?"t":(this.curItem.contract?this.curItem.contractUnit:"g"))+" / ("+player.ship.cargoSpaceAvailable+")\n";
if((chc&1) && player.ship.specialCargo) temp="- SEALED -\n";
l=defaultFont.measureString(temp);
txt += this.helper.strToWidth("Cargohold:",14-l," ")+temp;
txt += "-----------------------------------------------------\n";
if((chc&1)){
txt += "Cost for all available:\f("+global.formatCredits(this.store.totUnits*this.store.totBuy,1,1)+")\n";
txt += "Estimated TradeIn:\f\f("+global.formatCredits(this.store.totUnits*this.store.totSell,1,1)+")\n";
} else {
txt += "\n";
if(this.curPSHold.length) txt += "Estimated TradeIn:\f\f("+global.formatCredits(this.curPSHold[0].stored*this.store.totSell,1,1)+")\n";
else txt += "Estimated TradeIn:\f\f("+global.formatCredits(0,1,1)+")\n";
}
if(this.curItem.contract){
var t = System.infoForSystem(galaxyNumber,system.ID).distanceToSystem(System.infoForSystem(galaxyNumber,this.store.tarSys));
txt +=this.helper.strToWidth("Credits available:\f\f ("+global.formatCredits(player.credits,1,1)+")",20," ");
if(this.store.tarSys!==system.ID) txt += this.store.tarSysName+", "+t.toFixed(2)+"LY, "+this.helper.mapCoordsDirection(this.store.tarSys,system.ID)+"\n";
else txt += "\n";
} else txt += "Credits available:\f\f ("+global.formatCredits(player.credits,1,1)+")\n";
txt += "\nDescription:\n"+this.curItem.desc.substr(0,350);
mission.addMessageText(txt);
delete this.buy;
this.mso = false;
return;
};
this.showScreen = function(chc,model)
{
var spin = null,ov="cabal_common_specialmarkets_ov.png";
if(typeof(model)!=="undefined") spin = true;
if(this.curItem.block){
if(this.curItem.buyID===system.ID) ov="cabal_common_specialmarkets_ovSeal.png";
else ov="cabal_common_specialmarkets_ovUnseal.png";
} else if(this.curItem.contract) ov="cabal_common_specialmarkets_ovContract.png";
mission.runScreen({title:system.name+" Special Market",background:"cabal_common_specialmarkets.png",overlay:ov,choicesKey:chc,music:"cabal_common_specialmarkets.ogg",model:model,spinModel:spin},this.choiceEval);
if(model) this.helper.entScreenCornerPos(0.8,0.9,1.1,3.2);
return;
};
this.choiceEval = function(choice){worldScripts.Cabal_Common_SpecialMarkets.choiceEvaluation(choice); return;};
this.choiceEvaluation = function(choice)
{
if(!choice) return;
switch(choice){
case "CABAL_COMMON_SPECIALMARKETA": this.scr++; if(this.scr>=this.trades.length) this.scr=0; this.cycleScreens(); break;
case "CABAL_COMMON_SPECIALMARKETBA":
if(!player.ship.cargoSpaceAvailable || player.ship.cargoSpaceAvailable<this.store.totUnits){
this.snd.sound = "ccl_markets_fail.ogg";
} else if(player.credits>=this.store.totUnits*this.store.totBuy){
if(!this.store.totUnits){
this.snd.sound = "ccl_markets_nounits.ogg";
} else {
if(!this.curItem.contract){
if(this.curItem.block && player.ship.cargoSpaceAvailable<player.ship.cargoSpaceCapacity){
this.snd.sound = "ccl_markets_fail.ogg";
this.snd.play();
this.cycleScreens();
return;
}
if(this.curIndex===-1) this.psHold.push({item:this.curItem.item,stored:this.store.totUnits});
else this.psHold[this.curIndex].stored += this.store.totUnits;
}
player.credits -= this.store.totUnits*this.store.totBuy;
this.trades[this.scr].blend = clock.days+Math.ceil(Math.log(this.curItem.priceclass));
if(!this.curItem.legal){
this.inspection++;
this.rockOn.push(this.curItem.item);
}
if(this.curItem.block) player.ship.useSpecialCargo(this.curItem.item);
else if(this.curItem.contract){
var t = System.infoForSystem(galaxyNumber,system.ID).distanceToSystem(System.infoForSystem(galaxyNumber,this.store.tarSys))*1.3;
player.ship.awardContract(this.store.totUnits,this.curItem.contractDesc,system.ID,this.store.tarSys,clock.seconds+t*24*3600,this.store.totUnits*this.store.totSell)
}
this.snd.sound = "ccl_markets_bought.ogg";
}
} else this.snd.sound = "ccl_markets_creditsfail.ogg";
this.snd.play();
this.cycleScreens();
break;
case "CABAL_COMMON_SPECIALMARKETBN":
if(!player.ship.cargoSpaceAvailable || player.ship.cargoSpaceAvailable<this.store.totUnits){
this.snd.sound = "ccl_markets_fail.ogg";
this.snd.play();
this.cycleScreens();
} else if(!this.store.totUnits){
this.snd.sound = "ccl_markets_nounits.ogg";
this.snd.play();
this.cycleScreens();
} else {
worldScripts.Cabal_Common_Keyboard.start(this.name,1,2);
this.mso = true;
this.buy = true;
}
break;
case "CABAL_COMMON_SPECIALMARKETSA":
if(this.curIndex!==-1){
if(this.curPSHold.length && this.psHold[this.curIndex].stored){
if(worldScripts[this.trades[this.scr].cb] && worldScripts[this.trades[this.scr].cb][this.trades[this.scr].cbb]){
if(this.curItem.buyID===system.ID) this.trades[this.scr].avail += this.psHold[this.curIndex].stored;
player.credits += this.psHold[this.curIndex].stored*this.store.totSell;
var cr = this.psHold[this.curIndex].stored;
this.psHold[this.curIndex].stored = 0;
if(this.curItem.block && player.ship.specialCargo===this.curItem.item) player.ship.removeAllCargo();
var check = worldScripts[this.trades[this.scr].cb][this.trades[this.scr].cbb](this.psHold[this.curIndex].item,cr);
if(!this.curItem.legal){
this.inspection--;
if(this.inspection<0) this.inspection=0;
this.rockOn = this.helper.arrRemoveByValue(this.rockOn,this.curItem.item);
}
if(this.curItem.oneShot) this.removeTradeItem(this.curItem.item);
if(check) this.snd.sound = "ccl_markets_complete.ogg";
else {
this.snd.sound = "ccl_markets_sold.ogg";
this.snd.play();
this.mso = true;
return; // OXPs displays own screen
}
} else this.snd.sound = "ccl_markets_fail.ogg";
} else this.snd.sound = "ccl_markets_nounits.ogg";
} else this.snd.sound = "ccl_markets_nounits.ogg";
this.snd.play();
this.cycleScreens();
break;
case "CABAL_COMMON_SPECIALMARKETSN":
if(this.curPSHold.length || this.curIndex===-1 || !this.psHold[this.curIndex].stored){
this.snd.sound = "ccl_markets_nounits.ogg";
this.snd.play();
this.cycleScreens();
} else {
worldScripts.Cabal_Common_Keyboard.start(this.name,1,2);
this.mso = true;
this.buy = false;
}
break;
case "CABAL_COMMON_SPECIALMARKETP":
this.holdPage++;
if(this.holdPage*10>this.psHold.length-1) this.holdPage = 0;
var a = this.holdPage*10,chc;
if(a>this.psHold.length-1) a = 0;
chc = "CABAL_COMMON_SPECIALMARKET_OVERVIEW_3";
var b = this.helper.clamp(this.psHold.length,99,0);
b = Math.min(b,a+10);
mission.runScreen({title:"Loaded Cargo",background:"cabal_common_specialmarkets.png",overlay:"cabal_common_specialmarkets_ov.png",choicesKey:chc,music:"cabal_common_specialmarkets.ogg"},this.choiceEval);
for(var c=a;c<b;c++) mission.addMessageText(this.helper.strToWidth(this.psHold[c].item,14)+" : "+this.psHold[c].stored);
break;
case "CABAL_COMMON_SPECIALMARKETX":
this.cycleScreens();
break;
case "CABAL_COMMON_SPECIALMARKETY":
if(!this.psHold.length){
mission.runScreen({title:"Loaded Cargo",background:"cabal_common_specialmarkets.png",overlay:"cabal_common_specialmarkets_ov.png",choicesKey:"CABAL_COMMON_SPECIALMARKET_OVERVIEW_2",music:"cabal_common_specialmarkets.ogg"},this.choiceEval);
mission.addMessageText("No special good in your hold.");
} else {
var a = this.holdPage*10,chc;
if(this.psHold.length-1<10){
a = 0;
chc = "CABAL_COMMON_SPECIALMARKET_OVERVIEW_2";
} else chc = "CABAL_COMMON_SPECIALMARKET_OVERVIEW_3";
var b = this.helper.clamp(this.psHold.length,99,0);
b = Math.min(b,a+10);
mission.runScreen({title:"Loaded Cargo",background:"cabal_common_specialmarkets.png",overlay:"cabal_common_specialmarkets_ov.png",choicesKey:chc,music:"cabal_common_specialmarkets.ogg"},this.choiceEval);
for(var c=a;c<b;c++) mission.addMessageText(this.helper.strToWidth(this.psHold[c].item,14)+" : "+this.psHold[c].stored);
}
break;
case "CABAL_COMMON_SPECIALMARKETZ":
this.shipWillLaunchFromStation();
break;
default: log("Choice not handled.");
}
return;
};
this.Cabal_Common_Keyboard_Output = function(input){worldScripts.Cabal_Common_SpecialMarkets.keyboardEval(input); return;};
this.keyboardEval = function(input)
{
if(!input || input==="" || input==="0"){
this.cycleScreens();
return;
}
var cr = parseInt(input,null);
if(this.buy){
if(!player.ship.cargoSpaceAvailable || player.ship.cargoSpaceAvailable<this.store.totUnits){
this.snd.sound = "ccl_markets_fail.ogg";
} else if(player.credits>=cr*this.store.totBuy){
if(!this.store.totUnits){
this.snd.sound = "ccl_markets_nounits.ogg";
} else {
if(this.store.totUnits<cr) cr = this.store.totUnits;
if(!this.curItem.contract){
if(player.ship.cargoSpaceAvailable<player.ship.cargoSpaceCapacity){
this.snd.sound = "ccl_markets_fail.ogg";
this.snd.play();
this.cycleScreens();
return;
}
if(this.curIndex===-1) this.psHold.push({item:this.curItem.item,stored:cr});
else this.psHold[this.curIndex].stored += cr;
}
player.credits -= cr*this.store.totBuy;
this.trades[this.scr].blend = clock.days+Math.ceil(Math.log(this.curItem.priceclass)); // Only one trade? - TODO
if(!this.curItem.legal){
this.inspection++;
if(this.rockOn.indexOf(this.curItem.item)===-1) this.rockOn.push(this.curItem.item);
}
if(this.curItem.block) player.ship.useSpecialCargo(this.curItem.item);
else if(this.curItem.contract){
var t = System.infoForSystem(galaxyNumber,system.ID).distanceToSystem(System.infoForSystem(galaxyNumber,this.store.tarSys))*1.3;
player.ship.awardContract(cr,this.curItem.contractDesc,system.ID,this.store.tarSys,clock.seconds+t*24*3600,cr*this.store.totSell)
}
this.snd.sound = "ccl_markets_bought.ogg";
}
} else this.snd.sound = "ccl_markets_creditsfail.ogg";
this.snd.play();
this.cycleScreens();
} else {
if(this.psHold[this.curIndex].stored){
if(this.psHold[this.curIndex].stored<cr) cr = this.psHold[this.curIndex].stored;
if(worldScripts[this.trades[this.scr].cb] && worldScripts[this.trades[this.scr].cb][this.trades[this.scr].cbb]){
if(this.curItem.buyID===system.ID) this.trades[this.scr].avail += cr;
player.credits += cr*this.store.totSell;
this.psHold[this.curIndex].stored -= cr;
if(this.curItem.block && player.ship.specialCargo===this.curItem.item) player.ship.removeAllCargo();
if(!this.psHold[this.curIndex].stored){
this.inspection--;
if(this.inspection<0) this.inspection=0;
this.rockOn = this.helper.arrRemoveByValue(this.rockOn,this.psHold[this.curIndex].item);
}
var check = worldScripts[this.trades[this.scr].cb][this.trades[this.scr].cbb](this.psHold[this.curIndex].item,cr);
if(!this.psHold[this.curIndex].stored && this.curItem.oneShot) this.removeTradeItem(this.curItem.item);
if(check) this.snd.sound = "ccl_markets_complete.ogg";
else {
this.snd.sound = "ccl_markets_sold.ogg";
this.snd.play();
this.mso = true;
return; // OXPs displays own screen
}
} else this.snd.sound = "ccl_markets_fail.ogg";
} else this.snd.sound = "ccl_markets_nounits.ogg";
this.snd.play();
this.cycleScreens();
}
return;
};
this.missionScreenOpportunity = function()
{
if(this.mso) this.cycleScreens();
};
this.shipEnteredStationAegis = function(station)
{
if(station && this.inspection && player.ship.isValid){
if(this.rockOn.length && Math.random()>0.9){
if(worldScripts.vector_insp) worldScripts.vector_insp.startInspection(station,this.rockOn);
else {
var pen = Math.ceil(Math.sqrt(system.government+1)*this.rockOn.length);
player.addMessageToArrivalReport("You're fined with "+pen+" Credits for trading in illegal goods without license.");
player.credits -= pen;
}
}
}
};
/*
this.specialCargo = function(what,amount)
{
return(true);
};
*/
|
Scripts/cabal_common_comm_eq.js |
"use strict";
this.name = "cabal_common_comm_eq";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Secure comms channels - EQ script.";
this.version = "1.7";
this.activated = function()
{
if(!this.beep){
this.beep = new SoundSource();
this.beep.sound = "[cabal_common_commbeep]";
}
if(worldScripts.Cabal_Common_Comms.commChannelChanged){
this.store = worldScripts.Cabal_Common_Comms.commChannels;
worldScripts.Cabal_Common_Comms.commChannelChanged = false;
if(this.control) delete this.control;
}
if(!this.store) return;
if(!this.control || ((new Date()).getTime()-this.control.lastPress)>5000){
this.control = {actions:this.store,mode:0,cycleA:0,cycleB:0,selected:0,lastPress:1};
var current = this.control.actions[this.control.cycleA];
player.consoleMessage(current.display,2);
} else {
if(((new Date()).getTime()-this.control.lastPress)<1200){
var current;
if(!this.control.mode){
this.control.cycleA++;
if(this.control.cycleA>this.control.actions.length-1) this.control.cycleA = 0;
this.control.selected = this.control.cycleA;
current = this.control.actions[this.control.cycleA];
} else {
this.control.cycleB++;
if(this.control.cycleB>this.control.actions[this.control.cycleA].react.length-1) this.control.cycleB = 0;
current = this.control.actions[this.control.cycleA].react[this.control.cycleB];
}
player.consoleMessage(current.display,2);
} else {
var current,shorter;
if(!this.control.mode) current = this.control.actions[this.control.cycleA];
else current = this.control.actions[this.control.cycleA].react[this.control.cycleB];
switch(this.control.mode){
case 0:
if(current.display==="Discard"){
this.beep.play();
delete this.control;
player.consoleMessage('Cleared.',2);
return;
} else {
if(current.display==="Open channel"){
if(player.ship.target) this.requestChannel();
else player.consoleMessage('No target.',2);
delete this.control;
this.beep.play();
return;
} else {
this.control.cycleB = 0;
this.control.mode = 1;
current = this.control.actions[this.control.cycleA].react[this.control.cycleB];
}
}
player.consoleMessage(current.display,2);
break;
case 1:
if(current.display==="Back"){
this.control.cycleA = this.control.selected;
this.control.cycleB = 0;
this.control.mode = 0;
current = this.control.actions[this.control.cycleA];
} else {
shorter = this.control.actions[this.control.cycleA];
if(shorter.ent){
if(shorter.who.isValid){
if(shorter.noDist || shorter.who.position.distanceTo(player.ship.position)<25600){
shorter.who.script[shorter.callback](this.control.cycleB);
} else player.consoleMessage('Signal weak',2);
}
} else {
if(worldScripts[shorter.who] && !worldScripts[shorter.who].deactivated){
if(shorter.eID && shorter.eID.isValid){
if(shorter.eID.position.distanceTo(player.ship.position)<25600){
worldScripts[shorter.who][shorter.callback](this.control.cycleB,shorter.pID,shorter.react[this.control.cycleB]);
} else player.consoleMessage('Signal weak',2);
} else worldScripts[shorter.who][shorter.callback](this.control.cycleB,shorter.pID);
}
}
delete this.control;
this.beep.play();
return;
}
player.consoleMessage(current.display,2);
break;
}
}
}
this.control.lastPress = (new Date()).getTime();
this.beep.play();
};
this.requestChannel = function()
{
var pst = player.ship.target;
if(!pst.isShip || pst.isCargo || pst.isWeapon || pst.isRock || pst.isDerelict || !pst.isPiloted){
player.consoleMessage('Not possible.',2);
return;
}
this.patchedIDs = worldScripts.Cabal_Common_Comms.patchedIDs;
if(this.patchedIDs.indexOf(pst.entityPersonality)===-1){
if(pst.scriptInfo && pst.scriptInfo.ccl_secureChannel){
var channel = pst.scriptInfo.ccl_secureChannel;
if(pst.script[channel]){
if(worldScripts.Cabal_Common_Comms.addToComm(pst.script[channel])) player.consoleMessage('Channel created.',2);
return;
} else {
if(pst.scriptInfo.ccl_secureChannelPrep){
if(pst.script[pst.scriptInfo.ccl_secureChannelPrep]){
pst.script[pst.scriptInfo.ccl_secureChannelPrep]();
var channel = pst.scriptInfo.ccl_secureChannel;
if(worldScripts.Cabal_Common_Comms.addToComm(pst.script[channel])) player.consoleMessage('Channel created.',2);
return;
} else player.consoleMessage('Not available.',2);
} else player.consoleMessage('Not available.',2);
}
} else player.consoleMessage('Request denied.',2);
} else player.consoleMessage('Already done.',2);
return;
};
|
Scripts/cabal_common_oxps_mine.js |
"use strict";
this.name = "cabal_common_oxps_mine";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Boooh.";
this.version = "1.7";
this.shipDied = function()
{
if(this.ship.name==="CleanerMine") this.ship.spawn("cabal_common_oxps_minesub",5);
else return;
if(player.ship.isValid && this.ship.position.distanceTo(player.ship.position)<25600){
var s = new SoundSource();
s.sound = "cabal_common_bang.ogg";
s.play();
}
return;
};
|
Scripts/cabal_common_oxps_ov.js |
"use strict";
this.name = "cabal_common_oxps_ov";
this.author = "Svengali";
this.copyright = "(C)2010-2013, License:CC-by";
this.description = "Generic Overlay script.";
this.version = "1.7";
/* As view_positions are not exposed positioning is practically impossible
if shaders are off and therefor only roughly implemented.
*/
// Defaults
this.cclov_tar = player.ship;
this.cclov_blendC = -1;
this.cclov_blendI = -1;
this.cclov_blendA = -1;
this.cclov_noShade = false;
this.effectSpawned = function()
{
this.ovFCBID = addFrameCallback(this.repos.bind(this));
}
this.effectRemoved = function()
{
removeFrameCallback(this.ovFCBID);
}
this.repos = function(delta)
{
if(!player.ship.isValid || !this.cclov_tar.isValid) this.visualEffect.remove();
if(!delta) return;
if(this.cclov_blendA!==-1 && clock.absoluteSeconds>this.cclov_blendA) this.visualEffect.remove();
else {
if(this.visualEffect.shaderFloat1<1) this.visualEffect.shaderFloat1 += delta;
if(this.visualEffect.shaderFloat2>0){
this.visualEffect.shaderFloat2 -= delta;
if(this.visualEffect.shaderInt1>0) this.visualEffect.shaderInt1 -= 1;
if(this.visualEffect.shaderInt2>0) this.visualEffect.shaderInt2 -= 1;
} else {
if(this.cclov_blendC!==-1 && clock.absoluteSeconds>this.cclov_blendC){
if(this.visualEffect.shaderInt1<20) this.visualEffect.shaderInt1 += 1;
else if(this.cclov_autoremove){
this.visualEffect.remove();
return;
}
}
if(this.cclov_blendI!==-1 && clock.absoluteSeconds>this.cclov_blendI){
if(this.visualEffect.shaderInt2<20) this.visualEffect.shaderInt2 += 1;
else if(this.cclov_autoremove){
this.visualEffect.remove();
return;
}
}
}
if(!this.cclov_tar.isValid) return; // needs this check. strange.
var bb = this.cclov_tar.boundingBox;
if(this.cclov_tar.isPlayer){
switch(this.cclov_tar.viewDirection){
case "VIEW_FORWARD":
if(!this.cclov_noShade) this.visualEffect.position = this.cclov_tar.position.add(this.cclov_tar.vectorForward.multiply(bb.z));
else this.visualEffect.position = this.cclov_tar.position.add(this.cclov_tar.vectorForward.multiply(75)).add(this.cclov_tar.vectorUp.multiply(15)).subtract(this.visualEffect.shaderVector1.multiply(1.2).rotateBy(this.cclov_tar.orientation));
break;
case "VIEW_AFT":
if(!this.cclov_noShade) this.visualEffect.position = this.cclov_tar.position.subtract(this.cclov_tar.vectorForward.multiply(bb.z));
else this.visualEffect.position = this.cclov_tar.position.subtract(this.cclov_tar.vectorForward.multiply(75)).add(this.cclov_tar.vectorUp.multiply(15)).subtract(this.visualEffect.shaderVector1.multiply(1.2).rotateBy(this.cclov_tar.orientation));
break;
case "VIEW_PORT":
if(!this.cclov_noShade) this.visualEffect.position = this.cclov_tar.position.subtract(this.cclov_tar.vectorRight.multiply(bb.x));
else this.visualEffect.position = this.cclov_tar.position.subtract(this.cclov_tar.vectorRight.multiply(85)).add(this.cclov_tar.vectorUp.multiply(10)).subtract(this.visualEffect.shaderVector1.multiply(1.2).rotateBy(this.cclov_tar.orientation));
break;
case "VIEW_STARBOARD":
if(!this.cclov_noShade) this.visualEffect.position = this.cclov_tar.position.add(this.cclov_tar.vectorRight.multiply(bb.x));
else this.visualEffect.position = this.cclov_tar.position.add(this.cclov_tar.vectorRight.multiply(85)).add(this.cclov_tar.vectorUp.multiply(10)).subtract(this.visualEffect.shaderVector1.multiply(1.2).rotateBy(this.cclov_tar.orientation));
break;
case "VIEW_CUSTOM":
this.visualEffect.position = this.cclov_tar.position;
break;
case "VIEW_GUI_DISPLAY":
this.visualEffect.shaderFloat1 = 0;
break;
}
}
if(!this.cclov_tar.isValid) return; // needs this check. strange.
if(this.cclov_noShade) this.visualEffect.orientation = this.cclov_tar.orientation;
}
return;
};
|