Merge branch 'tutorial-scenario': lesson 7 and some other adjustments

This commit is contained in:
cim 2013-12-19 18:56:10 +00:00
commit 1975783f24
7 changed files with 448 additions and 7 deletions

View File

@ -806,6 +806,35 @@
"You docked without any clearance. For violating the station's docking protocol you have been fined %@."
);
// components of the tutorial's docking helper
"oolite-tutorial-dock-notarget" = "Use your identification system to target the station you wish to dock with to activate the docking assessment system.";
"oolite-tutorial-dock-weapons" = "Weapons: ";
"oolite-tutorial-dock-weapons-good" = "Disarmed\n";
"oolite-tutorial-dock-weapons-bad" = "Armed (press '[oolite_key_weapons_online_toggle]')\n";
"oolite-tutorial-dock-clearance" = "Clearance: ";
"oolite-tutorial-dock-clearance-good" = "Granted\n";
"oolite-tutorial-dock-clearance-expiring" = "Expiring ('[oolite_key_docking_clearance_request]' to extend)\n";
"oolite-tutorial-dock-clearance-bad" = "None (press '[oolite_key_docking_clearance_request]' to request)\n";
"oolite-tutorial-dock-clearance-wait" = "Waiting\n";
"oolite-tutorial-dock-approach" = "Approach: ";
"oolite-tutorial-dock-approach-good" = "On course\n";
"oolite-tutorial-dock-approach-okay" = "Adequate\n";
"oolite-tutorial-dock-approach-off" = "Off centre\n";
"oolite-tutorial-dock-approach-bad" = "Off course\n";
"oolite-tutorial-dock-speed" = "Speed: ";
"oolite-tutorial-dock-speed-fast" = "Too fast\n";
"oolite-tutorial-dock-speed-good" = "Good\n";
"oolite-tutorial-dock-speed-slow" = "Too slow\n";
"oolite-tutorial-dock-roll" = "Roll: ";
"oolite-tutorial-dock-roll-good" = "Matched\n";
"oolite-tutorial-dock-roll-okay" = "Adequate\n";
"oolite-tutorial-dock-roll-bad" = "Off course\n";
// system description after a nova
"nova-system-description" =
(

View File

@ -187,6 +187,8 @@
// tutorial
"oolite-tutorial-no-witchspace" = "Witchspace controls are not available in this simulator.";
"oolite-tutorial-no-torus" = "The torus drive is not available during this lesson.";
"oolite-tutorial-no-death" = "If this wasn't a simulator, that would have killed you. Be more careful this time!";
"oolite-tutorial-no-advance" = "Advancing with '[oolite_key_activate_equipment]' is not currently available.";
@ -353,6 +355,38 @@
"oolite-tutorial-6-10" = "Very well done! If you fly like that, you might stand a chance when the pirates come for you. That's all we've got for combat training. Press '[oolite_key_activate_equipment]' to start the next lesson.";
"oolite-tutorial-7-0" = "Lesson 7: Docking practice\nThis lesson will teach you how to dock your ship with a standard Cooperative station, and do so safely.";
"oolite-tutorial-7-1" = "Docking with the station is one of the things novice pilots often find the most difficult, and due to the size and solidity of the station, failing to dock successfully is often fatal. In this lesson, you'll learn the slow, safe way to dock. There are many shortcuts often taken by experienced pilots.";
"oolite-tutorial-7-2" = "We have added a Coriolis station to the simulator, coloured green on your scanner. As you can see, it rotates a few times every minute to provide cheap artificial gravity. There is a single docking bay, on the axis of rotation.";
"oolite-tutorial-7-3" = "In front of the station is the navigation buoy. For primary system stations this will always be on the side facing the planet - other stations may face in any direction. Fly close to the buoy, then press '[oolite_key_activate_equipment]'.";
"oolite-tutorial-7-4" = "Turn to face the station now. As you can see the docking bay is rectangular. The Cobra III is much wider than it is tall, so when you dock, you need to have the long axis of the bay as near to horizontal as possible.";
"oolite-tutorial-7-5" = "We'll start with the pre-docking checklist. Firstly, to avoid accidentally shooting your weapons at the station, put them into safe mode with the '[oolite_key_weapons_online_toggle]' key, and note the HUD message that appears. You can rearm them later with the same key.";
"oolite-tutorial-7-6" = "The next step is to request docking clearance. Target the station with your identification system (press '[oolite_key_ident_system]') and then press '[oolite_key_docking_clearance_request]' to request clearance. The station will respond, giving you a docking deadline (or if traffic is busy, requesting you wait)";
"oolite-tutorial-7-7" = "Okay, now it's time to dock. You need to do two things to dock safely - come in straight down the line extending from the docking bay, and keep the bay horizontal. If you get into trouble, just turn around, back off to the buoy, and start over. Press '[oolite_key_activate_equipment]' for a few more tips before you start.";
"oolite-tutorial-7-8" = "Docking Tips: 1/5\nOn your first few attempts, clearance might expire. The station will warn you - press '[oolite_key_docking_clearance_request]' to request an extension, which is almost always granted.";
"oolite-tutorial-7-9" = "Docking Tips: 2/5\nIf you're coming in on course, you'll be able to see all five interior walls of the bay at once. If you can't see a wall, temporarily point your nose well past the walls you can see.";
"oolite-tutorial-7-10" = "Docking Tips: 3/5\nIf you try to match the rotation before you're on course, you might get disoriented. Don't worry about the rotation until you're a kilometre or so out.";
"oolite-tutorial-7-11" = "Docking Tips: 4/5\nNormally if it's going wrong you should just stop, turn round, and try again. If you're too close, though, concentrate on getting the rotation right - your shields will bounce you in if you're reasonably close, but you just won't fit in sideways.";
"oolite-tutorial-7-12" = "Docking Tips: 5/5\nFinally, keep practicing! It will get easier.\n\nPress '[oolite_key_activate_equipment]' again to bring up a summary of your docking status.";
"oolite-tutorial-7-13-title" = "Lesson 7: Docking";
"oolite-tutorial-7-13-message" = "Well done - you've docked with some degree of success.\n\nYou can try again for some more practice, especially if this attempt didn't go particularly well, or you scraped the shields. Alternatively, if when feel ready, you can move on to the next lesson.";
"oolite-tutorial-7-13-choices" = { "01_AGAIN" = "Try again"; "02_CONTINUE" = "Continue to next lesson"; };
"oolite-tutorial-end-mfd" = "You have completed the course. Press '[oolite_key_activate_equipment]' to view your test scores.";
"oolite-tutorial-end-title" = "Course Complete";

View File

@ -3129,10 +3129,10 @@
ai_type = "nullAI.plist";
is_carrier = 1;
market = "none";
name = "Tutorial Station";
name = "Training Station";
requires_docking_clearance = 1;
roles = "oolite-tutorial-station";
rotating = no;
scan_class = "CLASS_NO_DRAW";
scan_class = "CLASS_STATION";
};
"oolite_template_sidewinder" =
{

View File

@ -65,7 +65,8 @@ this.startUp = function()
8, // stage 4: targeting + lasers
12, // stage 5: missiles + avoidance
11, // stage 6: combat
0, // stage 7: (not yet started)
15, // stage 7: docking
0, // stage 8: (not yet started)
];
this.$shipList = [];
@ -124,6 +125,34 @@ this.startUp = function()
this._nextItem();
});
}
else if (this.$tutorialStage == 7 && this.$tutorialSubstage <= 13)
{
this._setFrameCallback("");
mission.runScreen(
{
titleKey: "oolite-tutorial-7-13-title",
messageKey: "oolite-tutorial-7-13-message",
choicesKey: "oolite-tutorial-7-13-choices",
screenID: "oolite-tutorial-7-13"
},function(choice)
{
this.$advanceByEquipment = true;
player.ship.launch();
// in case the player docked early
this.$tutorialSubstage = 13;
if (choice != "01_AGAIN")
{
this._nextItem();
}
});
}
}
this.shipWillDockWithStation = function(station)
{
this._setFrameCallback("");
player.ship.setMultiFunctionText("oolite-tutorial",null);
this._resetShips(station);
}
@ -135,6 +164,16 @@ this.startUp = function()
station.remove(true);
this._nextItem();
}
else if (this.$tutorialStage == 7)
{
station.position = station.position.add([0,0,1E7]);
station.remove(true);
if (this.$tutorialSubstage != 14)
{
this.$tutorialStage--;
}
this._nextSection();
}
}
@ -160,6 +199,36 @@ this.startUp = function()
player.consoleMessage(expandMissionText("oolite-tutorial-no-witchspace"));
}
this.$blockTorus = true;
this.$blockTorusObj = null;
this.$blockTorusFCB = addFrameCallback(function(delta)
{
if ($blockTorus)
{
// doesn't help with injectors, but the player doesn't
// have those here
if (player.ship.speed > player.ship.maxSpeed)
{
if (!this.$blockTorusObj || !this.$blockTorusObj.isInSpace)
{
this.$blockTorusObj = system.addShips("[adder]",1,player.ship.position.add(player.ship.vectorUp.multiply(10000)),0)[0];
this.$blockTorusObj.scannerDisplayColor1 = [0,0,0,0];
this.$blockTorusObj.scannerDisplayColor2 = [0,0,0,0];
this.$blockTorusObj.setAI("nullAI.plist");
player.consoleMessage(expandMissionText("oolite-tutorial-no-torus"));
}
}
else if (this.$blockTorusObj)
{
this.$blockTorusObj.remove(true);
this.$blockTorusObj = null;
}
}
}.bind(this));
this._playSound = function(snd)
{
this.$tutorialSound.stop();
@ -351,16 +420,21 @@ this.startUp = function()
}
this._resetShips = function()
// exception parameter used to avoid removing the station the
// player is docked with
this._resetShips = function(exception)
{
for (var i=this.$shipList.length-1;i>=0;i--)
{
if (this.$shipList[i] && this.$shipList[i].isShip)
{
if (!exception || exception != this.$shipList[i])
{
this.$shipList[i].remove(true);
}
}
}
}
// just in case a role has been defined out by OXP
this.$roleFallbacks = {
@ -1083,7 +1157,6 @@ this.startUp = function()
this.__stage7sub0 = function()
{
if (missionVariables.oolite_tutorial_combat_stage > 0)
{
if (missionVariables.oolite_tutorial_combat_stage > 9)
@ -1100,8 +1173,80 @@ this.startUp = function()
}
}
this._setInstructions("oolite-tutorial-7-0");
}
this.__stage7sub1 = function()
{
this._setInstructions("oolite-tutorial-7-1");
}
this.__stage7sub2 = function()
{
this._setInstructions("oolite-tutorial-7-2");
var station = this._addShips("oolite-tutorial-station",1,player.ship.position,15E3)[0];
var buoy = this._addShips("oolite-tutorial-buoy",1,station.position.add(station.vectorForward.multiply(10E3)),0)[0];
}
this.__stage7sub3 = function()
{
this._setInstructions("oolite-tutorial-7-3");
}
this.__stage7sub4 = function()
{
this._setInstructions("oolite-tutorial-7-4");
}
this.__stage7sub5 = function()
{
this._setInstructions("oolite-tutorial-7-5");
}
this.__stage7sub6 = function()
{
this._setInstructions("oolite-tutorial-7-6");
}
this.__stage7sub7 = function()
{
this._setInstructions("oolite-tutorial-7-7");
}
this.__stage7sub8 = function()
{
this._setInstructions("oolite-tutorial-7-8");
}
this.__stage7sub9 = function()
{
this._setInstructions("oolite-tutorial-7-9");
}
this.__stage7sub10 = function()
{
this._setInstructions("oolite-tutorial-7-10");
}
this.__stage7sub11 = function()
{
this._setInstructions("oolite-tutorial-7-11");
}
this.__stage7sub12 = function()
{
this._setInstructions("oolite-tutorial-7-12");
}
this.__stage7sub13 = function()
{
this.$advanceByEquipment = false;
this._setFrameCallback(this._dockingMonitor.bind(this));
}
this.__stage8sub0 = function()
{
this._setInstructions("oolite-tutorial-end-mfd");
}
@ -1122,3 +1267,168 @@ this.startUp = function()
}
}
/* Define this outside the tutorial - it might be useful! */
this._dockingMonitor = function(delta)
{
var report = "";
if (!player.ship.target || !player.ship.target.isStation)
{
report += "[oolite-tutorial-dock-notarget]";
}
else
{
// check weapons
report += "[oolite-tutorial-dock-weapons]";
if (player.ship.weaponsOnline)
{
report += "[oolite-tutorial-dock-weapons-bad]";
}
else
{
report += "[oolite-tutorial-dock-weapons-good]";
}
// check clearance
report += "[oolite-tutorial-dock-clearance]";
switch (player.dockingClearanceStatus)
{
case "DOCKING_CLEARANCE_STATUS_NONE":
report += "[oolite-tutorial-dock-clearance-bad]";
break;
case "DOCKING_CLEARANCE_STATUS_REQUESTED":
report += "[oolite-tutorial-dock-clearance-wait]";
break;
case "DOCKING_CLEARANCE_STATUS_NOT_REQUIRED":
case "DOCKING_CLEARANCE_STATUS_GRANTED":
report += "[oolite-tutorial-dock-clearance-good]";
break;
case "DOCKING_CLEARANCE_STATUS_TIMING_OUT":
report += "[oolite-tutorial-dock-clearance-expiring]";
break;
}
// find dock
var station = player.ship.target;
var docks = station.subEntities;
var dock = null;
for (var i=0;i<docks.length;i++)
{
if (docks[i].isDock && docks[i].isQueued(player.ship))
{
dock = docks[i];
break;
}
}
if (dock != null)
{
// absolute position of dock
var dpos = station.position.add(station.vectorRight.multiply(dock.position.x)).add(station.vectorUp.multiply(dock.position.y)).add(station.vectorForward.multiply(dock.position.z));
// basis vectors in worldspace for dock
var dor = station.orientation.multiply(dock.orientation);
var dfwd = dor.vectorForward();
var dhoriz; var dvert; var shoriz; var svert; var dsize;
if (dock.boundingBox.y > dock.boundingBox.x)
{
// dock basis vectors
dhoriz = dor.vectorUp();
dvert = dor.vectorRight();
// safety margins
shoriz = (dock.boundingBox.y - player.ship.boundingBox.x)/2;
svert = (dock.boundingBox.x - player.ship.boundingBox.y)/2;
dsize = dock.boundingBox.x / 2;
}
else
{
dvert = dor.vectorUp();
dhoriz = dor.vectorRight();
// safety margins
shoriz = (dock.boundingBox.x - player.ship.boundingBox.x)/2
svert = (dock.boundingBox.y - player.ship.boundingBox.y)/2;
dsize = dock.boundingBox.y / 2;
}
// check approach direction and course
report += "[oolite-tutorial-dock-approach]";
var relpos = dpos.subtract(player.ship.position);
var distance = relpos.magnitude();
if (player.ship.vectorForward.dot(relpos.direction()) < Math.cos(Math.atan(dsize/distance)) && distance > dock.boundingBox.z)
{
report += "[oolite-tutorial-dock-approach-bad]";
}
else
{
var x = Math.abs(dhoriz.dot(relpos));
var y = Math.abs(dvert.dot(relpos));
if (x < shoriz && y < svert)
{
report += "[oolite-tutorial-dock-approach-good]";
}
else if (Math.abs(dfwd.dot(relpos)) > 0.999 && distance > 750)
{
report += "[oolite-tutorial-dock-approach-okay]";
}
else if (x < shoriz+50 && y < svert+50)
{
report += "[oolite-tutorial-dock-approach-okay]";
}
else
{
report += "[oolite-tutorial-dock-approach-off]";
}
}
// check speed
report += "[oolite-tutorial-dock-speed]";
var target = 40;
if (distance > 1000)
{
target = 75;
if (distance > 2000)
{
target = 120;
if (distance > 4000)
{
target = 200;
}
}
}
if (player.ship.speed > target * 1.5)
{
report += "[oolite-tutorial-dock-speed-fast]";
}
else if (player.ship.speed < target * 0.5)
{
report += "[oolite-tutorial-dock-speed-slow]";
}
else
{
report += "[oolite-tutorial-dock-speed-good]";
}
// check roll
report += "[oolite-tutorial-dock-roll]";
var roll = Math.abs(player.ship.vectorRight.dot(dhoriz));
if (roll > 0.999)
{
report += "[oolite-tutorial-dock-roll-good]";
}
else if (roll > 0.99)
{
report += "[oolite-tutorial-dock-roll-okay]";
}
else
{
report += "[oolite-tutorial-dock-roll-bad]";
}
}
}
var result = expandDescription(report);
player.ship.setMultiFunctionText("oolite-tutorial",result,true);
player.ship.setMultiFunctionDisplay(0,"oolite-tutorial");
}

