1
/*jslint indent: 4, maxlen: 120, maxerr: 50, white: true, es5: true, undef: true, bitwise: true, regexp: 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 worldScripts, Vector3D */
9
* Copyright © 2012 Richard Thomas Harrison (Tricky)
11
* This work is licensed under the Creative Commons
12
* Attribution-Noncommercial-Share Alike 3.0 Unported License.
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.
19
* Ship related functions for the tug.
25
/* Standard public variables for OXP scripts. */
26
this.name = "jaguar_company_tug.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 Tug.";
33
/* Private variable. */
36
/* Ship event callbacks. */
38
/* Initialise various variables on ship birth. */
39
this.shipSpawned = function () {
40
/* No longer needed after setting up. */
41
delete this.shipSpawned;
43
/* Initialise the p_tug variable object.
44
* Encapsulates all private global data.
47
/* Cache the world scripts. */
48
mainScript : worldScripts["Jaguar Company"],
49
attackersScript : worldScripts["Jaguar Company Attackers"],
50
/* Local copies of the logging variables. */
51
logging : worldScripts["Jaguar Company"].$logging,
52
logExtra : worldScripts["Jaguar Company"].$logExtra,
53
/* Local copy of the friends array. */
54
friendRoles : worldScripts["Jaguar Company Attackers"].$friendRoles
57
/* Register this tug as a friendly. */
58
p_tug.attackersScript.$addFriendly(this.ship);
59
/* Get a unique name for the tug. */
60
this.ship.displayName = p_tug.mainScript.$uniqueShipName(this.ship.name);
66
* attacker - entity that caused the death.
67
* why - cause as a string.
69
this.shipDied = function (attacker, why) {
70
/* Call common code used by all of Jaguar Company. */
71
worldScripts["Jaguar Company Attackers"].$shipDied(this.ship, attacker, why);
74
/* Tug was removed by script. */
75
this.shipRemoved = function (suppressDeathEvent) {
76
if (suppressDeathEvent) {
80
if (!p_tug.mainScript.$buoy || !p_tug.mainScript.$buoy.isValid) {
81
/* Not released the buoy yet, reset the launch status of the buoy. */
82
worldScripts["Jaguar Company"].$buoyLaunched = false;
86
/* The tug has just become invalid. */
87
this.entityDestroyed = function () {
88
if (!p_tug.mainScript.$buoy || !p_tug.mainScript.$buoy.isValid) {
89
/* Not released the buoy yet, reset the launch status of the buoy. */
90
worldScripts["Jaguar Company"].$buoyLaunched = false;
94
/* Someone is pinging us with their laser.
97
* attacker - entity of the ship that attacked.
99
this.shipBeingAttacked = function (attacker) {
100
/* Call common code used by all of Jaguar Company. */
101
p_tug.attackersScript.$shipIsBeingAttacked(this.ship, attacker);
104
/* Someone has fired a missile at us.
107
* missile - missile entity.
108
* attacker - entity of the ship that attacked.
110
this.shipAttackedWithMissile = function (missile, attacker) {
111
/* Call common code used by all of Jaguar Company. */
112
p_tug.attackersScript.$shipIsBeingAttackedWithMissile(this.ship, attacker);
115
/* Taking damage. Check attacker and what type.
118
* amount - amount of damage.
119
* attacker - entity that caused the damage.
120
* type - type of damage as a string.
122
this.shipTakingDamage = function (amount, attacker, type) {
123
if (!attacker || !attacker.isValid || !attacker.isShip) {
124
/* If it isn't a ship dealing damage then carry on with the damage. */
128
if (p_tug.friendRoles.indexOf(attacker.primaryRole) > -1 && type === "scrape damage") {
129
/* Cancel damage from collision with Jaguar Company ships. */
130
this.ship.energy += amount;
134
/* We killed someone.
137
* target - entity of the destroyed target.
139
this.shipTargetDestroyed = function (target) {
140
if (target.primaryRole === "constrictor" &&
141
missionVariables.conhunt &&
142
missionVariables.conhunt === "STAGE_1") {
143
/* Just in case the tug kills the constrictor, let's not break the mission for the player... */
144
missionVariables.conhunt = "CONSTRICTOR_DESTROYED";
146
player.credits += target.bounty;
147
player.consoleMessage(this.ship.displayName + " assisted in the death of " + target.name, 5);
148
player.consoleMessage(
149
this.ship.displayName + ": Commander " + player.name +
150
", you have the kill and bounty of " + target.bounty + "₢.", 5);
152
if (p_tug.logging && p_tug.logExtra) {
153
log(this.name, "shipTargetDestoryed::" +
154
this.ship.displayName + " killed - " + target.name + " : " + target.bounty);
159
/* Set the co-ordinates to the surface of the entity.
160
* This borrows some code from 'src/Core/Entities/ShipEntityAI.m - setCourseToPlanet'
163
* entity - entity to set co-ordinates to.
165
this.$setCoordsToEntity = function (entity) {
166
var position = entity.position,
171
/* Calculate a vector position between the entity's surface and the ship. */
172
distance = this.ship.position.distanceTo(position);
173
ratio = (entity.collisionRadius + this.ship.collisionRadius + 100) / distance;
174
position = Vector3D.interpolate(position, this.ship.position, ratio);
176
/* Higher variation if further away. */
177
variation = (distance > 51200 ? 0.5 : 0.2);
179
/* Move the vector a random amount. */
180
position.x += variation * (Math.random() - variation);
181
position.y += variation * (Math.random() - variation);
182
position.z += variation * (Math.random() - variation);
184
/* Save this position for 'setDestinationFromCoordinates' in the AI. */
185
this.ship.savedCoordinates = position;
190
/* Save the current AI state. */
191
this.$saveAIState = function () {
192
p_tug.saveAIState = this.ship.AIState;
195
/* Recall the saved AI state. */
196
this.$recallAIState = function () {
197
this.ship.AIState = p_tug.saveAIState;
200
/* Set the co-ordinates to the surface of the base. */
201
this.$setCoordsToJaguarCompanyBase = function () {
202
var base = p_tug.mainScript.$jaguarCompanyBase;
204
if (!base || !base.isValid) {
205
/* If it has gone, just go to the nearest station. */
206
this.ship.reactToAIMessage("JAGUAR_COMPANY_BASE_NOT_FOUND");
208
/* Set the coords to the buoy or the base. */
209
this.$setCoordsToEntity(base);
210
this.ship.reactToAIMessage("JAGUAR_COMPANY_BASE_FOUND");
214
this.$setCoordsForBuoyDropOff = function () {
215
var base = p_tug.mainScript.$jaguarCompanyBase,
219
/* If it has gone, just go to the nearest station. */
220
this.ship.reactToAIMessage("JAGUAR_COMPANY_BUOY_DROP_OFF_NOT_FOUND");
225
/* Calculate the base surface to buoy centre distance, not centre to centre. */
226
distance += base.collisionRadius;
227
/* Add on desired range. */
230
/* Set the ending position for the tug in front of the base. */
231
this.ship.savedCoordinates = base.position.add(base.heading.multiply(distance));
232
this.ship.reactToAIMessage("JAGUAR_COMPANY_BUOY_DROP_OFF_FOUND");
235
/* Release the buoy by removing the sub-entity and replacing with a real buoy. */
236
this.$releaseBuoy = function () {
238
subEntities = tug.subEntities,
243
/* We make the assumption that the buoy is the 1st sub-entity. */
244
if (!subEntities.length || !subEntities[0].hasRole("jaguar_company_base_buoy_subent")) {
245
/* The buoy isn't there??? */
249
/* Calculate the real-world position for the buoy. */
250
buoyPosition = tug.position.add(subEntities[0].position.rotateBy(tug.orientation));
251
/* Remove the buoy sub-entity quietly: don't trigger 'shipDied' in the ship script. */
252
subEntities[0].remove(true);
254
if (missionVariables.jaguar_company_reputation < p_tug.mainScript.$reputationHelper) {
255
/* No beacon. Scanner colour is solid white. */
256
buoyRole = "jaguar_company_base_buoy_no_beacon";
258
/* Beacon. Standard scanner colour for a buoy. */
259
buoyRole = "jaguar_company_base_buoy_beacon";
262
/* Create the real buoy and add it to the system. */
263
buoy = tug.spawnOne(buoyRole);
264
buoy.position = buoyPosition;
265
/* Keep the original orientation. */
266
buoy.orientation = tug.orientation;
267
/* Update the main script public variable. */
268
p_tug.mainScript.$buoy = buoy;
269
/* Stop the kick in velocity from spawning the buoy and it colliding with the tug.
270
* In effect this will put the tug into reverse.
272
tug.velocity = new Vector3D(0, 0, 0).subtract(tug.vectorForward.multiply(tug.maxSpeed));
275
/* Check for any previous attackers that have run away. */
276
this.$scanForAttackers = function () {
277
/* Call common code used by all of Jaguar Company. */
278
p_tug.attackersScript.$scanForAttackers(this.ship);
281
/* Checks the current target to make sure it is still valid. */
282
this.$checkTargetIsValid = function () {
283
/* Call common code used by all of Jaguar Company. */
284
p_tug.attackersScript.$checkTargetIsValid(this.ship);
287
/* This does something similar to the groupAttackTarget AI command. */
288
this.$performJaguarCompanyAttackTarget = function () {
289
/* Call common code used by all of Jaguar Company. */
290
p_tug.attackersScript.$performAttackTarget(this.ship);
293
/* Scan for cascade weapons. Won't be needed when v1.78 comes out. */
294
this.$scanForCascadeWeapon = function () {
295
/* Call common code used by all of Jaguar Company. */
296
p_tug.attackersScript.$scanForCascadeWeapon(this.ship);