Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include common_scripts\utility;
- #include maps\mp\_utility;
- init() {
- // assigns weapons with stat numbers from 0-149
- // attachments are now shown here, they are per weapon settings inste
- // generating weaponIDs array
- level.weaponIDs = [];
- max_weapon_num = 149;
- attachment_num = 150;
- for (i = 0; i <= max_weapon_num; i++) {
- weapon_name = tablelookup("mp/statstable.csv", 0, i, 4);
- if (!isdefined(weapon_name) || weapon_name == "") {
- level.weaponIDs[i] = "";
- continue;
- }
- level.weaponIDs[i] = weapon_name + "_mp";
- // generating attachment combinations
- attachment = tablelookup("mp/statstable.csv", 0, i, 8);
- if (!isdefined(attachment) || attachment == "") continue;
- attachment_tokens = strtok(attachment, " ");
- if (!isdefined(attachment_tokens)) continue;
- if (attachment_tokens.size == 0) {
- level.weaponIDs[attachment_num] = weapon_name + "_" + attachment + "_mp";
- attachment_num++;
- }
- else {
- for (k = 0; k < attachment_tokens.size; k++) {
- level.weaponIDs[attachment_num] = weapon_name + "_" + attachment_tokens[k] + "_mp";
- attachment_num++;
- }
- }
- }
- level.weaponNames = [];
- for (i = 0; i < max_weapon_num; i++) {
- if (!isdefined(level.weaponIDs[i]) || level.weaponIDs[i] == "") continue;
- level.weaponNames[level.weaponIDs[i]] = i;
- }
- level.weaponlist = [];
- assertex(isdefined(level.weaponIDs.size) , "level.weaponIDs is corrupted");
- for (i = 0; i < level.weaponIDs.size; i++) {
- if (!isdefined(level.weaponIDs[i]) || level.weaponIDs[i] == "") continue;
- level.weaponlist[level.weaponlist.size] = level.weaponIDs[i];
- }
- for (i = 0; i < level.weaponList.size; i++) {
- precacheItem(level.weaponList[i]);
- println("Precached weapon: " + level.weaponList[i]);
- }
- precacheItem("frag_grenade_short_mp");
- precacheModel("weapon_mp_bazooka_attach");
- precacheItem("napalmblob_mp");
- precacheItem("t34_mp_explosion_mp");
- precacheItem("panzer4_mp_explosion_mp");
- precacheShellShock("default");
- precacheShellShock("tabun_gas_mp");
- thread maps\mp\_flashgrenades::main();
- thread maps\mp\_entityheadicons::init();
- level.bettyDetonateRadius = weapons_get_dvar_int("bettyDetonateRadius", "150");
- level.bettyUpVelocity = weapons_get_dvar_int("bettyUpVelocity", "296");
- level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", "0.45");
- level.bettyTriggerDamageTraceEnabled = weapons_get_dvar_int("scr_bettyTriggerDamageTraceEnabled", "1");
- level.bettyTriggerLoopWait = weapons_get_dvar("scr_bettyTriggerLoopWait", 0.1);
- level.tabunInitialGasShockDuration = weapons_get_dvar_int("tabunInitialGasShockDuration", "7");
- level.tabunWalkInGasShockDuration = weapons_get_dvar_int("tabunWalkInGasShockDuration", "4");
- level.tabunGasShockRadius = weapons_get_dvar_int("tabun_shock_radius", "150");
- level.tabunGasPoisonRadius = weapons_get_dvar_int("tabun_effect_radius", "150");
- // Radius of effect of poison gas
- 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
- level.poisonDuration = weapons_get_dvar_int("poisonDuration", "8"); // in seconds you will get poison full screen effect for
- level.slappedWithMolotovDamage = 35; // how much damage to be applied every second
- level.bettyFXid = loadfx("weapon/bouncing_betty/fx_betty_trail");
- level thread onPlayerConnect();
- level.satchelexplodethisframe = false;
- level.bettyexplodethisframe = false;
- }
- isStrStart(string1, subStr) {
- return (getSubStr(string1, 0, subStr.size) == subStr);
- }
- onPlayerConnect() {
- for (;;) {
- level waittill("connecting", player);
- player.usedWeapons = false;
- player.hits = 0;
- player thread onPlayerSpawned();
- }
- }
- onPlayerSpawned() {
- self endon("disconnect");
- for (;;) {
- self waittill("spawned_player ");
- self.concussionEndTime = 0;
- self.hasDoneCombat = false;
- self thread watchWeaponUsage();
- self thread watchGrenadeUsage();
- self thread watchWeaponChange();
- self.droppedDeathWeapon = undefined;
- self.tookWeaponFrom = [];
- self thread updateStowedWeapon();
- }
- }
- watchWeaponChange() {
- self endon("death");
- self endon("disconnect");
- self.lastDroppableWeapon = self getCurrentWeapon();
- while (1) {
- self waittill("weapon_change", newWeapon);
- if (mayDropWeapon(newWeapon)) self.lastDroppableWeapon = newWeapon;
- }
- }
- isPistol(weapon) {
- return isdefined(level.side_arm_array[weapon]);
- }
- hasScope(weapon) {
- if (isSubStr(weapon, "_acog_")) return true;
- if (weapon == "m21_mp") return true;
- if (weapon == "aw50_mp") return true;
- if (weapon == "barrett_mp") return true;
- if (weapon == "dragunov_mp") return true;
- if (weapon == "m40a3_mp") return true;
- if (weapon == "remington700_mp") return true;
- return false;
- }
- isHackWeapon(weapon) {
- if (weapon == "radar_mp" || weapon == "artillery_mp" || weapon == "dogs_mp") return true;
- if (weapon == "briefcase_bomb_mp") return true;
- return false;
- }
- mayDropWeapon(weapon) {
- if (weapon == "none") return false;
- if (isHackWeapon(weapon)) return false;
- invType = WeaponInventoryType(weapon);
- if (invType != "primary") return false;
- if (weapon == "none") return false;
- return true;
- }
- dropWeaponForDeath(attacker) {
- weapon = self.lastDroppableWeapon;
- if (isdefined(self.droppedDeathWeapon)) return;
- if (!isdefined(weapon)) return;
- if (weapon == "none") return;
- if (!self hasWeapon(weapon)) return;
- if (!(self AnyAmmoForWeaponModes(weapon))) return;
- clipAmmo = self GetWeaponAmmoClip(weapon);
- if (!clipAmmo) return;
- stockAmmo = self GetWeaponAmmoStock(weapon);
- stockMax = WeaponMaxAmmo(weapon);
- if (stockAmmo > stockMax) stockAmmo = stockMax;
- item = self dropItem(weapon);
- self.droppedDeathWeapon = true;
- item itemWeaponSetAmmo(clipAmmo, stockAmmo);
- item itemRemoveAmmoFromAltModes();
- item.owner = self ;
- item.ownersattacker = attacker;
- item thread watchPickup();
- item thread deletePickupAfterAWhile();
- }
- deletePickupAfterAWhile() {
- self endon("death");
- wait 60;
- if (!isDefined(self)) return;
- self delete();
- }
- getItemWeaponName() {
- classname = self.classname;
- assert(getsubstr(classname, 0, 7) == "weapon_");
- weapname = getsubstr(classname, 7);
- return weapname;
- }
- watchPickup() {
- self endon("death");
- weapname = self getItemWeaponName();
- while (1) {
- self waittill("trigger", player , droppedItem);
- if (isdefined(droppedItem)) break;
- // otherwise, player merely acquired ammo and didn't pick this up
- }
- assert(isdefined(player.tookWeaponFrom));
- droppedWeaponName = droppedItem getItemWeaponName();
- if (isdefined(player.tookWeaponFrom[droppedWeaponName])) {
- droppedItem.owner = player.tookWeaponFrom[droppedWeaponName];
- droppedItem.ownersattacker = player ;
- player.tookWeaponFrom[droppedWeaponName] = undefined;
- }
- droppedItem thread watchPickup();
- if (isdefined(self.ownersattacker) && self.ownersattacker == player) {
- player.tookWeaponFrom[weapname] = self.owner;
- }
- else {
- player.tookWeaponFrom[weapname] = undefined;
- }
- }
- itemRemoveAmmoFromAltModes() {
- origweapname = self getItemWeaponName();
- curweapname = weaponAltWeaponName(origweapname);
- altindex = 1;
- while (curweapname != "none" && curweapname != origweapname) {
- self itemWeaponSetAmmo(0, 0, altindex);
- curweapname = weaponAltWeaponName(curweapname);
- altindex++;
- }
- }
- dropOffhand() {
- grenadeTypes = self thread getGrenadeTypes();
- for (i = 0; i < grenadeTypes.size; i++) {
- if (!self hasWeapon(grenadeTypes[i])) continue;
- count = self getAmmoCount(grenadeTypes[i]);
- if (!count) continue;
- self setWeaponAmmoClip(grenadeTypes[i], 1);
- item = self dropItem(grenadeTypes[i]);
- item thread deletePickupAfterAWhile();
- }
- }
- getGrenadeTypes() {
- grenadeTypes = [];
- grenadeTypes[0] = "frag_grenade_mp";
- grenadeTypes[1] = "sticky_grenade_mp";
- grenadeTypes[2] = "molotov_mp";
- return grenadeTypes;
- }
- getGrenade() {
- grenade = [];
- class = self.pers["class"];
- classNum = int(class [class.size - 1]) - 1;
- if (classNum == - 1) {
- if (isSubstr(class , "CLASS_DEMOLITIONS")) grenade["type"] = "sticky_grenade_mp";
- else grenade["type"] = "frag_grenade_mp";
- grenade["count"] = 1;
- }
- else {
- grenade["type"] = self.custom_class[classNum]["grenades"];
- grenade["count"] = self.custom_class[classNum]["grenades_count"];
- }
- return grenade;
- }
- pickupOffhand() {
- level endon("game_ended");
- self endon("disconnect");
- self endon("death");
- self endon("killed_player ");
- grenade = self thread getGrenade();
- grenadeTypes = self thread getGrenadeTypes();
- for (;;) {
- clipAmmo = self getWeaponAmmoClip(grenade["type"]);
- for (i = 0; i < grenadeTypes.size; i++) {
- if (grenade["type"] != grenadeTypes[i]) {
- if (self hasWeapon(grenadeTypes[i])) {
- if (grenade["type"] != "molotov_mp") clipAmmo = clipAmmo - 1;
- for (i = 0; i < grenadeTypes.size; i++) self takeWeapon(grenadeTypes[i]);
- self giveWeapon(grenade["type"]);
- if (grenade["count"] == 2)
- if (clipAmmo < 2) self setWeaponAmmoClip(grenade["type"], clipAmmo + 1);
- else self setWeaponAmmoClip(grenade["type"], 2);
- else self setWeaponAmmoClip(grenade["type"], 1);
- }
- else {
- if (clipAmmo > grenade["count"]) self setWeaponAmmoClip(grenade["type"], grenade["count"]);
- }
- }
- }
- wait 1;
- }
- }
- getWeaponBasedGrenadeCount(weapon) {
- return 2;
- }
- getWeaponBasedSmokeGrenadeCount(weapon) {
- return 1;
- }
- getFragGrenadeCount() {
- grenadetype = "frag_grenade_mp";
- count = self getammocount(grenadetype);
- return count;
- }
- getSmokeGrenadeCount() {
- grenadetype = "smoke_grenade_mp";
- count = self getammocount(grenadetype);
- return count;
- }
- watchWeaponUsage() {
- self endon("death");
- self endon("disconnect");
- level endon("game_ended");
- self.firingWeapon = false;
- for (;;) {
- self waittill("begin_firing");
- self.hasDoneCombat = true;
- self.firingWeapon = true;
- curWeapon = self getCurrentWeapon();
- switch (weaponClass(curWeapon)) {
- case "rifle":
- case "pistol":
- case "mg":
- case "smg":
- case "spread":
- self thread watchCurrentFiring(curWeapon);
- break;
- default:
- break;
- }
- self waittill("end_firing");
- self.firingWeapon = false;
- if (curWeapon == "bazooka_mp") {
- self setStatLBByName(curWeapon, 1, "shots");
- }
- }
- }
- watchCurrentFiring(curWeapon) {
- self endon("disconnect");
- startAmmo = self getWeaponAmmoClip(curWeapon);
- wasInLastStand = isDefined(self.lastStand);
- self waittill("end_firing");
- if (!self hasWeapon(curWeapon)) return;
- // ignore the case where a player is firing as they enter last stand.
- // it makes it too hard to calculate shotsFired properly.
- if (isDefined(self.lastStand) && !wasInLastStand) return;
- shotsFired = startAmmo - (self getWeaponAmmoClip(curWeapon)) + 1;
- if (isDefined(self.lastStandParams) && self.lastStandParams.lastStandStartTime == getTime()) {
- self.hits = 0;
- return;
- }
- assertEx(shotsFired >= 0, shotsFired + " startAmmo: " + startAmmo + " clipAmmo: " + self getWeaponAmmoclip(curWeapon) + " w/ " + curWeapon);
- if (shotsFired <= 0) return;
- self setStatLBByName(curWeapon, shotsFired, "shots");
- self setStatLBByName(curWeapon, self.hits, "hits");
- statTotal = self maps\mp\gametypes\_persistence::statGet("total_shots") + shotsFired;
- statHits = self maps\mp\gametypes\_persistence::statGet("hits") + self.hits;
- statMisses = self maps\mp\gametypes\_persistence::statGet("misses") + shotsFired - self.hits;
- self maps\mp\gametypes\_persistence::statSet("total_shots", statTotal);
- self maps\mp\gametypes\_persistence::statSet("hits", statHits);
- self maps\mp\gametypes\_persistence::statSet("misses", int(max(0, statMisses)));
- self maps\mp\gametypes\_persistence::statSet("accuracy", int(statHits * 10000 / statTotal));
- self.hits = 0;
- }
- checkHit(sWeapon) {
- switch (weaponClass(sWeapon)) {
- case "rifle":
- case "pistol":
- case "mg":
- case "smg":
- self.hits++;
- break;
- case "spread":
- self.hits = 1;
- break;
- default:
- break;
- }
- if ((sWeapon == "bazooka_mp") || isStrStart(sWeapon, "t34") || isStrStart(sWeapon, "panzer")) {
- self setStatLBByName(sWeapon, 1, "hits");
- }
- }
- // returns true if damage should be done to the item given its owner and the attacker
- friendlyFireCheck(owner, attacker, forcedFriendlyFireRule) {
- if (!isdefined(owner)) // owner has disconnected? allow it
- return true;
- if (!level.teamBased) // not a team based mode? allow it
- return true;
- friendlyFireRule = level.friendlyfire;
- if (isdefined(forcedFriendlyFireRule)) friendlyFireRule = forcedFriendlyFireRule;
- if (friendlyFireRule != 0) // friendly fire is on? allow it
- return true;
- if (attacker == owner) // owner may attack his own items
- return true;
- if (isplayer (attacker)) {
- if (!isdefined(attacker.pers["team"])) // attacker not on a team? allow it
- return true;
- if (attacker.pers["team"] != owner.pers["team"]) // attacker not on the same team as the owner? allow it
- return true;
- }
- else
- if (isai(attacker)) {
- if (attacker.aiteam != owner.pers["team"]) // attacker not on the same team as the owner? allow it
- return true;
- }
- return false; // disallow it
- }
- inPoisonArea(player , gasEffectArea) {
- player endon("disconnect");
- player.inPoisonArea = true;
- player startPoisoning();
- while ((isdefined(gasEffectArea)) && player istouching(gasEffectArea) && player.sessionstate == "playing") {
- wait (0.25);
- }
- player stopPoisoning();
- player.inPoisonArea = false;
- }
- watchTabunGrenadeDetonation(owner) {
- self waittill("explode", position);
- level.tabunGasPoisonRadius = weapons_get_dvar_int("tabun_effect_radius", level.tabunGasPoisonRadius);
- level.tabunGasShockRadius = weapons_get_dvar_int("tabun_shock_radius", level.tabunGasShockRadius);
- level.tabunInitialGasShockDuration = weapons_get_dvar_int("tabunInitialGasShockDuration", level.tabunInitialGasShockDuration);
- level.tabunWalkInGasShockDuration = weapons_get_dvar_int("tabunWalkInGasShockDuration", level.tabunWalkInGasShockDuration);
- level.tabunGasDuration = weapons_get_dvar_int("tabunGasDuration", level.tabunGasDuration);
- shockEffectArea = spawn("trigger_radius", position, 0, level.tabunGasShockRadius, level.tabunGasShockRadius * 2);
- players = get_players();
- for (i = 0; i < players.size; i++) {
- if (players[i] player_is_driver()) continue;
- if (players[i] istouching(shockEffectArea) && players[i].sessionstate == "playing") {
- players[i].lastPoisonedBy = owner;
- tabunInitialGasShockDuration = level.tabunInitialGasShockDuration;
- if (!players[i] hasPerk("specialty_gas_mask")) players[i] shellShock("tabun_gas_mp", tabunInitialGasShockDuration);
- thread inPoisonArea(players[i], shockEffectArea);
- players[i] thread maps\mp\gametypes\_battlechatter_mp::incomingSpecialGrenadeTracking("gas");
- }
- }
- owner thread maps\mp\_dogs::flash_dogs(shockEffectArea);
- gasEffectArea = spawn("trigger_radius", position, 0, level.tabunGasPoisonRadius, level.tabunGasPoisonRadius * 2);
- loopWaitTime = 0.5;
- durationOfTabun = level.tabunGasDuration;
- while (durationOfTabun > 0) {
- players = get_players();
- for (i = 0; i < players.size; i++) {
- if (players[i] player_is_driver()) continue;
- if ((!isDefined(players[i].inPoisonArea)) || (players[i].inPoisonArea == false)) {
- if (players[i] istouching(gasEffectArea) && players[i].sessionstate == "playing") {
- players[i].lastPoisonedBy = owner;
- if (!(players[i] hasPerk("specialty_gas_mask"))) players[i] shellShock("tabun_gas_mp", level.tabunWalkInGasShockDuration);
- thread inPoisonArea(players[i], gasEffectArea);
- }
- }
- }
- owner thread maps\mp\_dogs::flash_dogs(gasEffectArea);
- wait (loopWaitTime);
- durationOfTabun-= loopWaitTime;
- }
- if (level.tabunGasDuration < level.poisonDuration) wait(level.poisonDuration - level.tabunGasDuration);
- shockEffectArea delete();
- gasEffectArea delete();
- }
- watchGrenadeUsage() {
- self endon("death");
- self endon("disconnect");
- self.throwingGrenade = false;
- self.gotPullbackNotify = false;
- if (getdvar("scr_deleteexplosivesonspawn") == "") setdvar("scr_deleteexplosivesonspawn", "1");
- if (getdvarint("scr_deleteexplosivesonspawn") == 1) {
- if (isdefined(self.satchelarray)) {
- for (i = 0; i < self.satchelarray.size; i++) {
- if (isdefined(self.satchelarray[i])) self.satchelarray[i] delete();
- }
- }
- self.satchelarray = [];
- // delete shoeboxs from previous spawn
- if (isdefined(self.bettyarray)) {
- for (i = 0; i < self.bettyarray.size; i++) {
- if (isdefined(self.bettyarray[i])) self.bettyarray[i] delete();
- }
- }
- self.bettyarray = [];
- }
- else {
- if (!isdefined(self.bettyarray)) self.bettyarray = [];
- if (!isdefined(self.satchelarray)) self.satchelarray = [];
- }
- thread watchBettys();
- thread deleteSatchelAndBettysOnDisconnect();
- thread watchSatchel();
- thread watchSatchelDetonation();
- thread watchSatchelAltDetonation();
- thread deleteSatchelsAndBettysOnDisconnect();
- self thread beginSpecialGrenadeTracking();
- self thread watchForThrowbacks();
- for (;;) {
- self waittill("grenade_pullback", weaponName);
- self setStatLBByName(weaponName, 1, "shots");
- self.hasDoneCombat = true;
- if (weaponName == "mine_bouncing_betty_mp") continue;
- self.throwingGrenade = true;
- self.gotPullbackNotify = true;
- if (weaponName == "satchel_charge_mp") self beginSatchelTracking();
- else self beginGrenadeTracking();
- }
- }
- beginGrenadeTracking() {
- self endon("death");
- self endon("disconnect");
- startTime = getTime();
- self waittill("grenade_fire", grenade, weaponName);
- if ((getTime() - startTime > 1000)) grenade.isCooked = true;
- if (weaponName == "frag_grenade_mp") {
- grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- grenade.originalOwner = self ;
- }
- self.throwingGrenade = false;
- }
- beginSpecialGrenadeTracking() {
- self notify("grenadeTrackingStart");
- self endon("grenadeTrackingStart");
- self endon("disconnect");
- for (;;) {
- self waittill("grenade_fire", grenade, weaponName, parent);
- if (weaponName == "tabun_gas_mp") {
- grenade thread watchTabunGrenadeDetonation(self);
- }
- else
- if (weaponName == "signal_flare_mp") {
- grenade thread maps\mp\_flare::watchFlareDetonation(self);
- }
- else
- if (weaponName == "sticky_grenade_mp" || weaponName == "satchel_charge_mp") {
- grenade thread checkStuckToPlayer();
- }
- }
- }
- checkStuckToplayer () {
- self waittill("stuck_to_player ");
- self.stuckToplayer = true;
- }
- beginSatchelTracking() {
- self endon("death");
- self endon("disconnect");
- self waittill_any("grenade_fire", "weapon_change");
- self.throwingGrenade = false;
- }
- watchForThrowbacks() {
- self endon("death");
- self endon("disconnect");
- for (;;) {
- self waittill("grenade_fire", grenade, weapname);
- if (self.gotPullbackNotify) {
- self.gotPullbackNotify = false;
- continue;
- }
- if (!isSubStr(weapname, "frag_")) continue;
- // no grenade_pullback notify! we must have picked it up off the ground.
- grenade.threwBack = true;
- grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- grenade.originalOwner = self ;
- }
- }
- watchSatchel() {
- self endon("spawned_player ");
- self endon("disconnect");
- while (1) {
- self waittill("grenade_fire", satchel, weapname);
- if (weapname == "satchel_charge" || weapname == "satchel_charge_mp") {
- if (!self.satchelarray.size) self thread watchSatchelAltDetonate();
- self.satchelarray[self.satchelarray.size] = satchel;
- satchel.owner = self ;
- satchel thread bombDetectionTrigger_wait(self.pers["team"]);
- satchel thread maps\mp\gametypes\_shellshock::satchel_earthQuake();
- satchel thread satchelDamage();
- }
- }
- }
- watchBettys() {
- self endon("spawned_player ");
- self endon("disconnect");
- self.bettyarray = [];
- while (1) {
- self waittill("grenade_fire", betty, weapname);
- if (weapname == "mine_bouncing_betty_mp") {
- self.bettyarray[self.bettyarray.size] = betty;
- betty.owner = self ;
- betty thread bettyDetonation();
- betty thread bombDetectionTrigger_wait(self.pers["team"]);
- bettymapsmp_entityheadicons::setEntityHeadIcon(self.pers["team"], (0, 0, 20));
- betty thread bettyDamage();
- }
- }
- }
- waitTillNotMoving() {
- prevorigin = self.origin;
- while (1) {
- wait .15;
- if (self.origin == prevorigin) break;
- prevorigin = self.origin;
- }
- }
- bettyDetonation() {
- self endon("death");
- self waitTillNotMoving();
- level.bettyDetonateRadius = weapons_get_dvar_int("bettyDetonateRadius", level.bettyDetonateRadius);
- level.bettyUpVelocity = weapons_get_dvar_int("bettyUpVelocity", level.bettyUpVelocity);
- level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", level.bettyTimeBeforeDetonate);
- damagearea = spawn("trigger_radius", self.origin + (0, 0, 0 - level.bettyDetonateRadius) , level.aiTriggerSpawnFlags, level.bettyDetonateRadius, level.bettyDetonateRadius + 36);
- self thread deleteOnDeath(damagearea);
- rangeOrigin = damagearea.origin + (0, 0, level.bettyDetonateRadius);
- while (1) {
- damagearea waittill("trigger", triggerer);
- if (getdvarint("scr_bettydebug") != 1) {
- if (isdefined(self.owner) && triggerer == self.owner) continue;
- if (!friendlyFireCheck(self.owner, triggerer, 0)) continue;
- if (triggerer.origin[2] < rangeOrigin[2] - 24) continue;
- }
- if ((weapons_get_dvar_int("scr_bettyTriggerDamageTraceEnabled", level.bettyTriggerDamageTraceEnabled)) == 1) {
- if (triggererdamageConeTrace(self.origin + (0, 0, 12) , self) > 0) break;
- wait (weapons_get_dvar("scr_bettyTriggerLoopWait", level.bettyTriggerLoopWait)); // as the damage cone trace is CPU intensive
- }
- else {
- break;
- }
- }
- // check if triggerer has survived the betty for the challenges
- triggerer thread deathDodger();
- detonateTime = getTime();
- self playsound("betty_activated");
- self maps\mp\_entityheadicons::setEntityHeadIcon("none");
- self shootup(level.bettyUpVelocity);
- fx = PlayFXOnTag(level.bettyFXid, self , "tag_flash");
- level.bettyTimeBeforeDetonate = weapons_get_dvar("bettyTimeBeforeDetonate", level.bettyTimeBeforeDetonate);
- self thread waitAndDetonate(level.bettyTimeBeforeDetonate);
- }
- deathDodger() {
- self endon("death");
- self endon("disconnect");
- wait (0.2 + level.bettyTimeBeforeDetonate);
- self notify("death_dodger");
- }
- deleteOnDeath(ent) {
- self waittill("death");
- wait.05;
- if (isdefined(ent)) ent delete();
- }
- watchSatchelAltDetonation() {
- self endon("death");
- self endon("disconnect");
- while (1) {
- self waittill("alt_detonate");
- weap = self getCurrentWeapon();
- if (weap != "satchel_charge_mp") {
- newarray = [];
- for (i = 0; i < self.satchelarray.size; i++) {
- satchel = self.satchelarray[i];
- if (isdefined(self.satchelarray[i])) satchel thread waitAndDetonate(0.1);
- }
- self.satchelarray = newarray;
- self notify("detonated");
- }
- }
- }
- watchSatchelAltDetonate() {
- self endon("death");
- self endon("disconnect");
- self endon("detonated");
- level endon("game_ended");
- buttonTime = 0;
- for (;;) {
- if (self UseButtonPressed()) {
- buttonTime = 0;
- while (self UseButtonPressed()) {
- buttonTime+= 0.05;
- wait (0.05);
- }
- println("pressTime1: " + buttonTime);
- if (buttonTime >= 0.5) continue;
- buttonTime = 0;
- while (!self UseButtonPressed() && buttonTime < 0.5) {
- buttonTime+= 0.05;
- wait (0.05);
- }
- println("delayTime: " + buttonTime);
- if (buttonTime >= 0.5) continue;
- if (!self.satchelarray.size) return;
- self notify("alt_detonate");
- }
- wait (0.05);
- }
- }
- watchSatchelDetonation() {
- self endon("death");
- self endon("disconnect");
- while (1) {
- self waittill("detonate");
- weap = self getCurrentWeapon();
- if (weap == "satchel_charge_mp") {
- for (i = 0; i < self.satchelarray.size; i++) {
- if (isdefined(self.satchelarray[i])) self.satchelarray[i] thread waitAndDetonate(0.1);
- }
- self.satchelarray = [];
- }
- }
- }
- waitAndDetonate(delay) {
- self endon("death");
- wait (delay);
- self detonate();
- }
- deleteSatchelAndbettysOnDisconnect() {
- self endon("death");
- self waittill("disconnect");
- bettyarray = self.bettyarray;
- satchelarray = self.satchelarray;
- wait.05;
- for (i = 0; i < bettyarray.size; i++) {
- if (isdefined(bettyarray[i])) bettyarray[i] delete();
- }
- for (i = 0; i < satchelarray.size; i++) {
- if (isdefined(satchelarray[i])) satchelarray[i] delete();
- }
- }
- deleteSatchelsAndbettysOnDisconnect() {
- self endon("death");
- self waittill("disconnect");
- satchelarray = self.satchelarray;
- bettyarray = self.bettyarray;
- wait.05;
- for (i = 0; i < satchelarray.size; i++) {
- if (isdefined(satchelarray[i])) satchelarray[i] delete();
- }
- for (i = 0; i < bettyarray.size; i++) {
- if (isdefined(bettyarray[i])) bettyarray[i] delete();
- }
- }
- bettyDamage() {
- self endon("death");
- self setcandamage(true);
- self.maxhealth = 100000;
- self.health = self.maxhealth;
- attacker = undefined;
- starttime = getTime();
- while (1) {
- self waittill("damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags);
- if (!isplayer (attacker)) continue;
- // don't allow people to destroy satchel on their team if FF is off
- if (!friendlyFireCheck(self.owner, attacker)) continue;
- if (damage < 5) // ignore concussion grenades
- continue;
- break;
- }
- if (level.bettyexplodethisframe) wait.1 + randomfloat(.4);
- else wait.05;
- if (!isdefined(self)) return;
- level.bettyexplodethisframe = true;
- thread resetBettyExplodeThisFrame();
- self maps\mp\_entityheadicons::setEntityHeadIcon("none");
- if (isDefined(type) && (isSubStr(type, "MOD_GRENADE") || isSubStr(type, "MOD_EXPLOSIVE"))) self.wasChained = true;
- if (isDefined(iDFlags) && (iDFlags & level.iDFLAGS_PENETRATION)) self.wasDamagedFromBulletPenetration = true;
- self.wasDamaged = true;
- // "destroyed_explosive" notify, for challenges
- if (isdefined(attacker) && isdefined(attacker.pers["team"]) && isdefined(self.owner) && isdefined(self.owner.pers["team"])) {
- if ((attacker.pers["team"] != self.owner.pers["team"]) || ((game["dialog"]["gametype"] == "freeforall") && (attacker != self.owner))) {
- attackernotify("destroyed_explosive");
- detonateTime = getTime();
- if (startTime + 3000 > detonateTime) {
- if (attacker != self.owner) self.wasJustPlanted = true;
- }
- }
- }
- self detonate(attacker);
- // won't get here; got death notify.
- }
- resetbettyExplodeThisFrame() {
- wait.05;
- level.bettyexplodethisframe = false;
- }
- satchelDamage() {
- self endon("death");
- self setcandamage(true);
- self.maxhealth = 100000;
- self.health = self.maxhealth;
- attacker = undefined;
- while (1) {
- self waittill("damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags);
- if (!isplayer (attacker)) continue;
- // don't allow people to destroy satchel on their team if FF is off
- if (!friendlyFireCheck(self.owner, attacker)) continue;
- if (damage < 5) // ignore concussion grenades
- continue;
- break;
- }
- if (level.satchelexplodethisframe) wait.1 + randomfloat(.4);
- else wait.05;
- if (!isdefined(self)) return;
- level.satchelexplodethisframe = true;
- thread resetSatchelExplodeThisFrame();
- self maps\mp\_entityheadicons::setEntityHeadIcon("none");
- if (isDefined(type) && (isSubStr(type, "MOD_GRENADE_SPLASH") || isSubStr(type, "MOD_GRENADE") || isSubStr(type, "MOD_EXPLOSIVE"))) self.wasChained = true;
- if (isDefined(iDFlags) && (iDFlags & level.iDFLAGS_PENETRATION)) self.wasDamagedFromBulletPenetration = true;
- self.wasDamaged = true;
- // "destroyed_explosive" notify, for challenges
- if (isdefined(attacker) && isdefined(attacker.pers["team"]) && isdefined(self.owner) && isdefined(self.owner.pers["team"])) {
- if (attacker.pers["team"] != self.owner.pers["team"]) attackernotify("destroyed_explosive");
- }
- self detonate(attacker);
- // won't get here; got death notify.
- }
- resetSatchelExplodeThisFrame() {
- wait.05;
- level.satchelexplodethisframe = false;
- }
- sayDamaged(orig, amount) {
- for (i = 0; i < 60; i++) {
- print3d(orig, "damaged! " + amount);
- wait.05;
- }
- }
- bombDetectionTrigger_wait(ownerTeam) {
- self endon("death");
- waitTillNotMoving();
- if (level.oldschool) return;
- self thread bombDetectionTrigger(ownerTeam);
- }
- bombDetectionTrigger(ownerTeam) {
- trigger = spawn("trigger_radius", self.origin - (0, 0, 128) , 0, 512, 256);
- trigger.detectId = "trigger" + getTime() + randomInt(1000000);
- trigger thread detectIconWaiter(level.otherTeam[ownerTeam]);
- self waittill("death");
- triggernotify("end_detection");
- if (isDefined(trigger.bombSquadIcon)) trigger.bombSquadIcon destroy();
- trigger delete();
- }
- detectIconWaiter(detectTeam) {
- self endon("end_detection");
- level endon("game_ended");
- while (!level.gameEnded) {
- self waittill("trigger", player);
- if (isai(player)) continue;
- if (!isdefined(player.detectExplosives) || !player.detectExplosives) continue;
- // CODER_MOD: Bryce (05/08/08): Don't check team in FFA
- if (player.team != detectTeam && game["dialog"]["gametype"] != "freeforall") continue;
- if (isDefined(player.bombSquadIds[self.detectId])) continue;
- player thread showHeadIcon(self);
- }
- }
- setupBombSquad() {
- self.bombSquadIds = [];
- if (self.detectExplosives && !self.bombSquadIcons.size) {
- for (i = 0; i < 4; i++) {
- self.bombSquadIcons[i] = newClientHudElem(self);
- self.bombSquadIcons[i].x = 0;
- self.bombSquadIcons[i].y = 0;
- self.bombSquadIcons[i].z = 0;
- self.bombSquadIcons[i].alpha = 0;
- self.bombSquadIcons[i].archived = true;
- self.bombSquadIcons[i]setShader("waypoint_bombsquad", 14, 14);
- self.bombSquadIcons[i]setWaypoint(false);
- self.bombSquadIcons[i].detectId = "";
- }
- }
- else
- if (!self.detectExplosives) {
- for (i = 0; i < self.bombSquadIcons.size; i++) self.bombSquadIcons[i] destroy();
- self.bombSquadIcons = [];
- }
- }
- showHeadIcon(trigger) {
- triggerDetectId = trigger.detectId;
- useId = - 1;
- for (i = 0; i < 4; i++) {
- detectId = self.bombSquadIcons[i].detectId;
- if (detectId == triggerDetectId) return;
- if (detectId == "") useId = i;
- }
- if (useId < 0) return;
- self.bombSquadIds[triggerDetectId] = true;
- self.bombSquadIcons[useId].x = trigger.origin[0];
- self.bombSquadIcons[useId].y = trigger.origin[1];
- self.bombSquadIcons[useId].z = trigger.origin[2] + 24 + 128;
- self.bombSquadIcons[useId]fadeOverTime(0.25);
- self.bombSquadIcons[useId].alpha = 1;
- self.bombSquadIcons[useId].detectId = trigger.detectId;
- while (isAlive(self) && isDefined(trigger) && self isTouching(trigger)) wait (0.05);
- if (!isDefined(self)) return;
- self.bombSquadIcons[useId].detectId = "";
- self.bombSquadIcons[useId]fadeOverTime(0.25);
- self.bombSquadIcons[useId].alpha = 0;
- self.bombSquadIds[triggerDetectId] = undefined;
- }
- // these functions are used with scripted weapons (like satchels, shoeboxs, artillery)
- // returns an array of objects representing damageable entities (including players) within a given sphere.
- // each object has the property damageCenter, which represents its center (the location from which it can be damaged).
- // each object also has the property entity, which contains the entity that it represents.
- // to damage it, call damageEnt() on it.
- getDamageableEnts(pos, radius, doLOS, startRadius) {
- ents = [];
- if (!isdefined(doLOS)) doLOS = false;
- if (!isdefined(startRadius)) startRadius = 0;
- // players
- players = level.players;
- for (i = 0; i < players.size; i++) {
- if (!isalive(players[i]) || players[i].sessionstate != "playing") continue;
- player pos = players[i].origin + (0, 0, 32);
- dist = distance(pos, player pos);
- if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, player pos, startRadius, undefined))) {
- newent = spawnstruct();
- newent.isplayer = true;
- newent.isADestructable = false;
- newent.entity = players[i];
- newent.damageCenter = player pos;
- ents[ents.size] = newent;
- }
- }
- // grenades
- grenades = getentarray("grenade", "classname");
- for (i = 0; i < grenades.size; i++) {
- entpos = grenades[i].origin;
- dist = distance(pos, entpos);
- if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, grenades[i]))) {
- newent = spawnstruct();
- newent.isplayer = false;
- newent.isADestructable = false;
- newent.entity = grenades[i];
- newent.damageCenter = entpos;
- ents[ents.size] = newent;
- }
- }
- destructibles = getentarray("destructible", "targetname");
- for (i = 0; i < destructibles.size; i++) {
- entpos = destructibles[i].origin;
- dist = distance(pos, entpos);
- if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, destructibles[i]))) {
- newent = spawnstruct();
- newent.isplayer = false;
- newent.isADestructable = false;
- newent.entity = destructibles[i];
- newent.damageCenter = entpos;
- ents[ents.size] = newent;
- }
- }
- destructables = getentarray("destructable", "targetname");
- for (i = 0; i < destructables.size; i++) {
- entpos = destructables[i].origin;
- dist = distance(pos, entpos);
- if (dist < radius && (!doLOS || weaponDamageTracePassed(pos, entpos, startRadius, destructables[i]))) {
- newent = spawnstruct();
- newent.isplayer = false;
- newent.isADestructable = true;
- newent.entity = destructables[i];
- newent.damageCenter = entpos;
- ents[ents.size] = newent;
- }
- }
- return ents;
- }
- weaponDamageTracePassed(from, to, startRadius, ignore) {
- midpos = undefined;
- diff = to - from;
- if (lengthsquared(diff) < startRadius * startRadius) midpos = to;
- dir = vectornormalize(diff);
- midpos = from + (dir[0] * startRadius, dir[1] * startRadius, dir[2] * startRadius);
- trace = bullettrace(midpos, to, false, ignore);
- if (getdvarint("scr_damage_debug") != 0) {
- if (trace["fraction"] == 1) {
- thread debugline(midpos, to, (1, 1, 1));
- }
- else {
- thread debugline(midpos, trace["position"], (1,.9,.8));
- thread debugline(trace["position"], to, (1,.4,.3));
- }
- }
- return (trace["fraction"] == 1);
- }
- // eInflictor = the entity that causes the damage (e.g. a shoebox)
- // eAttacker = the player that is attacking
- // iDamage = the amount of damage to do
- // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
- // sWeapon = string specifying the weapon used (e.g. "mine_shoebox_mp")
- // damagepos = the position damage is coming from
- // damagedir = the direction damage is moving in
- damageEnt(eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir) {
- if (self.isplayer) {
- self.damageOrigin = damagepos;
- self.entity thread [[level.callbackplayer Damage]](
- eInflictor, // eInflictor The entity that causes the damage.(e.g. a turret)
- eAttacker, // eAttacker The entity that is attacking.
- iDamage, // iDamage Integer specifying the amount of damage done
- 0, // iDFlags Integer specifying flags that are to be applied to the damage
- sMeansOfDeath, // sMeansOfDeath Integer specifying the method of death
- sWeapon, // sWeapon The weapon number of the weapon used to inflict the damage
- damagepos, // vPoint The point the damage is from?
- damagedir, // vDir The direction of the damage
- "none", // sHitLoc The location of the hit
- 0 // psOffsetTime The time offset for the damage
- );
- }
- else {
- // destructable walls and such can only be damaged in certain ways.
- if (self.isADestructable && (sWeapon == "artillery_mp" || sWeapon == "mine_bouncing_betty_mp")) return;
- self.entitynotify("damage", iDamage, eAttacker, (0, 0, 0) , (0, 0, 0) , "mod_explosive", "", "");
- }
- }
- debugLine(a, b, color) {
- for (i = 0; i < 30 * 20; i++) {
- line(a, b, color);
- wait.05;
- }
- }
- onWeaponDamage(eInflictor, sWeapon, meansOfDeath, damage) {
- self endon("death");
- self endon("disconnect");
- switch (sWeapon) {
- case "concussion_grenade_mp":
- // should match weapon settings in gdt
- radius = 512;
- scale = 1 - (distance(self.origin, eInflictor.origin) / radius);
- if (scale < 0) scale = 0;
- time = 2 + (4 * scale);
- wait (0.05);
- self.concussionEndTime = getTime() + (time * 1000);
- break;
- default:
- // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage.
- maps\mp\gametypes\_shellshock::shellshockOnDamage(meansOfDeath, damage);
- break;
- }
- }
- // weapon stowing logic ===================================================================
- // weapon class boolean helpers
- isPrimaryWeapon(weaponname) {
- return isdefined(level.primary_weapon_array[weaponname]);
- }
- isSideArm(weaponname) {
- return isdefined(level.side_arm_array[weaponname]);
- }
- isInventory(weaponname) {
- return isdefined(level.inventory_array[weaponname]);
- }
- isGrenade(weaponname) {
- return isdefined(level.grenade_array[weaponname]);
- }
- getWeaponClass_array(current) {
- if (isPrimaryWeapon(current)) return level.primary_weapon_array;
- else
- if (isSideArm(current)) return level.side_arm_array;
- else
- if (isGrenade(current)) return level.grenade_array;
- else return level.inventory_array;
- }
- // thread loop life = player 's life
- updateStowedWeapon() {
- self endon("spawned");
- self endon("killed_player ");
- self endon("disconnect");
- self.tag_stowed_back = undefined;
- self.tag_stowed_hip = undefined;
- team = self.pers["team"];
- class = self.pers["class"];
- while (true) {
- self waittill("weapon_change", newWeapon);
- // weapon array reset, might have swapped weapons off the ground
- self.weapon_array_primary = [];
- self.weapon_array_sidearm = [];
- self.weapon_array_grenade = [];
- self.weapon_array_inventory = [];
- // populate player 's weapon stock arrays
- weaponsList = self getWeaponsList();
- for (idx = 0; idx < weaponsList.size; idx++) {
- if (isPrimaryWeapon(weaponsList[idx])) self.weapon_array_primary[self.weapon_array_primary.size] = weaponsList[idx];
- else
- if (isSideArm(weaponsList[idx])) self.weapon_array_sidearm[self.weapon_array_sidearm.size] = weaponsList[idx];
- else
- if (isGrenade(weaponsList[idx])) self.weapon_array_grenade[self.weapon_array_grenade.size] = weaponsList[idx];
- else
- if (isInventory(weaponsList[idx])) self.weapon_array_inventory[self.weapon_array_inventory.size] = weaponsList[idx];
- }
- detach_all_weapons();
- stow_on_back();
- stow_on_hip();
- }
- }
- forceStowedWeaponUpdate() {
- detach_all_weapons();
- stow_on_back();
- stow_on_hip();
- }
- detachCarryObjectModel() {
- if (isDefined(self.carryObject) && isdefined(self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel())) {
- if (isDefined(self.tag_stowed_back)) {
- self detach(self.tag_stowed_back, "tag_stowed_back");
- self.tag_stowed_back = undefined;
- }
- }
- }
- detach_all_weapons() {
- if (isDefined(self.tag_stowed_back)) {
- self detach(self.tag_stowed_back, "tag_stowed_back");
- self.tag_stowed_back = undefined;
- }
- if (isDefined(self.tag_stowed_hip)) {
- detach_model = getWeaponModel(self.tag_stowed_hip);
- self detach(detach_model, "tag_stowed_hip_rear");
- self.tag_stowed_hip = undefined;
- }
- }
- stow_on_back() {
- current = self getCurrentWeapon();
- self.tag_stowed_back = undefined;
- // carry objects take priority
- if (isDefined(self.carryObject) && isdefined(self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel())) {
- self.tag_stowed_back = self.carryObject maps\mp\gametypes\_gameobjects::getVisibleCarrierModel();
- }
- else
- if (self hasWeapon("m2_flamethrower_mp")) {
- // no back stowing if you have flamethrower tanks
- return;
- }
- // large projectile weaponry always show
- else
- if (self hasWeapon("bazooka_mp") && current != "bazooka_mp") {
- self.tag_stowed_back = "weapon_mp_bazooka_attach";
- }
- else {
- for (idx = 0; idx < self.weapon_array_primary.size; idx++) {
- index_weapon = self.weapon_array_primary[idx];
- assertex(isdefined(index_weapon) , "Primary weapon list corrupted.");
- if (index_weapon == current) continue;
- if (isSubStr(current, "gl_") || isSubStr(index_weapon, "gl_")) {
- index_weapon_tok = strtok(index_weapon, "_");
- current_tok = strtok(current, "_");
- // finding the alt-mode of current weapon; the tokens of both weapons are subsets of each other
- for (i = 0; i < index_weapon_tok.size; i++) {
- if (!isSubStr(current, index_weapon_tok[i]) || index_weapon_tok.size != current_tok.size) {
- i = 0;
- break;
- }
- }
- if (i == index_weapon_tok.size) continue;
- }
- // camo only applicable for custom classes
- assertex(isdefined(self.curclass) , "player missing current class");
- 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"]);
- else self.tag_stowed_back = getWeaponModel(index_weapon, 0);
- }
- }
- if (!isDefined(self.tag_stowed_back)) return;
- self attach(self.tag_stowed_back, "tag_stowed_back", true);
- }
- stow_on_hip() {
- current = self getCurrentWeapon();
- self.tag_stowed_hip = undefined;
- for (idx = 0; idx < self.weapon_array_inventory.size; idx++) {
- if (self.weapon_array_inventory[idx] == current) continue;
- if (!self GetWeaponAmmoStock(self.weapon_array_inventory[idx])) continue;
- self.tag_stowed_hip = self.weapon_array_inventory[idx];
- }
- if (!isDefined(self.tag_stowed_hip)) return;
- // getting rid of these until we get attach models
- if (self.tag_stowed_hip == "satchel_charge_mp" || self.tag_stowed_hip == "mine_bouncing_betty_mp") {
- self.tag_stowed_hip = undefined;
- return;
- }
- weapon_model = getWeaponModel(self.tag_stowed_hip);
- self attach(weapon_model, "tag_stowed_hip_rear", true);
- }
- stow_inventory(inventories, current) {
- // deatch last weapon attached
- if (isdefined(self.inventory_tag)) {
- detach_model = getweaponmodel(self.inventory_tag);
- self detach(detach_model, "tag_stowed_hip_rear");
- self.inventory_tag = undefined;
- }
- if (!isdefined(inventories[0]) || self GetWeaponAmmoStock(inventories[0]) == 0) return;
- if (inventories[0] != current) {
- self.inventory_tag = inventories[0];
- weapon_model = getweaponmodel(self.inventory_tag);
- self attach(weapon_model, "tag_stowed_hip_rear", true);
- }
- }
- // returns dvar value in int
- weapons_get_dvar_int(dvar, def) {
- return int(weapons_get_dvar(dvar, def));
- }
- // dvar set/fetch/check
- weapons_get_dvar(dvar, def) {
- if (getdvar(dvar) != "") {
- return getdvarfloat(dvar);
- }
- else {
- setdvar(dvar, def);
- return def;
- }
- }
- player_is_driver() {
- if (!isalive(self)) return false;
- vehicle = self getVehicleOccupied();
- if (IsDefined(vehicle)) {
- seat = vehicle GetOccupantSeat(self);
- if (isdefined(seat) && seat == 0) return true;
- }
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement