Advertisement
Guest User

Untitled

a guest
Oct 18th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 47.42 KB | None | 0 0
  1. #include common_scripts\utility;
  2. #include maps\mp\_utility;
  3.  
  4. init() {
  5.  
  6. // assigns weapons with stat numbers from 0-149
  7. // attachments are now shown here, they are per weapon settings inste
  8. // generating weaponIDs array
  9.  
  10. level.weaponIDs = [];
  11. max_weapon_num = 149;
  12. attachment_num = 150;
  13. for (i = 0; i <= max_weapon_num; i++) {
  14. weapon_name = tablelookup("mp/statstable.csv", 0, i, 4);
  15. if (!isdefined(weapon_name) || weapon_name == "") {
  16. level.weaponIDs[i] = "";
  17. continue;
  18. }
  19.  
  20. level.weaponIDs[i] = weapon_name + "_mp";
  21.  
  22. // generating attachment combinations
  23.  
  24. attachment = tablelookup("mp/statstable.csv", 0, i, 8);
  25. if (!isdefined(attachment) || attachment == "") continue;
  26. attachment_tokens = strtok(attachment, " ");
  27. if (!isdefined(attachment_tokens)) continue;
  28. if (attachment_tokens.size == 0) {
  29. level.weaponIDs[attachment_num] = weapon_name + "_" + attachment + "_mp";
  30. attachment_num++;
  31. }
  32. else {
  33. for (k = 0; k < attachment_tokens.size; k++) {
  34. level.weaponIDs[attachment_num] = weapon_name + "_" + attachment_tokens[k] + "_mp";
  35. attachment_num++;
  36. }
  37. }
  38. }
  39.  
  40. level.weaponNames = [];
  41. for (i = 0; i < max_weapon_num; i++) {
  42. if (!isdefined(level.weaponIDs[i]) || level.weaponIDs[i] == "") continue;
  43. level.weaponNames[level.weaponIDs[i]] = i;
  44. }
  45.  
  46. level.weaponlist = [];
  47. assertex(isdefined(level.weaponIDs.size) , "level.weaponIDs is corrupted");
  48. for (i = 0; i < level.weaponIDs.size; i++) {
  49. if (!isdefined(level.weaponIDs[i]) || level.weaponIDs[i] == "") continue;
  50. level.weaponlist[level.weaponlist.size] = level.weaponIDs[i];
  51. }
  52.  
  53. for (i = 0; i < level.weaponList.size; i++) {
  54. precacheItem(level.weaponList[i]);
  55. println("Precached weapon: " + level.weaponList[i]);
  56. }
  57.  
  58. precacheItem("frag_grenade_short_mp");
  59. precacheModel("weapon_mp_bazooka_attach");
  60. precacheItem("napalmblob_mp");
  61. precacheItem("t34_mp_explosion_mp");
  62. precacheItem("panzer4_mp_explosion_mp");
  63. precacheShellShock("default");
  64. precacheShellShock("tabun_gas_mp");
  65. thread maps\mp\_flashgrenades::main();
  66. thread maps\mp\_entityheadicons::init();
  67. level.bettyDetonateRadius = weapons_get_dvar_int("bettyDetonateRadius", "150");
  68. level.bettyUpVelocity = weapons_get_dvar_int("bettyUpVelocity", "296");
  69. level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", "0.45");
  70. level.bettyTriggerDamageTraceEnabled = weapons_get_dvar_int("scr_bettyTriggerDamageTraceEnabled", "1");
  71. level.bettyTriggerLoopWait = weapons_get_dvar("scr_bettyTriggerLoopWait", 0.1);
  72. level.tabunInitialGasShockDuration = weapons_get_dvar_int("tabunInitialGasShockDuration", "7");
  73. level.tabunWalkInGasShockDuration = weapons_get_dvar_int("tabunWalkInGasShockDuration", "4");
  74. level.tabunGasShockRadius = weapons_get_dvar_int("tabun_shock_radius", "150");
  75. level.tabunGasPoisonRadius = weapons_get_dvar_int("tabun_effect_radius", "150");
  76.  
  77. // Radius of effect of poison gas
  78.  
  79. level.tabunGasDuration = weapons_get_dvar_int("tabunGasDuration", "3"); // in seconds, after initial shock if you enter, you will get cough, blurred vision if you stay in this length
  80. level.poisonDuration = weapons_get_dvar_int("poisonDuration", "8"); // in seconds you will get poison full screen effect for
  81. level.slappedWithMolotovDamage = 35; // how much damage to be applied every second
  82. level.bettyFXid = loadfx("weapon/bouncing_betty/fx_betty_trail");
  83. level thread onPlayerConnect();
  84. level.satchelexplodethisframe = false;
  85. level.bettyexplodethisframe = false;
  86. }
  87.  
  88. isStrStart(string1, subStr) {
  89. return (getSubStr(string1, 0, subStr.size) == subStr);
  90. }
  91.  
  92. onPlayerConnect() {
  93. for (;;) {
  94. level waittill("connecting", player);
  95. player.usedWeapons = false;
  96. player.hits = 0;
  97. player thread onPlayerSpawned();
  98. }
  99. }
  100.  
  101. onPlayerSpawned() {
  102. self endon("disconnect");
  103. for (;;) {
  104. self waittill("spawned_player ");
  105. self.concussionEndTime = 0;
  106. self.hasDoneCombat = false;
  107. self thread watchWeaponUsage();
  108. self thread watchGrenadeUsage();
  109. self thread watchWeaponChange();
  110. self.droppedDeathWeapon = undefined;
  111. self.tookWeaponFrom = [];
  112. self thread updateStowedWeapon();
  113. }
  114. }
  115.  
  116. watchWeaponChange() {
  117. self endon("death");
  118. self endon("disconnect");
  119. self.lastDroppableWeapon = self getCurrentWeapon();
  120. while (1) {
  121. self waittill("weapon_change", newWeapon);
  122. if (mayDropWeapon(newWeapon)) self.lastDroppableWeapon = newWeapon;
  123. }
  124. }
  125.  
  126. isPistol(weapon) {
  127. return isdefined(level.side_arm_array[weapon]);
  128. }
  129.  
  130. hasScope(weapon) {
  131. if (isSubStr(weapon, "_acog_")) return true;
  132. if (weapon == "m21_mp") return true;
  133. if (weapon == "aw50_mp") return true;
  134. if (weapon == "barrett_mp") return true;
  135. if (weapon == "dragunov_mp") return true;
  136. if (weapon == "m40a3_mp") return true;
  137. if (weapon == "remington700_mp") return true;
  138. return false;
  139. }
  140.  
  141. isHackWeapon(weapon) {
  142. if (weapon == "radar_mp" || weapon == "artillery_mp" || weapon == "dogs_mp") return true;
  143. if (weapon == "briefcase_bomb_mp") return true;
  144. return false;
  145. }
  146.  
  147. mayDropWeapon(weapon) {
  148. if (weapon == "none") return false;
  149. if (isHackWeapon(weapon)) return false;
  150. invType = WeaponInventoryType(weapon);
  151. if (invType != "primary") return false;
  152. if (weapon == "none") return false;
  153. return true;
  154. }
  155.  
  156. dropWeaponForDeath(attacker) {
  157. weapon = self.lastDroppableWeapon;
  158. if (isdefined(self.droppedDeathWeapon)) return;
  159. if (!isdefined(weapon)) return;
  160. if (weapon == "none") return;
  161. if (!self hasWeapon(weapon)) return;
  162. if (!(self AnyAmmoForWeaponModes(weapon))) return;
  163.  
  164. clipAmmo = self GetWeaponAmmoClip(weapon);
  165. if (!clipAmmo) return;
  166.  
  167. stockAmmo = self GetWeaponAmmoStock(weapon);
  168. stockMax = WeaponMaxAmmo(weapon);
  169. if (stockAmmo > stockMax) stockAmmo = stockMax;
  170. item = self dropItem(weapon);
  171. self.droppedDeathWeapon = true;
  172. item itemWeaponSetAmmo(clipAmmo, stockAmmo);
  173. item itemRemoveAmmoFromAltModes();
  174. item.owner = self ;
  175. item.ownersattacker = attacker;
  176. item thread watchPickup();
  177. item thread deletePickupAfterAWhile();
  178. }
  179.  
  180. deletePickupAfterAWhile() {
  181. self endon("death");
  182. wait 60;
  183. if (!isDefined(self)) return;
  184. self delete();
  185. }
  186.  
  187. getItemWeaponName() {
  188. classname = self.classname;
  189. assert(getsubstr(classname, 0, 7) == "weapon_");
  190. weapname = getsubstr(classname, 7);
  191. return weapname;
  192. }
  193.  
  194. watchPickup() {
  195. self endon("death");
  196. weapname = self getItemWeaponName();
  197. while (1) {
  198. self waittill("trigger", player , droppedItem);
  199. if (isdefined(droppedItem)) break;
  200.  
  201. // otherwise, player merely acquired ammo and didn't pick this up
  202.  
  203. }
  204.  
  205. assert(isdefined(player.tookWeaponFrom));
  206. droppedWeaponName = droppedItem getItemWeaponName();
  207. if (isdefined(player.tookWeaponFrom[droppedWeaponName])) {
  208. droppedItem.owner = player.tookWeaponFrom[droppedWeaponName];
  209. droppedItem.ownersattacker = player ;
  210. player.tookWeaponFrom[droppedWeaponName] = undefined;
  211. }
  212.  
  213. droppedItem thread watchPickup();
  214. if (isdefined(self.ownersattacker) && self.ownersattacker == player) {
  215. player.tookWeaponFrom[weapname] = self.owner;
  216. }
  217. else {
  218. player.tookWeaponFrom[weapname] = undefined;
  219. }
  220. }
  221.  
  222. itemRemoveAmmoFromAltModes() {
  223. origweapname = self getItemWeaponName();
  224. curweapname = weaponAltWeaponName(origweapname);
  225. altindex = 1;
  226. while (curweapname != "none" && curweapname != origweapname) {
  227. self itemWeaponSetAmmo(0, 0, altindex);
  228. curweapname = weaponAltWeaponName(curweapname);
  229. altindex++;
  230. }
  231. }
  232.  
  233. dropOffhand() {
  234. grenadeTypes = self thread getGrenadeTypes();
  235. for (i = 0; i < grenadeTypes.size; i++) {
  236. if (!self hasWeapon(grenadeTypes[i])) continue;
  237. count = self getAmmoCount(grenadeTypes[i]);
  238. if (!count) continue;
  239. self setWeaponAmmoClip(grenadeTypes[i], 1);
  240. item = self dropItem(grenadeTypes[i]);
  241. item thread deletePickupAfterAWhile();
  242. }
  243. }
  244.  
  245. getGrenadeTypes() {
  246. grenadeTypes = [];
  247. grenadeTypes[0] = "frag_grenade_mp";
  248. grenadeTypes[1] = "sticky_grenade_mp";
  249. grenadeTypes[2] = "molotov_mp";
  250. return grenadeTypes;
  251. }
  252.  
  253. getGrenade() {
  254. grenade = [];
  255. class = self.pers["class"];
  256.  
  257. classNum = int(class [class.size - 1]) - 1;
  258.  
  259. if (classNum == - 1) {
  260. if (isSubstr(class , "CLASS_DEMOLITIONS")) grenade["type"] = "sticky_grenade_mp";
  261.  
  262. else grenade["type"] = "frag_grenade_mp";
  263. grenade["count"] = 1;
  264. }
  265. else {
  266. grenade["type"] = self.custom_class[classNum]["grenades"];
  267. grenade["count"] = self.custom_class[classNum]["grenades_count"];
  268. }
  269.  
  270. return grenade;
  271. }
  272.  
  273. pickupOffhand() {
  274. level endon("game_ended");
  275. self endon("disconnect");
  276. self endon("death");
  277. self endon("killed_player ");
  278. grenade = self thread getGrenade();
  279. grenadeTypes = self thread getGrenadeTypes();
  280. for (;;) {
  281. clipAmmo = self getWeaponAmmoClip(grenade["type"]);
  282. for (i = 0; i < grenadeTypes.size; i++) {
  283. if (grenade["type"] != grenadeTypes[i]) {
  284. if (self hasWeapon(grenadeTypes[i])) {
  285. if (grenade["type"] != "molotov_mp") clipAmmo = clipAmmo - 1;
  286. for (i = 0; i < grenadeTypes.size; i++) self takeWeapon(grenadeTypes[i]);
  287. self giveWeapon(grenade["type"]);
  288. if (grenade["count"] == 2)
  289. if (clipAmmo < 2) self setWeaponAmmoClip(grenade["type"], clipAmmo + 1);
  290. else self setWeaponAmmoClip(grenade["type"], 2);
  291. else self setWeaponAmmoClip(grenade["type"], 1);
  292. }
  293. else {
  294. if (clipAmmo > grenade["count"]) self setWeaponAmmoClip(grenade["type"], grenade["count"]);
  295. }
  296. }
  297. }
  298.  
  299. wait 1;
  300. }
  301. }
  302.  
  303. getWeaponBasedGrenadeCount(weapon) {
  304. return 2;
  305. }
  306.  
  307. getWeaponBasedSmokeGrenadeCount(weapon) {
  308. return 1;
  309. }
  310.  
  311. getFragGrenadeCount() {
  312. grenadetype = "frag_grenade_mp";
  313. count = self getammocount(grenadetype);
  314. return count;
  315. }
  316.  
  317. getSmokeGrenadeCount() {
  318. grenadetype = "smoke_grenade_mp";
  319. count = self getammocount(grenadetype);
  320. return count;
  321. }
  322.  
  323. watchWeaponUsage() {
  324. self endon("death");
  325. self endon("disconnect");
  326. level endon("game_ended");
  327. self.firingWeapon = false;
  328. for (;;) {
  329. self waittill("begin_firing");
  330. self.hasDoneCombat = true;
  331. self.firingWeapon = true;
  332. curWeapon = self getCurrentWeapon();
  333. switch (weaponClass(curWeapon)) {
  334. case "rifle":
  335. case "pistol":
  336. case "mg":
  337. case "smg":
  338. case "spread":
  339. self thread watchCurrentFiring(curWeapon);
  340. break;
  341.  
  342. default:
  343. break;
  344. }
  345.  
  346. self waittill("end_firing");
  347. self.firingWeapon = false;
  348. if (curWeapon == "bazooka_mp") {
  349. self setStatLBByName(curWeapon, 1, "shots");
  350. }
  351. }
  352. }
  353.  
  354. watchCurrentFiring(curWeapon) {
  355. self endon("disconnect");
  356. startAmmo = self getWeaponAmmoClip(curWeapon);
  357. wasInLastStand = isDefined(self.lastStand);
  358. self waittill("end_firing");
  359. if (!self hasWeapon(curWeapon)) return;
  360.  
  361. // ignore the case where a player is firing as they enter last stand.
  362. // it makes it too hard to calculate shotsFired properly.
  363.  
  364. if (isDefined(self.lastStand) && !wasInLastStand) return;
  365. shotsFired = startAmmo - (self getWeaponAmmoClip(curWeapon)) + 1;
  366. if (isDefined(self.lastStandParams) && self.lastStandParams.lastStandStartTime == getTime()) {
  367. self.hits = 0;
  368. return;
  369. }
  370.  
  371. assertEx(shotsFired >= 0, shotsFired + " startAmmo: " + startAmmo + " clipAmmo: " + self getWeaponAmmoclip(curWeapon) + " w/ " + curWeapon);
  372. if (shotsFired <= 0) return;
  373. self setStatLBByName(curWeapon, shotsFired, "shots");
  374. self setStatLBByName(curWeapon, self.hits, "hits");
  375. statTotal = self maps\mp\gametypes\_persistence::statGet("total_shots") + shotsFired;
  376. statHits = self maps\mp\gametypes\_persistence::statGet("hits") + self.hits;
  377. statMisses = self maps\mp\gametypes\_persistence::statGet("misses") + shotsFired - self.hits;
  378. self maps\mp\gametypes\_persistence::statSet("total_shots", statTotal);
  379. self maps\mp\gametypes\_persistence::statSet("hits", statHits);
  380. self maps\mp\gametypes\_persistence::statSet("misses", int(max(0, statMisses)));
  381. self maps\mp\gametypes\_persistence::statSet("accuracy", int(statHits * 10000 / statTotal));
  382. self.hits = 0;
  383. }
  384.  
  385. checkHit(sWeapon) {
  386. switch (weaponClass(sWeapon)) {
  387. case "rifle":
  388. case "pistol":
  389. case "mg":
  390. case "smg":
  391. self.hits++;
  392. break;
  393.  
  394. case "spread":
  395. self.hits = 1;
  396. break;
  397.  
  398. default:
  399. break;
  400. }
  401.  
  402. if ((sWeapon == "bazooka_mp") || isStrStart(sWeapon, "t34") || isStrStart(sWeapon, "panzer")) {
  403. self setStatLBByName(sWeapon, 1, "hits");
  404. }
  405. }
  406.  
  407. // returns true if damage should be done to the item given its owner and the attacker
  408.  
  409. friendlyFireCheck(owner, attacker, forcedFriendlyFireRule) {
  410. if (!isdefined(owner)) // owner has disconnected? allow it
  411. return true;
  412. if (!level.teamBased) // not a team based mode? allow it
  413. return true;
  414. friendlyFireRule = level.friendlyfire;
  415. if (isdefined(forcedFriendlyFireRule)) friendlyFireRule = forcedFriendlyFireRule;
  416. if (friendlyFireRule != 0) // friendly fire is on? allow it
  417. return true;
  418. if (attacker == owner) // owner may attack his own items
  419. return true;
  420. if (isplayer (attacker)) {
  421. if (!isdefined(attacker.pers["team"])) // attacker not on a team? allow it
  422. return true;
  423. if (attacker.pers["team"] != owner.pers["team"]) // attacker not on the same team as the owner? allow it
  424. return true;
  425. }
  426. else
  427. if (isai(attacker)) {
  428. if (attacker.aiteam != owner.pers["team"]) // attacker not on the same team as the owner? allow it
  429. return true;
  430. }
  431.  
  432. return false; // disallow it
  433. }
  434.  
  435. inPoisonArea(player , gasEffectArea) {
  436. player endon("disconnect");
  437. player.inPoisonArea = true;
  438. player startPoisoning();
  439. while ((isdefined(gasEffectArea)) && player istouching(gasEffectArea) && player.sessionstate == "playing") {
  440. wait (0.25);
  441. }
  442.  
  443. player stopPoisoning();
  444. player.inPoisonArea = false;
  445. }
  446.  
  447. watchTabunGrenadeDetonation(owner) {
  448. self waittill("explode", position);
  449. level.tabunGasPoisonRadius = weapons_get_dvar_int("tabun_effect_radius", level.tabunGasPoisonRadius);
  450. level.tabunGasShockRadius = weapons_get_dvar_int("tabun_shock_radius", level.tabunGasShockRadius);
  451. level.tabunInitialGasShockDuration = weapons_get_dvar_int("tabunInitialGasShockDuration", level.tabunInitialGasShockDuration);
  452. level.tabunWalkInGasShockDuration = weapons_get_dvar_int("tabunWalkInGasShockDuration", level.tabunWalkInGasShockDuration);
  453. level.tabunGasDuration = weapons_get_dvar_int("tabunGasDuration", level.tabunGasDuration);
  454. shockEffectArea = spawn("trigger_radius", position, 0, level.tabunGasShockRadius, level.tabunGasShockRadius * 2);
  455. players = get_players();
  456. for (i = 0; i < players.size; i++) {
  457. if (players[i] player_is_driver()) continue;
  458. if (players[i] istouching(shockEffectArea) && players[i].sessionstate == "playing") {
  459. players[i].lastPoisonedBy = owner;
  460. tabunInitialGasShockDuration = level.tabunInitialGasShockDuration;
  461. if (!players[i] hasPerk("specialty_gas_mask")) players[i] shellShock("tabun_gas_mp", tabunInitialGasShockDuration);
  462. thread inPoisonArea(players[i], shockEffectArea);
  463. players[i] thread maps\mp\gametypes\_battlechatter_mp::incomingSpecialGrenadeTracking("gas");
  464. }
  465. }
  466.  
  467. owner thread maps\mp\_dogs::flash_dogs(shockEffectArea);
  468. gasEffectArea = spawn("trigger_radius", position, 0, level.tabunGasPoisonRadius, level.tabunGasPoisonRadius * 2);
  469. loopWaitTime = 0.5;
  470. durationOfTabun = level.tabunGasDuration;
  471. while (durationOfTabun > 0) {
  472. players = get_players();
  473. for (i = 0; i < players.size; i++) {
  474. if (players[i] player_is_driver()) continue;
  475. if ((!isDefined(players[i].inPoisonArea)) || (players[i].inPoisonArea == false)) {
  476. if (players[i] istouching(gasEffectArea) && players[i].sessionstate == "playing") {
  477. players[i].lastPoisonedBy = owner;
  478. if (!(players[i] hasPerk("specialty_gas_mask"))) players[i] shellShock("tabun_gas_mp", level.tabunWalkInGasShockDuration);
  479. thread inPoisonArea(players[i], gasEffectArea);
  480. }
  481. }
  482. }
  483.  
  484. owner thread maps\mp\_dogs::flash_dogs(gasEffectArea);
  485. wait (loopWaitTime);
  486. durationOfTabun-= loopWaitTime;
  487. }
  488.  
  489. if (level.tabunGasDuration < level.poisonDuration) wait(level.poisonDuration - level.tabunGasDuration);
  490. shockEffectArea delete();
  491. gasEffectArea delete();
  492. }
  493.  
  494. watchGrenadeUsage() {
  495. self endon("death");
  496. self endon("disconnect");
  497. self.throwingGrenade = false;
  498. self.gotPullbackNotify = false;
  499. if (getdvar("scr_deleteexplosivesonspawn") == "") setdvar("scr_deleteexplosivesonspawn", "1");
  500. if (getdvarint("scr_deleteexplosivesonspawn") == 1) {
  501. if (isdefined(self.satchelarray)) {
  502. for (i = 0; i < self.satchelarray.size; i++) {
  503. if (isdefined(self.satchelarray[i])) self.satchelarray[i] delete();
  504. }
  505. }
  506.  
  507. self.satchelarray = [];
  508.  
  509. // delete shoeboxs from previous spawn
  510.  
  511. if (isdefined(self.bettyarray)) {
  512. for (i = 0; i < self.bettyarray.size; i++) {
  513. if (isdefined(self.bettyarray[i])) self.bettyarray[i] delete();
  514. }
  515. }
  516.  
  517. self.bettyarray = [];
  518. }
  519. else {
  520. if (!isdefined(self.bettyarray)) self.bettyarray = [];
  521. if (!isdefined(self.satchelarray)) self.satchelarray = [];
  522. }
  523.  
  524. thread watchBettys();
  525. thread deleteSatchelAndBettysOnDisconnect();
  526. thread watchSatchel();
  527. thread watchSatchelDetonation();
  528. thread watchSatchelAltDetonation();
  529. thread deleteSatchelsAndBettysOnDisconnect();
  530. self thread beginSpecialGrenadeTracking();
  531. self thread watchForThrowbacks();
  532. for (;;) {
  533. self waittill("grenade_pullback", weaponName);
  534. self setStatLBByName(weaponName, 1, "shots");
  535. self.hasDoneCombat = true;
  536. if (weaponName == "mine_bouncing_betty_mp") continue;
  537. self.throwingGrenade = true;
  538. self.gotPullbackNotify = true;
  539. if (weaponName == "satchel_charge_mp") self beginSatchelTracking();
  540. else self beginGrenadeTracking();
  541. }
  542. }
  543.  
  544. beginGrenadeTracking() {
  545. self endon("death");
  546. self endon("disconnect");
  547. startTime = getTime();
  548. self waittill("grenade_fire", grenade, weaponName);
  549. if ((getTime() - startTime > 1000)) grenade.isCooked = true;
  550. if (weaponName == "frag_grenade_mp") {
  551. grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  552. grenade.originalOwner = self ;
  553. }
  554.  
  555. self.throwingGrenade = false;
  556. }
  557.  
  558. beginSpecialGrenadeTracking() {
  559. self notify("grenadeTrackingStart");
  560. self endon("grenadeTrackingStart");
  561. self endon("disconnect");
  562. for (;;) {
  563. self waittill("grenade_fire", grenade, weaponName, parent);
  564. if (weaponName == "tabun_gas_mp") {
  565. grenade thread watchTabunGrenadeDetonation(self);
  566. }
  567. else
  568. if (weaponName == "signal_flare_mp") {
  569. grenade thread maps\mp\_flare::watchFlareDetonation(self);
  570. }
  571. else
  572. if (weaponName == "sticky_grenade_mp" || weaponName == "satchel_charge_mp") {
  573. grenade thread checkStuckToPlayer();
  574. }
  575. }
  576. }
  577.  
  578. checkStuckToplayer () {
  579. self waittill("stuck_to_player ");
  580. self.stuckToplayer = true;
  581. }
  582.  
  583. beginSatchelTracking() {
  584. self endon("death");
  585. self endon("disconnect");
  586. self waittill_any("grenade_fire", "weapon_change");
  587. self.throwingGrenade = false;
  588. }
  589.  
  590. watchForThrowbacks() {
  591. self endon("death");
  592. self endon("disconnect");
  593. for (;;) {
  594. self waittill("grenade_fire", grenade, weapname);
  595. if (self.gotPullbackNotify) {
  596. self.gotPullbackNotify = false;
  597. continue;
  598. }
  599.  
  600. if (!isSubStr(weapname, "frag_")) continue;
  601.  
  602. // no grenade_pullback notify! we must have picked it up off the ground.
  603.  
  604. grenade.threwBack = true;
  605. grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  606. grenade.originalOwner = self ;
  607. }
  608. }
  609.  
  610. watchSatchel() {
  611. self endon("spawned_player ");
  612. self endon("disconnect");
  613.  
  614. while (1) {
  615. self waittill("grenade_fire", satchel, weapname);
  616. if (weapname == "satchel_charge" || weapname == "satchel_charge_mp") {
  617. if (!self.satchelarray.size) self thread watchSatchelAltDetonate();
  618. self.satchelarray[self.satchelarray.size] = satchel;
  619. satchel.owner = self ;
  620. satchel thread bombDetectionTrigger_wait(self.pers["team"]);
  621. satchel thread maps\mp\gametypes\_shellshock::satchel_earthQuake();
  622. satchel thread satchelDamage();
  623. }
  624. }
  625. }
  626.  
  627. watchBettys() {
  628. self endon("spawned_player ");
  629. self endon("disconnect");
  630. self.bettyarray = [];
  631. while (1) {
  632. self waittill("grenade_fire", betty, weapname);
  633. if (weapname == "mine_bouncing_betty_mp") {
  634. self.bettyarray[self.bettyarray.size] = betty;
  635. betty.owner = self ;
  636. betty thread bettyDetonation();
  637.  
  638. betty thread bombDetectionTrigger_wait(self.pers["team"]);
  639. bettymapsmp_entityheadicons::setEntityHeadIcon(self.pers["team"], (0, 0, 20));
  640. betty thread bettyDamage();
  641. }
  642. }
  643. }
  644.  
  645. waitTillNotMoving() {
  646. prevorigin = self.origin;
  647. while (1) {
  648. wait .15;
  649. if (self.origin == prevorigin) break;
  650.  
  651. prevorigin = self.origin;
  652. }
  653. }
  654.  
  655. bettyDetonation() {
  656. self endon("death");
  657. self waitTillNotMoving();
  658. level.bettyDetonateRadius = weapons_get_dvar_int("bettyDetonateRadius", level.bettyDetonateRadius);
  659. level.bettyUpVelocity = weapons_get_dvar_int("bettyUpVelocity", level.bettyUpVelocity);
  660. level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", level.bettyTimeBeforeDetonate);
  661. damagearea = spawn("trigger_radius", self.origin + (0, 0, 0 - level.bettyDetonateRadius) , level.aiTriggerSpawnFlags, level.bettyDetonateRadius, level.bettyDetonateRadius + 36);
  662. self thread deleteOnDeath(damagearea);
  663. rangeOrigin = damagearea.origin + (0, 0, level.bettyDetonateRadius);
  664. while (1) {
  665. damagearea waittill("trigger", triggerer);
  666. if (getdvarint("scr_bettydebug") != 1) {
  667. if (isdefined(self.owner) && triggerer == self.owner) continue;
  668. if (!friendlyFireCheck(self.owner, triggerer, 0)) continue;
  669. if (triggerer.origin[2] < rangeOrigin[2] - 24) continue;
  670. }
  671.  
  672. if ((weapons_get_dvar_int("scr_bettyTriggerDamageTraceEnabled", level.bettyTriggerDamageTraceEnabled)) == 1) {
  673. if (triggererdamageConeTrace(self.origin + (0, 0, 12) , self) > 0) break;
  674.  
  675. wait (weapons_get_dvar("scr_bettyTriggerLoopWait", level.bettyTriggerLoopWait)); // as the damage cone trace is CPU intensive
  676. }
  677. else {
  678. break;
  679. }
  680. }
  681.  
  682. // check if triggerer has survived the betty for the challenges
  683.  
  684. triggerer thread deathDodger();
  685. detonateTime = getTime();
  686. self playsound("betty_activated");
  687. self maps\mp\_entityheadicons::setEntityHeadIcon("none");
  688. self shootup(level.bettyUpVelocity);
  689. fx = PlayFXOnTag(level.bettyFXid, self , "tag_flash");
  690. level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", level.bettyTimeBeforeDetonate);
  691. self thread waitAndDetonate(level.bettyTimeBeforeDetonate);
  692. }
  693.  
  694. deathDodger() {
  695. self endon("death");
  696. self endon("disconnect");
  697. wait (0.2 + level.bettyTimeBeforeDetonate);
  698. self notify("death_dodger");
  699. }
  700.  
  701. deleteOnDeath(ent) {
  702. self waittill("death");
  703. wait.05;
  704. if (isdefined(ent)) ent delete();
  705. }
  706.  
  707. watchSatchelAltDetonation() {
  708. self endon("death");
  709. self endon("disconnect");
  710. while (1) {
  711. self waittill("alt_detonate");
  712. weap = self getCurrentWeapon();
  713. if (weap != "satchel_charge_mp") {
  714. newarray = [];
  715. for (i = 0; i < self.satchelarray.size; i++) {
  716. satchel = self.satchelarray[i];
  717. if (isdefined(self.satchelarray[i])) satchel thread waitAndDetonate(0.1);
  718. }
  719.  
  720. self.satchelarray = newarray;
  721. self notify("detonated");
  722. }
  723. }
  724. }
  725.  
  726. watchSatchelAltDetonate() {
  727. self endon("death");
  728. self endon("disconnect");
  729. self endon("detonated");
  730. level endon("game_ended");
  731. buttonTime = 0;
  732. for (;;) {
  733. if (self UseButtonPressed()) {
  734. buttonTime = 0;
  735. while (self UseButtonPressed()) {
  736. buttonTime+= 0.05;
  737. wait (0.05);
  738. }
  739.  
  740. println("pressTime1: " + buttonTime);
  741. if (buttonTime >= 0.5) continue;
  742. buttonTime = 0;
  743. while (!self UseButtonPressed() && buttonTime < 0.5) {
  744. buttonTime+= 0.05;
  745. wait (0.05);
  746. }
  747.  
  748. println("delayTime: " + buttonTime);
  749. if (buttonTime >= 0.5) continue;
  750. if (!self.satchelarray.size) return;
  751. self notify("alt_detonate");
  752. }
  753.  
  754. wait (0.05);
  755. }
  756. }
  757.  
  758. watchSatchelDetonation() {
  759. self endon("death");
  760. self endon("disconnect");
  761. while (1) {
  762. self waittill("detonate");
  763. weap = self getCurrentWeapon();
  764. if (weap == "satchel_charge_mp") {
  765. for (i = 0; i < self.satchelarray.size; i++) {
  766. if (isdefined(self.satchelarray[i])) self.satchelarray[i] thread waitAndDetonate(0.1);
  767. }
  768.  
  769. self.satchelarray = [];
  770. }
  771. }
  772. }
  773.  
  774. waitAndDetonate(delay) {
  775. self endon("death");
  776. wait (delay);
  777. self detonate();
  778. }
  779.  
  780. deleteSatchelAndbettysOnDisconnect() {
  781. self endon("death");
  782. self waittill("disconnect");
  783. bettyarray = self.bettyarray;
  784. satchelarray = self.satchelarray;
  785. wait.05;
  786. for (i = 0; i < bettyarray.size; i++) {
  787. if (isdefined(bettyarray[i])) bettyarray[i] delete();
  788. }
  789.  
  790. for (i = 0; i < satchelarray.size; i++) {
  791. if (isdefined(satchelarray[i])) satchelarray[i] delete();
  792. }
  793. }
  794.  
  795. deleteSatchelsAndbettysOnDisconnect() {
  796. self endon("death");
  797. self waittill("disconnect");
  798. satchelarray = self.satchelarray;
  799. bettyarray = self.bettyarray;
  800. wait.05;
  801. for (i = 0; i < satchelarray.size; i++) {
  802. if (isdefined(satchelarray[i])) satchelarray[i] delete();
  803. }
  804.  
  805. for (i = 0; i < bettyarray.size; i++) {
  806. if (isdefined(bettyarray[i])) bettyarray[i] delete();
  807. }
  808. }
  809.  
  810. bettyDamage() {
  811. self endon("death");
  812. self setcandamage(true);
  813. self.maxhealth = 100000;
  814. self.health = self.maxhealth;
  815. attacker = undefined;
  816. starttime = getTime();
  817. while (1) {
  818. self waittill("damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags);
  819. if (!isplayer (attacker)) continue;
  820.  
  821. // don't allow people to destroy satchel on their team if FF is off
  822.  
  823. if (!friendlyFireCheck(self.owner, attacker)) continue;
  824. if (damage < 5) // ignore concussion grenades
  825. continue;
  826. break;
  827. }
  828.  
  829. if (level.bettyexplodethisframe) wait.1 + randomfloat(.4);
  830. else wait.05;
  831. if (!isdefined(self)) return;
  832. level.bettyexplodethisframe = true;
  833. thread resetBettyExplodeThisFrame();
  834. self maps\mp\_entityheadicons::setEntityHeadIcon("none");
  835. if (isDefined(type) && (isSubStr(type, "MOD_GRENADE") || isSubStr(type, "MOD_EXPLOSIVE"))) self.wasChained = true;
  836. if (isDefined(iDFlags) && (iDFlags & level.iDFLAGS_PENETRATION)) self.wasDamagedFromBulletPenetration = true;
  837. self.wasDamaged = true;
  838.  
  839. // "destroyed_explosive" notify, for challenges
  840.  
  841. if (isdefined(attacker) && isdefined(attacker.pers["team"]) && isdefined(self.owner) && isdefined(self.owner.pers["team"])) {
  842. if ((attacker.pers["team"] != self.owner.pers["team"]) || ((game["dialog"]["gametype"] == "freeforall") && (attacker != self.owner))) {
  843. attackernotify("destroyed_explosive");
  844. detonateTime = getTime();
  845. if (startTime + 3000 > detonateTime) {
  846. if (attacker != self.owner) self.wasJustPlanted = true;
  847. }
  848. }
  849. }
  850.  
  851. self detonate(attacker);
  852.  
  853. // won't get here; got death notify.
  854.  
  855. }
  856.  
  857. resetbettyExplodeThisFrame() {
  858. wait.05;
  859. level.bettyexplodethisframe = false;
  860. }
  861.  
  862. satchelDamage() {
  863. self endon("death");
  864. self setcandamage(true);
  865. self.maxhealth = 100000;
  866. self.health = self.maxhealth;
  867. attacker = undefined;
  868. while (1) {
  869. self waittill("damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags);
  870. if (!isplayer (attacker)) continue;
  871.  
  872. // don't allow people to destroy satchel on their team if FF is off
  873.  
  874. if (!friendlyFireCheck(self.owner, attacker)) continue;
  875. if (damage < 5) // ignore concussion grenades
  876. continue;
  877. break;
  878. }
  879.  
  880. if (level.satchelexplodethisframe) wait.1 + randomfloat(.4);
  881. else wait.05;
  882. if (!isdefined(self)) return;
  883. level.satchelexplodethisframe = true;
  884. thread resetSatchelExplodeThisFrame();
  885. self maps\mp\_entityheadicons::setEntityHeadIcon("none");
  886. if (isDefined(type) && (isSubStr(type, "MOD_GRENADE_SPLASH") || isSubStr(type, "MOD_GRENADE") || isSubStr(type, "MOD_EXPLOSIVE"))) self.wasChained = true;
  887. if (isDefined(iDFlags) && (iDFlags & level.iDFLAGS_PENETRATION)) self.wasDamagedFromBulletPenetration = true;
  888. self.wasDamaged = true;
  889.  
  890. // "destroyed_explosive" notify, for challenges
  891.  
  892. if (isdefined(attacker) && isdefined(attacker.pers["team"]) && isdefined(self.owner) && isdefined(self.owner.pers["team"])) {
  893. if (attacker.pers["team"] != self.owner.pers["team"]) attackernotify("destroyed_explosive");
  894. }
  895.  
  896. self detonate(attacker);
  897.  
  898. // won't get here; got death notify.
  899.  
  900. }
  901.  
  902. resetSatchelExplodeThisFrame() {
  903. wait.05;
  904. level.satchelexplodethisframe = false;
  905. }
  906.  
  907. sayDamaged(orig, amount) {
  908. for (i = 0; i < 60; i++) {
  909. print3d(orig, "damaged! " + amount);
  910. wait.05;
  911. }
  912. }
  913.  
  914. bombDetectionTrigger_wait(ownerTeam) {
  915. self endon("death");
  916. waitTillNotMoving();
  917. if (level.oldschool) return;
  918. self thread bombDetectionTrigger(ownerTeam);
  919. }
  920.  
  921. bombDetectionTrigger(ownerTeam) {
  922. trigger = spawn("trigger_radius", self.origin - (0, 0, 128) , 0, 512, 256);
  923. trigger.detectId = "trigger" + getTime() + randomInt(1000000);
  924. trigger thread detectIconWaiter(level.otherTeam[ownerTeam]);
  925. self waittill("death");
  926. triggernotify("end_detection");
  927. if (isDefined(trigger.bombSquadIcon)) trigger.bombSquadIcon destroy();
  928. trigger delete();
  929. }
  930.  
  931. detectIconWaiter(detectTeam) {
  932. self endon("end_detection");
  933. level endon("game_ended");
  934. while (!level.gameEnded) {
  935. self waittill("trigger", player);
  936. if (isai(player)) continue;
  937. if (!isdefined(player.detectExplosives) || !player.detectExplosives) continue;
  938.  
  939. // CODER_MOD: Bryce (05/08/08): Don't check team in FFA
  940.  
  941. if (player.team != detectTeam && game["dialog"]["gametype"] != "freeforall") continue;
  942. if (isDefined(player.bombSquadIds[self.detectId])) continue;
  943. player thread showHeadIcon(self);
  944. }
  945. }
  946.  
  947. setupBombSquad() {
  948. self.bombSquadIds = [];
  949. if (self.detectExplosives && !self.bombSquadIcons.size) {
  950. for (i = 0; i < 4; i++) {
  951. self.bombSquadIcons[i] = newClientHudElem(self);
  952. self.bombSquadIcons[i].x = 0;
  953. self.bombSquadIcons[i].y = 0;
  954. self.bombSquadIcons[i].z = 0;
  955. self.bombSquadIcons[i].alpha = 0;
  956. self.bombSquadIcons[i].archived = true;
  957. self.bombSquadIcons[i]setShader("waypoint_bombsquad", 14, 14);
  958. self.bombSquadIcons[i]setWaypoint(false);
  959. self.bombSquadIcons[i].detectId = "";
  960. }
  961. }
  962. else
  963. if (!self.detectExplosives) {
  964. for (i = 0; i < self.bombSquadIcons.size; i++) self.bombSquadIcons[i] destroy();
  965. self.bombSquadIcons = [];
  966. }
  967. }
  968.  
  969. showHeadIcon(trigger) {
  970. triggerDetectId = trigger.detectId;
  971. useId = - 1;
  972. for (i = 0; i < 4; i++) {
  973. detectId = self.bombSquadIcons[i].detectId;
  974. if (detectId == triggerDetectId) return;
  975. if (detectId == "") useId = i;
  976. }
  977.  
  978. if (useId < 0) return;
  979. self.bombSquadIds[triggerDetectId] = true;
  980. self.bombSquadIcons[useId].x = trigger.origin[0];
  981. self.bombSquadIcons[useId].y = trigger.origin[1];
  982. self.bombSquadIcons[useId].z = trigger.origin[2] + 24 + 128;
  983. self.bombSquadIcons[useId]fadeOverTime(0.25);
  984. self.bombSquadIcons[useId].alpha = 1;
  985. self.bombSquadIcons[useId].detectId = trigger.detectId;
  986. while (isAlive(self) && isDefined(trigger) && self isTouching(trigger)) wait (0.05);
  987. if (!isDefined(self)) return;
  988. self.bombSquadIcons[useId].detectId = "";
  989. self.bombSquadIcons[useId]fadeOverTime(0.25);
  990. self.bombSquadIcons[useId].alpha = 0;
  991. self.bombSquadIds[triggerDetectId] = undefined;
  992. }
  993.  
  994. // these functions are used with scripted weapons (like satchels, shoeboxs, artillery)
  995. // returns an array of objects representing damageable entities (including players) within a given sphere.
  996. // each object has the property damageCenter, which represents its center (the location from which it can be damaged).
  997. // each object also has the property entity, which contains the entity that it represents.
  998. // to damage it, call damageEnt() on it.
  999.  
  1000. getDamageableEnts(pos, radius, doLOS, startRadius) {
  1001. ents = [];
  1002. if (!isdefined(doLOS)) doLOS = false;
  1003. if (!isdefined(startRadius)) startRadius = 0;
  1004.  
  1005. // players
  1006.  
  1007. players = level.players;
  1008. for (i = 0; i < players.size; i++) {
  1009. if (!isalive(players[i]) || players[i].sessionstate != "playing") continue;
  1010. player pos = players[i].origin + (0, 0, 32);
  1011. dist = distance(pos, player pos);
  1012. if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, player pos, startRadius, undefined))) {
  1013. newent = spawnstruct();
  1014. newent.isplayer = true;
  1015. newent.isADestructable = false;
  1016. newent.entity = players[i];
  1017. newent.damageCenter = player pos;
  1018. ents[ents.size] = newent;
  1019. }
  1020. }
  1021.  
  1022. // grenades
  1023.  
  1024. grenades = getentarray("grenade", "classname");
  1025. for (i = 0; i < grenades.size; i++) {
  1026. entpos = grenades[i].origin;
  1027. dist = distance(pos, entpos);
  1028. if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, grenades[i]))) {
  1029. newent = spawnstruct();
  1030. newent.isplayer = false;
  1031. newent.isADestructable = false;
  1032. newent.entity = grenades[i];
  1033. newent.damageCenter = entpos;
  1034. ents[ents.size] = newent;
  1035. }
  1036. }
  1037.  
  1038. destructibles = getentarray("destructible", "targetname");
  1039. for (i = 0; i < destructibles.size; i++) {
  1040. entpos = destructibles[i].origin;
  1041. dist = distance(pos, entpos);
  1042. if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, destructibles[i]))) {
  1043. newent = spawnstruct();
  1044. newent.isplayer = false;
  1045. newent.isADestructable = false;
  1046. newent.entity = destructibles[i];
  1047. newent.damageCenter = entpos;
  1048. ents[ents.size] = newent;
  1049. }
  1050. }
  1051.  
  1052. destructables = getentarray("destructable", "targetname");
  1053. for (i = 0; i < destructables.size; i++) {
  1054. entpos = destructables[i].origin;
  1055. dist = distance(pos, entpos);
  1056. if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, destructables[i]))) {
  1057. newent = spawnstruct();
  1058. newent.isplayer = false;
  1059. newent.isADestructable = true;
  1060. newent.entity = destructables[i];
  1061. newent.damageCenter = entpos;
  1062. ents[ents.size] = newent;
  1063. }
  1064. }
  1065.  
  1066. return ents;
  1067. }
  1068.  
  1069. weaponDamageTracePassed(from, to, startRadius, ignore) {
  1070. midpos = undefined;
  1071. diff = to - from;
  1072. if (lengthsquared(diff) < startRadius * startRadius) midpos = to;
  1073. dir = vectornormalize(diff);
  1074. midpos = from + (dir[0] * startRadius, dir[1] * startRadius, dir[2] * startRadius);
  1075. trace = bullettrace(midpos, to, false, ignore);
  1076. if (getdvarint("scr_damage_debug") != 0) {
  1077. if (trace["fraction"] == 1) {
  1078. thread debugline(midpos, to, (1, 1, 1));
  1079. }
  1080. else {
  1081. thread debugline(midpos, trace["position"], (1,.9,.8));
  1082. thread debugline(trace["position"], to, (1,.4,.3));
  1083. }
  1084. }
  1085.  
  1086. return (trace["fraction"] == 1);
  1087. }
  1088.  
  1089. // eInflictor = the entity that causes the damage (e.g. a shoebox)
  1090. // eAttacker = the player that is attacking
  1091. // iDamage = the amount of damage to do
  1092. // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
  1093. // sWeapon = string specifying the weapon used (e.g. "mine_shoebox_mp")
  1094. // damagepos = the position damage is coming from
  1095. // damagedir = the direction damage is moving in
  1096.  
  1097. damageEnt(eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir) {
  1098. if (self.isplayer) {
  1099. self.damageOrigin = damagepos;
  1100. self.entity thread [[level.callbackplayer Damage]](
  1101. eInflictor, // eInflictor The entity that causes the damage.(e.g. a turret)
  1102. eAttacker, // eAttacker The entity that is attacking.
  1103. iDamage, // iDamage Integer specifying the amount of damage done
  1104. 0, // iDFlags Integer specifying flags that are to be applied to the damage
  1105. sMeansOfDeath, // sMeansOfDeath Integer specifying the method of death
  1106. sWeapon, // sWeapon The weapon number of the weapon used to inflict the damage
  1107. damagepos, // vPoint The point the damage is from?
  1108. damagedir, // vDir The direction of the damage
  1109. "none", // sHitLoc The location of the hit
  1110. 0 // psOffsetTime The time offset for the damage
  1111. );
  1112. }
  1113. else {
  1114.  
  1115. // destructable walls and such can only be damaged in certain ways.
  1116.  
  1117. if (self.isADestructable && (sWeapon == "artillery_mp" || sWeapon == "mine_bouncing_betty_mp")) return;
  1118. self.entitynotify("damage", iDamage, eAttacker, (0, 0, 0) , (0, 0, 0) , "mod_explosive", "", "");
  1119. }
  1120. }
  1121.  
  1122. debugLine(a, b, color) {
  1123. for (i = 0; i < 30 * 20; i++) {
  1124. line(a, b, color);
  1125. wait.05;
  1126. }
  1127. }
  1128.  
  1129. onWeaponDamage(eInflictor, sWeapon, meansOfDeath, damage) {
  1130. self endon("death");
  1131. self endon("disconnect");
  1132. switch (sWeapon) {
  1133. case "concussion_grenade_mp":
  1134.  
  1135. // should match weapon settings in gdt
  1136.  
  1137. radius = 512;
  1138. scale = 1 - (distance(self.origin, eInflictor.origin) / radius);
  1139. if (scale < 0) scale = 0;
  1140. time = 2 + (4 * scale);
  1141. wait (0.05);
  1142.  
  1143. self.concussionEndTime = getTime() + (time * 1000);
  1144. break;
  1145.  
  1146. default:
  1147.  
  1148. // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage.
  1149.  
  1150. maps\mp\gametypes\_shellshock::shellshockOnDamage(meansOfDeath, damage);
  1151. break;
  1152. }
  1153. }
  1154.  
  1155. // weapon stowing logic ===================================================================
  1156. // weapon class boolean helpers
  1157.  
  1158. isPrimaryWeapon(weaponname) {
  1159. return isdefined(level.primary_weapon_array[weaponname]);
  1160. }
  1161.  
  1162. isSideArm(weaponname) {
  1163. return isdefined(level.side_arm_array[weaponname]);
  1164. }
  1165.  
  1166. isInventory(weaponname) {
  1167. return isdefined(level.inventory_array[weaponname]);
  1168. }
  1169.  
  1170. isGrenade(weaponname) {
  1171. return isdefined(level.grenade_array[weaponname]);
  1172. }
  1173.  
  1174. getWeaponClass_array(current) {
  1175. if (isPrimaryWeapon(current)) return level.primary_weapon_array;
  1176. else
  1177. if (isSideArm(current)) return level.side_arm_array;
  1178. else
  1179. if (isGrenade(current)) return level.grenade_array;
  1180. else return level.inventory_array;
  1181. }
  1182.  
  1183. // thread loop life = player 's life
  1184.  
  1185. updateStowedWeapon() {
  1186. self endon("spawned");
  1187. self endon("killed_player ");
  1188. self endon("disconnect");
  1189.  
  1190. self.tag_stowed_back = undefined;
  1191. self.tag_stowed_hip = undefined;
  1192. team = self.pers["team"];
  1193. class = self.pers["class"];
  1194.  
  1195. while (true) {
  1196. self waittill("weapon_change", newWeapon);
  1197.  
  1198. // weapon array reset, might have swapped weapons off the ground
  1199.  
  1200. self.weapon_array_primary = [];
  1201. self.weapon_array_sidearm = [];
  1202. self.weapon_array_grenade = [];
  1203. self.weapon_array_inventory = [];
  1204.  
  1205. // populate player 's weapon stock arrays
  1206.  
  1207. weaponsList = self getWeaponsList();
  1208. for (idx = 0; idx < weaponsList.size; idx++) {
  1209. if (isPrimaryWeapon(weaponsList[idx])) self.weapon_array_primary[self.weapon_array_primary.size] = weaponsList[idx];
  1210. else
  1211. if (isSideArm(weaponsList[idx])) self.weapon_array_sidearm[self.weapon_array_sidearm.size] = weaponsList[idx];
  1212. else
  1213. if (isGrenade(weaponsList[idx])) self.weapon_array_grenade[self.weapon_array_grenade.size] = weaponsList[idx];
  1214. else
  1215. if (isInventory(weaponsList[idx])) self.weapon_array_inventory[self.weapon_array_inventory.size] = weaponsList[idx];
  1216. }
  1217.  
  1218. detach_all_weapons();
  1219. stow_on_back();
  1220. stow_on_hip();
  1221. }
  1222. }
  1223.  
  1224. forceStowedWeaponUpdate() {
  1225. detach_all_weapons();
  1226. stow_on_back();
  1227. stow_on_hip();
  1228. }
  1229.  
  1230. detachCarryObjectModel() {
  1231. if (isDefined(self.carryObject) && isdefined(self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel())) {
  1232. if (isDefined(self.tag_stowed_back)) {
  1233. self detach(self.tag_stowed_back, "tag_stowed_back");
  1234. self.tag_stowed_back = undefined;
  1235. }
  1236. }
  1237. }
  1238.  
  1239. detach_all_weapons() {
  1240. if (isDefined(self.tag_stowed_back)) {
  1241. self detach(self.tag_stowed_back, "tag_stowed_back");
  1242. self.tag_stowed_back = undefined;
  1243. }
  1244.  
  1245. if (isDefined(self.tag_stowed_hip)) {
  1246. detach_model = getWeaponModel(self.tag_stowed_hip);
  1247. self detach(detach_model, "tag_stowed_hip_rear");
  1248. self.tag_stowed_hip = undefined;
  1249. }
  1250. }
  1251.  
  1252. stow_on_back() {
  1253. current = self getCurrentWeapon();
  1254. self.tag_stowed_back = undefined;
  1255.  
  1256. // carry objects take priority
  1257.  
  1258. if (isDefined(self.carryObject) && isdefined(self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel())) {
  1259. self.tag_stowed_back = self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel();
  1260. }
  1261. else
  1262. if (self hasWeapon("m2_flamethrower_mp")) {
  1263.  
  1264. // no back stowing if you have flamethrower tanks
  1265.  
  1266. return;
  1267. }
  1268.  
  1269. // large projectile weaponry always show
  1270.  
  1271. else
  1272. if (self hasWeapon("bazooka_mp") && current != "bazooka_mp") {
  1273. self.tag_stowed_back = "weapon_mp_bazooka_attach";
  1274. }
  1275. else {
  1276. for (idx = 0; idx < self.weapon_array_primary.size; idx++) {
  1277. index_weapon = self.weapon_array_primary[idx];
  1278. assertex(isdefined(index_weapon) , "Primary weapon list corrupted.");
  1279. if (index_weapon == current) continue;
  1280. if (isSubStr(current, "gl_") || isSubStr(index_weapon, "gl_")) {
  1281. index_weapon_tok = strtok(index_weapon, "_");
  1282. current_tok = strtok(current, "_");
  1283.  
  1284. // finding the alt-mode of current weapon; the tokens of both weapons are subsets of each other
  1285.  
  1286. for (i = 0; i < index_weapon_tok.size; i++) {
  1287. if (!isSubStr(current, index_weapon_tok[i]) || index_weapon_tok.size != current_tok.size) {
  1288. i = 0;
  1289. break;
  1290. }
  1291. }
  1292.  
  1293. if (i == index_weapon_tok.size) continue;
  1294. }
  1295.  
  1296. // camo only applicable for custom classes
  1297.  
  1298. assertex(isdefined(self.curclass) , "player missing current class");
  1299. if (isDefined(self.custom_class) && isDefined(self.custom_class[self.class_num]["camo_num"]) && isSubStr(index_weapon, self.pers["primaryWeapon"]) && isSubStr(self.curclass, "CUSTOM")) self.tag_stowed_back = getWeaponModel(index_weapon, self.custom_class[self.class_num]["camo_num"]);
  1300. else self.tag_stowed_back = getWeaponModel(index_weapon, 0);
  1301. }
  1302. }
  1303.  
  1304. if (!isDefined(self.tag_stowed_back)) return;
  1305. self attach(self.tag_stowed_back, "tag_stowed_back", true);
  1306. }
  1307.  
  1308. stow_on_hip() {
  1309. current = self getCurrentWeapon();
  1310. self.tag_stowed_hip = undefined;
  1311. for (idx = 0; idx < self.weapon_array_inventory.size; idx++) {
  1312. if (self.weapon_array_inventory[idx] == current) continue;
  1313. if (!self GetWeaponAmmoStock(self.weapon_array_inventory[idx])) continue;
  1314. self.tag_stowed_hip = self.weapon_array_inventory[idx];
  1315. }
  1316.  
  1317. if (!isDefined(self.tag_stowed_hip)) return;
  1318.  
  1319. // getting rid of these until we get attach models
  1320.  
  1321. if (self.tag_stowed_hip == "satchel_charge_mp" || self.tag_stowed_hip == "mine_bouncing_betty_mp") {
  1322. self.tag_stowed_hip = undefined;
  1323. return;
  1324. }
  1325.  
  1326. weapon_model = getWeaponModel(self.tag_stowed_hip);
  1327. self attach(weapon_model, "tag_stowed_hip_rear", true);
  1328. }
  1329.  
  1330. stow_inventory(inventories, current) {
  1331.  
  1332. // deatch last weapon attached
  1333.  
  1334. if (isdefined(self.inventory_tag)) {
  1335. detach_model = getweaponmodel(self.inventory_tag);
  1336. self detach(detach_model, "tag_stowed_hip_rear");
  1337. self.inventory_tag = undefined;
  1338. }
  1339.  
  1340. if (!isdefined(inventories[0]) || self GetWeaponAmmoStock(inventories[0]) == 0) return;
  1341. if (inventories[0] != current) {
  1342. self.inventory_tag = inventories[0];
  1343. weapon_model = getweaponmodel(self.inventory_tag);
  1344. self attach(weapon_model, "tag_stowed_hip_rear", true);
  1345. }
  1346. }
  1347.  
  1348. // returns dvar value in int
  1349.  
  1350. weapons_get_dvar_int(dvar, def) {
  1351. return int(weapons_get_dvar(dvar, def));
  1352. }
  1353.  
  1354. // dvar set/fetch/check
  1355.  
  1356. weapons_get_dvar(dvar, def) {
  1357. if (getdvar(dvar) != "") {
  1358. return getdvarfloat(dvar);
  1359. }
  1360. else {
  1361. setdvar(dvar, def);
  1362. return def;
  1363. }
  1364. }
  1365.  
  1366. player_is_driver() {
  1367. if (!isalive(self)) return false;
  1368. vehicle = self getVehicleOccupied();
  1369. if (IsDefined(vehicle)) {
  1370. seat = vehicle GetOccupantSeat(self);
  1371. if (isdefined(seat) && seat == 0) return true;
  1372. }
  1373.  
  1374. return false;
  1375. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement