~harrison-rt/+junk/jaguar_company

« back to all changes in this revision

Viewing changes to tags/2.3/jaguar_company_2.3.oxp/Scripts/jaguar_company_base.js

  • Committer: Richard Harrison
  • Date: 2013-01-19 23:01:03 UTC
  • Revision ID: harrison.rt@gmail.com-20130119230103-hukuh0h9jorz3hk1
Tags: 2.4
* Bug fix for spawning Jaguar Company. Potential to spawn the base at all times if the Galactic Navy wasn't present.
* Bug fix for checking the safe zone around the base. Wasn't checking to see if it actually existed.
* Main world script saves the last system ID that was visited for interstellar space.
* Timer on start up for the worldscripts has been added to allow each worldscript to be loaded in. Stops a potential dependency error happening.
* Stray commas in the route list arrays removed.
* Welcome code has been cleaned up.
* missiontext.plist and descriptions.plist cleaned up.
* Altered all player consoleMessage's to show messages for the default time limit.
* Changed all player commsMessage's to consoleMessage.
* Changed some of the player consoleMessage's back into commsMessage.
* Only insert news into Snoopers about battle help if more than 10 minutes has passed since the last news item was inserted.
* If you set $alwaysSpawn to true with OXPConfig the base will be spawned if it doesn't exist.
* Patrol ships follow the Galactic Navy.
** If by some freak accident, all of the Galactic Navy is destroyed, the patrol ships will go back to base if it exists. Otherwise they will patrol the witchpoint to planet lane.
* New reputation level. Shows the location of Jaguar Company Bases in the current galaxy.
** Re-implementation of the game random number generators for system.pseudoRandomNumber and system.scrambledPseudoRandomNumber, to allow checking of all the systems in the current galaxy. The system versions only gives back a value for the current system.
** Oolite v1.76.1 or older only show a list of system names. Go to the long range chart then select the status screen (F6, F6, F5). Borrowed some code from Spara's Trophy Collector OXP for this.
** Oolite v1.77 or newer display the locations on the long range chart. Uses the new object method of mission.markSystem so it won't intefere with other OXPs. (Hopefully)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*jslint indent: 4, maxlen: 120, maxerr: 50, white: true, es5: true, undef: true, regexp: true, newcap: true */
 
2
/*jshint es5: true, undef: true, eqnull: true, noempty: true, eqeqeq: true, boss: true, loopfunc: true, laxbreak: true,
 
3
strict: true, curly: true */
 
4
/*global system, log, worldScripts, missionVariables, Timer */
 
5
 
 
6
/* Jaguar Company Base
 
7
 *
 
8
 * Copyright © 2012 Richard Thomas Harrison (Tricky)
 
9
 *
 
10
 * This work is licensed under the Creative Commons
 
11
 * Attribution-Noncommercial-Share Alike 3.0 Unported License.
 
12
 *
 
13
 * To view a copy of this license, visit
 
14
 * http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter
 
15
 * to Creative Commons, 171 Second Street, Suite 300, San Francisco,
 
16
 * California, 94105, USA.
 
17
 *
 
18
 * Ship related functions for the base AI.
 
19
 */
 
