/* SB Items. New items for use with Custom TF 3.2 (or something) */ // Internal prototypes void() AntiGravGrenadeExplode; // antigrav goes boom void() AntiGravGrenadeTimer; // controls antigrav decay or whatever you call it void(entity inflictor, entity attacker, float bounce, entity ignore) T_RadiusAntiGrav; // bang void() MotionSensorIdle; // motion sensor sitting float() MotionSensorFindTarget; // sensor scans for target void() MotionSensorDie; // I wonder what this does void() MotionSensorSpawn; // let's make a sensor void() SensorBeAlarmed; // very alarming void() TeamFortress_C4DetpackTouch; void() ThrowC4Det; //void() SBInitiateInterface; float(entity hacked, float r) ReturnHackDelay; void() SBHackDotTimerThink; /*void() SwitchToCamera; void() SwitchFromCamera; void() CameraSwitchView;*/ // External functions void() ConcussionGrenadeTouch; void() Security_Camera_Pain; float(float tno, entity ignore, string st) teamsprint; void() TeamFortress_DetpackTouch; void() TeamFortress_DetpackCountDown; void() TeamFortress_DetpackExplode; void() TeamFortress_DetpackDisarm; void() SBFireInterface; // -- OfN -- void(float tno, entity ignore) teamprefixsprint; //-------------------------------------------------------------- /* void() CameraSwitchView = { if (!self.has_camera) return; if (self.is_cameraviewing) SwitchFromCamera(); else SwitchToCamera(); }; void() SwitchToCamera = { local entity camera; local float done; if (!self.has_camera) return; if (self.is_cameraviewing) return; camera = find(world, classname, "building_camera"); if (camera.real_owner == self) done = #TRUE; while (!done) { camera = find(camera, classname, "building_camera"); if (camera.real_owner == self) done = #TRUE; if (camera == world) done = #TRUE; } if (camera == world) return; msg_entity = self; WriteByte(#MSG_ONE, #SVC_SETVIEWPORT); WriteEntity(#MSG_ONE, camera); WriteByte(#MSG_ONE, #SVC_SETANGLES); WriteAngle(#MSG_ONE, camera.angles_x); WriteAngle(#MSG_ONE, camera.angles_y); WriteAngle(#MSG_ONE, camera.angles_z); self.fixangle = #TRUE; self.is_cameraviewing = #TRUE; self.t_s_h = self.weaponmodel; self.weaponmodel= ""; self.view_ofs = '0 0 0'; sprint(self, #PRINT_HIGH, "Camera view activated.\n"); }; void() SwitchFromCamera = { if (!self.has_camera) return; if (!self.is_cameraviewing) return; msg_entity = self; WriteByte(#MSG_ONE, #SVC_SETVIEWPORT); WriteEntity(#MSG_ONE, self); WriteByte(#MSG_ONE, #SVC_SETANGLES); WriteAngle(#MSG_ONE, self.angles_x); WriteAngle(#MSG_ONE, self.angles_y); WriteAngle(#MSG_ONE, self.angles_z); self.fixangle = #FALSE; self.weaponmodel = self.t_s_h; self.view_ofs = '0 0 22'; self.is_cameraviewing = #FALSE; }; */ // SB Tossable Detpack! // A 10 second detpack that can be thrown around corners void() PrimeC4Det = { local entity te; if (!(self.cutf_items & #CUTF_TOSSABLEDET)) { sprint (self, #PRINT_HIGH, "You do not have the C4 tossable detpack.\n"); return; } if (self.ammo_c4det < 1) { sprint (self, #PRINT_HIGH, "Looks like you're out of C4.\n"); return; } if (self.is_detpacking || self.is_toffingadet) { sprint (self, #PRINT_HIGH, "You can only set one detpack at once, throwable or otherwise!\n"); return; } if (self.is_haxxxoring) { sprint (self, #PRINT_HIGH, "You can't set a detpack while hacking.\n"); return; } te = spawn(); te.owner = self; te.nextthink = time + #WEAP_DETPACK_SETTIME; te.think = ThrowC4Det; te.classname = "timer"; te.netname = "C4detpack_timer"; self.is_toffingadet = 1; self.tfstate = self.tfstate | #TFSTATE_C4THROW; TeamFortress_SetSpeed(self); sprint(self, #PRINT_HIGH, "Arming detpack...\n"); }; void() TeamFortress_C4DetpackTouch = { local entity disarm; if (other.classname != "player") return; //WK if (other.playerclass != #PC_SCOUT) if (!(other.tf_items & #NIT_SCANNER)) return; if (self.weaponmode == 1) return; if (Teammate(self.owner.team_no,other.team_no)) return; makeImmune(other,time + 2); //other.immune_to_check = time + 2; other.tfstate = other.tfstate | #TFSTATE_CANT_MOVE; sprint(other, #PRINT_HIGH, "Disarming detpack...\n"); #ifdef QUAKE_WORLD TeamFortress_SetSpeed(other); #else other.pausetime = time + #WEAP_DETPACK_DISARMTIME; #endif // Spawn disarming entity disarm = spawn(); disarm.movetype = #MOVETYPE_NONE; //WK M3 Bug Hunt disarm.owner = other; // the scout disarm.enemy = self; // the detpack disarm.classname = "timer"; disarm.nextthink = time + #WEAP_DETPACK_DISARMTIME; disarm.think = TeamFortress_DetpackDisarm; self.weaponmode = 1; // indicates disarming self.enemy = other; // points to scout self.observer_list = disarm; }; void(entity ignore, string st, string st2, string st3, string st4, string st5, string st6) teamsprint6; void() ThrowC4Det = { local entity user; local entity oldself; self.owner.is_toffingadet = 0; self.owner.ammo_c4det = self.owner.ammo_c4det - 1; user = self.owner; sound (user, #CHAN_WEAPON, "weapons/grenade.wav", 1, #ATTN_NORM); KickPlayer(-1, user); newmis = spawn (); newmis.owner = user; newmis.movetype = #MOVETYPE_BOUNCE; newmis.solid = #SOLID_BBOX; newmis.solid = #SOLID_TRIGGER; newmis.classname = "detpack"; // for identify it on airfist pushable? routine //newmis.netname = "C4"; // set grenade speed makevectors (user.v_angle); if (user.deadflag) { // if user is dead, throw grenade directly up newmis.velocity = '0 0 200'; } else { if (user.v_angle_x) { newmis.velocity = v_forward*600 + v_up * 200 + random()*v_right*10 + random()*v_up*10; } else { newmis.velocity = aim(user, 10000); newmis.velocity = newmis.velocity * 600; newmis.velocity_z = 200; } } newmis.angles = vectoangles(newmis.velocity); newmis.touch = TeamFortress_C4DetpackTouch; newmis.think = TeamFortress_DetpackExplode; newmis.nextthink = time + 10; newmis.avelocity = '300 300 300'; setmodel (newmis, "progs/detpack.mdl"); setsize (newmis, '-16 -16 -8', '16 16 8'); setorigin (newmis, user.origin); oldself = self; self = user; #ifdef DEMO_STUFF if (live_camera) CamProjectileLockOn(); #endif local entity countd; newmis.weaponmode = 0; // Detpack weaponmode = 1 when disarming sound (newmis, #CHAN_WEAPON, "doors/medtry.wav", 1, #ATTN_NORM); //CH play set detpack sound // Create the CountDown entity countd = spawn(); newmis.linked_list = countd; // attach count to its detpack countd.think = TeamFortress_DetpackCountDown; countd.health = 9; countd.nextthink = time + 1; countd.owner = newmis.owner; countd.movetype = #MOVETYPE_BOUNCE; countd.classname = "countdown_timer"; // Don't call it timer, because we // don't want it removed if player dies countd.enemy = newmis; newmis.oldenemy = countd; sprint(self, #PRINT_HIGH, "Detpack armed!\n"); teamprefixsprint(self.team_no,self); teamsprint6(self,self.netname," throws a C4!\n","","","",""); self.tfstate = self.tfstate - (self.tfstate & #TFSTATE_C4THROW); TeamFortress_SetSpeed(self); // let's roll }; // SB Motion Sensor // Sits in shadows and lights up and makes noise when player goes near void() SBBuildSensor = { if (self.ammo_cells >= #BUILD_COST_SENSOR && self.has_sensor == 0) { self.ammo_cells = self.ammo_cells - #BUILD_COST_SENSOR; MotionSensorSpawn(); self.has_sensor = 1; sprint(self, #PRINT_HIGH, "You place the motion sensor.\n"); self.option = time + 2; } else if (self.ammo_cells < #BUILD_COST_SENSOR && self.has_sensor == 0) sprint(self, #PRINT_HIGH, "You do not have enough metal to build a motion sensor.\n"); else { if (self.option < time) // avoids ppl overflowing by destroying/building it repeatedly { Find_And_Dmg("building_sensor", self, 1); sprint(self, #PRINT_HIGH, "You detonate your motion sensor.\n"); self.has_sensor = 0; } } }; void() MotionSensorTossTouch = { if (other != world || other == self.real_owner) return; if (pointcontents(self.origin) == #CONTENT_SKY || pointcontents(self.origin + '0 0 2') == #CONTENT_SKY || pointcontents(self.origin) == #CONTENT_SOLID) { MotionSensorDie(); return; } //CH sees where landed and adjusts to proper things if (pointcontents(self.origin + '0 0 1') == #CONTENT_SOLID) self.origin = self.origin - '0 0 12'; if (pointcontents(self.origin - '0 0 1') == #CONTENT_SOLID) self.origin = self.origin + '0 0 4'; if (pointcontents(self.origin + '0 1 0') == #CONTENT_SOLID) self.origin = self.origin - '0 16 0'; if (pointcontents(self.origin - '0 1 0') == #CONTENT_SOLID) self.origin = self.origin + '0 16 0'; if (pointcontents(self.origin + '1 0 0') == #CONTENT_SOLID) self.origin = self.origin - '16 0 0'; if (pointcontents(self.origin + '1 0 0') == #CONTENT_SOLID) self.origin = self.origin + '16 0 0'; setorigin (self, self.origin); if (pointcontents(self.origin) == #CONTENT_SKY || pointcontents(self.origin + '0 0 2') == #CONTENT_SKY || pointcontents(self.origin) == #CONTENT_SOLID) { MotionSensorDie(); return; } teamprefixsprint(self.real_owner.team_no,self.real_owner); //- OfN teamsprint(self.real_owner.team_no, self.real_owner, self.real_owner.netname); teamsprint(self.real_owner.team_no, self.real_owner, " has built a Motion Sensor.\n"); self.movetype = #MOVETYPE_NONE; setsize (self, '-16 -16 -6', '16 16 10'); self.solid = #SOLID_BBOX; self.takedamage = #DAMAGE_AIM; sound (self, #CHAN_WEAPON, "weapons/guerilla_set.wav", 1, #ATTN_NORM); self.think = MotionSensorIdle; self.nextthink = time + 1; }; void() MotionSensorIdle = { if (MotionSensorFindTarget()) self.nextthink = time + 2.4; //if found wait 2.5 sec before do another check else self.nextthink = time + 0.05; // lots per sec self.think = MotionSensorIdle; }; float() MotionSensorFindTarget = { local entity client; local float r, gotone, loopc; // Try a few checks to make it react faster r = 0; loopc = 0; gotone = #FALSE; if (self.is_malfunctioning & #SCREWUP_THREE) return #FALSE; local float trange; //- OfN - Hack trange=300; // was 250 if (self.num_mines & #IMPROVED_ONE) trange=500; // was 400 //CH Theortetically this will check every client on the server now while (loopc < 32 && gotone == #FALSE) { client = checkclient(); gotone = #TRUE; if (!client) gotone = #FALSE; else if (!Pharse_Client(client, self, 1, trange, 0, 1)) gotone = #FALSE; loopc = loopc + 1; if (gotone) loopc = 1000; } if (!gotone) { self.effects = 0; self.skin=1; return #FALSE; } // Found a Target self.enemy = client; /*if (self.enemy.classname != "player") // OfN - wtf does this? { self.enemy = self.enemy.enemy; if (self.enemy.classname != "player") { self.enemy = world; return #FALSE; } }*/ // OfN - wtf does this? // SPIES, only returned by pharseclient if sensor is able to uncover them -changed if (Teammate(self.enemy.undercover_team,self.team_no) && self.num_mines & #IMPROVED_FOUR) { /*if (!(self.enemy.cutf_items & #CUTF_JAMMER)) // if they dont have a scanner jammer remove their disguise {*/ Spy_RemoveDisguise(self.enemy); sprint(self.real_owner, #PRINT_HIGH, "Your motion sensor detects a spy!\n"); sprint(self.enemy, #PRINT_HIGH, "That motion sensor knows you are a spy!\n"); //} //else // return #FALSE; // removed cause sensors alarm is activated anyway, even if they will not uncover them } // THIEVES, ALWAYS DETECTED BUT SENSOR ONLY UNCOVERS THEM IF HACKED TO DO- changed if (self.enemy.classname=="player") { if (self.enemy.job & #JOB_THIEF && (self.enemy.job & #JOB_ACTIVE || self.enemy.job & #JOB_FULL_HIDE)) { if (self.num_mines & #IMPROVED_SEVEN) { sprint(self.real_owner, #PRINT_HIGH, "Your motion sensor detects a thief!\n"); sprint(self.enemy, #PRINT_HIGH, "That motion sensor can see you!\n"); RevealThief(self.enemy,#TRUE); } } } if (!(self.is_malfunctioning & #SCREWUP_ONE)) sound(self, #CHAN_WEAPON, "misc/enemy.wav", 1, #ATTN_NORM); if (!(self.is_malfunctioning & #SCREWUP_TWO)) { self.effects = #EF_BRIGHTLIGHT; self.skin=0;} sprint(self.real_owner,#PRINT_HIGH,"Your motion sensor reports enemy presence!\n"); self.think = SensorBeAlarmed; return #TRUE; }; void() SensorBeAlarmed = { if (MotionSensorFindTarget()) { if (!(self.is_malfunctioning & #SCREWUP_ONE)) sound(self, #CHAN_WEAPON, "misc/enemy.wav", 1, #ATTN_NORM); self.nextthink = 2.4; } else { self.think = MotionSensorIdle; self.effects = 0; self.nextthink = 1; /// self.skin=1; } }; void() MotionSensorSpawn = { self.has_sensor = #TRUE; newmis = spawn(); newmis.movetype = #MOVETYPE_BOUNCE; setsize (newmis, '0 0 0', '0 0 0'); // setsize (newmis, '-8 -8 -8', '8 8 8'); newmis.solid = #SOLID_BBOX; newmis.takedamage = #DAMAGE_AIM; newmis.classname = "building_sensor"; newmis.netname = "motion_sensor"; setorigin (newmis, self.origin); newmis.owner = world; newmis.real_owner = self; makevectors (self.v_angle); newmis.avelocity = '0 0 0'; newmis.velocity = v_forward*800 + v_up * 200 + v_right*10 + v_up*10; newmis.angles = '0 0 0'; newmis.angles_y = anglemod(self.angles_y + 180); // newmis.skin = 1; newmis.th_die = MotionSensorDie; // Death function newmis.th_pain = Security_Camera_Pain; // may as well use this eh //newmis.mdl = "progs/s_light.spr"; //CH temp model newmis.mdl = "progs/sencer.mdl"; newmis.skin=1; setmodel (newmis, newmis.mdl); newmis.team_no = self.team_no; newmis.colormap = self.colormap; newmis.heat = 0; //Beeps newmis.health = newmis.max_health = #BUILD_HEALTH_SENSOR; newmis.touch = MotionSensorTossTouch; newmis.num_mines=0; // OfN - reset HACKER improvements W_SetCurrentAmmo(); }; void() MotionSensorDie = { sprint(self.real_owner, #PRINT_HIGH, "Your motion sensor was destroyed.\n"); self.real_owner.has_sensor = #FALSE; // ThrowGib("progs/tgib1.mdl", -70); // ThrowGib("progs/tgib2.mdl", -70); // ThrowGib("progs/tgib3.mdl", -70); WriteByte (#MSG_BROADCAST, #SVC_TEMPENTITY); WriteByte (#MSG_BROADCAST, #TE_EXPLOSION); WriteCoord (#MSG_BROADCAST, self.origin_x); WriteCoord (#MSG_BROADCAST, self.origin_y); WriteCoord (#MSG_BROADCAST, self.origin_z); #ifdef QUAKE_WORLD multicast (self.origin, #MULTICAST_PHS); dremove(self); #else BecomeExplosion (); #endif }; // SB AntiGrav Grenade(tm) // Screws over a player's gravity for a short time // // Uses the conc gren's touch function - why repeat it with an identical one? void() AntiGravGrenadeExplode = { T_RadiusAntiGrav (self, self.owner, 100, world); #ifdef DEMO_STUFF // Remove any camera's locks on this missile if (self.enemy) CamProjectileLockOff(); #endif WriteByte (#MSG_BROADCAST, #SVC_TEMPENTITY); WriteByte (#MSG_BROADCAST, #TE_EXPLOSION); WriteCoord (#MSG_BROADCAST, self.origin_x); WriteCoord (#MSG_BROADCAST, self.origin_y); WriteCoord (#MSG_BROADCAST, self.origin_z); #ifdef QUAKE_WORLD multicast (self.origin, #MULTICAST_PHS); dremove(self); #else BecomeExplosion (); #endif }; // Bounces the enemy a bit and screws over their gravity :) void(entity inflictor, entity attacker, float bounce, entity ignore) T_RadiusAntiGrav = { local float points; local entity head, te; local vector org; local string st; head = findradius(inflictor.origin, bounce+40); while (head) { if (head != ignore) { if (head.takedamage) { org = head.origin + (head.mins + head.maxs)*0.5; points = 0.5*vlen (org - inflictor.origin); if (points < 0) points = 0; points = bounce - points; if (self.cutf_items & #CUTF_GYMNAST) points = points * 2; if (!IsBuilding(head) && points > 0) { // Bounce!! head.velocity = org - inflictor.origin; head.velocity = head.velocity * (points / 20); if (head.classname != "player") { if(head.flags & #FL_ONGROUND) head.flags = head.flags - #FL_ONGROUND; } else { //WK Add cheat immunity since they fly makeImmune(head,time+3); // Turn on antigrav // If it's already on, restore it to full time // Try to find a concusstimer entity for this player te = find(world, classname, "timer"); while (((te.owner != head) || (te.think != AntiGravGrenadeTimer)) && (te != world)) te = find(te, classname, "timer"); if (te != world) { head.gravity = 0.3 * random(); te.health = 100; te.nextthink = time + #GR_CONCUSS_TIME; } else { head.gravity = 0.3 * random(); stuffcmd(head,"bf\n"); // Create a timer entity te = spawn(); te.nextthink = time + #GR_CONCUSS_TIME; te.think = AntiGravGrenadeTimer; te.team_no = attacker.team_no; te.classname = "timer"; te.owner = head; te.health = 100; } } } } } head = head.chain; } }; // Timer used to control antigrav effects void() AntiGravGrenadeTimer = { local string st; if (self.owner.invincible_finished > time) { self.owner.gravity = 1; dremove(self); return; } self.health = self.health - #GR_CONCUSS_DEC * 2; // hwguy recovers twice as fast - heh heh if (self.owner.cutf_items & #CUTF_HWGUY) self.health = self.health - #GR_CONCUSS_DEC * 2; if (self.health < 0) self.health = 0; self.nextthink = time + #GR_CONCUSS_TIME; if (self.health == 0) { self.owner.gravity = 1; sprint(self.owner, #PRINT_HIGH, "Your weight feels normal again.\n"); dremove(self); } };