1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525 |
- /*
- client.qc
- client functions
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to:
- Free Software Foundation, Inc.
- 59 Temple Place - Suite 330
- Boston, MA 02111-1307, USA
- */
- // prototypes
- void () W_WeaponFrame;
- void() W_SetCurrentAmmo;
- void() player_pain;
- void() player_stand1;
- void (vector org) spawn_tfog;
- void (vector org, entity death_owner) spawn_tdeath;
- float modelindex_eyes, modelindex_player;
- /*
- =============================================================================
- LEVEL CHANGING / INTERMISSION
- =============================================================================
- */
- string nextmap;
- float intermission_running;
- float intermission_exittime;
- /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
- This is the camera point for the intermission.
- Use mangle instead of angle, so you can set pitch or roll as well as yaw. 'pitch roll yaw'
- */
- void() info_intermission =
- {
- self.angles = self.mangle; // so C can get at it
- };
- void() SetChangeParms =
- {
- if (self.health <= 0)
- {
- SetNewParms ();
- return;
- }
-
- // remove items
- self.items = self.items - (self.items &
- (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
-
- // cap super health
- if (self.health > 100)
- self.health = 100;
- if (self.health < 50)
- self.health = 50;
- parm1 = self.items;
- parm2 = self.health;
- parm3 = self.armorvalue;
- if (self.ammo_shells < 25)
- parm4 = 25;
- else
- parm4 = self.ammo_shells;
- parm5 = self.ammo_nails;
- parm6 = self.ammo_rockets;
- parm7 = self.ammo_cells;
- parm8 = self.weapon;
- parm9 = self.armortype * 100;
- };
- void() SetNewParms =
- {
- parm1 = IT_SHOTGUN | IT_AXE;
- parm2 = 100;
- parm3 = 0;
- parm4 = 25;
- parm5 = 0;
- parm6 = 0;
- parm7 = 0;
- parm8 = 1;
- parm9 = 0;
- };
- void() DecodeLevelParms =
- {
- if (serverflags)
- {
- if (world.model == "maps/start.bsp")
- SetNewParms (); // take away all stuff on starting new episode
- }
-
- self.items = parm1;
- self.health = parm2;
- self.armorvalue = parm3;
- self.ammo_shells = parm4;
- self.ammo_nails = parm5;
- self.ammo_rockets = parm6;
- self.ammo_cells = parm7;
- self.weapon = parm8;
- self.armortype = parm9 * 0.01;
- };
- /*
- ============
- FindIntermission
- Returns the entity to view from
- ============
- */
- entity() FindIntermission =
- {
- local entity spot;
- local float cyc;
- // look for info_intermission first
- spot = find (world, classname, "info_intermission");
- if (spot)
- { // pick a random one
- cyc = random() * 4;
- while (cyc > 1)
- {
- spot = find (spot, classname, "info_intermission");
- if (!spot)
- spot = find (spot, classname, "info_intermission");
- cyc = cyc - 1;
- }
- return spot;
- }
- // then look for the start position
- spot = find (world, classname, "info_player_start");
- if (spot)
- return spot;
-
- objerror ("FindIntermission: no spot");
- };
- void() GotoNextMap =
- {
- local string newmap;
- //ZOID: 12-13-96, samelevel is overloaded, only 1 works for same level
- if (cvar("samelevel") == 1) // if samelevel is set, stay on same level
- changelevel (mapname);
- else {
- // configurable map lists, see if the current map exists as a
- // serverinfo/localinfo var
- newmap = infokey(world, mapname);
- if (newmap != "")
- changelevel (newmap);
- else
- changelevel (nextmap);
- }
- };
- /*
- ============
- IntermissionThink
- When the player presses attack or jump, change to the next level
- ============
- */
- void() IntermissionThink =
- {
- if (time < intermission_exittime)
- return;
- if (!self.button0 && !self.button1 && !self.button2)
- return;
-
- GotoNextMap ();
- };
- /*
- ============
- execute_changelevel
- The global "nextmap" has been set previously.
- Take the players to the intermission spot
- ============
- */
- void() execute_changelevel =
- {
- local entity pos;
- intermission_running = 1;
-
- // enforce a wait time before allowing changelevel
- intermission_exittime = time + 5;
- pos = FindIntermission ();
- // play intermission music
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_INTERMISSION);
- WriteCoord (MSG_ALL, pos.origin_x);
- WriteCoord (MSG_ALL, pos.origin_y);
- WriteCoord (MSG_ALL, pos.origin_z);
- WriteAngle (MSG_ALL, pos.mangle_x);
- WriteAngle (MSG_ALL, pos.mangle_y);
- WriteAngle (MSG_ALL, pos.mangle_z);
-
- other = find (world, classname, "player");
- while (other != world)
- {
- other.takedamage = DAMAGE_NO;
- other.solid = SOLID_NOT;
- other.movetype = MOVETYPE_NONE;
- other.modelindex = 0;
- other = find (other, classname, "player");
- }
- };
- void() changelevel_touch =
- {
- local entity pos;
- if (other.classname != "player")
- return;
- // if "noexit" is set, blow up the player trying to leave
- //ZOID, 12-13-96, noexit isn't supported in QW. Overload samelevel
- // if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
- if ((cvar("samelevel") == 2) || ((cvar("samelevel") == 3) && (mapname != "start")))
- {
- T_Damage (other, self, self, 50000);
- return;
- }
- bprint (PRINT_HIGH, other.netname);
- bprint (PRINT_HIGH," exited the level\n");
-
- nextmap = self.map;
- SUB_UseTargets ();
- self.touch = SUB_Null;
- // we can't move people right now, because touch functions are called
- // in the middle of C movement code, so set a think time to do it
- self.think = execute_changelevel;
- self.nextthink = time + 0.1;
- };
- /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
- When the player touches this, he gets sent to the map listed in the "map" variable. Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
- */
- void() trigger_changelevel =
- {
- if (!self.map)
- objerror ("chagnelevel trigger doesn't have map");
-
- InitTrigger ();
- self.touch = changelevel_touch;
- };
- /*
- =============================================================================
- PLAYER GAME EDGE FUNCTIONS
- =============================================================================
- */
- void() set_suicide_frame;
- // called by ClientKill and DeadThink
- void() respawn =
- {
- // make a copy of the dead body for appearances sake
- CopyToBodyQue (self);
- // set default spawn parms
- SetNewParms ();
- // respawn
- PutClientInServer ();
- };
- /*
- ============
- ClientKill
- Player entered the suicide command
- ============
- */
- void() ClientKill =
- {
- bprint (PRINT_MEDIUM, self.netname);
- bprint (PRINT_MEDIUM, " suicides\n");
- set_suicide_frame ();
- self.modelindex = modelindex_player;
- logfrag (self, self);
- self.frags = self.frags - 2; // extra penalty
- respawn ();
- };
- float(vector v) CheckSpawnPoint =
- {
- return FALSE;
- };
- /*
- ============
- SelectSpawnPoint
- Returns the entity to spawn at
- ============
- */
- entity() SelectSpawnPoint =
- {
- local entity spot, newspot, thing;
- local float numspots, totalspots;
- local float rnum, pcount;
- local float rs;
- local entity spots;
- numspots = 0;
- totalspots = 0;
- // testinfo_player_start is only found in regioned levels
- spot = find (world, classname, "testplayerstart");
- if (spot)
- return spot;
-
- // choose a info_player_deathmatch point
- // ok, find all spots that don't have players nearby
- spots = world;
- spot = find (world, classname, "info_player_deathmatch");
- while (spot)
- {
- totalspots = totalspots + 1;
- thing=findradius(spot.origin, 84);
- pcount=0;
- while (thing)
- {
- if (thing.classname == "player")
- pcount=pcount + 1;
- thing=thing.chain;
- }
- if (pcount == 0) {
- spot.goalentity = spots;
- spots = spot;
- numspots = numspots + 1;
- }
- // Get the next spot in the chain
- spot = find (spot, classname, "info_player_deathmatch");
- }
- totalspots=totalspots - 1;
- if (!numspots) {
- // ack, they are all full, just pick one at random
- // bprint (PRINT_HIGH, "Ackk! All spots are full. Selecting random spawn spot\n");
- totalspots = rint((random() * totalspots));
- spot = find (world, classname, "info_player_deathmatch");
- while (totalspots > 0) {
- totalspots = totalspots - 1;
- spot = find (spot, classname, "info_player_deathmatch");
- }
- return spot;
- }
-
- // We now have the number of spots available on the map in numspots
- // Generate a random number between 1 and numspots
- numspots = numspots - 1;
-
- numspots = rint((random() * numspots ) );
- spot = spots;
- while (numspots > 0) {
- spot = spot.goalentity;
- numspots = numspots - 1;
- }
- return spot;
- };
- void() DecodeLevelParms;
- void() PlayerDie;
- /*
- ===========
- ValidateUser
- ============
- */
- float(entity e) ValidateUser =
- {
- /*
- local string s;
- local string userclan;
- local float rank, rankmin, rankmax;
- //
- // if the server has set "clan1" and "clan2", then it
- // is a clan match that will allow only those two clans in
- //
- s = serverinfo("clan1");
- if (s)
- {
- userclan = masterinfo(e,"clan");
- if (s == userclan)
- return true;
- s = serverinfo("clan2");
- if (s == userclan)
- return true;
- return false;
- }
- //
- // if the server has set "rankmin" and/or "rankmax" then
- // the users rank must be between those two values
- //
- s = masterinfo (e, "rank");
- rank = stof (s);
- s = serverinfo("rankmin");
- if (s)
- {
- rankmin = stof (s);
- if (rank < rankmin)
- return false;
- }
- s = serverinfo("rankmax");
- if (s)
- {
- rankmax = stof (s);
- if (rankmax < rank)
- return false;
- }
- return true;
- */
- };
- /*
- ===========
- PutClientInServer
- called each time a player enters a new level
- ============
- */
- void() PutClientInServer =
- {
- local entity spot;
- local string s;
- self.classname = "player";
- self.health = 100;
- self.takedamage = DAMAGE_AIM;
- self.solid = SOLID_SLIDEBOX;
- self.movetype = MOVETYPE_WALK;
- self.show_hostile = 0;
- self.max_health = 100;
- self.flags = FL_CLIENT;
- self.air_finished = time + 12;
- self.dmg = 2; // initial water damage
- self.super_damage_finished = 0;
- self.radsuit_finished = 0;
- self.invisible_finished = 0;
- self.invincible_finished = 0;
- self.effects = 0;
- self.invincible_time = 0;
- DecodeLevelParms ();
-
- W_SetCurrentAmmo ();
- self.attack_finished = time;
- self.th_pain = player_pain;
- self.th_die = PlayerDie;
-
- self.deadflag = DEAD_NO;
- // paustime is set by teleporters to keep the player from moving a while
- self.pausetime = 0;
-
- spot = SelectSpawnPoint ();
- self.origin = spot.origin + '0 0 1';
- self.angles = spot.angles;
- self.fixangle = TRUE; // turn this way immediately
- // oh, this is a hack!
- setmodel (self, "progs/eyes.mdl");
- modelindex_eyes = self.modelindex;
- setmodel (self, "progs/player.mdl");
- modelindex_player = self.modelindex;
- setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
-
- self.view_ofs = '0 0 22';
- // Mod - Xian (May.20.97)
- // Bug where player would have velocity from their last kill
- self.velocity = '0 0 0';
- player_stand1 ();
-
- makevectors(self.angles);
- spawn_tfog (self.origin + v_forward*20);
- spawn_tdeath (self.origin, self);
- // Set Rocket Jump Modifiers
- if (stof(infokey(world, "rj")) != 0)
- {
- rj = stof(infokey(world, "rj"));
- }
- if (deathmatch == 4)
- {
- self.ammo_shells = 0;
- if (stof(infokey(world, "axe")) == 0)
- {
- self.ammo_nails = 255;
- self.ammo_shells = 255;
- self.ammo_rockets = 255;
- self.ammo_cells = 255;
- self.items = self.items | IT_NAILGUN;
- self.items = self.items | IT_SUPER_NAILGUN;
- self.items = self.items | IT_SUPER_SHOTGUN;
- self.items = self.items | IT_ROCKET_LAUNCHER;
- // self.items = self.items | IT_GRENADE_LAUNCHER;
- self.items = self.items | IT_LIGHTNING;
- }
- self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
- self.armorvalue = 200;
- self.armortype = 0.8;
- self.health = 250;
- self.items = self.items | IT_INVULNERABILITY;
- self.invincible_time = 1;
- self.invincible_finished = time + 3;
- }
- if (deathmatch == 5)
- {
- self.ammo_nails = 80;
- self.ammo_shells = 30;
- self.ammo_rockets = 10;
- self.ammo_cells = 30;
- self.items = self.items | IT_NAILGUN;
- self.items = self.items | IT_SUPER_NAILGUN;
- self.items = self.items | IT_SUPER_SHOTGUN;
- self.items = self.items | IT_ROCKET_LAUNCHER;
- self.items = self.items | IT_GRENADE_LAUNCHER;
- self.items = self.items | IT_LIGHTNING;
- self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
- self.armorvalue = 200;
- self.armortype = 0.8;
- self.health = 200;
- self.items = self.items | IT_INVULNERABILITY;
- self.invincible_time = 1;
- self.invincible_finished = time + 3;
- }
- };
- /*
- =============================================================================
- QUAKED FUNCTIONS
- =============================================================================
- */
- /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
- The normal starting point for a level.
- */
- void() info_player_start =
- {
- };
- /*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
- Only used on start map for the return point from an episode.
- */
- void() info_player_start2 =
- {
- };
- /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
- potential spawning position for deathmatch games
- */
- void() info_player_deathmatch =
- {
- };
- /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
- potential spawning position for coop games
- */
- void() info_player_coop =
- {
- };
- /*
- ===============================================================================
- RULES
- ===============================================================================
- */
- /*
- go to the next level for deathmatch
- */
- void() NextLevel =
- {
- local entity o;
- local string newmap;
- if (nextmap != "")
- return; // already done
- if (mapname == "start")
- {
- if (!cvar("registered"))
- {
- mapname = "e1m1";
- }
- else if (!(serverflags & 1))
- {
- mapname = "e1m1";
- serverflags = serverflags | 1;
- }
- else if (!(serverflags & 2))
- {
- mapname = "e2m1";
- serverflags = serverflags | 2;
- }
- else if (!(serverflags & 4))
- {
- mapname = "e3m1";
- serverflags = serverflags | 4;
- }
- else if (!(serverflags & 8))
- {
- mapname = "e4m1";
- serverflags = serverflags - 7;
- }
-
- o = spawn();
- o.map = mapname;
- }
- else
- {
- // find a trigger changelevel
- o = find(world, classname, "trigger_changelevel");
- if (!o || mapname == "start")
- { // go back to same map if no trigger_changelevel
- o = spawn();
- o.map = mapname;
- }
- }
- nextmap = o.map;
- if (o.nextthink < time)
- {
- o.think = execute_changelevel;
- o.nextthink = time + 0.1;
- }
- };
- /*
- ============
- CheckRules
- Exit deathmatch games upon conditions
- ============
- */
- void() CheckRules =
- {
- if (timelimit && time >= timelimit)
- NextLevel ();
-
- if (fraglimit && self.frags >= fraglimit)
- NextLevel ();
- };
- //============================================================================
- void() PlayerDeathThink =
- {
- local entity old_self;
- local float forward;
- if ((self.flags & FL_ONGROUND))
- {
- forward = vlen (self.velocity);
- forward = forward - 20;
- if (forward <= 0)
- self.velocity = '0 0 0';
- else
- self.velocity = forward * normalize(self.velocity);
- }
- // wait for all buttons released
- if (self.deadflag == DEAD_DEAD)
- {
- if (self.button2 || self.button1 || self.button0)
- return;
- self.deadflag = DEAD_RESPAWNABLE;
- return;
- }
- // wait for any button down
- if (!self.button2 && !self.button1 && !self.button0)
- return;
- self.button0 = 0;
- self.button1 = 0;
- self.button2 = 0;
- respawn();
- };
- void() PlayerJump =
- {
- local vector start, end;
- if (self.flags & FL_WATERJUMP)
- return;
-
- if (self.waterlevel >= 2)
- {
- // play swiming sound
- if (self.swim_flag < time)
- {
- self.swim_flag = time + 1;
- if (random() < 0.5)
- sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
- else
- sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
- }
- return;
- }
- if (!(self.flags & FL_ONGROUND))
- return;
- if ( !(self.flags & FL_JUMPRELEASED) )
- return; // don't pogo stick
- self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
- self.button2 = 0;
- // player jumping sound
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- };
- /*
- ===========
- WaterMove
- ============
- */
- .float dmgtime;
- void() WaterMove =
- {
- //dprint (ftos(self.waterlevel));
- if (self.movetype == MOVETYPE_NOCLIP)
- return;
- if (self.health < 0)
- return;
- if (self.waterlevel != 3)
- {
- if (self.air_finished < time)
- sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
- else if (self.air_finished < time + 9)
- sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
- self.air_finished = time + 12;
- self.dmg = 2;
- }
- else if (self.air_finished < time)
- { // drown!
- if (self.pain_finished < time)
- {
- self.dmg = self.dmg + 2;
- if (self.dmg > 15)
- self.dmg = 10;
- T_Damage (self, world, world, self.dmg);
- self.pain_finished = time + 1;
- }
- }
-
- if (!self.waterlevel)
- {
- if (self.flags & FL_INWATER)
- {
- // play leave water sound
- sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
- self.flags = self.flags - FL_INWATER;
- }
- return;
- }
- if (self.watertype == CONTENT_LAVA)
- { // do damage
- if (self.dmgtime < time)
- {
- if (self.radsuit_finished > time)
- self.dmgtime = time + 1;
- else
- self.dmgtime = time + 0.2;
- T_Damage (self, world, world, 10*self.waterlevel);
- }
- }
- else if (self.watertype == CONTENT_SLIME)
- { // do damage
- if (self.dmgtime < time && self.radsuit_finished < time)
- {
- self.dmgtime = time + 1;
- T_Damage (self, world, world, 4*self.waterlevel);
- }
- }
-
- if ( !(self.flags & FL_INWATER) )
- {
- // player enter water sound
- if (self.watertype == CONTENT_LAVA)
- sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
- if (self.watertype == CONTENT_WATER)
- sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
- if (self.watertype == CONTENT_SLIME)
- sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
- self.flags = self.flags + FL_INWATER;
- self.dmgtime = 0;
- }
- };
- void() CheckWaterJump =
- {
- local vector start, end;
- // check for a jump-out-of-water
- makevectors (self.angles);
- start = self.origin;
- start_z = start_z + 8;
- v_forward_z = 0;
- normalize(v_forward);
- end = start + v_forward*24;
- traceline (start, end, TRUE, self);
- if (trace_fraction < 1)
- { // solid at waist
- start_z = start_z + self.maxs_z - 8;
- end = start + v_forward*24;
- self.movedir = trace_plane_normal * -50;
- traceline (start, end, TRUE, self);
- if (trace_fraction == 1)
- { // open at eye level
- self.flags = self.flags | FL_WATERJUMP;
- self.velocity_z = 225;
- self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
- self.teleport_time = time + 2; // safety net
- return;
- }
- }
- };
- /*
- ================
- PlayerPreThink
- Called every frame before physics are run
- ================
- */
- void() PlayerPreThink =
- {
- local float mspeed, aspeed;
- local float r;
- if (intermission_running)
- {
- IntermissionThink (); // otherwise a button could be missed between
- return; // the think tics
- }
- if (self.view_ofs == '0 0 0')
- return; // intermission or finale
- makevectors (self.v_angle); // is this still used
- self.deathtype = "";
- CheckRules ();
- WaterMove ();
- /*
- if (self.waterlevel == 2)
- CheckWaterJump ();
- */
- if (self.deadflag >= DEAD_DEAD)
- {
- PlayerDeathThink ();
- return;
- }
-
- if (self.deadflag == DEAD_DYING)
- return; // dying, so do nothing
- if (self.button2)
- {
- PlayerJump ();
- }
- else
- self.flags = self.flags | FL_JUMPRELEASED;
- // teleporters can force a non-moving pause time
- if (time < self.pausetime)
- self.velocity = '0 0 0';
- if(time > self.attack_finished && self.currentammo == 0 && self.weapon != IT_AXE)
- {
- self.weapon = W_BestWeapon ();
- W_SetCurrentAmmo ();
- }
- };
-
- /*
- ================
- CheckPowerups
- Check for turning off powerups
- ================
- */
- void() CheckPowerups =
- {
- if (self.health <= 0)
- return;
- // invisibility
- if (self.invisible_finished)
- {
- // sound and screen flash when items starts to run out
- if (self.invisible_sound < time)
- {
- sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
- self.invisible_sound = time + ((random() * 3) + 1);
- }
- if (self.invisible_finished < time + 3)
- {
- if (self.invisible_time == 1)
- {
- sprint (self, PRINT_HIGH, "Ring of Shadows magic is fading\n");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
- self.invisible_time = time + 1;
- }
-
- if (self.invisible_time < time)
- {
- self.invisible_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
- if (self.invisible_finished < time)
- { // just stopped
- self.items = self.items - IT_INVISIBILITY;
- self.invisible_finished = 0;
- self.invisible_time = 0;
- }
-
- // use the eyes
- self.frame = 0;
- self.modelindex = modelindex_eyes;
- }
- else
- self.modelindex = modelindex_player; // don't use eyes
- // invincibility
- if (self.invincible_finished)
- {
- // sound and screen flash when items starts to run out
- if (self.invincible_finished < time + 3)
- {
- if (self.invincible_time == 1)
- {
- sprint (self, PRINT_HIGH, "Protection is almost burned out\n");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
- self.invincible_time = time + 1;
- }
-
- if (self.invincible_time < time)
- {
- self.invincible_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
-
- if (self.invincible_finished < time)
- { // just stopped
- self.items = self.items - IT_INVULNERABILITY;
- self.invincible_time = 0;
- self.invincible_finished = 0;
- }
- if (self.invincible_finished > time)
- {
- self.effects = self.effects | EF_DIMLIGHT;
- self.effects = self.effects | EF_RED;
- }
- else
- {
- self.effects = self.effects - (self.effects & EF_DIMLIGHT);
- self.effects = self.effects - (self.effects & EF_RED);
- }
- }
- // super damage
- if (self.super_damage_finished)
- {
- // sound and screen flash when items starts to run out
- if (self.super_damage_finished < time + 3)
- {
- if (self.super_time == 1)
- {
- if (deathmatch == 4)
- sprint (self, PRINT_HIGH, "OctaPower is wearing off\n");
- else
- sprint (self, PRINT_HIGH, "Quad Damage is wearing off\n");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
- self.super_time = time + 1;
- }
-
- if (self.super_time < time)
- {
- self.super_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
- if (self.super_damage_finished < time)
- { // just stopped
- self.items = self.items - IT_QUAD;
- if (deathmatch == 4)
- {
- self.ammo_cells = 255;
- self.armorvalue = 1;
- self.armortype = 0.8;
- self.health = 100;
- }
- self.super_damage_finished = 0;
- self.super_time = 0;
- }
- if (self.super_damage_finished > time)
- {
- self.effects = self.effects | EF_DIMLIGHT;
- self.effects = self.effects | EF_BLUE;
- }
- else
- {
- self.effects = self.effects - (self.effects & EF_DIMLIGHT);
- self.effects = self.effects - (self.effects & EF_BLUE);
- }
- }
- // suit
- if (self.radsuit_finished)
- {
- self.air_finished = time + 12; // don't drown
- // sound and screen flash when items starts to run out
- if (self.radsuit_finished < time + 3)
- {
- if (self.rad_time == 1)
- {
- sprint (self, PRINT_HIGH, "Air supply in Biosuit expiring\n");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
- self.rad_time = time + 1;
- }
-
- if (self.rad_time < time)
- {
- self.rad_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
- if (self.radsuit_finished < time)
- { // just stopped
- self.items = self.items - IT_SUIT;
- self.rad_time = 0;
- self.radsuit_finished = 0;
- }
- }
- };
- /*
- ================
- PlayerPostThink
- Called every frame after physics are run
- ================
- */
- void() PlayerPostThink =
- {
- local float mspeed, aspeed;
- local float r;
- //dprint ("post think\n");
- if (self.view_ofs == '0 0 0')
- return; // intermission or finale
- if (self.deadflag)
- return;
- // check to see if player landed and play landing sound
- if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) )
- {
- if (self.watertype == CONTENT_WATER)
- sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
- else if (self.jump_flag < -650)
- {
- self.deathtype = "falling";
- T_Damage (self, world, world, 5);
- sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
- }
- else
- sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
- }
- self.jump_flag = self.velocity_z;
- CheckPowerups ();
- W_WeaponFrame ();
- };
- /*
- ===========
- ClientConnect
- called when a player connects to a server
- ============
- */
- void() ClientConnect =
- {
- bprint (PRINT_HIGH, self.netname);
- bprint (PRINT_HIGH, " entered the game\n");
-
- // a client connecting during an intermission can cause problems
- if (intermission_running)
- GotoNextMap ();
- };
- /*
- ===========
- ClientDisconnect
- called when a player disconnects from a server
- ============
- */
- void() ClientDisconnect =
- {
- // let everyone else know
- bprint (PRINT_HIGH, self.netname);
- bprint (PRINT_HIGH, " left the game with ");
- bprint (PRINT_HIGH, ftos(self.frags));
- bprint (PRINT_HIGH, " frags\n");
- sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
- set_suicide_frame ();
- };
- /*
- ===========
- ClientObituary
- called when a player dies
- ============
- */
- void(entity targ, entity attacker) ClientObituary =
- {
- local float rnum;
- local string deathstring, deathstring2;
- local string s;
- local string attackerteam, targteam;
- rnum = random();
- //ZOID 12-13-96: self.team doesn't work in QW. Use keys
- attackerteam = infokey(attacker, "team");
- targteam = infokey(targ, "team");
- if (targ.classname == "player")
- {
- if (deathmatch > 3)
- {
- if (targ.deathtype == "selfwater")
- {
- bprint (PRINT_MEDIUM, targ.netname);
- bprint (PRINT_MEDIUM," electrocutes himself.\n ");
- targ.frags = targ.frags - 1;
- return;
- }
- }
- if (attacker.classname == "teledeath")
- {
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM," was telefragged by ");
- bprint (PRINT_MEDIUM,attacker.owner.netname);
- bprint (PRINT_MEDIUM,"\n");
- logfrag (attacker.owner, targ);
- attacker.owner.frags = attacker.owner.frags + 1;
- return;
- }
- if (attacker.classname == "teledeath2")
- {
- bprint (PRINT_MEDIUM,"Satan's power deflects ");
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM,"'s telefrag\n");
- targ.frags = targ.frags - 1;
- logfrag (targ, targ);
- return;
- }
- // double 666 telefrag (can happen often in deathmatch 4)
- if (attacker.classname == "teledeath3")
- {
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM," was telefragged by ");
- bprint (PRINT_MEDIUM,attacker.owner.netname);
- bprint (PRINT_MEDIUM, "'s Satan's power\n");
- targ.frags = targ.frags - 1;
- logfrag (targ, targ);
- return;
- }
-
- if (targ.deathtype == "squish")
- {
- if (teamplay && targteam == attackerteam && attackerteam != "" && targ != attacker)
- {
- logfrag (attacker, attacker);
- attacker.frags = attacker.frags - 1;
- bprint (PRINT_MEDIUM,attacker.netname);
- bprint (PRINT_MEDIUM," squished a teammate\n");
- return;
- }
- else if (attacker.classname == "player" && attacker != targ)
- {
- bprint (PRINT_MEDIUM, attacker.netname);
- bprint (PRINT_MEDIUM," squishes ");
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM,"\n");
- logfrag (attacker, targ);
- attacker.frags = attacker.frags + 1;
- return;
- }
- else
- {
- logfrag (targ, targ);
- targ.frags = targ.frags - 1; // killed self
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM," was squished\n");
- return;
- }
- }
- if (attacker.classname == "player")
- {
- if (targ == attacker)
- {
- // killed self
- logfrag (attacker, attacker);
- attacker.frags = attacker.frags - 1;
- bprint (PRINT_MEDIUM,targ.netname);
- if (targ.deathtype == "grenade")
- bprint (PRINT_MEDIUM," tries to put the pin back in\n");
- else if (targ.deathtype == "rocket")
- bprint (PRINT_MEDIUM," becomes bored with life\n");
- else if (targ.weapon == 64 && targ.waterlevel > 1)
- {
- if (targ.watertype == CONTENT_SLIME)
- bprint (PRINT_MEDIUM," discharges into the slime\n");
- else if (targ.watertype == CONTENT_LAVA)
- bprint (PRINT_MEDIUM," discharges into the lava\n");
- else
- bprint (PRINT_MEDIUM," discharges into the water.\n");
- }
- else
- bprint (PRINT_MEDIUM," becomes bored with life\n");
- return;
- }
- else if ( (teamplay == 2) && (targteam == attackerteam) &&
- (attackerteam != "") )
- {
- if (rnum < 0.25)
- deathstring = " mows down a teammate\n";
- else if (rnum < 0.50)
- deathstring = " checks his glasses\n";
- else if (rnum < 0.75)
- deathstring = " gets a frag for the other team\n";
- else
- deathstring = " loses another friend\n";
- bprint (PRINT_MEDIUM, attacker.netname);
- bprint (PRINT_MEDIUM, deathstring);
- attacker.frags = attacker.frags - 1;
- //ZOID 12-13-96: killing a teammate logs as suicide
- logfrag (attacker, attacker);
- return;
- }
- else
- {
- logfrag (attacker, targ);
- attacker.frags = attacker.frags + 1;
- rnum = attacker.weapon;
- if (targ.deathtype == "nail")
- {
- deathstring = " was nailed by ";
- deathstring2 = "\n";
- }
- else if (targ.deathtype == "supernail")
- {
- deathstring = " was punctured by ";
- deathstring2 = "\n";
- }
- else if (targ.deathtype == "grenade")
- {
- deathstring = " eats ";
- deathstring2 = "'s pineapple\n";
- if (targ.health < -40)
- {
- deathstring = " was gibbed by ";
- deathstring2 = "'s grenade\n";
- }
- }
- else if (targ.deathtype == "rocket")
- {
- if (attacker.super_damage_finished > 0 && targ.health < -40)
- {
- rnum = random();
- if (rnum < 0.3)
- deathstring = " was brutalized by ";
- else if (rnum < 0.6)
- deathstring = " was smeared by ";
- else
- {
- bprint (PRINT_MEDIUM, attacker.netname);
- bprint (PRINT_MEDIUM, " rips ");
- bprint (PRINT_MEDIUM, targ.netname);
- bprint (PRINT_MEDIUM, " a new one\n");
- return;
- }
- deathstring2 = "'s quad rocket\n";
- }
- else
- {
- deathstring = " rides ";
- deathstring2 = "'s rocket\n";
- if (targ.health < -40)
- {
- deathstring = " was gibbed by ";
- deathstring2 = "'s rocket\n" ;
- }
- }
- }
- else if (rnum == IT_AXE)
- {
- deathstring = " was ax-murdered by ";
- deathstring2 = "\n";
- }
- else if (rnum == IT_SHOTGUN)
- {
- deathstring = " chewed on ";
- deathstring2 = "'s boomstick\n";
- }
- else if (rnum == IT_SUPER_SHOTGUN)
- {
- deathstring = " ate 2 loads of ";
- deathstring2 = "'s buckshot\n";
- }
- else if (rnum == IT_LIGHTNING)
- {
- deathstring = " accepts ";
- if (attacker.waterlevel > 1)
- deathstring2 = "'s discharge\n";
- else
- deathstring2 = "'s shaft\n";
- }
- bprint (PRINT_MEDIUM,targ.netname);
- bprint (PRINT_MEDIUM,deathstring);
- bprint (PRINT_MEDIUM,attacker.netname);
- bprint (PRINT_MEDIUM,deathstring2);
- }
- return;
- }
- else
- {
- logfrag (targ, targ);
- targ.frags = targ.frags - 1; // killed self
- rnum = targ.watertype;
- bprint (PRINT_MEDIUM,targ.netname);
- if (rnum == -3)
- {
- if (random() < 0.5)
- bprint (PRINT_MEDIUM," sleeps with the fishes\n");
- else
- bprint (PRINT_MEDIUM," sucks it down\n");
- return;
- }
- else if (rnum == -4)
- {
- if (random() < 0.5)
- bprint (PRINT_MEDIUM," gulped a load of slime\n");
- else
- bprint (PRINT_MEDIUM," can't exist on slime alone\n");
- return;
- }
- else if (rnum == -5)
- {
- if (targ.health < -15)
- {
- bprint (PRINT_MEDIUM," burst into flames\n");
- return;
- }
- if (random() < 0.5)
- bprint (PRINT_MEDIUM," turned into hot slag\n");
- else
- bprint (PRINT_MEDIUM," visits the Volcano God\n");
- return;
- }
- if (attacker.classname == "explo_box")
- {
- bprint (PRINT_MEDIUM," blew up\n");
- return;
- }
- if (targ.deathtype == "falling")
- {
- bprint (PRINT_MEDIUM," fell to his death\n");
- return;
- }
- if (targ.deathtype == "nail" || targ.deathtype == "supernail")
- {
- bprint (PRINT_MEDIUM," was spiked\n");
- return;
- }
- if (targ.deathtype == "laser")
- {
- bprint (PRINT_MEDIUM," was zapped\n");
- return;
- }
- if (attacker.classname == "fireball")
- {
- bprint (PRINT_MEDIUM," ate a lavaball\n");
- return;
- }
- if (attacker.classname == "trigger_changelevel")
- {
- bprint (PRINT_MEDIUM," tried to leave\n");
- return;
- }
- bprint (PRINT_MEDIUM," died\n");
- }
- }
- };
|