‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_globallogic_vehicle.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\damagefeedback_shared;
4 #using scripts\shared\spawner_shared;
5 #using scripts\shared\vehicle_shared;
6 #using scripts\shared\callbacks_shared;
7 
8 #insert scripts\shared\shared.gsh;
9 
10 #using scripts\zm\gametypes\_damagefeedback;
11 #using scripts\zm\gametypes\_globallogic_player;
12 #using scripts\zm\gametypes\_weapons;
13 
14 #namespace globallogic_vehicle;
15 
16 function ‪Callback_VehicleSpawned( spawner )
17 {
18  if ( isdefined( level.vehicle_main_callback ) )
19  {
20  if( isdefined( level.vehicle_main_callback[ self.vehicleType ] ) )
21  {
22  self thread [[level.vehicle_main_callback[ self.vehicleType ]]]();
23  }
24  else if( isdefined( self.scriptVehicleType ) && isdefined( level.vehicle_main_callback[ self.scriptVehicleType ] ) )
25  {
26  self thread [[level.vehicle_main_callback[ self.scriptVehicleType ]]]();
27  }
28  }
29 
30  if ( IsSentient( self ) )
31  {
32  self ‪spawner::spawn_think( spawner );
33  }
34 }
35 
36 function ‪Callback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
37 {
38  // already applied in the Callback_VehicleDamage
39  /*if ( !(level.iDFLAGS_RADIUS & iDFlags) )
40  {
41  // create a class specialty checks; CAC:bulletdamage, CAC:armorvest
42  iDamage = _class::cac_modified_vehicle_damage( self, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor );
43  }*/
44 
45  self.iDFlags = iDFlags;
46  self.iDFlagsTime = getTime();
47 
48  if ( game["state"] == "postgame" )
49  return;
50 
51  if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isdefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
52  return;
53 
54 
55  // Don't do knockback if the damage direction was not specified
56  if( !isdefined( vDir ) )
57  iDFlags |= level.iDFLAGS_NO_KNOCKBACK;
58 
59  friendly = false;
60 
61  if ( ( isdefined( self.maxhealth ) && (self.health == self.maxhealth)) || !isdefined( self.attackers ) )
62  {
63  self.attackers = [];
64  self.attackerData = [];
65  self.attackerDamage = [];
66  }
67 
68  // explosive barrel/car detection
69  if ( weapon == level.weaponNone && isdefined( eInflictor ) )
70  {
71  if ( isdefined( eInflictor.targetname ) && eInflictor.targetname == "explodable_barrel" )
72  weapon = GetWeapon( "explodable_barrel" );
73  else if ( isdefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
74  weapon = GetWeapon( "destructible_car" );
75  }
76 
77 
78  // check for completely getting out of the damage
79  if( !(iDFlags & level.iDFLAGS_NO_PROTECTION) )
80  {
81  if ( self IsVehicleImmuneToDamage( iDFlags, sMeansOfDeath, weapon ) )
82  {
83  if ( isdefined( self.overrideVehicleDamage ) )
84  {
85  iDamage = self [[self.overrideVehicleDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
86  }
87  else if ( isdefined( level.overrideVehicleDamage ) )
88  {
89  iDamage = self [[level.overrideVehicleDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
90  }
91 
92  return;
93  }
94 
95  // This handles direct damage only. Splash is done in VehicleRadiusDamage
96  if ( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_GRENADE" )
97  {
98  iDamage *= weapon.vehicleProjectileDamageScalar;
99  iDamage = int(iDamage);
100 
101  if ( iDamage == 0 )
102  {
103  return;
104  }
105  }
106  // Except for splash that we want to modify additionally based on "underneath"
107  else if ( sMeansOfDeath == "MOD_GRENADE_SPLASH" )
108  {
109  iDamage *= ‪GetVehicleUnderneathSplashScalar( weapon );
110  iDamage = int(iDamage);
111 
112  if ( iDamage == 0 )
113  {
114  return;
115  }
116  }
117 
118  iDamage *= level.vehicleDamageScalar;
119  iDamage *= self GetVehDamageMultiplier(sMeansOfDeath);
120  iDamage = int(iDamage);
121 
122  if ( isPlayer( eAttacker ) )
123  eAttacker.pers["participation"]++;
124 
125  if( !isdefined( self.maxhealth ) )
126  {
127  self.maxhealth = self.healthdefault; // healthdefault if from the GDT
128  }
129 
130  if ( isdefined( self.overrideVehicleDamage ) )
131  {
132  iDamage = self [[self.overrideVehicleDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
133  }
134  else if ( isdefined( level.overrideVehicleDamage ) )
135  {
136  iDamage = self [[level.overrideVehicleDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
137  }
138 
139  prevHealthRatio = self.health / self.maxhealth;
140 
141  if ( isdefined( self.owner ) && IsPlayer(self.owner) )
142  {
143  team = self.owner.pers["team"];
144  }
145  else
146  {
147  team = self vehicle::vehicle_get_occupant_team();
148  }
149 
150  if ( level.teamBased && isPlayer( eAttacker ) && (team == eAttacker.pers["team"]) )
151  {
152  if ( level.friendlyfire == 0 ) // no one takes damage
153  {
154  if( !‪AllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon ) )
155  return;
156 
157  // Make sure at least one point of damage is done
158  if ( iDamage < 1 )
159  iDamage = 1;
160 
161  self.lastDamageWasFromEnemy = false;
162 
163  self finishVehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName, true);
164  }
165  else if ( level.friendlyfire == 1 ) // the friendly takes damage
166  {
167  // Make sure at least one point of damage is done
168  if ( iDamage < 1 )
169  iDamage = 1;
170 
171  self.lastDamageWasFromEnemy = false;
172 
173  self finishVehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName, false);
174  }
175  else if ( level.friendlyfire == 2 ) // no one takes damage
176  {
177  if( !‪AllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon ) )
178  return;
179 
180  // Make sure at least one point of damage is done
181  if ( iDamage < 1 )
182  iDamage = 1;
183 
184  self.lastDamageWasFromEnemy = false;
185 
186  self finishVehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName, true);
187  }
188  else if ( level.friendlyfire == 3 ) // both friendly and attacker take damage
189  {
190  iDamage = int(iDamage * .5);
191 
192  // Make sure at least one point of damage is done
193  if ( iDamage < 1 )
194  iDamage = 1;
195 
196  self.lastDamageWasFromEnemy = false;
197 
198  self finishVehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName, false);
199  }
200 
201  friendly = true;
202  }
203  else
204  {
205  if ( !level.teamBased && isdefined( self.targetname ) && self.targetname == "rcbomb" )
206  {
207  // allow the rc bomb to be damaged by owners in FFA games (DT 75676)
208  }
209  else if ( isdefined( self.owner ) && isdefined( eAttacker ) && self.owner == eAttacker )
210  return;
211 
212  // Make sure at least one point of damage is done
213  if( (iDamage < 1) && !‪IS_TRUE(level.bzm_worldPaused) )
214  iDamage = 1;
215 
216  if ( issubstr( sMeansOfDeath, "MOD_GRENADE" ) && isdefined( eInflictor ) && isdefined( eInflictor.isCooked ) )
217  self.wasCooked = getTime();
218  else
219  self.wasCooked = undefined;
220 
221  attacker_seat = undefined;
222  if ( isdefined( eAttacker ) )
223  attacker_seat = self GetOccupantSeat( eAttacker );
224 
225  self.lastDamageWasFromEnemy = (isdefined( eAttacker ) && !isdefined(attacker_seat));
226 
227  self finishVehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName, false);
228 
229  if ( level.gameType == "hack" && !weapon.isEmp )
230  {
231  iDamage = 0;
232  }
233  }
234 
235  if ( isdefined(eAttacker) && eAttacker != self )
236  {
237  if( ‪damagefeedback::doDamageFeedback( weapon, eInflictor ) )
238  {
239  if ( iDamage > 0 )
240  eAttacker thread ‪damagefeedback::update( sMeansOfDeath, eInflictor );
241  }
242  }
243  }
244 
245  if(1) // self.sessionstate != "dead")
246  {
247  lpselfnum = self getEntityNumber();
248  lpselfteam = "";
249  lpattackerteam = "";
250 
251  if(isPlayer(eAttacker))
252  {
253  lpattacknum = eAttacker getEntityNumber();
254  lpattackGuid = eAttacker getGuid();
255  lpattackname = eAttacker.name;
256  lpattackerteam = eAttacker.pers["team"];
257  }
258  else
259  {
260  lpattacknum = -1;
261  lpattackGuid = "";
262  lpattackname = "";
263  lpattackerteam = "world";
264  }
265 
266  logPrint("VD;" + lpselfnum + ";" + lpselfteam + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + weapon.name + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n");
267  }
268 
269 }
270 
271 function ‪Callback_VehicleRadiusDamage( eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime )
272 {
273  self.iDFlags = iDFlags;
274  self.iDFlagsTime = getTime();
275 
276  if ( game["state"] == "postgame" )
277  return;
278 
279  if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isdefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
280  return;
281 
282  friendly = false;
283 
284  // check for completely getting out of the damage
285  if( !(iDFlags & level.iDFLAGS_NO_PROTECTION) )
286  {
287  if ( self IsVehicleImmuneToDamage( iDFlags, sMeansOfDeath, weapon ) )
288  {
289  return;
290  }
291 
292  if ( isdefined( self.overrideVehicleRadiusDamage ) )
293  {
294  iDamage = self [[self.overrideVehicleRadiusDamage]]( eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime );
295  }
296  else if ( isdefined( level.overrideVehicleRadiusDamage ) )
297  {
298  iDamage = self [[level.overrideVehicleRadiusDamage]]( eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime );
299  }
300 
301  // THIS HANDLES SPLASH DAMAGE ONLY. SPLASH IS DONE IN VehicleRadiusDamage
302  if ( sMeansOfDeath == "MOD_PROJECTILE_SPLASH" || sMeansOfDeath == "MOD_GRENADE_SPLASH" || sMeansOfDeath == "MOD_EXPLOSIVE" )
303  {
304 
305  scalar = weapon.vehicleProjectileSplashDamageScalar;
306  iDamage = int(iDamage * scalar);
307  fInnerDamage = (fInnerDamage * scalar);
308  fOuterDamage = (fOuterDamage * scalar);
309 
310  if ( fInnerDamage == 0 )
311  {
312  return;
313  }
314  if ( iDamage < 1 )
315  {
316  iDamage = 1;
317  }
318  }
319 
320  occupant_team = self vehicle::vehicle_get_occupant_team();
321 
322  if ( level.teamBased && isPlayer( eAttacker ) && (occupant_team == eAttacker.pers["team"]) )
323  {
324  if ( level.friendlyfire == 0 ) // no one takes damage
325  {
326  if( !‪AllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon ) )
327  return;
328 
329  // Make sure at least one point of damage is done
330  if ( iDamage < 1 )
331  iDamage = 1;
332 
333  self.lastDamageWasFromEnemy = false;
334 
335  self finishVehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime);
336  }
337  else if ( level.friendlyfire == 1 ) // the friendly takes damage
338  {
339  // Make sure at least one point of damage is done
340  if ( iDamage < 1 )
341  iDamage = 1;
342 
343  self.lastDamageWasFromEnemy = false;
344 
345  self finishVehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime);
346  }
347  else if ( level.friendlyfire == 2 ) // Attacker will take damage from artillery
348  {
349  if( !‪AllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon ) )
350  return;
351 
352  // Make sure at least one point of damage is done
353  if ( iDamage < 1 )
354  iDamage = 1;
355 
356  self.lastDamageWasFromEnemy = false;
357 
358  self finishVehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime);
359  }
360  else if ( level.friendlyfire == 3 ) // both friendly and attacker take damage
361  {
362  iDamage = int(iDamage * .5);
363 
364  // Make sure at least one point of damage is done
365  if ( iDamage < 1 )
366  iDamage = 1;
367 
368  self.lastDamageWasFromEnemy = false;
369 
370  self finishVehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime);
371  }
372 
373  friendly = true;
374  }
375  else
376  {
377  // Make sure at least one point of damage is done
378  if(iDamage < 1)
379  iDamage = 1;
380 
381  self finishVehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime);
382  }
383  }
384 }
385 
386 
387 function ‪Callback_VehicleKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime )
388 {
389  params = SpawnStruct();
390  params.eInflictor = eInflictor;
391  params.eAttacker = eAttacker;
392  params.iDamage = iDamage;
393  params.sMeansOfDeath = sMeansOfDeath;
394  params.weapon = weapon;
395  params.vDir = vDir;
396  params.sHitLoc = sHitLoc;
397  params.psOffsetTime = psOffsetTime;
398 
399  //TODO - will get moved to code in T8
400  self.str_damagemod = sMeansOfDeath;
401  self.w_damage = weapon;
402 
403  if ( game["state"] == "postgame" )
404  return;
405 
406  if( IsAI(eAttacker) && isdefined( eAttacker.script_owner ) )
407  {
408  // if the person who called the dogs in switched teams make sure they don't
409  // get penalized for the kill
410  if ( eAttacker.script_owner.team != self.team )
411  eAttacker = eAttacker.script_owner;
412  }
413 
414  if ( isdefined( eAttacker ) && isdefined( eAttacker.onKill ) )
415  {
416  eAttacker [[eAttacker.onKill]]( self );
417  }
418 
419  if ( isdefined(eInflictor) )
420  {
421  self.damageInflictor = eInflictor;
422  }
423 
424  self ‪callback::callback( #"on_vehicle_killed", params );
425 
426  // do vehicle killed callback
427  // generally this should be used as system callback, and the callback "on_vehicle_killed" callback can be used by level script
428  if ( isdefined( self.overrideVehicleKilled ) )
429  {
430  self [[self.overrideVehicleKilled]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime );
431  }
432 }
433 
434 function ‪vehicleCrush()
435 {
436  self endon("disconnect");
437 
438  if(isdefined( level._effect ) && isdefined( level._effect["tanksquish"] ) )
439  {
440  PlayFX( level._effect["tanksquish"], self.origin + (0, 0, 30));
441  }
442 
443  self playsound( "chr_crunch" );
444 }
445 
446 // damage going through this function will have already passed through the
447 // GetVehicleProjectileSplashScalar so keep that in mind when adjusting values
449 {
450  if ( weapon.name == "satchel_charge" )
451  {
452  // canceling all splash scaling done by the other function
453  scale = 10.0;
454 
455  // making it really deadly
456  scale *= 3.0;
457  }
458  else
459  {
460  scale = 1.0;
461  }
462 
463  return scale;
464 }
465 
466 function ‪AllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon )
467 {
468  if (isdefined( self.allowFriendlyFireDamageOverride ) )
469  {
470  return [[self.allowFriendlyFireDamageOverride]](eInflictor, eAttacker, sMeansOfDeath, weapon );
471  }
472 
473  return false;
474 }
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪Callback_VehicleRadiusDamage
‪function Callback_VehicleRadiusDamage(eInflictor, eAttacker, iDamage, fInnerDamage, fOuterDamage, iDFlags, sMeansOfDeath, weapon, vPoint, fRadius, fConeAngleCos, vConeDir, psOffsetTime)
Definition: _globallogic_vehicle.gsc:266
‪Callback_VehicleDamage
‪function Callback_VehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal)
Definition: _globallogic_vehicle.gsc:45
‪spawn_think
‪function spawn_think(spawner)
Definition: spawner_shared.gsc:504
‪Callback_VehicleSpawned
‪function Callback_VehicleSpawned(spawner)
Definition: _globallogic_vehicle.gsc:19
‪Callback_VehicleKilled
‪function Callback_VehicleKilled(eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _globallogic_vehicle.gsc:341
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪GetVehicleUnderneathSplashScalar
‪function GetVehicleUnderneathSplashScalar(weapon)
Definition: _globallogic_vehicle.gsc:379
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: damagefeedback_shared.gsc:423
‪vehicleCrush
‪function vehicleCrush()
Definition: _globallogic_vehicle.gsc:365
‪update
‪function update()
Definition: _serversettings.gsc:71
‪AllowFriendlyFireDamage
‪function AllowFriendlyFireDamage(eInflictor, eAttacker, sMeansOfDeath, weapon)
Definition: _globallogic_vehicle.gsc:400