prozac-qfcc/weapons.qc
Timothy C. McGrath c8157f4105 Fixed the lightning gun 'target bounces' bug. This was in the original quakec for customtf, but apparently never was being evaluated correctly
before someone fixed it for quakeforge aaaaandd.... IMHO, people shouldn't bounce into the air like they're on trampolines when you hit them
with the lightning gun :)

Also edited the way excess cells are discharged. No longer is there a cap on the minimum amount of cells that can be evaluted.
Original code made it so that if you had 101 cells and discharged it was the same as if you had 175... IMHO, not funny :)

Also, the excess cells output power is no longer dropped by a third of normal - I may change this back if there are problems with the lg
being too easy to kill people with excess cells... But then again, by nature excess cells are a one time shot - if you miss, they're gone.

Tim McGrath (Misty)
2002-05-13 16:12:26 +00:00

5157 lines
129 KiB
C++

/*======================================================
WEAPONS.QC Custom TeamFortress v3.1
(c) TeamFortress Software Pty Ltd 29/2/97
(c) William Kerney 5/21/00
========================================================
All the functions for firing all the weapons, holds
all new precache() functions, finding best weapons,
choosing next weapon, and all impulse commands.
======================================================*/
#include "defs.qh"
#include "menu.qh"
void() SniperSight_Update2; //CH for RL
void() I_DID_CHEAT_ONE; //CH for speed.qc
void() I_DID_CHEAT_TWO;
void() I_DID_CHEAT_THREE;
void(string gibname, float dm) ThrowGib;
void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
void (entity targ, entity inflictor, entity attacker, float damage, float T_flags, float T_AttackType) TF_T_Damage;
void () player_run;
void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
void() TeamFortress_DisplayDetectionItems;
vector(vector veca, vector vecb) crossproduct;
void(vector org, float damage) SpawnBlood;
void(entity rhook) Reset_Grapple;
void() SuperDamageSound;
float() W_BestWeapon;
void() ConcussionGrenadeTimer;
void() W_PrintWeaponMessage;
void() button_touch;
void() button_fire;
void() MauserRecoilThink;
float() ReturnWeaponVelocity;
vector() Grunty_LeadShot;
// TeamFortress Impulse Commands
void() TeamFortress_ChangeClass;
void() TeamFortress_DisplayLegalClasses;
void() TeamFortress_Inventory;
void() TeamFortress_SaveMe;
void(float inAuto) TeamFortress_ID;
void() TeamFortress_ShowTF;
void() TeamFortress_SniperWeapon;
void() TeamFortress_AssaultWeapon;
void() TeamFortress_IncendiaryCannon;
void() TeamFortress_FlameThrower;
void() TeamFortress_PrimeGrenade;
void() TeamFortress_ThrowGrenade;
void() TeamFortress_Discard;
void(entity p) TeamFortress_SetSpeed;
void() TeamFortress_DetonatePipebombs;
void() PipebombTouch;
void(float foo) TeamFortress_DetpackStop;
void(float type) SniperSight_Create;
void(float zoom_level) TF_zoom;
void() TeamFortress_ReloadCurrentWeapon;
void() TeamFortress_AutoZoomToggle;
void() TeamFortress_StatusQuery;
void() TeamFortress_SpyGoUndercover;
void(float type) TeamFortress_SpyFeignDeath;
void() TeamFortress_EngineerBuild;
void() DropKey;
void() UseSpecialSkill;
void() UseJobSkill; //WK Function for handling professions
void (entity targ, float pain) RevealThief;
void(vector startpos) GuerillaMineSweep;
void(entity foo,float bar) makeImmune;
float() CheckForReload;
void() SBBuildSensor;
void() SBFireInterface;
//void() SBInitiateInterface;
void() W_FireMauser;
void() W_FireDaedalus;
// TeamFortress Pre-Impulse Commands
void(float scanrange,float inAuto) TeamFortress_Scan;
void(float timer) TeamFortress_SetDetpack;
// Team Functions
float(float tno) TeamFortress_TeamSet;
void(float tno) TeamFortress_TeamShowScores;
void(entity Player) TeamFortress_TeamShowMemberClasses;
#ifdef DEMO_STUFF
// Camera Functions
void() CamLock;
void() CamDistLock;
void() CamVecLock;
void() CamAngleLock;
void() CamRevAngleLock;
void() CamProjectileLock;
void() CamProjectileZoom;
void() CamProjectileLockOn;
void() CamProjectileLockOff;
void() CamOffset;
void() CamDrop;
void() fadetoblack;
void() fadefromblack;
void() fadetowhite;
void() fadefromwhite;
#endif
// Engineer Functions
void(entity disp) Engineer_UseDispenser;
void(entity cam) Engineer_UseSensor;
void(entity gun) Engineer_UseSentryGun;
void(entity gun) Engineer_UseTesla;
void(entity cam) Engineer_UseCamera;
void(entity tele) Engineer_UseTeleporter;
void(entity field) Engineer_UseFieldGen;
void(entity spy) Spy_RemoveDisguise;
// Help functions
void() TeamFortress_MOTD;
void() TeamFortress_HelpMap;
void(float res) StatusRes;
// BioInfection functions
void() BioInfection_Decay;
void() BioInfection_MonsterDecay;
// Attacking functions
void() W_FireFlame;
void() W_FireIncendiaryCannon;
void() W_FireTranq;
void() W_FireLaser;
// Timer Functions
void() HallucinationTimer;
void() TranquiliserTimer;
// CTF Support functions
void() TeamFortress_CTF_FlagInfo;
// PC_UNDEFINED viewing functions
void() TF_MovePlayer;
//WK CustomTF Functions
void() custom_demon_precache;
void() custom_lay;
//void() CameraSwitchView;
//CH dropitems
void() TeamFortress_DropItems;
//- OfN -
void(entity player) ActivateHolo;
void(entity who) MakeMeDebug;
void(vector org, vector dir) grunty_spike;
void () UpdateInfos;
void() launch_horn;
void() player_laser1;
void(entity field) PutFieldWork;
void(entity tfield, vector where, entity thing) FieldExplosion;
// called by worldspawn
void() W_Precache =
{
precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
precache_sound ("weapons/rocket1i.wav"); // spike gun
precache_sound ("weapons/sgun1.wav");
precache_sound ("weapons/guncock.wav"); // player shotgun
precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
precache_sound ("weapons/ric2.wav"); // ricochet (used in c code)
precache_sound ("weapons/ric3.wav"); // ricochet (used in c code)
precache_sound ("weapons/spike2.wav"); // super spikes
precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
precache_sound ("weapons/grenade.wav"); // grenade launcher
precache_sound ("weapons/bounce.wav"); // grenade bounce
precache_sound ("weapons/shotgn2.wav"); // super shotgun
precache_sound ("wizard/wattack.wav"); // sniper rifle
precache_sound ("items/r_item1.wav"); // Medikit
precache_sound ("items/r_item2.wav"); // Medikit
precache_model ("progs/flame2.mdl"); // Flamethrower
precache_sound ("ambience/fire1.wav");
precache_sound2("blob/land1.wav"); // Hook
precache_model2("progs/v_spike.mdl"); // Hook
precache_sound ("hknight/hit.wav"); // Hook
// NEW FILES
precache_sound ("weapons/turrset.wav"); // Sentry Gun Setup
precache_sound ("weapons/turrspot.wav"); // Sentry Gun Spot
precache_sound ("weapons/turridle.wav"); // Sentry Gun Idle
precache_sound ("weapons/sniper.wav"); // sniper rifle
precache_sound ("weapons/flmfire2.wav"); // flamethrower
precache_sound ("weapons/flmgrexp.wav"); // flamethrower
precache_sound ("misc/vapeur2.wav"); // flamethrower
precache_sound ("weapons/asscan1.wav"); // Assault Cannon Powerup
precache_sound ("weapons/asscan2.wav"); // Assault Cannon Churning
precache_sound ("weapons/asscan3.wav"); // Assault Cannon Powerdown
precache_sound ("weapons/railgun.wav"); // Railgun
precache_sound ("weapons/dartgun.wav"); // Spy's dart gun
precache_sound ("ambience/thunder1.wav"); // Connect sound
//WK
//precache_model ("progs/v_merc.mdl"); //Carbine Model
//precache_sound ("weapons/carbfire.wav"); // Carbine shooting
//precache_sound ("weapons/carbreld.wav"); // Carbine shooting
//precache_sound ("weapons/carbrock.wav"); // Carbine shooting
//precache_sound ("weapons/nishi.wav"); // Nishi shooting
precache_model ("progs/telepad.mdl"); //Teleporter pad
precache_model ("progs/camera.mdl"); // Security Camera
precache_sound ("ambience/orff.wav"); // Chaplan sound
precache_sound ("weapons/guerilla_blip.wav"); // Landmine beep
precache_sound ("weapons/guerilla_set.wav"); // Landmine set
precache_sound ("weapons/camera_beep.wav"); // CH camera beep
precache_sound ("misc/enemy.wav"); // sensor alert
precache_sound ("weapons/fith.wav"); // WK Fire in the hole
//precache_model2("progs/guerilla_mine.mdl"); // The Landmine
//precache_model ("progs/tesla.mdl"); // The Tesla (by --Warrior--)
precache_model ("progs/minimissile.mdl"); // Swarm missile (BLOG)
//precache_model ("progs/newtesla.mdl"); // The Tesla (by --Warrior-- & BLOG)
precache_model ("progs/coil.mdl"); // The Tesla (by --Warrior-- & BLOG)
//precache_model ("progs/tscloak.mdl");
precache_model ("progs/tesgib1.mdl"); // Tesla Gib
precache_model ("progs/tesgib2.mdl"); // Tesla Gib
precache_model ("progs/tesgib3.mdl"); // Tesla Gib
precache_sound ("doors/medtry.wav"); //CH Dropping detpack sound
precache_sound ("doors/baseuse.wav"); //CH Detpack warning sound
precache_sound ("enforcer/sight1.wav"); // WK Taunt
precache_sound ("enforcer/sight2.wav"); // WK Taunt
precache_sound ("enforcer/sight3.wav"); // WK Taunt
precache_sound ("enforcer/sight4.wav"); // WK Taunt
custom_demon_precache();
};
float() crandom =
{
return 2*(random() - 0.5);
};
//======================================================================
// Calculate the attack_finished time
void(float att_delay) Attack_Finished =
{
if (self.tfstate & TFSTATE_TRANQUILISED)
self.attack_finished = time + (att_delay * 1.5);
else if (self.aura == AURA_HASTE)
self.attack_finished = time + (att_delay * 0.75);
else
self.attack_finished = time + att_delay;
};
/*
================
W_FireAxe
================
*/
void() W_FireAxe =
{
local vector source;
local vector org, def;
local vector dir = NIL; //XXX false +ve on uninit
if (self.classname == "player")
makevectors(self.v_angle);
else
dir = normalize (self.enemy.origin - self.origin);
source = self.origin + '0 0 16';
if (self.classname == "player")
{
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
traceline (source, source + v_forward*64, FALSE, self);
else
traceline (source, source + v_forward*96, FALSE, self);
}
else
traceline (source, source + dir*64, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.classname == "force_field")
{
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
return;
}
if (trace_ent.takedamage)
{
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
if (!(self.cutf_items & CUTF_KNIFE) || trace_ent.classname != "player")
{
deathmsg = DMSG_AXE;
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
TF_T_Damage (trace_ent, self, self, 30, TF_TD_NOTTEAM, TF_TD_OTHER);
else
TF_T_Damage (trace_ent, self, self, 60, TF_TD_NOTTEAM, TF_TD_OTHER);
}
else // spy can try for the backstab!
{
//WK Only give blood if you hit an enemy when being a warlock
if ((!Teammate(trace_ent.team_no, self.team_no) || !(self.job & JOB_WARLOCK)) && prematch < time)
{
self.job = self.job | JOB_BLOODY_KNIFE;
self.weaponmode = 1; // Put blood on the knife
self.weaponmodel = "progs/v_knife2.mdl";
}
else if (self.job & JOB_WARLOCK)
{
sprint(self,PRINT_HIGH,"You may only draw blood from enemies\n");
}
// Check direction of Attack
makevectors(trace_ent.v_angle);
def = v_right;
if (self.classname == "player")
makevectors(self.v_angle);
else
makevectors(self.angles);
// Backstab
if ((crossproduct(def,v_forward) * '0 0 1') > 0)
{
deathmsg = DMSG_BACKSTAB;
ThrowGib("progs/gib1.mdl", -50);
ThrowGib("progs/gib2.mdl", 10);
ThrowGib("progs/gib3.mdl", 50);
ThrowGib ("progs/gib2.mdl", 25); //-added
//WK 120 & no IGNOREARMOR
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
TF_T_Damage (trace_ent, self, self, 100, TF_TD_IGNOREARMOUR | TF_TD_NOTTEAM, TF_TD_OTHER);
else
TF_T_Damage (trace_ent, self, self, 200, TF_TD_IGNOREARMOUR | TF_TD_NOTTEAM, TF_TD_OTHER);
}
else
{
deathmsg = DMSG_AXE;
//WK 40
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
TF_T_Damage (trace_ent, self, self, 50, TF_TD_NOTTEAM, TF_TD_OTHER);
else
TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM, TF_TD_OTHER);
}
}
}
else
{ // hit wall
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
}
};
/*
================
W_FireSpanner
================
*/
void() W_FireSpanner =
{
local vector source;
local vector org;
local float healam;
local entity te;
makevectors(self.v_angle);
source = self.origin + '0 0 16';
if (self.cutf_items & CUTF_CLOSECOMBAT)
traceline (source, source + v_forward*96, FALSE, self);
else
traceline (source, source + v_forward*64, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.classname == "force_field")
{
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
deathmsg = DMSG_SPANNERFIELD;
TF_T_Damage(self, self, self, self.health + 50, TF_TD_IGNOREARMOUR, TF_TD_OTHER);
sound (self, CHAN_MISC, "effects/crunch.wav", 1, ATTN_NONE);
return;
}
// It may be a trigger that can be activated by the engineer's spanner
if (trace_ent.goal_activation & TFGA_SPANNER)
{
// Does the AP match the AP Criteria?
if (Activated(trace_ent,self))
{
DoResults(trace_ent, self, TRUE);
if (trace_ent.classname == "func_button")
{
trace_ent.enemy = self;
other = self;
self = trace_ent;
self.dont_do_triggerwork = TRUE; // Already done in DoResults
button_fire();
self = other;
}
}
else
{
// If an else goal should be activated, activate it
if (trace_ent.else_goal != 0)
{
te = Findgoal(trace_ent.else_goal);
if (te)
DoResults(te, self, (trace_ent.goal_result & TFGR_ADD_BONUSES));
}
else
{
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
}
}
return;
}
if (trace_ent.takedamage)
{
// Engineer can repair/use his buildings
if (trace_ent.classname == "building_dispenser")
{
Engineer_UseDispenser(trace_ent);
return;
}
else if (trace_ent.classname == "building_sentrygun")
{
Engineer_UseSentryGun(trace_ent);
return;
}
else if (trace_ent.classname == "building_sentrygun_base")
{
if (trace_ent.oldenemy)
Engineer_UseSentryGun(trace_ent.oldenemy);
return;
}
else if (trace_ent.classname == "building_tesla")
{
Engineer_UseTesla(trace_ent);
return;
}
else if (trace_ent.classname == "building_camera")
{
Engineer_UseCamera(trace_ent);
return;
}
else if (trace_ent.classname == "building_sensor")
{
Engineer_UseSensor(trace_ent);
return;
}
else if (trace_ent.classname == "building_teleporter")
{
Engineer_UseTeleporter(trace_ent);
return;
}
else if (trace_ent.classname == "building_fieldgen")
{
Engineer_UseFieldGen(trace_ent);
return;
}
else
{
if (trace_ent.classname == "player")
{
if (Teammate(trace_ent.team_no, self.team_no) && (teamplay) || (coop))
{
healam = WEAP_SPANNER_REPAIR;
if (self.ammo_cells < healam)
healam = self.ammo_cells;
// Only fix armor if they've got some
if (trace_ent.armor_allowed == 0) //WK
return;
if (trace_ent.armorvalue <= 0) // SB
return;
if (trace_ent.maxarmor - trace_ent.armorvalue < (healam * 4))
healam = ceil((trace_ent.maxarmor - trace_ent.armorvalue) / 4);
if (healam > 0)
{
trace_ent.armorvalue = trace_ent.armorvalue + (healam * 4);
if (trace_ent.armorvalue > trace_ent.maxarmor)
trace_ent.armorvalue = trace_ent.maxarmor;
//WK Give them full armor color
trace_ent.armortype = trace_ent.armor_allowed;
self.ammo_cells = self.ammo_cells - healam;
sound(trace_ent, CHAN_WEAPON, "items/r_item1.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
W_SetCurrentAmmo ();
}
return;
}
}
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
deathmsg = DMSG_SPANNER;
//WK 20
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
TF_T_Damage (trace_ent, self, self, 20, TF_TD_NOTTEAM, TF_TD_OTHER);
else
TF_T_Damage (trace_ent, self, self, 40, TF_TD_NOTTEAM, TF_TD_OTHER);
}
}
else // hit wall
{
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
}
};
/*
================
W_FireMedikit
================
*/
void(entity ignore, entity ignore2, string st, string st2, string st3, string st4, string st5, string st6) teamsprintbi;
void(float tno, entity ignore, entity ignore2) teamprefixsprintbi;
void(float inAuto) W_FireMedikit =
{
local vector source;
local vector org;
local float healam;
local entity te, BioInfection;
source = self.origin + '0 0 16';
if (self.cutf_items & CUTF_CLOSECOMBAT)
traceline (source, source + v_forward*96, FALSE, self);
else
traceline (source, source + v_forward*64, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.takedamage)
{
if (trace_ent.classname == "player")
{
if (Teammate(trace_ent.team_no, self.team_no) || (coop))
{
healam = WEAP_MEDIKIT_HEAL;
// remove concussion from player
// Try to find a concusstimer entity for this player
te = find(NIL, classname, "timer");
while (((te.owner != trace_ent) || (te.think != ConcussionGrenadeTimer)) && (te))
{
te = find(te, classname, "timer");
}
if (te)
{
stuffcmd(trace_ent ,"v_idlescale 0\n");
SpawnBlood(org, 20);
sprint(trace_ent, PRINT_HIGH, "you have been healed of your concussion\n");
// Give the medic a frag for doing it, only if it was caused by an enemy
if (!Teammate(self.team_no,te.team_no))
{
self.real_frags = self.real_frags + 1;
if (!(toggleflags & TFLAG_TEAMFRAGS))
self.frags = self.real_frags;
}
dremove(te);
}
// remove hallucination from player
// Try to find a hallucination timer entity for this player
if (trace_ent.tfstate & TFSTATE_HALLUCINATING)
{
te = find(NIL, classname, "timer");
while (((te.owner != trace_ent) || (te.think != HallucinationTimer)) && (te))
{
te = find(te, classname, "timer");
}
if (te)
{
trace_ent.tfstate = trace_ent.tfstate - (trace_ent.tfstate & TFSTATE_HALLUCINATING);
SpawnBlood(org, 20);
sprint(trace_ent, PRINT_HIGH, "you have been healed of your hallucinations\n");
// Give the medic a frag for doing it, only if it was caused by an enemy
if (!Teammate(self.team_no,te.team_no))
{
self.real_frags = self.real_frags + 1;
if (!(toggleflags & TFLAG_TEAMFRAGS))
self.frags = self.real_frags;
}
dremove(te);
}
else
{
RPrint("Warning: Error in Hallucination Timer logic.\n");
}
}
// remove tranquilisation from player
// Try to find a tranquilisation timer entity for this player
if (trace_ent.tfstate & TFSTATE_TRANQUILISED)
{
te = find(NIL, classname, "timer");
while (((te.owner != trace_ent) || (te.think != TranquiliserTimer)) && (te))
{
te = find(te, classname, "timer");
}
if (te)
{
trace_ent.tfstate = trace_ent.tfstate - (trace_ent.tfstate & TFSTATE_TRANQUILISED);
TeamFortress_SetSpeed(trace_ent);
SpawnBlood(org, 20);
sprint(trace_ent, PRINT_HIGH, "you have been healed of your tranquilisation\n");
// Give the medic a frag for doing it, only if it was caused by an enemy
if (!Teammate(self.team_no,te.team_no))
{
self.real_frags = self.real_frags + 1;
if (!(toggleflags & TFLAG_TEAMFRAGS))
self.frags = self.real_frags;
}
dremove(te);
}
else
{
RPrint("Warning: Error in Tranquilisation Timer logic.\n");
}
}
// check if the healed player is blinded
if (trace_ent.FlashTime > 0)
{
te = find(NIL, netname, "flashtimer");
while ((te.owner != trace_ent || te.classname != "timer") && (te))
te = find(te, netname, "flashtimer");
if (te)
{
trace_ent.FlashTime = 0;
SpawnBlood(org, 20);
// Give the medic a frag for doing it, only if it was caused by an enemy
stuffcmd(trace_ent, "v_cshift 0\n"); //WK -- /CH te -> trace_ent
stuffcmd(trace_ent, "r_norefresh 0;wait;echo;wait;echo;wait;echo;wait;echo\n"); //WK -- /CH te -> trace_ent
if (!Teammate(self.team_no,te.team_no))
{
self.real_frags = self.real_frags + 1;
if (!(toggleflags & TFLAG_TEAMFRAGS))
self.frags = self.real_frags;
}
dremove(te);
}
else
{
RPrint("Warning: Error in Flash Timer logic.\n");
trace_ent.FlashTime = 0;
}
}
// check if the healed player is infected
if (trace_ent.tfstate & TFSTATE_INFECTED)
{
healam = rint(trace_ent.health / 2);
// remove the infection
trace_ent.tfstate = trace_ent.tfstate - (trace_ent.tfstate & TFSTATE_INFECTED);
// some damage is caused (because of the use of leeches!)
// remove half their remaining health
deathmsg = DMSG_MEDIKIT;
T_Damage(trace_ent, self, self, healam);
SpawnBlood(org, 30);
sprint(trace_ent, PRINT_HIGH,self.netname);
sprint(trace_ent, PRINT_HIGH, " cures your infection!\n");
if (self.classname == "player")
{
sprint(self, PRINT_HIGH, "You have healed ");
sprint(self, PRINT_HIGH, trace_ent.netname);
sprint(self, PRINT_HIGH, " of the infection.\n");
teamprefixsprintbi(self.team_no,self,trace_ent);
teamsprintbi(self,trace_ent,trace_ent.netname," infection has been cured by ",self.netname,"\n","","");
// Give the medic a frag for doing it, only if it was caused by an enemy
if (!Teammate(trace_ent.infection_team_no, self.team_no))
{
self.real_frags = self.real_frags + 1;
if (!(toggleflags & TFLAG_TEAMFRAGS))
self.frags = self.real_frags;
}
}
return;
}
// put out the fire if they are burning
if (trace_ent.numflames > 0)
{
sound(trace_ent, CHAN_WEAPON, "items/r_item1.wav", 1, ATTN_NORM);
trace_ent.numflames = 0;
sprint(trace_ent, PRINT_HIGH, "The flames have been doused!\n");
if (self.classname == "player")
{
sprint(self, PRINT_MEDIUM, "You have put out ");
sprint(self, PRINT_MEDIUM, trace_ent.netname);
sprint(self, PRINT_MEDIUM, "'s fire.\n");
}
return;
}
if (healam > 0 && trace_ent.health < trace_ent.max_health)
{
sound(trace_ent, CHAN_WEAPON, "items/r_item1.wav", 1, ATTN_NORM);
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
T_Heal(trace_ent, healam, 0);
}
else if (trace_ent.health >= trace_ent.max_health && trace_ent.health < (trace_ent.max_health + WEAP_MEDIKIT_OVERHEAL))
{
healam = 10;
if (healam > (self.ammo_medikit * 10))
healam = (self.ammo_medikit * 10);
if (healam > 0)
{
sound(trace_ent, CHAN_ITEM, "items/r_item2.wav", 1, ATTN_NORM);
T_Heal(trace_ent, healam, 1);
self.ammo_medikit = self.ammo_medikit - rint(healam / 10);
if (!(trace_ent.items & IT_SUPERHEALTH))
{
trace_ent.items = trace_ent.items | IT_SUPERHEALTH;
newmis = spawn();
newmis.classname = "medikit_rot";
newmis.nextthink = time + 20;
newmis.think = item_megahealth_rot;
newmis.owner = trace_ent;
}
}
}
}
#ifdef MEDIKIT_IS_BIOWEAPON
//WK Don't infect if they're invincible or observing
else if (!(trace_ent.invincible_finished) && !(trace_ent.playerclass == PC_UNDEFINED))
{
if (inAuto)
return;
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
deathmsg = DMSG_BIOWEAPON_ATT;
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
T_Damage (trace_ent, self, self, 10);
else
T_Damage (trace_ent, self, self, 20);
if (trace_ent.weapons_carried & WEAP_MEDIKIT) //WK
return;
//Melee armor stops infection 75% of the time
if (trace_ent.tf_items & NIT_GEL && random() < 0.75)
return;
trace_ent.tfstate = trace_ent.tfstate | TFSTATE_INFECTED;
BioInfection = spawn ();
BioInfection.classname = "timer";
BioInfection.netname = "biotimer";
BioInfection.owner = trace_ent;
BioInfection.nextthink = time + 2;
BioInfection.think = BioInfection_Decay;
BioInfection.enemy = self;
trace_ent.infection_team_no = self.team_no;
}
#endif
}
else if (IsMonster(trace_ent))//- OfN - //|| trace_ent.classname == "monster_fish")
{
if (Teammate(trace_ent.real_owner.team_no, self.team_no))
{
if (trace_ent.health < trace_ent.max_health)
{
if (trace_ent.max_health - trace_ent.health < 50)
healam = trace_ent.max_health - trace_ent.health;
else
healam = 50;
if (healam > self.ammo_medikit)
healam = self.ammo_medikit;
if (healam == 0)
return;
sound(trace_ent, CHAN_WEAPON, "items/r_item1.wav", 1, ATTN_NORM);
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
T_Heal(trace_ent, healam, 0);
self.ammo_medikit = self.ammo_medikit - healam;
if (trace_ent.health > trace_ent.max_health)
trace_ent.health = trace_ent.max_health;
}
}
} else {
trace_ent.axhitme = 1;
SpawnBlood (org, 30);
T_Damage (trace_ent, self, self, 10);
}
}
else
{
if (inAuto) return; //Don't click for automedic
// hit wall
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
}
};
/*
================
W_FireBioweapon
================
*/
void() W_FireBioweapon =
{
local vector source;
local vector org;
local entity BioInfection;
source = self.origin + '0 0 16';
traceline (source, source + v_forward*64, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.takedamage)
{
if (trace_ent.classname == "player")
{
if ((!Teammate(trace_ent.team_no, self.team_no) && teamplay) || teamplay == 0)
{
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
deathmsg = DMSG_BIOWEAPON_ATT;
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
T_Damage (trace_ent, self, self, 10);
else
T_Damage (trace_ent, self, self, 20);
if (trace_ent.weapons_carried & WEAP_MEDIKIT) //WK
return;
trace_ent.tfstate = trace_ent.tfstate | TFSTATE_INFECTED;
BioInfection = spawn ();
BioInfection.classname = "timer";
BioInfection.netname = "biotimer";
BioInfection.owner = trace_ent;
BioInfection.nextthink = time + 2;
BioInfection.think = BioInfection_Decay;
BioInfection.enemy = self;
trace_ent.infection_team_no = self.team_no;
}
}
else if (trace_ent.flags & FL_MONSTER)
{
if (trace_ent.classname == "monster_zombie")
{
// zombie slayer!
T_Damage (trace_ent, self, self, 200);
}
trace_ent.axhitme = 1;
SpawnBlood(org, 20);
if (!(self.cutf_items & CUTF_CLOSECOMBAT))
T_Damage (trace_ent, self, self, 10);
else
T_Damage (trace_ent, self, self, 20);
BioInfection = spawn ();
BioInfection.classname = "timer";
BioInfection.classname = "biotimer";
BioInfection.nextthink = time + 2;
BioInfection.think = BioInfection_MonsterDecay;
BioInfection.owner = self;
BioInfection.enemy = trace_ent;
}
else // must be a switch
{
trace_ent.axhitme = 1;
SpawnBlood (org, 30);
T_Damage(trace_ent, self, self, 40);
}
}
else
{ // hit wall
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
}
};
//============================================================================
vector() wall_velocity =
{
local vector vel;
vel = normalize (self.velocity);
vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
vel = vel + 2*trace_plane_normal;
vel = vel * 200;
return vel;
};
/*
================
SpawnMeatSpray
================
*/
void(vector org, vector vel) SpawnMeatSpray =
{
local entity missile;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_NOT;
makevectors (self.angles);
missile.velocity = vel;
missile.velocity_z = missile.velocity_z + 250 + 50*random();
missile.avelocity = '3000 1000 2000';
// set missile duration
missile.nextthink = time + 1;
missile.think = SUB_Remove;
setmodel (missile, "progs/zom_gib.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, org);
};
/*
================
SpawnBlood
================
*/
void(vector org, float damage) SpawnBlood =
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_BLOOD);
WriteByte (MSG_MULTICAST, 1);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PVS);
};
/*
================
spawn_touchblood
================
*/
void(float damage) spawn_touchblood =
{
local vector vel;
vel = wall_velocity () * 0.2;
SpawnBlood (self.origin + vel*0.01, damage);
};
/*
================
SpawnChunk
================
*/
void(vector org, vector vel) SpawnChunk =
{
particle (org, vel*0.02, 0, 10);
};
/*
==============================================================================
MULTI-DAMAGE
Collects multiple small damages into a single damage
==============================================================================
*/
entity multi_ent;
float multi_damage;
vector blood_org;
float blood_count;
vector puff_org;
float puff_count;
void() ClearMultiDamage =
{
multi_ent = NIL;
multi_damage = 0;
blood_count = 0;
puff_count = 0;
};
void() ApplyMultiDamage =
{
if (!multi_ent)
return;
// don't set deathmsg here, since it'll be set by the weapon that fired
if (self.current_weapon & WEAP_LIGHT_ASSAULT)
TF_T_Damage (multi_ent, self, self, multi_damage, TF_TD_NOTTEAM, TF_TD_NAIL);
else
TF_T_Damage (multi_ent, self, self, multi_damage, TF_TD_NOTTEAM, TF_TD_SHOT);
};
void(entity hit, float damage) AddMultiDamage =
{
if (!hit)
return;
if (hit != multi_ent)
{
ApplyMultiDamage ();
multi_damage = damage;
multi_ent = hit;
}
else
multi_damage = multi_damage + damage;
};
void (integer big) Multi_Finish =
{
if (puff_count)
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, big ? puff_count * 2 : puff_count);
WriteCoord (MSG_MULTICAST, puff_org_x);
WriteCoord (MSG_MULTICAST, puff_org_y);
WriteCoord (MSG_MULTICAST, puff_org_z);
multicast (puff_org, MULTICAST_PVS);
}
if (blood_count)
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_BLOOD);
WriteByte (MSG_MULTICAST, big ? blood_count * 2 : puff_count);
WriteCoord (MSG_MULTICAST, blood_org_x);
WriteCoord (MSG_MULTICAST, blood_org_y);
WriteCoord (MSG_MULTICAST, blood_org_z);
multicast (puff_org, MULTICAST_PVS);
}
};
/*
==============================================================================
BULLETS
==============================================================================
*/
/*
================
TraceAttack
================
*/
void (float damage, vector dir) TraceAttack =
{
local vector vel, org;
vel = normalize (dir + v_up * crandom() + v_right * crandom());
vel = vel + 2 * trace_plane_normal;
vel = vel * 200;
org = trace_endpos - v_forward * 4;
//WK Sweep mines at the end of the attack
GuerillaMineSweep (trace_endpos);
if (damage && trace_ent.takedamage) {
blood_org = org;
blood_count++;
AddMultiDamage (trace_ent, damage);
} else {
puff_org = org;
puff_count++;
if (trace_ent.classname == "force_field") { //- OfN - Makes field explosion b4 removing it
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
}
}
};
/*
================
FireBullets
Used by shotgun, super shotgun, assault cannon, and enemy soldier firing
Go to the trouble of combining multiple pellets into a single damage call.
================
*/
void(float shotcount, vector dir, vector spread) FireBullets =
{
local vector direction;
local vector src;
makevectors (self.v_angle);
src = self.origin + v_forward * 10;
src_z = self.absmin_z + self.size_z * 0.7;
ClearMultiDamage ();
while (shotcount > 0)
{
direction = dir;
direction += AVG (crandom(), crandom()) * spread_x * v_right;
direction += AVG (crandom(), crandom()) * spread_y * v_up;
if (self.current_weapon & WEAP_ASSAULT_CANNON)
traceline (src, src + direction * 2048, FALSE, self);
else
traceline (src, src + direction * 1024, FALSE, self);
if (trace_fraction == 1.0)
TraceAttack (0, direction);
else if (self.current_weapon & WEAP_ASSAULT_CANNON) //WK Sinth's bugfix
TraceAttack (8, direction); //WK(12) (6) Reversed from 2.5
else if (self.current_weapon & WEAP_LIGHT_ASSAULT)
TraceAttack (3, direction);
else
TraceAttack (6, direction); //WK 4
shotcount--;
}
ApplyMultiDamage ();
Multi_Finish (TRUE);
};
/*
================
W_FireShotgun
================
*/
void() W_FireShotgun =
{
local vector dir;
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
if (self.classname == "player")
KickPlayer(-2, self);
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
if (self.classname == "player")
dir = aim (self, 100000);
else
{
dir = self.enemy.origin - self.enemy.velocity * (0.08 / self.has_sensor);
dir = normalize (dir - self.origin);
}
deathmsg = DMSG_SHOTGUN;
FireBullets (6, dir, '0.02 0.02 0');
};
/*
================
W_FireSuperShotgun
================
*/
void() W_FireSuperShotgun =
{
local vector dir;
if (self.currentammo == 1)
{
W_FireShotgun ();
return;
}
sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
if (self.classname == "player")
KickPlayer(-4, self);
self.currentammo = self.ammo_shells = self.ammo_shells - 2;
if (self.classname == "player")
dir = aim (self, 100000);
else
{
dir = self.enemy.origin - self.enemy.velocity * (0.08 / self.has_sensor);
dir = normalize (dir - self.origin);
}
deathmsg = DMSG_SSHOTGUN;
FireBullets (6, dir, '0.05 0.05 0'); //WK 14, 0.14, 0.08
FireBullets (6, dir, '0.05 0.05 0');
};
/*
================
FireSniperBullet
Used by sniper rifle firing (W_FireSniperRifle)
================
*/
void(vector direction, float damage) FireSniperBullet =
{
local vector src;
makevectors (self.v_angle);
src = self.origin + v_forward * 10;
src_z = self.absmin_z + self.size_z * 0.7;
ClearMultiDamage ();
traceline (src, src + direction * 4096, FALSE, self);
if (trace_fraction == 1.0)
TraceAttack (0, direction);
else
TraceAttack (damage, direction);
ApplyMultiDamage ();
Multi_Finish (FALSE);
};
/*
=================================
TeamFortress : W_FireSniperRifle
=================================
*/
void() W_FireSniperRifle =
{
local vector dir, src;
local float dam_mult, zdif, use_this;
sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM);
KickPlayer(-2, self);
//self.currentammo = self.ammo_shells = self.ammo_shells - 1; // ofn moved!
makevectors(self.v_angle);
src = self.origin + v_forward * 10;
src_z = self.absmin_z + self.size_z * 0.7;
dir = v_forward; //XXX is this correct?
use_this = FALSE;
traceline (src, src + dir*8092, FALSE, self);
if (trace_fraction != 1.0)
{
if (trace_ent)
{
if (trace_ent.classname == "player")
{
use_this = TRUE;
}
}
}
KickPlayer(-4, self);
if (!use_this)
{
// aim, 'cause no entity in sights
dir = aim (self, 10000); // this corrects the aiming slightly, for bad players
traceline (src, src + dir*3072, FALSE, self);
}
deathmsg = DMSG_SNIPERRIFLE;
dam_mult = 1;
//- OfN - float factor to handle OTR bullets difference
local float is_OTR; // factor of dmg 1 no otr, >1 yes
is_OTR=1;
if (self.cutf_items & CUTF_OTR && self.ammo_shells > 2)
{
is_OTR = OTR_DMGFACTOR;
self.currentammo = self.ammo_shells = self.ammo_shells - 3;
}
else
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
dam_mult=dam_mult*is_OTR;
if (trace_ent)
{
if (trace_ent.classname == "player")
{
local float x;
local vector f, g, h;
f = trace_endpos - src;
g_x = trace_endpos_x;
g_y = trace_endpos_y;
g_z = 0;
h_x = trace_ent.origin_x;
h_y = trace_ent.origin_y;
h_z = 0;
x = vlen(g - h);
f = (normalize(f) * x) + trace_endpos;
zdif = f_z - trace_ent.origin_z;
deathmsg = DMSG_SNIPERRIFLE;
trace_ent.head_shot_vector = '0 0 0';
if (zdif < 0)
{
// leg shot
dam_mult = 0.75;
trace_ent.leg_damage = trace_ent.leg_damage + 1;
//- OfN - OTR bullets do twice damage ----------//
if (self.cutf_items & CUTF_OTR)
{
dam_mult=dam_mult*is_OTR;
trace_ent.leg_damage = trace_ent.leg_damage + 1;
}
TeamFortress_SetSpeed(trace_ent);
deathmsg = DMSG_SNIPERLEGSHOT;
//WK Kevlar ignored for snipers again.
TF_T_Damage (trace_ent, self, self, self.heat * dam_mult, 0, 0);
if (trace_ent.health > 0)
{
if (is_OTR > 1) {
sprint(trace_ent, PRINT_MEDIUM, "Leg injury! That was OTR stuff!\n");
sprint(self, PRINT_MEDIUM, "OTR Leg shot - that'll slow him down!\n");
} else { //- not OTR..
sprint(trace_ent, PRINT_MEDIUM, "Leg injury!\n");
sprint(self, PRINT_MEDIUM, "Leg shot - that'll slow him down!\n");}
}
return;
}
else if (zdif > 20)
{
// head shot
dam_mult = 2;
//- OfN - OTR bullets do twice damage
dam_mult=dam_mult*is_OTR;
stuffcmd(trace_ent, "bf\n");
trace_ent.head_shot_vector = trace_ent.origin - self.origin;
deathmsg = DMSG_SNIPERHEADSHOT;
TF_T_Damage (trace_ent, self, self, self.heat * dam_mult, 0, TF_TD_SHOT);
if (trace_ent.health > 0)
{
if (is_OTR > 1) {
sprint(trace_ent, PRINT_MEDIUM, "Head injury! That was OTR stuff!\n");
sprint(self, PRINT_MEDIUM, "OTR Head shot - that's gotta hurt!\n");
} else {
sprint(trace_ent, PRINT_MEDIUM, "Head injury!\n");
sprint(self, PRINT_MEDIUM, "Head shot - that's gotta hurt!\n");}
}
return;
}
else
deathmsg = DMSG_SNIPERRIFLE;
}
}
ClearMultiDamage ();
if (trace_fraction == 1.0)
TraceAttack (0, dir);
else // if it hit something
TraceAttack (self.heat * dam_mult, dir);
ApplyMultiDamage ();
Multi_Finish (FALSE);
};
/*
===================================
TeamFortress : W_FireAutoRifle
===================================
*/
void() W_FireAutoRifle =
{
local vector dir;
sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM);
KickPlayer(-1, self);
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
makevectors(self.v_angle);
dir = v_forward;
deathmsg = DMSG_AUTORIFLE;
FireSniperBullet (dir, 8);
};
/*
================
TeamFortress : W_FireAssaultCannon
================
*/
void() W_FireAssaultCannon =
{
local vector dir;
KickPlayer(-4, self);
//WK Judoka's usually don't have enough ammo to shoot this thing...
if (!(self.job & JOB_JUDOKA && self.job & JOB_ACTIVE))
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
dir = aim (self, 100000);
deathmsg = DMSG_ASSAULTCANNON;
FireBullets (5, dir, '0.15 0.10 0');
//We want more of a cone of fire...
// FireBullets (5, dir, '0.2 0.1 0');
// FireBullets (5, dir, '0.4 0.1 0');
// FireBullets (7, dir, '0.16 0.12 0');
// FireBullets (3, dir, '0.12 0.09 0');
};
/*
=========================================
Custom TeamFortress : W_FireLightAssault
=========================================
*/
void() W_FireLightAssault =
{
local vector dir;
if (self.ammo_nails < 1)
{
self.current_weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
return;
}
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 0.6, ATTN_NORM);
KickPlayer(-4, self);
makevectors(self.v_angle);
dir = v_forward;
deathmsg = DMSG_LIGHT_ASSAULT;
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
self.reload_light_assault = self.reload_light_assault + 1;
if (CheckForReload() == TRUE) return;
FireBullets (5, dir, '0.15 0.10 0');
Attack_Finished(0.2);
};
/*
==============================================================================
ROCKETS
==============================================================================
*/
void() s_explode1 = [0, s_explode2] {};
void() s_explode2 = [1, s_explode3] {};
void() s_explode3 = [2, s_explode4] {};
void() s_explode4 = [3, s_explode5] {};
void() s_explode5 = [4, s_explode6] {};
void() s_explode6 = [5, SUB_Remove] {};
void() BecomeExplosion =
{
dremove(self);
};
void() T_MissileTouch =
{
local float damg;
local float bonus;
if (other.classname == "player" && other.playerclass == PC_UNDEFINED)
return;
if (pointcontents(self.origin) == CONTENTS_SKY)
{
dremove(self);
return;
}
// Lowered from 120
damg = 92;
if (self.owner.classname == "trap_shooter" || self.owner.classname == "trap_spikeshooter" || self.owner.classname == "trap_tf_spikeshooter" || self.owner.classname == "trap_tf_shooter")
if (self.owner.dmg != 0)
damg = self.owner.dmg;
/*
if (self.owner)
if (self.owner.tf_items & NIT_RL_LASER_SIGHT) {
//RPrint("Laser rocket hit!\n");
damg = damg - 10;
}
*/
if (self.has_tesla) //Cluster rockets do less
damg = damg - 25;
deathmsg = self.weapon;
if (other.health)
{
bonus = 10 + random()*20;
if (self.has_tesla)
bonus = 0;
TF_T_Damage (other, self, self.owner, damg+bonus, 0, TF_TD_EXPLOSION);
}
// don't do radius damage to the other, because all the damage
// was done in the impact
// Lowered from 120
T_RadiusDamage (self, self.owner, damg, other);
self.origin = self.origin - 8*normalize(self.velocity);
#ifdef DEMO_STUFF
// Remove any camera's locks on this missile
if (self.enemy)
CamProjectileLockOff();
#endif
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PHS);
if (other.classname == "force_field") //- OfN - Makes field explosion b4 removing it
FieldExplosion(other,self.origin,self);
dremove(self);
};
//CH rocket tracker (taken from shalrath.qc)
void() Rocket_Track_Dot =
{
if (time > self.has_sentry) {
self.think = SUB_Remove;
}
else
{
local vector dir, vtemp;
local entity tg, sight;
sight = NIL;
tg = find (NIL, classname, "timer");
while (tg)
{
if (tg.owner == self.owner && tg.think == SniperSight_Update2)
sight = tg;
tg = find(tg, classname, "timer");
}
if (sight) //Found a sight
{
vtemp = sight.origin;
dir = normalize(vtemp - self.origin);
//if (self.owner.cluster_mode && !(self.has_tesla)) //Slow down main rocket
// self.velocity = dir * 500;
//else
if (self.owner.cluster_mode)
self.velocity = dir * 600;
else
self.velocity = dir * 900;
self.angles = vectoangles(self.velocity);
self.think = Rocket_Track_Dot;
//WK Add in cluster munitions support
if (self.has_tesla) { //We're a cluster, so act crazy
makevectors(self.angles);
self.v_angle = sight.origin; //Save last direction for losing sight
self.velocity = self.velocity + 300 * v_right * (random() - 0.5);
self.velocity = self.velocity + 300 * v_up * (random() - 0.5);
}
}
else { //Lost sight of sight
if (self.has_tesla && self.v_angle != '0 0 0') {
vtemp = self.v_angle;
dir = normalize(vtemp - self.origin);
if (self.owner.cluster_mode && !(self.has_tesla)) //Slow down main rocket
self.velocity = dir * 900;
else
self.velocity = dir * 1000;
self.angles = vectoangles(self.velocity);
self.think = Rocket_Track_Dot;
makevectors(self.angles);
self.velocity = self.velocity + 300 * v_right * (random() - 0.5);
self.velocity = self.velocity + 300 * v_up * (random() - 0.5);
}
// self.velocity = 1000 * normalize(self.v_angle);
}
}
self.nextthink = time + 0.25;
};
/*
================
W_FireRocket
================
*/
void() W_FireRocket =
{
local float loops;
local vector olorigin, dir = NIL; //XXX false +ve for dir
loops = 0;
if (self.tf_items & NIT_CLUSTER_ROCKETS && self.cluster_mode == TRUE)
loops = 5;
while (loops >= 0) {
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
if (self.ammo_rockets < 0) {
self.currentammo = self.ammo_rockets = 0;
return;
}
if (loops == 0)
{
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
if (self.classname == "player")
KickPlayer(-2, self);
}
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
newmis.classname = "rocket"; //- OfN - Checked on airfist
// set newmis speed
if (self.classname == "player")
{
makevectors (self.v_angle);
dir = v_forward;
}
else if (self.classname == "monster_army")
dir = Grunty_LeadShot();
newmis.velocity = dir;
if (!loops)
{ //WK Not a cluster Rocket
if (self.tf_items & NIT_CLUSTER_ROCKETS && self.cluster_mode == TRUE)
{ //Make lead rocket start slower too
if (self.tf_items & NIT_RL_LASER_SIGHT) //Cluster and sight to start
newmis.velocity = newmis.velocity * 400;
else
newmis.velocity = newmis.velocity * 600; //Cluster and no sight
}
else
newmis.velocity = newmis.velocity * 900;
}
else if (self.tf_items & NIT_RL_LASER_SIGHT) //Cluster and sight to start
newmis.velocity = newmis.velocity * 400;
else
newmis.velocity = newmis.velocity * 600; //Cluster and no sight
newmis.angles = vectoangles(newmis.velocity);
newmis.touch = T_MissileTouch;
// set newmis duration
if (self.tf_items & NIT_RL_LASER_SIGHT) {
newmis.nextthink = time + 0.1; //Because tracks a sight
if (loops)
newmis.nextthink = time + 0.5; //Delay one second to spread out
newmis.think = Rocket_Track_Dot;
newmis.has_sentry = time + 6;
} else {
newmis.nextthink = time + 4;
newmis.think = SUB_Remove;
}
newmis.weapon = DMSG_ROCKETL;
if (!loops)
setmodel (newmis, "progs/missile.mdl");
else
setmodel (newmis, "progs/minimissile.mdl"); //Diff model for swarm rockets
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin + dir*8 + '0 0 16');
if (loops) { //WK Vary the starting point of the cluster
traceline (self.origin, self.origin + v_forward*9192, FALSE, self); //Make this TRUE
newmis.v_angle = trace_endpos;
newmis.has_tesla = loops; //Tell the rocket it is a cluster
newmis.weapon = DMSG_CLUSTER_ROCKET;
olorigin = newmis.origin;
newmis.origin = newmis.origin + v_right * (random() * 120 - 60);
newmis.origin = newmis.origin + v_forward * (random() * 40);
newmis.origin = newmis.origin + v_up * (random() * 50 - 20);
olorigin = olorigin - newmis.origin; //Get vector to new point
olorigin = 200 * normalize(olorigin);
if (self.tf_items & NIT_RL_LASER_SIGHT) //Dont spread without sight
newmis.velocity = newmis.velocity + olorigin;
}
loops = loops - 1;
} //End while loops
#ifdef DEMO_STUFF
// Have we got a live camera in projectile mode?
if (live_camera)
CamProjectileLockOn();
#endif
};
/*
===============================================================================
LIGHTNING
===============================================================================
*/
void(entity from, float damage) LightningHit =
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_LIGHTNINGBLOOD);
WriteCoord (MSG_MULTICAST, trace_endpos_x);
WriteCoord (MSG_MULTICAST, trace_endpos_y);
WriteCoord (MSG_MULTICAST, trace_endpos_z);
multicast (trace_endpos, MULTICAST_PVS);
TF_T_Damage (trace_ent, from, from, damage, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
};
/*
=================
LightningDamage
=================
*/
void(vector p1, vector p2, entity from, float damage) LightningDamage =
{
local entity e1, e2;
local vector f;
f = p2 - p1;
normalize (f);
f_x = 0 - f_y;
f_y = f_x;
f_z = 0;
f = f*16;
e1 = e2 = NIL;
traceline (p1, p2, FALSE, self);
//WK Sweep mines at point of impact
GuerillaMineSweep(trace_endpos);
deathmsg = DMSG_LIGHTNING;
if (trace_ent.takedamage)
{
LightningHit (from, damage);
}
e1 = trace_ent;
traceline (p1 + f, p2 + f, FALSE, self);
if (trace_ent != e1 && trace_ent.takedamage)
{
LightningHit (from, damage);
}
e2 = trace_ent;
traceline (p1 - f, p2 - f, FALSE, self);
if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
{
LightningHit (from, damage);
}
};
void() W_FireLightning =
{
local vector org;
local float cells,excess;
if (self.ammo_cells < 1)
{
self.current_weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
return;
}
// explode if under water
if (self.waterlevel > 1)
{
cells = self.ammo_cells;
if (cells > 10) cells = 10; //WK Don't allow detpacks on the fly!
self.ammo_cells = self.ammo_cells - cells;
W_SetCurrentAmmo ();
deathmsg = DMSG_LIGHTNING;
//WK T_RadiusDamage (self, self, 35*cells, NIL);
T_RadiusDamage (self, self, 20*cells, NIL);
Attack_Finished(5);
return;
}
if (self.t_width < time)
{
sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
self.t_width = time + 0.6;
}
KickPlayer(-2, self);
//WK Allow 6 seconds MAX of firing the lightning gun
#define BIGLIGHT
#ifdef BIGLIGHT
//We do this by capping the maximum ammo at 100, and using all
//cells above that in one tremendous shot
if (self.ammo_cells > 100) {
excess = self.ammo_cells - 100;
self.ammo_cells = 100;
}
else {
excess = 0;
self.ammo_cells = self.ammo_cells - 0.75;
}
#else
//Or this method, which consumes cells at a rate to ensure we run out
//In a few seconds, no matter what. But resupplying is a bitch.
excess = 0;
self.ammo_cells = self.ammo_cells - ceil(self.maxammo_cells / 30);
if (self.ammo_cells < 0) self.ammo_cells = 0;
#endif
self.currentammo = self.ammo_cells;
org = self.origin + '0 0 16';
// OfN - Check for force field
traceline (org, org + v_forward*600, FALSE, self);
if (trace_ent.classname == "force_field")
{
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
WriteEntity (MSG_MULTICAST, self);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
WriteCoord (MSG_MULTICAST, trace_endpos_x);
WriteCoord (MSG_MULTICAST, trace_endpos_y);
WriteCoord (MSG_MULTICAST, trace_endpos_z);
multicast (org, MULTICAST_PHS);
return;
}
//_------------------------------------_//
traceline (org, org + v_forward*600, TRUE, self);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
WriteEntity (MSG_MULTICAST, self);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
WriteCoord (MSG_MULTICAST, trace_endpos_x);
WriteCoord (MSG_MULTICAST, trace_endpos_y);
WriteCoord (MSG_MULTICAST, trace_endpos_z);
multicast (org, MULTICAST_PHS);
//WK Either way of firing the gun, we handle it here
//WK2 - Tone it down a LOT
if (excess) {
sprint(self,PRINT_HIGH,"You discharge your excess cells\n");
LightningDamage (self.origin, trace_endpos + v_forward*4, self, excess);
}
else
//WK 30. Lowered damage to make it a $2200 weapon
LightningDamage (self.origin, trace_endpos + v_forward*4, self, 12);
};
//=============================================================================
float (float tno) num_team_pipebombs =
{
if (tno == 1)
return num_team_pipebombs_1;
else if (tno == 2)
return num_team_pipebombs_2;
else if (tno == 3)
return num_team_pipebombs_3;
else if (tno == 4)
return num_team_pipebombs_4;
return 0;
};
void(float tno) ExplodeOldPipebomb =
{
local entity old;
local float index;
if (tno != 0)
{
index = num_team_pipebombs(tno);
index = index - (MAX_WORLD_PIPEBOMBS / number_of_teams);
}
else
{
index = num_world_pipebombs - MAX_WORLD_PIPEBOMBS;
}
old = find(NIL, classname, "pipebomb");
while (index > 0)
{
if (!old)
{
RPrint("*** ERROR: ExplodeOldPipebomb. ***\n");
RPrint("*** Please report this. ***\n");
num_world_pipebombs = 0;
num_team_pipebombs_1 = 0;
num_team_pipebombs_2 = 0;
num_team_pipebombs_3 = 0;
num_team_pipebombs_4 = 0;
return;
}
if (old.owner.team_no == tno || tno == 0)
{
old.nextthink = time + 0.5;
index = index - 1;
}
old = find(old, classname, "pipebomb");
}
};
void(float tno) increment_team_pipebombs =
{
if (tno == 1)
num_team_pipebombs_1 = num_team_pipebombs_1 + 1;
else if (tno == 2)
num_team_pipebombs_2 = num_team_pipebombs_2 + 1;
else if (tno == 3)
num_team_pipebombs_3 = num_team_pipebombs_3 + 1;
else if (tno == 4)
num_team_pipebombs_4 = num_team_pipebombs_4 + 1;
};
void(float tno) decrement_team_pipebombs =
{
if (tno == 1)
num_team_pipebombs_1 = num_team_pipebombs_1 - 1;
else if (tno == 2)
num_team_pipebombs_2 = num_team_pipebombs_2 - 1;
else if (tno == 3)
num_team_pipebombs_3 = num_team_pipebombs_3 - 1;
else if (tno == 4)
num_team_pipebombs_4 = num_team_pipebombs_4 - 1;
};
//=============================================================================
void() GrenadeExplode =
{
if (self.classname == "pipebomb")
{
num_world_pipebombs = num_world_pipebombs - 1;
decrement_team_pipebombs(self.owner.team_no);
}
deathmsg = self.weapon;
T_RadiusDamage (self, self.owner, 120, NIL);
#ifdef DEMO_STUFF
// Remove any camera's locks on this missile
if (self.enemy)
CamProjectileLockOff();
#endif
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PHS);
dremove(self);
};
void() GrenadeTouch =
{
if (other == self.owner)
return; // don't explode on owner
if (other.takedamage == DAMAGE_AIM)
{
GrenadeExplode();
return;
}
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
/*
================
W_FireGrenade
================
*/
void() W_FireGrenade =
{
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
KickPlayer(-2, self);
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_BOUNCE;
newmis.solid = SOLID_BBOX;
// Set grenade type based on firing mode
if (self.weaponmode == GL_NORMAL)
{
newmis.weapon = DMSG_GRENADEL;
newmis.classname = "grenade";
newmis.skin = 1;
newmis.touch = GrenadeTouch;
newmis.nextthink = time + 2.5;
}
else // if (self.weaponmode == GL_PIPEBOMB)
{
if (self.team_no != 0)
{
increment_team_pipebombs(self.team_no);
if (num_team_pipebombs(self.team_no) > (MAX_WORLD_PIPEBOMBS / number_of_teams))
ExplodeOldPipebomb(self.team_no);
}
else
{
num_world_pipebombs = num_world_pipebombs + 1;
if (num_world_pipebombs > MAX_WORLD_PIPEBOMBS)
ExplodeOldPipebomb(0);
}
newmis.classname = "pipebomb";
newmis.skin = 2;
newmis.touch = PipebombTouch;
newmis.nextthink = time + 120; // Remove pipebombs older than 2 minutes
newmis.weapon = DMSG_GREN_PIPE;
}
// set newmis speed
makevectors (self.v_angle);
if (self.v_angle_x)
newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
newmis.velocity = aim(self, 10000);
newmis.velocity = newmis.velocity * 600;
newmis.velocity_z = 200;
}
newmis.avelocity = '300 300 300';
newmis.angles = vectoangles(newmis.velocity);
newmis.think = GrenadeExplode;
setmodel (newmis, "progs/grenade2.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin);
#ifdef DEMO_STUFF
// Have we got a live camera in projectile mode?
if (live_camera)
CamProjectileLockOn();
#endif
};
//=============================================================================
void() spike_touch;
/*
===============
launch_spike
Used for both the player and the ogre
===============
*/
void(vector org, vector dir) launch_spike =
{
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
newmis.angles = vectoangles(dir);
newmis.touch = spike_touch;
newmis.weapon = DMSG_NAILGUN;
newmis.classname = "spike";
newmis.think = SUB_Remove;
newmis.nextthink = time + 6;
setmodel (newmis, "progs/spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
setorigin (newmis, org);
newmis.velocity = dir * 1600; // was 1000
#ifdef DEMO_STUFF
// Have we got a live camera in projectile mode?
if (live_camera)
CamProjectileLockOn();
#endif
};
void() superspike_touch =
{
local float ndmg;
if (other == self.owner)
return;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENTS_SKY)
{
dremove(self);
return;
}
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (18);
deathmsg = self.weapon;
/*
// In QW, nail grens only launch 1 nail, and it does more damage.
if (deathmsg == DMSG_GREN_NAIL)
ndmg = 40;
else
*/
ndmg = 13;
if (self.owner.classname == "grenade")
TF_T_Damage (other, self, self.owner.owner, ndmg, TF_TD_NOTTEAM, TF_TD_NAIL);
else
TF_T_Damage (other, self, self.owner, ndmg, TF_TD_NOTTEAM, TF_TD_NAIL);
}
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_SUPERSPIKE);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PHS);
}
}
dremove(self);
};
void() W_FireSuperSpikes =
{
local vector dir;
sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
Attack_Finished(0.2);
self.currentammo = self.ammo_nails = self.ammo_nails - 2;
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16', dir);
newmis.touch = superspike_touch;
newmis.weapon = DMSG_SNG;
setmodel (newmis, "progs/s_spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
KickPlayer(-2, self);
};
void(float ox) W_FireSpikes =
{
if (self.ammo_nails >= 2 && self.current_weapon == WEAP_SNG)
{
W_FireSuperSpikes ();
return;
}
local vector dir;
if (self.classname == "player")
makevectors (self.v_angle);
else
makevectors (self.angles);
if (self.ammo_nails < 1)
if (self.classname == "player")
{
self.current_weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
return;
}
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
Attack_Finished(0.2);
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
if (self.classname == "player")
{
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
KickPlayer(-2, self);
}
else if (self.classname == "monster_army") //- OfN -
{
dir = Grunty_LeadShot();
grunty_spike(self.origin + '0 0 16' + v_right*ox, dir);
}
};
//.float hit_z;
void() spike_touch =
{
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENTS_SKY)
{
dremove(self);
return;
}
//WK Sweep mines at point of impact
GuerillaMineSweep(self.origin);
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (9);
deathmsg = self.weapon;
//- OfN - Wizard projectiles do SCRAG_DMG damage
if (self.classname == "wizspike")
{
local float wizdmg;
wizdmg = SCRAG_DMG;
if (other.classname == "player")
{
if (other.cutf_items & CUTF_DEMONLORE) // if we have demon lore, it does less damage to us
wizdmg = wizdmg * 0.8;
}
TF_T_Damage (other, self, self.owner, wizdmg, TF_TD_NOTTEAM, 0);
sound (self, CHAN_MISC, "effects/crunch.wav", 0.4, ATTN_NORM); // any better sound?
} // - OfN -
else
if (self.owner.classname == "grenade")
TF_T_Damage (other, self, self.owner.owner, 12, TF_TD_NOTTEAM, TF_TD_NAIL);
else
TF_T_Damage (other, self, self.owner, 12, TF_TD_NOTTEAM, TF_TD_NAIL);
}
else
{
if (other.classname == "force_field") //- OfN - Makes field explosion b4 removing it
FieldExplosion(other,self.origin,self);
else
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
if (self.classname == "wizspike")
WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
else if (self.classname == "knightspike")
WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
else
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_PHS);
}
}
#ifdef DEMO_STUFF
// Remove any camera's locks on this missile
if (self.enemy)
CamProjectileLockOff();
#endif
dremove(self);
};
/*
===============================================================================
PLAYER WEAPON USE
===============================================================================
*/
void() W_SetCurrentAmmo =
{
if (self.health <= 0 || self.current_weapon == 0)
return; // get out of any weapon firing states
player_run();
self.items = self.items & ~(IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS);
self.weapon = 0;
//WK Set armor here... update armor picture
self.items = self.items & ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3);
if (self.armortype >= 0.8)
self.items = self.items | IT_ARMOR3;
else if (self.armortype >= 0.6)
self.items = self.items | IT_ARMOR2;
else if (self.armortype >= 0.3)
self.items = self.items | IT_ARMOR1;
//WK Show nothing for custom playerclass while building
if (self.playerclass == PC_CUSTOM && (self.done_custom & CUSTOM_BUILDING)) //We are building a class
{
self.currentammo = 0;
self.weaponmodel = "";
return;
}
if (self.current_weapon == WEAP_AXE)
{
self.currentammo = 0;
if (self.cutf_items & CUTF_KNIFE) //WK
{
if (self.job & JOB_BLOODY_KNIFE)
self.weaponmode = 1;
else
self.weaponmode = 0; //CH maybe fix bug that knife is bloody when not?
if (self.weaponmode == 0)
self.weaponmodel = "progs/v_knife.mdl"; //Nonbloody
else
self.weaponmodel = "progs/v_knife2.mdl"; //Bloody
}
else
self.weaponmodel = "progs/v_axe.mdl";
self.weaponframe = 0;
}
else if (self.current_weapon == WEAP_HOOK)
{
self.currentammo = 0;
self.weaponmodel = "progs/v_grap.mdl";
self.weaponframe = 0;
}
else if (self.current_weapon == WEAP_SPANNER)
{
self.currentammo = self.ammo_cells;
self.weaponmodel = "progs/v_span.mdl";
self.weaponframe = 0;
}
else if (self.current_weapon == WEAP_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.items = self.items | IT_CELLS;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_shot.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_SHELLS;
self.weapon = IT_SHOTGUN;
}
else if (self.current_weapon == WEAP_SUPER_SHOTGUN)
{
self.currentammo = self.ammo_shells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_shot2.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_SHELLS;
self.weapon = IT_SUPER_SHOTGUN;
}
else if (self.current_weapon == WEAP_NAILGUN)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_nail.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_NAILGUN;
}
else if (self.current_weapon == WEAP_LIGHT_ASSAULT)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_nail2.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_LIGHT_ASSAULT;
}
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rock.mdl";
self.weaponframe = 0;
}
self.weapon = IT_GRENADE_LAUNCHER;
self.items = self.items | IT_ROCKETS;
}
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rock2.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_ROCKETS;
self.weapon = IT_ROCKET_LAUNCHER;
}
else if (self.current_weapon == WEAP_LIGHTNING)
{
self.currentammo = self.ammo_cells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_light.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_CELLS;
self.weapon = IT_LIGHTNING;
}
else if (self.current_weapon == WEAP_SNIPER_RIFLE)
{
self.currentammo = self.ammo_shells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_srifle.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_SHELLS;
self.weapon = IT_SHOTGUN;
}
else if (self.current_weapon == WEAP_AUTO_RIFLE)
{
self.currentammo = self.ammo_shells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_srifle.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_SHELLS;
self.weapon = IT_SUPER_SHOTGUN;
}
else if (self.current_weapon == WEAP_ASSAULT_CANNON)
{
self.currentammo = self.ammo_shells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_asscan.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_SHELLS;
self.weapon = IT_ROCKET_LAUNCHER;
}
else if (self.current_weapon == WEAP_FLAMETHROWER)
{
self.currentammo = self.ammo_cells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rock.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_CELLS;
self.weapon = IT_GRENADE_LAUNCHER;
}
else if (self.current_weapon == WEAP_INCENDIARY)
{
self.currentammo = self.ammo_rockets;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rock2.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_ROCKETS;
self.weapon = IT_ROCKET_LAUNCHER;
}
else if (self.current_weapon == WEAP_MEDIKIT)
{
self.currentammo = 0;
self.weaponmodel = "progs/v_medi.mdl";
self.weaponframe = 0;
}
else if (self.current_weapon == WEAP_TRANQ)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_shot.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_SHOTGUN;
}
else if (self.current_weapon == WEAP_LASER)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rail.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_SHOTGUN;
}
else if (self.current_weapon == WEAP_DAEDALUS)
{
self.currentammo = self.ammo_cells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rock.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_CELLS;
self.weapon = IT_LIGHTNING;
}
else if (self.current_weapon == WEAP_MAUSER)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_rail.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_LIGHT_ASSAULT;
}
else if (self.current_weapon == WEAP_AIRF)
{
self.currentammo = 0;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_airgun.mdl";
self.weaponframe = 0;
}
}
else if (self.current_weapon == WEAP_SNG)
{
self.currentammo = self.ammo_nails;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_nail2.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_NAILS;
self.weapon = IT_LIGHT_ASSAULT;//IT_SUPER_NAILGUN;
}
else if (self.current_weapon == WEAP_LASERCANNON)
{
self.currentammo = self.ammo_cells;
if (!(self.tfstate & TFSTATE_RELOADING))
{
self.weaponmodel = "progs/v_laserg.mdl";
self.weaponframe = 0;
}
self.items = self.items | IT_CELLS;
self.weapon = WEAP_LASERCANNON;
}
else
{
self.currentammo = 0;
self.weaponmodel = "";
self.weaponframe = 0;
}
};
float() W_BestWeapon =
{
local float it;
it = self.weapons_carried;
if (self.ammo_cells >= 1 && (it & WEAP_LIGHTNING) && self.waterlevel <= 1)
return WEAP_LIGHTNING;
else if(self.ammo_shells >= 1 && (it & WEAP_SNIPER_RIFLE) )
return WEAP_SNIPER_RIFLE;
else if(self.ammo_rockets >= 1 && (it & WEAP_ROCKET_LAUNCHER) )
return WEAP_ROCKET_LAUNCHER;
else if (self.ammo_cells >= 5 && (it & WEAP_DAEDALUS) )
return WEAP_DAEDALUS;
else if (self.ammo_cells >= 6 && (self.ammo_shells >= 1) && (it & WEAP_ASSAULT_CANNON))
return WEAP_ASSAULT_CANNON;
else if(self.ammo_nails >= 10 && (it & WEAP_LIGHT_ASSAULT) )
return WEAP_LIGHT_ASSAULT;
else if(self.ammo_rockets >= 3 && (it & WEAP_INCENDIARY) )
return WEAP_INCENDIARY;
else if(self.ammo_rockets >= 1 && (it & WEAP_GRENADE_LAUNCHER) )
return WEAP_GRENADE_LAUNCHER;
else if (self.ammo_cells >= 1 && (it & WEAP_LASERCANNON))
return WEAP_LASERCANNON;
else if(self.ammo_nails >= 2 && (it & WEAP_SNG))
return WEAP_SNG;
else if (self.ammo_cells >= 1 && (it & WEAP_FLAMETHROWER))
return WEAP_FLAMETHROWER;
else if(self.ammo_shells >= 2 && (it & WEAP_SUPER_SHOTGUN) )
return WEAP_SUPER_SHOTGUN;
else if (self.ammo_nails >= 1 && (it & WEAP_LASER) )
return WEAP_LASER;
else if(self.ammo_nails >= 1 && (it & WEAP_NAILGUN) )
return WEAP_NAILGUN;
else if(self.ammo_shells >= 1 && (it & WEAP_SHOTGUN) )
return WEAP_SHOTGUN;
else if (self.ammo_nails >= 1 && (it & WEAP_MAUSER) )
return WEAP_MAUSER;
else if (self.ammo_nails >= 1 && (it & WEAP_TRANQ) )
return WEAP_TRANQ;
else if (it & WEAP_MEDIKIT)
return WEAP_MEDIKIT;
else if (it & WEAP_AIRF)
return WEAP_AIRF;
else if (it & WEAP_SPANNER)
return WEAP_SPANNER;
else if (it & WEAP_AXE)
return WEAP_AXE;
return 0;
};
float() W_CheckNoAmmo =
{
if (self.current_weapon == WEAP_MEDIKIT)
return TRUE;
if (self.current_weapon == WEAP_AIRF)
return TRUE;
else if (self.current_weapon == WEAP_AXE || self.current_weapon == WEAP_HOOK || self.current_weapon == WEAP_SPANNER)
return TRUE;
else if (self.current_weapon == WEAP_INCENDIARY)
{
if (self.currentammo >= 3)
return TRUE;
}
else if (self.current_weapon == WEAP_DAEDALUS)
{
if (self.currentammo >= 5)
return TRUE;
}
else if (self.currentammo > 0)
return TRUE;
self.current_weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
// drop the weapon down
return FALSE;
};
/*====================
W_Reload
Is called when weapon has finished reloading
====================*/
void() W_Reload_shotgun =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_shot.mdl";
sprint(self.owner, PRINT_LOW, "finished reloading\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
void() W_Reload_light_assault =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_nail2.mdl";
sprint(self.owner, PRINT_LOW, "finished reloading\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
void() W_Reload_super_shotgun =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_shot2.mdl";
sprint(self.owner, PRINT_LOW, "finished reloading\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
void() W_Reload_grenade_launcher =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_rock.mdl";
sprint(self.owner, PRINT_LOW, "finished reloading\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
void() W_Reload_rocket_launcher =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_rock2.mdl";
sprint(self.owner, PRINT_LOW, "finished reloading\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
void() W_Reload_laser_cannon =
{
self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
self.owner.weaponmodel = "progs/v_laserg.mdl";
sprint(self.owner, PRINT_LOW, "Laser Cannon charged\n");
self.owner.StatusRefreshTime = time + 0.1;
dremove(self);
};
float() CheckForReload =
{
local entity tWeapon;
if (self.current_weapon == WEAP_SHOTGUN)
{
if (self.reload_shotgun >= RE_SHOTGUN && self.ammo_shells > 0)
{
self.reload_shotgun = 0;
if (self.ammo_shells < RE_SHOTGUN)
self.reload_shotgun = RE_SHOTGUN - self.ammo_shells;
sprint (self, PRINT_HIGH, "reloading...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
tWeapon.nextthink = time + RE_SHOTGUN_TIME;
tWeapon.think = W_Reload_shotgun;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
else if (self.current_weapon == WEAP_SUPER_SHOTGUN)
{
if (self.reload_super_shotgun > RE_SUPER_SHOTGUN)
self.reload_super_shotgun = RE_SUPER_SHOTGUN;
if (self.reload_super_shotgun >= RE_SUPER_SHOTGUN && self.ammo_shells > 0)
{
self.reload_super_shotgun = 0;
if (self.ammo_shells < RE_SUPER_SHOTGUN)
self.reload_super_shotgun = RE_SUPER_SHOTGUN - self.ammo_shells;
sprint (self, PRINT_HIGH, "reloading...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
tWeapon.nextthink = time + RE_SUPER_SHOTGUN_TIME;
tWeapon.think = W_Reload_super_shotgun;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
else if (self.current_weapon == WEAP_LIGHT_ASSAULT)
{
if (self.reload_light_assault >= RE_LIGHT_ASSAULT && self.ammo_nails > 0)
{
self.reload_light_assault = 0;
if (self.ammo_nails < RE_LIGHT_ASSAULT)
self.reload_light_assault = RE_LIGHT_ASSAULT - self.ammo_nails;
sprint (self, PRINT_HIGH, "reloading...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
tWeapon.nextthink = time + RE_LIGHT_ASSAULT_TIME;
tWeapon.think = W_Reload_light_assault;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
else if (self.current_weapon == WEAP_LASERCANNON)
{
if (self.reload_laser_cannon >= RE_LASER_CANNON && self.ammo_cells > 0)
{
self.reload_laser_cannon = 0;
if (self.ammo_cells < RE_LASER_CANNON)
self.reload_laser_cannon = RE_LASER_CANNON - self.ammo_cells;
sprint (self, PRINT_HIGH, "Charging cannon...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
tWeapon.nextthink = time + RE_LASER_CANNON_TIME;
tWeapon.think = W_Reload_laser_cannon;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER)
{
if (self.reload_grenade_launcher >= RE_GRENADE_LAUNCHER && self.ammo_rockets > 0)
{
self.reload_grenade_launcher = 0;
if (self.ammo_rockets < RE_GRENADE_LAUNCHER)
self.reload_grenade_launcher = RE_GRENADE_LAUNCHER - self.ammo_rockets;
sprint (self, PRINT_HIGH, "reloading...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
tWeapon.nextthink = time + RE_GRENADE_LAUNCHER_TIME;
tWeapon.think = W_Reload_grenade_launcher;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER)
{
if (self.reload_rocket_launcher >= RE_ROCKET_LAUNCHER && self.ammo_rockets > 0)
{
self.reload_rocket_launcher = 0;
if (self.ammo_rockets < RE_ROCKET_LAUNCHER)
self.reload_rocket_launcher = RE_ROCKET_LAUNCHER - self.ammo_rockets;
sprint (self, PRINT_HIGH, "reloading...\n");
self.tfstate = (self.tfstate | TFSTATE_RELOADING);
tWeapon = spawn();
tWeapon.owner = self;
tWeapon.classname = "timer";
if(self.tf_items & NIT_CLUSTER_ROCKETS)
tWeapon.nextthink = time + RE_ROCKET_LAUNCHER_TIME - 1;
else
tWeapon.nextthink = time + RE_ROCKET_LAUNCHER_TIME;
tWeapon.think = W_Reload_rocket_launcher;
self.weaponmodel = "";
self.weaponframe = 0;
return TRUE;
}
}
return FALSE;
};
/*
============
W_Attack
An attack impulse can be triggered now
============
*/
void() player_axe1;
void() player_axeb1;
void() player_axec1;
void() player_axed1;
void() player_shot1;
void() player_nail1;
void() player_snail1; // ofn SNG
void() player_light1;
void() player_light_assault1;
void() player_rocket1;
void() player_autorifle1;
void() player_assaultcannon1;
void() player_assaultcannonup1;
void() player_assaultcannondown1;
void() player_medikit1;
void() player_medikitb1;
void() player_medikitc1;
void() player_medikitd1;
void() player_bioweapon1;
void() player_bioweaponb1;
void() player_bioweaponc1;
void() player_bioweapond1;
void() player_chain1;
void() player_chain2;
void() player_chain3;
void() player_chain4;
void() player_chain5;
void() W_Attack =
{
local float r;
if (!W_CheckNoAmmo ())
return;
if (self.playerclass == PC_CUSTOM && (self.done_custom & CUSTOM_BUILDING))
return;
if (self.tfstate & TFSTATE_RELOADING)
return;
if (self.penance_time > time)
return;
//WK Tranq does not remove disguise
if (self.is_undercover && (self.current_weapon != WEAP_TRANQ && self.current_weapon != WEAP_MAUSER))
Spy_RemoveDisguise(self);
if (self.job & JOB_THIEF && (self.job & JOB_ACTIVE || self.job & JOB_FULL_HIDE))
RevealThief(self,FALSE);
//WK When conced you randomly don't fire
if (self.tfstate & TFSTATE_CONCUSSIONED)
if (random() <= 0.3)
return;
makevectors (self.v_angle); // calculate forward angle for velocity
self.show_hostile = time + 1; // wake monsters up
if (self.current_weapon == WEAP_AXE)
{
//if (self.cutf_items & CUTF_KNIFE) //WK Go berserk with the knife
// Attack_Finished(0.5); // no, don't (0.35)
//else
Attack_Finished(0.5);
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
r = random();
if (r < 0.25)
player_axe1 ();
else if (r<0.5)
player_axeb1 ();
else if (r<0.75)
player_axec1 ();
else
player_axed1 ();
}
else if (self.current_weapon == WEAP_SPANNER)
{
Attack_Finished(0.35); //WK Berserk with spanner
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
player_axe1 ();
}
else if (self.current_weapon == WEAP_HOOK)
{
if (!self.hook_out)
player_chain1 ();
Attack_Finished(1); //WK
}
else if (self.current_weapon == WEAP_SHOTGUN)
{
if (CheckForReload() == TRUE)
return;
player_shot1 ();
W_FireShotgun ();
self.reload_shotgun = self.reload_shotgun + 1;
self.StatusRefreshTime = time + 0.1;
CheckForReload();
Attack_Finished(0.5);
}
else if (self.current_weapon == WEAP_SUPER_SHOTGUN)
{
if (CheckForReload() == TRUE)
return;
player_shot1 ();
W_FireSuperShotgun ();
self.reload_super_shotgun = self.reload_super_shotgun + 2;
self.StatusRefreshTime = time + 0.1;
CheckForReload();
Attack_Finished(0.7);
}
else if (self.current_weapon == WEAP_SNG)
{
player_snail1 ();
}
else if (self.current_weapon == WEAP_NAILGUN)
{
player_nail1 ();
}
else if (self.current_weapon == WEAP_LIGHT_ASSAULT)
{
if (CheckForReload() == TRUE)
return;
player_light_assault1();
CheckForReload();
}
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER)
{
if (CheckForReload() == TRUE)
return;
player_rocket1();
W_FireGrenade();
self.reload_grenade_launcher = self.reload_grenade_launcher + 1;
self.StatusRefreshTime = time + 0.1;
CheckForReload();
Attack_Finished(0.6);
}
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER)
{
if (CheckForReload() == TRUE)
return;
player_rocket1();
W_FireRocket();
if (self.tf_items & NIT_CLUSTER_ROCKETS && self.cluster_mode == TRUE) //WK Clusters are multiple shots
self.reload_rocket_launcher = self.reload_rocket_launcher + 8;
else
self.reload_rocket_launcher = self.reload_rocket_launcher + 1;
self.StatusRefreshTime = time + 0.1;
CheckForReload();
//CH so that the dot can be removed quicker (reset after dot gone)
if (self.tf_items & NIT_RL_LASER_SIGHT)
Attack_Finished(0.1);
else
Attack_Finished(0.8);
}
else if (self.current_weapon == WEAP_LIGHTNING)
{
player_light1();
Attack_Finished(0.1);
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
}
else if (self.current_weapon == WEAP_DAEDALUS) //CHANGEME
{
player_rocket1();
W_FireDaedalus();
Attack_Finished(0.8);
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
}
else if (self.current_weapon == WEAP_SNIPER_RIFLE)
{
// Can't fire while jumping
// WK You can if you are a scuba commando!
if ((self.flags & FL_ONGROUND) || (self.hook_out) || ((self.tf_items & NIT_SCUBA) && self.waterlevel) )
{
player_shot1();
W_FireSniperRifle();
Attack_Finished(SNIPER_RIFLE_RELOAD_TIME);
}
}
else if (self.current_weapon == WEAP_AUTO_RIFLE)
{
player_autorifle1();
W_FireAutoRifle();
Attack_Finished(0.1);
}
else if (self.current_weapon == WEAP_ASSAULT_CANNON)
{
// Need 4 cells to power up the Assault Cannon
if (self.ammo_cells < 4)
{
sprint (self, PRINT_MEDIUM, "Insufficient cells to power up the Assault Cannon.\n");
stuffcmd (self, "-attack;\n"); // to avoid flooding
}
else
{
self.ammo_cells = self.ammo_cells - 4;
// Can't move while firing the Assault Cannon :)
self.heat = 1;
makeImmune(self,time+2);
//self.immune_to_check = time + 2;
self.tfstate = self.tfstate | TFSTATE_ASSAULTCANNON;
TeamFortress_SetSpeed(self);
player_assaultcannonup1();
}
}
else if (self.current_weapon == WEAP_FLAMETHROWER)
{
player_shot1();
W_FireFlame();
if (self.waterlevel >2)
Attack_Finished(1);
else
Attack_Finished(0.15);
}
else if (self.current_weapon == WEAP_INCENDIARY)
{
player_rocket1();
W_FireIncendiaryCannon();
Attack_Finished(1.2);
}
else if (self.current_weapon == WEAP_MEDIKIT)
{
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
r = random();
if (r < 0.25)
player_medikit1 ();
else if (r<0.5)
player_medikitb1 ();
else if (r<0.75)
player_medikitc1 ();
else
player_medikitd1 ();
Attack_Finished(0.5);
}
else if (self.current_weapon == WEAP_TRANQ)
{
sound (self, CHAN_WEAPON, "weapons/dartgun.wav", 1, ATTN_NORM);
player_shot1 ();
W_FireTranq ();
Attack_Finished(1.5);
}
else if (self.current_weapon == WEAP_LASER)
{
sound (self, CHAN_WEAPON, "weapons/railgun.wav", 1, ATTN_NORM);
player_shot1();
W_FireLaser();
Attack_Finished(0.4);
}
else if (self.current_weapon == WEAP_MAUSER)
{
sound (self, CHAN_WEAPON, "weapons/dartgun.wav", 1, ATTN_NORM);
//player_shot1();
W_FireMauser();
Attack_Finished(2.0);
}
else if (self.current_weapon == WEAP_AIRF)
{
launch_horn();
}
if (self.current_weapon == WEAP_LASERCANNON)
{
if (CheckForReload() == TRUE)
return;
player_laser1();
CheckForReload();
}
};
/*=========================
W_PrintWeaponMessage
Prints a message indicating
the current selected weapon,
if needed.
=========================*/
void() W_PrintWeaponMessage =
{
//WK Custom class friendly
if (self.current_weapon == WEAP_AXE) // && (self.weapons_carried & WEAP_HOOK))
{
if (!(self.cutf_items & CUTF_KNIFE))
sprint(self, PRINT_MEDIUM, "Axe selected\n");
else
{
if (self.weaponmode == 0)
sprint(self, PRINT_MEDIUM, "Knife selected\n"); //Nonbloody
else
sprint(self, PRINT_MEDIUM, "Bloody Knife selected\n"); //Bloody
}
}
else if (self.current_weapon == WEAP_HOOK)
sprint(self, PRINT_MEDIUM, "Grappling Hook selected\n");
//CH because they use the same mdl, say what they are.
else if (self.current_weapon == WEAP_FLAMETHROWER)
sprint(self, PRINT_MEDIUM, "Flamethrower selected\n");
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER) {
sprint(self, PRINT_MEDIUM, "Rocket Launcher selected");
if (self.cluster_mode == TRUE && self.tf_items & NIT_CLUSTER_ROCKETS) //set to fire cluster rockets
sprint(self, PRINT_MEDIUM, " Cluster Mode");
else if (self.tf_items & NIT_CLUSTER_ROCKETS)
sprint(self, PRINT_MEDIUM, " Normal Mode");
sprint(self, PRINT_MEDIUM, "\n");
}
else if (self.current_weapon == WEAP_INCENDIARY)
sprint(self, PRINT_MEDIUM, "Incendiary cannon selected\n");
else if (self.current_weapon == WEAP_LIGHTNING)
sprint(self, PRINT_MEDIUM, "Lightning Gun selected\n");
else if (self.current_weapon == WEAP_SPANNER)
sprint(self, PRINT_MEDIUM, "Spanner readied\n");
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER)
{
if (self.weaponmode == GL_NORMAL)
sprint(self, PRINT_MEDIUM, "Normal grenade mode\n");
else if (self.weaponmode == GL_PIPEBOMB)
sprint(self, PRINT_MEDIUM, "Pipebomb mode\n");
}
else if (self.current_weapon == WEAP_SNIPER_RIFLE)
sprint(self, PRINT_MEDIUM, "Sniper Rifle ready\n");
else if (self.current_weapon == WEAP_AUTO_RIFLE)
sprint(self, PRINT_MEDIUM, "Rifle on fully auto\n");
else if (self.current_weapon == WEAP_TRANQ)
sprint(self, PRINT_MEDIUM, "Tranquiliser gun selected\n");
else if (self.current_weapon == WEAP_MEDIKIT)
sprint(self, PRINT_MEDIUM, "Medikit/Bioweapon readied\n");
else if (self.current_weapon == WEAP_MAUSER)
sprint(self, PRINT_MEDIUM, "Mauser WK-77 Assassin's Gun readied\n");
else if (self.current_weapon == WEAP_DAEDALUS)
sprint(self, PRINT_MEDIUM, "Daedalus Impulse Rifle readied\n");
else if (self.current_weapon == WEAP_LIGHTNING)
sprint(self, PRINT_MEDIUM, "Lighting gun selected\n");
else if (self.current_weapon == WEAP_AIRF)
sprint(self, PRINT_MEDIUM, "Airfist prepared\n");
else if (self.current_weapon == WEAP_LASERCANNON)
sprint(self, PRINT_MEDIUM, "Laser Cannon selected\n");
else if (self.current_weapon == WEAP_SNG)
sprint(self, PRINT_MEDIUM, "Super Nailgun selected\n");
else if (self.current_weapon == WEAP_NAILGUN)
sprint(self, PRINT_MEDIUM, "Nailgun selected\n");
else if (self.current_weapon == WEAP_LIGHT_ASSAULT)
sprint(self, PRINT_MEDIUM, "Light Assualt cannon selected\n");
};
/*
============
W_ChangeWeapon
============
*/
void() W_ChangeWeapon =
{
local float it, am, fl, loopck;
local float have_weapon, usable;
if (self.tfstate & TFSTATE_RELOADING)
return;
if (self.tfstate & TFSTATE_CANT_MOVE)
return;
it = self.weapons_carried;
fl = self.current_weapon;
am = 0;
usable = 0;
have_weapon = TRUE;
if (self.impulse == 1)
{
if (!(it & (WEAP_HOOK | WEAP_MEDIKIT | WEAP_AXE | WEAP_SPANNER)))
have_weapon = FALSE;
while (!usable && have_weapon)
{
if (fl == WEAP_SPANNER)
{
fl = WEAP_MEDIKIT;
if (it & WEAP_MEDIKIT)
usable = 1;
}
else if (fl == WEAP_MEDIKIT)
{
fl = WEAP_HOOK;
if ((self.weapons_carried & WEAP_HOOK) && (fl & WEAP_HOOK))
usable = 1;
if (self.hook_out)
Reset_Grapple(self.hook);
}
else if (fl == WEAP_HOOK)
{
fl = WEAP_AXE;
if (it & WEAP_AXE)
usable = 1;
}
else
{
fl = WEAP_SPANNER;
if (it & WEAP_SPANNER)
usable = 1;
}
}
}
else if ((self.weapons_carried & WEAP_HOOK) && (self.impulse == HOOK_IMP1 || self.impulse == HOOK_IMP2))
{
fl = WEAP_HOOK;
}
else if (self.impulse == AXE_IMP)
{
if (!(it & (WEAP_MEDIKIT | WEAP_AXE | WEAP_SPANNER)))
have_weapon = FALSE;
while (!usable && have_weapon)
{
if (fl == WEAP_SPANNER)
{
fl = WEAP_MEDIKIT;
if (it & WEAP_MEDIKIT)
usable = 1;
}
else if (fl == WEAP_MEDIKIT)
{
fl = WEAP_AXE;
if (it & WEAP_AXE)
usable = 1;
}
else
{
fl = WEAP_SPANNER;
if (it & WEAP_SPANNER)
usable = 1;
}
}
}
else if (self.impulse == 2)
{
if (!(((it & WEAP_SNIPER_RIFLE || it & WEAP_SHOTGUN || it & WEAP_TRANQ) && self.ammo_shells > 0) || (it & WEAP_LASER && self.ammo_nails > 0)|| (it & WEAP_DAEDALUS && self.ammo_cells > 0)))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_SNIPER_RIFLE)
{
fl = WEAP_SHOTGUN;
if (it & WEAP_SHOTGUN && self.ammo_shells > 0)
usable = 1;
}
else if (fl == WEAP_SHOTGUN)
{
fl = WEAP_TRANQ;
if (it & WEAP_TRANQ && self.ammo_nails > 0)
usable = 1;
}
else if (fl == WEAP_TRANQ)
{
fl = WEAP_LASER;
if (it & WEAP_LASER && self.ammo_nails > 0)
usable = 1;
}
else
{
fl = WEAP_SNIPER_RIFLE;
if (it & WEAP_SNIPER_RIFLE && self.ammo_shells > 0)
usable = 1;
}
}
if (fl == WEAP_LASER)
{
if (self.ammo_nails < 1)
am = 1;
}
else
{
if (self.ammo_shells < 1)
am = 1;
}
}
else if (self.impulse == 3)
{
if (!((it & WEAP_AUTO_RIFLE && self.ammo_shells > 0) || (it & WEAP_SUPER_SHOTGUN && self.ammo_shells >1)))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_AUTO_RIFLE)
{
fl = WEAP_SUPER_SHOTGUN;
if (it & WEAP_SUPER_SHOTGUN && self.ammo_shells > 1)
usable = 1;
}
else
{
fl = WEAP_AUTO_RIFLE;
if (it & WEAP_AUTO_RIFLE && self.ammo_shells > 0)
usable = 1;
}
}
if (fl == WEAP_SUPER_SHOTGUN)
{
if (self.ammo_shells < 2)
am = 1;
}
else
{
if (self.ammo_shells < 1)
am = 1;
}
}
else if (self.impulse == 4)
{
/*fl = WEAP_NAILGUN;
if (self.ammo_nails < 1)
am = 1;*/
if (!(it & WEAP_LASERCANNON || it & WEAP_NAILGUN))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_LASERCANNON)
{
fl = WEAP_NAILGUN;
if (it & WEAP_NAILGUN)
usable = 1;
}
else
{
fl = WEAP_LASERCANNON;
if (it & WEAP_LASERCANNON)
usable = 1;
}
}
if (fl == WEAP_NAILGUN)
{
if (self.ammo_nails < 1)
am = 1;
}
else if (fl == WEAP_LASERCANNON)
{
if (self.ammo_cells < 1)
am = 1;
}
}
else if (self.impulse == 5)
{
if (!(it & WEAP_LIGHT_ASSAULT || it & WEAP_MAUSER || it & WEAP_SNG))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_LIGHT_ASSAULT)
{
fl = WEAP_MAUSER;
if (it & WEAP_MAUSER)
usable = 1;
}
//-
else if (fl == WEAP_MAUSER)
{
fl = WEAP_SNG;
if (it & WEAP_SNG)
usable = 1;
}
//-
else
{
fl = WEAP_LIGHT_ASSAULT;
if (it & WEAP_LIGHT_ASSAULT)
usable = 1;
}
}
if (fl == WEAP_MAUSER)
{
if (self.ammo_nails < 1)
am = 1;
}
else if (fl == WEAP_LIGHT_ASSAULT)
{
if (self.ammo_nails < 1)
am = 1;
}
//
else if (fl == WEAP_SNG)
{
if (self.ammo_nails < 2)
am = 1;
}
}
else if (self.impulse == 6)
{
if (!((it & WEAP_FLAMETHROWER && self.ammo_cells > 0) || (it & WEAP_GRENADE_LAUNCHER && self.ammo_rockets > 0)))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_FLAMETHROWER)
{
fl = WEAP_GRENADE_LAUNCHER;
self.weaponmode = GL_NORMAL;
if (it & WEAP_GRENADE_LAUNCHER && self.ammo_rockets > 0)
usable = 1;
}
else
{
fl = WEAP_FLAMETHROWER;
if (it & WEAP_FLAMETHROWER && self.ammo_cells > 0)
usable = 1;
}
}
if (fl == WEAP_FLAMETHROWER)
{
if (self.ammo_cells < 1)
am = 1;
}
else
{
if (self.ammo_rockets < 1)
am = 1;
}
}
else if (self.impulse == 7)
{
if (!((it & WEAP_INCENDIARY && self.ammo_rockets > 2) || ((it & WEAP_ROCKET_LAUNCHER || it & WEAP_GRENADE_LAUNCHER) && self.ammo_rockets > 0) || (it & WEAP_ASSAULT_CANNON && self.ammo_shells > 0 && self.ammo_cells > 3)))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_INCENDIARY)
{
fl = WEAP_ROCKET_LAUNCHER;
if (it & WEAP_ROCKET_LAUNCHER && self.ammo_rockets > 0)
usable = 1;
}
else if (fl == WEAP_ROCKET_LAUNCHER)
{
if (self.tf_items & NIT_CLUSTER_ROCKETS)
{
if (self.cluster_mode == TRUE)
{
// bprint(PRINT_HIGH, "cluster mode FALSE\n");
self.cluster_mode = FALSE;
fl = WEAP_ASSAULT_CANNON;
if (it & WEAP_ASSAULT_CANNON && self.ammo_shells > 0 && self.ammo_cells > 3)
usable = 1;
}
else
{
// bprint(PRINT_HIGH, "cluster mode TRUE\n");
self.cluster_mode = TRUE;
fl = WEAP_ROCKET_LAUNCHER;
if (it & WEAP_ROCKET_LAUNCHER && self.ammo_rockets > 0)
usable = 1;
}
}
else
{
fl = WEAP_ASSAULT_CANNON;
if (it & WEAP_ASSAULT_CANNON && self.ammo_shells > 0 && self.ammo_cells > 3)
usable = 1;
}
}
else if (fl == WEAP_ASSAULT_CANNON)
{
fl = WEAP_GRENADE_LAUNCHER;
self.weaponmode = GL_PIPEBOMB;
if (it & WEAP_GRENADE_LAUNCHER && self.ammo_rockets > 0)
usable = 1;
}
else
{
fl = WEAP_INCENDIARY;
if (it & WEAP_INCENDIARY && self.ammo_rockets > 2)
usable = 1;
}
}
if (fl == WEAP_ASSAULT_CANNON)
{
if (self.ammo_cells < 4 || self.ammo_shells < 1)
am = 1;
}
else if (fl == WEAP_INCENDIARY)
{
if (self.ammo_rockets < 3)
am = 1;
}
else
{
if (self.ammo_rockets < 1)
am = 1;
}
}
else if (self.impulse == 8)
{
if (!(it & WEAP_LIGHTNING || it & WEAP_DAEDALUS || it & WEAP_AIRF))
have_weapon = FALSE;
loopck = 0;
while (!usable && have_weapon)
{
loopck = (loopck + 1);
if (loopck >= 10)
have_weapon = FALSE;
if (fl == WEAP_DAEDALUS)
{
fl = WEAP_LIGHTNING;
if (it & WEAP_LIGHTNING) //WEAP_DAEDALUS
usable = 1;
}
else if (fl == WEAP_LIGHTNING)
{
fl = WEAP_AIRF;
if (it & WEAP_AIRF) //WEAP_DAEDALUS
usable = 1;
}
else
{
fl = WEAP_DAEDALUS;
if (it & WEAP_DAEDALUS)
usable = 1;
}
}
if (fl == WEAP_DAEDALUS)
{
if (self.ammo_cells < 5)
am = 1;
}
else if (fl == WEAP_LIGHTNING)
{
if (self.ammo_cells < 1)
am = 1;
}
}
else if (self.impulse == TF_MEDIKIT)
{
fl = WEAP_MEDIKIT;
if (it & WEAP_MEDIKIT)
usable = 1;
}
self.impulse = 0;
// don't have the weapon
if (!have_weapon || (!(it & fl)))
{
sprint (self, PRINT_HIGH, "no weapon.\n");
return;
}
// don't have the ammo
if (am == 1)
{
sprint(self, PRINT_HIGH, "not enough ammo.\n");
return;
}
// don't have the cells for the cannon
if (am == 2)
{
sprint(self, PRINT_HIGH, "not enough cells to power assault cannon.\n");
return;
}
// set weapon, set ammo
self.current_weapon = fl;
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
self.StatusRefreshTime = time + 0.1;
};
/*
============
CycleWeaponCommand
Go to the next weapon with ammo
============
*/
void() CycleWeaponCommand =
{
//CH reorder so that they please me
local float it, am, cont, loopcount;
// Some safety code
if (!self.weaponmodel || self.current_weapon == 0)
return;
if (self.tfstate & TFSTATE_RELOADING)
return;
if (self.tfstate & TFSTATE_CANT_MOVE)
return;
it = self.weapons_carried;
self.impulse = 0;
loopcount = 0;
while (1)
{
am = 0;
cont = FALSE;
if (self.current_weapon == WEAP_AXE)
{
self.current_weapon = WEAP_SPANNER;
}
else if (self.current_weapon == WEAP_SPANNER)
{
self.current_weapon = WEAP_SHOTGUN;
if (self.ammo_shells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_SHOTGUN)
{
self.current_weapon = WEAP_LASER;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.current_weapon == WEAP_LASER)
{
self.current_weapon = WEAP_TRANQ;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.current_weapon == WEAP_TRANQ)
{
self.current_weapon = WEAP_SNIPER_RIFLE;
if (self.ammo_shells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_SNIPER_RIFLE)
{
self.current_weapon = WEAP_AUTO_RIFLE;
if (self.ammo_shells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_AUTO_RIFLE)
{
self.current_weapon = WEAP_MAUSER;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.current_weapon == WEAP_MAUSER)
{
self.current_weapon = WEAP_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
am = 1;
}
else if (self.current_weapon == WEAP_SUPER_SHOTGUN)
{
self.current_weapon = WEAP_NAILGUN;
if (self.ammo_nails < 1)
am = 1;
}
//-
else if (self.current_weapon == WEAP_NAILGUN)
{
self.current_weapon = WEAP_SNG;
if (self.ammo_nails < 2)
am = 1;
}
//-
else if (self.current_weapon == WEAP_SNG)
{
self.current_weapon = WEAP_LASERCANNON;
if (self.ammo_cells < 1)
am = 1;
}
//-
else if (self.current_weapon == WEAP_LASERCANNON) // was WEAP_NAILGUN
{
self.current_weapon = WEAP_LIGHT_ASSAULT;
if (self.ammo_nails < 2)
am = 1;
}
else if (self.current_weapon == WEAP_LIGHT_ASSAULT)
{
self.current_weapon = WEAP_FLAMETHROWER;
if (self.ammo_cells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_FLAMETHROWER)
{
self.current_weapon = WEAP_GRENADE_LAUNCHER;
self.weaponmode = GL_NORMAL;
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER && self.weaponmode == GL_NORMAL)
{
self.current_weapon = WEAP_GRENADE_LAUNCHER;
self.weaponmode = GL_PIPEBOMB;
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.current_weapon == WEAP_GRENADE_LAUNCHER && self.weaponmode == GL_PIPEBOMB)
{
self.current_weapon = WEAP_INCENDIARY;
if (self.ammo_rockets < 3)
am = 1;
}
else if (self.current_weapon == WEAP_INCENDIARY)
{
self.current_weapon = WEAP_DAEDALUS;
if (self.ammo_cells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_DAEDALUS)
{
self.current_weapon = WEAP_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER)
{
if (self.tf_items & NIT_CLUSTER_ROCKETS)
{
if (self.cluster_mode == TRUE)
{
// bprint(PRINT_HIGH, "cluster mode FALSE\n");
self.cluster_mode = FALSE;
self.current_weapon = WEAP_ASSAULT_CANNON;
if (self.ammo_cells < 4)
am = 1;
if (self.ammo_shells < 1)
am = 1;
}
else
{
// bprint(PRINT_HIGH, "cluster mode TRUE\n");
self.cluster_mode = TRUE;
self.current_weapon = WEAP_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
}
else
{
self.current_weapon = WEAP_ASSAULT_CANNON;
if (self.ammo_cells < 4)
am = 1;
if (self.ammo_shells < 1)
am = 1;
}
}
else if (self.current_weapon == WEAP_ASSAULT_CANNON)
{
self.current_weapon = WEAP_LIGHTNING;
if (self.ammo_cells < 1)
am = 1;
}
else if (self.current_weapon == WEAP_LIGHTNING)
{
self.current_weapon = WEAP_AIRF;
if (!(self.weapons_carried & WEAP_AIRF))
am = 1;
}
else if (self.current_weapon == WEAP_AIRF)
{
self.current_weapon = WEAP_HOOK;
if (!(self.weapons_carried & WEAP_HOOK))
am = 1;
}
else if (self.current_weapon == WEAP_HOOK)
{
self.current_weapon = WEAP_MEDIKIT;
}
else if (self.current_weapon == WEAP_MEDIKIT)
{
self.current_weapon = WEAP_AXE;
}
// Safety precaution
if (loopcount > 30)
return;
loopcount = loopcount + 1;
// check if player actually has the weapon
// if not, loop again
if ((self.weapons_carried & self.current_weapon) && (am == 0))
{
if (self.current_weapon != WEAP_GRENADE_LAUNCHER)
self.weaponmode = GL_NORMAL; // reset the pipebombs
W_SetCurrentAmmo ();
W_PrintWeaponMessage();
self.StatusRefreshTime = time + 0.1;
return;
}
}
};
/*
============
ImpulseCommands
============
*/
void() DeadImpulses;
float(float inp) BuildingImpulses =
{
if (inp < 10) return TRUE;
if (inp > TF_CHANGEPC && inp <= TF_CHANGEPC + PC_LASTCLASS) return TRUE;
if (inp == TF_CHANGECLASS) return TRUE;
if (inp == TF_HELP_MAP) return TRUE;
if (inp == TF_SHOWTF) return TRUE;
if (inp == TF_TEAM_CLASSES) return TRUE;
if (inp == TF_TEAM_SCORES) return TRUE;
if (inp == TF_TEAM_LIST) return TRUE;
if (inp == TF_TEAM_ENUM) return TRUE;
if (inp == TF_ID) return TRUE;
if (inp == TF_SELL) return TRUE;
if (inp >= TF_ADMIN_KICK_CYCLE && inp <= TF_ADMIN_CEASEFIRE) return TRUE;
if (inp == I_CHEAT_ONE) return TRUE;
if (inp == I_CHEAT_TWO) return TRUE;
if (inp == I_CHEAT_THREE) return TRUE;
if (inp == IMPULSE_DEBUG) return TRUE; //- OfN -
if (inp == IMPULSE_UPDATEINFO) return TRUE; //- OfN -
if (inp == IMPULSE_CHECKADMIN) return TRUE; //- OfN -
if (inp == IMPULSE_STUFFCMD) return TRUE; //- OfN -
return FALSE;
};
void() Alias_BitImpulse;
void() ImpulseCommands =
{
if (self.impulse >= TF_BITSTART && self.impulse <= TF_BITNONE) {
Alias_BitImpulse ();
self.impulse = 0;
return;
}
if (self.impulse == TF_ALIASNEXT) {
self.impulse = 0;
self.got_aliases_time = time;
return;
}
if ((self.impulse== TF_CHANGEPC + PC_CUSTOM || self.impulse==TF_SELL) && custom_mode==2)
{
self.impulse=0;
sprint(self,PRINT_MEDIUM,"Custom player classes are disabled\n");
return;
}
if (self.impulse <= TF_CHANGEPC + PC_RANDOM && self.impulse >= TF_CHANGEPC + PC_SCOUT && stock_mode==2)
{
self.impulse=0;
sprint(self,PRINT_MEDIUM,"Stock player classes are disabled\n");
return;
}
//local entity te; //- OfN - Unused!
//WK Don't allow any commands except menu ones when building a class
if (self.playerclass == PC_CUSTOM && (self.done_custom & CUSTOM_BUILDING))
{
if (!BuildingImpulses(self.impulse))
{
self.impulse = 0;
return;
}
}
//WK Don't allow bastards to do any commands
if (self.penance_time > time)
return;
if (prematch >= time)
if (self.impulse > 10 || self.impulse < 1)
{
self.impulse = 0;
return;
}
/*=====================
These Impulse commands rely on the use of self.last_impulse. Since they use
self.impulse for their own purposes, they _must_ be placed before the other
self.impulse tests, and they _must_ set self.impulse = 0 when they're done.
=====================*/
// TeamFortress Detpack
if (self.last_impulse == TF_DETPACK && self.impulse)
TeamFortress_SetDetpack(self.impulse);
// TeamFortress Scan
else if (self.last_impulse == TF_SCAN && self.impulse)
TeamFortress_Scan(self.impulse,FALSE);
/*=====================
The rest of these Impulse Commands don't use self.last_impulse. They _must_
be placed _after_ the Impulse Commands that do require self.last_impulse
=====================*/
// Catch the 8 key to reprint the classhelp.
// Remove this when we return the lightning gun
//CH was on impulse 8, but thats lgun
if (self.impulse == 9 && self.current_menu != MENU_CLASSHELP && (self.playerclass > 0 && self.playerclass < 11))
{
self.current_menu = MENU_CLASSHELP;
self.menu_count = MENU_REFRESH_RATE;
self.menu_displaytime = 0;
}
// uses the special skill of the player's class
if (self.impulse == TF_SPECIAL_SKILL)
UseSpecialSkill();
// uses the special skill of the player's class
if (self.impulse == TF_SKILL)
UseJobSkill();
// No weapon related impulses can be done when setting detpacks or building WK or chaplaning
if (!self.is_building && !self.is_detpacking && !self.is_feigning && !(self.job & JOB_CHAPLAN && self.job & JOB_ACTIVE))
{
if ((self.impulse >= 1 && self.impulse < 9) || (self.impulse == TF_MEDIKIT))
W_ChangeWeapon ();
// Grappling Hook
else if ((self.weapons_carried & WEAP_HOOK) && (self.impulse == HOOK_IMP1 || self.impulse == HOOK_IMP2))
W_ChangeWeapon ();
// Axe
else if (self.impulse == AXE_IMP)
W_ChangeWeapon ();
// cycle weapon reverse and cycle weapon do the same thing
// TBD: make CycleWeaponReverseCommand()
else if (self.impulse == 10 || self.impulse == 12)
CycleWeaponCommand ();
// TeamFortress Reload current weapon
else if (self.impulse == TF_RELOAD)
TeamFortress_ReloadCurrentWeapon();
// Scanning impulses
else if (self.impulse == TF_SCAN_10)
TeamFortress_Scan(10,FALSE);
else if (self.impulse == TF_SCAN_30)
TeamFortress_Scan(30,FALSE);
else if (self.impulse == TF_SCAN_100)
TeamFortress_Scan(100,FALSE);
else if (self.impulse == TF_SCAN_ENEMY) //CH
TeamFortress_Scan(TF_SCAN_ENEMY,FALSE);
else if (self.impulse == TF_SCAN_FRIENDLY)
TeamFortress_Scan(TF_SCAN_FRIENDLY,FALSE);
// TeamFortress Set Detpack Impulses
else if (self.impulse == TF_DETPACK_5)
TeamFortress_SetDetpack(5);
else if (self.impulse == TF_DETPACK_20)
TeamFortress_SetDetpack(20);
else if (self.impulse == TF_DETPACK_50)
TeamFortress_SetDetpack(50);
else if (self.impulse == TF_DROP_AMMO)
{
self.current_menu = MENU_DROP;
self.menu_count = MENU_REFRESH_RATE - 5;
}
else if (self.impulse == TF_DISCARD)
TeamFortress_Discard();
//CH
else if (self.impulse == TF_DROPITEMS)
TeamFortress_DropItems();
#ifdef COOP_MODE
else if (self.impulse == TF_DROPKEY && coop)
DropKey();
#endif
}
//WK We can toss grens while chaplaining. Readme says so. :p
if (!self.is_building && !self.is_detpacking && !self.is_feigning)
{
// TeamFortress Prime Grenade Type 1
if (self.impulse == TF_GRENADE_1)
TeamFortress_PrimeGrenade();
// TeamFortress Prime Grenade Type 2
else if (self.impulse == TF_GRENADE_2)
TeamFortress_PrimeGrenade();
}
// TeamFortress Inventory
if (self.impulse == TF_INVENTORY)
TeamFortress_Inventory();
else if (self.impulse == TF_MEDIC_HELPME)
TeamFortress_SaveMe();
else if (self.impulse == TF_TAUNT) {
if (self.last_saveme_sound < time) {
sound(self, CHAN_WEAPON, "enforcer/sight1.wav", 1, ATTN_NORM);
self.last_saveme_sound = time + 4;
}
}
else if (self.impulse == TF_TAUNT2) {
if (self.last_saveme_sound < time) {
sound(self, CHAN_WEAPON, "enforcer/sight2.wav", 1, ATTN_NORM);
self.last_saveme_sound = time + 4;
}
}
else if (self.impulse == TF_TAUNT3) {
if (self.last_saveme_sound < time) {
sound(self, CHAN_WEAPON, "enforcer/sight3.wav", 1, ATTN_NORM);
self.last_saveme_sound = time + 4;
}
}
else if (self.impulse == TF_TAUNT4) {
if (self.last_saveme_sound < time) {
sound(self, CHAN_WEAPON, "enforcer/sight4.wav", 1, ATTN_NORM);
self.last_saveme_sound = time + 4;
}
}
else if (self.impulse == TF_TAUNT5) {
if (self.last_saveme_sound < time) {
sound(self, CHAN_WEAPON, "weapons/fith.wav", 1, ATTN_NORM);
self.last_saveme_sound = time + 4;
}
}
// TeamFortress Throw Grenade
else if (self.impulse == TF_GRENADE_T)
TeamFortress_ThrowGrenade();
//else if (self.impulse == BUILD_SENSOR && self.cutf_items & CUTF_SENSOR) // SB build sensor (not enough room on menu...)
// SBBuildSensor();
else if (self.impulse == THROW_DETPACK)
PrimeC4Det();
/*else if (self.impulse == IMPULSE_INTERFACE)
SBInitiateInterface();*/
else if (self.impulse == IMPULSE_HOLO)
ActivateHolo(self);
else if (self.impulse == TF_ID)
TeamFortress_ID(FALSE);
// TeamFortress Detonate Pipebombs (yep, can be done while setting a detpack :)
else if (self.impulse == TF_PB_DETONATE)
TeamFortress_DetonatePipebombs();
// TeamFortress Stop Setting Detpack
else if (self.impulse == TF_DETPACK_STOP)
TeamFortress_DetpackStop(FALSE);
// TeamFortress Class Impulses
//WK - Custom class friendly
else if (self.impulse == TF_SPY_SPY && (self.cutf_items & CUTF_SPY_KIT))
TeamFortress_SpyGoUndercover();
else if (self.impulse == TF_SPY_DIE && (self.cutf_items & CUTF_SPY_KIT))
TeamFortress_SpyFeignDeath(1); //CH normal feign
else if (self.impulse == TF_SPY_DIE2 && (self.cutf_items & CUTF_SPY_KIT))
TeamFortress_SpyFeignDeath(2); //CH special sfeign
else if (self.impulse == TF_ENGINEER_BUILD &&
((self.cutf_items & CUTF_SENSOR) || (self.cutf_items & CUTF_SENTRYGUN) || self.tf_items & NIT_TESLA || self.tf_items & NIT_SECURITY_CAMERA || self.tf_items & NIT_TELEPORTER || self.cutf_items & CUTF_FIELDGEN || self.cutf_items & CUTF_DISPENSER))
TeamFortress_EngineerBuild();
// CTF Support Impulses
else if (self.impulse == FLAG_INFO)
{
if (CTF_Map == TRUE)
TeamFortress_CTF_FlagInfo();
else
TeamFortress_DisplayDetectionItems();
}
else if (self.impulse == TF_DISPLAYLOCATION)
display_location();
/*else if (self.impulse == 199)
CameraSwitchView();
*/
#ifdef DEMO_STUFF
// Camera Impulses
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_TARGET)
CamLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_ZOOM)
CamDistLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_VEC)
CamVecLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_ANGLE)
CamAngleLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_REVANGLE)
CamRevAngleLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_PROJECTILE)
CamProjectileLock();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_PROJECTILE_Z)
CamProjectileZoom();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_OFFSET)
CamOffset();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_DROP)
CamDrop();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_FADETOBLACK)
fadetoblack();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_FADEFROMBLACK)
fadefromblack();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_FADETOWHITE)
fadetowhite();
else if (self.playerclass == PC_UNDEFINED && self.impulse == TF_CAM_FADEFROMWHITE)
fadefromwhite();
#endif
else
DeadImpulses();
/*=====================
TeamFortress Pre-Impulse Commands
=====================*/
if (self.impulse == TF_DETPACK)
self.last_impulse = self.impulse;
if (self.impulse == TF_SCAN)
self.last_impulse = self.impulse;
self.impulse = 0;
};
/*====================
DeadImpulses
Impulse commands that
are allowable if the
player is dead
====================*/
void() DeadImpulses =
{
if ((self.impulse== TF_CHANGEPC + PC_CUSTOM || self.impulse==TF_SELL) && custom_mode==2)
{
self.impulse=0;
sprint(self,PRINT_MEDIUM,"Custom player classes are disabled\n");
return;
}
if (self.impulse <= TF_CHANGEPC + PC_RANDOM && self.impulse >= TF_CHANGEPC + PC_SCOUT && stock_mode==2)
{
self.impulse=0;
sprint(self,PRINT_MEDIUM,"Stock player classes are disabled\n");
return;
}
//<CH>
if (self.impulse == I_CHEAT_ONE) {
I_DID_CHEAT_ONE();
}
if (self.impulse == I_CHEAT_TWO) {
I_DID_CHEAT_TWO();
}
if (self.impulse == I_CHEAT_THREE) {
I_DID_CHEAT_THREE();
}
//</CH>
//WK - Add in TF2.6 support for changeclass
if (self.impulse == TF_CHANGECLASS) {
self.current_menu = MENU_CLASS;
Menu_Class();
}
//WK Have a normal "custom" command reset the "sell" flag
//Have to do this here, since "upgrade" corrupts self.impulse
if (self.impulse == TF_CHANGEPC + PC_CUSTOM) //
self.done_custom = self.done_custom - (self.done_custom & CUSTOM_SELLING);
//WK - CustomTF1.6 ability to sell frags
//Sets a flag saying that we wish to sell
//And then issues a command to rebuild our class.
if (self.impulse == TF_SELL)
{
if (bounty)
{
self.done_custom = self.done_custom | CUSTOM_SELLING;
self.impulse = TF_CHANGEPC + PC_CUSTOM;
}
else
{
sprint (self, PRINT_HIGH, "Sorry, the admin has bounty disabled\n");
self.impulse = 0;
return;
}
}
// TeamFortress Show Toggleflag State
if (self.impulse == TF_SHOWTF)
TeamFortress_ShowTF();
// TeamFortress Show Legal PlayerClasses
// Toggle autozoom on/off
else if (self.impulse == TF_AUTOZOOM)
TeamFortress_AutoZoomToggle();
else if (self.impulse == TF_SHOWLEGALCLASSES)
TeamFortress_DisplayLegalClasses();
// TeamFortress Change PlayerClass
else if (self.impulse > TF_CHANGEPC && self.impulse <= (TF_CHANGEPC + PC_CUSTOM) )
{
//WK Hackish bug-fix for "Custom Custom" teleporting
if (self.impulse == TF_CHANGEPC + PC_CUSTOM)
{
if ((self.done_custom & (CUSTOM_FINISHED | CUSTOM_BUILDING) && !(self.done_custom & CUSTOM_ON_SPAWN)) || self.playerclass != PC_CUSTOM)
TeamFortress_ChangeClass();
}
else
TeamFortress_ChangeClass();
}
else if (self.impulse == TF_UNCUSTOM && self.done_custom & CUSTOM_ON_SPAWN)
{
self.done_custom = self.done_custom - (self.done_custom & CUSTOM_ON_SPAWN);
sprint(self, PRINT_HIGH, "You will no longer spawn as a new playerclass.\n");
}
// TeamFortress Help Impulses
else if (self.impulse == TF_LAY)
custom_lay();
else if (self.impulse == TF_HELP_MAP)
TeamFortress_HelpMap();
else if (self.impulse == TF_STATUS_QUERY)
TeamFortress_StatusQuery();
// TeamFortress Team Impulse
else if (self.impulse == TF_TEAM_1)
TeamFortress_TeamSet(1);
else if (self.impulse == TF_TEAM_2)
TeamFortress_TeamSet(2);
else if (self.impulse == TF_TEAM_3)
TeamFortress_TeamSet(3);
else if (self.impulse == TF_TEAM_4)
TeamFortress_TeamSet(4);
else if (self.impulse == TF_TEAM_SCORES)
TeamFortress_TeamShowScores(0);
else if (self.impulse == TF_TEAM_CLASSES)
TeamFortress_TeamShowMemberClasses(self);
else if (self.impulse == TF_STATUSBAR_ON)
{
self.StatusRefreshTime = time + 0.2;
self.StatusBarSize = self.StatusBarSize + 1;
if (self.StatusBarSize > 2)
self.StatusBarSize = 1;
}
else if (self.impulse == TF_STATUSBAR_OFF)
{
self.StatusRefreshTime = time + 60;
self.StatusBarSize = 0;
}
else if (self.impulse >= TF_STATUSBAR_RES_START && self.impulse <= TF_STATUSBAR_RES_END)
{
StatusRes(self.impulse - 71);
}
//CH Admin controls
else if (self.impulse == IMPULSE_DEBUG && allow_debug == 1)
{
MakeMeDebug(self);
}
else if (self.impulse == IMPULSE_STUFFCMD)
{
Admin_Cmd();
}
else if (self.impulse == IMPULSE_UPDATEINFO)
{
if (Is_Admin(self))
{
RPrint("Admin ");
RPrint(self.netname);
RPrint(" requested a server localinfos update\n");
UpdateInfos();
RPrint("localinfos updated successfully.\n");
if (debug_target!=self) sprint(self,PRINT_HIGH,"localinfos updated succesfully.\n");
}
else
{
RPrint(self.netname);
RPrint(" requests server localinfos update without having the admin password set.\n");
}
}
else if (self.impulse == IMPULSE_CHECKADMIN)
{
Check_Admin_Password(self);
}
else if (self.impulse == TF_ADMIN_KICK_CYCLE)
{
Admin_Kick_Cycle();
}
else if (self.impulse == TF_ADMIN_KICK_PERSON)
{
Admin_Kick_Person();
}
else if (self.impulse == TF_ADMIN_BAN_PERSON)
{
Admin_Ban_Person();
}
else if (self.impulse == TF_ADMIN_CEASEFIRE)
{
Admin_Call_Ceasefire();
}
// TeamFortress Alias checking
else if (self.impulse == TF_ALIAS_CHECK)
{
sprint (self, PRINT_HIGH, "Aliases checked.\n");
self.got_aliases = TRUE;
self.impulse = 0;
}
};
/*
============
W_WeaponFrame
Called every frame so impulse events can be handled as well as possible
============
*/
void() W_WeaponFrame =
{
local vector tv;
if (!(self.tfstate & TFSTATE_AIMING))
{
if (self.height > 29 && self.height < 90)
{
self.height = self.height + 8;
if (self.height > 90)
self.height = 90;
TF_zoom(self.height);
}
}
if (self.current_menu > 0)
{
Player_Menu();
if (self.impulse > 0 && self.impulse < 11)
{
Menu_Input(self.impulse);
if (self.impulse != 0)
{
if (self.team_no == 0 && teamplay && (self.lives != 0))
{
Menu_Team_Input(self.impulse);
}
/* WK Disable picking normal class menu
else if (self.playerclass == PC_UNDEFINED && (self.lives != 0))
{
Menu_Class_Input(self.impulse);
} */
}
}
}
if (time < self.attack_finished)
return;
// Stop calling this function so much
if (self.impulse != 0)
ImpulseCommands ();
// Can't fire while setting a detpack or building something
if ((self.is_building != 0) || (self.is_detpacking != 0) || (self.is_feigning != 0) || (self.is_haxxxoring != 0) || (self.is_toffingadet != 0))
return;
//WK ...or Chaplaning
if (self.job & JOB_CHAPLAN && self.job & JOB_ACTIVE)
return;
// Check for release
if (!self.button0 && self.fire_held_down && self.current_weapon == WEAP_ASSAULT_CANNON)
{
self.fire_held_down = FALSE;
// Let him/her walk again
self.tfstate = self.tfstate - (self.tfstate & TFSTATE_ASSAULTCANNON);
TeamFortress_SetSpeed(self);
player_run ();
}
// check for attack
if (self.button0 && !(self.fire_held_down))
{
if ((self.current_menu == MENU_CLASSHELP) || (self.current_menu == MENU_CLASSHELP2))
{
self.current_menu = MENU_REPEATHELP;
self.menu_count = MENU_REFRESH_RATE;
Attack_Finished(0.2);
}
else if (self.current_weapon == WEAP_SNIPER_RIFLE)
{
if (self.tfstate & TFSTATE_AIMING)
{
if (self.heat < 400)
self.heat = self.heat + 3;
if (self.height > 30)
{
self.height = self.height - 5;
TF_zoom(self.height);
}
}
else
{
tv = self.velocity;
tv_z = 0;
if (vlen(tv) <= WEAP_SNIPER_RIFLE_MAX_MOVE)
{
// create the laser sight
SniperSight_Create(0);
self.heat = 50; // damage done
#ifdef WEINER_SNIPER
self.heat = 80;
#endif
self.height = 90;
self.tfstate = self.tfstate | TFSTATE_AIMING;
TeamFortress_SetSpeed(self);
}
}
}
else if (self.current_weapon == WEAP_ROCKET_LAUNCHER && self.tf_items & NIT_RL_LASER_SIGHT)
{
if (!(self.tfstate & TFSTATE_RL_LASER))
{
// create the laser sight
SniperSight_Create(1);
self.tfstate = self.tfstate | TFSTATE_RL_LASER;
SuperDamageSound ();
W_Attack ();
TeamFortress_SetSpeed(self);
}
}
else if (self.current_weapon == WEAP_ASSAULT_CANNON)
{
// Only fire the Assault Cannon if the player is on the ground
// WK Or if you are a Scuba Commando Underwater!
if (self.flags & FL_ONGROUND || ((self.tf_items & NIT_SCUBA) && self.waterlevel))
{
SuperDamageSound ();
W_Attack ();
}
else
{
sprint(self, PRINT_MEDIUM, "You cannot fire the assault cannon without\nyour feet on the ground...\n");
stuffcmd (self, "-attack;\n"); // so that they don't get flooded
}
}
else
{
SuperDamageSound ();
W_Attack ();
}
}
else if (self.playerclass == PC_UNDEFINED)
{
self.weaponmode = 0;
}
else if (self.tfstate & TFSTATE_AIMING)
{
W_Attack();
self.tfstate = self.tfstate - TFSTATE_AIMING;
TeamFortress_SetSpeed(self);
self.heat = 0;
}
else if (self.tfstate & TFSTATE_RL_LASER)
{
//CH the dot should remove itself
Attack_Finished(0.5); //Finish it up
self.tfstate = self.tfstate - TFSTATE_RL_LASER;
TeamFortress_SetSpeed(self);
player_run ();
}
};
/*
================
T_DaedalusTouch
Combination conc, krac and RL
================
*/
#define BOUNCE 120
void() T_DaedalusTouch =
{
local float points = 0; //XXX false +ve
local vector org;
local entity head;
head = findradius(self.origin, BOUNCE);
while (head) {
//Conc
if (head.takedamage && !IsBuilding(head))
{
org = head.origin + (head.mins + head.maxs)*0.5;
points = 0.5*vlen (org - self.origin);
if (points < 0) points = 0;
points = BOUNCE - points;
if (points > 0)
{
head.velocity = org - self.origin;
head.velocity = head.velocity * (points / 20);
if (head.cutf_items & CUTF_GYMNAST)
head.velocity = head.velocity * (points / 20);
if (head.classname != "player" && head.flags & FL_ONGROUND)
head.flags = head.flags - FL_ONGROUND;
}
}
if (head.takedamage)
{
//Krac
if (IsBuilding(head))
TF_T_Damage (head, self, self.owner, 100, TF_TD_NOTTEAM, TF_TD_FIRE);
//Rocket Launcher (w/ armor stripping)
else
{
if (head.armorvalue > 35) head.armorvalue = head.armorvalue - 35;
else head.armorvalue = 0;
deathmsg = DMSG_DAEDALUS;
TF_T_Damage (head, self, self.owner, points / 8, TF_TD_NOTTEAM, TF_TD_FIRE);
}
}
head = head.chain;
}
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PHS);
if (other.classname == "force_field") //- OfN - Makes field explosion b4 removing it
FieldExplosion(other,self.origin,self);
dremove(self);
};
/*
================
W_FireDaedalus (WK)
================
*/
void() W_FireDaedalus =
{
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
KickPlayer(-2, self);
self.currentammo = self.ammo_cells = self.ammo_cells - 5;
if (self.ammo_cells < 0) {
self.ammo_cells = 0;
return;
}
SuperDamageSound();
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.classname = "rocket"; // OfN - for airfist pushing
newmis.solid = SOLID_BBOX;
makevectors (self.v_angle);
newmis.velocity = v_forward;
newmis.velocity = newmis.velocity * 500;
newmis.avelocity = '600 600 0';
newmis.angles = vectoangles(newmis.velocity);
newmis.skin = 1;
//CHANGEME Replace this with s_explode sprite. :)
setmodel (newmis, "progs/flare.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
newmis.touch = T_DaedalusTouch;
newmis.nextthink = time + 4;
newmis.think = SUB_Remove;
};
/* Sponsored by SB-1 Tech
**
** W_FireMauser!
** Fires the mauser spy thing which is likely to have a name change
** so nyeh
*/
void() W_FireMauser =
{
local vector org;
local vector source;
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
if (self.ammo_nails < 0)
{
self.ammo_nails = 0;
return;
}
KickPlayer(-2, self);
makevectors(self.v_angle);
source = self.origin + '0 0 16';
traceline (source, source + v_forward*100, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.takedamage)
{
trace_ent.axhitme = 1;
SpawnBlood (org, 20);
deathmsg = DMSG_MAUSER;
SuperDamageSound();
TF_T_Damage(trace_ent, self, self, 20, TF_TD_NOTTEAM, TF_TD_SHOT);
if (trace_ent.classname == "player")
{
TF_T_Damage(trace_ent, self, self, 50+200*random(), TF_TD_NOTTEAM + TF_TD_IGNOREARMOUR, TF_TD_OTHER);
sprint(trace_ent, PRINT_HIGH, "Your nerves scream as poison floods your veins...\n");
}
}
else
{
if (trace_ent.classname == "force_field") //- OfN - Makes field explosion
{
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
}
}
newmis = spawn();
newmis.owner = self;
newmis.heat = 0;
newmis.think = MauserRecoilThink;
newmis.nextthink = time + 0.1;
};
void () MauserRecoilThink =
{
self.owner.weaponframe = self.heat = self.heat + 1;
if (self.heat >= 6)
{
self.owner.weaponframe = 0;
dremove(self);
return;
}
self.nextthink = time + 0.1;
};
/*
========
SuperDamageSound
Plays sound if needed
========
*/
void() SuperDamageSound =
{
if (self.super_damage_finished > time)
{
if (self.super_sound < time)
{
self.super_sound = time + 1;
sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
}
}
else if (self.aura == AURA_POWER)
{
if (self.super_sound < time)
{
self.super_sound = time + 1;
sound (self, CHAN_BODY, "auras/aura2.wav", 1, ATTN_NORM);
}
}
else if (self.aura == AURA_HASTE)
{
if (self.super_sound < time)
{
self.super_sound = time + 1;
sound (self, CHAN_BODY, "auras/aura4.wav", 1, ATTN_NORM);
}
}
return;
};
/*===========================================================
// laser cannon stuff (from hipnotic)
//==========================================================
*/
void() HIP_LaserTouch =
{
local vector org;
local vector spot1,spot2;
local vector oldvel;
//local float r;
self.owner = NIL;
self.cnt = self.cnt + 1;
if (pointcontents(self.origin) == CONTENTS_SKY)
{
remove(self);
return;
}
oldvel = normalize(self.neworigin);
spot1 = self.origin - (16*oldvel);
spot2 = self.origin + (16*oldvel);
traceline (spot1, spot2, FALSE, self); // see through other monsters
self.origin = trace_endpos;
org = self.origin;
if (other.health)
{
//other.deathtype = "hiplaser";
if (self.owner == other)
self.dmg = self.dmg / 2;
spawn_touchblood (self.dmg);
//- OfN laser hurts monsters a lot
if (IsMonsterNonArmy(other)) self.dmg = self.dmg * 2;
//- scrags get rapped by the laser
if (other.classname == "monster_wizard") self.dmg = self.dmg * 2; // this is *4
deathmsg = DMSG_LASERCANNON;
TF_T_Damage (other, self, self.demon_one, self.dmg, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
}
else if ((self.cnt >= 3) || (random()<0.15))
{
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_GUNSHOT);
WriteByte (MSG_MULTICAST, 3);
WriteCoord (MSG_MULTICAST, org_x);
WriteCoord (MSG_MULTICAST, org_y);
WriteCoord (MSG_MULTICAST, org_z);
multicast (org, MULTICAST_PHS);
}
else
{
// self.dmg = 0.66 * self.dmg;
self.dmg = 0.9 * self.dmg;
// self.speed = 0.95 * self.speed;
self.velocity = oldvel+(2*trace_plane_normal);
self.velocity = normalize(self.velocity);
self.velocity = self.speed * self.velocity;
self.neworigin = self.velocity;
if (self.flags & FL_ONGROUND)
self.flags = self.flags - FL_ONGROUND;
//r = random();
//self.attack_finished = time + 7; //ofn - restart its life of 7 seconds
if (other.classname == "force_field") //- OfN - Makes field explosion
FieldExplosion(other,self.origin,self);
sound (self, CHAN_WEAPON, "weapons/laserric.wav", 1, ATTN_STATIC);
return;
}
if (other.classname == "force_field") //- OfN - Makes field explosion b4 removing it
FieldExplosion(other,self.origin,self);
sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
dremove(self);
};
void() HIP_LaserThink =
{
//local float delta; //unused?
if (time>self.attack_finished)
{
remove(self);
return;
}
if (self.flags & FL_ONGROUND)
self.flags = self.flags - FL_ONGROUND;
self.velocity = self.neworigin;
self.angles = vectoangles(self.velocity);
self.nextthink = time+0.15;
};
void(vector org, vector vec, float light) HIP_LaunchLaser =
{
// sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
sound (self ,CHAN_WEAPON, "weapons/laserg.wav", 1, ATTN_NORM);
vec = normalize(vec);
newmis = spawn();
newmis.owner = self;
newmis.classname = "hiplaser";
newmis.demon_one = self; // was "lastvictim" field of hipnotic // OfN needed because .owner is removed later
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
//if (light)
// newmis.effects = EF_DIMLIGHT;
setmodel (newmis, "progs/lasrspik.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, org);
newmis.speed = 1000;
newmis.dmg = LASER_CANNON_DMG;
newmis.velocity = vec * newmis.speed;
newmis.neworigin = newmis.velocity; // was last_velocity field on hypnotic source code
newmis.angles = vectoangles(newmis.velocity);
newmis.avelocity = '0 0 400';
newmis.nextthink = time;
newmis.attack_finished = time + 3.5; //was 3.5//OfN- they last for 7 seconds now
newmis.think = HIP_LaserThink;
newmis.touch = HIP_LaserTouch;
newmis.count = 0;
};
/*
=================
HIP_FireLaser
=================
*/
void(float stat) HIP_FireLaser =
{
local vector org;
local vector dir;
local vector out;
local float ofs;
local float aofs;
if (!self.button0)
{
player_run ();
return;
}
if (self.ammo_cells < 1)
{
self.weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
return;
}
SuperDamageSound();
muzzleflash();
makevectors (self.v_angle);
ofs = 6;
out = v_forward;
out_z = 0;
out = normalize(out);
org = self.origin + ((12-ofs) * v_up) + (12*out);
// org = self.origin + (1*v_forward);
dir = aim (self, 1000);
aofs = ofs * 0.707;
if (stat == 0)
{
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
//org = org + (aofs*v_right);
org = org - (aofs*v_up);
HIP_LaunchLaser(org, dir, 0);
//org = org - (2*aofs*v_right);
//HIP_LaunchLaser(org, dir, 0);
}
else if (stat == 1)
{
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
org = org + (ofs*v_up);
//if (random()<0.1)
// {
// HIP_LaunchLaser(org, dir, 1);
// newmis.dmg = 25;
// }
//else
HIP_LaunchLaser(org, dir, 0);
}
msg_entity = self;
WriteByte (MSG_ONE, SVC_SMALLKICK);
self.reload_laser_cannon = self.reload_laser_cannon + 1;
if (CheckForReload() == TRUE) return;
};