Guest User

Untitled

a guest
Feb 19th, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 31.32 KB | None | 0 0
  1.  
  2. // prototypes
  3.  
  4. void () W_WeaponFrame;
  5. void (float weap) W_WeaponSwitch;
  6. void() player_pain;
  7. void() player_stand1;
  8. void (vector org) spawn_tfog;
  9. void (vector org, entity death_owner) spawn_tdeath;
  10.  
  11. float   modelindex_eyes, modelindex_player;
  12.  
  13. /*
  14. =============================================================================
  15.  
  16.                 LEVEL CHANGING / INTERMISSION
  17.  
  18. =============================================================================
  19. */
  20.  
  21. string nextmap;
  22.  
  23. /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
  24. This is the camera point for the intermission.
  25. Use mangle instead of angle, so you can set pitch or roll as well as yaw.  'pitch roll yaw'
  26. */
  27. void() info_intermission =
  28. {
  29.     self.angles = self.mangle;      // so C can get at it
  30. };
  31.  
  32.  
  33.  
  34. void() SetChangeParms =
  35. {
  36.     if (self.health <= 0)
  37.     {
  38.         SetNewParms ();
  39.         return;
  40.     }
  41.  
  42. // remove items
  43.     self.items = self.items - (self.items &
  44.     (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
  45.    
  46. // cap super health
  47.     if (self.health > 100)
  48.         self.health = 100;
  49.     if (self.health < 50)
  50.         self.health = 50;
  51.     parm1 = self.items;
  52.     parm2 = self.health;
  53.     parm3 = self.armorvalue;
  54.     if (self.ammo_shells_real < 25)
  55.         parm4 = 25;
  56.     else
  57.         parm4 = self.ammo_shells_real;
  58.     parm5 = self.ammo_nails_real;
  59.     parm6 = self.ammo_rockets_real;
  60.     parm7 = self.ammo_cells_real;
  61.     parm8 = self.weapon;
  62.     parm9 = self.armortype;
  63. };
  64.  
  65. void() SetNewParms =
  66. {
  67.     parm1 = IT_SHOTGUN | IT_AXE;
  68.     parm2 = 100;
  69.     parm3 = 0;
  70.     parm4 = 25;
  71.     parm5 = 0;
  72.     parm6 = 0;
  73.     parm7 = 0;
  74.     parm8 = IT_SHOTGUN;
  75.     parm9 = 0;
  76. };
  77.  
  78. void() DecodeLevelParms =
  79. {
  80.     if (!deathmatch)
  81.     {
  82.         if (world.model == "maps/start.bsp")
  83.             SetNewParms ();         // take away all stuff on starting new episode
  84.     }
  85.    
  86.     self.items = parm1;
  87.     self.health = parm2;
  88.     self.armorvalue = parm3;
  89.     self.ammo_shells_real = parm4;
  90.     self.ammo_nails_real = parm5;
  91.     self.ammo_rockets_real = parm6;
  92.     self.ammo_cells_real = parm7;
  93.     self.weapon = parm8;
  94.     self.armortype = parm9;
  95. };
  96.  
  97. /*
  98. ============
  99. FindIntermission
  100.  
  101. Returns the entity to view from
  102. ============
  103. */
  104. entity() FindIntermission =
  105. {
  106.     local   entity spot;
  107.     local   float cyc;
  108.  
  109. // look for info_intermission first
  110.     spot = find (world, classname, "info_intermission");
  111.     if (spot)
  112.     {       // pick a random one
  113.         cyc = random() * 4;
  114.         while (cyc > 1)
  115.         {
  116.             spot = find (spot, classname, "info_intermission");
  117.             if (!spot)
  118.                 spot = find (spot, classname, "info_intermission");
  119.             cyc = cyc - 1;
  120.         }
  121.         return spot;
  122.     }
  123.  
  124. // then look for the start position
  125.     spot = find (world, classname, "info_player_start");
  126.     if (spot)
  127.         return spot;
  128.    
  129.     objerror ("FindIntermission: no spot");
  130.     return world; // remove warning
  131. };
  132.  
  133. void() GotoNextMap =
  134. {
  135.     local string newmap;
  136.  
  137. //ZOID: 12-13-96, samelevel is overloaded, only 1 works for same level
  138.  
  139.     if (cvar("samelevel") == 1)     // if samelevel is set, stay on same level
  140.         changelevel (mapname);
  141.     else {
  142.         // configurable map lists, see if the current map exists as a
  143.         // serverinfo/localinfo var
  144.         newmap = stringserverinfokey(mapname);
  145.         if (newmap != "")
  146.             changelevel (newmap);
  147.         else
  148.             changelevel (nextmap);
  149.     }
  150. };
  151.  
  152. void() ExitIntermission=
  153. {
  154. // skip any text in deathmatch
  155.     if (deathmatch)
  156.     {
  157.         GotoNextMap ();
  158.         return;
  159.     }
  160.    
  161.     intermission_exittime = time + 1;
  162.     intermission_running = intermission_running + 1;
  163.  
  164. //
  165. // run some text if at the end of an episode
  166. //
  167.     if (intermission_running == 2)
  168.     {
  169.         if (world.model == "maps/e1m7.bsp")
  170.         {
  171.             ENG_SwitchTrack(2, 3);
  172.             if (!cvar("registered"))
  173.             {
  174.                 WriteByte (MSG_ALL, SVC_FINALE);
  175.                 WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task in the other three\nhaunted lands of Quake. Or are you? If\nyou don't register Quake, you'll never\nknow what awaits you in the Realm of\nBlack Magic, the Netherworld, and the\nElder World!");
  176.             }
  177.             else
  178.             {
  179.                 WriteByte (MSG_ALL, SVC_FINALE);
  180.                 WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task. A Rune of magic\npower lies at the end of each haunted\nland of Quake. Go forth, seek the\ntotality of the four Runes!");
  181.             }
  182.             return;
  183.         }
  184.         else if (world.model == "maps/e2m6.bsp")
  185.         {
  186.             ENG_SwitchTrack(2, 3);
  187.             WriteByte (MSG_ALL, SVC_FINALE);
  188.             WriteString (MSG_ALL, "The Rune of Black Magic throbs evilly in\nyour hand and whispers dark thoughts\ninto your brain. You learn the inmost\nlore of the Hell-Mother; Shub-Niggurath!\nYou now know that she is behind all the\nterrible plotting which has led to so\nmuch death and horror. But she is not\ninviolate! Armed with this Rune, you\nrealize that once all four Runes are\ncombined, the gate to Shub-Niggurath's\nPit will open, and you can face the\nWitch-Goddess herself in her frightful\notherworld cathedral.");
  189.             return;
  190.         }
  191.         else if (world.model == "maps/e3m6.bsp")
  192.         {
  193.             ENG_SwitchTrack(2, 3);
  194.             WriteByte (MSG_ALL, SVC_FINALE);
  195.             WriteString (MSG_ALL, "The charred viscera of diabolic horrors\nbubble viscously as you seize the Rune\nof Hell Magic. Its heat scorches your\nhand, and its terrible secrets blight\nyour mind. Gathering the shreds of your\ncourage, you shake the devil's shackles\nfrom your soul, and become ever more\nhard and determined to destroy the\nhideous creatures whose mere existence\nthreatens the souls and psyches of all\nthe population of Earth.");
  196.             return;
  197.         }
  198.         else if (world.model == "maps/e4m7.bsp")
  199.         {
  200.             ENG_SwitchTrack(2, 3);
  201.             WriteByte (MSG_ALL, SVC_FINALE);
  202.             WriteString (MSG_ALL, "Despite the awful might of the Elder\nWorld, you have achieved the Rune of\nElder Magic, capstone of all types of\narcane wisdom. Beyond good and evil,\nbeyond life and death, the Rune\npulsates, heavy with import. Patient and\npotent, the Elder Being Shub-Niggurath\nweaves her dire plans to clear off all\nlife from the Earth, and bring her own\nfoul offspring to our world! For all the\ndwellers in these nightmare dimensions\nare her descendants! Once all Runes of\nmagic power are united, the energy\nbehind them will blast open the Gateway\nto Shub-Niggurath, and you can travel\nthere to foil the Hell-Mother's plots\nin person.");
  203.             return;
  204.         }
  205.  
  206.         GotoNextMap();
  207.     }
  208.    
  209.     if (intermission_running == 3)
  210.     {
  211.         if (!cvar("registered"))
  212.         {   // shareware episode has been completed, go to sell screen
  213.             WriteByte (MSG_ALL, SVC_SELLSCREEN);
  214.             return;
  215.         }
  216.        
  217.         if ( (serverflags&15) == 15)
  218.         {
  219.             WriteByte (MSG_ALL, SVC_FINALE);
  220.             WriteString (MSG_ALL, "Now, you have all four Runes. You sense\ntremendous invisible forces moving to\nunseal ancient barriers. Shub-Niggurath\nhad hoped to use the Runes Herself to\nclear off the Earth, but now instead,\nyou will use them to enter her home and\nconfront her as an avatar of avenging\nEarth-life. If you defeat her, you will\nbe remembered forever as the savior of\nthe planet. If she conquers, it will be\nas if you had never been born.");
  221.             return;
  222.         }
  223.        
  224.     }
  225.  
  226.     GotoNextMap();
  227. };
  228.  
  229. /*
  230. ============
  231. IntermissionThink
  232.  
  233. When the player presses attack or jump, change to the next level
  234. ============
  235. */
  236. void() IntermissionThink =
  237. {
  238.     if (time < intermission_exittime)
  239.         return;
  240.  
  241.     if (!self.button0 && !self.button1 && !self.button2)
  242.         return;
  243.    
  244.     ExitIntermission ();
  245. };
  246.  
  247. /*
  248. ============
  249. execute_changelevel
  250.  
  251. The global "nextmap" has been set previously.
  252. Take the players to the intermission spot
  253. ============
  254. */
  255. void() execute_changelevel =
  256. {
  257.     local entity    pos;
  258.  
  259.     intermission_running = 1;
  260.    
  261. // enforce a wait time before allowing changelevel
  262.     if (deathmatch)
  263.         intermission_exittime = time + 5;
  264.     else
  265.         intermission_exittime = time + 2;
  266.  
  267.     pos = FindIntermission ();
  268.  
  269. // play intermission music
  270.     ENG_SwitchTrack(3, 3);
  271.  
  272. #ifdef NETQUAKE
  273.     pos = FindIntermission ();
  274.  
  275.     other = find (world, classname, "player");
  276.     while (other != world)
  277.     {
  278.         other.view_ofs = '0 0 0';
  279.         other.angles = other.v_angle = pos.mangle;
  280.         other.fixangle = TRUE;      // turn this way immediately
  281.         other.nextthink = time + 0.5;
  282.         other.takedamage = DAMAGE_NO;
  283.         other.solid = SOLID_NOT;
  284.         other.movetype = MOVETYPE_NONE;
  285.         other.modelindex = 0;
  286.         setorigin (other, pos.origin);
  287.         other = find (other, classname, "player");
  288.     }  
  289.  
  290.     WriteByte (MSG_ALL, SVC_INTERMISSION);
  291. #else
  292.     WriteByte (MSG_ALL, SVC_INTERMISSION);
  293.     WriteCoord (MSG_ALL, pos.origin_x);
  294.     WriteCoord (MSG_ALL, pos.origin_y);
  295.     WriteCoord (MSG_ALL, pos.origin_z);
  296.     WriteAngle (MSG_ALL, pos.mangle_x);
  297.     WriteAngle (MSG_ALL, pos.mangle_y);
  298.     WriteAngle (MSG_ALL, pos.mangle_z);
  299.    
  300.     other = find (world, classname, "player");
  301.     while (other != world)
  302.     {
  303.         other.takedamage = DAMAGE_NO;
  304.         other.solid = SOLID_NOT;
  305.         other.movetype = MOVETYPE_NONE;
  306.         other.modelindex = 0;
  307.         other = find (other, classname, "player");
  308.     }      
  309. #endif
  310. };
  311.  
  312.  
  313. void() changelevel_touch =
  314. {
  315.     if (other.classname != "player")
  316.         return;
  317.  
  318. // if "noexit" is set, blow up the player trying to leave
  319. //ZOID, 12-13-96, noexit isn't supported in QW.  Overload samelevel
  320. //      if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
  321.     if (deathmatch)
  322.     {
  323.         if ((cvar("samelevel") == 2) || ((cvar("samelevel") == 3) && (mapname != "start")))
  324.         {
  325.             T_Damage (other, self, self, 50000, MOD_EXIT);
  326.             return;
  327.         }
  328.     }
  329.  
  330.     bprint2 (PRINT_HIGH, other.netname, " exited the level\n");
  331.    
  332.     nextmap = self.map;
  333.  
  334.     SUB_UseTargets ();
  335.  
  336.     self.touch = SUB_Null;
  337.  
  338. // we can't move people right now, because touch functions are called
  339. // in the middle of C movement code, so set a think time to do it
  340.     self.think = execute_changelevel;
  341.     self.nextthink = time + 0.1;
  342. };
  343.  
  344. /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
  345. 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.
  346. */
  347. void() trigger_changelevel =
  348. {
  349.     if (!self.map)
  350.         objerror ("chagnelevel trigger doesn't have map");
  351.    
  352.     InitTrigger ();
  353.     self.touch = changelevel_touch;
  354. };
  355.  
  356.  
  357. /*
  358. =============================================================================
  359.  
  360.                 PLAYER GAME EDGE FUNCTIONS
  361.  
  362. =============================================================================
  363. */
  364.  
  365. void() set_suicide_frame;
  366.  
  367. // create a deadbody ent that is removed over time
  368. void(entity ent) CopyToDeadbody =
  369. {
  370.     local entity deadbody;
  371.  
  372.     deadbody = spawn();
  373.     deadbody.angles = ent.angles;
  374.     deadbody.model = ent.model;
  375.     deadbody.modelindex = ent.modelindex;
  376.     deadbody.frame = ent.frame;
  377.     deadbody.colormap = ent.colormap;
  378.     deadbody.movetype = ent.movetype;
  379.     deadbody.velocity = ent.velocity;
  380.     deadbody.flags = 0;
  381.     setorigin (deadbody, ent.origin);
  382.     setsize (deadbody, ent.mins, ent.maxs);
  383.  
  384.     deadbody.think = SUB_Remove;
  385.     deadbody.nextthink = time + 30;
  386. };
  387.  
  388. // called by ClientKill and DeadThink
  389. void() respawn =
  390. {
  391.     if (coop)
  392.     {
  393.         // make a copy of the dead body for appearances sake
  394.         CopyToDeadbody (self);
  395.         // get the spawn parms as they were at level start
  396.         setspawnparms (self);
  397.         // respawn     
  398.         PutClientInServer ();
  399.     }
  400.     else if (deathmatch)
  401.     {
  402.         // make a copy of the dead body for appearances sake
  403.         CopyToDeadbody (self);
  404.         // set default spawn parms
  405.         SetNewParms ();
  406.         // respawn     
  407.         PutClientInServer ();
  408.     }
  409.     else
  410.     {   // restart the entire server
  411.         localcmd ("restart\n");
  412.     }
  413. };
  414.  
  415.  
  416. /*
  417. ============
  418. ClientKill
  419.  
  420. Player entered the suicide command
  421. ============
  422. */
  423. void() PlayerDropStuff;
  424.  
  425. void() ClientKill =
  426. {
  427.     if (intermission_running)
  428.         return;
  429.  
  430.     if (self.suicide_time > time)
  431.         return;
  432.  
  433.     bprint2 (PRINT_MEDIUM, self.netname, " suicides\n");
  434.     PlayerDropStuff ();
  435.     set_suicide_frame ();
  436.     self.modelindex = modelindex_player;
  437.     logfrag (self, self);
  438.     self.frags = self.frags - 2;    // extra penalty
  439.     respawn ();
  440. };
  441.  
  442. /*
  443. ============
  444. SelectSpawnPoint
  445.  
  446. Returns the entity to spawn at
  447. ============
  448. */
  449. entity() SelectSpawnPoint =
  450. {
  451.     local entity spot, thing;
  452.     local float numspots, totalspots;
  453.     local float pcount;
  454.     local entity spots;
  455.  
  456.     if (coop) // coop spawning
  457.     {
  458.         if (!spotspawn)
  459.         {
  460.             spotspawn = 1;
  461.             spot = find (world, classname, "info_player_start");
  462.             if (spot)
  463.                 return spot;
  464.         }
  465.         lastspawn = find(lastspawn, classname, "info_player_coop");
  466.         if (lastspawn)
  467.             return lastspawn;
  468.     }
  469.  
  470.     if (!deathmatch) // single player spawning
  471.     {
  472.         if (serverflags)
  473.         {   // return with a rune to start
  474.             spot = find (world, classname, "info_player_start2");
  475.             if (spot)
  476.                 return spot;
  477.         }
  478.    
  479.         spot = find (world, classname, "info_player_start");
  480.         if (spot)
  481.             return spot;
  482.     }
  483.  
  484.     // QuakeWorld style deathmatch spawning
  485.     numspots = 0;
  486.     totalspots = 0;
  487.    
  488.     // choose a info_player_deathmatch point
  489.     // ok, find all spots that don't have players nearby
  490.     spots = world;
  491.     spot = find (world, classname, "info_player_deathmatch");      
  492.     while (spot)
  493.     {
  494.         totalspots = totalspots + 1;
  495.  
  496.         thing=findradius(spot.origin, 84);
  497.         pcount=0;              
  498.         while (thing)
  499.         {
  500.             if (thing.classname == "player")
  501.                 pcount=pcount + 1;                      
  502.             thing=thing.chain;      
  503.         }
  504.         if (pcount == 0) {
  505.             spot.goalentity = spots;
  506.             spots = spot;
  507.             numspots = numspots + 1;
  508.         }
  509.  
  510.         // Get the next spot in the chain
  511.         spot = find (spot, classname, "info_player_deathmatch");                
  512.     }
  513.     totalspots=totalspots - 1;
  514.     if (!numspots) {
  515.         // ack, they are all full, just pick one at random
  516.         totalspots = rint((random() * totalspots));
  517.         spot = find (world, classname, "info_player_deathmatch");      
  518.         while (totalspots > 0) {
  519.             totalspots = totalspots - 1;
  520.             spot = find (spot, classname, "info_player_deathmatch");
  521.         }
  522.         return spot;
  523.     }
  524.        
  525.     // We now have the number of spots available on the map in numspots
  526.     // Generate a random number between 1 and numspots
  527.     numspots = numspots - 1;
  528.     numspots = rint((random() * numspots));
  529.  
  530.     spot = spots;
  531.     while (numspots > 0) {
  532.         spot = spot.goalentity;
  533.         numspots = numspots - 1;
  534.     }
  535.     return spot;
  536.  
  537. };
  538. void() DecodeLevelParms;
  539. void() PlayerDie;
  540.  
  541. /*
  542. ===========
  543. PutClientInServer
  544.  
  545. called each time a player enters a new level
  546. ============
  547. */
  548. void() PutClientInServer =
  549. {
  550.     local   entity spot;
  551.     local float wtemp;
  552.    
  553.    
  554.     self.classname = "player";
  555.     self.health = 100;
  556.     self.takedamage = DAMAGE_AIM;
  557.     self.solid = SOLID_SLIDEBOX;
  558.     self.movetype = MOVETYPE_WALK;
  559.     self.show_hostile = 0;
  560.     self.max_health = 100;
  561.     self.flags = FL_CLIENT;
  562.     self.air_finished = time + 12;
  563.     self.waterdmg = 2; // initial water damage
  564.     self.super_damage_finished = 0;
  565.     self.radsuit_finished = 0;
  566.     self.invisible_finished = 0;
  567.     self.invincible_finished = 0;
  568.     self.effects = 0;
  569.     self.invincible_time = 0;
  570.     self.suicide_time = time + 3;
  571.     self.weaponstate = WS_IDLE;
  572.  
  573.     DecodeLevelParms ();
  574.    
  575.     // dumb hack until I get the real weapon system in
  576.     wtemp = self.weapon;
  577.  
  578.     if (deathmatch == 4)
  579.     {
  580.         self.ammo_shells_real = 0;
  581.         if (numberserverinfokey("axe") == 0)
  582.         {
  583.             self.ammo_nails_real = 255;
  584.             self.ammo_shells_real = 255;
  585.             self.ammo_rockets_real = 255;
  586.             self.ammo_cells_real = 255;
  587.             self.items |= IT_NAILGUN
  588.             | IT_SUPER_NAILGUN
  589.             | IT_SUPER_SHOTGUN
  590.             | IT_ROCKET_LAUNCHER
  591.             | IT_LIGHTNING;
  592.         }
  593.         else
  594.             wtemp = IT_AXE;
  595.  
  596.         self.items |= IT_ARMOR3 | IT_INVULNERABILITY;
  597.         self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2));
  598.         self.armorvalue = 200;
  599.         self.armortype = 0.8;
  600.         self.health = 250;
  601.         self.invincible_time = 1;
  602.         self.invincible_finished = time + 3;
  603.     }
  604.  
  605.     if (deathmatch == 5)
  606.     {
  607.         self.ammo_nails_real = 80;
  608.         self.ammo_shells_real = 30;
  609.         self.ammo_rockets_real = 10;
  610.         self.ammo_cells_real = 30;
  611.         self.items |= IT_NAILGUN
  612.             | IT_SUPER_NAILGUN
  613.             | IT_SUPER_SHOTGUN
  614.             | IT_ROCKET_LAUNCHER
  615.             | IT_GRENADE_LAUNCHER
  616.             | IT_LIGHTNING
  617.             | IT_ARMOR3
  618.             | IT_INVULNERABILITY;
  619.         self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2));
  620.         self.armorvalue = 200;
  621.         self.armortype = 0.8;
  622.         self.health = 200;
  623.         self.invincible_time = 1;
  624.         self.invincible_finished = time + 3;
  625.     }
  626.  
  627.     self.weapon = 0;
  628.     W_WeaponSwitch (wtemp);
  629.  
  630.     self.attack_finished = time;
  631.     self.th_pain = player_pain;
  632.     self.th_die = PlayerDie;
  633.    
  634.     self.deadflag = DEAD_NO;
  635.    
  636.     spot = SelectSpawnPoint ();
  637.  
  638.     self.origin = spot.origin + '0 0 1';
  639.     self.angles = spot.angles;
  640.     self.fixangle = TRUE;           // turn this way immediately
  641.  
  642. // oh, this is a hack!
  643.     setmodel (self, "progs/eyes.mdl");
  644.     modelindex_eyes = self.modelindex;
  645.  
  646.     setmodel (self, "progs/player.mdl");
  647.     modelindex_player = self.modelindex;
  648.  
  649.     setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
  650.    
  651.     self.view_ofs = '0 0 22';
  652.  
  653. // Mod - Xian (May.20.97)
  654. // Bug where player would have velocity from their last kill
  655.  
  656.     self.velocity = '0 0 0';
  657.  
  658.     player_stand1 ();
  659.    
  660.     makevectors(self.angles);
  661.     spawn_tfog (self.origin + v_forward*20);
  662.  
  663.     spawn_tdeath (self.origin, self);
  664.  
  665.     // Set Rocket Jump Modifiers
  666.     rj = numberserverinfokey("rj");
  667. };
  668.  
  669.  
  670. /*
  671. =============================================================================
  672.  
  673.                 QUAKED FUNCTIONS
  674.  
  675. =============================================================================
  676. */
  677.  
  678.  
  679. /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
  680. The normal starting point for a level.
  681. */
  682. void() info_player_start =
  683. {
  684. };
  685.  
  686.  
  687. /*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
  688. Only used on start map for the return point from an episode.
  689. */
  690. void() info_player_start2 =
  691. {
  692. };
  693.  
  694. /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
  695. potential spawning position for deathmatch games
  696. */
  697. void() info_player_deathmatch =
  698. {
  699. };
  700.  
  701. /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
  702. potential spawning position for coop games
  703. */
  704. void() info_player_coop =
  705. {
  706. };
  707.  
  708. /*
  709. ===============================================================================
  710.  
  711. RULES
  712.  
  713. ===============================================================================
  714. */
  715.  
  716. /*
  717. go to the next level for deathmatch
  718. */
  719. void() NextLevel =
  720. {
  721.     local entity o;
  722.  
  723.     if (nextmap != "")
  724.         return; // already done
  725.  
  726.     if (mapname == "start")
  727.     {
  728.         if (!cvar("registered"))
  729.         {
  730.             mapname = "e1m1";
  731.         }
  732.         else if (!(serverflags & 1))
  733.         {
  734.             mapname = "e1m1";
  735.             serverflags = serverflags | 1;
  736.         }
  737.         else if (!(serverflags & 2))
  738.         {
  739.             mapname = "e2m1";
  740.             serverflags = serverflags | 2;
  741.         }
  742.         else if (!(serverflags & 4))
  743.         {
  744.             mapname = "e3m1";
  745.             serverflags = serverflags | 4;
  746.         }
  747.         else if (!(serverflags & 8))
  748.         {
  749.             mapname = "e4m1";
  750.             serverflags = serverflags - 7;
  751.         }
  752.  
  753.         o = spawn();
  754.         o.map = mapname;
  755.     }
  756.     else
  757.     {
  758.         // find a trigger changelevel
  759.         o = find(world, classname, "trigger_changelevel");
  760.         if (!o || mapname == "start")
  761.         {       // go back to same map if no trigger_changelevel
  762.             o = spawn();
  763.             o.map = mapname;
  764.         }
  765.     }
  766.  
  767.     nextmap = o.map;
  768.  
  769.     if (o.nextthink < time)
  770.     {
  771.         o.think = execute_changelevel;
  772.         o.nextthink = time + 0.1;
  773.     }
  774. };
  775.  
  776. /*
  777. ============
  778. CheckRules
  779.  
  780. Exit deathmatch games upon conditions
  781. ============
  782. */
  783. void() CheckRules =
  784. {      
  785.     if (deathmatch && timelimit && time >= timelimit)
  786.         NextLevel ();
  787.    
  788.     if (deathmatch && fraglimit && self.frags >= fraglimit)
  789.         NextLevel ();
  790. };
  791.  
  792. //============================================================================
  793.  
  794. void() PlayerDeathThink =
  795. {
  796.     local float             forward;
  797.  
  798.     if ((self.flags & FL_ONGROUND))
  799.     {
  800.         forward = vlen (self.velocity);
  801.         forward = forward - 20;
  802.         if (forward <= 0)
  803.             self.velocity = '0 0 0';
  804.         else    
  805.             self.velocity = forward * normalize(self.velocity);
  806.     }
  807.  
  808. // wait for all buttons released
  809.     if (self.deadflag == DEAD_DEAD)
  810.     {
  811.         if (self.button2 || self.button1 || self.button0)
  812.             return;
  813.         self.deadflag = DEAD_RESPAWNABLE;
  814.         return;
  815.     }
  816.  
  817. // wait for any button down
  818.     if (!self.button2 && !self.button1 && !self.button0)
  819.         return;
  820.  
  821.     self.button0 = 0;
  822.     self.button1 = 0;
  823.     self.button2 = 0;
  824.     respawn();
  825. };
  826.  
  827.  
  828. void() PlayerJump =
  829. {
  830.     if (self.flags & FL_WATERJUMP)
  831.         return;
  832.    
  833.     if (self.waterlevel >= 2)
  834.     {
  835. // play swiming sound
  836.         if (self.swim_flag < time)
  837.         {
  838.             self.swim_flag = time + 1;
  839.             if (random() < 0.5)
  840.                 sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
  841.             else
  842.                 sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
  843.         }
  844.  
  845.         return;
  846.     }
  847.  
  848.     if (!(self.flags & FL_ONGROUND))
  849.         return;
  850.  
  851.     if ( !(self.flags & FL_JUMPRELEASED) )
  852.         return;         // don't pogo stick
  853.  
  854.     self.flags = self.flags - (self.flags & FL_JUMPRELEASED);      
  855.     self.button2 = 0;
  856.  
  857. // player jumping sound
  858.     sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
  859. #ifdef NETQUAKE
  860.     self.flags = self.flags - FL_ONGROUND;
  861.     self.velocity_z = self.velocity_z + 270;
  862. #endif
  863. };
  864.  
  865.  
  866. /*
  867. ===========
  868. WaterMove
  869.  
  870. ============
  871. */
  872. void() WaterMove =
  873. {
  874. //dprint (ftos(self.waterlevel));
  875.     if (self.movetype == MOVETYPE_NOCLIP)
  876.         return;
  877.     if (self.health < 0)
  878.         return;
  879.  
  880.     if (self.waterlevel != 3)
  881.     {
  882.         if (self.air_finished < time)
  883.             sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
  884.         else if (self.air_finished < time + 9)
  885.             sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
  886.         self.air_finished = time + 12;
  887.         self.waterdmg = 2;
  888.     }
  889.     else if (self.air_finished < time)
  890.     {       // drown!
  891.         if (self.pain_finished < time)
  892.         {
  893.             self.waterdmg = self.waterdmg + 2;
  894.             if (self.waterdmg > 15)
  895.                 self.waterdmg = 10;
  896.             T_Damage (self, world, world, self.waterdmg, MOD_DROWN);
  897.             self.pain_finished = time + 1;
  898.         }
  899.     }
  900.    
  901.     if (!self.waterlevel)
  902.     {
  903.         if (self.flags & FL_INWATER)
  904.         {      
  905.             // play leave water sound
  906.             sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
  907.             self.flags = self.flags - FL_INWATER;
  908.         }
  909.         return;
  910.     }
  911.  
  912.     if ( !(self.flags & FL_INWATER) )
  913.     {      
  914.         // player enter water sound
  915.         switch (self.watertype)
  916.         {
  917.         case CONTENT_LAVA:
  918.             sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
  919.             break;
  920.         case CONTENT_WATER:
  921.             sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
  922.             break;
  923.         case CONTENT_SLIME:
  924.             sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
  925.             break;
  926.         }
  927.  
  928.         self.flags = self.flags + FL_INWATER;
  929.         self.dmgtime = 0;
  930.     }      
  931.  
  932.     if (self.watertype == CONTENT_LAVA)
  933.     {       // do damage
  934.         if (self.dmgtime < time)
  935.         {
  936.             if (self.radsuit_finished > time)
  937.                 self.dmgtime = time + 1;
  938.             else
  939.                 self.dmgtime = time + 0.2;
  940.  
  941.             T_Damage (self, world, world, 10*self.waterlevel, MOD_LAVA);
  942.         }
  943.     }
  944.     else if (self.watertype == CONTENT_SLIME)
  945.     {       // do damage
  946.         if (self.dmgtime < time && self.radsuit_finished < time)
  947.         {
  948.             self.dmgtime = time + 1;
  949.             T_Damage (self, world, world, 4*self.waterlevel, MOD_SLIME);
  950.         }
  951.     }
  952.  
  953. };
  954.  
  955. void() CheckWaterJump =
  956. {
  957.     local vector start, end;
  958.  
  959. // check for a jump-out-of-water
  960.     makevectors (self.angles);
  961.     start = self.origin;
  962.     start_z = start_z + 8;
  963.     v_forward_z = 0;
  964.     normalize(v_forward);
  965.     end = start + v_forward*24;
  966.     traceline (start, end, TRUE, self);
  967.     if (trace_fraction < 1)
  968.     {       // solid at waist
  969.         start_z = start_z + self.maxs_z - 8;
  970.         end = start + v_forward*24;
  971.         self.movedir = trace_plane_normal * -50;
  972.         traceline (start, end, TRUE, self);
  973.         if (trace_fraction == 1)
  974.         {       // open at eye level
  975.             self.flags = self.flags | FL_WATERJUMP;
  976.             self.velocity_z = 225;
  977.             self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
  978.             self.teleport_time = time + 2;  // safety net
  979.             return;
  980.         }
  981.     }
  982. };
  983.  
  984. /*
  985. ================
  986. PlayerPreThink
  987.  
  988. Called every frame before physics are run
  989. ================
  990. */
  991. void() PlayerPreThink =
  992. {
  993.     if (intermission_running)
  994.     {
  995.         IntermissionThink ();   // otherwise a button could be missed between
  996.         return;                                 // the think tics
  997.     }
  998.  
  999. // if intermission is running what is the point of this?
  1000. //  if (self.view_ofs == '0 0 0')
  1001. //      return;
  1002.  
  1003.     makevectors (self.v_angle);             // is this still used
  1004.  
  1005.     CheckRules ();
  1006.     WaterMove ();
  1007. /*
  1008.     if (self.waterlevel == 2)
  1009.         CheckWaterJump ();
  1010. */
  1011.  
  1012.     if (self.deadflag >= DEAD_DEAD)
  1013.     {
  1014.         PlayerDeathThink ();
  1015.         return;
  1016.     }
  1017.    
  1018.     if (self.deadflag == DEAD_DYING)
  1019.         return; // dying, so do nothing
  1020.  
  1021.     if (self.button2)
  1022.         PlayerJump ();
  1023.     else
  1024.         self.flags = self.flags | FL_JUMPRELEASED;
  1025.  
  1026.     if(time > self.attack_finished && self.currentammo == 0 && self.weapon != IT_AXE)
  1027.     {
  1028.         W_WeaponSwitch (W_BestWeapon ());
  1029.     }
  1030. };
  1031.    
  1032. /*
  1033. ================
  1034. CheckPowerups
  1035.  
  1036. Check for turning off powerups
  1037. ================
  1038. */
  1039. void() CheckPowerups =
  1040. {
  1041.     if (self.health <= 0)
  1042.         return;
  1043.  
  1044. // invisibility
  1045.     if (self.invisible_finished)
  1046.     {
  1047. // sound and screen flash when items starts to run out
  1048.         if (self.invisible_sound < time)
  1049.         {
  1050.             sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
  1051.             self.invisible_sound = time + ((random() * 3) + 1);
  1052.         }
  1053.  
  1054.  
  1055.         if (self.invisible_finished < time + 3)
  1056.         {
  1057.             if (self.invisible_time == 1)
  1058.             {
  1059.                 sprint1 (self, PRINT_HIGH, "Ring of Shadows magic is fading\n");
  1060.                 stuffcmd (self, "bf\n");
  1061.                 sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
  1062.                 self.invisible_time = time + 1;
  1063.             }
  1064.            
  1065.             if (self.invisible_time < time)
  1066.             {
  1067.                 self.invisible_time = time + 1;
  1068.                 stuffcmd (self, "bf\n");
  1069.             }
  1070.         }
  1071.  
  1072.         if (self.invisible_finished < time)
  1073.         {       // just stopped
  1074.             self.items = self.items - IT_INVISIBILITY;
  1075.             self.invisible_finished = 0;
  1076.             self.invisible_time = 0;
  1077.         }
  1078.        
  1079.     // use the eyes
  1080.         self.frame = 0;
  1081.         self.modelindex = modelindex_eyes;
  1082.     }
  1083.     else
  1084.         self.modelindex = modelindex_player;    // don't use eyes
  1085.  
  1086. // invincibility
  1087.     if (self.invincible_finished)
  1088.     {
  1089. // sound and screen flash when items starts to run out
  1090.         if (self.invincible_finished < time + 3)
  1091.         {
  1092.             if (self.invincible_time == 1)
  1093.             {
  1094.                 sprint1 (self, PRINT_HIGH, "Protection is almost burned out\n");
  1095.                 stuffcmd (self, "bf\n");
  1096.                 sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
  1097.                 self.invincible_time = time + 1;
  1098.             }
  1099.            
  1100.             if (self.invincible_time < time)
  1101.             {
  1102.                 self.invincible_time = time + 1;
  1103.                 stuffcmd (self, "bf\n");
  1104.             }
  1105.         }
  1106.        
  1107.         if (self.invincible_finished < time)
  1108.         {       // just stopped
  1109.             self.items = self.items - IT_INVULNERABILITY;
  1110.             self.invincible_time = 0;
  1111.             self.invincible_finished = 0;
  1112.         }
  1113.         if (self.invincible_finished > time)
  1114.             self.effects = self.effects | ef_pent;
  1115.         else
  1116.             self.effects = self.effects - (self.effects & ef_pent);
  1117.     }
  1118.  
  1119. // super damage
  1120.     if (self.super_damage_finished)
  1121.     {
  1122.  
  1123. // sound and screen flash when items starts to run out
  1124.  
  1125.         if (self.super_damage_finished < time + 3)
  1126.         {
  1127.             if (self.super_time == 1)
  1128.             {
  1129.                 if (deathmatch == 4)
  1130.                     sprint1 (self, PRINT_HIGH, "OctaPower is wearing off\n");
  1131.                 else
  1132.                     sprint1 (self, PRINT_HIGH, "Quad Damage is wearing off\n");
  1133.                 stuffcmd (self, "bf\n");
  1134.                 sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1135.                 self.super_time = time + 1;
  1136.             }        
  1137.            
  1138.             if (self.super_time < time)
  1139.             {
  1140.                 self.super_time = time + 1;
  1141.                 stuffcmd (self, "bf\n");
  1142.             }
  1143.         }
  1144.  
  1145.         if (self.super_damage_finished < time)
  1146.         {       // just stopped
  1147.             self.items = self.items - IT_QUAD;
  1148.             if (deathmatch == 4)
  1149.             {
  1150.                 self.ammo_cells_real = 255;
  1151.                 W_UpdateAmmoCounts(self);
  1152.                 self.armorvalue = 1;
  1153.                 self.armortype = 0.8;
  1154.                 self.health = 100;
  1155.             }
  1156.             self.super_damage_finished = 0;
  1157.             self.super_time = 0;
  1158.         }
  1159.         if (self.super_damage_finished > time)
  1160.             self.effects = self.effects | ef_quad;
  1161.         else
  1162.             self.effects = self.effects - (self.effects & ef_quad);
  1163.     }      
  1164.  
  1165. // suit
  1166.     if (self.radsuit_finished)
  1167.     {
  1168.         self.air_finished = time + 12;          // don't drown
  1169.  
  1170. // sound and screen flash when items starts to run out
  1171.         if (self.radsuit_finished < time + 3)
  1172.         {
  1173.             if (self.rad_time == 1)
  1174.             {
  1175.                 sprint1 (self, PRINT_HIGH, "Air supply in Biosuit expiring\n");
  1176.                 stuffcmd (self, "bf\n");
  1177.                 sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
  1178.                 self.rad_time = time + 1;
  1179.             }
  1180.            
  1181.             if (self.rad_time < time)
  1182.             {
  1183.                 self.rad_time = time + 1;
  1184.                 stuffcmd (self, "bf\n");
  1185.             }
  1186.         }
  1187.  
  1188.         if (self.radsuit_finished < time)
  1189.         {       // just stopped
  1190.             self.items = self.items - IT_SUIT;
  1191.             self.rad_time = 0;
  1192.             self.radsuit_finished = 0;
  1193.         }
  1194.     }      
  1195.  
  1196. };
  1197.  
  1198.  
  1199. /*
  1200. ================
  1201. PlayerPostThink
  1202.  
  1203. Called every frame after physics are run
  1204. ================
  1205. */
  1206. void() PlayerPostThink =
  1207. {
  1208. //dprint ("post think\n");
  1209.     if (intermission_running)
  1210.         return;
  1211. //  if (self.view_ofs == '0 0 0')
  1212. //      return;
  1213.     if (self.deadflag)
  1214.         return;
  1215.  
  1216. // check to see if player landed and play landing sound
  1217.     if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) )
  1218.     {
  1219.         if (self.watertype == CONTENT_WATER)
  1220.             sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
  1221.         else if (self.jump_flag < -650)
  1222.         {
  1223.             T_Damage (self, world, world, 5, MOD_FALL);
  1224.             sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
  1225.         }
  1226.         else
  1227.             sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
  1228.     }
  1229.  
  1230.     self.jump_flag = self.velocity_z;
  1231.  
  1232.     CheckPowerups ();
  1233.  
  1234.     W_WeaponFrame ();
  1235.  
  1236.     // decay health
  1237.     if (self.healdecay < time)
  1238.     {
  1239.         if (self.health > self.max_health)
  1240.             self.health = self.health - 1;
  1241.         self.healdecay = time + 1;
  1242.     }
  1243.    
  1244.     // ZERG
  1245.     // regen health
  1246.     if (self.healregen < time)
  1247.     {
  1248.         if (self.health < 30)
  1249.         {
  1250.             self.health = self.health + 1;
  1251.             self.healregen = time + 0.05;
  1252.         }
  1253.         else if (self.health < self.max_health)
  1254.         {
  1255.             self.health = self.health + 1;
  1256.             self.healregen = time + 0.5;
  1257.         }
  1258.     }
  1259.  
  1260.    
  1261. };
  1262.  
  1263.  
  1264. /*
  1265. ===========
  1266. ClientConnect
  1267.  
  1268. called when a player connects to a server
  1269. ============
  1270. */
  1271. void() ClientConnect =
  1272. {
  1273.     bprint2 (PRINT_HIGH, self.netname, " entered the game\n");
  1274.    
  1275. // a client connecting during an intermission can cause problems
  1276.     if (intermission_running)
  1277.         GotoNextMap ();
  1278. };
  1279.  
  1280.  
  1281. /*
  1282. ===========
  1283. ClientDisconnect
  1284.  
  1285. called when a player disconnects from a server
  1286. ============
  1287. */
  1288. void() ClientDisconnect =
  1289. {
  1290.     // let everyone else know
  1291.     bprint4 (PRINT_HIGH, self.netname, " left the game with ", ftos(self.frags), " frags\n");
  1292.     sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
  1293.     set_suicide_frame ();
  1294. };
  1295.  
  1296. /*
  1297. ===========
  1298. ClientObituary
  1299.  
  1300. called when a player dies
  1301. ============
  1302. */
  1303. BOOL(entity targ, entity attacker) OnSameTeam;
  1304.  
  1305. void(entity targ, entity attacker, INTEGER mod) ClientObituary =
  1306. {
  1307.     if (attacker.flags & FL_CLIENT)
  1308.     {
  1309.         if (attacker == targ)
  1310.         {
  1311.             SuicideMessage(targ.netname, mod);
  1312.             targ.frags = targ.frags - 1;
  1313.             logfrag(targ, targ);
  1314.             return;
  1315.         } // else if anything else
  1316.  
  1317.         if (OnSameTeam(targ, attacker))
  1318.         {
  1319.             TeamKillMessage(targ.netname, attacker.netname, mod);
  1320.             logfrag(attacker, attacker);       
  1321.             attacker.frags = attacker.frags - 1;
  1322.             return;
  1323.         }
  1324.  
  1325.         if (targ.flags & FL_CLIENT)
  1326.         {
  1327.             KillMessage(targ.netname, attacker.netname, mod);
  1328.             attacker.frags = attacker.frags + 1;
  1329.             logfrag(attacker, targ);
  1330.         }
  1331.         return;
  1332.     } // else if attacker != player
  1333.  
  1334.     if (targ.flags & FL_CLIENT)
  1335.     {
  1336.         WorldKillMessage(targ.netname, mod);
  1337.         targ.frags = targ.frags - 1;
  1338.         logfrag(targ, targ);
  1339.     }
  1340. };
Add Comment
Please, Sign In to add comment