~harrison-rt/+junk/jaguar_company

« back to all changes in this revision

Viewing changes to tags/2.0/jaguar_company_2.0.oxp/Scripts/jaguar_company_base.js

  • Committer: Richard Harrison
  • Date: 2013-01-19 22:54:57 UTC
  • Revision ID: harrison.rt@gmail.com-20130119225457-ymm3tf03jao7b3lp
Tags: 2.1
* Thargoids and tharglets always returns true in $isHostile check.
* There is a safe zone of 30km around the base.
** NB: The safe zone does not extend to known attackers.
* Took out some ship script event handlers and AI sendScriptMessage functions from the base, buoy, miner and tug ship scripts that is inserted by $addFriendly.
* Fixed colour bug with the tracker. Didn't start off red if the target was behind the player.
* Fixed name error for $performJaguarCompanyAttackTarget in $addFriendly.
* Fixed sun check error if no sun exists.

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, bitwise: true, regexp: true,
 
2
newcap: true */
 
3
/*jshint es5: true, undef: true, bitwise: true, eqnull: true, noempty: true, eqeqeq: true, boss: true, loopfunc: true,
 
4
laxbreak: true, strict: true, curly: true */
 
5
/*global system, log, worldScripts, missionVariables, Timer, player */
 
6
 
 
7
/* Jaguar Company Base
 
8
 *
 
9
 * Copyright © 2012 Richard Thomas Harrison (Tricky)
 
10
 *
 
11
 * This work is licensed under the Creative Commons
 
12
 * Attribution-Noncommercial-Share Alike 3.0 Unported License.
 
13
 *
 
14
 * To view a copy of this license, visit
 
15
 * http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter
 
16
 * to Creative Commons, 171 Second Street, Suite 300, San Francisco,
 
17
 * California, 94105, USA.
 
18
 *
 
19
 * Ship related functions for the base AI.
 
20
 */
 