20
 
 
21
(function () {
 
22
    "use strict";
 
23
 
 
24
    /* Standard public variables for OXP scripts. */
 
25
    this.name = "jaguar_company_base.js";
 
26
    this.author = "Tricky";
 
27
    this.copyright = "© 2012 Richard Thomas Harrison (Tricky)";
 
28
    this.license = "CC BY-NC-SA 3.0";
 
29
    this.description = "Ship script for the Jaguar Company Base.";
 
30
    this.version = "1.4";
 
31
 
 
32
    /* Private variable. */
 
33
    var p_base = {};
 
34
 
 
35
    /* Ship event callbacks. */
 
36
 
 
37
    /* Initialise various variables on ship birth. */
 
38
    this.shipSpawned = function () {
 
39
        var num,
 
40
        vector,
 
41
        cross,
 
42
        angle;
 
43
 
 
44
        /* No longer needed after setting up. */
 
45
        delete this.shipSpawned;
 
46
 
 
47
        /* Initialise the p_base variable object.
 
48
         * Encapsulates all private global data.
 
49
         */
 
50
        p_base = {
 
51
            /* Cache the world scripts. */
 
52
            mainScript : worldScripts["Jaguar Company"],
 
53
            attackersScript : worldScripts["Jaguar Company Attackers"],
 
54
            /* Local copies of the logging variables. */
 
55
            logging : worldScripts["Jaguar Company"].$logging,
 
56
            logExtra : worldScripts["Jaguar Company"].$logExtra
 
57
        };
 
58
 
 
59
        /* Register this base as a friendly. */
 
60
        p_base.attackersScript.$addFriendly(this.ship);
 
61
 
 
62
        if (p_base.mainScript.$swapBase) {
 
63
            /* Swapping base roles. */
 
64
 
 
65
            /* How many patrol ships have launched. */
 
66
            p_base.patrolShipsLaunched = system.shipsWithPrimaryRole("jaguar_company_patrol").length;
 
67
            /* Has the miner launched. */
 
68
            p_base.minerLaunched = (system.shipsWithRole("jaguar_company_miner").length !== 0);
 
69
            /* Base fully spawned and set-up so we can reset this. */
 
70
            p_base.mainScript.$swapBase = false;
 
71
        } else {
 
72
            /* Get a unique name for the base.
 
73
             * Maximum length (not including prefix) for the base's name is 16 characters.
 
74
             * Fits perfectly into the mission screen title header.
 
75
             */
 
76
            this.ship.displayName = p_base.mainScript.$uniqueShipName(this.ship.name, 16);
 
77
 
 
78
            if (!system.isInterstellarSpace) {
 
79
                /* Point the docking bay in the general direction of the sun. */
 
80
                vector = system.sun.position.subtract(this.ship.position).direction();
 
81
            } else {
 
82
                /* Point the docking bay in the general direction of the fake witchpoint. */
 
83
                vector = p_base.mainScript.$witchpointBuoy.position.subtract(this.ship.position).direction();
 
84
            }
 
85
 
 
86
            /* Angle to the vector from current heading + about 1/8th turn. */
 
87
            angle = this.ship.heading.angleTo(vector) + 0.707;
 
88
            /* Cross vector for rotate. */
 
89
            cross = this.ship.heading.cross(vector).direction();
 
90
            /* Rotate the base by angle. */
 
91
            this.ship.orientation = this.ship.orientation.rotate(cross, -angle);
 
92
 
 
93
            /* Add some clutter within 20km around the base.
 
94
             * 20 to 27 asteroids and 10 to 17 boulders
 
95
             * - gives the miners something to do. (Also apparently any Thargoids!)
 
96
             */
 
97
            num = Math.floor(system.scrambledPseudoRandomNumber(p_base.mainScript.$salt) * 8) + 20;
 
98
            system.addShips("jaguar_company_asteroid", num, this.ship.position, 20000);
 
99
            num = Math.floor(system.scrambledPseudoRandomNumber(p_base.mainScript.$salt / 2) * 8) + 10;
 
100
            system.addShips("jaguar_company_boulder", num, this.ship.position, 20000);
 
101
 
 
102
            /* Reset the launch status of the buoy. */
 
103
            p_base.mainScript.$buoyLaunched = false;
 
104
            /* Miner has not launched. */
 
105
            p_base.minerLaunched = false;
 
106
 
 
107
            if (!system.shipsWithPrimaryRole("jaguar_company_patrol").length) {
 
108
                /* Reset how many Jaguar Company patrol ships are in system. */
 
109
                p_base.mainScript.$numPatrolShips = 0;
 
110
                /* No patrol ships have launched. */
 
111
                p_base.patrolShipsLaunched = 0;
 
112
                /* Reset the fully launched status of the patrol ships. */
 
113
                p_base.mainScript.$patrolShipsFullyLaunched = false;
 
114
            } else {
 
115
                /* Set how many Jaguar Company patrol ships are in system. */
 
116
                p_base.mainScript.$numPatrolShips = system.shipsWithPrimaryRole("jaguar_company_patrol").length;
 
117
                /* All patrol ships have launched. */
 
118
                p_base.patrolShipsLaunched = p_base.mainScript.$numPatrolShips;
 
119
                /* Set the fully launched status of the patrol ships. */
 
120
                p_base.mainScript.$patrolShipsFullyLaunched = true;
 
121
            }
 
122
        }
 
123
 
 
124
        /* Start up the timer to do some house keeping. */
 
125
        this.$baseTimerReference = new Timer(this, this.$baseTimer, 5, 5);
 
126
    };
 
127
 
 
128
    /* Base was destroyed.
 
129
     * Called after the script installed by $addFriendly in jaguar_company_attackers.js
 
130
     *
 
131
     * INPUTS
 
132
     *   attacker - entity that caused the death.
 
133
     *   why - cause as a string.
 
134
     */
 
135
    this.shipDied = function (attacker, why) {
 
136
        var mainScript,
 
137
        base = this.ship,
 
138
        basePosition,
 
139
        witchpointBuoy,
 
140
        mainPlanet,
 
141
        mPovUp,
 
142
        ratio,
 
143
        entities,
 
144
        salt,
 
145
        ok;
 
146
 
 
147
        /* Stop warnings about anonymous local functions within loops.
 
148
         * Used by 'system.filteredEntities'. Returns true for any valid entity.
 
149
         */
 
150
        function $validEntity(entity) {
 
151
            return (entity && entity.isValid);
 
152
        }
 
153
 
 
154
        if (base.name === base.displayName) {
 
155
            /* Died whilst being created. The base will not have had it's display name set up. */
 
156
            mainScript = worldScripts["Jaguar Company"];
 
157
            witchpointBuoy = mainScript.$witchpointBuoy;
 
158
            mainPlanet = system.mainPlanet;
 
159
            salt = mainScript.$salt;
 
160
            ok = false;
 
161
 
 
162
            /* Shift the base position if it is too close to any entity.
 
163
             * If we happen to pick a new position that would collide with something already in the system
 
164
             * then the loop will pick another position and so on.
 
165
             * In practice the loop will only happen once as space is BIG.
 
166
             */
 
167
            while (!ok) {
 
168
                /* Increase the salt. */
 
169
                salt += 1;
 
170
                /* Place the base 0.1 to 0.3 units along the witchpoint -> main planet route. */
 
171
                ratio = 0.1 + (system.scrambledPseudoRandomNumber(salt) * 0.2);
 
172
                basePosition = Vector3D.interpolate(witchpointBuoy.position, mainPlanet.position, ratio);
 
173
                /* Move it 4 to 6 times scanning range upwards with respect to the main planet's surface. */
 
174
                ratio = (4 + (system.scrambledPseudoRandomNumber(salt) * 2)) * 25600;
 
175
                mPovUp = mainPlanet.orientation.vectorUp();
 
176
                base.position = basePosition.add(mPovUp.multiply(mainPlanet.radius + ratio)); 
 
177
                /* Search for any entity intersecting this base within scanner range. */
 
178
                entities = system.filteredEntities(this, $validEntity, base, 25600);
 
179
                /* An empty array is what we are looking for. */
 
180
                ok = !entities.length;
 
181
            }
 
182
 
 
183
            if (mainScript.$logging && mainScript.$logExtra) {
 
184
                log(this.name, "shipDied::\n" +
 
185
                    "Base respawning: " + why + " whilst being created.\n" +
 
186
                    "* WP-Sun dot WP-MP: " +
 
187
                    (witchpointBuoy.position.subtract(system.sun.position).direction()
 
188
                        .dot(witchpointBuoy.position.subtract(mainPlanet.position).direction())) + "\n" +
 
189
                    "* Moved: " + (salt - mainScript.$salt) + " times.");
 
190
            }
 
191
 
 
192
            /* Spawn a new base. Update the public variable in the main script. */
 
193
            mainScript.$jaguarCompanyBase = base.spawnOne("jaguar_company_base");
 
194
 
 
195
            return;
 
196
        }
 
197
    };
 
198
 
 
199
    /* Base was removed by script. */
 
200
    this.shipRemoved = function (suppressDeathEvent) {
 
201
        if (suppressDeathEvent) {
 
202
            return;
 
203
        }
 
204
 
 
205
        /* Set this as no more ships will be launched. "Obvious cat is obvious!" */
 
206
        worldScripts["Jaguar Company"].$patrolShipsFullyLaunched = true;
 
207
    };
 
208
 
 
209
    /* The base has just become invalid. */
 
210
    this.entityDestroyed = function () {
 
211
        /* Set this as no more ships will be launched. "Obvious cat is obvious!" */
 
212
        worldScripts["Jaguar Company"].$patrolShipsFullyLaunched = true;
 
213
 
 
214
        /* Stop and remove the timer. */
 
215
        if (this.$baseTimerReference) {
 
216
            if (this.$baseTimerReference.isRunning) {
 
217
                this.$baseTimerReference.stop();
 
218
            }
 
219
 
 
220
            delete this.$baseTimerReference;
 
221
        }
 
222
    };
 
223
 
 
224
    /* A ship has docked.
 
225
     *
 
226
     * INPUT
 
227
     *   whom - entity of the docked ship.
 
228
     */
 
229
    this.otherShipDocked = function (whom) {
 
230
        if (whom.hasRole("jaguar_company_patrol")) {
 
231
            /* Decrease the number of patrol ships that are launched. */
 
232
            p_base.patrolShipsLaunched -= 1;
 
233
        } else if (whom.hasRole("jaguar_company_miner")) {
 
234
            /* Reset the launch status of the miner. */
 
235
            p_base.mainScript.$minerLaunched = false;
 
236
        }
 
237
    };
 
238
 
 
239
    /* A ship has launched.
 
240
     *
 
241
     * INPUT
 
242
     *   whom - entity of the launched ship.
 
243
     */
 
244
    this.stationLaunchedShip = function (whom) {
 
245
        if (whom.hasRole("jaguar_company_patrol")) {
 
246
            if (p_base.patrolShipsLaunched === 1) {
 
247
                /* Initialise the route list with the default route. */
 
248
                p_base.mainScript.$initRoute();
 
249
            }
 
250
 
 
251
            if (whom.script.name !== "jaguar_company_patrol.js") {
 
252
                /* Remove the patrol ship. */
 
253
                whom.remove();
 
254
                /* Decrease the number of patrol ships that are launched. */
 
255
                p_base.patrolShipsLaunched -= 1;
 
256
 
 
257
                if (p_base.logging && p_base.logExtra) {
 
258
                    log(this.name, "Script sanity check - fixed a patrol ship.");
 
259
                }
 
260
            }
 
261
 
 
262
            if (p_base.patrolShipsLaunched !== p_base.mainScript.$maxPatrolShips) {
 
263
                /* Launch another patrol ship. */
 
264
                this.$launchJaguarCompanyPatrol();
 
265
            } else {
 
266
                /* All patrol ships are now fully launched. */
 
267
                p_base.mainScript.$patrolShipsFullyLaunched = true;
 
268
            }
 
269
        } else if (whom.hasRole("jaguar_company_tug")) {
 
270
            if (whom.script.name !== "jaguar_company_tug.js") {
 
271
                /* Remove the tug. */
 
272
                whom.remove();
 
273
                /* Reset the launch status of the buoy. */
 
274
                p_base.mainScript.$buoyLaunched = false;
 
275
                /* Launch another tug. */
 
276
                this.$launchJaguarCompanyTug();
 
277
 
 
278
                if (p_base.logging && p_base.logExtra) {
 
279
                    log(this.name, "Script sanity check - fixed the tug.");
 
280
                }
 
281
            }
 
282
        } else if (whom.hasRole("jaguar_company_miner")) {
 
283
            if (whom.script.name !== "jaguar_company_miner.js") {
 
284
                /* Remove the miner. */
 
285
                whom.remove();
 
286
                /* Reset the launch status of the miner. */
 
287
                p_base.mainScript.$minerLaunched = false;
 
288
                /* Launch another miner. */
 
289
                this.ship.launchShipWithRole("jaguar_company_miner");
 
290
 
 
291
                if (p_base.logging && p_base.logExtra) {
 
292
                    log(this.name, "Script sanity check - fixed the miner.");
 
293
                }
 
294
            }
 
295
        }
 
296
    };
 
297
 
 
298
    /* Timer callback. */
 
299
 
 
300
    /* Some OXP's dick around with the scanner colours. This will reset the base's scanner colour
 
301
     * back to the station default of solid green if the player has helped out in combat with Jaguar Company.
 
302
     *
 
303
     * Starts the launch sequence for the patrol ships if needed.
 
304
     *
 
305
     * Checks the buoy and launches a tug if there isn't one. Resets the scanner colour as per the base.
 
306
     * Swaps the buoy to 'no beacon' or 'beacon' dependent on the reputation mission variable.
 
307
     *
 
308
     * Called every 5 seconds.
 
309
     */
 
310
    this.$baseTimer = function () {
 
311
        var base = this.ship,
 
312
        position,
 
313
        orientation,
 
314
        buoy,
 
315
        newBuoy,
 
316
        newBuoyRole;
 
317
 
 
318
        /* Reset the base scanner colour. */
 
319
        base.scannerDisplayColor1 = null;
 
320
        base.scannerDisplayColor2 = null;
 
321
 
 
322
        if (!p_base.patrolShipsLaunched) {
 
323
            /* Start launching patrol ships. */
 
324
            this.$launchJaguarCompanyPatrol();
 
325
        }
 
326
 
 
327
        if (p_base.patrolShipsLaunched !== p_base.mainScript.$maxPatrolShips) {
 
328
            /* Reset the fully launched status of the patrol ships. */
 
329
            p_base.mainScript.$patrolShipsFullyLaunched = false;
 
330
        }
 
331
 
 
332
        buoy = p_base.mainScript.$buoy;
 
333
 
 
334
        if ((!buoy || !buoy.isValid) &&
 
335
            !p_base.mainScript.$buoyLaunched && p_base.mainScript.$patrolShipsFullyLaunched) {
 
336
            /* No buoys. Launch the tug to drop a buoy off. */
 
337
            this.$launchJaguarCompanyTug();
 
338
 
 
339
            return;
 
340
        }
 
341
 
 
342
        if (buoy && buoy.isValid) {
 
343
            /* Reset the buoy scanner colour. */
 
344
            buoy.scannerDisplayColor1 = null;
 
345
            buoy.scannerDisplayColor2 = null;
 
346
 
 
347
            if (missionVariables.jaguar_company_reputation < p_base.mainScript.$reputationHelper) {
 
348
                newBuoyRole = "jaguar_company_base_buoy_no_beacon";
 
349
            } else {
 
350
                newBuoyRole = "jaguar_company_base_buoy_beacon";
 
351
            }
 
352
 
 
353
            /* Check if the buoy already has the new role. */
 
354
            if (!buoy.hasRole(newBuoyRole)) {
 
355
                /* Copy some properties. */
 
356
                position = buoy.position;
 
357
                orientation = buoy.orientation;
 
358
                /* Create a new buoy. */
 
359
                newBuoy = buoy.spawnOne(newBuoyRole);
 
360
                /* Remove the origial buoy quietly: don't trigger 'shipDied' in the ship script. */
 
361
                buoy.remove(true);
 
362
                /* Setup the new buoy with the original properties. */
 
363
                newBuoy.position = position;
 
364
                newBuoy.orientation = orientation;
 
365
                /* Update the main script public variable. */
 
366
                p_base.mainScript.$buoy = newBuoy;
 
367
            }
 
368
        }
 
369
    };
 
370
 
 
371
    /* Launch a patrol ship. */
 
372
    this.$launchJaguarCompanyPatrol = function () {
 
373
        if (p_base.logging && p_base.logExtra) {
 
374
            log(this.name, "$launchJaguarCompanyPatrol::Launching patrol ship...");
 
375
        }
 
376
 
 
377
        p_base.patrolShipsLaunched += 1;
 
378
        this.ship.launchShipWithRole("jaguar_company_patrol");
 
379
    };
 
380
 
 
381
    /* Launch the tug to drag the buoy into position. */
 
382
    this.$launchJaguarCompanyTug = function () {
 
383
        if (p_base.mainScript.$patrolShipsFullyLaunched &&
 
384
            !p_base.mainScript.$buoyLaunched &&
 
385
            (!p_base.mainScript.$buoy || !p_base.mainScript.$buoy.isValid)) {
 
386
            /* Only one tug dragging a buoy at a time. Also no more than 1 buoy in system at a time.
 
387
             * Also don't launch until all patrol ships have launched.
 
388
             */
 
389
            p_base.mainScript.$buoyLaunched = true;
 
390
            this.ship.launchShipWithRole("jaguar_company_tug");
 
391
 
 
392
            if (p_base.logging && p_base.logExtra) {
 
393
                log(this.name, "$launchJaguarCompanyTug::Launching tug...");
 
394
            }
 
395
        }
 
396
    };
 
397
 
 
398
    /* AI functions. */
 
399
 
 
400
    /* Check if we need to launch a miner. Don't launch in interstellar space. */
 
401
    this.$launchShip = function () {
 
402
        if (!system.isInterstellarSpace &&
 
403
            Math.random() < 0.05 &&
 
404
            !p_base.minerLaunched &&
 
405
            p_base.mainScript.$patrolShipsFullyLaunched) {
 
406
            /* Only 1 miner at a time.
 
407
             * Also don't launch until all patrol ships have launched.
 
408
             */
 
409
            p_base.minerLaunched = true;
 
410
            this.ship.launchShipWithRole("jaguar_company_miner");
 
411
 
 
412
            if (p_base.logging && p_base.logExtra) {
 
413
                log(this.name, "$launchShip::Launching miner...");
 
414
            }
 
415
        }
 
416
    };
 
417
}).call(this);