View File

@ -629,6 +629,11 @@ MA 02110-1301, USA.
{
return YES;
}
// player docking manually
if ([ship isPlayer] && [[self owner] playerReservedDock] == self)
{
return YES;
}
return NO;
}

View File

@ -2708,6 +2708,18 @@ static OOPolygonSprite *IconForMissileRole(NSString *role)
- (void) drawWeaponsOfflineText:(NSDictionary *)info
{
OOViewID viewID = [UNIVERSE viewDirection];
if (viewID == VIEW_CUSTOM ||
overallAlpha == 0.0f ||
!([PLAYER status] == STATUS_IN_FLIGHT || [PLAYER status] == STATUS_WITCHSPACE_COUNTDOWN) ||
[UNIVERSE displayGUI]
)
{
// Don't draw weapons offline text
return;
}
if (![PLAYER weaponsOnline])
{
int x, y;

View File

@ -34,6 +34,9 @@ MA 02110-1301, USA.
static JSObject *sDockPrototype;
static BOOL JSDockGetDockEntity(JSContext *context, JSObject *stationObj, DockEntity **outEntity);
static BOOL JSDockGetShipEntity(JSContext *context, JSObject *shipObj, ShipEntity **outEntity);
static JSBool DockIsQueued(JSContext *context, uintN argc, jsval *vp);
static JSBool DockGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
@ -83,6 +86,7 @@ static JSPropertySpec sDockProperties[] =
static JSFunctionSpec sDockMethods[] =
{
// JS name Function min args
{ "isQueued", DockIsQueued, 1 },
{ 0 }
};
@ -117,6 +121,28 @@ static BOOL JSDockGetDockEntity(JSContext *context, JSObject *dockObj, DockEntit
}
static BOOL JSDockGetShipEntity(JSContext *context, JSObject *shipObj, ShipEntity **outEntity)
{
OOJS_PROFILE_ENTER
BOOL result;
Entity *entity = nil;
if (outEntity == NULL) return NO;
*outEntity = nil;
result = OOJSEntityGetEntity(context, shipObj, &entity);
if (!result) return NO;
if (![entity isKindOfClass:[ShipEntity class]]) return NO;
*outEntity = (ShipEntity *)entity;
return YES;
OOJS_PROFILE_EXIT
}
@implementation DockEntity (OOJavaScriptExtensions)
- (void)getJSClass:(JSClass **)outClass andPrototype:(JSObject **)outPrototype
@ -227,3 +253,28 @@ static JSBool DockSetProperty(JSContext *context, JSObject *this, jsid propID, J
// *** Methods ***
static JSBool DockIsQueued(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
BOOL result = NO;
DockEntity *dock = nil;
JSDockGetDockEntity(context, OOJS_THIS, &dock);
if (argc == 0)
{
OOJSReportBadArguments(context, @"Dock", @"isQueued", MIN(argc, 1U), OOJS_ARGV, nil, @"ship");
return NO;
}
ShipEntity *ship = nil;
JSDockGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &ship);
if (ship != nil)
{
result = [dock shipIsInDockingQueue:ship];
}
OOJS_RETURN_BOOL(result);
OOJS_NATIVE_EXIT
}