prozac-qfcc/spy.qc
Adam Olsen 0b97684c96 - bugs, todo
- cleaned up some misc bugs in the hook, as well as formatting
2001-12-05 18:47:21 +00:00

1104 lines
31 KiB
C++

#include "defs.qh"
#include "menu.qh"
/*==============================================
SPY.QC
TeamFortress v2.5 29/2/97
========================================================
Functions for the SPY class and associated weaponry
========================================================*/
void() TeamFortress_SpyGoUndercover;
void(float type) TeamFortress_SpyFeignDeath;
void(entity spy) TeamFortress_SpyCalcName;
void() TeamFortress_SpyUndercoverThink;
void(float class) TeamFortress_SpyChangeSkin;
void(float teamno) TeamFortress_SpyChangeColor;
void() GasGrenadeMakeGas;
void() HallucinationTimer;
void() W_FireTranq;
void() T_TranqDartTouch;
void() TranquiliserTimer;
void() TranquiliserTimer2; //CH for demons
void(entity spy) Spy_RemoveDisguise;
// Spy Feign Death Handling
$cd /raid/quake/id1/models/player_4
$origin 0 -6 24
$base base
$skin skin
$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6
$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6
$frame stand1 stand2 stand3 stand4 stand5
$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12
$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6
$frame pain1 pain2 pain3 pain4 pain5 pain6
$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6
$frame axdeth7 axdeth8 axdeth9
$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8
$frame deatha9 deatha10 deatha11
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
$frame deathb9
$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15
$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7
$frame deathd8 deathd9
$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7
$frame deathe8 deathe9
/*
$frame nailatt1 nailatt2
$frame light1 light2
$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6
$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6
$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6
$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6
$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
*/
// Spy Feign Death Frames
void() spy_diea1 = [ $deatha1, spy_diea2 ] {};
void() spy_diea2 = [ $deatha2, spy_diea3 ] {};
void() spy_diea3 = [ $deatha3, spy_diea4 ] {};
void() spy_diea4 = [ $deatha4, spy_diea5 ] {};
void() spy_diea5 = [ $deatha5, spy_diea6 ] {};
void() spy_diea6 = [ $deatha6, spy_diea7 ] {};
void() spy_diea7 = [ $deatha7, spy_diea8 ] {};
void() spy_diea8 = [ $deatha8, spy_diea9 ] {};
void() spy_diea9 = [ $deatha9, spy_diea10 ] {};
void() spy_diea10 = [ $deatha10, spy_diea11 ] {};
void() spy_diea11 = [ $deatha11, spy_diea11 ] {};
void() spy_dieb1 = [ $deathb1, spy_dieb2 ] {};
void() spy_dieb2 = [ $deathb2, spy_dieb3 ] {};
void() spy_dieb3 = [ $deathb3, spy_dieb4 ] {};
void() spy_dieb4 = [ $deathb4, spy_dieb5 ] {};
void() spy_dieb5 = [ $deathb5, spy_dieb6 ] {};
void() spy_dieb6 = [ $deathb6, spy_dieb7 ] {};
void() spy_dieb7 = [ $deathb7, spy_dieb8 ] {};
void() spy_dieb8 = [ $deathb8, spy_dieb9 ] {};
void() spy_dieb9 = [ $deathb9, spy_dieb9 ] {};
void() spy_diec1 = [ $deathc1, spy_diec2 ] {};
void() spy_diec2 = [ $deathc2, spy_diec3 ] {};
void() spy_diec3 = [ $deathc3, spy_diec4 ] {};
void() spy_diec4 = [ $deathc4, spy_diec5 ] {};
void() spy_diec5 = [ $deathc5, spy_diec6 ] {};
void() spy_diec6 = [ $deathc6, spy_diec7 ] {};
void() spy_diec7 = [ $deathc7, spy_diec8 ] {};
void() spy_diec8 = [ $deathc8, spy_diec9 ] {};
void() spy_diec9 = [ $deathc9, spy_diec10 ] {};
void() spy_diec10 = [ $deathc10, spy_diec11 ] {};
void() spy_diec11 = [ $deathc11, spy_diec12 ] {};
void() spy_diec12 = [ $deathc12, spy_diec13 ] {};
void() spy_diec13 = [ $deathc13, spy_diec14 ] {};
void() spy_diec14 = [ $deathc14, spy_diec15 ] {};
void() spy_diec15 = [ $deathc15, spy_diec15 ] {};
void() spy_died1 = [ $deathd1, spy_died2 ] {};
void() spy_died2 = [ $deathd2, spy_died3 ] {};
void() spy_died3 = [ $deathd3, spy_died4 ] {};
void() spy_died4 = [ $deathd4, spy_died5 ] {};
void() spy_died5 = [ $deathd5, spy_died6 ] {};
void() spy_died6 = [ $deathd6, spy_died7 ] {};
void() spy_died7 = [ $deathd7, spy_died8 ] {};
void() spy_died8 = [ $deathd8, spy_died9 ] {};
void() spy_died9 = [ $deathd9, spy_died9 ] {};
void() spy_diee1 = [ $deathe1, spy_diee2 ] {};
void() spy_diee2 = [ $deathe2, spy_diee3 ] {};
void() spy_diee3 = [ $deathe3, spy_diee4 ] {};
void() spy_diee4 = [ $deathe4, spy_diee5 ] {};
void() spy_diee5 = [ $deathe5, spy_diee6 ] {};
void() spy_diee6 = [ $deathe6, spy_diee7 ] {};
void() spy_diee7 = [ $deathe7, spy_diee8 ] {};
void() spy_diee8 = [ $deathe8, spy_diee9 ] {};
void() spy_diee9 = [ $deathe9, spy_diee9 ] {};
void() spy_die_ax1 = [ $axdeth1, spy_die_ax2 ] {};
void() spy_die_ax2 = [ $axdeth2, spy_die_ax3 ] {};
void() spy_die_ax3 = [ $axdeth3, spy_die_ax4 ] {};
void() spy_die_ax4 = [ $axdeth4, spy_die_ax5 ] {};
void() spy_die_ax5 = [ $axdeth5, spy_die_ax6 ] {};
void() spy_die_ax6 = [ $axdeth6, spy_die_ax7 ] {};
void() spy_die_ax7 = [ $axdeth7, spy_die_ax8 ] {};
void() spy_die_ax8 = [ $axdeth8, spy_die_ax9 ] {};
void() spy_die_ax9 = [ $axdeth9, spy_die_ax9 ] {};
// Spy Feign Death... getting up Frames
void() spy_upb1 = [ $deathb9, spy_upb2 ] {};
void() spy_upb2 = [ $deathb8, spy_upb3 ] {};
void() spy_upb3 = [ $deathb7, spy_upb4 ] {};
void() spy_upb4 = [ $deathb6, spy_upb5 ] {};
void() spy_upb5 = [ $deathb5, spy_upb6 ] {};
void() spy_upb6 = [ $deathb4, spy_upb7 ] {};
void() spy_upb7 = [ $deathb3, spy_upb8 ] {};
void() spy_upb8 = [ $deathb2, spy_upb9 ] {};
void() spy_upb9 = [ $deathb1, spy_upb9 ]
{
player_stand1();
};
void() spy_upc1 = [ $deathc15, spy_upc2 ] {};
void() spy_upc2 = [ $deathc14, spy_upc3 ] {};
void() spy_upc3 = [ $deathc13, spy_upc4 ] {};
void() spy_upc4 = [ $deathc12, spy_upc5 ] {};
void() spy_upc5 = [ $deathc11, spy_upc6 ] {};
void() spy_upc6 = [ $deathc10, spy_upc7 ] {};
void() spy_upc7 = [ $deathc9, spy_upc8 ] {};
void() spy_upc8 = [ $deathc8, spy_upc9 ] {};
void() spy_upc9 = [ $deathc7, spy_upc10 ] {};
void() spy_upc10 = [ $deathc6, spy_upc11 ] {};
void() spy_upc11 = [ $deathc5, spy_upc12 ] {};
void() spy_upc12 = [ $deathc4, spy_upc13 ] {};
void() spy_upc13 = [ $deathc3, spy_upc14 ] {};
void() spy_upc14 = [ $deathc2, spy_upc15 ] {};
void() spy_upc15 = [ $deathc1, spy_upc15 ]
{
player_stand1();
};
void() spy_upd1 = [ $deathd9, spy_upd2 ] {};
void() spy_upd2 = [ $deathd8, spy_upd3 ] {};
void() spy_upd3 = [ $deathd7, spy_upd4 ] {};
void() spy_upd4 = [ $deathd6, spy_upd5 ] {};
void() spy_upd5 = [ $deathd5, spy_upd6 ] {};
void() spy_upd6 = [ $deathd4, spy_upd7 ] {};
void() spy_upd7 = [ $deathd3, spy_upd8 ] {};
void() spy_upd8 = [ $deathd2, spy_upd9 ] {};
void() spy_upd9 = [ $deathd1, spy_upd9 ]
{
player_stand1();
};
void() spy_upe1 = [ $deathe1, spy_upe9 ] {};
void() spy_upe2 = [ $deathe2, spy_upe8 ] {};
void() spy_upe3 = [ $deathe3, spy_upe7 ] {};
void() spy_upe4 = [ $deathe4, spy_upe6 ] {};
void() spy_upe5 = [ $deathe5, spy_upe5 ] {};
void() spy_upe6 = [ $deathe6, spy_upe4 ] {};
void() spy_upe7 = [ $deathe7, spy_upe3 ] {};
void() spy_upe8 = [ $deathe8, spy_upe2 ] {};
void() spy_upe9 = [ $deathe9, spy_upe1 ]
{
player_stand1();
};
void() spy_upaxe1 = [ $axdeth9, spy_upaxe2 ] {};
void() spy_upaxe2 = [ $axdeth8, spy_upaxe3 ] {};
void() spy_upaxe3 = [ $axdeth7, spy_upaxe4 ] {};
void() spy_upaxe4 = [ $axdeth6, spy_upaxe5 ] {};
void() spy_upaxe5 = [ $axdeth5, spy_upaxe6 ] {};
void() spy_upaxe6 = [ $axdeth4, spy_upaxe7 ] {};
void() spy_upaxe7 = [ $axdeth3, spy_upaxe8 ] {};
void() spy_upaxe8 = [ $axdeth2, spy_upaxe9 ] {};
void() spy_upaxe9 = [ $axdeth1, spy_upaxe9 ]
{
player_stand1();
};
//=========================================================================
// Function handling the Spy's feign death ability
void(float type) TeamFortress_SpyFeignDeath =
{
local float i;
local entity at_spot;
if (self.is_feigning)
{
// Check to make sure there isn't anyone on top of us
at_spot = findradius(self.origin, 64);
i = TRUE;
while (at_spot)
{
if (at_spot.classname == "player" && at_spot.deadflag == DEAD_NO && self != at_spot)
i = FALSE;
at_spot = at_spot.chain;
}
if (i == TRUE)
{
i = 1 + floor(random()*5);
self.velocity = '0 0 0';
//WK Jump em up since they fall down now when feigning
//setorigin (self, self.origin + '0 0 30');
setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
self.view_ofs = '0 0 22';
//Prevent bad movetype errors, or something
if (self.classname != "player") {
RPrint("BUG BUG BUG BUG BUG BUG BUG BUG BUG\n");
RPrint("Non-player tried to un-feign!\n");
return;
}
self.movetype = MOVETYPE_WALK;
self.is_feigning = FALSE;
self.current_weapon = self.weapon;
W_SetCurrentAmmo();
self.tfstate = self.tfstate - (self.tfstate & TFSTATE_CANT_MOVE);
TeamFortress_SetSpeed(self);
// Check .weapon, because .current_weapon has been reset
if (self.weapon <= WEAP_AXE)
{
spy_upaxe1 ();
return;
}
if (i == 1)
spy_upb1();
else if (i == 2)
spy_upc1();
else if (i == 3)
spy_upd1();
else
spy_upe1();
}
else
{
sprint(self, PRINT_HIGH, "You can't get up while someone\nis standing on you.\n");
}
}
else
{
if (!(self.flags & FL_ONGROUND) && (self.waterlevel == 0))
{
sprint(self, PRINT_HIGH, "You can't feign in the air.\n");
return;
}
//WK - Can't feign while carrying flag. King cheater!
if (self.effects & (EF_DIMLIGHT | EF_BRIGHTLIGHT)) {
sprint(self, PRINT_HIGH, "Can't feign while glowing, you sloppy bitch.\n");
return;
}
//WK - Can't feign while shooting grapple. Crash fix?
if (self.hook_out) {
sprint(self, PRINT_HIGH, "Can't feign and grapple, silly\n");
return;
}
//WK - No feign detpackers
if (self.is_detpacking) {
sprint(self, PRINT_HIGH, "Can't feign while setting a detpack, fool\n");
return;
}
if (self.is_toffingadet) //SB same for C4 det
{
sprint(self, PRINT_HIGH, "How are you going to throw a detpack while lying down?\n");
return;
}
if (self.is_haxxxoring) // SB No sleep-hackers
{
sprint(self, PRINT_HIGH, "You can't fall asleep AND hack, do one or the other.\n");
return;
}
//WK Stop detpackers
if (self.tfstate & TFSTATE_CANT_MOVE) {
sprint(self,PRINT_HIGH, "Can't feign whilst stationary\n");
return;
}
//WK Prevent sliders
if (self.is_building == TRUE) {
sprint(self, PRINT_HIGH, "Can't feign while building, beeatch.\n");
return;
}
//WK Prevent worker/feigners
if (self.job & JOB_ACTIVE) {
sprint(self, PRINT_HIGH, "Can't rest while working, you lazy bum!\n");
return;
}
//CH Prevents the most evil bug of all, so evil that I can not speak of it.... j/k
if (self.done_custom & CUSTOM_BUILDING) {
sprint (self, PRINT_HIGH, "You can't pretend to die when you're not alive!\n");
return;
}
// Check to make sure there isn't anyone on top of us
at_spot = findradius(self.origin, 64);
while (at_spot)
{
if (at_spot.classname == "player" && self != at_spot && at_spot.is_feigning == TRUE)
{
sprint(self, PRINT_HIGH, "You can't feign on top of another spy!\n");
return;
}
at_spot = at_spot.chain;
}
makeImmune(self,time+2);
//self.immune_to_check = time + 2;
self.tfstate = self.tfstate | TFSTATE_CANT_MOVE;
TeamFortress_SetSpeed(self);
self.is_feigning = TRUE;
Attack_Finished(0.8);
// make dead guy release hook (wedge)
if (self.hook_out)
{
Reset_Grapple (self.hook);
Attack_Finished(0.75);
// self.hook_out = TRUE; // PutClientInServer will reset this
}
if (self.undercover_team == 0 && self.undercover_skin == 0)
self.items = self.items & ~IT_INVISIBILITY;
self.invisible_finished = 0;
self.modelindex = modelindex_player; // don't use eyes
// Save the current weapon and remove it
self.weapon = self.current_weapon;
self.current_weapon = 0;
self.weaponmodel = "";
self.weaponframe = 0;
//WK setsize (self, '-16 -16 -24', '16 16 4');
//WK Make people fall to the ground when they feign
// Ambush, the guy that made MegaTF swears that there is no way
// to lower the camera angle, and even has a letter from Carmack
// testifying to that fact...
// Here's how you do it, moron:
// setsize (self, '0 0 -10', '0 0 0');
setsize (self, '-16 -16 -24', '16 16 4');
self.view_ofs = '0 0 4';
self.movetype = MOVETYPE_TOSS;
if (type == 1) //CH normal feign
DeathSound();
self.angles_x = 0;
self.angles_z = 0;
// Check .weapon, because .current_weapon has been reset
if (self.weapon <= WEAP_AXE)
{
spy_die_ax1 ();
return;
}
i = 1 + floor(random()*6);
if (i == 1)
spy_diea1();
else if (i == 2)
spy_dieb1();
else if (i == 3)
spy_diec1();
else if (i == 4)
spy_died1();
else
spy_diee1();
}
};
//=========================================================================
// If its a net game, the SPY goes invisible.
// If its a LAN game, the class/skin changing menu pops up.
void() TeamFortress_SpyGoUndercover =
{
local entity te;
if (self.effects & (EF_DIMLIGHT | EF_BRIGHTLIGHT))
{
sprint(self, PRINT_MEDIUM, "You cannot disguise while glowing.\n");
return;
}
if (invis_only == TRUE)
{
// If the spy is already invisible, become visible
if (self.is_undercover == 1)
{
self.is_undercover = 0;
self.modelindex = modelindex_player; // return to normal
//WK self.items = self.items & ~IT_INVISIBILITY;
}
else if (self.is_undercover == 2)
{
sprint(self, PRINT_HIGH, "You stop going undercover.\n");
self.is_undercover = 0;
}
else // Become invisible
{
if (self.ammo_cells > 1)
{
sprint(self, PRINT_HIGH, "Going undercover...\n");
self.is_undercover = 2;
// Start a timer, which turns the player invisible when it ticks
te = spawn();
te.classname = "timer";
te.owner = self;
te.think = TeamFortress_SpyUndercoverThink;
te.nextthink = time + PC_SPY_GO_UNDERCOVER_TIME;
}
}
self.StatusRefreshTime = time + 0.1;
}
else
{
// Pop up the menu
if (self.is_undercover != 2)
{
self.current_menu = MENU_SPY;
self.menu_count = MENU_REFRESH_RATE;
}
else // if (self.is_undercover == 2)
{
//WK Fix TF2.5 bug
sprint(self, PRINT_HIGH, "You stop going undercover.\n");
if (self.undercover_team != 0 || self.undercover_skin != 0)
self.is_undercover = 1;
else
self.is_undercover = 0;
local entity ent = NIL;
while (ent = find (ent, classname, "timer")) {
if (ent.owner == self && ent.think == TeamFortress_SpyUndercoverThink) {
ent.think = SUB_Remove;
ent.nextthink = time + 0.1;
}
}
}
}
};
//=========================================================================
// Try and find the player's name who's skin and team closest fit the
// current disguise of the spy
void(entity spy) TeamFortress_SpyCalcName =
{
local entity te;
spy.undercover_name = "";
// Find a player on the team the spy is disguised as to pretend to be
if (spy.undercover_team != 0)
{
te = find(NIL, classname, "player");
while (te)
{
// First, try to find a player with same color and skins
if (te.team_no == spy.undercover_team && te.skin == spy.undercover_skin)
{
spy.undercover_name = te.netname;
te = NIL;
}
else
te = find(te, classname, "player");
}
// If we couldn't, just find one of that team
if (!spy.undercover_name)
{
te = find(NIL, classname, "player");
while (te)
{
if (te.team_no == spy.undercover_team)
{
spy.undercover_name = te.netname;
te = NIL;
}
else
te = find(te, classname, "player");
}
}
}
};
//=========================================================================
// Make the spy who owns this timer undercover, and then remove itself
void() TeamFortress_SpyUndercoverThink =
{
local float tc, tc2;
local string st;
if (!(self.owner.cutf_items & CUTF_SPY_KIT)) //WK
return;
if (self.owner.is_undercover == 2)
{
//WK self.owner.items = self.owner.items | IT_INVISIBILITY;
if (invis_only == TRUE)
{
self.owner.frame = 0;
self.owner.modelindex = modelindex_eyes;
self.owner.is_undercover = 1;
}
else
{
makeImmune(self.owner,time + 4);
//self.owner.immune_to_check = time + 4;
// Skin change?
if (self.skin != 0)
{
sprint(self.owner, PRINT_HIGH, "Skin set to ");
TeamFortress_PrintClassName(self.owner,self.skin,0);
self.owner.undercover_skin = self.skin;
TeamFortress_SetSkin(self.owner);
}
// Color change
if (self.team != 0)
{
sprint(self.owner, PRINT_HIGH, "Colors set to Team ");
st = ftos(self.team);
sprint(self.owner, PRINT_HIGH, st);
sprint(self.owner, PRINT_HIGH, "\n");
self.owner.undercover_team = self.team;
// Set their color
tc = TeamGetColor (self.team) - 1;
tc2 = TeamGetNiceColor (self.team);
SetPlayerColor (self.owner, tc, tc2);
}
TeamFortress_SpyCalcName(self.owner);
if (self.owner.StatusBarSize == 0)
CenterPrint(self.owner, "You are now disguised.\n");
self.owner.is_undercover = 1;
}
}
self.owner.StatusRefreshTime = time + 0.1;
//CH go to special bar :)
self.owner.StatusBarScreen = 2;
dremove(self);
};
//=========================================================================
// Change the Spy's skin to the class they chose
void(float class) TeamFortress_SpyChangeSkin =
{
local entity te;
// If they're returning their skin to their Spy, just reset it
if (class == PC_SPY && self.playerclass == PC_SPY) //WK
{
sprint (self, PRINT_HIGH, "Skin reset.");
self.undercover_skin = 0;
TeamFortress_SetSkin(self);
if (self.undercover_team == 0)
{
//WK self.items = self.items & ~IT_INVISIBILITY;
self.is_undercover = 0;
}
return;
}
sprint(self, PRINT_HIGH, "Going undercover...\n");
self.is_undercover = 2;
// Start a timer, which changes the spy's skin to the chosen one
te = spawn();
te.classname = "timer";
te.owner = self;
te.think = TeamFortress_SpyUndercoverThink;
te.nextthink = time + PC_SPY_GO_UNDERCOVER_TIME;
te.skin = class;
TeamFortress_SetSkin(self);
};
//=========================================================================
// Change the Spy's color to that of the Team they chose
void(float teamno) TeamFortress_SpyChangeColor =
{
local entity te;
local float tc, tc2;
// If they're returning their color to their own team, just reset it
if (teamno == self.team_no)
{
sprint (self, PRINT_HIGH, "Colors reset.\n");
makeImmune(self,time + 4);
//self.immune_to_check = time + 4;
self.undercover_team = 0;
tc = TeamGetColor (self.team_no) - 1;
tc2 = TeamGetNiceColor (self.team_no);
SetPlayerColor (self, tc, tc2);
if (self.undercover_skin == 0)
{
//WK self.items = self.items & ~IT_INVISIBILITY;
self.is_undercover = 0;
}
return;
}
sprint(self, PRINT_HIGH, "Going undercover...\n");
self.is_undercover = 2;
// Start a timer, which changes the spy's skin to the chosen one
te = spawn();
te.classname = "timer";
te.owner = self;
te.think = TeamFortress_SpyUndercoverThink;
te.nextthink = time + PC_SPY_GO_UNDERCOVER_TIME;
te.team = teamno;
};
//=========================================================================
// Gas Grenade touch function.
void() GasGrenadeTouch =
{
// 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';
};
//=========================================================================
// Gas grenade explosion. Throws up the particle cloud.
void() GasGrenadeExplode =
{
local entity te;
local float pos;
// Check the pointcontents to prevent detpack outside the world
pos = pointcontents(self.origin);
if (pos == CONTENTS_EMPTY)
{
te = spawn();
te.think = GasGrenadeMakeGas;
te.nextthink = time + 0.1;
te.heat = 0;
te.origin = self.origin;
te.owner = self.owner;
te.team_no = self.owner.team_no;
te.weapon = 0;
}
else
{
// Make some bubbles :)
pos = 0;
while (pos < 10)
{
newmis = spawn();
setmodel (newmis, "progs/s_bubble.spr");
setorigin (newmis, self.origin);
newmis.movetype = MOVETYPE_NOCLIP;
newmis.solid = SOLID_NOT;
newmis.velocity = '0 0 15';
newmis.velocity_z = 10 + (random() * 20);
newmis.nextthink = time + 0.5;
newmis.think = bubble_bob;
newmis.classname = "bubble";
newmis.frame = 0;
newmis.cnt = 0;
setsize (newmis, '-8 -8 -8', '8 8 8');
pos = pos + 1;
}
}
#ifdef DEMO_STUFF
// Remove any camera's locks on this missile
if (self.enemy)
CamProjectileLockOff();
#endif
dremove(self);
};
//=========================================================================
// Gas Grenade Gas function
void() GasGrenadeMakeGas =
{
local entity te, timer;
self.nextthink = time + 0.75;
// Do the Effects
te = findradius(self.origin, 200);
while (te)
{
if (te.classname == "player" && te.deadflag == DEAD_NO)
{
//Dont affect those with gas masks or invincible or biosuits
if (!(te.tf_items & NIT_SCUBA || te.invincible_finished > time || te.radsuit_finished > time)) //WK
{
// Damage
deathmsg = DMSG_GREN_GAS;
if (self.heat = 0)
TF_T_Damage (te, NIL, self.owner, 20, TF_TD_IGNOREARMOUR, TF_TD_OTHER);
else
TF_T_Damage (te, NIL, self.owner, 40, TF_TD_IGNOREARMOUR, TF_TD_OTHER);
// Make them hallucinate
if (te.tfstate & TFSTATE_HALLUCINATING)
{
// Already Hallucination, so just increase the time
timer = find(NIL, classname, "timer");
while (((timer.owner != te) || (timer.think != HallucinationTimer)) && (timer))
{
timer = find(timer, classname, "timer");
}
if (timer)
{
timer.health = timer.health + 50; //SB used to be 25
if (timer.health > 100)
timer.health = 100;
timer.nextthink = time + GR_HALLU_TIME;
}
}
else
{
sprint(te, PRINT_HIGH, "You stop breathing as the poison attacks your nerves...\n");
te.tfstate = te.tfstate | TFSTATE_HALLUCINATING;
// Create a timer entity
timer = spawn();
timer.nextthink = time + GR_HALLU_TIME;
timer.think = HallucinationTimer;
timer.classname = "timer";
timer.owner = te;
timer.health = 75; //WK 100 - this makes it more balanced
//SB 25 - this makes it more funner
timer.team_no = self.team_no;
}
} //WK --^
}
te = te.chain;
}
self.heat = self.heat + 1;
// Do the cloud
if (self.heat == 1)
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_TAREXPLOSION);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PVS);
return;
}
if (self.heat <= 3)
{
self.weapon = self.weapon + 1;
if (self.weapon == 1)
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_LAVASPLASH);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z - 24);
multicast (self.origin, MULTICAST_PVS);
}
else if (self.weapon == 2)
{
self.weapon = 0;
}
return;
}
dremove(self);
};
//=========================================================================
// Timer function for Hallucinations.
void() HallucinationTimer =
{
local entity te;
local float tmpx, tmpy, halltype;
// Setup for the next Think
self.health = self.health - GR_HALLU_DEC;
// medic recovers twice as fast
if (self.owner.weapons_carried & WEAP_MEDIKIT) //WK
self.health = self.health - GR_HALLU_DEC;
if (self.health <= 0)
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_HALLUCINATING);
if (!(self.owner.tfstate & TFSTATE_HALLUCINATING))
{
sprint(self.owner, PRINT_HIGH, "You feel a little better now.\n");
dremove(self);
return;
}
self.nextthink = time + GR_HALLU_TIME;
// Kick
if (random() < 0.5)
{
KickPlayer(-10, self.owner);
}
// Do the Hallucinations
tmpx = (random() * 800) - 400;
tmpy = (random() * 800) - 400;
halltype = random();
msg_entity = self.owner;
// Explosions
if (halltype < 0.4) //WK .4 We want all hallucination to be explosions. :)
{
WriteByte (MSG_ONE, SVC_TEMPENTITY);
if (halltype < 0.4)
WriteByte (MSG_ONE, TE_EXPLOSION);
else if (halltype < 0.6)
WriteByte (MSG_ONE, TE_TAREXPLOSION);
else // if (halltype < 0.4)
WriteByte (MSG_ONE, TE_LAVASPLASH);
WriteCoord (MSG_ONE, msg_entity.origin_x + tmpx);
WriteCoord (MSG_ONE, msg_entity.origin_y + tmpy);
WriteCoord (MSG_ONE, msg_entity.origin_z);
}
// Teleport
else if (halltype < 0.7)
{
WriteByte (MSG_ONE, SVC_TEMPENTITY);
WriteByte (MSG_ONE, TE_TELEPORT);
WriteCoord (MSG_ONE, msg_entity.origin_x + tmpx);
WriteCoord (MSG_ONE, msg_entity.origin_y + tmpy);
WriteCoord (MSG_ONE, msg_entity.origin_z);
}
// Lightning
else // if (halltype < 1)
{
te = spawn();
te.origin_x = msg_entity.origin_x + tmpx;
te.origin_y = msg_entity.origin_y + tmpy;
te.origin_z = msg_entity.origin_z;
WriteByte (MSG_ONE, SVC_TEMPENTITY);
WriteByte (MSG_ONE, TE_LIGHTNING2);
WriteEntity (MSG_ONE, te);
WriteCoord (MSG_ONE, te.origin_x);
WriteCoord (MSG_ONE, te.origin_y);
WriteCoord (MSG_ONE, te.origin_z);
tmpx = (random() * 800) - 400;
tmpy = (random() * 800) - 400;
WriteCoord (MSG_ONE, msg_entity.origin_x + tmpx);
WriteCoord (MSG_ONE, msg_entity.origin_y + tmpy);
WriteCoord (MSG_ONE, msg_entity.origin_z);
dremove(te);
}
};
//=========================================================================
// Firing Function for the Tranquiliser Gun
void() W_FireTranq =
{
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
KickPlayer(-2, self);
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
makevectors (self.v_angle);
newmis.velocity = v_forward;
newmis.velocity = newmis.velocity * 1500; // Faster than a normal nail WK 1500
newmis.angles = vectoangles(newmis.velocity);
newmis.touch = T_TranqDartTouch;
newmis.think = SUB_Remove;
newmis.nextthink = time + 6;
setmodel (newmis, "progs/spike.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
};
//=========================================================================
// Touch Function for the Tranquiliser Darts
void() T_TranqDartTouch =
{
local entity timer;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENTS_SKY)
{
dremove(self);
return;
}
//WK Sweep for mines at point of contact
GuerillaMineSweep(self.origin);
// hit something that bleeds
if (other.takedamage)
{
//WK Make sure they aren't immune
if (!(other.tf_items & NIT_SCUBA || other.invincible_finished > time || other.radsuit_finished > time))
{
spawn_touchblood (9);
deathmsg = DMSG_TRANQ;
// Do the Damage
TF_T_Damage (other, self, self.owner, 10, TF_TD_NOTTEAM, TF_TD_NAIL);
// If its a player or demon, tranquilise them
//- OfN if (other.classname == "monster_demon1" && !(Teammate(other.real_owner.team_no,self.owner.team_no) && (teamplay & (TEAMPLAY_HALFDIRECT | TEAMPLAY_NODIRECT))))
if (IsMonster(other))// && !(Teammate(other.real_owner.team_no,self.owner.team_no) && (teamplay & (TEAMPLAY_HALFDIRECT | TEAMPLAY_NODIRECT))))
{
//bprint(PRINT_HIGH, "demon tranq!\n");
// If they're already tranquilised, just make it last longer
if (other.tfstate & TFSTATE_TRANQUILISED)
{
timer = find(NIL, classname, "timer");
while (((timer.owner != other) || (timer.think != TranquiliserTimer2)) && (timer))
{
timer = find(timer, classname, "timer");
}
if (timer)
{
timer.nextthink = time + TRANQ_TIME;
}
}
else
{
other.tfstate = other.tfstate | TFSTATE_TRANQUILISED;
// Create a timer entity
timer = spawn();
timer.nextthink = time + TRANQ_TIME;
timer.think = TranquiliserTimer2;
timer.classname = "timer";
timer.owner = other;
timer.team_no = self.owner.team_no;
}
}
if (other.classname == "player" && !(Teammate(other.team_no, self.owner.team_no) && (teamplay & (TEAMPLAY_HALFDIRECT | TEAMPLAY_NODIRECT))))
{
// If they're already tranquilised, just make it last longer
if (other.tfstate & TFSTATE_TRANQUILISED)
{
timer = find(NIL, classname, "timer");
while (((timer.owner != other) || (timer.think != TranquiliserTimer)) && (timer))
{
timer = find(timer, classname, "timer");
}
if (timer)
{
timer.nextthink = time + TRANQ_TIME;
}
}
else
{
sprint(other, PRINT_HIGH, "You stop breathing...\n");
other.tfstate = other.tfstate | TFSTATE_TRANQUILISED;
// Create a timer entity
timer = spawn();
timer.nextthink = time + TRANQ_TIME;
timer.think = TranquiliserTimer;
timer.classname = "timer";
timer.owner = other;
timer.team_no = self.owner.team_no;
// now slow them down
TeamFortress_SetSpeed(other);
}
}
}
}
else
{
if (other.classname == "force_field") //- OfN - Makes field explosion b4 removing it
FieldExplosion(other,self.origin,self);
else
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_SPIKE);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PVS);
}
}
dremove(self);
};
//=========================================================================
// Think function for Tranquilisation.
// Just remove the player's tranquilisation.
void() TranquiliserTimer =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_TRANQUILISED);
TeamFortress_SetSpeed(self.owner);
sprint(self.owner, PRINT_HIGH, "You feel more alert now\n");
dremove(self);
};
//CH used for demons
void() TranquiliserTimer2 =
{
if (self.owner.tfstate & TFSTATE_TRANQUILISED) //Just in case
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_TRANQUILISED);
dremove(self);
};
// Reset spy skin and color or remove invisibility
void(entity spy) Spy_RemoveDisguise =
{
local float tc, tc2;
if (invis_only != TRUE)
{
if (spy.cutf_items & CUTF_SPY_KIT)
{
// Reset the Skin
if (spy.undercover_skin != 0)
{
//WK spy.items = spy.items & ~IT_INVISIBILITY;
makeImmune(spy,time + 4);
//spy.immune_to_check = time + 4;
spy.undercover_skin = 0;
spy.skin = 0;
TeamFortress_SetSkin(spy);
}
// Set their color
if (spy.undercover_team != 0)
{
//WK spy.items = spy.items - (spy.items & IT_INVISIBILITY);
makeImmune(spy,time + 4);
//spy.immune_to_check = time + 4;
spy.undercover_team = 0;
tc = TeamGetColor (spy.team_no) - 1;
tc2 = TeamGetNiceColor (spy.team_no);
SetPlayerColor (spy, tc, tc2);
}
spy.is_undercover = 0;
self.StatusRefreshTime = time + 0.1;
TeamFortress_SpyCalcName(spy);
}
}
else
{
if (spy.is_undercover)
{
// remove the invisibility
spy.is_undercover = 0;
spy.modelindex = modelindex_player; // return to normal
//WK if (spy.items & IT_INVISIBILITY)
//WK spy.items = spy.items & ~IT_INVISIBILITY;
self.StatusRefreshTime = time + 0.1;
}
}
};