1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062 |
- /* Copyright (C) 1996-2022 id Software LLC
- 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 the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- See file, 'COPYING', for details.
- */
- // 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, modelindex_hammer;
- /*
- =============================================================================
- LEVEL CHANGING / INTERMISSION
- =============================================================================
- */
- 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 =
- {
- };
- void() SetChangeParms =
- {
- if (self.health <= 0 || deathmatch)
- {
- SetNewParms ();
- return;
- }
- //JIM
- // remove items
- self.items = self.items - (self.items &
- (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD ) );
- //MED
- self.items2 = self.items2 - (self.items2 &
- (HIP_IT_WETSUIT | HIP_IT_EMPATHY_SHIELDS ) );
- //MED
- self.gravity = 1.0;
- // cap super health
- if (self.health > self.max_health)
- self.health = self.max_health;
- if (self.health < self.max_health / 2)
- self.health = self.max_health / 2;
- 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;
- if (skill == 3 && !deathmatch)
- parm2 = 50;
- else
- parm2 = 100;
- parm3 = 0;
- parm4 = 25;
- parm5 = 0;
- parm6 = 0;
- parm7 = 0;
- parm8 = 1;
- parm9 = 0;
- };
- void() DecodeLevelParms =
- {
- //HIPNOTIC
- if (world.model == "maps/start.bsp")
- SetNewParms (); // take away all stuff on starting new episode
- if (world.model == "maps/hip1m1.bsp")
- SetNewParms (); // take away all stuff on starting new episode
- if (world.model == "maps/hip2m1.bsp")
- SetNewParms (); // take away all stuff on starting new episode
- if (world.model == "maps/hip3m1.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;
- // testinfo_player_start is only found in regioned levels
- spot = find (world, classname, "testplayerstart");
- if (spot)
- return spot;
- objerror ("FindIntermission: no spot");
- };
- string nextmap;
- void() GotoNextMap =
- {
- if (cvar("samelevel")) // if samelevel is set, stay on same level
- changelevel (mapname);
- else
- changelevel (nextmap);
- };
- void() finale_transition =
- {
- if (!coop) {
- localcmd("menu_credits\n");
- localcmd("disconnect\n");
- } else {
- changelevel("start");
- }
- }
- void() finale_check =
- {
- if (finaleFinished()) {
- self.nextthink = time + 5;
- self.think = finale_transition;
- } else {
- self.nextthink = time + 0.1;
- }
- }
- void() ExitIntermission =
- {
- // skip any text in deathmatch
- if (deathmatch)
- {
- GotoNextMap ();
- return;
- }
- intermission_exittime = time + 1;
- intermission_running = intermission_running + 1;
- //
- // run some text if at the end of an episode
- //
- if (intermission_running == 2)
- {
- if (world.model == "maps/e1m7.bsp")
- {
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
- if (!cvar("registered"))
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_e1_shareware");
- }
- else
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_e1");
- }
- return;
- }
- else if (world.model == "maps/e2m6.bsp")
- {
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_e2");
- return;
- }
- else if (world.model == "maps/e3m6.bsp")
- {
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_e3");
- return;
- }
- else if (world.model == "maps/e4m7.bsp")
- {
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_e4");
- return;
- }
- //HIPNOTIC
- if (world.model == "maps/hip1m4.bsp")
- {
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 6);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- /*
- **************************************
- Deep within the bowels of the
- Research Facility, you discover the
- passage that the followers of Quake
- have used to enter our world.
- The bastards used some type of
- gigantic teleporter to overload
- one of our own slipgates! As long as
- this portal exists, Earth will never
- be safe from Quake's cruel minions.
- If you can find the source of the
- portal's power, you can shut it
- down--possibly forever! With only a
- moment's consideration for your own
- safety, you re-enter the dark domain,
- knowing Hell would be a better fate
- than experiencing the reign of Quake.
- */
- WriteString (MSG_ALL, "$qc_finale_hip1" );
- //WriteString (MSG_ALL, "If you can find the source of the\nportal's power, you can shut it\ndown--possibly forever! With only a\nmoment's consideration for your own\nsafety, you re-enter the dark domain,\nknowing Hell would be a better fate\nthan experiencing the reign of Quake." );
- return;
- }
- else if (world.model == "maps/hip2m5.bsp")
- {
- /*
- **************************************
- After destroying the power generator,
- you pass beyond the gate of Mortum's
- Keep. A wave of nausea suddenly flows
- over you and you find yourself cast
- out into a liquid void. You float
- lifelessly, yet aware, in a lavender
- sea of energy.
- After what seems like an eternity,
- you feel the presence of a diabolical
- intelligence. You are held helpless
- for a moment as your mind is open to
- that of Armagon--Quake's General and
- master of this realm. Recognizing
- you as the one who foiled his
- attempt to conquer Earth, a hellish
- howl fills your mind and blots out
- all consciousness. When you awake,
- you find yourself on the shores of
- reality, but in a time and place
- unknown to you.
- */
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 6);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_hip2" );
- //WriteString (MSG_ALL, "After what seems like an eternity,\nyou feel the presence of a diabolical\nintelligence. You are held helpless\nfor a moment as your mind is open to\nthat of Armagon--Quake's General and\nmaster of this realm. Recognizing\nyou as the one who foiled his\nattempts to conquer Earth, a hellish\nhowl fills your mind and blots out\nall consciousness. When you awake,\nyou find yourself on the shores of\nreality, but in a time and place\nunknown to you." );
- return;
- }
- else if (world.model == "maps/hipend.bsp")
- {
- /*
- **************************************
- After the last echoes of Armagon's
- death yell fade away, you breathe a
- heavy sigh of relief. With the loss
- of his magic, Armagon's fortress
- begins to collapse. The rift he
- created to send his grisly troops
- through time slowly closes and seals
- itself forever. In the chaos that
- ensues, a wall collapses, revealing
- one remaining time portal. With your
- chances to escape rapidly growing
- slim, you race for the portal,
- mindless of your destination. In a
- flash of light, you find yourself
- back at Command HQ, safe and sound.
- Congratulations! You are victorious!
- The minions of Quake have once again
- fallen before your mighty hand.
- Is this the last you will see of
- Quake's hellions?
- Only time will tell...
- */
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 2);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_hipend" );
- //WriteString (MSG_ALL, "Congratulations! You are victorious!\nThe minions of Quake have once again\nfallen before your mighty hand.\nIs this the last you will see of\nQuake's hellions?\n\nOnly time will tell..." );
- //intermission_exittime = time + 10000000; // never allow exit
- if (campaign && world.model == "maps/hipend.bsp")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_COMPLETE_HIPEND");
- if (skill == 3)
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_COMPLETE_HIPEND_NIGHTMARE");
- }
- }
-
- return;
- }
- GotoNextMap();
- }
- if (intermission_running == 3)
- {
- if (!cvar("registered"))
- { // shareware episode has been completed, go to sell screen
- WriteByte (MSG_ALL, SVC_SELLSCREEN);
- return;
- }
- if ( (serverflags&15) == 15)
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_all_runes");
- return;
- }
- //HIPNOTIC
- if (world.model == "maps/hip1m4.bsp")
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_hip1m4" );
- return;
- }
- else if (world.model == "maps/hip2m5.bsp")
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_hip2m5" );
- return;
- }
- else if (world.model == "maps/hipend.bsp")
- {
- WriteByte (MSG_ALL, SVC_FINALE);
- WriteString (MSG_ALL, "$qc_finale_hipend2" );
- intermission_exittime = time + 10000000; // never allow exit
- // instead of sitting here forever, run the quake ex credits and send the user back to start
- local entity timer = spawn();
- timer.nextthink = time + 1;
- timer.think = finale_check;
- return;
- }
- }
- GotoNextMap();
- };
- /*
- ============
- 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;
- ExitIntermission ();
- };
- void() execute_changelevel =
- {
- local entity pos;
- intermission_running = 1;
- // enforce a wait time before allowing changelevel
- if (deathmatch)
- intermission_exittime = time + 5;
- else
- intermission_exittime = time + 2;
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 9);
- WriteByte (MSG_ALL, 3);
- pos = FindIntermission ();
- other = find (world, classname, "player");
- while (other != world)
- {
- other.view_ofs = '0 0 0';
- other.angles = other.v_angle = pos.mangle;
- other.fixangle = TRUE; // turn this way immediately
- other.nextthink = time + 0.5;
- other.takedamage = DAMAGE_NO;
- other.solid = SOLID_NOT;
- other.movetype = MOVETYPE_NONE;
- other.modelindex = 0;
- setorigin (other, pos.origin);
- other = find (other, classname, "player");
- }
- WriteByte (MSG_ALL, SVC_INTERMISSION);
- if (campaign && world.model == "maps/hip1m4.bsp")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_COMPLETE_HIP1M4");
- }
- else if (campaign && world.model == "maps/hip2m5.bsp")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_COMPLETE_HIP2M5");
- }
-
- if (world.model == "maps/hip1m2.bsp" && nextmap == "hip1m5")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_FIND_HIP1M5");
- }
- else if (world.model == "maps/hip2m1.bsp" && nextmap == "hip2m6")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_FIND_HIP2M6");
- }
- else if (world.model == "maps/hip3m3.bsp" && nextmap == "hipdm1")
- {
- WriteByte (MSG_ALL, SVC_ACHIEVEMENT);
- WriteString(MSG_ALL, "ACH_FIND_HIPDM1");
- }
- };
- void() changelevel_touch =
- {
- local entity pos;
- if (other.classname != "player")
- return;
- if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
- {
- T_Damage (other, self, self, 50000);
- return;
- }
- if (coop || deathmatch)
- {
- bprint("$qc_exited", other.netname);
- }
- nextmap = self.map;
- SUB_UseTargets ();
- if ( (self.spawnflags & 1) && (deathmatch == 0) )
- { // NO_INTERMISSION
- GotoNextMap();
- return;
- }
- 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 =
- {
- if (coop)
- {
- // make a copy of the dead body for appearances sake
- CopyToBodyQue (self);
- // get the spawn parms as they were at level start
- setspawnparms (self);
- // respawn
- PutClientInServer ();
- }
- else if (deathmatch)
- {
- // make a copy of the dead body for appearances sake
- CopyToBodyQue (self);
- // set default spawn parms
- SetNewParms ();
- // respawn
- PutClientInServer ();
- }
- else
- { // restart the entire server
- cvar_set("campaign", ftos(campaign));
- localcmd ("restart\n");
- }
- };
- /*
- ============
- ClientKill
- Player entered the suicide command
- ============
- */
- void() ClientKill =
- {
- bprint("$qc_suicides", self.netname);
- set_suicide_frame ();
- self.modelindex = modelindex_player;
- self.frags = self.frags - 2; // extra penalty
- respawn ();
- };
- /*
- ============
- PlayerVisibleToSpawnPoint
- Returns true if player can see this point
- ============
- */
- float PlayerVisibleToSpawnPoint( entity point ) {
- local vector spot1, spot2;
- local entity player = find( world, classname, "player" );
- while ( player ) {
- if ( player.health > 0 ) {
- spot1 = point.origin + player.view_ofs;
- spot2 = player.origin + player.view_ofs;
- traceline( spot1, spot2, TRUE, point );
- if ( trace_fraction >= 1.0f ) {
- return TRUE;
- }
- }
- player = find( player, classname, "player" );
- }
- return FALSE;
- }
- float IDEAL_DIST_FROM_DM_SPAWN_POINT = 384;
- float MIN_DIST_FROM_DM_SPAWN_POINT = 84;
- /*
- ============
- SelectSpawnPoint
- Returns the entity to spawn at
- ============
- */
- entity SelectSpawnPoint(float forceSpawn) {
- local entity spot, thing;
- local float numspots, totalspots;
- local float pcount;
- 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
- if ( coop ) {
- lastspawn = find( lastspawn, classname, "info_player_coop" );
- if ( lastspawn == world ) {
- lastspawn = find( lastspawn, classname, "info_player_start" );
- }
- if ( lastspawn != world ) {
- return lastspawn;
- }
- } else if ( deathmatch ) {
- // find all spots that don't have visible players nearby
- spots = world;
- spot = find( world, classname, "info_player_deathmatch" );
- while( spot ) {
- totalspots = totalspots + 1;
- thing = findradius( spot.origin, IDEAL_DIST_FROM_DM_SPAWN_POINT );
- pcount = 0;
- while( thing ) {
- if ( thing.classname == "player" && thing.health > 0 ) {
- pcount = pcount + 1;
- }
- thing = thing.chain;
- }
- if ( pcount == 0 ) {
- if ( PlayerVisibleToSpawnPoint( spot ) ) {
- pcount = pcount + 1;
- }
- }
- if ( pcount == 0 ) { // good spot!
- 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;
- // on small maps with few spawn points, our "ideal" spawn conditions may not be possible to meet
- // so fallback to just trying to pick a point without a player on top of it, so we don't start
- // a spawn frag loop
- if ( numspots == 0 ) {
- spot = find( world, classname, "info_player_deathmatch" );
- while( spot ) {
- thing = findradius( spot.origin, MIN_DIST_FROM_DM_SPAWN_POINT );
- pcount = 0;
- while( thing ) {
- if ( thing.classname == "player" && thing.health > 0 ) {
- pcount = pcount + 1;
- }
- thing = thing.chain;
- }
- if ( pcount == 0 ) { // good spot!
- spot.goalentity = spots;
- spots = spot;
- numspots = numspots + 1;
- }
- // Get the next spot in the chain
- spot = find( spot, classname, "info_player_deathmatch" );
- }
- }
- // uncomment to force a deferred spawn
- // if (forceSpawn == FALSE) return world;
- if ( !numspots ) {
- if (forceSpawn == FALSE) {
- return world;
- }
- // no spots available so just pick one at random
- 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;
- }
-
- // 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;
- }
- if ( serverflags ) { // return with a rune to start
- spot = find( world, classname, "info_player_start2" );
- if ( spot ) {
- return spot;
- }
- }
-
- spot = find( world, classname, "info_player_start" );
-
- if ( !spot ) {
- error( "PutClientInServer: no info_player_start on level" );
- }
-
- return spot;
- };
- /*
- ===========
- PutClientInServer
- called each time a player is spawned
- ============
- */
- void() DecodeLevelParms;
- void() PlayerDie;
- void() PutClientInServer =
- {
- local entity spot;
- spot = SelectSpawnPoint ();
- self.classname = "player";
- if (skill == 3 && !deathmatch)
- self.health = 50;
- else
- self.health = 100;
- self.takedamage = DAMAGE_AIM;
- self.solid = SOLID_SLIDEBOX;
- self.movetype = MOVETYPE_WALK;
- self.show_hostile = 0;
- if (skill == 3 && !deathmatch)
- self.max_health = 50;
- else
- 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;
- //JIM
- self.wetsuit_finished = 0;
- //MED
- self.empathy_finished = 0;
- //MED
- self.items2 = 0;
- self.gravity = 1.0;
- if ( coop ) {
- self.team = TEAM_HUMANS;
- }
- 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
- //JIM
- // Clear out velocity so you're not launched into the air
- // when you respawn.
- self.velocity = '0 0 0';
- // oh, this is a hack!
- setmodel (self, "progs/playham.mdl");
- modelindex_hammer = self.modelindex;
- 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';
- player_stand1 ();
- if (deathmatch || coop)
- {
- makevectors(self.angles);
- spawn_tfog (self.origin + v_forward*20);
- }
- spawn_tdeath (self.origin, self);
-
- stuffcmd(self, "-attack\n"); // prevent shooting after respawning
- };
- /*
- =============================================================================
- 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 =
- {
- };
- /*
- saved out by quaked in region mode
- */
- void() testplayerstart =
- {
- };
- /*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
- only called if a time or frag limit has expired
- */
- void() NextLevel =
- {
- local entity o;
- //HIPNOTIC
- //Commented out so that timelimit and fraglimit work on start map
- /*
- 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");
- // go back to start if no trigger_changelevel
- if (!o)
- {
- mapname = "start";
- o = spawn();
- o.map = mapname;
- }
- // }
- nextmap = o.map;
- gameover = TRUE;
- if (o.nextthink < time)
- {
- o.think = execute_changelevel;
- o.nextthink = time + 0.1;
- }
- };
- /*
- ============
- CheckRules
- Exit deathmatch games upon conditions
- ============
- */
- void() CheckRules =
- {
- local float timelimit;
- local float fraglimit;
- if (gameover) // someone else quit the game already
- return;
- timelimit = cvar("timelimit") * 60;
- fraglimit = cvar("fraglimit");
- if (timelimit && time >= timelimit)
- {
- NextLevel ();
- return;
- }
- if (fraglimit && self.frags >= fraglimit)
- {
- NextLevel ();
- return;
- }
- };
- //============================================================================
- 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);
- }
- if (self.spawn_deferred)
- {
- local entity spot;
-
- spot = SelectSpawnPoint(FALSE);
- //dprint("time {} >= self.spawn_deferred {}\n", ftos(time), ftos(self.spawn_deferred));
- if (spot != world || time >= self.spawn_deferred) {
- respawn();
- }
- return;
- }
- // 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)
- {
- if (self.watertype == CONTENT_WATER)
- self.velocity_z = 100;
- else if (self.watertype == CONTENT_SLIME)
- self.velocity_z = 80;
- else
- self.velocity_z = 50;
- // 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.flags = self.flags - FL_ONGROUND; // don't stairwalk
- self.button2 = 0;
- // player jumping sound
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- self.velocity_z = self.velocity_z + 270;
- };
- /*
- ===========
- 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;
- }
- if (! (self.flags & FL_WATERJUMP) )
- self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
- };
- 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
- ================
- */
- //MED 01/17/97
- void(float num_bubbles) DeathBubbles;
- void() PlayerPreThink =
- {
- local float mspeed, aspeed;
- local float r;
- if (intermission_running)
- {
- earthquake_prethink();
- IntermissionThink (); // otherwise a button could be missed between
- return; // the think tics
- }
- if (self.view_ofs == '0 0 0')
- return; // intermission or finale
- //JIM
- // Kill player on Edge of Oblivion
- if ( ( self.origin_z < -1300 ) && (world.model == "maps/hipdm1.bsp") &&
- ( self.health > 0 ) )
- {
- self.deathtype = "falling";
- if (self.invincible_finished >= time)
- {
- self.invincible_finished = 0;
- self.items = self.items - (self.items & IT_INVULNERABILITY);
- self.invincible_time = 0;
- self.invincible_finished = 0;
- self.effects = self.effects - (self.effects & EF_PENTALIGHT);
- }
- T_Damage( self, self, world, self.health + 1000 );
- }
- //JIM
- // if (!deathmatch)
- // {
- earthquake_prethink();
- // }
- makevectors (self.v_angle); // is this still used
- CheckRules ();
- WaterMove ();
- //JIM
- //WETSUIT
- if (self.wetsuit_finished > time)
- {
- if (self.waterlevel==2)
- {
- self.velocity = self.velocity * 1.25;
- }
- if (self.waterlevel==3)
- {
- self.velocity = self.velocity * 1.5;
- }
- if (self.waterlevel >= 2)
- {
- // play scuba sound
- if (self.swim_flag < time)
- {
- self.swim_flag = time + 7;
- sound (self, CHAN_BODY, "misc/wetsuit.wav", 1, ATTN_NORM);
- }
- //MED 01/17/97
- else
- {
- if (fabs(self.swim_flag - time - 6)<0.04)
- {
- DeathBubbles(1);
- }
- else if (fabs(self.swim_flag - time - 5.5)<0.04)
- {
- DeathBubbles(1);
- }
- else if (fabs(self.swim_flag - time - 5)<0.04)
- {
- DeathBubbles(1);
- }
- }
- }
- }
- 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 != IT_MJOLNIR)
- {
- 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, "$qc_ring_fade");
- 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;
- }
- //MED 12/04/96 added mjolnir stuff
- else if (self.weapon == IT_MJOLNIR)
- self.modelindex = modelindex_hammer; // don't use 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, "$qc_protection_fade");
- 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_PENTALIGHT;
- else
- self.effects = self.effects - (self.effects & EF_PENTALIGHT);
- }
- // 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)
- {
- sprint(self, "$qc_quad_fade");
- 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;
- self.super_damage_finished = 0;
- self.super_time = 0;
- }
- if (self.super_damage_finished > time)
- self.effects = self.effects | EF_QUADLIGHT;
- else
- self.effects = self.effects - (self.effects & EF_QUADLIGHT);
- }
- // 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, "$qc_biosuit_fade");
- 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;
- }
- }
- //JIM
- // wetsuit
- if (self.wetsuit_finished)
- {
- self.air_finished = time + 12; // don't drown
- // sound and screen flash when items starts to run out
- if (self.wetsuit_finished < time + 3)
- {
- if (self.wetsuit_time == 1)
- {
- sprint (self, "$qc_wetsuit_fade");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
- self.wetsuit_time = time + 1;
- }
- if (self.wetsuit_time < time)
- {
- self.wetsuit_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
- if (self.wetsuit_finished < time)
- { // just stopped
- //MED
- self.items2 = self.items2 - HIP_IT_WETSUIT;
- self.wetsuit_time = 0;
- self.wetsuit_finished = 0;
- }
- }
- //MED
- // empathy shields
- if (self.empathy_finished)
- {
- // sound and screen flash when items starts to run out
- if (self.empathy_finished < time + 3)
- {
- if (self.empathy_time == 1)
- {
- sprint (self, "$qc_empathy_fade");
- stuffcmd (self, "bf\n");
- sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
- self.empathy_time = time + 1;
- }
- if (self.empathy_time < time)
- {
- self.empathy_time = time + 1;
- stuffcmd (self, "bf\n");
- }
- }
- if (self.empathy_finished < time)
- { // just stopped
- //MED
- self.items2 = self.items2 - HIP_IT_EMPATHY_SHIELDS;
- self.empathy_time = 0;
- self.empathy_finished = 0;
- }
- //MED
- if (self.empathy_finished > time)
- self.effects = self.effects | EF_DIMLIGHT;
- else
- self.effects = self.effects - (self.effects & EF_DIMLIGHT);
- }
- };
- /*
- ================
- PlayerPostThink
- Called every frame after physics are run
- ================
- */
- void() PlayerPostThink =
- {
- local float mspeed, aspeed;
- local float r;
- if (self.view_ofs == '0 0 0')
- {
- earthquake_postthink();
- return; // intermission or finale
- }
- //JIM
- //WETSUIT
- if (self.wetsuit_finished > time)
- {
- if (self.waterlevel==2)
- {
- self.velocity = self.velocity * 0.8;
- }
- if (self.waterlevel==3)
- {
- self.velocity = self.velocity * 0.66;
- }
- }
- //JIM
- // if (!deathmatch)
- // {
- earthquake_postthink();
- // }
- if (self.deadflag)
- return;
- // do weapon stuff
- W_WeaponFrame ();
- // check to see if player landed and play landing sound
- if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) && (self.health > 0))
- {
- if (self.watertype == CONTENT_WATER)
- sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
- else if (self.jump_flag < -650)
- {
- T_Damage (self, world, world, 5);
- sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
- self.deathtype = "falling";
- }
- else
- sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
- self.jump_flag = 0;
- }
- if (!(self.flags & FL_ONGROUND))
- self.jump_flag = self.velocity_z;
- CheckPowerups ();
- };
- /*
- ===========
- ClientConnect
- called when a player connects to a server
- ============
- */
- void() ClientConnect =
- {
- bprint("$qc_entered", self.netname);
- // a client connecting during an intermission can cause problems
- if (intermission_running)
- ExitIntermission ();
- };
- /*
- ===========
- ClientDisconnect
- called when a player disconnects from a server
- ============
- */
- void() ClientDisconnect =
- {
- if (gameover)
- return;
- // if the level end trigger has been activated, just return
- // since they aren't *really* leaving
- // let everyone else know
- bprint("$qc_left_game", self.netname, ftos(self.frags));
- sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
- self->effects = 0;
- set_suicide_frame ();
- };
- /*
- ===========
- ClientObituary
- called when a player dies
- ============
- */
- void(entity targ, entity attacker) ClientObituary =
- {
- local float rnum;
- local string deathstring, deathstring2;
- rnum = random();
- if (targ.classname == "player")
- {
- if (attacker.classname == "teledeath")
- {
- bprint("$qc_telefragged", targ.netname, attacker.owner.netname);
- attacker.owner.frags = attacker.owner.frags + 1;
- return;
- }
- if (attacker.classname == "teledeath2")
- {
- bprint("$qc_satans_power", targ.netname);
- targ.frags = targ.frags - 1;
- return;
- }
- if (attacker.classname == "player")
- {
- if (targ == attacker)
- {
- // killed self
- attacker.frags = attacker.frags - 1;
-
- if (targ.weapon == 64 && targ.waterlevel > 1)
- {
- if (targ.watertype == CONTENT_SLIME)
- bprint("$qc_discharge_slime", targ.netname);
- else if (targ.watertype == CONTENT_LAVA)
- bprint("$qc_discharge_lava", targ.netname);
- else
- bprint("$qc_discharge_water", targ.netname);
- return;
- }
- if (targ.weapon == 16)
- bprint("$qc_suicide_pin", targ.netname);
- else if (rnum)
- bprint("$qc_suicide_bored", targ.netname);
- else
- bprint("$qc_suicide_loaded", targ.netname);
- return;
- }
- else if ( (teamplay == 2) && (targ.team == attacker.team) &&
- (attacker.team != 0) )
- {
- if (rnum < 0.25)
- bprint("$qc_ff_teammate", attacker.netname);
- else if (rnum < 0.50)
- bprint("$qc_ff_glasses", attacker.netname);
- else if (rnum < 0.75)
- bprint("$qc_ff_otherteam", attacker.netname);
- else
- bprint("$qc_ff_friend", attacker.netname);
- attacker.frags = attacker.frags - 1;
- return;
- }
- else
- {
- attacker.frags = attacker.frags + 1;
- //MED 01/19/97
- if (empathyused == 1)
- {
- if (random()<0.5)
- bprint("$qc_death_empathy1", targ.netname, attacker.netname);
- else
- bprint("$qc_death_empathy2", targ.netname, attacker.netname);
- return;
- }
- //MED 11/18/96
- if (targ.dmg_inflictor.classname == "proximity_grenade")
- {
- if (random()<0.5)
- bprint("$qc_death_bomb1", targ.netname, attacker.netname);
- else
- bprint("$qc_death_bomb2", targ.netname, attacker.netname);
- return;
- }
- rnum = attacker.weapon;
- if (rnum == IT_AXE)
- {
- bprint("$qc_death_ax", targ.netname, attacker.netname);
- return;
- }
- if (rnum == IT_SHOTGUN)
- {
- bprint("$qc_death_sg", targ.netname, attacker.netname);
- return;
- }
- if (rnum == IT_SUPER_SHOTGUN)
- {
- bprint("$qc_death_dbl", targ.netname, attacker.netname);
- return;
- }
- if (rnum == IT_NAILGUN)
- {
- bprint("$qc_death_nail", targ.netname, attacker.netname);
- return;
- }
- if (rnum == IT_SUPER_NAILGUN)
- {
- bprint("$qc_death_sng", targ.netname, attacker.netname);
- return;
- }
- if (rnum == IT_GRENADE_LAUNCHER)
- {
- if (targ.health < -40)
- {
- bprint("$qc_death_gl1", targ.netname, attacker.netname);
- return;
- }
- else
- {
- bprint("$qc_death_gl2", targ.netname, attacker.netname);
- return;
- }
- }
- if (rnum == IT_ROCKET_LAUNCHER)
- {
- if (attacker.super_damage_finished > 0 && targ.health < -40)
- {
- rnum = random();
- if (rnum < 0.3)
- {
- bprint("$qc_death_rl_quad1", targ.netname, attacker.netname);
- return;
- }
- else if (rnum < 0.6)
- {
- bprint("$qc_death_rl_quad2", targ.netname, attacker.netname);
- return;
- }
- else
- {
- bprint("$qc_death_rl1", targ.netname, attacker.netname);
- return;
- }
- }
- else
- {
- if (targ.health < -40)
- {
- bprint("$qc_death_rl2", targ.netname, attacker.netname);
- return;
- }
- else
- {
- bprint("$qc_death_rl3", targ.netname, attacker.netname);
- return;
- }
- }
- }
- if (rnum == IT_LIGHTNING)
- {
- if (attacker.waterlevel > 1)
- {
- bprint("$qc_death_lg1", targ.netname, attacker.netname);
- if (attacker.invincible_finished)
- {
- msg_entity = attacker;
- WriteByte (MSG_ONE, SVC_ACHIEVEMENT);
- WriteString(MSG_ONE, "ACH_SURVIVE_DISCHARGE");
- }
- }
- else
- bprint("$qc_death_lg2", targ.netname, attacker.netname);
-
- return;
- }
- //MED
- if (rnum == IT_LASER_CANNON)
- {
- if (random()<0.5)
- {
- bprint("$qc_death_laser1", targ.netname, attacker.netname);
- }
- else
- {
- bprint("$qc_death_laser2", targ.netname, attacker.netname);
- }
- }
- //MED
- if (rnum == IT_MJOLNIR)
- {
- bprint("$qc_death_hammer", targ.netname, attacker.netname);
- }
- }
- return;
- }
- else
- {
- targ.frags = targ.frags - 1; // killed self
- rnum = targ.watertype;
- //JIM
- if ( attacker.deathtype )
- {
- bprint(attacker.deathtype, targ.netname);
- return;
- }
- if (rnum == -3)
- {
- if (random() < 0.5)
- bprint ("$qc_death_drown1", targ.netname);
- else
- bprint ("$qc_death_drown2", targ.netname);
- return;
- }
- else if (rnum == -4)
- {
- if (random() < 0.5)
- bprint ("$qc_death_slime1", targ.netname);
- else
- bprint ("$qc_death_slime2", targ.netname);
- return;
- }
- else if (rnum == -5)
- {
- if (targ.health < -15)
- {
- bprint ("$qc_death_lava1", targ.netname);
- return;
- }
- if (random() < 0.5)
- bprint ("$qc_death_lava2", targ.netname);
- else
- bprint ("$qc_death_lava3", targ.netname);
- return;
- }
- if (attacker.flags & FL_MONSTER)
- {
- if (attacker.classname == "monster_army")
- bprint ("$qc_ks_grunt", targ.netname);
- if (attacker.classname == "monster_demon1")
- bprint ("$qc_ks_fiend", targ.netname);
- if (attacker.classname == "monster_dog")
- bprint ("$qc_ks_rottweiler", targ.netname);
- if (attacker.classname == "monster_dragon")
- bprint ("$qc_ks_dragon", targ.netname);
- if (attacker.classname == "monster_enforcer")
- bprint ("$qc_ks_enforcer", targ.netname);
- if (attacker.classname == "monster_fish")
- bprint ("$qc_ks_rotfish", targ.netname);
- if (attacker.classname == "monster_hell_knight")
- bprint ("$qc_ks_deathknight", targ.netname);
- if (attacker.classname == "monster_knight")
- bprint ("$qc_ks_knight", targ.netname);
- if (attacker.classname == "monster_ogre")
- bprint ("$qc_ks_ogre", targ.netname);
- if (attacker.classname == "monster_oldone")
- bprint ("$qc_ks_shub", targ.netname);
- if (attacker.classname == "monster_shalrath")
- bprint ("$qc_ks_vore", targ.netname);
- if (attacker.classname == "monster_shambler")
- bprint ("$qc_ks_shambler", targ.netname);
- if (attacker.classname == "monster_tarbaby")
- bprint ("$qc_ks_spawn", targ.netname);
- if (attacker.classname == "monster_vomit")
- bprint ("$qc_ks_vomitus", targ.netname);
- if (attacker.classname == "monster_wizard")
- bprint ("$qc_ks_scrag", targ.netname);
- if (attacker.classname == "monster_zombie")
- bprint ("$qc_ks_zombie", targ.netname);
- //MED
- if (attacker.classname == "monster_gremlin")
- bprint ("$qc_ks_gremlin", targ.netname);
- //MED
- if (attacker.classname == "monster_scourge")
- bprint ("$qc_ks_centroid", targ.netname);
- //MED
- if (attacker.classname == "monster_armagon")
- bprint ("$qc_ks_armagon", targ.netname);
- return;
- }
- if (attacker.classname == "explo_box")
- {
- bprint ("$qc_ks_blew_up", targ.netname);
- return;
- }
- if (attacker.solid == SOLID_BSP && attacker != world)
- {
- bprint ("$qc_death_squish", targ.netname);
- return;
- }
- if (targ.deathtype == "falling")
- {
- targ.deathtype = "";
- bprint ("$qc_death_fall", targ.netname);
- return;
- }
- if (attacker.classname == "trap_shooter" || attacker.classname == "trap_spikeshooter")
- {
- bprint ("$qc_ks_spiked", targ.netname);
- return;
- }
- if (attacker.classname == "fireball")
- {
- bprint ("$qc_ks_lavaball", targ.netname);
- return;
- }
- if (attacker.classname == "trigger_changelevel")
- {
- bprint ("$qc_ks_tried_leave", targ.netname);
- return;
- }
- bprint ("$qc_death_died", targ.netname);
- }
- }
- };
|