Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // sv_user.c -- server code for moving users
  21.  
  22. #include "quakedef.h"
  23.  
  24. edict_t *sv_player;
  25.  
  26. extern  cvar_t  sv_friction;
  27. cvar_t  sv_edgefriction = {"edgefriction", "2"};
  28. extern  cvar_t  sv_stopspeed;
  29.  
  30. static  vec3_t          forward, right, up;
  31.  
  32. vec3_t  wishdir;
  33. float   wishspeed;
  34.  
  35. // world
  36. float   *angles;
  37. float   *origin;
  38. float   *velocity;
  39.  
  40. qboolean        onground;
  41.  
  42. usercmd_t       cmd;
  43.  
  44. cvar_t  sv_idealpitchscale = {"sv_idealpitchscale","0.8"};
  45.  
  46.  
  47. /*
  48. ===============
  49. SV_SetIdealPitch
  50. ===============
  51. */
  52. #define MAX_FORWARD     6
  53. void SV_SetIdealPitch (void)
  54. {
  55.         float   angleval, sinval, cosval;
  56.         trace_t tr;
  57.         vec3_t  top, bottom;
  58.         float   z[MAX_FORWARD];
  59.         int             i, j;
  60.         int             step, dir, steps;
  61.  
  62.         if (!((int)sv_player->v.flags & FL_ONGROUND))
  63.                 return;
  64.                
  65.         angleval = sv_player->v.angles[YAW] * M_PI*2 / 360;
  66.         sinval = sin(angleval);
  67.         cosval = cos(angleval);
  68.  
  69.         for (i=0 ; i<MAX_FORWARD ; i++)
  70.         {
  71.                 top[0] = sv_player->v.origin[0] + cosval*(i+3)*12;
  72.                 top[1] = sv_player->v.origin[1] + sinval*(i+3)*12;
  73.                 top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2];
  74.                
  75.                 bottom[0] = top[0];
  76.                 bottom[1] = top[1];
  77.                 bottom[2] = top[2] - 160;
  78.                
  79.                 tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player);
  80.                 if (tr.allsolid)
  81.                         return; // looking at a wall, leave ideal the way is was
  82.  
  83.                 if (tr.fraction == 1)
  84.                         return; // near a dropoff
  85.                
  86.                 z[i] = top[2] + tr.fraction*(bottom[2]-top[2]);
  87.         }
  88.        
  89.         dir = 0;
  90.         steps = 0;
  91.         for (j=1 ; j<i ; j++)
  92.         {
  93.                 step = z[j] - z[j-1];
  94.                 if (step > -ON_EPSILON && step < ON_EPSILON)
  95.                         continue;
  96.  
  97.                 if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
  98.                         return;         // mixed changes
  99.  
  100.                 steps++;       
  101.                 dir = step;
  102.         }
  103.        
  104.         if (!dir)
  105.         {
  106.                 sv_player->v.idealpitch = 0;
  107.                 return;
  108.         }
  109.        
  110.         if (steps < 2)
  111.                 return;
  112.         sv_player->v.idealpitch = -dir * sv_idealpitchscale.value;
  113. }
  114.  
  115.  
  116. /*
  117. ==================
  118. SV_UserFriction
  119.  
  120. ==================
  121. */
  122. void SV_UserFriction (void)
  123. {
  124.         float   *vel;
  125.         float   speed, newspeed, control;
  126.         vec3_t  start, stop;
  127.         float   friction;
  128.         trace_t trace;
  129.        
  130.         vel = velocity;
  131.        
  132.         speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
  133.         if (!speed)
  134.                 return;
  135.  
  136. // if the leading edge is over a dropoff, increase friction
  137.         start[0] = stop[0] = origin[0] + vel[0]/speed*16;
  138.         start[1] = stop[1] = origin[1] + vel[1]/speed*16;
  139.         start[2] = origin[2] + sv_player->v.mins[2];
  140.         stop[2] = start[2] - 34;
  141.  
  142.         trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player);
  143.  
  144.         if (trace.fraction == 1.0)
  145.                 friction = sv_friction.value*sv_edgefriction.value;
  146.         else
  147.                 friction = sv_friction.value;
  148.  
  149. // apply friction      
  150.         control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
  151.         newspeed = speed - host_frametime*control*friction;
  152.        
  153.         if (newspeed < 0)
  154.                 newspeed = 0;
  155.         newspeed /= speed;
  156.  
  157.         vel[0] = vel[0] * newspeed;
  158.         vel[1] = vel[1] * newspeed;
  159.         vel[2] = vel[2] * newspeed;
  160. }
  161.  
  162. /*
  163. ==============
  164. SV_Accelerate
  165. ==============
  166. */
  167. cvar_t  sv_maxspeed = {"sv_maxspeed", "320", false, true};
  168. cvar_t  sv_accelerate = {"sv_accelerate", "10"};
  169. #if 0
  170. void SV_Accelerate (vec3_t wishvel)
  171. {
  172.         int                     i;
  173.         float           addspeed, accelspeed;
  174.         vec3_t          pushvec;
  175.  
  176.         if (wishspeed == 0)
  177.                 return;
  178.  
  179.         VectorSubtract (wishvel, velocity, pushvec);
  180.         addspeed = VectorNormalize (pushvec);
  181.  
  182.         accelspeed = sv_accelerate.value*host_frametime*addspeed;
  183.         if (accelspeed > addspeed)
  184.                 accelspeed = addspeed;
  185.        
  186.         for (i=0 ; i<3 ; i++)
  187.                 velocity[i] += accelspeed*pushvec[i];  
  188. }
  189. #endif
  190. void SV_Accelerate (void)
  191. {
  192.         int                     i;
  193.         float           addspeed, accelspeed, currentspeed;
  194.  
  195.         currentspeed = DotProduct (velocity, wishdir);
  196.         addspeed = wishspeed - currentspeed;
  197.         if (addspeed <= 0)
  198.                 return;
  199.         accelspeed = sv_accelerate.value*host_frametime*wishspeed;
  200.         if (accelspeed > addspeed)
  201.                 accelspeed = addspeed;
  202.        
  203.         for (i=0 ; i<3 ; i++)
  204.                 velocity[i] += accelspeed*wishdir[i];  
  205. }
  206.  
  207. void SV_AirAccelerate (vec3_t wishveloc)
  208. {
  209.         int                     i;
  210.         float           addspeed, wishspd, accelspeed, currentspeed;
  211.                
  212.         wishspd = VectorNormalize (wishveloc);
  213.         if (wishspd > 30)
  214.                 wishspd = 30;
  215.         currentspeed = DotProduct (velocity, wishveloc);
  216.         addspeed = wishspd - currentspeed;
  217.         if (addspeed <= 0)
  218.                 return;
  219. //      accelspeed = sv_accelerate.value * host_frametime;
  220.         accelspeed = sv_accelerate.value*wishspeed * host_frametime;
  221.         if (accelspeed > addspeed)
  222.                 accelspeed = addspeed;
  223.        
  224.         for (i=0 ; i<3 ; i++)
  225.                 velocity[i] += accelspeed*wishveloc[i];
  226. }
  227.  
  228.  
  229. void DropPunchAngle (void)
  230. {
  231.         float   len;
  232.        
  233.         len = VectorNormalize (sv_player->v.punchangle);
  234.        
  235.         len -= 10*host_frametime;
  236.         if (len < 0)
  237.                 len = 0;
  238.         VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle);
  239. }
  240.  
  241. /*
  242. ===================
  243. SV_WaterMove
  244.  
  245. ===================
  246. */
  247. void SV_WaterMove (void)
  248. {
  249.         int             i;
  250.         vec3_t  wishvel;
  251.         float   speed, newspeed, wishspeed, addspeed, accelspeed;
  252.  
  253. //
  254. // user intentions
  255. //
  256.         AngleVectors (sv_player->v.v_angle, forward, right, up);
  257.  
  258.         for (i=0 ; i<3 ; i++)
  259.                 wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove;
  260.  
  261.         if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove)
  262.                 wishvel[2] -= 60;               // drift towards bottom
  263.         else
  264.                 wishvel[2] += cmd.upmove;
  265.  
  266.         wishspeed = Length(wishvel);
  267.         if (wishspeed > sv_maxspeed.value)
  268.         {
  269.                 VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
  270.                 wishspeed = sv_maxspeed.value;
  271.         }
  272.         wishspeed *= 0.7;
  273.  
  274. //
  275. // water friction
  276. //
  277.         speed = Length (velocity);
  278.         if (speed)
  279.         {
  280.                 newspeed = speed - host_frametime * speed * sv_friction.value;
  281.                 if (newspeed < 0)
  282.                         newspeed = 0;  
  283.                 VectorScale (velocity, newspeed/speed, velocity);
  284.         }
  285.         else
  286.                 newspeed = 0;
  287.        
  288. //
  289. // water acceleration
  290. //
  291.         if (!wishspeed)
  292.                 return;
  293.  
  294.         addspeed = wishspeed - newspeed;
  295.         if (addspeed <= 0)
  296.                 return;
  297.  
  298.         VectorNormalize (wishvel);
  299.         accelspeed = sv_accelerate.value * wishspeed * host_frametime;
  300.         if (accelspeed > addspeed)
  301.                 accelspeed = addspeed;
  302.  
  303.         for (i=0 ; i<3 ; i++)
  304.                 velocity[i] += accelspeed * wishvel[i];
  305. }
  306.  
  307. void SV_WaterJump (void)
  308. {
  309.         if (sv.time > sv_player->v.teleport_time
  310.         || !sv_player->v.waterlevel)
  311.         {
  312.                 sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP;
  313.                 sv_player->v.teleport_time = 0;
  314.         }
  315.         sv_player->v.velocity[0] = sv_player->v.movedir[0];
  316.         sv_player->v.velocity[1] = sv_player->v.movedir[1];
  317. }
  318.  
  319.  
  320. /*
  321. ===================
  322. SV_AirMove
  323.  
  324. ===================
  325. */
  326. void SV_AirMove (void)
  327. {
  328.         int                     i;
  329.         vec3_t          wishvel;
  330.         float           fmove, smove;
  331.  
  332.         AngleVectors (sv_player->v.angles, forward, right, up);
  333.  
  334.         fmove = cmd.forwardmove;
  335.         smove = cmd.sidemove;
  336.        
  337. // hack to not let you back into teleporter
  338.         if (sv.time < sv_player->v.teleport_time && fmove < 0)
  339.                 fmove = 0;
  340.                
  341.         for (i=0 ; i<3 ; i++)
  342.                 wishvel[i] = forward[i]*fmove + right[i]*smove;
  343.  
  344.         if ( (int)sv_player->v.movetype != MOVETYPE_WALK)
  345.                 wishvel[2] = cmd.upmove;
  346.         else
  347.                 wishvel[2] = 0;
  348.  
  349.         VectorCopy (wishvel, wishdir);
  350.         wishspeed = VectorNormalize(wishdir);
  351.         if (wishspeed > sv_maxspeed.value)
  352.         {
  353.                 VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
  354.                 wishspeed = sv_maxspeed.value;
  355.         }
  356.        
  357.         if ( sv_player->v.movetype == MOVETYPE_NOCLIP)
  358.         {       // noclip
  359.                 VectorCopy (wishvel, velocity);
  360.         }
  361.         else if ( onground )
  362.         {
  363.                 SV_UserFriction ();
  364.                 SV_Accelerate ();
  365.         }
  366.         else
  367.         {       // not on ground, so little effect on velocity
  368.                 SV_AirAccelerate (wishvel);
  369.         }              
  370. }
  371.  
  372. /*
  373. ===================
  374. SV_ClientThink
  375.  
  376. the move fields specify an intended velocity in pix/sec
  377. the angle fields specify an exact angular motion in degrees
  378. ===================
  379. */
  380. void SV_ClientThink (void)
  381. {
  382.         vec3_t          v_angle;
  383.  
  384.         if (sv_player->v.movetype == MOVETYPE_NONE)
  385.                 return;
  386.        
  387.         onground = (int)sv_player->v.flags & FL_ONGROUND;
  388.  
  389.         origin = sv_player->v.origin;
  390.         velocity = sv_player->v.velocity;
  391.  
  392.         DropPunchAngle ();
  393.        
  394. //
  395. // if dead, behave differently
  396. //
  397.         if (sv_player->v.health <= 0)
  398.                 return;
  399.  
  400. //
  401. // angles
  402. // show 1/3 the pitch angle and all the roll angle
  403.         cmd = host_client->cmd;
  404.         angles = sv_player->v.angles;
  405.        
  406.         VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle);
  407.         angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
  408.         if (!sv_player->v.fixangle)
  409.         {
  410.                 angles[PITCH] = -v_angle[PITCH]/3;
  411.                 angles[YAW] = v_angle[YAW];
  412.         }
  413.  
  414.         if ( (int)sv_player->v.flags & FL_WATERJUMP )
  415.         {
  416.                 SV_WaterJump ();
  417.                 return;
  418.         }
  419. //
  420. // walk
  421. //
  422.         if ( (sv_player->v.waterlevel >= 2)
  423.         && (sv_player->v.movetype != MOVETYPE_NOCLIP) )
  424.         {
  425.                 SV_WaterMove ();
  426.                 return;
  427.         }
  428.  
  429.         SV_AirMove (); 
  430. }
  431.  
  432.  
  433. /*
  434. ===================
  435. SV_ReadClientMove
  436. ===================
  437. */
  438. void SV_ReadClientMove (usercmd_t *move)
  439. {
  440.         int             i;
  441.         vec3_t  angle;
  442.         int             bits;
  443.        
  444. // read ping time
  445.         host_client->ping_times[host_client->num_pings%NUM_PING_TIMES]
  446.                 = sv.time - MSG_ReadFloat ();
  447.         host_client->num_pings++;
  448.  
  449. // read current angles 
  450.         for (i=0 ; i<3 ; i++)
  451.                 angle[i] = MSG_ReadAngle ();
  452.  
  453.         VectorCopy (angle, host_client->edict->v.v_angle);
  454.                
  455. // read movement
  456.         move->forwardmove = MSG_ReadShort ();
  457.         move->sidemove = MSG_ReadShort ();
  458.         move->upmove = MSG_ReadShort ();
  459.        
  460. // read buttons
  461.         bits = MSG_ReadByte ();
  462.         host_client->edict->v.button0 = bits & 1;
  463.         host_client->edict->v.button2 = (bits & 2)>>1;
  464.  
  465.         i = MSG_ReadByte ();
  466.         if (i)
  467.                 host_client->edict->v.impulse = i;
  468.  
  469. #ifdef QUAKE2
  470. // read light level
  471.         host_client->edict->v.light_level = MSG_ReadByte ();
  472. #endif
  473. }
  474.  
  475. /*
  476. ===================
  477. SV_ReadClientMessage
  478.  
  479. Returns false if the client should be killed
  480. ===================
  481. */
  482. qboolean SV_ReadClientMessage (void)
  483. {
  484.         int             ret;
  485.         int             cmd;
  486.         char            *s;
  487.        
  488.         do
  489.         {
  490. nextmsg:
  491.                 ret = NET_GetMessage (host_client->netconnection);
  492.                 if (ret == -1)
  493.                 {
  494.                         Sys_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n");
  495.                         return false;
  496.                 }
  497.                 if (!ret)
  498.                         return true;
  499.                                        
  500.                 MSG_BeginReading ();
  501.                
  502.                 while (1)
  503.                 {
  504.                         if (!host_client->active)
  505.                                 return false;   // a command caused an error
  506.  
  507.                         if (msg_badread)
  508.                         {
  509.                                 Sys_Printf ("SV_ReadClientMessage: badread\n");
  510.                                 return false;
  511.                         }      
  512.        
  513.                         cmd = MSG_ReadChar ();
  514.                        
  515.                         switch (cmd)
  516.                         {
  517.                         case -1:
  518.                                 goto nextmsg;           // end of message
  519.                                
  520.                         default:
  521.                                 Sys_Printf ("SV_ReadClientMessage: unknown command char\n");
  522.                                 return false;
  523.                                                        
  524.                         case clc_nop:
  525. //                              Sys_Printf ("clc_nop\n");
  526.                                 break;
  527.                                
  528.                         case clc_stringcmd:    
  529.                                 s = MSG_ReadString ();
  530.                                 if (host_client->privileged)
  531.                                         ret = 2;
  532.                                 else
  533.                                         ret = 0;
  534.                                 if (Q_strncasecmp(s, "status", 6) == 0)
  535.                                         ret = 1;
  536.                                 else if (Q_strncasecmp(s, "god", 3) == 0)
  537.                                         ret = 1;
  538.                                 else if (Q_strncasecmp(s, "notarget", 8) == 0)
  539.                                         ret = 1;
  540.                                 else if (Q_strncasecmp(s, "fly", 3) == 0)
  541.                                         ret = 1;
  542.                                 else if (Q_strncasecmp(s, "name", 4) == 0)
  543.                                         ret = 1;
  544.                                 else if (Q_strncasecmp(s, "noclip", 6) == 0)
  545.                                         ret = 1;
  546.                                 else if (Q_strncasecmp(s, "say", 3) == 0)
  547.                                         ret = 1;
  548.                                 else if (Q_strncasecmp(s, "say_team", 8) == 0)
  549.                                         ret = 1;
  550.                                 else if (Q_strncasecmp(s, "tell", 4) == 0)
  551.                                         ret = 1;
  552.                                 else if (Q_strncasecmp(s, "color", 5) == 0)
  553.                                         ret = 1;
  554.                                 else if (Q_strncasecmp(s, "kill", 4) == 0)
  555.                                         ret = 1;
  556.                                 else if (Q_strncasecmp(s, "pause", 5) == 0)
  557.                                         ret = 1;
  558.                                 else if (Q_strncasecmp(s, "spawn", 5) == 0)
  559.                                         ret = 1;
  560.                                 else if (Q_strncasecmp(s, "begin", 5) == 0)
  561.                                         ret = 1;
  562.                                 else if (Q_strncasecmp(s, "prespawn", 8) == 0)
  563.                                         ret = 1;
  564.                                 else if (Q_strncasecmp(s, "kick", 4) == 0)
  565.                                         ret = 1;
  566.                                 else if (Q_strncasecmp(s, "ping", 4) == 0)
  567.                                         ret = 1;
  568.                                 else if (Q_strncasecmp(s, "give", 4) == 0)
  569.                                         ret = 1;
  570.                                 else if (Q_strncasecmp(s, "ban", 3) == 0)
  571.                                         ret = 1;
  572.                                 if (ret == 2)
  573.                                         Cbuf_InsertText (s);
  574.                                 else if (ret == 1)
  575.                                         Cmd_ExecuteString (s, src_client);
  576.                                 else
  577.                                         Con_DPrintf("%s tried to %s\n", host_client->name, s);
  578.                                 break;
  579.                                
  580.                         case clc_disconnect:
  581. //                              Sys_Printf ("SV_ReadClientMessage: client disconnected\n");
  582.                                 return false;
  583.                        
  584.                         case clc_move:
  585.                                 SV_ReadClientMove (&host_client->cmd);
  586.                                 break;
  587.                         }
  588.                 }
  589.         } while (ret == 1);
  590.        
  591.         return true;
  592. }
  593.  
  594.  
  595. /*
  596. ==================
  597. SV_RunClients
  598. ==================
  599. */
  600. void SV_RunClients (void)
  601. {
  602.         int                             i;
  603.        
  604.         for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  605.         {
  606.                 if (!host_client->active)
  607.                         continue;
  608.        
  609.                 sv_player = host_client->edict;
  610.  
  611.                 if (!SV_ReadClientMessage ())
  612.                 {
  613.                         SV_DropClient (false);  // client misbehaved...
  614.                         continue;
  615.                 }
  616.  
  617.                 if (!host_client->spawned)
  618.                 {
  619.                 // clear client movement until a new packet is received
  620.                         memset (&host_client->cmd, 0, sizeof(host_client->cmd));
  621.                         continue;
  622.                 }
  623.  
  624. // always pause in single player if in console or menus
  625.                 if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
  626.                         SV_ClientThink ();
  627.         }
  628. }
  629.  
  630.