mirror of
https://git.code.sf.net/p/quake/prozac-qfcc
synced 2024-11-10 15:21:51 +00:00
1116 lines
31 KiB
C++
1116 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;
|
|
float(entity p) Return_Custom_Skins;
|
|
|
|
// 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_ANYGLOW) {
|
|
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_ANYGLOW)
|
|
{
|
|
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 (!self.is_undercover)
|
|
{
|
|
self.undercover_team = 0;
|
|
self.undercover_skin = 0;
|
|
}
|
|
|
|
// If they're returning their skin to their Spy, just reset it
|
|
if (class == PC_SPY && (Return_Custom_Skins(self) == 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)
|
|
{
|
|
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 (!self.is_undercover) // prevent confusion
|
|
{
|
|
self.undercover_skin = 0;
|
|
self.undercover_team = 0;
|
|
}
|
|
|
|
// 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)
|
|
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;
|
|
}
|
|
}
|
|
};
|