/*====================================================== 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; local vector org; 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); if (self.classname == "player") { if (other.classname == "player") trace_ent.velocity_z = trace_ent.velocity_z + 400; } } 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) * 2 / 3; if (excess < 50) excess = 50; 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; } // 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(); } // //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; };