Subversion Repositories Kolibri OS

Rev

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_phys.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. /*
  25.  
  26.  
  27. pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
  28.  
  29. onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects
  30.  
  31. doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
  32. bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
  33. corpses are SOLID_NOT and MOVETYPE_TOSS
  34. crates are SOLID_BBOX and MOVETYPE_TOSS
  35. walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
  36. flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
  37.  
  38. solid_edge items only clip against bsp models.
  39.  
  40. */
  41.  
  42. cvar_t  sv_friction = {"sv_friction","4",false,true};
  43. cvar_t  sv_stopspeed = {"sv_stopspeed","100"};
  44. cvar_t  sv_gravity = {"sv_gravity","800",false,true};
  45. cvar_t  sv_maxvelocity = {"sv_maxvelocity","2000"};
  46. cvar_t  sv_nostep = {"sv_nostep","0"};
  47.  
  48. #ifdef QUAKE2
  49. static  vec3_t  vec_origin = {0.0, 0.0, 0.0};
  50. #endif
  51.  
  52. #define MOVE_EPSILON    0.01
  53.  
  54. void SV_Physics_Toss (edict_t *ent);
  55.  
  56. /*
  57. ================
  58. SV_CheckAllEnts
  59. ================
  60. */
  61. void SV_CheckAllEnts (void)
  62. {
  63.         int                     e;
  64.         edict_t         *check;
  65.  
  66. // see if any solid entities are inside the final position
  67.         check = NEXT_EDICT(sv.edicts);
  68.         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
  69.         {
  70.                 if (check->free)
  71.                         continue;
  72.                 if (check->v.movetype == MOVETYPE_PUSH
  73.                 || check->v.movetype == MOVETYPE_NONE
  74. #ifdef QUAKE2
  75.                 || check->v.movetype == MOVETYPE_FOLLOW
  76. #endif
  77.                 || check->v.movetype == MOVETYPE_NOCLIP)
  78.                         continue;
  79.  
  80.                 if (SV_TestEntityPosition (check))
  81.                         Con_Printf ("entity in invalid position\n");
  82.         }
  83. }
  84.  
  85. /*
  86. ================
  87. SV_CheckVelocity
  88. ================
  89. */
  90. void SV_CheckVelocity (edict_t *ent)
  91. {
  92.         int             i;
  93.  
  94. //
  95. // bound velocity
  96. //
  97.         for (i=0 ; i<3 ; i++)
  98.         {
  99.                 if (IS_NAN(ent->v.velocity[i]))
  100.                 {
  101.                         Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
  102.                         ent->v.velocity[i] = 0;
  103.                 }
  104.                 if (IS_NAN(ent->v.origin[i]))
  105.                 {
  106.                         Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
  107.                         ent->v.origin[i] = 0;
  108.                 }
  109.                 if (ent->v.velocity[i] > sv_maxvelocity.value)
  110.                         ent->v.velocity[i] = sv_maxvelocity.value;
  111.                 else if (ent->v.velocity[i] < -sv_maxvelocity.value)
  112.                         ent->v.velocity[i] = -sv_maxvelocity.value;
  113.         }
  114. }
  115.  
  116. /*
  117. =============
  118. SV_RunThink
  119.  
  120. Runs thinking code if time.  There is some play in the exact time the think
  121. function will be called, because it is called before any movement is done
  122. in a frame.  Not used for pushmove objects, because they must be exact.
  123. Returns false if the entity removed itself.
  124. =============
  125. */
  126. qboolean SV_RunThink (edict_t *ent)
  127. {
  128.         float   thinktime;
  129.  
  130.         thinktime = ent->v.nextthink;
  131.         if (thinktime <= 0 || thinktime > sv.time + host_frametime)
  132.                 return true;
  133.                
  134.         if (thinktime < sv.time)
  135.                 thinktime = sv.time;    // don't let things stay in the past.
  136.                                                                 // it is possible to start that way
  137.                                                                 // by a trigger with a local time.
  138.         ent->v.nextthink = 0;
  139.         pr_global_struct->time = thinktime;
  140.         pr_global_struct->self = EDICT_TO_PROG(ent);
  141.         pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
  142.         PR_ExecuteProgram (ent->v.think);
  143.         return !ent->free;
  144. }
  145.  
  146. /*
  147. ==================
  148. SV_Impact
  149.  
  150. Two entities have touched, so run their touch functions
  151. ==================
  152. */
  153. void SV_Impact (edict_t *e1, edict_t *e2)
  154. {
  155.         int             old_self, old_other;
  156.        
  157.         old_self = pr_global_struct->self;
  158.         old_other = pr_global_struct->other;
  159.        
  160.         pr_global_struct->time = sv.time;
  161.         if (e1->v.touch && e1->v.solid != SOLID_NOT)
  162.         {
  163.                 pr_global_struct->self = EDICT_TO_PROG(e1);
  164.                 pr_global_struct->other = EDICT_TO_PROG(e2);
  165.                 PR_ExecuteProgram (e1->v.touch);
  166.         }
  167.        
  168.         if (e2->v.touch && e2->v.solid != SOLID_NOT)
  169.         {
  170.                 pr_global_struct->self = EDICT_TO_PROG(e2);
  171.                 pr_global_struct->other = EDICT_TO_PROG(e1);
  172.                 PR_ExecuteProgram (e2->v.touch);
  173.         }
  174.  
  175.         pr_global_struct->self = old_self;
  176.         pr_global_struct->other = old_other;
  177. }
  178.  
  179.  
  180. /*
  181. ==================
  182. ClipVelocity
  183.  
  184. Slide off of the impacting object
  185. returns the blocked flags (1 = floor, 2 = step / wall)
  186. ==================
  187. */
  188. #define STOP_EPSILON    0.1
  189.  
  190. int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
  191. {
  192.         float   backoff;
  193.         float   change;
  194.         int             i, blocked;
  195.        
  196.         blocked = 0;
  197.         if (normal[2] > 0)
  198.                 blocked |= 1;           // floor
  199.         if (!normal[2])
  200.                 blocked |= 2;           // step
  201.        
  202.         backoff = DotProduct (in, normal) * overbounce;
  203.  
  204.         for (i=0 ; i<3 ; i++)
  205.         {
  206.                 change = normal[i]*backoff;
  207.                 out[i] = in[i] - change;
  208.                 if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
  209.                         out[i] = 0;
  210.         }
  211.        
  212.         return blocked;
  213. }
  214.  
  215.  
  216. /*
  217. ============
  218. SV_FlyMove
  219.  
  220. The basic solid body movement clip that slides along multiple planes
  221. Returns the clipflags if the velocity was modified (hit something solid)
  222. 1 = floor
  223. 2 = wall / step
  224. 4 = dead stop
  225. If steptrace is not NULL, the trace of any vertical wall hit will be stored
  226. ============
  227. */
  228. #define MAX_CLIP_PLANES 5
  229. int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
  230. {
  231.         int                     bumpcount, numbumps;
  232.         vec3_t          dir;
  233.         float           d;
  234.         int                     numplanes;
  235.         vec3_t          planes[MAX_CLIP_PLANES];
  236.         vec3_t          primal_velocity, original_velocity, new_velocity;
  237.         int                     i, j;
  238.         trace_t         trace;
  239.         vec3_t          end;
  240.         float           time_left;
  241.         int                     blocked;
  242.        
  243.         numbumps = 4;
  244.        
  245.         blocked = 0;
  246.         VectorCopy (ent->v.velocity, original_velocity);
  247.         VectorCopy (ent->v.velocity, primal_velocity);
  248.         numplanes = 0;
  249.        
  250.         time_left = time;
  251.  
  252.         for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
  253.         {
  254.                 if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
  255.                         break;
  256.  
  257.                 for (i=0 ; i<3 ; i++)
  258.                         end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
  259.  
  260.                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
  261.  
  262.                 if (trace.allsolid)
  263.                 {       // entity is trapped in another solid
  264.                         VectorCopy (vec3_origin, ent->v.velocity);
  265.                         return 3;
  266.                 }
  267.  
  268.                 if (trace.fraction > 0)
  269.                 {       // actually covered some distance
  270.                         VectorCopy (trace.endpos, ent->v.origin);
  271.                         VectorCopy (ent->v.velocity, original_velocity);
  272.                         numplanes = 0;
  273.                 }
  274.  
  275.                 if (trace.fraction == 1)
  276.                          break;         // moved the entire distance
  277.  
  278.                 if (!trace.ent)
  279.                         Sys_Error ("SV_FlyMove: !trace.ent");
  280.  
  281.                 if (trace.plane.normal[2] > 0.7)
  282.                 {
  283.                         blocked |= 1;           // floor
  284.                         if (trace.ent->v.solid == SOLID_BSP)
  285.                         {
  286.                                 ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
  287.                                 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
  288.                         }
  289.                 }
  290.                 if (!trace.plane.normal[2])
  291.                 {
  292.                         blocked |= 2;           // step
  293.                         if (steptrace)
  294.                                 *steptrace = trace;     // save for player extrafriction
  295.                 }
  296.  
  297. //
  298. // run the impact function
  299. //
  300.                 SV_Impact (ent, trace.ent);
  301.                 if (ent->free)
  302.                         break;          // removed by the impact function
  303.  
  304.                
  305.                 time_left -= time_left * trace.fraction;
  306.                
  307.         // cliped to another plane
  308.                 if (numplanes >= MAX_CLIP_PLANES)
  309.                 {       // this shouldn't really happen
  310.                         VectorCopy (vec3_origin, ent->v.velocity);
  311.                         return 3;
  312.                 }
  313.  
  314.                 VectorCopy (trace.plane.normal, planes[numplanes]);
  315.                 numplanes++;
  316.  
  317. //
  318. // modify original_velocity so it parallels all of the clip planes
  319. //
  320.                 for (i=0 ; i<numplanes ; i++)
  321.                 {
  322.                         ClipVelocity (original_velocity, planes[i], new_velocity, 1);
  323.                         for (j=0 ; j<numplanes ; j++)
  324.                                 if (j != i)
  325.                                 {
  326.                                         if (DotProduct (new_velocity, planes[j]) < 0)
  327.                                                 break;  // not ok
  328.                                 }
  329.                         if (j == numplanes)
  330.                                 break;
  331.                 }
  332.                
  333.                 if (i != numplanes)
  334.                 {       // go along this plane
  335.                         VectorCopy (new_velocity, ent->v.velocity);
  336.                 }
  337.                 else
  338.                 {       // go along the crease
  339.                         if (numplanes != 2)
  340.                         {
  341. //                              Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
  342.                                 VectorCopy (vec3_origin, ent->v.velocity);
  343.                                 return 7;
  344.                         }
  345.                         CrossProduct (planes[0], planes[1], dir);
  346.                         d = DotProduct (dir, ent->v.velocity);
  347.                         VectorScale (dir, d, ent->v.velocity);
  348.                 }
  349.  
  350. //
  351. // if original velocity is against the original velocity, stop dead
  352. // to avoid tiny occilations in sloping corners
  353. //
  354.                 if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
  355.                 {
  356.                         VectorCopy (vec3_origin, ent->v.velocity);
  357.                         return blocked;
  358.                 }
  359.         }
  360.  
  361.         return blocked;
  362. }
  363.  
  364.  
  365. /*
  366. ============
  367. SV_AddGravity
  368.  
  369. ============
  370. */
  371. void SV_AddGravity (edict_t *ent)
  372. {
  373.         float   ent_gravity;
  374.  
  375. #ifdef QUAKE2
  376.         if (ent->v.gravity)
  377.                 ent_gravity = ent->v.gravity;
  378.         else
  379.                 ent_gravity = 1.0;
  380. #else
  381.         eval_t  *val;
  382.  
  383.         val = GetEdictFieldValue(ent, "gravity");
  384.         if (val && val->_float)
  385.                 ent_gravity = val->_float;
  386.         else
  387.                 ent_gravity = 1.0;
  388. #endif
  389.         ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
  390. }
  391.  
  392.  
  393. /*
  394. ===============================================================================
  395.  
  396. PUSHMOVE
  397.  
  398. ===============================================================================
  399. */
  400.  
  401. /*
  402. ============
  403. SV_PushEntity
  404.  
  405. Does not change the entities velocity at all
  406. ============
  407. */
  408. trace_t SV_PushEntity (edict_t *ent, vec3_t push)
  409. {
  410.         trace_t trace;
  411.         vec3_t  end;
  412.                
  413.         VectorAdd (ent->v.origin, push, end);
  414.  
  415.         if (ent->v.movetype == MOVETYPE_FLYMISSILE)
  416.                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
  417.         else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
  418.         // only clip against bmodels
  419.                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
  420.         else
  421.                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);      
  422.        
  423.         VectorCopy (trace.endpos, ent->v.origin);
  424.         SV_LinkEdict (ent, true);
  425.  
  426.         if (trace.ent)
  427.                 SV_Impact (ent, trace.ent);            
  428.  
  429.         return trace;
  430. }                                      
  431.  
  432.  
  433. /*
  434. ============
  435. SV_PushMove
  436.  
  437. ============
  438. */
  439. void SV_PushMove (edict_t *pusher, float movetime)
  440. {
  441.         int                     i, e;
  442.         edict_t         *check, *block;
  443.         vec3_t          mins, maxs, move;
  444.         vec3_t          entorig, pushorig;
  445.         int                     num_moved;
  446.         edict_t         *moved_edict[MAX_EDICTS];
  447.         vec3_t          moved_from[MAX_EDICTS];
  448.  
  449.         if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
  450.         {
  451.                 pusher->v.ltime += movetime;
  452.                 return;
  453.         }
  454.  
  455.         for (i=0 ; i<3 ; i++)
  456.         {
  457.                 move[i] = pusher->v.velocity[i] * movetime;
  458.                 mins[i] = pusher->v.absmin[i] + move[i];
  459.                 maxs[i] = pusher->v.absmax[i] + move[i];
  460.         }
  461.  
  462.         VectorCopy (pusher->v.origin, pushorig);
  463.        
  464. // move the pusher to it's final position
  465.  
  466.         VectorAdd (pusher->v.origin, move, pusher->v.origin);
  467.         pusher->v.ltime += movetime;
  468.         SV_LinkEdict (pusher, false);
  469.  
  470.  
  471. // see if any solid entities are inside the final position
  472.         num_moved = 0;
  473.         check = NEXT_EDICT(sv.edicts);
  474.         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
  475.         {
  476.                 if (check->free)
  477.                         continue;
  478.                 if (check->v.movetype == MOVETYPE_PUSH
  479.                 || check->v.movetype == MOVETYPE_NONE
  480. #ifdef QUAKE2
  481.                 || check->v.movetype == MOVETYPE_FOLLOW
  482. #endif
  483.                 || check->v.movetype == MOVETYPE_NOCLIP)
  484.                         continue;
  485.  
  486.         // if the entity is standing on the pusher, it will definately be moved
  487.                 if ( ! ( ((int)check->v.flags & FL_ONGROUND)
  488.                 && PROG_TO_EDICT(check->v.groundentity) == pusher) )
  489.                 {
  490.                         if ( check->v.absmin[0] >= maxs[0]
  491.                         || check->v.absmin[1] >= maxs[1]
  492.                         || check->v.absmin[2] >= maxs[2]
  493.                         || check->v.absmax[0] <= mins[0]
  494.                         || check->v.absmax[1] <= mins[1]
  495.                         || check->v.absmax[2] <= mins[2] )
  496.                                 continue;
  497.  
  498.                 // see if the ent's bbox is inside the pusher's final position
  499.                         if (!SV_TestEntityPosition (check))
  500.                                 continue;
  501.                 }
  502.  
  503.         // remove the onground flag for non-players
  504.                 if (check->v.movetype != MOVETYPE_WALK)
  505.                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
  506.                
  507.                 VectorCopy (check->v.origin, entorig);
  508.                 VectorCopy (check->v.origin, moved_from[num_moved]);
  509.                 moved_edict[num_moved] = check;
  510.                 num_moved++;
  511.  
  512.                 // try moving the contacted entity
  513.                 pusher->v.solid = SOLID_NOT;
  514.                 SV_PushEntity (check, move);
  515.                 pusher->v.solid = SOLID_BSP;
  516.  
  517.         // if it is still inside the pusher, block
  518.                 block = SV_TestEntityPosition (check);
  519.                 if (block)
  520.                 {       // fail the move
  521.                         if (check->v.mins[0] == check->v.maxs[0])
  522.                                 continue;
  523.                         if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
  524.                         {       // corpse
  525.                                 check->v.mins[0] = check->v.mins[1] = 0;
  526.                                 VectorCopy (check->v.mins, check->v.maxs);
  527.                                 continue;
  528.                         }
  529.                        
  530.                         VectorCopy (entorig, check->v.origin);
  531.                         SV_LinkEdict (check, true);
  532.  
  533.                         VectorCopy (pushorig, pusher->v.origin);
  534.                         SV_LinkEdict (pusher, false);
  535.                         pusher->v.ltime -= movetime;
  536.  
  537.                         // if the pusher has a "blocked" function, call it
  538.                         // otherwise, just stay in place until the obstacle is gone
  539.                         if (pusher->v.blocked)
  540.                         {
  541.                                 pr_global_struct->self = EDICT_TO_PROG(pusher);
  542.                                 pr_global_struct->other = EDICT_TO_PROG(check);
  543.                                 PR_ExecuteProgram (pusher->v.blocked);
  544.                         }
  545.                        
  546.                 // move back any entities we already moved
  547.                         for (i=0 ; i<num_moved ; i++)
  548.                         {
  549.                                 VectorCopy (moved_from[i], moved_edict[i]->v.origin);
  550.                                 SV_LinkEdict (moved_edict[i], false);
  551.                         }
  552.                         return;
  553.                 }      
  554.         }
  555.  
  556.        
  557. }
  558.  
  559. #ifdef QUAKE2
  560. /*
  561. ============
  562. SV_PushRotate
  563.  
  564. ============
  565. */
  566. void SV_PushRotate (edict_t *pusher, float movetime)
  567. {
  568.         int                     i, e;
  569.         edict_t         *check, *block;
  570.         vec3_t          move, a, amove;
  571.         vec3_t          entorig, pushorig;
  572.         int                     num_moved;
  573.         edict_t         *moved_edict[MAX_EDICTS];
  574.         vec3_t          moved_from[MAX_EDICTS];
  575.         vec3_t          org, org2;
  576.         vec3_t          forward, right, up;
  577.  
  578.         if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
  579.         {
  580.                 pusher->v.ltime += movetime;
  581.                 return;
  582.         }
  583.  
  584.         for (i=0 ; i<3 ; i++)
  585.                 amove[i] = pusher->v.avelocity[i] * movetime;
  586.  
  587.         VectorSubtract (vec3_origin, amove, a);
  588.         AngleVectors (a, forward, right, up);
  589.  
  590.         VectorCopy (pusher->v.angles, pushorig);
  591.        
  592. // move the pusher to it's final position
  593.  
  594.         VectorAdd (pusher->v.angles, amove, pusher->v.angles);
  595.         pusher->v.ltime += movetime;
  596.         SV_LinkEdict (pusher, false);
  597.  
  598.  
  599. // see if any solid entities are inside the final position
  600.         num_moved = 0;
  601.         check = NEXT_EDICT(sv.edicts);
  602.         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
  603.         {
  604.                 if (check->free)
  605.                         continue;
  606.                 if (check->v.movetype == MOVETYPE_PUSH
  607.                 || check->v.movetype == MOVETYPE_NONE
  608.                 || check->v.movetype == MOVETYPE_FOLLOW
  609.                 || check->v.movetype == MOVETYPE_NOCLIP)
  610.                         continue;
  611.  
  612.         // if the entity is standing on the pusher, it will definately be moved
  613.                 if ( ! ( ((int)check->v.flags & FL_ONGROUND)
  614.                 && PROG_TO_EDICT(check->v.groundentity) == pusher) )
  615.                 {
  616.                         if ( check->v.absmin[0] >= pusher->v.absmax[0]
  617.                         || check->v.absmin[1] >= pusher->v.absmax[1]
  618.                         || check->v.absmin[2] >= pusher->v.absmax[2]
  619.                         || check->v.absmax[0] <= pusher->v.absmin[0]
  620.                         || check->v.absmax[1] <= pusher->v.absmin[1]
  621.                         || check->v.absmax[2] <= pusher->v.absmin[2] )
  622.                                 continue;
  623.  
  624.                 // see if the ent's bbox is inside the pusher's final position
  625.                         if (!SV_TestEntityPosition (check))
  626.                                 continue;
  627.                 }
  628.  
  629.         // remove the onground flag for non-players
  630.                 if (check->v.movetype != MOVETYPE_WALK)
  631.                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
  632.                
  633.                 VectorCopy (check->v.origin, entorig);
  634.                 VectorCopy (check->v.origin, moved_from[num_moved]);
  635.                 moved_edict[num_moved] = check;
  636.                 num_moved++;
  637.  
  638.                 // calculate destination position
  639.                 VectorSubtract (check->v.origin, pusher->v.origin, org);
  640.                 org2[0] = DotProduct (org, forward);
  641.                 org2[1] = -DotProduct (org, right);
  642.                 org2[2] = DotProduct (org, up);
  643.                 VectorSubtract (org2, org, move);
  644.  
  645.                 // try moving the contacted entity
  646.                 pusher->v.solid = SOLID_NOT;
  647.                 SV_PushEntity (check, move);
  648.                 pusher->v.solid = SOLID_BSP;
  649.  
  650.         // if it is still inside the pusher, block
  651.                 block = SV_TestEntityPosition (check);
  652.                 if (block)
  653.                 {       // fail the move
  654.                         if (check->v.mins[0] == check->v.maxs[0])
  655.                                 continue;
  656.                         if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
  657.                         {       // corpse
  658.                                 check->v.mins[0] = check->v.mins[1] = 0;
  659.                                 VectorCopy (check->v.mins, check->v.maxs);
  660.                                 continue;
  661.                         }
  662.                        
  663.                         VectorCopy (entorig, check->v.origin);
  664.                         SV_LinkEdict (check, true);
  665.  
  666.                         VectorCopy (pushorig, pusher->v.angles);
  667.                         SV_LinkEdict (pusher, false);
  668.                         pusher->v.ltime -= movetime;
  669.  
  670.                         // if the pusher has a "blocked" function, call it
  671.                         // otherwise, just stay in place until the obstacle is gone
  672.                         if (pusher->v.blocked)
  673.                         {
  674.                                 pr_global_struct->self = EDICT_TO_PROG(pusher);
  675.                                 pr_global_struct->other = EDICT_TO_PROG(check);
  676.                                 PR_ExecuteProgram (pusher->v.blocked);
  677.                         }
  678.                        
  679.                 // move back any entities we already moved
  680.                         for (i=0 ; i<num_moved ; i++)
  681.                         {
  682.                                 VectorCopy (moved_from[i], moved_edict[i]->v.origin);
  683.                                 VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
  684.                                 SV_LinkEdict (moved_edict[i], false);
  685.                         }
  686.                         return;
  687.                 }
  688.                 else
  689.                 {
  690.                         VectorAdd (check->v.angles, amove, check->v.angles);
  691.                 }
  692.         }
  693.  
  694.        
  695. }
  696. #endif
  697.  
  698. /*
  699. ================
  700. SV_Physics_Pusher
  701.  
  702. ================
  703. */
  704. void SV_Physics_Pusher (edict_t *ent)
  705. {
  706.         float   thinktime;
  707.         float   oldltime;
  708.         float   movetime;
  709.  
  710.         oldltime = ent->v.ltime;
  711.        
  712.         thinktime = ent->v.nextthink;
  713.         if (thinktime < ent->v.ltime + host_frametime)
  714.         {
  715.                 movetime = thinktime - ent->v.ltime;
  716.                 if (movetime < 0)
  717.                         movetime = 0;
  718.         }
  719.         else
  720.                 movetime = host_frametime;
  721.  
  722.         if (movetime)
  723.         {
  724. #ifdef QUAKE2
  725.                 if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
  726.                         SV_PushRotate (ent, movetime);
  727.                 else
  728. #endif
  729.                         SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
  730.         }
  731.                
  732.         if (thinktime > oldltime && thinktime <= ent->v.ltime)
  733.         {
  734.                 ent->v.nextthink = 0;
  735.                 pr_global_struct->time = sv.time;
  736.                 pr_global_struct->self = EDICT_TO_PROG(ent);
  737.                 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
  738.                 PR_ExecuteProgram (ent->v.think);
  739.                 if (ent->free)
  740.                         return;
  741.         }
  742.  
  743. }
  744.  
  745.  
  746. /*
  747. ===============================================================================
  748.  
  749. CLIENT MOVEMENT
  750.  
  751. ===============================================================================
  752. */
  753.  
  754. /*
  755. =============
  756. SV_CheckStuck
  757.  
  758. This is a big hack to try and fix the rare case of getting stuck in the world
  759. clipping hull.
  760. =============
  761. */
  762. void SV_CheckStuck (edict_t *ent)
  763. {
  764.         int             i, j;
  765.         int             z;
  766.         vec3_t  org;
  767.  
  768.         if (!SV_TestEntityPosition(ent))
  769.         {
  770.                 VectorCopy (ent->v.origin, ent->v.oldorigin);
  771.                 return;
  772.         }
  773.  
  774.         VectorCopy (ent->v.origin, org);
  775.         VectorCopy (ent->v.oldorigin, ent->v.origin);
  776.         if (!SV_TestEntityPosition(ent))
  777.         {
  778.                 Con_DPrintf ("Unstuck.\n");
  779.                 SV_LinkEdict (ent, true);
  780.                 return;
  781.         }
  782.        
  783.         for (z=0 ; z< 18 ; z++)
  784.                 for (i=-1 ; i <= 1 ; i++)
  785.                         for (j=-1 ; j <= 1 ; j++)
  786.                         {
  787.                                 ent->v.origin[0] = org[0] + i;
  788.                                 ent->v.origin[1] = org[1] + j;
  789.                                 ent->v.origin[2] = org[2] + z;
  790.                                 if (!SV_TestEntityPosition(ent))
  791.                                 {
  792.                                         Con_DPrintf ("Unstuck.\n");
  793.                                         SV_LinkEdict (ent, true);
  794.                                         return;
  795.                                 }
  796.                         }
  797.                        
  798.         VectorCopy (org, ent->v.origin);
  799.         Con_DPrintf ("player is stuck.\n");
  800. }
  801.  
  802.  
  803. /*
  804. =============
  805. SV_CheckWater
  806. =============
  807. */
  808. qboolean SV_CheckWater (edict_t *ent)
  809. {
  810.         vec3_t  point;
  811.         int             cont;
  812. #ifdef QUAKE2
  813.         int             truecont;
  814. #endif
  815.  
  816.         point[0] = ent->v.origin[0];
  817.         point[1] = ent->v.origin[1];
  818.         point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;      
  819.        
  820.         ent->v.waterlevel = 0;
  821.         ent->v.watertype = CONTENTS_EMPTY;
  822.         cont = SV_PointContents (point);
  823.         if (cont <= CONTENTS_WATER)
  824.         {
  825. #ifdef QUAKE2
  826.                 truecont = SV_TruePointContents (point);
  827. #endif
  828.                 ent->v.watertype = cont;
  829.                 ent->v.waterlevel = 1;
  830.                 point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
  831.                 cont = SV_PointContents (point);
  832.                 if (cont <= CONTENTS_WATER)
  833.                 {
  834.                         ent->v.waterlevel = 2;
  835.                         point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
  836.                         cont = SV_PointContents (point);
  837.                         if (cont <= CONTENTS_WATER)
  838.                                 ent->v.waterlevel = 3;
  839.                 }
  840. #ifdef QUAKE2
  841.                 if (truecont <= CONTENTS_CURRENT_0 && truecont >= CONTENTS_CURRENT_DOWN)
  842.                 {
  843.                         static vec3_t current_table[] =
  844.                         {
  845.                                 {1, 0, 0},
  846.                                 {0, 1, 0},
  847.                                 {-1, 0, 0},
  848.                                 {0, -1, 0},
  849.                                 {0, 0, 1},
  850.                                 {0, 0, -1}
  851.                         };
  852.  
  853.                         VectorMA (ent->v.basevelocity, 150.0*ent->v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->v.basevelocity);
  854.                 }
  855. #endif
  856.         }
  857.        
  858.         return ent->v.waterlevel > 1;
  859. }
  860.  
  861. /*
  862. ============
  863. SV_WallFriction
  864.  
  865. ============
  866. */
  867. void SV_WallFriction (edict_t *ent, trace_t *trace)
  868. {
  869.         vec3_t          forward, right, up;
  870.         float           d, i;
  871.         vec3_t          into, side;
  872.        
  873.         AngleVectors (ent->v.v_angle, forward, right, up);
  874.         d = DotProduct (trace->plane.normal, forward);
  875.        
  876.         d += 0.5;
  877.         if (d >= 0)
  878.                 return;
  879.                
  880. // cut the tangential velocity
  881.         i = DotProduct (trace->plane.normal, ent->v.velocity);
  882.         VectorScale (trace->plane.normal, i, into);
  883.         VectorSubtract (ent->v.velocity, into, side);
  884.        
  885.         ent->v.velocity[0] = side[0] * (1 + d);
  886.         ent->v.velocity[1] = side[1] * (1 + d);
  887. }
  888.  
  889. /*
  890. =====================
  891. SV_TryUnstick
  892.  
  893. Player has come to a dead stop, possibly due to the problem with limited
  894. float precision at some angle joins in the BSP hull.
  895.  
  896. Try fixing by pushing one pixel in each direction.
  897.  
  898. This is a hack, but in the interest of good gameplay...
  899. ======================
  900. */
  901. int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
  902. {
  903.         int             i;
  904.         vec3_t  oldorg;
  905.         vec3_t  dir;
  906.         int             clip;
  907.         trace_t steptrace;
  908.        
  909.         VectorCopy (ent->v.origin, oldorg);
  910.         VectorCopy (vec3_origin, dir);
  911.  
  912.         for (i=0 ; i<8 ; i++)
  913.         {
  914. // try pushing a little in an axial direction
  915.                 switch (i)
  916.                 {
  917.                         case 0: dir[0] = 2; dir[1] = 0; break;
  918.                         case 1: dir[0] = 0; dir[1] = 2; break;
  919.                         case 2: dir[0] = -2; dir[1] = 0; break;
  920.                         case 3: dir[0] = 0; dir[1] = -2; break;
  921.                         case 4: dir[0] = 2; dir[1] = 2; break;
  922.                         case 5: dir[0] = -2; dir[1] = 2; break;
  923.                         case 6: dir[0] = 2; dir[1] = -2; break;
  924.                         case 7: dir[0] = -2; dir[1] = -2; break;
  925.                 }
  926.                
  927.                 SV_PushEntity (ent, dir);
  928.  
  929. // retry the original move
  930.                 ent->v.velocity[0] = oldvel[0];
  931.                 ent->v. velocity[1] = oldvel[1];
  932.                 ent->v. velocity[2] = 0;
  933.                 clip = SV_FlyMove (ent, 0.1, &steptrace);
  934.  
  935.                 if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
  936.                 || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
  937.                 {
  938. //Con_DPrintf ("unstuck!\n");
  939.                         return clip;
  940.                 }
  941.                        
  942. // go back to the original pos and try again
  943.                 VectorCopy (oldorg, ent->v.origin);
  944.         }
  945.        
  946.         VectorCopy (vec3_origin, ent->v.velocity);
  947.         return 7;               // still not moving
  948. }
  949.  
  950. /*
  951. =====================
  952. SV_WalkMove
  953.  
  954. Only used by players
  955. ======================
  956. */
  957. #define STEPSIZE        18
  958. void SV_WalkMove (edict_t *ent)
  959. {
  960.         vec3_t          upmove, downmove;
  961.         vec3_t          oldorg, oldvel;
  962.         vec3_t          nosteporg, nostepvel;
  963.         int                     clip;
  964.         int                     oldonground;
  965.         trace_t         steptrace, downtrace;
  966.        
  967. //
  968. // do a regular slide move unless it looks like you ran into a step
  969. //
  970.         oldonground = (int)ent->v.flags & FL_ONGROUND;
  971.         ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
  972.        
  973.         VectorCopy (ent->v.origin, oldorg);
  974.         VectorCopy (ent->v.velocity, oldvel);
  975.        
  976.         clip = SV_FlyMove (ent, host_frametime, &steptrace);
  977.  
  978.         if ( !(clip & 2) )
  979.                 return;         // move didn't block on a step
  980.  
  981.         if (!oldonground && ent->v.waterlevel == 0)
  982.                 return;         // don't stair up while jumping
  983.        
  984.         if (ent->v.movetype != MOVETYPE_WALK)
  985.                 return;         // gibbed by a trigger
  986.        
  987.         if (sv_nostep.value)
  988.                 return;
  989.        
  990.         if ( (int)sv_player->v.flags & FL_WATERJUMP )
  991.                 return;
  992.  
  993.         VectorCopy (ent->v.origin, nosteporg);
  994.         VectorCopy (ent->v.velocity, nostepvel);
  995.  
  996. //
  997. // try moving up and forward to go up a step
  998. //
  999.         VectorCopy (oldorg, ent->v.origin);     // back to start pos
  1000.  
  1001.         VectorCopy (vec3_origin, upmove);
  1002.         VectorCopy (vec3_origin, downmove);
  1003.         upmove[2] = STEPSIZE;
  1004.         downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
  1005.  
  1006. // move up
  1007.         SV_PushEntity (ent, upmove);    // FIXME: don't link?
  1008.  
  1009. // move forward
  1010.         ent->v.velocity[0] = oldvel[0];
  1011.         ent->v. velocity[1] = oldvel[1];
  1012.         ent->v. velocity[2] = 0;
  1013.         clip = SV_FlyMove (ent, host_frametime, &steptrace);
  1014.  
  1015. // check for stuckness, possibly due to the limited precision of floats
  1016. // in the clipping hulls
  1017.         if (clip)
  1018.         {
  1019.                 if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
  1020.                 && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
  1021.                 {       // stepping up didn't make any progress
  1022.                         clip = SV_TryUnstick (ent, oldvel);
  1023.                 }
  1024.         }
  1025.        
  1026. // extra friction based on view angle
  1027.         if ( clip & 2 )
  1028.                 SV_WallFriction (ent, &steptrace);
  1029.  
  1030. // move down
  1031.         downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
  1032.  
  1033.         if (downtrace.plane.normal[2] > 0.7)
  1034.         {
  1035.                 if (ent->v.solid == SOLID_BSP)
  1036.                 {
  1037.                         ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
  1038.                         ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
  1039.                 }
  1040.         }
  1041.         else
  1042.         {
  1043. // if the push down didn't end up on good ground, use the move without
  1044. // the step up.  This happens near wall / slope combinations, and can
  1045. // cause the player to hop up higher on a slope too steep to climb     
  1046.                 VectorCopy (nosteporg, ent->v.origin);
  1047.                 VectorCopy (nostepvel, ent->v.velocity);
  1048.         }
  1049. }
  1050.  
  1051.  
  1052. /*
  1053. ================
  1054. SV_Physics_Client
  1055.  
  1056. Player character actions
  1057. ================
  1058. */
  1059. void SV_Physics_Client (edict_t *ent, int num)
  1060. {
  1061.         if ( ! svs.clients[num-1].active )
  1062.                 return;         // unconnected slot
  1063.  
  1064. //
  1065. // call standard client pre-think
  1066. //     
  1067.         pr_global_struct->time = sv.time;
  1068.         pr_global_struct->self = EDICT_TO_PROG(ent);
  1069.         PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
  1070.        
  1071. //
  1072. // do a move
  1073. //
  1074.         SV_CheckVelocity (ent);
  1075.  
  1076. //
  1077. // decide which move function to call
  1078. //
  1079.         switch ((int)ent->v.movetype)
  1080.         {
  1081.         case MOVETYPE_NONE:
  1082.                 if (!SV_RunThink (ent))
  1083.                         return;
  1084.                 break;
  1085.  
  1086.         case MOVETYPE_WALK:
  1087.                 if (!SV_RunThink (ent))
  1088.                         return;
  1089.                 if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
  1090.                         SV_AddGravity (ent);
  1091.                 SV_CheckStuck (ent);
  1092. #ifdef QUAKE2
  1093.                 VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1094. #endif
  1095.                 SV_WalkMove (ent);
  1096.  
  1097. #ifdef QUAKE2
  1098.                 VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1099. #endif
  1100.                 break;
  1101.                
  1102.         case MOVETYPE_TOSS:
  1103.         case MOVETYPE_BOUNCE:
  1104.                 SV_Physics_Toss (ent);
  1105.                 break;
  1106.  
  1107.         case MOVETYPE_FLY:
  1108.                 if (!SV_RunThink (ent))
  1109.                         return;
  1110.                 SV_FlyMove (ent, host_frametime, NULL);
  1111.                 break;
  1112.                
  1113.         case MOVETYPE_NOCLIP:
  1114.                 if (!SV_RunThink (ent))
  1115.                         return;
  1116.                 VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
  1117.                 break;
  1118.                
  1119.         default:
  1120.                 Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
  1121.         }
  1122.  
  1123. //
  1124. // call standard player post-think
  1125. //             
  1126.         SV_LinkEdict (ent, true);
  1127.  
  1128.         pr_global_struct->time = sv.time;
  1129.         pr_global_struct->self = EDICT_TO_PROG(ent);
  1130.         PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
  1131. }
  1132.  
  1133. //============================================================================
  1134.  
  1135. /*
  1136. =============
  1137. SV_Physics_None
  1138.  
  1139. Non moving objects can only think
  1140. =============
  1141. */
  1142. void SV_Physics_None (edict_t *ent)
  1143. {
  1144. // regular thinking
  1145.         SV_RunThink (ent);
  1146. }
  1147.  
  1148. #ifdef QUAKE2
  1149. /*
  1150. =============
  1151. SV_Physics_Follow
  1152.  
  1153. Entities that are "stuck" to another entity
  1154. =============
  1155. */
  1156. void SV_Physics_Follow (edict_t *ent)
  1157. {
  1158. // regular thinking
  1159.         SV_RunThink (ent);
  1160.         VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
  1161.         SV_LinkEdict (ent, true);
  1162. }
  1163. #endif
  1164.  
  1165. /*
  1166. =============
  1167. SV_Physics_Noclip
  1168.  
  1169. A moving object that doesn't obey physics
  1170. =============
  1171. */
  1172. void SV_Physics_Noclip (edict_t *ent)
  1173. {
  1174. // regular thinking
  1175.         if (!SV_RunThink (ent))
  1176.                 return;
  1177.        
  1178.         VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
  1179.         VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
  1180.  
  1181.         SV_LinkEdict (ent, false);
  1182. }
  1183.  
  1184. /*
  1185. ==============================================================================
  1186.  
  1187. TOSS / BOUNCE
  1188.  
  1189. ==============================================================================
  1190. */
  1191.  
  1192. /*
  1193. =============
  1194. SV_CheckWaterTransition
  1195.  
  1196. =============
  1197. */
  1198. void SV_CheckWaterTransition (edict_t *ent)
  1199. {
  1200.         int             cont;
  1201. #ifdef QUAKE2
  1202.         vec3_t  point;
  1203.        
  1204.         point[0] = ent->v.origin[0];
  1205.         point[1] = ent->v.origin[1];
  1206.         point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;      
  1207.         cont = SV_PointContents (point);
  1208. #else
  1209.         cont = SV_PointContents (ent->v.origin);
  1210. #endif
  1211.         if (!ent->v.watertype)
  1212.         {       // just spawned here
  1213.                 ent->v.watertype = cont;
  1214.                 ent->v.waterlevel = 1;
  1215.                 return;
  1216.         }
  1217.        
  1218.         if (cont <= CONTENTS_WATER)
  1219.         {
  1220.                 if (ent->v.watertype == CONTENTS_EMPTY)
  1221.                 {       // just crossed into water
  1222.                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
  1223.                 }              
  1224.                 ent->v.watertype = cont;
  1225.                 ent->v.waterlevel = 1;
  1226.         }
  1227.         else
  1228.         {
  1229.                 if (ent->v.watertype != CONTENTS_EMPTY)
  1230.                 {       // just crossed into water
  1231.                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
  1232.                 }              
  1233.                 ent->v.watertype = CONTENTS_EMPTY;
  1234.                 ent->v.waterlevel = cont;
  1235.         }
  1236. }
  1237.  
  1238. /*
  1239. =============
  1240. SV_Physics_Toss
  1241.  
  1242. Toss, bounce, and fly movement.  When onground, do nothing.
  1243. =============
  1244. */
  1245. void SV_Physics_Toss (edict_t *ent)
  1246. {
  1247.         trace_t trace;
  1248.         vec3_t  move;
  1249.         float   backoff;
  1250. #ifdef QUAKE2
  1251.         edict_t *groundentity;
  1252.  
  1253.         groundentity = PROG_TO_EDICT(ent->v.groundentity);
  1254.         if ((int)groundentity->v.flags & FL_CONVEYOR)
  1255.                 VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
  1256.         else
  1257.                 VectorCopy(vec_origin, ent->v.basevelocity);
  1258.         SV_CheckWater (ent);
  1259. #endif
  1260.         // regular thinking
  1261.         if (!SV_RunThink (ent))
  1262.                 return;
  1263.  
  1264. #ifdef QUAKE2
  1265.         if (ent->v.velocity[2] > 0)
  1266.                 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
  1267.  
  1268.         if ( ((int)ent->v.flags & FL_ONGROUND) )
  1269. //@@
  1270.                 if (VectorCompare(ent->v.basevelocity, vec_origin))
  1271.                         return;
  1272.  
  1273.         SV_CheckVelocity (ent);
  1274.  
  1275. // add gravity
  1276.         if (! ((int)ent->v.flags & FL_ONGROUND)
  1277.                 && ent->v.movetype != MOVETYPE_FLY
  1278.                 && ent->v.movetype != MOVETYPE_BOUNCEMISSILE
  1279.                 && ent->v.movetype != MOVETYPE_FLYMISSILE)
  1280.                         SV_AddGravity (ent);
  1281.  
  1282. #else
  1283. // if onground, return without moving
  1284.         if ( ((int)ent->v.flags & FL_ONGROUND) )
  1285.                 return;
  1286.  
  1287.         SV_CheckVelocity (ent);
  1288.  
  1289. // add gravity
  1290.         if (ent->v.movetype != MOVETYPE_FLY
  1291.         && ent->v.movetype != MOVETYPE_FLYMISSILE)
  1292.                 SV_AddGravity (ent);
  1293. #endif
  1294.  
  1295. // move angles
  1296.         VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
  1297.  
  1298. // move origin
  1299. #ifdef QUAKE2
  1300.         VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1301. #endif
  1302.         VectorScale (ent->v.velocity, host_frametime, move);
  1303.         trace = SV_PushEntity (ent, move);
  1304. #ifdef QUAKE2
  1305.         VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1306. #endif
  1307.         if (trace.fraction == 1)
  1308.                 return;
  1309.         if (ent->free)
  1310.                 return;
  1311.        
  1312.         if (ent->v.movetype == MOVETYPE_BOUNCE)
  1313.                 backoff = 1.5;
  1314. #ifdef QUAKE2
  1315.         else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
  1316.                 backoff = 2.0;
  1317. #endif
  1318.         else
  1319.                 backoff = 1;
  1320.  
  1321.         ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
  1322.  
  1323. // stop if on ground
  1324.         if (trace.plane.normal[2] > 0.7)
  1325.         {              
  1326. #ifdef QUAKE2
  1327.                 if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
  1328. #else
  1329.                 if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
  1330. #endif
  1331.                 {
  1332.                         ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
  1333.                         ent->v.groundentity = EDICT_TO_PROG(trace.ent);
  1334.                         VectorCopy (vec3_origin, ent->v.velocity);
  1335.                         VectorCopy (vec3_origin, ent->v.avelocity);
  1336.                 }
  1337.         }
  1338.        
  1339. // check for in water
  1340.         SV_CheckWaterTransition (ent);
  1341. }
  1342.  
  1343. /*
  1344. ===============================================================================
  1345.  
  1346. STEPPING MOVEMENT
  1347.  
  1348. ===============================================================================
  1349. */
  1350.  
  1351. /*
  1352. =============
  1353. SV_Physics_Step
  1354.  
  1355. Monsters freefall when they don't have a ground entity, otherwise
  1356. all movement is done with discrete steps.
  1357.  
  1358. This is also used for objects that have become still on the ground, but
  1359. will fall if the floor is pulled out from under them.
  1360. =============
  1361. */
  1362. #ifdef QUAKE2
  1363. void SV_Physics_Step (edict_t *ent)
  1364. {
  1365.         qboolean        wasonground;
  1366.         qboolean        inwater;
  1367.         qboolean        hitsound = false;
  1368.         float           *vel;
  1369.         float           speed, newspeed, control;
  1370.         float           friction;
  1371.         edict_t         *groundentity;
  1372.  
  1373.         groundentity = PROG_TO_EDICT(ent->v.groundentity);
  1374.         if ((int)groundentity->v.flags & FL_CONVEYOR)
  1375.                 VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
  1376.         else
  1377.                 VectorCopy(vec_origin, ent->v.basevelocity);
  1378. //@@
  1379.         pr_global_struct->time = sv.time;
  1380.         pr_global_struct->self = EDICT_TO_PROG(ent);
  1381.         PF_WaterMove();
  1382.  
  1383.         SV_CheckVelocity (ent);
  1384.  
  1385.         wasonground = (int)ent->v.flags & FL_ONGROUND;
  1386. //      ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
  1387.  
  1388.         // add gravity except:
  1389.         //   flying monsters
  1390.         //   swimming monsters who are in the water
  1391.         inwater = SV_CheckWater(ent);
  1392.         if (! wasonground)
  1393.                 if (!((int)ent->v.flags & FL_FLY))
  1394.                         if (!(((int)ent->v.flags & FL_SWIM) && (ent->v.waterlevel > 0)))
  1395.                         {
  1396.                                 if (ent->v.velocity[2] < sv_gravity.value*-0.1)
  1397.                                         hitsound = true;
  1398.                                 if (!inwater)
  1399.                                         SV_AddGravity (ent);
  1400.                         }
  1401.  
  1402.         if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin))
  1403.         {
  1404.                 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
  1405.                 // apply friction
  1406.                 // let dead monsters who aren't completely onground slide
  1407.                 if (wasonground)
  1408.                         if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent)))
  1409.                         {
  1410.                                 vel = ent->v.velocity;
  1411.                                 speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
  1412.                                 if (speed)
  1413.                                 {
  1414.                                         friction = sv_friction.value;
  1415.  
  1416.                                         control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
  1417.                                         newspeed = speed - host_frametime*control*friction;
  1418.  
  1419.                                         if (newspeed < 0)
  1420.                                                 newspeed = 0;
  1421.                                         newspeed /= speed;
  1422.  
  1423.                                         vel[0] = vel[0] * newspeed;
  1424.                                         vel[1] = vel[1] * newspeed;
  1425.                                 }
  1426.                         }
  1427.  
  1428.                 VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1429.                 SV_FlyMove (ent, host_frametime, NULL);
  1430.                 VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
  1431.  
  1432.                 // determine if it's on solid ground at all
  1433.                 {
  1434.                         vec3_t  mins, maxs, point;
  1435.                         int             x, y;
  1436.                
  1437.                         VectorAdd (ent->v.origin, ent->v.mins, mins);
  1438.                         VectorAdd (ent->v.origin, ent->v.maxs, maxs);
  1439.  
  1440.                         point[2] = mins[2] - 1;
  1441.                         for     (x=0 ; x<=1 ; x++)
  1442.                                 for     (y=0 ; y<=1 ; y++)
  1443.                                 {
  1444.                                         point[0] = x ? maxs[0] : mins[0];
  1445.                                         point[1] = y ? maxs[1] : mins[1];
  1446.                                         if (SV_PointContents (point) == CONTENTS_SOLID)
  1447.                                         {
  1448.                                                 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
  1449.                                                 break;
  1450.                                         }
  1451.                                 }
  1452.  
  1453.                 }
  1454.  
  1455.                 SV_LinkEdict (ent, true);
  1456.  
  1457.                 if ((int)ent->v.flags & FL_ONGROUND)
  1458.                         if (!wasonground)
  1459.                                 if (hitsound)
  1460.                                         SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
  1461.         }
  1462.  
  1463. // regular thinking
  1464.         SV_RunThink (ent);
  1465.         SV_CheckWaterTransition (ent);
  1466. }
  1467. #else
  1468. void SV_Physics_Step (edict_t *ent)
  1469. {
  1470.         qboolean        hitsound;
  1471.  
  1472. // freefall if not onground
  1473.         if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
  1474.         {
  1475.                 if (ent->v.velocity[2] < sv_gravity.value*-0.1)
  1476.                         hitsound = true;
  1477.                 else
  1478.                         hitsound = false;
  1479.  
  1480.                 SV_AddGravity (ent);
  1481.                 SV_CheckVelocity (ent);
  1482.                 SV_FlyMove (ent, host_frametime, NULL);
  1483.                 SV_LinkEdict (ent, true);
  1484.  
  1485.                 if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
  1486.                 {
  1487.                         if (hitsound)
  1488.                                 SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
  1489.                 }
  1490.         }
  1491.  
  1492. // regular thinking
  1493.         SV_RunThink (ent);
  1494.        
  1495.         SV_CheckWaterTransition (ent);
  1496. }
  1497. #endif
  1498.  
  1499. //============================================================================
  1500.  
  1501. /*
  1502. ================
  1503. SV_Physics
  1504.  
  1505. ================
  1506. */
  1507. void SV_Physics (void)
  1508. {
  1509.         int             i;
  1510.         edict_t *ent;
  1511.  
  1512. // let the progs know that a new frame has started
  1513.         pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
  1514.         pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
  1515.         pr_global_struct->time = sv.time;
  1516.         PR_ExecuteProgram (pr_global_struct->StartFrame);
  1517.  
  1518. //SV_CheckAllEnts ();
  1519.  
  1520. //
  1521. // treat each object in turn
  1522. //
  1523.         ent = sv.edicts;
  1524.         for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
  1525.         {
  1526.                 if (ent->free)
  1527.                         continue;
  1528.  
  1529.                 if (pr_global_struct->force_retouch)
  1530.                 {
  1531.                         SV_LinkEdict (ent, true);       // force retouch even for stationary
  1532.                 }
  1533.  
  1534.                 if (i > 0 && i <= svs.maxclients)
  1535.                         SV_Physics_Client (ent, i);
  1536.                 else if (ent->v.movetype == MOVETYPE_PUSH)
  1537.                         SV_Physics_Pusher (ent);
  1538.                 else if (ent->v.movetype == MOVETYPE_NONE)
  1539.                         SV_Physics_None (ent);
  1540. #ifdef QUAKE2
  1541.                 else if (ent->v.movetype == MOVETYPE_FOLLOW)
  1542.                         SV_Physics_Follow (ent);
  1543. #endif
  1544.                 else if (ent->v.movetype == MOVETYPE_NOCLIP)
  1545.                         SV_Physics_Noclip (ent);
  1546.                 else if (ent->v.movetype == MOVETYPE_STEP)
  1547.                         SV_Physics_Step (ent);
  1548.                 else if (ent->v.movetype == MOVETYPE_TOSS
  1549.                 || ent->v.movetype == MOVETYPE_BOUNCE
  1550. #ifdef QUAKE2
  1551.                 || ent->v.movetype == MOVETYPE_BOUNCEMISSILE
  1552. #endif
  1553.                 || ent->v.movetype == MOVETYPE_FLY
  1554.                 || ent->v.movetype == MOVETYPE_FLYMISSILE)
  1555.                         SV_Physics_Toss (ent);
  1556.                 else
  1557.                         Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                       
  1558.         }
  1559.        
  1560.         if (pr_global_struct->force_retouch)
  1561.                 pr_global_struct->force_retouch--;     
  1562.  
  1563.         sv.time += host_frametime;
  1564. }
  1565.  
  1566.  
  1567. #ifdef QUAKE2
  1568. trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
  1569. {
  1570.         edict_t tempent, *tent;
  1571.         trace_t trace;
  1572.         vec3_t  move;
  1573.         vec3_t  end;
  1574.         double  save_frametime;
  1575. //      extern particle_t       *active_particles, *free_particles;
  1576. //      particle_t      *p;
  1577.  
  1578.  
  1579.         save_frametime = host_frametime;
  1580.         host_frametime = 0.05;
  1581.  
  1582.         memcpy(&tempent, ent, sizeof(edict_t));
  1583.         tent = &tempent;
  1584.  
  1585.         while (1)
  1586.         {
  1587.                 SV_CheckVelocity (tent);
  1588.                 SV_AddGravity (tent);
  1589.                 VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
  1590.                 VectorScale (tent->v.velocity, host_frametime, move);
  1591.                 VectorAdd (tent->v.origin, move, end);
  1592.                 trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);  
  1593.                 VectorCopy (trace.endpos, tent->v.origin);
  1594.  
  1595. //              p = free_particles;
  1596. //              if (p)
  1597. //              {
  1598. //                      free_particles = p->next;
  1599. //                      p->next = active_particles;
  1600. //                      active_particles = p;
  1601. //             
  1602. //                      p->die = 256;
  1603. //                      p->color = 15;
  1604. //                      p->type = pt_static;
  1605. //                      VectorCopy (vec3_origin, p->vel);
  1606. //                      VectorCopy (tent->v.origin, p->org);
  1607. //              }
  1608.  
  1609.                 if (trace.ent)
  1610.                         if (trace.ent != ignore)
  1611.                                 break;
  1612.         }
  1613. //      p->color = 224;
  1614.         host_frametime = save_frametime;
  1615.         return trace;
  1616. }
  1617. #endif
  1618.