21
 
 
22
(function () {
 
23
    "use strict";
 
24
 
 
25
    /* Standard public variables for OXP scripts. */
 
26
    this.name = "jaguar_company_base.js";
 
27
    this.author = "Tricky";
 
28
    this.copyright = "© 2012 Richard Thomas Harrison (Tricky)";
 
29
    this.license = "CC BY-NC-SA 3.0";
 
30
    this.description = "Ship script for the Jaguar Company Base.";
 
31
    this.version = "1.2";
 
32
 
 
33
    /* Private variable. */
 
34
    var p_base = {};
 
35
 
 
36
    /* Ship event callbacks. */
 
37
 
 
38
    /* Initialise various variables on ship birth. */
 
39
    this.shipSpawned = function () {
 
40
        var num,
 
41
        vector,
 
42
        cross,
 
43
        angle;
 
44
 
 
45
        /* No longer needed after setting up. */
 
46
        delete this.shipSpawned;
 
47
 
 
48
        /* Initialise the p_base variable object.
 
49
         * Encapsulates all private global data.
 
50
         */
 
51
        p_base = {
 
52
            /* Cache the world scripts. */
 
53
            mainScript : worldScripts["Jaguar Company"],
 
54
            attackersScript : worldScripts["Jaguar Company Attackers"],
 
55
            /* Local copies of the logging variables. */
 
56
            logging : worldScripts["Jaguar Company"].$logging,
 
57
            logExtra : worldScripts["Jaguar Company"].$logExtra
 
58
        };
 
59
 
 
60
        /* Register this base as a friendly. */
 
61
        p_base.attackersScript.$addFriendly(this.ship);
 
62
 
 
63
        if (p_base.mainScript.$swapBase) {
 
64
            /* Swapping base roles. */
 
65
 
 
66
            /* How many patrol ships have launched. */
 
67
            p_base.patrolShipsLaunched = system.shipsWithPrimaryRole("jaguar_company_patrol").length;
 
68
            /* Has the miner launched. */
 
69
            p_base.minerLaunched = (system.shipsWithRole("jaguar_company_miner").length !== 0);
 
70
            /* Base fully spawned and set-up so we can reset this. */
 
71
            p_base.mainScript.$swapBase = false;
 
72
        } else {
 
73
            /* Get a unique name for the base.
 
74
             * Maximum length (not including prefix) for the base's name is 16 characters.
 
75
             * Fits perfectly into the mission screen title header.
 
76
             */
 
77
            this.ship.displayName = p_base.mainScript.$uniqueShipName(this.ship.name, 16);
 
78
 
 
79
            if (!system.isInterstellarSpace) {
 
80
                /* Point the docking bay in the general direction of the sun. */
 
81
                vector = system.sun.position.subtract(this.ship.position).direction();
 
82
            } else {
 
83
                /* Point the docking bay in the general direction of the fake witchpoint. */
 
84
                vector = p_base.mainScript.$witchpointBuoy.position.subtract(this.ship.position).direction();
 
85
            }
 
86
 
 
87
            /* Angle to the vector from current heading + about 1/8th turn. */
 
88
            angle = this.ship.heading.angleTo(vector) + 0.707;
 
89
            /* Cross vector for rotate. */
 
90
            cross = this.ship.heading.cross(vector).direction();
 
91
            /* Rotate the base by angle. */
 
92
            this.ship.orientation = this.ship.orientation.rotate(cross, -angle);
 
93
 
 
94
            /* Add some clutter within 20km around the base.
 
95
             * 20 to 27 asteroids and 20 to 27 boulders
 
96
             * - gives the miners something to do. (Also apparently any Thargoids!)
 
97
             */
 
98
            num = Math.floor(system.scrambledPseudoRandomNumber(p_base.mainScript.$salt) * 8) + 20;
 
99
            system.addShips("jaguar_company_asteroid", num, this.ship.position, 20000);
 
100
            num = Math.floor(system.scrambledPseudoRandomNumber(p_base.mainScript.$salt / 2) * 8) + 20;
 
101
            system.addShips("jaguar_company_boulder", num, this.ship.position, 20000);
 
102
 
 
103
            /* Reset the launch status of the buoy. */
 
104
            p_base.mainScript.$buoyLaunched = false;
 
105
            /* Miner has not launched. */
 
106
            p_base.minerLaunched = false;
 
107
 
 
108
            if (!system.shipsWithPrimaryRole("jaguar_company_patrol").length) {
 
109
                /* Reset how many Jaguar Company patrol ships are in system. */
 
110
                p_base.mainScript.$numPatrolShips = 0;
 
111
                /* No patrol ships have launched. */
 
112
                p_base.patrolShipsLaunched = 0;
 
113
                /* Reset the fully launched status of the patrol ships. */
 
114
                p_base.mainScript.$patrolShipsFullyLaunched = false;
 
115
            } else {
 
116
                /* Set how many Jaguar Company patrol ships are in system. */
 
117
                p_base.mainScript.$numPatrolShips = system.shipsWithPrimaryRole("jaguar_company_patrol").length;
 
118
                /* All patrol ships have launched. */
 
119
                p_base.patrolShipsLaunched = p_base.mainScript.$numPatrolShips;
 
120
                /* Set the fully launched status of the patrol ships. */
 
121
                p_base.mainScript.$patrolShipsFullyLaunched = true;
 
122
            }
 
123
        }
 
124
 
 
125
        /* Start up the timer to do some house keeping. */
 
126
        this.$baseTimerReference = new Timer(this, this.$baseTimer, 5, 5);
 
127
    };
 
128
 
 
129
    /* Base was destroyed.
 
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
        /* Call common code used by all of Jaguar Company. */
 
199
        worldScripts["Jaguar Company Attackers"].$shipDied(this.ship, attacker, why);
 
200
    };
 
201
 
 
202
    /* Base was removed by script. */
 
203
    this.shipRemoved = function (suppressDeathEvent) {
 
204
        if (suppressDeathEvent) {
 
205
            return;
 
206
        }
 
207
 
 
208
        /* Set this as no more ships will be launched. "Obvious cat is obvious!" */
 
209
        worldScripts["Jaguar Company"].$patrolShipsFullyLaunched = true;
 
210
    };
 
211
 
 
212
    /* The base has just become invalid. */
 
213
    this.entityDestroyed = function () {
 
214
        /* Set this as no more ships will be launched. "Obvious cat is obvious!" */
 
215
        worldScripts["Jaguar Company"].$patrolShipsFullyLaunched = true;
 
216
 
 
217
        /* Stop and remove the timer. */
 
218
        if (this.$baseTimerReference) {
 
219
            if (this.$baseTimerReference.isRunning) {
 
220
                this.$baseTimerReference.stop();
 
221
            }
 
222
 
 
223
            delete this.$baseTimerReference;
 
224
        }
 
225
    };
 
226
 
 
227
    /* Someone is pinging us with their laser.
 
228
     *
 
229
     * INPUTS
 
230
     *   attacker - entity of the ship that attacked.
 
231
     */
 
232
    this.shipBeingAttacked = function (attacker) {
 
233
        /* Call common code used by all of Jaguar Company. */
 
234
        p_base.attackersScript.$shipIsBeingAttacked(this.ship, attacker);
 
235
    };
 
236
 
 
237
    /* Someone has fired a missile at us.
 
238
     *
 
239
     * INPUTS
 
240
     *   missile - missile entity.
 
241
     *   attacker - entity of the ship that attacked.
 
242
     */
 
243
    this.shipAttackedWithMissile = function (missile, attacker) {
 
244
        /* Call common code used by all of Jaguar Company. */
 
245
        p_base.attackersScript.$shipIsBeingAttackedWithMissile(this.ship, attacker);
 
246
    };
 
247
 
 
248
    /* We killed someone.
 
249
     *
 
250
     * INPUT
 
251
     *   target - entity of the destroyed target.
 
252
     */
 
253
    this.shipTargetDestroyed = function (target) {
 
254
        if (target.primaryRole === "constrictor" &&
 
255
            missionVariables.conhunt &&
 
256
            missionVariables.conhunt === "STAGE_1") {
 
257
            /* Just in case the base kills the constrictor, let's not break the mission for the player... */
 
258
            missionVariables.conhunt = "CONSTRICTOR_DESTROYED";
 
259
            player.score += 1;
 
260
            player.credits += target.bounty;
 
261
            player.consoleMessage(this.ship.displayName + " assisted in the death of " + target.name, 3);
 
262
            player.consoleMessage(
 
263
                this.ship.displayName + ": Commander " + player.name +
 
264
                ", you have the kill and bounty of " + target.bounty + "₢.", 3);
 
265
 
 
266
            if (p_base.logging && p_base.logExtra) {
 
267
                log(this.name, "shipTargetDestroyed::" +
 
268
                    this.ship.displayName + " killed - " + target.name + " : " + target.bounty);
 
269
            }
 
270
        }
 
271
    };
 
272
 
 
273
    /* A ship has docked.
 
274
     *
 
275
     * INPUT
 
276
     *   whom - entity of the docked ship.
 
277
     */
 
278
    this.otherShipDocked = function (whom) {
 
279
        if (whom.hasRole("jaguar_company_patrol")) {
 
280
            /* Decrease the number of patrol ships that are launched. */
 
281
            p_base.patrolShipsLaunched -= 1;
 
282
        } else if (whom.hasRole("jaguar_company_miner")) {
 
283
            /* Reset the launch status of the miner. */
 
284
            p_base.mainScript.$minerLaunched = false;
 
285
        }
 
286
    };
 
287
 
 
288
    /* A ship has launched.
 
289
     *
 
290
     * INPUT
 
291
     *   whom - entity of the launched ship.
 
292
     */
 
293
    this.stationLaunchedShip = function (whom) {
 
294
        if (whom.hasRole("jaguar_company_patrol")) {
 
295
            if (p_base.patrolShipsLaunched === 1) {
 
296
                /* Initialise the route list with the default route. */
 
297
                p_base.mainScript.$initRoute();
 
298
            }
 
299
 
 
300
            if (whom.script.name !== "jaguar_company_patrol.js") {
 
301
                /* Remove the patrol ship. */
 
302
                whom.remove();
 
303
                /* Decrease the number of patrol ships that are launched. */
 
304
                p_base.patrolShipsLaunched -= 1;
 
305
 
 
306
                if (p_base.logging && p_base.logExtra) {
 
307
                    log(this.name, "Script sanity check - fixed a patrol ship.");
 
308
                }
 
309
            }
 
310
 
 
311
            if (p_base.patrolShipsLaunched !== p_base.mainScript.$maxPatrolShips) {
 
312
                /* Launch another patrol ship. */
 
313
                this.$launchJaguarCompanyPatrol();
 
314
            } else {
 
315
                /* All patrol ships are now fully launched. */
 
316
                p_base.mainScript.$patrolShipsFullyLaunched = true;
 
317
            }
 
318
        } else if (whom.hasRole("jaguar_company_tug")) {
 
319
            if (whom.script.name !== "jaguar_company_tug.js") {
 
320
                /* Remove the tug. */
 
321
                whom.remove();
 
322
                /* Reset the launch status of the buoy. */
 
323
                p_base.mainScript.$buoyLaunched = false;
 
324
                /* Launch another tug. */
 
325
                this.$launchJaguarCompanyTug();
 
326
 
 
327
                if (p_base.logging && p_base.logExtra) {
 
328
                    log(this.name, "Script sanity check - fixed the tug.");
 
329
                }
 
330
            }
 
331
        } else if (whom.hasRole("jaguar_company_miner")) {
 
332
            if (whom.script.name !== "jaguar_company_miner.js") {
 
333
                /* Remove the miner. */
 
334
                whom.remove();
 
335
                /* Reset the launch status of the miner. */
 
336
                p_base.mainScript.$minerLaunched = false;
 
337
                /* Launch another miner. */
 
338
                this.ship.launchShipWithRole("jaguar_company_miner");
 
339
 
 
340
                if (p_base.logging && p_base.logExtra) {
 
341
                    log(this.name, "Script sanity check - fixed the miner.");
 
342
                }
 
343
            }
 
344
        }
 
345
    };
 
346
 
 
347
    /* Timer callback. */
 
348
 
 
349
    /* Some OXP's dick around with the scanner colours. This will reset the base's scanner colour
 
350
     * back to the station default of solid green if the player has helped out in combat with Jaguar Company.
 
351
     *
 
352
     * Starts the launch sequence for the patrol ships if needed.
 
353
     *
 
354
     * Checks the buoy and launches a tug if there isn't one. Resets the scanner colour as per the base.
 
355
     * Swaps the buoy to 'no beacon' or 'beacon' dependent on the reputation mission variable.
 
356
     *
 
357
     * Called every 5 seconds.
 
358
     */
 
359
    this.$baseTimer = function () {
 
360
        var base = this.ship,
 
361
        position,
 
362
        orientation,
 
363
        buoy,
 
364
        newBuoy,
 
365
        newBuoyRole;
 
366
 
 
367
        /* Reset the base scanner colour. */
 
368
        base.scannerDisplayColor1 = null;
 
369
        base.scannerDisplayColor2 = null;
 
370
 
 
371
        if (!p_base.patrolShipsLaunched) {
 
372
            /* Start launching patrol ships. */
 
373
            this.$launchJaguarCompanyPatrol();
 
374
        }
 
375
 
 
376
        if (p_base.patrolShipsLaunched !== p_base.mainScript.$maxPatrolShips) {
 
377
            /* Reset the fully launched status of the patrol ships. */
 
378
            p_base.mainScript.$patrolShipsFullyLaunched = false;
 
379
        }
 
380
 
 
381
        buoy = p_base.mainScript.$buoy;
 
382
 
 
383
        if ((!buoy || !buoy.isValid) &&
 
384
            !p_base.mainScript.$buoyLaunched && p_base.mainScript.$patrolShipsFullyLaunched) {
 
385
            /* No buoys. Launch the tug to drop a buoy off. */
 
386
            this.$launchJaguarCompanyTug();
 
387
 
 
388
            return;
 
389
        }
 
390
 
 
391
        if (buoy && buoy.isValid) {
 
392
            /* Reset the buoy scanner colour. */
 
393
            buoy.scannerDisplayColor1 = null;
 
394
            buoy.scannerDisplayColor2 = null;
 
395
 
 
396
            if (missionVariables.jaguar_company_reputation < p_base.mainScript.$reputationHelper) {
 
397
                newBuoyRole = "jaguar_company_base_buoy_no_beacon";
 
398
            } else {
 
399
                newBuoyRole = "jaguar_company_base_buoy_beacon";
 
400
            }
 
401
 
 
402
            /* Check if the buoy already has the new role. */
 
403
            if (!buoy.hasRole(newBuoyRole)) {
 
404
                /* Copy some properties. */
 
405
                position = buoy.position;
 
406
                orientation = buoy.orientation;
 
407
                /* Create a new buoy. */
 
408
                newBuoy = buoy.spawnOne(newBuoyRole);
 
409
                /* Remove the origial buoy quietly: don't trigger 'shipDied' in the ship script. */
 
410
                buoy.remove(true);
 
411
                /* Setup the new buoy with the original properties. */
 
412
                newBuoy.position = position;
 
413
                newBuoy.orientation = orientation;
 
414
                /* Update the main script public variable. */
 
415
                p_base.mainScript.$buoy = newBuoy;
 
416
            }
 
417
        }
 
418
    };
 
419
 
 
420
    /* Launch a patrol ship. */
 
421
    this.$launchJaguarCompanyPatrol = function () {
 
422
        if (p_base.logging && p_base.logExtra) {
 
423
            log(this.name, "$launchJaguarCompanyPatrol::Launching patrol ship...");
 
424
        }
 
425
 
 
426
        p_base.patrolShipsLaunched += 1;
 
427
        this.ship.launchShipWithRole("jaguar_company_patrol");
 
428
    };
 
429
 
 
430
    /* Launch the tug to drag the buoy into position. */
 
431
    this.$launchJaguarCompanyTug = function () {
 
432
        if (p_base.mainScript.$patrolShipsFullyLaunched &&
 
433
            !p_base.mainScript.$buoyLaunched &&
 
434
            (!p_base.mainScript.$buoy || !p_base.mainScript.$buoy.isValid)) {
 
435
            /* Only one tug dragging a buoy at a time. Also no more than 1 buoy in system at a time.
 
436
             * Also don't launch until all patrol ships have launched.
 
437
             */
 
438
            p_base.mainScript.$buoyLaunched = true;
 
439
            this.ship.launchShipWithRole("jaguar_company_tug");
 
440
 
 
441
            if (p_base.logging && p_base.logExtra) {
 
442
                log(this.name, "$launchJaguarCompanyTug::Launching tug...");
 
443
            }
 
444
        }
 
445
    };
 
446
 
 
447
    /* AI functions. */
 
448
 
 
449
    /* Check if we need to launch a miner. Don't launch in interstellar space. */
 
450
    this.$launchShip = function () {
 
451
        if (!system.isInterstellarSpace &&
 
452
            Math.random() < 0.05 &&
 
453
            !p_base.minerLaunched &&
 
454
            p_base.mainScript.$patrolShipsFullyLaunched) {
 
455
            /* Only 1 miner at a time.
 
456
             * Also don't launch until all patrol ships have launched.
 
457
             */
 
458
            p_base.minerLaunched = true;
 
459
            this.ship.launchShipWithRole("jaguar_company_miner");
 
460
 
 
461
            if (p_base.logging && p_base.logExtra) {
 
462
                log(this.name, "$launchShip::Launching miner...");
 
463
            }
 
464
        }
 
465
    };
 
466
 
 
467
    /* Check for any previous attackers that have run away. */
 
468
    this.$scanForAttackers = function () {
 
469
        /* Call common code used by all of Jaguar Company. */
 
470
        p_base.attackersScript.$scanForAttackers(this.ship);
 
471
    };
 
472
 
 
473
    /* Checks the current target to make sure it is still valid. */
 
474
    this.$checkTargetIsValid = function () {
 
475
        /* Call common code used by all of Jaguar Company. */
 
476
        p_base.attackersScript.$checkTargetIsValid(this.ship);
 
477
    };
 
478
 
 
479
    /* This does something similar to the groupAttackTarget AI command. */
 
480
    this.$performJaguarCompanyAttackTarget = function () {
 
481
        /* Call common code used by all of Jaguar Company. */
 
482
        p_base.attackersScript.$performAttackTarget(this.ship);
 
483
    };
 
484
}).call(this);