mirror of
https://git.code.sf.net/p/quake/prozac-qfcc
synced 2024-11-23 20:52:29 +00:00
c8157f4105
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)
5157 lines
129 KiB
C++
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;
|
|
};
|