home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-30 | 53.5 KB | 2,007 lines |
- /*
- TeamFortress 1.1 - 27/8/96
-
- Robin Walker, John Cook, Ian Caughley.
-
- Functions specific to the TeamFortress QuakeC patch.
- */
-
- // Function Prototypes
- void() GrenadeExplode;
- void() spike_touch;
-
- // Help Functions
- void() TeamFortress_MOTD;
- void() TeamFortress_HelpIndex;
- void() TeamFortress_HelpWeapon;
- void() TeamFortress_HelpClass;
- void() TeamFortress_HelpItem;
- void() TeamFortress_HelpGeneral;
- void() TeamFortress_HelpPreImp;
- void() TeamFortress_HelpShowPreImp;
-
- // Multiskin Functions
- void(float skinno) Multiskin_SetSkin;
-
- // Team Functions
- float(float tno) TeamFortress_TeamGetColor;
- void(float tno) TeamFortress_TeamSetColor;
-
- // Impulse Functions
- void() TeamFortress_ChangeClass;
- void() TeamFortress_Inventory;
- void() TeamFortress_PrimeGrenade;
- void() TeamFortress_ThrowGrenade;
- void() TeamFortress_DetonatePipebombs;
- // Pre-Impulse Functions
- void(float tflag) TeamFortress_Toggle;
- void(float scanrange) TeamFortress_Scan;
- void(float timer) TeamFortress_SetDetpack;
- void(float skinno) TeamFortress_Multiskin;
-
- // Player Class Handling Functions
- void() TeamFortress_SetHealth;
- void() TeamFortress_SetEquipment;
- void() TeamFortress_SetSpeed;
- void() TeamFortress_SetSkin;
- float(entity Retriever, float AmmoType) TeamFortress_GetMaxAmmo;
- float(entity Retriever, float WeaponType) TeamFortress_CanGetWeapon;
- float(entity Retriever, entity Armor) TeamFortress_CanGetArmor;
- float(entity Retriever, entity Items) TeamFortress_AddBackpackItems;
-
- // Weapon Handling Functions
- void() TeamFortress_SniperWeapon;
- void() TeamFortress_ExplodePerson;
- void() NormalGrenadeTouch;
- void() NormalGrenadeExplode;
- void() ConcussionGrenadeTouch;
- void() ConcussionGrenadeExplode;
- void() ConcussionGrenadeTimer;
- void() NailGrenadeTouch;
- void() NailGrenadeExplode;
- void() NailGrenadeNailEm;
- void() NailGrenadeLaunchNail;
- void() MirvGrenadeTouch;
- void() MirvGrenadeExplode;
- void(vector org, entity shooter) MirvGrenadeLaunch;
- void() PipebombTouch;
-
- // Item Handling Functions
- void() TeamFortress_DetpackSet;
- void() TeamFortress_DetpackExplode;
- void() TeamFortress_DetpackTouch;
- void() TeamFortress_DetpackCountDown;
-
- // Utility Functions
- void(entity inflictor, entity attacker, float bounce, entity ignore) T_RadiusBounce;
- entity(entity scanner, float scanrange, float enemies, float friends) T_RadiusScan;
- void(string halias, float himpulse1, float himpulse2) TeamFortress_Alias;
-
- // Cyclic Event Functions
- void() TeamFortress_Regenerate;
- void() TeamFortress_CheckforCheats;
-
- //=========================================================================
- // IMPULSE FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Impulse function which Toggles Game Settings
- void(float tflag) TeamFortress_Toggle =
- {
- local entity e,bak;
-
- // prevent help pre-impulse from triggering anything else
- self.impulse = 0;
- self.last_impulse = 0;
-
- // Classkin/Multiskin
- if (tflag == TF_TOGGLE_SKIN)
- {
- if (toggleflags & TFLAG_SKIN)
- {
- bprint("Classkin On.\n");
- toggleflags = toggleflags - (toggleflags & TFLAG_SKIN);
-
- bak = self;
- // Change everyone's skins to their class
- e = find(world, classname, "player");
- while (e)
- {
- self = e;
- TeamFortress_SetSkin();
-
- e = find(e, classname, "player");
- }
- self = bak;
- }
- else
- {
- bprint("Multiskin On.\n");
- toggleflags = (toggleflags | TFLAG_SKIN);
- }
-
- return;
- }
-
- // Class Persistence between lvls On/Off
- if (tflag == TF_TOGGLE_CLASS_PERSIST)
- {
- if (toggleflags & TFLAG_CLASS_PERSIST)
- {
- bprint("Class Persistence Off.\n");
- toggleflags = toggleflags - (toggleflags & TFLAG_CLASS_PERSIST);
- }
- else
- {
- bprint("Class Persistence On.\n");
- toggleflags = (toggleflags | TFLAG_CLASS_PERSIST);
- }
-
- return;
- }
-
- // Cheat Checking On/Off
- if (tflag == TF_TOGGLE_CHEATCHECK)
- {
- if (toggleflags & TFLAG_CHEATCHECK)
- {
- bprint("Cheat Checking Off.\n");
- toggleflags = toggleflags - (toggleflags & TFLAG_CHEATCHECK);
-
- // Remove everyone's cheattimers
- e = find(world, classname, "player");
- while (e)
- {
- if (e.cheattimer)
- remove(e.cheattimer);
-
- e = find(e, classname, "player");
- }
- }
- else
- {
- bprint("Cheat Checking On.\n");
- toggleflags = (toggleflags | TFLAG_CHEATCHECK);
- // Create everyone's cheattimers
- e = find(world, classname, "player");
- while (e)
- {
- if (!(e.cheattimer))
- {
- e.cheattimer = spawn();
- e.cheattimer.nextthink = time + 20;
- e.cheattimer.think = TeamFortress_CheckforCheats;
- e.cheattimer.owner = e;
- }
-
- e = find(e, classname, "player");
- }
- }
-
- return;
- }
-
- // FortressMap details On/Off (see readme.txt for more info)
- if (tflag == TF_TOGGLE_FORTRESSMAP)
- {
- if (toggleflags & TFLAG_FORTRESSMAP)
- {
- bprint("FortressMap Off.\n");
- toggleflags = toggleflags - (toggleflags & TFLAG_FORTRESSMAP);
- }
- else
- {
- bprint("FortressMap On.\n");
- toggleflags = (toggleflags | TFLAG_FORTRESSMAP);
- }
-
- return;
- }
-
- };
-
- //=========================================================================
- // Handles the Multiskin Pre-Impulse to Set Skin
- void(float skinno) TeamFortress_Multiskin =
- {
- // prevent help pre-impulse from triggering anything else
- self.impulse = 0;
- self.last_impulse = 0;
-
- Multiskin_SetSkin(skinno);
- };
-
- //=========================================================================
- // Player change class function
- void() TeamFortress_ChangeClass =
- {
- cvar_set("sv_maxspeed", "600");
- // Only change playerclass once - remove this if you want to change on the fly
- // if ( self.playerclass != PC_UNDEFINED )
- // return;
-
- self.playerclass = self.impulse - TF_CHANGEPC;
-
- // Turn off PC_UNDEFINED's nomove and invincibility
- self.takedamage = 1;
- self.movetype = MOVETYPE_WALK;
-
- self.teamno = 0;
-
- // Display chosen class, and Tell rest of the team in the future
- if ( self.playerclass == PC_SCOUT )
- {
- sprint(self, "SCOUT.\n");
- }
- else if ( self.playerclass == PC_SNIPER )
- {
- sprint(self, "SNIPER.\n");
- }
- else if ( self.playerclass == PC_SOLDIER )
- {
- sprint(self, "SOLDIER.\n");
- }
- else if ( self.playerclass == PC_DEMOMAN )
- {
- sprint(self, "DEMOLITIONS MAN.\n");
- }
- else if ( self.playerclass == PC_MEDIC )
- {
- sprint(self, "COMBAT MEDIC.\n");
- }
- else if ( self.playerclass == PC_HVYWEAP )
- {
- sprint(self, "HEAVY WEAPONS GUY.\n");
- }
-
- TeamFortress_SetEquipment();
- TeamFortress_SetHealth();
- TeamFortress_SetSpeed();
- TeamFortress_SetSkin();
- };
-
- //=========================================================================
- // Displays the player's inventory
- void() TeamFortress_Inventory =
- {
- local string ac;
- local float col;
-
- // Display Team
- sprint(self, "You're in team ");
- ac = ftos(self.teamno);
- sprint(self, ac);
- sprint(self, ", color ");
- col = TeamFortress_TeamGetColor(self.teamno);
- ac = ftos(col);
- sprint(self, ac);
- sprint(self, ".\n");
-
- // Display Number of Grenades of each type
- if (self.no_grenades_1 > 0)
- {
- ac = ftos(self.no_grenades_1);
- sprint(self, ac);
- if (self.tp_grenades_1 == GR_TYPE_CONCUSSION)
- sprint(self, " concussion");
- if (self.tp_grenades_1 == GR_TYPE_NAIL)
- sprint(self, " nail");
- if (self.tp_grenades_1 == GR_TYPE_MIRV)
- sprint(self, " Mirv");
-
- sprint(self, " grenades. ");
- }
- if (self.no_grenades_2 > 0)
- {
- ac = ftos(self.no_grenades_2);
- sprint(self, ac);
- if (self.tp_grenades_2 == GR_TYPE_CONCUSSION)
- sprint(self, " concussion");
- if (self.tp_grenades_2 == GR_TYPE_NAIL)
- sprint(self, " nail");
- if (self.tp_grenades_2 == GR_TYPE_MIRV)
- sprint(self, " Mirv");
-
- sprint(self, " grenades. ");
- }
-
- if (self.tf_items & NIT_SCANNER)
- sprint(self, "Scanner. ");
-
- if (self.secondary_items & NIT_MEDIKIT)
- {
- sprint(self, "Medikit (");
- ac = ftos(self.ammo_medikit);
- sprint(self, ac);
- sprint(self,") ");
- }
-
- if (self.secondary_items & NIT_DETPACK)
- {
- if (self.ammo_detpack > 0)
- {
- ac = ftos(self.ammo_detpack);
- sprint(self, ac);
- sprint(self, " Detpack");
- if (self.ammo_detpack > 1)
- sprint(self, "s");
- sprint(self, ".");
- }
- }
-
- sprint(self, "\n");
- };
-
- //=========================================================================
- // Primes a grenade of the type corresponding to the player's impulse
- void() TeamFortress_PrimeGrenade =
- {
- local float gtype;
- local string gs, ptime;
-
- // If you've already primed a grenade, return
- if (self.grenadeprimed)
- return;
-
- if (self.impulse == TF_GRENADE_1)
- {
- gtype = self.tp_grenades_1;
- if (self.tp_grenades_1 == GR_TYPE_CONCUSSION)
- gs = "Concussion grenade";
- else if (self.tp_grenades_1 == GR_TYPE_NAIL)
- gs = "Nail grenade";
- else if (self.tp_grenades_1 == GR_TYPE_MIRV)
- gs = "Mirv grenade";
- else
- gs = "Grenade";
-
- if (self.no_grenades_1 > 0)
- {
- ptime = ftos( GR_PRIMETIME );
- sprint(self, gs);
- sprint(self, " primed, ");
- sprint(self, ptime);
- sprint(self, " seconds...\n");
- self.no_grenades_1 = self.no_grenades_1 - 1;
- }
- else
- {
- sprint(self, "No ");
- sprint(self, gs);
- sprint(self, "s left.\n");
- return;
- }
- }
- if (self.impulse == TF_GRENADE_2)
- {
- gtype = self.tp_grenades_2;
- if (self.tp_grenades_2 == GR_TYPE_CONCUSSION)
- gs = "Concussion grenade";
- else if (self.tp_grenades_2 == GR_TYPE_NAIL)
- gs = "Nail grenade";
- else if (self.tp_grenades_2 == GR_TYPE_MIRV)
- gs = "Mirv grenade";
- else
- gs = "Grenade";
-
- if (self.no_grenades_2 > 0)
- {
- ptime = ftos( GR_PRIMETIME );
- sprint(self, gs);
- sprint(self, " primed, ");
- sprint(self, ptime);
- sprint(self, " seconds...\n");
- self.no_grenades_2 = self.no_grenades_2 - 1;
- }
- else
- {
- sprint(self, "No ");
- sprint(self, gs);
- sprint(self, "s left.\n");
- return;
- }
- }
-
- self.grenadeprimed = 1;
- self.Grenade = spawn();
- self.Grenade.owner = self;
- self.Grenade.weapon = gtype;
- self.Grenade.nextthink = time + GR_PRIMETIME;
- self.Grenade.think = TeamFortress_ExplodePerson;
- };
-
- //=========================================================================
- // Throws a currently primed grenade
- void() TeamFortress_ThrowGrenade =
- {
- local entity missile;
-
- // If no grenade is primed, return
- if (self.grenadeprimed == 0)
- return;
-
- self.grenadeprimed = 0;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
-
- // set grenade speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- // set the grenade's alternative kill flag
- missile.altkill = 1;
-
- // set the grenade's thinktime to when the PRIMETIME runs out
- missile.nextthink = self.Grenade.nextthink;
-
- // set the think and touches to the appropriate grenade type
- if (self.Grenade.weapon == GR_TYPE_NORMAL)
- {
- missile.touch = NormalGrenadeTouch;
- missile.think = NormalGrenadeExplode;
- missile.altkillweapon = AK_GRENADE;
- }
- if (self.Grenade.weapon == GR_TYPE_CONCUSSION)
- {
- missile.touch = ConcussionGrenadeTouch;
- missile.think = ConcussionGrenadeExplode;
- }
- if (self.Grenade.weapon == GR_TYPE_NAIL)
- {
- missile.touch = NailGrenadeTouch;
- missile.think = NailGrenadeExplode;
- missile.altkillweapon = AK_GRENADE_NAIL;
- }
- if (self.Grenade.weapon == GR_TYPE_MIRV)
- {
- missile.touch = MirvGrenadeTouch;
- missile.think = MirvGrenadeExplode;
- missile.altkillweapon = AK_GRENADE_MIRV;
- }
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
-
- // Remove primed grenade object
- remove(self.Grenade);
- };
-
- //=========================================================================
- // PLAYER CLASS HANDLING FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Alter the player's Movement based on class
- void() TeamFortress_SetSpeed =
- {
- local string sp;
- local float tf;
-
- stuffcmd(self,"v_idlescale 0\n");
- stuffcmd(self,"cl_movespeedkey 1\n");
-
- if ( self.playerclass == PC_SCOUT )
- {
- self.maxfbspeed = PC_SCOUT_MAXSPEED;
- self.maxstrafespeed = PC_SCOUT_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_SNIPER )
- {
- self.maxfbspeed = PC_SNIPER_MAXSPEED;
- self.maxstrafespeed = PC_SNIPER_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_SOLDIER )
- {
- self.maxfbspeed = PC_SOLDIER_MAXSPEED;
- self.maxstrafespeed = PC_SOLDIER_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_DEMOMAN )
- {
- self.maxfbspeed = PC_DEMOMAN_MAXSPEED;
- self.maxstrafespeed = PC_DEMOMAN_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_MEDIC )
- {
- self.maxfbspeed = PC_MEDIC_MAXSPEED;
- self.maxstrafespeed = PC_MEDIC_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_HVYWEAP )
- {
- self.maxfbspeed = PC_HVYWEAP_MAXSPEED;
- self.maxstrafespeed = PC_HVYWEAP_MAXSTRAFESPEED;
- }
- else if ( self.playerclass == PC_UNDEFINED )
- {
- self.maxfbspeed = 50;
- self.maxstrafespeed = 50;
- self.movetype = MOVETYPE_NONE;
- }
-
- sp = ftos(self.maxfbspeed);
- stuffcmd(self,"cl_backspeed ");
- stuffcmd(self,sp);
- stuffcmd(self,"\n");
- stuffcmd(self,"cl_forwardspeed ");
- stuffcmd(self,sp);
- stuffcmd(self,"\n");
- sp = ftos(self.maxstrafespeed);
- stuffcmd(self,"cl_sidespeed ");
- stuffcmd(self,sp);
- stuffcmd(self,"\n");
- };
-
- //=========================================================================
- // Set the max_health of a player based on his/her class
- void() TeamFortress_SetHealth =
- {
- if ( self.playerclass == PC_SCOUT )
- self.max_health = PC_SCOUT_MAXHEALTH;
- else if ( self.playerclass == PC_SNIPER )
- self.max_health = PC_SNIPER_MAXHEALTH;
- else if ( self.playerclass == PC_SOLDIER )
- self.max_health = PC_SOLDIER_MAXHEALTH;
- else if ( self.playerclass == PC_DEMOMAN )
- self.max_health = PC_DEMOMAN_MAXHEALTH;
- else if ( self.playerclass == PC_MEDIC )
- self.max_health = PC_MEDIC_MAXHEALTH;
- else if ( self.playerclass == PC_HVYWEAP )
- self.max_health = PC_HVYWEAP_MAXHEALTH;
- else if ( self.playerclass == PC_UNDEFINED )
- {
- self.max_health = 1;
- self.takedamage = 0; // Prevent damage to PC_UNDEFINED players
- }
-
- self.health = self.max_health;
- };
-
- //=========================================================================
- // Set the skin of a player based on his/her class, if Classkin is on
- void() TeamFortress_SetSkin =
- {
- local string st;
-
- // If Multiskin is on, return
- if (toggleflags & TFLAG_SKIN)
- return;
-
- if ( self.playerclass == PC_SCOUT )
- self.skin = PC_SCOUT_SKIN;
- else if ( self.playerclass == PC_SNIPER )
- self.skin = PC_SNIPER_SKIN;
- else if ( self.playerclass == PC_SOLDIER )
- self.skin = PC_SOLDIER_SKIN;
- else if ( self.playerclass == PC_DEMOMAN )
- self.skin = PC_DEMOMAN_SKIN;
- else if ( self.playerclass == PC_MEDIC )
- self.skin = PC_MEDIC_SKIN;
- else if ( self.playerclass == PC_HVYWEAP )
- self.skin = PC_HVYWEAP_SKIN;
- else if ( self.playerclass == PC_UNDEFINED )
- self.skin = 1;
-
- };
-
- //=========================================================================
- // Set the details of a player based on his/her class
- void() TeamFortress_SetEquipment =
- {
- if (self.classname != "player")
- return;
-
- self.items = 0;
- self.secondary_weapon = 0;
- self.secondary_items = 0;
- self.tf_items = 0;
- self.tf_items_flags = 0;
- self.armorclass = 0;
- self.grenadeprimed = 0;
- self.impulse = 0;
-
- self.ammo_medikit = 0;
- self.maxammo_medikit = 0;
- self.ammo_detpack = 0;
- self.maxammo_detpack = 0;
- self.items_allowed = 0;
- self.secondary_items_allowed = 0;
- self.armor_allowed = 0;
- self.maxarmor = 0;
- self.weaponmode = 0;
- self.altkill = 0;
- self.altkillweapon = 0;
- self.heat = 0;
-
- self.is_concussed = FALSE;
-
- // Start the Cheat-Checking Cyclic Event if CheatChecking Toggleflag is on
- if (toggleflags & TFLAG_CHEATCHECK)
- {
- self.cheattimer = spawn();
- self.cheattimer.nextthink = time + 20;
- self.cheattimer.think = TeamFortress_CheckforCheats;
- self.cheattimer.owner = self;
- }
-
- if ( self.playerclass == PC_SCOUT )
- {
- self.items = self.items | PC_SCOUT_WEAPONS;
- self.ammo_rockets = PC_SCOUT_INITAMMO_ROCKET;
- self.ammo_nails = PC_SCOUT_INITAMMO_NAIL;
- self.ammo_shells = PC_SCOUT_INITAMMO_SHOT;
- self.ammo_cells = PC_SCOUT_INITAMMO_CELL;
- self.maxammo_rockets = PC_SCOUT_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_SCOUT_MAXAMMO_NAIL;
- self.maxammo_shells = PC_SCOUT_MAXAMMO_SHOT;
- self.maxammo_cells = PC_SCOUT_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_SCOUT_GRENADE_INIT_1;
- self.no_grenades_2 = PC_SCOUT_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_SCOUT_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_SCOUT_GRENADE_TYPE_2;
- self.tf_items = PC_SCOUT_TF_ITEMS;
-
- // the scanner defaults to enemy scanning ON, friendly scanning OFF
- // and movement scanner only OFF
- self.tf_items_flags = self.tf_items_flags | NIT_SCANNER_ENEMY;
-
- self.armorclass = self.armorclass | PC_SCOUT_INITARMORCLASS;
- self.armortype = PC_SCOUT_INITARMORTYPE;
- self.armorvalue = PC_SCOUT_INITARMOR;
- self.armor_allowed = PC_SCOUT_MAXARMORTYPE;
- self.maxarmor = PC_SCOUT_MAXARMOR;
- self.weapon = IT_NAILGUN;
-
- self.items_allowed = PC_SCOUT_WEAPONS;
- }
- else if ( self.playerclass == PC_SNIPER )
- {
- self.items = self.items | PC_SNIPER_WEAPONS;
- self.ammo_rockets = PC_SNIPER_INITAMMO_ROCKET;
- self.ammo_nails = PC_SNIPER_INITAMMO_NAIL;
- self.ammo_shells = PC_SNIPER_INITAMMO_SHOT;
- self.ammo_cells = PC_SNIPER_INITAMMO_CELL;
- self.maxammo_rockets = PC_SNIPER_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_SNIPER_MAXAMMO_NAIL;
- self.maxammo_shells = PC_SNIPER_MAXAMMO_SHOT;
- self.maxammo_cells = PC_SNIPER_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_SNIPER_GRENADE_INIT_1;
- self.no_grenades_2 = PC_SNIPER_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_SNIPER_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_SNIPER_GRENADE_TYPE_2;
- self.tf_items = PC_SNIPER_TF_ITEMS;
-
- // Get the sniper's weapon
- self.secondary_items = self.secondary_items | NIT_SNIPER_RIFLE | NIT_AUTO_RIFLE;
-
- self.armorclass = self.armorclass | PC_SNIPER_INITARMORCLASS;
- self.armortype = PC_SNIPER_INITARMORTYPE;
- self.armorvalue = PC_SNIPER_INITARMOR;
- self.armor_allowed = PC_SNIPER_MAXARMORTYPE;
- self.maxarmor = PC_SNIPER_MAXARMOR;
- self.weapon = IT_EXTRA_WEAPON;
- self.secondary_weapon = NIT_SNIPER_RIFLE;
-
- self.items_allowed = PC_SNIPER_WEAPONS;
- }
- else if ( self.playerclass == PC_SOLDIER )
- {
- self.items = self.items | PC_SOLDIER_WEAPONS;
- self.ammo_rockets = PC_SOLDIER_INITAMMO_ROCKET;
- self.ammo_nails = PC_SOLDIER_INITAMMO_NAIL;
- self.ammo_shells = PC_SOLDIER_INITAMMO_SHOT;
- self.ammo_cells = PC_SOLDIER_INITAMMO_CELL;
- self.maxammo_rockets = PC_SOLDIER_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_SOLDIER_MAXAMMO_NAIL;
- self.maxammo_shells = PC_SOLDIER_MAXAMMO_SHOT;
- self.maxammo_cells = PC_SOLDIER_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_SOLDIER_GRENADE_INIT_1;
- self.no_grenades_2 = PC_SOLDIER_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_SOLDIER_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_SOLDIER_GRENADE_TYPE_2;
- self.tf_items = PC_SOLDIER_TF_ITEMS;
-
- self.armorclass = self.armorclass | PC_SOLDIER_INITARMORCLASS;
- self.armortype = PC_SOLDIER_INITARMORTYPE;
- self.armorvalue = PC_SOLDIER_INITARMOR;
- self.armor_allowed = PC_SOLDIER_MAXARMORTYPE;
- self.maxarmor = PC_SOLDIER_MAXARMOR;
- self.weapon = IT_ROCKET_LAUNCHER;
-
- self.items_allowed = PC_SOLDIER_WEAPONS;
- }
- else if ( self.playerclass == PC_DEMOMAN )
- {
- self.items = self.items | PC_DEMOMAN_WEAPONS;
- self.ammo_rockets = PC_DEMOMAN_INITAMMO_ROCKET;
- self.ammo_nails = PC_DEMOMAN_INITAMMO_NAIL;
- self.ammo_shells = PC_DEMOMAN_INITAMMO_SHOT;
- self.ammo_cells = PC_DEMOMAN_INITAMMO_CELL;
- self.maxammo_rockets = PC_DEMOMAN_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_DEMOMAN_MAXAMMO_NAIL;
- self.maxammo_shells = PC_DEMOMAN_MAXAMMO_SHOT;
- self.maxammo_cells = PC_DEMOMAN_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_DEMOMAN_GRENADE_INIT_1;
- self.no_grenades_2 = PC_DEMOMAN_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_DEMOMAN_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_DEMOMAN_GRENADE_TYPE_2;
- self.tf_items = PC_DEMOMAN_TF_ITEMS;
-
- // Detpacks
- self.secondary_items = self.secondary_items | NIT_DETPACK;
- self.ammo_detpack = PC_DEMOMAN_INITAMMO_DETPACK;
- self.maxammo_detpack = PC_DEMOMAN_MAXAMMO_DETPACK;
-
- self.armorclass = self.armorclass | PC_DEMOMAN_INITARMORCLASS;
- self.armortype = PC_DEMOMAN_INITARMORTYPE;
- self.armorvalue = PC_DEMOMAN_INITARMOR;
- self.armor_allowed = PC_DEMOMAN_MAXARMORTYPE;
- self.maxarmor = PC_DEMOMAN_MAXARMOR;
- self.weapon = IT_GRENADE_LAUNCHER;
-
- self.items_allowed = PC_DEMOMAN_WEAPONS;
- }
- else if ( self.playerclass == PC_MEDIC )
- {
- self.items = self.items | PC_MEDIC_WEAPONS;
- self.ammo_rockets = PC_MEDIC_INITAMMO_ROCKET;
- self.ammo_nails = PC_MEDIC_INITAMMO_NAIL;
- self.ammo_shells = PC_MEDIC_INITAMMO_SHOT;
- self.ammo_cells = PC_MEDIC_INITAMMO_CELL;
- self.maxammo_rockets = PC_MEDIC_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_MEDIC_MAXAMMO_NAIL;
- self.maxammo_shells = PC_MEDIC_MAXAMMO_SHOT;
- self.maxammo_cells = PC_MEDIC_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_MEDIC_GRENADE_INIT_1;
- self.no_grenades_2 = PC_MEDIC_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_MEDIC_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_MEDIC_GRENADE_TYPE_2;
- self.tf_items = PC_MEDIC_TF_ITEMS;
-
- self.armorclass = self.armorclass | PC_MEDIC_INITARMORCLASS;
- self.armortype = PC_MEDIC_INITARMORTYPE;
- self.armorvalue = PC_MEDIC_INITARMOR;
- self.armor_allowed = PC_MEDIC_MAXARMORTYPE;
- self.maxarmor = PC_MEDIC_MAXARMOR;
- self.weapon = IT_SUPER_NAILGUN;
-
- // Medikit
- self.secondary_items = self.secondary_items | NIT_MEDIKIT;
- self.ammo_medikit = PC_MEDIC_INITAMMO_MEDIKIT;
- self.maxammo_medikit = PC_MEDIC_MAXAMMO_MEDIKIT;
-
- // Start the Regeneration Cyclic Event
- self.cyclictimer = spawn();
- self.cyclictimer.nextthink = time + PC_MEDIC_REGEN_TIME;
- self.cyclictimer.think = TeamFortress_Regenerate;
- self.cyclictimer.owner = self;
-
- self.items_allowed = PC_MEDIC_WEAPONS;
- }
- else if ( self.playerclass == PC_HVYWEAP )
- {
- self.items = self.items | PC_HVYWEAP_WEAPONS;
- self.ammo_rockets = PC_HVYWEAP_INITAMMO_ROCKET;
- self.ammo_nails = PC_HVYWEAP_INITAMMO_NAIL;
- self.ammo_shells = PC_HVYWEAP_INITAMMO_SHOT;
- self.ammo_cells = PC_HVYWEAP_INITAMMO_CELL;
- self.maxammo_rockets = PC_HVYWEAP_MAXAMMO_ROCKET;
- self.maxammo_nails = PC_HVYWEAP_MAXAMMO_NAIL;
- self.maxammo_shells = PC_HVYWEAP_MAXAMMO_SHOT;
- self.maxammo_cells = PC_HVYWEAP_MAXAMMO_CELL;
-
- self.no_grenades_1 = PC_HVYWEAP_GRENADE_INIT_1;
- self.no_grenades_2 = PC_HVYWEAP_GRENADE_INIT_2;
- self.tp_grenades_1 = PC_HVYWEAP_GRENADE_TYPE_1;
- self.tp_grenades_2 = PC_HVYWEAP_GRENADE_TYPE_2;
- self.tf_items = PC_HVYWEAP_TF_ITEMS;
-
- // Get the Assault Cannon
- self.secondary_items = self.secondary_items | NIT_ASSAULT_CANNON;
-
- self.armorclass = self.armorclass | PC_HVYWEAP_INITARMORCLASS;
- self.armortype = PC_HVYWEAP_INITARMORTYPE;
- self.armorvalue = PC_HVYWEAP_INITARMOR;
- self.armor_allowed = PC_HVYWEAP_MAXARMORTYPE;
- self.maxarmor = PC_HVYWEAP_MAXARMOR;
- self.weapon = IT_NAILGUN;
-
- self.items_allowed = PC_HVYWEAP_WEAPONS;
- }
- else if ( self.playerclass == PC_UNDEFINED )
- {
- self.items = self.items | IT_AXE;
- self.ammo_rockets = 0;
- self.ammo_nails = 0;
- self.ammo_shells = 0;
- self.ammo_cells = 0;
-
- self.no_grenades_1 = 0;
- self.no_grenades_2 = 0;
- self.tp_grenades_1 = 0;
- self.tp_grenades_2 = 0;
-
- self.armorclass = 0;
- self.armortype = 0;
- self.armorvalue = 0;
- self.weapon = IT_AXE;
- }
-
- W_SetCurrentAmmo ();
- };
-
- //=========================================================================
- // Return the max amount of ammo the Retriever can carry, based on his class
- float(entity Retriever, float AmmoType) TeamFortress_GetMaxAmmo =
- {
- if (AmmoType == IT_SHELLS)
- {
- return Retriever.maxammo_shells;
- }
- else if (AmmoType == IT_NAILS)
- {
- return Retriever.maxammo_nails;
- }
- else if (AmmoType == IT_CELLS)
- {
- return Retriever.maxammo_cells;
- }
- else if (AmmoType == IT_ROCKETS)
- {
- return Retriever.maxammo_rockets;
- }
-
- dprint("Error in TeamFortress_GetMaxAmmo()\n");
- dprint("Invalid ammo type passed.\n");
- return 0;
- };
-
- //=========================================================================
- // Return 1 if the Retriever is allowed to pick up the Weapon
- float(entity Retriever, float WeaponType) TeamFortress_CanGetWeapon =
- {
- if ( Retriever.items_allowed & WeaponType )
- return 1;
-
- return 0;
- };
-
- //=========================================================================
- // Return 1 if the Retriever is allowed to pick up the Armor
- float(entity Retriever, entity Armor) TeamFortress_CanGetArmor =
- {
- local float type;
- local float af;
- local string at;
-
- if (Armor.classname == "item_armor1")
- {
- type = 0.3;
- }
- else if (Armor.classname == "item_armor2")
- {
- type = 0.6;
- }
- else if (Armor.classname == "item_armorInv")
- {
- type = 0.8;
- }
- else
- {
- dprint("Error in TeamFortress_CanGetArmor()\n");
- dprint("Invalid armor type passed.\n");
- return 0;
- }
-
- af = Armor.spawnflags - (Armor.spawnflags & AT_NORMAL);
-
- if ( type > Retriever.armor_allowed )
- return 0;
-
- return 1;
-
- if (!af)
- return 1;
- if (PC_SCOUT_ARMORCLASSES & af)
- return 1;
-
- return 0;
- };
-
-
- //=========================================================================
- // Controls the equipment a class receives from backpacks
- float(entity Retriever, entity Items) TeamFortress_AddBackpackItems =
- {
- // If you want the classes to _not_ start off with all their legal
- // weapons, then you may want them to be able to pick up weapons
- // from backpacks. If so, this is where to do it.
- // For now, return.
- return;
- };
-
- //=========================================================================
- // WEAPON HANDLING FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Sniper/Auto Rifle selection function
- void() TeamFortress_SniperWeapon =
- {
- local float it;
-
- self.impulse = 0;
-
- if (self.reloading)
- return;
-
- if (!((self.secondary_items & NIT_SNIPER_RIFLE) && (self.secondary_items & NIT_AUTO_RIFLE)))
- return;
-
- if (self.ammo_shells < 1)
- { // don't have the ammo
- sprint (self, "not enough ammo.\n");
- return;
- }
-
- if (self.weapon == IT_EXTRA_WEAPON && self.secondary_weapon == NIT_SNIPER_RIFLE)
- {
- self.secondary_weapon = NIT_AUTO_RIFLE;
- }
- else if (self.weapon == IT_EXTRA_WEAPON && self.secondary_weapon == NIT_AUTO_RIFLE)
- {
- self.secondary_weapon = NIT_SNIPER_RIFLE;
- }
- else
- {
- self.secondary_weapon = NIT_SNIPER_RIFLE;
- self.weapon = IT_EXTRA_WEAPON;
- }
-
- W_SetCurrentAmmo ();
- };
-
- //=========================================================================
- // Assault Cannon selection function
- void() TeamFortress_AssaultWeapon =
- {
- local float it;
-
- self.impulse = 0;
-
- if (self.reloading)
- return;
-
- if (!(self.secondary_items & NIT_ASSAULT_CANNON))
- return;
-
- if (self.heat > 0)
- {
- sprint(self, "the assault cannon is still overheated.\n");
- return;
- }
-
- if (self.ammo_shells < 1)
- { // don't have the ammo
- sprint (self, "not enough ammo.\n");
- return;
- }
- // The cannon also nees 10 cells to power up
- if (self.ammo_cells < 10)
- {
- sprint(self, "not enough cells to power the assault cannon.\n");
- return;
- }
-
- self.secondary_weapon = NIT_ASSAULT_CANNON;
- self.weapon = IT_EXTRA_WEAPON;
-
- W_SetCurrentAmmo ();
- };
-
- //=========================================================================
- // If this gets called, the players holding onto an exploding grenade :)
- void() TeamFortress_ExplodePerson =
- {
- local entity missile;
-
- // Removes the owners grenade
- self.owner.grenadeprimed = 0;
-
- self.owner.punchangle_x = -2;
-
- missile = spawn ();
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
-
- // Don't bother calculating a velocity
- missile.velocity = '0 0 0';
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- // set the grenade's alternative kill flag
- missile.altkill = 1;
-
- // set the grenades thinktime to now
- missile.nextthink = time + 0.1;
-
- // set the think and touches to the appropriate grenade type
- if (self.weapon == GR_TYPE_NORMAL)
- {
- missile.touch = NormalGrenadeTouch;
- missile.think = NormalGrenadeExplode;
- missile.altkillweapon = AK_GRENADE;
- }
- if (self.weapon == GR_TYPE_CONCUSSION)
- {
- missile.touch = ConcussionGrenadeTouch;
- missile.think = ConcussionGrenadeExplode;
- }
- if (self.weapon == GR_TYPE_NAIL)
- {
- missile.touch = NailGrenadeTouch;
- missile.think = NailGrenadeExplode;
- missile.altkillweapon = AK_GRENADE_NAIL;
- }
- if (self.weapon == GR_TYPE_MIRV)
- {
- missile.touch = MirvGrenadeTouch;
- missile.think = MirvGrenadeExplode;
- missile.altkillweapon = AK_GRENADE_MIRV;
- }
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.owner.origin);
-
- bprint("No ");
- bprint(self.owner.netname);
- bprint(", throw the grenade, not the pin!\n");
-
- // Remove primed grenade object
- remove(self);
- };
-
- //=========================================================================
- // Touch function for a concussion grenade
- void() ConcussionGrenadeTouch =
- {
- if (other.takedamage == DAMAGE_AIM)
- {
- // A person hit by a concussion grenade doesn't move much,
- // since their origin is pretty much right on the grenade's
- // explosion point, so we'll give him a kick.
- other.velocity_x = self.velocity_x - 300;
- other.velocity_y = self.velocity_y - 300;
- other.velocity_z = 300;
-
- if (other.classname != "player")
- {
- if(other.flags & FL_ONGROUND)
- other.flags = other.flags - FL_ONGROUND;
- }
-
- ConcussionGrenadeExplode();
- return;
- }
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- //=========================================================================
- // Concussion grenade explosion function
- void() ConcussionGrenadeExplode =
- {
- T_RadiusBounce (self, self.owner, 240, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- BecomeExplosion ();
- };
-
- //=========================================================================
- // Concussion grenade timer to remove idlescale
- void() ConcussionGrenadeTimer =
- {
- local string st;
-
- // checks the flag which stops all concussions
- // this flag is set when a player dies
- if (self.owner.is_concussed == FALSE)
- {
- remove(self);
- return;
- }
-
- self.health = self.health - GR_CONCUSS_DEC;
- if (self.health < 0)
- self.health = 0;
- self.nextthink = time + GR_CONCUSS_TIME;
-
- st = ftos(self.health);
- stuffcmd(self.owner, "v_idlescale ");
- stuffcmd(self.owner, st);
- stuffcmd(self.owner, "\n");
-
- if (self.health == 0)
- {
- remove(self);
- return;
- }
-
- };
-
- //=========================================================================
- // Touch Function for Nail Grenade
- void() NailGrenadeTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
-
- // If the Nail Grenade hits a player, it just bounces off
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- //=========================================================================
- // Explode Function for Nail Grenade
- void() NailGrenadeExplode =
- {
- // Raise into the air
- self.movetype = MOVETYPE_NOCLIP;
- self.velocity = '0 0 100';
- self.avelocity = '0 500 0';
- self.nextthink = time + 0.5;
- self.think = NailGrenadeNailEm;
- };
-
- //=========================================================================
- // Nail function for Nail Grenade
- void() NailGrenadeNailEm =
- {
- // Rotate and spew Nails
- self.velocity = '0 0 0';
-
- self.nextthink = time + 0.1;
- self.think = NailGrenadeLaunchNail;
- self.playerclass = 0;
- };
-
- //=========================================================================
- // Nail function for Nail Grenade
- void() NailGrenadeLaunchNail =
- {
- local float i,j;
-
- i = 0;
- while (i < 3)
- {
- j = (random() + 2) * 2;
- current_yaw = anglemod( self.angles_y );
- current_yaw = anglemod(current_yaw + j);
- self.angles_y = current_yaw;
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles);
-
- launch_spike(self.origin, v_forward, 1, AK_GRENADE_NAIL);
-
- i = i + 1;
- }
-
- self.playerclass = self.playerclass + 1;
- self.nextthink = time + 0.1;
-
- // Explode
- if (self.playerclass > 50)
- self.think = GrenadeExplode;
- };
-
- //=========================================================================
- // Touch Function for Mirv Grenade
- // Mirv Grenade heavily influenced by the Firewall Grenade by Steve Bond (wedge@nuc.net)
- void() MirvGrenadeTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
-
- // If the Mirv Grenade hits a player, it just bounces off
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- //=========================================================================
- // Mirv Grenade explode function, for when the PRIMETIME runs out
- void() MirvGrenadeExplode =
- {
- local float i;
-
- T_RadiusDamage (self, self.owner, 250, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- self.solid=SOLID_NOT;
- BecomeExplosion ();
-
- // Launch mirvs
- i = 0;
- while (i < GR_TYPE_MIRV_NO)
- {
- MirvGrenadeLaunch (self.origin + '0 0 -1',self.owner);
- i = i + 1;
- }
- };
-
- //=========================================================================
- // Launch a Mirv
- void (vector org, entity shooter) MirvGrenadeLaunch =
- {
- local float xdir,ydir,zdir, spin;
-
- xdir = 150 * random() - 75;
- ydir = 150 * random() - 75;
- zdir = 40 * random();
-
- newmis = spawn ();
- newmis.owner = shooter;
- newmis.movetype = MOVETYPE_BOUNCE;
- self.touch = SUB_Null;
- newmis.solid = SOLID_BBOX;
-
- newmis.classname = "grenade";
- newmis.touch = GrenadeTouch;
- newmis.think = GrenadeExplode;
- newmis.nextthink = time + 2;
-
- newmis.velocity_x = xdir * 2;
- newmis.velocity_y = ydir * 2;
- newmis.velocity_z = zdir * 15;
-
- spin = (random() * 10) / 2;
- if (spin <= 0)
- newmis.avelocity='250 300 400';
- if (spin == 1)
- newmis.avelocity='400 250 300';
- if (spin == 2)
- newmis.avelocity='300 400 250';
- if (spin == 3)
- newmis.avelocity='300 300 300';
- if (spin >= 4)
- newmis.avelocity='400 250 400';
-
- setmodel (newmis, "progs/grenade.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- setorigin (newmis, org);
- };
-
- //=========================================================================
- // Thrown Grenade touch function.
- void() NormalGrenadeTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
-
- // Thrown grenades don't detonate when hitting an enemy
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- //=========================================================================
- // Thrown grenade explosion. Twice as powerful as grenade launcher grenades.
- void() NormalGrenadeExplode =
- {
- T_RadiusDamage (self, self.owner, 240, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- BecomeExplosion ();
- };
-
- //=========================================================================
- // Detonate all thrown pipebombs
- void() TeamFortress_DetonatePipebombs =
- {
- local entity e;
-
- // Find all this players pipebombs
- e = find(world, classname, "pipebomb");
- while (e)
- {
- if(e.owner == self)
- e.nextthink = time;
-
- e = find(e, classname, "pipebomb");
- }
- };
-
- //=========================================================================
- // Pipebomb touch function
- void() PipebombTouch =
- {
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- //=========================================================================
- // ITEM HANDLING FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Handles the scanner function for scouts, and Base Defences
- void(float scanrange) TeamFortress_Scan =
- {
- local string power;
- local entity list;
- local float scen, scfr;
-
- // added in for the direction scanner code
- local float enemy_detected;
- local float any_detected;
-
- local vector vf, vr, e; // transformed versions of v_forward, v_right and the enemy vector
- local float res1, res2, res3; // for the vector work
- local float vf_e_angle, vr_e_angle; // results
-
- // prevent scan impulse from triggering anything else
- self.impulse = 0;
- self.last_impulse = 0;
-
- if (self.classname == "player")
- {
- if (!(self.tf_items & NIT_SCANNER))
- return;
-
- // If Impulse is TF_SCAN_ENEMY, toggle Scanning for Enemies
- if (scanrange == TF_SCAN_ENEMY)
- {
- if (self.tf_items_flags & NIT_SCANNER_ENEMY)
- {
- sprint(self, "Enemy Scanning disabled.\n");
- self.tf_items_flags = self.tf_items_flags - NIT_SCANNER_ENEMY;
- return;
- }
- sprint(self, "Enemy Scanning enabled.\n");
- self.tf_items_flags = self.tf_items_flags | NIT_SCANNER_ENEMY;
- return;
- }
-
- // If Impulse is TF_SCAN_FRIENDLY, toggle Scanning for Friendlies
- if (scanrange == TF_SCAN_FRIENDLY)
- {
- if (self.tf_items_flags & NIT_SCANNER_FRIENDLY)
- {
- sprint(self, "Friendly Scanning disabled.\n");
- self.tf_items_flags = self.tf_items_flags - NIT_SCANNER_FRIENDLY;
- return;
- }
- sprint(self, "Friendly Scanning enabled.\n");
- self.tf_items_flags = self.tf_items_flags | NIT_SCANNER_FRIENDLY;
- return;
- }
-
- // If the user doesn't have as many cells as he/she specified, just
- // use as many as they've got.
-
- if (scanrange > self.ammo_cells)
- scanrange = self.ammo_cells;
-
- if (scanrange <= 0)
- {
- sprint(self,"No cells.\n");
- return;
- }
-
- if (scanrange > NIT_SCANNER_MAXCELL)
- scanrange = NIT_SCANNER_MAXCELL;
-
- scen = 0;
- scfr = 0;
- // Set the Scanner flags
- if (self.tf_items_flags & NIT_SCANNER_ENEMY)
- scen = 1;
- if (self.tf_items_flags & NIT_SCANNER_FRIENDLY)
- scfr = 1;
-
- // If no entity type is enabled, don't scan
- if ((scen == 0) && (scfr == 0))
- {
- sprint(self,"All scanner functions are disabled.\n");
- return;
- }
-
- sprint(self, "Power Usage: ");
- power = ftos(scanrange);
- sprint(self, power);
- sprint(self, ". Scanning...\n");
-
- // Use up cells to power the scanner
- // additions:
- // altered this so scanner could be more easily tested
- self.ammo_cells = self.ammo_cells - rint(scanrange / 5);
- scanrange = scanrange * NIT_SCANNER_POWER;
-
- // Get the list of entities the scanner finds
- list = T_RadiusScan(self, scanrange, scen, scfr);
- }
- // Base Defence scanning code here
-
- // Reset the entity counts
- scen = 0;
- scfr = 0;
-
- // the vectors v_forward and v_right are required to
- // 'triangulate' the enemies position
- makevectors(self.v_angle);
-
- // Walk the list
- // For now, just count the entities.
- // In the future, we'll display bearings :)
- // additions: the future is now!
- while (list)
- {
- // sets the enemy_detected flag to TRUE if not on your team, FALSE if so
- any_detected = TRUE; // this flag is set to false if bogie is moving
- // too slow to be detected (and velocity checking is on)
-
- // If this scanner is a motion detector, don't record
- // object that don't have the required velocity to be detected.
- if (self.tf_items_flags & NIT_SCANNER_MOVEMENT)
- {
- if (vlen(list.velocity) > NIT_SCANNER_MIN_MOVEMENT)
- {
- if ((list.team > 0) && (self.team > 0) && (list.team == self.team))
- {
- scfr = scfr + 1;
- enemy_detected = FALSE;
- }
- else
- {
- scen = scen + 1;
- enemy_detected = TRUE;
- }
- }
- else
- {
- any_detected = FALSE;
- }
- }
- else
- {
- if ((list.team > 0) && (self.team > 0) && (list.team == self.team))
- {
- scfr = scfr + 1;
- enemy_detected = FALSE;
- }
- else
- {
- scen = scen + 1;
- enemy_detected = TRUE;
- }
- }
-
- // this displays the direction of the detected player
- // using the cosine rule to find the angle
- // cos theta = A.B divided by |A||B|
- // it should return a value between 1 and -1
- if (any_detected)
- {
- if (enemy_detected)
- sprint(self, "Enemy detected at ");
- else
- sprint(self, "Comrade detected at ");
-
- // finding the angle from v_forward gives the forward-back angle
- vf = v_forward;
- vf_z = 0;
-
- // finding the angle from v_right gives the left-right angle
- vr = v_right;
- vr_z = 0;
-
- // make a vector from the player to the detected one
- e = list.origin - self.origin;
- e_z = 0;
-
- res1 = vlen(e);
- if (res1 > 1200)
- sprint(self, "very far ");
- else if (res1 > 600)
- sprint(self, "far ");
-
-
- // dot product of vf and e (A.B)
- res1 = (vf_x * e_x) + (vf_y * e_y);
-
- // multiple the vector lengths of vf and e (eg |A||B| )
- res2 = vlen(vf);
- res3 = vlen(e);
- res2 = res2 * res3;
-
- // divide the results
- vf_e_angle = res1 / res2;
-
- // finding the inverse cos of this gives the angle
- // but we don't need to do that because we realise:
-
- // if res3 is 1, then the arcos would be 0 degrees (directly ahead)
- // if res3 is 0.7, then the arcos would be 45 degrees (forward and off to one side)
- // if res3 is 0, then the arcos would be 90 degrees (directly to the side)
- // if res3 is -1, the the arcos would be 180 degrees (directly behind)
-
- // to narrow it right down, we need to find the angle between the enemy and v_right
-
- res1 = (vr_x * e_x) + (vr_y * e_y);
- res2 = vlen(vr);
- res3 = vlen(e);
- res2 = res2 * res3;
- vr_e_angle = res1 / res2;
-
- // if the vr_e_angle is positive, then the enemy is on the right-hand side
- // otherwise it is on the left
- // if vr_e_angle is 0, then the enemy is either directly in front or behind
-
- // the o'clock value is determined by a degree range
- // eg 1 o'clock is cos 15deg to cos 45deg
- // 2 o'clock is cos 45deg to cos 75deg
- if (vr_e_angle > 0)
- {
- if (vf_e_angle >= 0.96) // cos15
- sprint(self, "12");
- else if (vf_e_angle >= 0.7) // cos45
- sprint(self, "1");
- else if (vf_e_angle >= 0.25) // cos75
- sprint(self, "2");
- else if (vf_e_angle >= -0.25) // cos105
- sprint(self, "3");
- else if (vf_e_angle >= -0.7) // cos135
- sprint(self, "4");
- else if (vf_e_angle >= -0.96) // cos165
- sprint(self, "5");
- else
- sprint(self, "6");
- }
- else if (vr_e_angle < 0)
- {
- if (vf_e_angle >= 0.96)
- sprint(self, "12");
- else if (vf_e_angle >= 0.7)
- sprint(self, "11");
- else if (vf_e_angle >= 0.25)
- sprint(self, "10");
- else if (vf_e_angle >= -0.25)
- sprint(self, "9");
- else if (vf_e_angle >= -0.7)
- sprint(self, "8");
- else if (vf_e_angle >= -0.96)
- sprint(self, "7");
- else
- sprint(self, "6");
-
- }
- else // vr_e_angle must be 0
- {
- if (vf_e_angle < 0)
- sprint(self, "12");
- else
- sprint(self, "6");
- }
-
-
- sprint(self, " o'clock");
-
- // do the up-down (z) direction
- res1 = list.origin_z - self.origin_z;
-
- if (res1 > 200)
- sprint(self, ", really high");
- else if (res1 > 60)
- sprint(self, ", high");
- else if (res1 < -200)
- sprint(self, ", really low");
- else if (res1 < -60)
- sprint(self, ", low");
-
- sprint(self, "\n");
- } // end if(any_detected)
-
-
- list = list.linked_list;
- }
-
- // Display the counts
- // For Base Defences, it will display the counts to all team members
- if ((scen == 0) && (scfr == 0))
- {
- sprint(self, "No blips.\n");
- return;
- }
-
- // Update ammo levels
- W_SetCurrentAmmo ();
-
- return;
- };
-
- //=========================================================================
- // Handles the Setting of Detpacks
- void(float timer) TeamFortress_SetDetpack =
- {
- local string stimer;
-
- // prevent detpack impulse from triggering anything else
- self.impulse = 0;
- self.last_impulse = 0;
-
- if (!(self.secondary_items & NIT_DETPACK))
- return;
-
- if (self.ammo_detpack <= 0)
- return;
-
- self.ammo_detpack = self.ammo_detpack - 1;
- //stuffcmd(self, "cl_forwardspeed 0\n");
- //stuffcmd(self, "cl_backspeed 0\n");
- //stuffcmd(self, "cl_sidespeed 0\n");
- self.movetype = MOVETYPE_NONE;
-
- sprint(self, "Setting detpack for ");
- stimer = ftos(timer);
- sprint(self, stimer);
- sprint(self, " seconds...\n");
-
- self.detpack = spawn();
- self.detpack.owner = self;
- self.detpack.nextthink = time + NIT_DETPACK_SETTIME;
- self.detpack.think = TeamFortress_DetpackSet;
- self.detpack.health = timer;
- };
-
- //=========================================================================
- // The detpack is set, let the player go and start timer
- void() TeamFortress_DetpackSet =
- {
- local entity countd, dp;
-
- self.owner.movetype = MOVETYPE_WALK;
-
- dp = spawn ();
- dp.owner = self.owner;
- dp.origin = self.owner.origin - '0 0 23';
- dp.movetype = MOVETYPE_BOUNCE;
- dp.solid = SOLID_TRIGGER;
- dp.classname = "detpack";
- dp.flags = FL_ITEM;
-
- dp.velocity = '0 0 0';
- dp.avelocity = '0 0 0';
- dp.angles = vectoangles(dp.velocity);
-
- // Set the Detpack alternative kill flag
- dp.altkill = 1;
- dp.altkillweapon = AK_DETPACK;
-
- dp.touch = TeamFortress_DetpackTouch;
-
- setmodel (dp, "progs/backpack.mdl");
- setsize (dp, '-16 -16 0', '16 16 56');
- setorigin (dp, self.owner.origin);
-
- // Create the CountDown entity
- countd = spawn();
- countd.think = TeamFortress_DetpackCountDown;
- countd.health = self.health - 1;
- countd.owner = self.owner;
- if (self.health <= 10)
- countd.nextthink = time + 1;
- else
- {
- countd.nextthink = time + self.health - 10;
- countd.health = 9;
- }
- dp.nextthink = time + self.health;
- dp.think = TeamFortress_DetpackExplode;
-
- sprint(self.owner, "Detpack set!\n");
- remove(self);
- };
-
- //=========================================================================
- // The detpack goes BOOM!
- void() TeamFortress_DetpackExplode =
- {
- bprint("FIRE IN THE HOLE!!!!\n");
- T_RadiusDamage (self, self.owner, NIT_DETPACK_SIZE, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- BecomeExplosion ();
- };
-
- //=========================================================================
- // The detpack touch function. Scouts can disarm it
- void() TeamFortress_DetpackTouch =
- {
- if (other.classname != "player")
- return;
-
- if (other.playerclass != PC_SCOUT)
- return;
-
- bprint(other.netname);
- bprint(" snuffs ");
- bprint(self.owner.netname);
- bprint("'s fuse!\n");
-
- remove(self);
- };
-
- //=========================================================================
- // The Detpack CountDown function. Displays the seconds left before the
- // detpack detonates to the owner of the detpack, if <10
- void() TeamFortress_DetpackCountDown =
- {
- local string cd;
-
- cd = ftos(self.health);
- sprint(self.owner, cd);
- sprint(self.owner, "...\n");
-
- self.nextthink = time + 1;
- self.health = self.health - 1;
-
- if (self.health == 0)
- remove(self);
- };
-
- //=========================================================================
- // UTILITY FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Acts just like T_RadiusDamage, but doesn't damage things, just pushes them away
- // from the explosion at a speed relative to the distance from the explosion's origin.
- void(entity inflictor, entity attacker, float bounce, entity ignore) T_RadiusBounce =
- {
- local float points;
- local entity head, timer;
- local vector org;
- local string st;
-
- head = findradius(inflictor.origin, bounce+40);
-
- while (head)
- {
- if (head != ignore)
- {
- if (head.takedamage)
- {
- org = head.origin + (head.mins + head.maxs)*0.5;
- points = 0.5*vlen (org - inflictor.origin);
- if (points < 0)
- points = 0;
- points = bounce - points;
- if (points > 0)
- {
- // Bounce!!
- head.velocity = org - inflictor.origin;
- head.velocity = head.velocity * (points / 10);
-
- if (head.classname != "player")
- {
- if(head.flags & FL_ONGROUND)
- head.flags = head.flags - FL_ONGROUND;
- }
- else
- {
- // Concuss 'em!!
- head.is_concussed = TRUE;
- stuffcmd(head,"v_idlescale 100\n");
- stuffcmd(head,"bf\n");
- // Create a timer entity
- head.concusstimer = spawn();
- head.concusstimer.nextthink = time + GR_CONCUSS_TIME;
- head.concusstimer.think = ConcussionGrenadeTimer;
- head.concusstimer.owner = head;
- head.concusstimer.health = 100;
- }
- }
- }
- }
- head = head.chain;
- }
- };
-
- //=========================================================================
- // Returns a list of players within a radius around the origin, like findradius,
- // except that some parsing of the list can be done based on the parameters passed in.
- // Make sure you check that the return value is not NULL b4 using it.
- entity(entity scanner, float scanrange, float enemies, float friends) T_RadiusScan =
- {
- local entity head;
- local entity list_head;
- local entity list;
- local float gotatarget;
-
- head = findradius(scanner.origin, scanrange+40);
-
- while (head)
- {
- gotatarget = 0;
- if (head != scanner) // Don't pick up the entity that's scanning
- {
- if (head.takedamage)
- {
- if ((head.classname == "player") && (friends || enemies))
- {
- if (teamplay == 1)
- {
- if ( friends && (head.team > 0) && (scanner.team > 0) && (head.team == scanner.team) )
- gotatarget = 1;
- if ( enemies && (head.team > 0) && (scanner.team > 0) && (head.team != scanner.team) )
- gotatarget = 1;
- }
- else
- gotatarget = 1;
- }
- }
- }
-
- // Add this entity to the linked list if it matches the target criteria
- if (gotatarget)
- {
- if (list)
- {
- list.linked_list = head;
- list = list.linked_list;
- }
- else
- {
- list_head = head;
- list = head;
- }
- }
-
- head = head.chain;
- }
-
- return list_head;
- };
-
- //=========================================================================
- // Stuff an alias. This is a little messy since we insisted
- // on maintaining the ability to alter the impulse numbers in the defs.qc
- // and not have to change any code.
- void(string halias, float himpulse1, float himpulse2) TeamFortress_Alias =
- {
- local string imp;
-
- stuffcmd(self, "alias ");
- stuffcmd(self, halias);
- stuffcmd(self, " \"impulse ");
- imp = ftos(himpulse1);
- stuffcmd(self, imp);
-
- // if himpulse2 is not zero, assume that himpulse1 is a preimpulse
- // and complete the alias
- if (himpulse1)
- {
- stuffcmd(self, ";wait; impulse ");
- imp = ftos(himpulse2);
- stuffcmd(self, imp);
- }
- stuffcmd(self, "\"\n");
- };
-
- //=========================================================================
- // CYCLIC EVENT FUNCTIONS
- //=========================================================================
- //=========================================================================
- // Regenerates the entity which owns this cyclictimer
- void() TeamFortress_Regenerate =
- {
- if (self.owner.playerclass == PC_MEDIC)
- {
- self.nextthink = time + PC_MEDIC_REGEN_TIME;
-
- if (self.owner.health >= self.owner.max_health)
- return;
-
- self.owner.health = self.owner.health + PC_MEDIC_REGEN_AMOUNT;
- if (self.owner.health > self.owner.max_health)
- self.owner.health = self.owner.max_health;
- return;
- }
-
- return;
- };
-
- //=========================================================================
- // Check for cheats :) Mainly for internet play
- // This is _far_ from a good solution. It will catch non-scouts that
- // set their speeds to maxspeed, but not much else.
- // It will occasionally catch someone who only sets their speed up
- // by a little bit.
- // Still, in my opinion it was better than noth checking at all.
- // If you trust people, or play only with friends, remove the creation
- // of the cheattimer ( See TeamFortress_SetEquipment() above )
- // If anyone knows of a better way to do this, or knows how to
- // get the value of a _client_ cvar, please mail me.
- void() TeamFortress_CheckforCheats =
- {
- local float tf;
- local string st;
-
- tf = random() * 50;
- self.nextthink = time + 10 + tf;
-
- tf = vlen(self.owner.velocity);
-
- // Since players still exceed their maxfbspeed when strafing
- // as well as moving forward or backward, I played around a
- // while until I decided on 200. I've never broken this.
- // If you do exceed this when not cheating, please mail me.
- if (tf > (self.owner.maxfbspeed + 300))
- {
- // Make sure they're on the ground
- if ((self.owner.flags & FL_ONGROUND) && (self.velocity_z == 0))
- {
- bprint(self.owner.netname);
- bprint(" has been fined 5 frags for cheating!\n");
- self.owner.frags = self.owner.frags - 5;
- T_Damage(self.owner, world, world, 400);
-
- // Make sure they don't get fined again before they respawn
- self.owner.maxfbspeed = 1000;
- }
- }
- };
-