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 = CVAR4("sv_friction","4",false,true); 43 cvar_t sv_stopspeed = CVAR2("sv_stopspeed","100"); 44 cvar_t sv_gravity = CVAR4("sv_gravity","800",false,true); 45 cvar_t sv_maxvelocity = CVAR2("sv_maxvelocity","2000"); 46 cvar_t sv_nostep = CVAR2("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->u.v.movetype == MOVETYPE_PUSH 73 || check->u.v.movetype == MOVETYPE_NONE 74 #ifdef QUAKE2 75 || check->u.v.movetype == MOVETYPE_FOLLOW 76 #endif 77 || check->u.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->u.v.velocity[i])) 100 { 101 Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->u.v.classname); 102 ent->u.v.velocity[i] = 0; 103 } 104 if (IS_NAN(ent->u.v.origin[i])) 105 { 106 Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->u.v.classname); 107 ent->u.v.origin[i] = 0; 108 } 109 if (ent->u.v.velocity[i] > sv_maxvelocity.value) 110 ent->u.v.velocity[i] = sv_maxvelocity.value; 111 else if (ent->u.v.velocity[i] < -sv_maxvelocity.value) 112 ent->u.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->u.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->u.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->u.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->u.v.touch && e1->u.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->u.v.touch); 166 } 167 168 if (e2->u.v.touch && e2->u.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->u.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->u.v.velocity, original_velocity); 247 VectorCopy (ent->u.v.velocity, primal_velocity); 248 numplanes = 0; 249 250 time_left = time; 251 252 for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) 253 { 254 if (!ent->u.v.velocity[0] && !ent->u.v.velocity[1] && !ent->u.v.velocity[2]) 255 break; 256 257 for (i=0 ; i<3 ; i++) 258 end[i] = ent->u.v.origin[i] + time_left * ent->u.v.velocity[i]; 259 260 trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, false, ent); 261 262 if (trace.allsolid) 263 { // entity is trapped in another solid 264 VectorCopy (vec3_origin, ent->u.v.velocity); 265 return 3; 266 } 267 268 if (trace.fraction > 0) 269 { // actually covered some distance 270 VectorCopy (trace.endpos, ent->u.v.origin); 271 VectorCopy (ent->u.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->u.v.solid == SOLID_BSP) 285 { 286 ent->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND; 287 ent->u.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->u.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->u.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->u.v.velocity); 343 return 7; 344 } 345 CrossProduct (planes[0], planes[1], dir); 346 d = DotProduct (dir, ent->u.v.velocity); 347 VectorScale (dir, d, ent->u.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->u.v.velocity, primal_velocity) <= 0) 355 { 356 VectorCopy (vec3_origin, ent->u.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->u.v.gravity) 377 ent_gravity = ent->u.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->u.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->u.v.origin, push, end); 414 415 if (ent->u.v.movetype == MOVETYPE_FLYMISSILE) 416 trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_MISSILE, ent); 417 else if (ent->u.v.solid == SOLID_TRIGGER || ent->u.v.solid == SOLID_NOT) 418 // only clip against bmodels 419 trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_NOMONSTERS, ent); 420 else 421 trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_NORMAL, ent); 422 423 VectorCopy (trace.endpos, ent->u.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->u.v.velocity[0] && !pusher->u.v.velocity[1] && !pusher->u.v.velocity[2]) 450 { 451 pusher->u.v.ltime += movetime; 452 return; 453 } 454 455 for (i=0 ; i<3 ; i++) 456 { 457 move[i] = pusher->u.v.velocity[i] * movetime; 458 mins[i] = pusher->u.v.absmin[i] + move[i]; 459 maxs[i] = pusher->u.v.absmax[i] + move[i]; 460 } 461 462 VectorCopy (pusher->u.v.origin, pushorig); 463 464 // move the pusher to it's final position 465 466 VectorAdd (pusher->u.v.origin, move, pusher->u.v.origin); 467 pusher->u.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->u.v.movetype == MOVETYPE_PUSH 479 || check->u.v.movetype == MOVETYPE_NONE 480 #ifdef QUAKE2 481 || check->u.v.movetype == MOVETYPE_FOLLOW 482 #endif 483 || check->u.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->u.v.flags & FL_ONGROUND) 488 && PROG_TO_EDICT(check->u.v.groundentity) == pusher) ) 489 { 490 if ( check->u.v.absmin[0] >= maxs[0] 491 || check->u.v.absmin[1] >= maxs[1] 492 || check->u.v.absmin[2] >= maxs[2] 493 || check->u.v.absmax[0] <= mins[0] 494 || check->u.v.absmax[1] <= mins[1] 495 || check->u.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->u.v.movetype != MOVETYPE_WALK) 505 check->u.v.flags = (int)check->u.v.flags & ~FL_ONGROUND; 506 507 VectorCopy (check->u.v.origin, entorig); 508 VectorCopy (check->u.v.origin, moved_from[num_moved]); 509 moved_edict[num_moved] = check; 510 num_moved++; 511 512 // try moving the contacted entity 513 pusher->u.v.solid = SOLID_NOT; 514 SV_PushEntity (check, move); 515 pusher->u.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->u.v.mins[0] == check->u.v.maxs[0]) 522 continue; 523 if (check->u.v.solid == SOLID_NOT || check->u.v.solid == SOLID_TRIGGER) 524 { // corpse 525 check->u.v.mins[0] = check->u.v.mins[1] = 0; 526 VectorCopy (check->u.v.mins, check->u.v.maxs); 527 continue; 528 } 529 530 VectorCopy (entorig, check->u.v.origin); 531 SV_LinkEdict (check, true); 532 533 VectorCopy (pushorig, pusher->u.v.origin); 534 SV_LinkEdict (pusher, false); 535 pusher->u.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->u.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->u.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]->u.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->u.v.avelocity[0] && !pusher->u.v.avelocity[1] && !pusher->u.v.avelocity[2]) 579 { 580 pusher->u.v.ltime += movetime; 581 return; 582 } 583 584 for (i=0 ; i<3 ; i++) 585 amove[i] = pusher->u.v.avelocity[i] * movetime; 586 587 VectorSubtract (vec3_origin, amove, a); 588 AngleVectors (a, forward, right, up); 589 590 VectorCopy (pusher->u.v.angles, pushorig); 591 592 // move the pusher to it's final position 593 594 VectorAdd (pusher->u.v.angles, amove, pusher->u.v.angles); 595 pusher->u.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->u.v.movetype == MOVETYPE_PUSH 607 || check->u.v.movetype == MOVETYPE_NONE 608 || check->u.v.movetype == MOVETYPE_FOLLOW 609 || check->u.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->u.v.flags & FL_ONGROUND) 614 && PROG_TO_EDICT(check->u.v.groundentity) == pusher) ) 615 { 616 if ( check->u.v.absmin[0] >= pusher->u.v.absmax[0] 617 || check->u.v.absmin[1] >= pusher->u.v.absmax[1] 618 || check->u.v.absmin[2] >= pusher->u.v.absmax[2] 619 || check->u.v.absmax[0] <= pusher->u.v.absmin[0] 620 || check->u.v.absmax[1] <= pusher->u.v.absmin[1] 621 || check->u.v.absmax[2] <= pusher->u.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->u.v.movetype != MOVETYPE_WALK) 631 check->u.v.flags = (int)check->u.v.flags & ~FL_ONGROUND; 632 633 VectorCopy (check->u.v.origin, entorig); 634 VectorCopy (check->u.v.origin, moved_from[num_moved]); 635 moved_edict[num_moved] = check; 636 num_moved++; 637 638 // calculate destination position 639 VectorSubtract (check->u.v.origin, pusher->u.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->u.v.solid = SOLID_NOT; 647 SV_PushEntity (check, move); 648 pusher->u.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->u.v.mins[0] == check->u.v.maxs[0]) 655 continue; 656 if (check->u.v.solid == SOLID_NOT || check->u.v.solid == SOLID_TRIGGER) 657 { // corpse 658 check->u.v.mins[0] = check->u.v.mins[1] = 0; 659 VectorCopy (check->u.v.mins, check->u.v.maxs); 660 continue; 661 } 662 663 VectorCopy (entorig, check->u.v.origin); 664 SV_LinkEdict (check, true); 665 666 VectorCopy (pushorig, pusher->u.v.angles); 667 SV_LinkEdict (pusher, false); 668 pusher->u.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->u.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->u.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]->u.v.origin); 683 VectorSubtract (moved_edict[i]->u.v.angles, amove, moved_edict[i]->u.v.angles); 684 SV_LinkEdict (moved_edict[i], false); 685 } 686 return; 687 } 688 else 689 { 690 VectorAdd (check->u.v.angles, amove, check->u.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->u.v.ltime; 711 712 thinktime = ent->u.v.nextthink; 713 if (thinktime < ent->u.v.ltime + host_frametime) 714 { 715 movetime = thinktime - ent->u.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->u.v.avelocity[0] || ent->u.v.avelocity[1] || ent->u.v.avelocity[2]) 726 SV_PushRotate (ent, movetime); 727 else 728 #endif 729 SV_PushMove (ent, movetime); // advances ent->u.v.ltime if not blocked 730 } 731 732 if (thinktime > oldltime && thinktime <= ent->u.v.ltime) 733 { 734 ent->u.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->u.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->u.v.origin, ent->u.v.oldorigin); 771 return; 772 } 773 774 VectorCopy (ent->u.v.origin, org); 775 VectorCopy (ent->u.v.oldorigin, ent->u.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->u.v.origin[0] = org[0] + i; 788 ent->u.v.origin[1] = org[1] + j; 789 ent->u.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->u.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->u.v.origin[0]; 817 point[1] = ent->u.v.origin[1]; 818 point[2] = ent->u.v.origin[2] + ent->u.v.mins[2] + 1; 819 820 ent->u.v.waterlevel = 0; 821 ent->u.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->u.v.watertype = cont; 829 ent->u.v.waterlevel = 1; 830 point[2] = ent->u.v.origin[2] + (ent->u.v.mins[2] + ent->u.v.maxs[2])*0.5; 831 cont = SV_PointContents (point); 832 if (cont <= CONTENTS_WATER) 833 { 834 ent->u.v.waterlevel = 2; 835 point[2] = ent->u.v.origin[2] + ent->u.v.view_ofs[2]; 836 cont = SV_PointContents (point); 837 if (cont <= CONTENTS_WATER) 838 ent->u.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->u.v.basevelocity, 150.0*ent->u.v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->u.v.basevelocity); 854 } 855 #endif 856 } 857 858 return ent->u.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->u.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->u.v.velocity); 882 VectorScale (trace->plane.normal, i, into); 883 VectorSubtract (ent->u.v.velocity, into, side); 884 885 ent->u.v.velocity[0] = side[0] * (1 + d); 886 ent->u.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->u.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->u.v.velocity[0] = oldvel[0]; 931 ent->u.v. velocity[1] = oldvel[1]; 932 ent->u.v. velocity[2] = 0; 933 clip = SV_FlyMove (ent, 0.1, &steptrace); 934 935 if ( fabs(oldorg[1] - ent->u.v.origin[1]) > 4 936 || fabs(oldorg[0] - ent->u.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->u.v.origin); 944 } 945 946 VectorCopy (vec3_origin, ent->u.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->u.v.flags & FL_ONGROUND; 971 ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND; 972 973 VectorCopy (ent->u.v.origin, oldorg); 974 VectorCopy (ent->u.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->u.v.waterlevel == 0) 982 return; // don't stair up while jumping 983 984 if (ent->u.v.movetype != MOVETYPE_WALK) 985 return; // gibbed by a trigger 986 987 if (sv_nostep.value) 988 return; 989 990 if ( (int)sv_player->u.v.flags & FL_WATERJUMP ) 991 return; 992 993 VectorCopy (ent->u.v.origin, nosteporg); 994 VectorCopy (ent->u.v.velocity, nostepvel); 995 996 // 997 // try moving up and forward to go up a step 998 // 999 VectorCopy (oldorg, ent->u.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->u.v.velocity[0] = oldvel[0]; 1011 ent->u.v. velocity[1] = oldvel[1]; 1012 ent->u.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->u.v.origin[1]) < 0.03125 1020 && fabs(oldorg[0] - ent->u.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->u.v.solid == SOLID_BSP) 1036 { 1037 ent->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND; 1038 ent->u.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->u.v.origin); 1047 VectorCopy (nostepvel, ent->u.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->u.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->u.v.flags & FL_WATERJUMP) ) 1090 SV_AddGravity (ent); 1091 SV_CheckStuck (ent); 1092 #ifdef QUAKE2 1093 VectorAdd (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity); 1094 #endif 1095 SV_WalkMove (ent); 1096 1097 #ifdef QUAKE2 1098 VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.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->u.v.origin, host_frametime, ent->u.v.velocity, ent->u.v.origin); 1117 break; 1118 1119 default: 1120 Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->u.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->u.v.aiment)->u.v.origin, ent->u.v.v_angle, ent->u.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->u.v.angles, host_frametime, ent->u.v.avelocity, ent->u.v.angles); 1179 VectorMA (ent->u.v.origin, host_frametime, ent->u.v.velocity, ent->u.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->u.v.origin[0]; 1205 point[1] = ent->u.v.origin[1]; 1206 point[2] = ent->u.v.origin[2] + ent->u.v.mins[2] + 1; 1207 cont = SV_PointContents (point); 1208 #else 1209 cont = SV_PointContents (ent->u.v.origin); 1210 #endif 1211 if (!ent->u.v.watertype) 1212 { // just spawned here 1213 ent->u.v.watertype = cont; 1214 ent->u.v.waterlevel = 1; 1215 return; 1216 } 1217 1218 if (cont <= CONTENTS_WATER) 1219 { 1220 if (ent->u.v.watertype == CONTENTS_EMPTY) 1221 { // just crossed into water 1222 SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); 1223 } 1224 ent->u.v.watertype = cont; 1225 ent->u.v.waterlevel = 1; 1226 } 1227 else 1228 { 1229 if (ent->u.v.watertype != CONTENTS_EMPTY) 1230 { // just crossed into water 1231 SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); 1232 } 1233 ent->u.v.watertype = CONTENTS_EMPTY; 1234 ent->u.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->u.v.groundentity); 1254 if ((int)groundentity->u.v.flags & FL_CONVEYOR) 1255 VectorScale(groundentity->u.v.movedir, groundentity->u.v.speed, ent->u.v.basevelocity); 1256 else 1257 VectorCopy(vec_origin, ent->u.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->u.v.velocity[2] > 0) 1266 ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND; 1267 1268 if ( ((int)ent->u.v.flags & FL_ONGROUND) ) 1269 //@@ 1270 if (VectorCompare(ent->u.v.basevelocity, vec_origin)) 1271 return; 1272 1273 SV_CheckVelocity (ent); 1274 1275 // add gravity 1276 if (! ((int)ent->u.v.flags & FL_ONGROUND) 1277 && ent->u.v.movetype != MOVETYPE_FLY 1278 && ent->u.v.movetype != MOVETYPE_BOUNCEMISSILE 1279 && ent->u.v.movetype != MOVETYPE_FLYMISSILE) 1280 SV_AddGravity (ent); 1281 1282 #else 1283 // if onground, return without moving 1284 if ( ((int)ent->u.v.flags & FL_ONGROUND) ) 1285 return; 1286 1287 SV_CheckVelocity (ent); 1288 1289 // add gravity 1290 if (ent->u.v.movetype != MOVETYPE_FLY 1291 && ent->u.v.movetype != MOVETYPE_FLYMISSILE) 1292 SV_AddGravity (ent); 1293 #endif 1294 1295 // move angles 1296 VectorMA (ent->u.v.angles, host_frametime, ent->u.v.avelocity, ent->u.v.angles); 1297 1298 // move origin 1299 #ifdef QUAKE2 1300 VectorAdd (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity); 1301 #endif 1302 VectorScale (ent->u.v.velocity, host_frametime, move); 1303 trace = SV_PushEntity (ent, move); 1304 #ifdef QUAKE2 1305 VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity); 1306 #endif 1307 if (trace.fraction == 1) 1308 return; 1309 if (ent->free) 1310 return; 1311 1312 if (ent->u.v.movetype == MOVETYPE_BOUNCE) 1313 backoff = 1.5; 1314 #ifdef QUAKE2 1315 else if (ent->u.v.movetype == MOVETYPE_BOUNCEMISSILE) 1316 backoff = 2.0; 1317 #endif 1318 else 1319 backoff = 1; 1320 1321 ClipVelocity (ent->u.v.velocity, trace.plane.normal, ent->u.v.velocity, backoff); 1322 1323 // stop if on ground 1324 if (trace.plane.normal[2] > 0.7) 1325 { 1326 #ifdef QUAKE2 1327 if (ent->u.v.velocity[2] < 60 || (ent->u.v.movetype != MOVETYPE_BOUNCE && ent->u.v.movetype != MOVETYPE_BOUNCEMISSILE)) 1328 #else 1329 if (ent->u.v.velocity[2] < 60 || ent->u.v.movetype != MOVETYPE_BOUNCE) 1330 #endif 1331 { 1332 ent->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND; 1333 ent->u.v.groundentity = EDICT_TO_PROG(trace.ent); 1334 VectorCopy (vec3_origin, ent->u.v.velocity); 1335 VectorCopy (vec3_origin, ent->u.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->u.v.groundentity); 1374 if ((int)groundentity->u.v.flags & FL_CONVEYOR) 1375 VectorScale(groundentity->u.v.movedir, groundentity->u.v.speed, ent->u.v.basevelocity); 1376 else 1377 VectorCopy(vec_origin, ent->u.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->u.v.flags & FL_ONGROUND; 1386 // ent->u.v.flags = (int)ent->u.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->u.v.flags & FL_FLY)) 1394 if (!(((int)ent->u.v.flags & FL_SWIM) && (ent->u.v.waterlevel > 0))) 1395 { 1396 if (ent->u.v.velocity[2] < sv_gravity.value*-0.1) 1397 hitsound = true; 1398 if (!inwater) 1399 SV_AddGravity (ent); 1400 } 1401 1402 if (!VectorCompare(ent->u.v.velocity, vec_origin) || !VectorCompare(ent->u.v.basevelocity, vec_origin)) 1403 { 1404 ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND; 1405 // apply friction 1406 // let dead monsters who aren't completely onground slide 1407 if (wasonground) 1408 if (!(ent->u.v.health <= 0.0 && !SV_CheckBottom(ent))) 1409 { 1410 vel = ent->u.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->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity); 1429 SV_FlyMove (ent, host_frametime, NULL); 1430 VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.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->u.v.origin, ent->u.v.mins, mins); 1438 VectorAdd (ent->u.v.origin, ent->u.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->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND; 1449 break; 1450 } 1451 } 1452 1453 } 1454 1455 SV_LinkEdict (ent, true); 1456 1457 if ((int)ent->u.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->u.v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) 1474 { 1475 if (ent->u.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->u.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->u.v.movetype == MOVETYPE_PUSH) 1537 SV_Physics_Pusher (ent); 1538 else if (ent->u.v.movetype == MOVETYPE_NONE) 1539 SV_Physics_None (ent); 1540 #ifdef QUAKE2 1541 else if (ent->u.v.movetype == MOVETYPE_FOLLOW) 1542 SV_Physics_Follow (ent); 1543 #endif 1544 else if (ent->u.v.movetype == MOVETYPE_NOCLIP) 1545 SV_Physics_Noclip (ent); 1546 else if (ent->u.v.movetype == MOVETYPE_STEP) 1547 SV_Physics_Step (ent); 1548 else if (ent->u.v.movetype == MOVETYPE_TOSS 1549 || ent->u.v.movetype == MOVETYPE_BOUNCE 1550 #ifdef QUAKE2 1551 || ent->u.v.movetype == MOVETYPE_BOUNCEMISSILE 1552 #endif 1553 || ent->u.v.movetype == MOVETYPE_FLY 1554 || ent->u.v.movetype == MOVETYPE_FLYMISSILE) 1555 SV_Physics_Toss (ent); 1556 else 1557 Sys_Error ("SV_Physics: bad movetype %i", (int)ent->u.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->u.v.angles, host_frametime, tent->u.v.avelocity, tent->u.v.angles); 1590 VectorScale (tent->u.v.velocity, host_frametime, move); 1591 VectorAdd (tent->u.v.origin, move, end); 1592 trace = SV_Move (tent->u.v.origin, tent->u.v.mins, tent->u.v.maxs, end, MOVE_NORMAL, tent); 1593 VectorCopy (trace.endpos, tent->u.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->u.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