|
|
1.1 ! root 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 "qwsvdef.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_maxvelocity = {"sv_maxvelocity","2000"}; ! 43: ! 44: cvar_t sv_gravity = { "sv_gravity", "800"}; ! 45: cvar_t sv_stopspeed = { "sv_stopspeed", "100"}; ! 46: cvar_t sv_maxspeed = { "sv_maxspeed", "320"}; ! 47: cvar_t sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"}; ! 48: cvar_t sv_accelerate = { "sv_accelerate", "10"}; ! 49: cvar_t sv_airaccelerate = { "sv_airaccelerate", "0.7"}; ! 50: cvar_t sv_wateraccelerate = { "sv_wateraccelerate", "10"}; ! 51: cvar_t sv_friction = { "sv_friction", "4"}; ! 52: cvar_t sv_waterfriction = { "sv_waterfriction", "4"}; ! 53: ! 54: ! 55: #define MOVE_EPSILON 0.01 ! 56: ! 57: void SV_Physics_Toss (edict_t *ent); ! 58: ! 59: /* ! 60: ================ ! 61: SV_CheckAllEnts ! 62: ================ ! 63: */ ! 64: void SV_CheckAllEnts (void) ! 65: { ! 66: int e; ! 67: edict_t *check; ! 68: ! 69: // see if any solid entities are inside the final position ! 70: check = NEXT_EDICT(sv.edicts); ! 71: for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) ! 72: { ! 73: if (check->free) ! 74: continue; ! 75: if (check->v.movetype == MOVETYPE_PUSH ! 76: || check->v.movetype == MOVETYPE_NONE ! 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_GetString(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_GetString(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: do ! 131: { ! 132: thinktime = ent->v.nextthink; ! 133: if (thinktime <= 0) ! 134: return true; ! 135: if (thinktime > sv.time + host_frametime) ! 136: return true; ! 137: ! 138: if (thinktime < sv.time) ! 139: thinktime = sv.time; // don't let things stay in the past. ! 140: // it is possible to start that way ! 141: // by a trigger with a local time. ! 142: ent->v.nextthink = 0; ! 143: pr_global_struct->time = thinktime; ! 144: pr_global_struct->self = EDICT_TO_PROG(ent); ! 145: pr_global_struct->other = EDICT_TO_PROG(sv.edicts); ! 146: PR_ExecuteProgram (ent->v.think); ! 147: ! 148: if (ent->free) ! 149: return false; ! 150: } while (1); ! 151: ! 152: return true; ! 153: } ! 154: ! 155: /* ! 156: ================== ! 157: SV_Impact ! 158: ! 159: Two entities have touched, so run their touch functions ! 160: ================== ! 161: */ ! 162: void SV_Impact (edict_t *e1, edict_t *e2) ! 163: { ! 164: int old_self, old_other; ! 165: ! 166: old_self = pr_global_struct->self; ! 167: old_other = pr_global_struct->other; ! 168: ! 169: pr_global_struct->time = sv.time; ! 170: if (e1->v.touch && e1->v.solid != SOLID_NOT) ! 171: { ! 172: pr_global_struct->self = EDICT_TO_PROG(e1); ! 173: pr_global_struct->other = EDICT_TO_PROG(e2); ! 174: PR_ExecuteProgram (e1->v.touch); ! 175: } ! 176: ! 177: if (e2->v.touch && e2->v.solid != SOLID_NOT) ! 178: { ! 179: pr_global_struct->self = EDICT_TO_PROG(e2); ! 180: pr_global_struct->other = EDICT_TO_PROG(e1); ! 181: PR_ExecuteProgram (e2->v.touch); ! 182: } ! 183: ! 184: pr_global_struct->self = old_self; ! 185: pr_global_struct->other = old_other; ! 186: } ! 187: ! 188: ! 189: /* ! 190: ================== ! 191: ClipVelocity ! 192: ! 193: Slide off of the impacting object ! 194: returns the blocked flags (1 = floor, 2 = step / wall) ! 195: ================== ! 196: */ ! 197: #define STOP_EPSILON 0.1 ! 198: ! 199: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) ! 200: { ! 201: float backoff; ! 202: float change; ! 203: int i, blocked; ! 204: ! 205: blocked = 0; ! 206: if (normal[2] > 0) ! 207: blocked |= 1; // floor ! 208: if (!normal[2]) ! 209: blocked |= 2; // step ! 210: ! 211: backoff = DotProduct (in, normal) * overbounce; ! 212: ! 213: for (i=0 ; i<3 ; i++) ! 214: { ! 215: change = normal[i]*backoff; ! 216: out[i] = in[i] - change; ! 217: if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) ! 218: out[i] = 0; ! 219: } ! 220: ! 221: return blocked; ! 222: } ! 223: ! 224: ! 225: /* ! 226: ============ ! 227: SV_FlyMove ! 228: ! 229: The basic solid body movement clip that slides along multiple planes ! 230: Returns the clipflags if the velocity was modified (hit something solid) ! 231: 1 = floor ! 232: 2 = wall / step ! 233: 4 = dead stop ! 234: If steptrace is not NULL, the trace of any vertical wall hit will be stored ! 235: ============ ! 236: */ ! 237: #define MAX_CLIP_PLANES 5 ! 238: int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) ! 239: { ! 240: int bumpcount, numbumps; ! 241: vec3_t dir; ! 242: float d; ! 243: int numplanes; ! 244: vec3_t planes[MAX_CLIP_PLANES]; ! 245: vec3_t primal_velocity, original_velocity, new_velocity; ! 246: int i, j; ! 247: trace_t trace; ! 248: vec3_t end; ! 249: float time_left; ! 250: int blocked; ! 251: ! 252: numbumps = 4; ! 253: ! 254: blocked = 0; ! 255: VectorCopy (ent->v.velocity, original_velocity); ! 256: VectorCopy (ent->v.velocity, primal_velocity); ! 257: numplanes = 0; ! 258: ! 259: time_left = time; ! 260: ! 261: for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) ! 262: { ! 263: for (i=0 ; i<3 ; i++) ! 264: end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; ! 265: ! 266: trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); ! 267: ! 268: if (trace.allsolid) ! 269: { // entity is trapped in another solid ! 270: VectorCopy (vec3_origin, ent->v.velocity); ! 271: return 3; ! 272: } ! 273: ! 274: if (trace.fraction > 0) ! 275: { // actually covered some distance ! 276: VectorCopy (trace.endpos, ent->v.origin); ! 277: VectorCopy (ent->v.velocity, original_velocity); ! 278: numplanes = 0; ! 279: } ! 280: ! 281: if (trace.fraction == 1) ! 282: break; // moved the entire distance ! 283: ! 284: if (!trace.ent) ! 285: SV_Error ("SV_FlyMove: !trace.ent"); ! 286: ! 287: if (trace.plane.normal[2] > 0.7) ! 288: { ! 289: blocked |= 1; // floor ! 290: if (trace.ent->v.solid == SOLID_BSP) ! 291: { ! 292: ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ! 293: ent->v.groundentity = EDICT_TO_PROG(trace.ent); ! 294: } ! 295: } ! 296: if (!trace.plane.normal[2]) ! 297: { ! 298: blocked |= 2; // step ! 299: if (steptrace) ! 300: *steptrace = trace; // save for player extrafriction ! 301: } ! 302: ! 303: // ! 304: // run the impact function ! 305: // ! 306: SV_Impact (ent, trace.ent); ! 307: if (ent->free) ! 308: break; // removed by the impact function ! 309: ! 310: ! 311: time_left -= time_left * trace.fraction; ! 312: ! 313: // cliped to another plane ! 314: if (numplanes >= MAX_CLIP_PLANES) ! 315: { // this shouldn't really happen ! 316: VectorCopy (vec3_origin, ent->v.velocity); ! 317: return 3; ! 318: } ! 319: ! 320: VectorCopy (trace.plane.normal, planes[numplanes]); ! 321: numplanes++; ! 322: ! 323: // ! 324: // modify original_velocity so it parallels all of the clip planes ! 325: // ! 326: for (i=0 ; i<numplanes ; i++) ! 327: { ! 328: ClipVelocity (original_velocity, planes[i], new_velocity, 1); ! 329: for (j=0 ; j<numplanes ; j++) ! 330: if (j != i) ! 331: { ! 332: if (DotProduct (new_velocity, planes[j]) < 0) ! 333: break; // not ok ! 334: } ! 335: if (j == numplanes) ! 336: break; ! 337: } ! 338: ! 339: if (i != numplanes) ! 340: { // go along this plane ! 341: VectorCopy (new_velocity, ent->v.velocity); ! 342: } ! 343: else ! 344: { // go along the crease ! 345: if (numplanes != 2) ! 346: { ! 347: // Con_Printf ("clip velocity, numplanes == %i\n",numplanes); ! 348: VectorCopy (vec3_origin, ent->v.velocity); ! 349: return 7; ! 350: } ! 351: CrossProduct (planes[0], planes[1], dir); ! 352: d = DotProduct (dir, ent->v.velocity); ! 353: VectorScale (dir, d, ent->v.velocity); ! 354: } ! 355: ! 356: // ! 357: // if original velocity is against the original velocity, stop dead ! 358: // to avoid tiny occilations in sloping corners ! 359: // ! 360: if (DotProduct (ent->v.velocity, primal_velocity) <= 0) ! 361: { ! 362: VectorCopy (vec3_origin, ent->v.velocity); ! 363: return blocked; ! 364: } ! 365: } ! 366: ! 367: return blocked; ! 368: } ! 369: ! 370: ! 371: /* ! 372: ============ ! 373: SV_AddGravity ! 374: ! 375: ============ ! 376: */ ! 377: void SV_AddGravity (edict_t *ent, float scale) ! 378: { ! 379: ent->v.velocity[2] -= scale * movevars.gravity * host_frametime; ! 380: } ! 381: ! 382: /* ! 383: =============================================================================== ! 384: ! 385: PUSHMOVE ! 386: ! 387: =============================================================================== ! 388: */ ! 389: ! 390: /* ! 391: ============ ! 392: SV_PushEntity ! 393: ! 394: Does not change the entities velocity at all ! 395: ============ ! 396: */ ! 397: trace_t SV_PushEntity (edict_t *ent, vec3_t push) ! 398: { ! 399: trace_t trace; ! 400: vec3_t end; ! 401: ! 402: VectorAdd (ent->v.origin, push, end); ! 403: ! 404: if (ent->v.movetype == MOVETYPE_FLYMISSILE) ! 405: trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent); ! 406: else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT) ! 407: // only clip against bmodels ! 408: trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent); ! 409: else ! 410: trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); ! 411: ! 412: VectorCopy (trace.endpos, ent->v.origin); ! 413: SV_LinkEdict (ent, true); ! 414: ! 415: if (trace.ent) ! 416: SV_Impact (ent, trace.ent); ! 417: ! 418: return trace; ! 419: } ! 420: ! 421: ! 422: /* ! 423: ============ ! 424: SV_Push ! 425: ! 426: ============ ! 427: */ ! 428: qboolean SV_Push (edict_t *pusher, vec3_t move) ! 429: { ! 430: int i, e; ! 431: edict_t *check, *block; ! 432: vec3_t mins, maxs; ! 433: vec3_t pushorig; ! 434: int num_moved; ! 435: edict_t *moved_edict[MAX_EDICTS]; ! 436: vec3_t moved_from[MAX_EDICTS]; ! 437: ! 438: for (i=0 ; i<3 ; i++) ! 439: { ! 440: mins[i] = pusher->v.absmin[i] + move[i]; ! 441: maxs[i] = pusher->v.absmax[i] + move[i]; ! 442: } ! 443: ! 444: VectorCopy (pusher->v.origin, pushorig); ! 445: ! 446: // move the pusher to it's final position ! 447: ! 448: VectorAdd (pusher->v.origin, move, pusher->v.origin); ! 449: SV_LinkEdict (pusher, false); ! 450: ! 451: // see if any solid entities are inside the final position ! 452: num_moved = 0; ! 453: check = NEXT_EDICT(sv.edicts); ! 454: for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) ! 455: { ! 456: if (check->free) ! 457: continue; ! 458: if (check->v.movetype == MOVETYPE_PUSH ! 459: || check->v.movetype == MOVETYPE_NONE ! 460: || check->v.movetype == MOVETYPE_NOCLIP) ! 461: continue; ! 462: ! 463: pusher->v.solid = SOLID_NOT; ! 464: block = SV_TestEntityPosition (check); ! 465: pusher->v.solid = SOLID_BSP; ! 466: if (block) ! 467: continue; ! 468: ! 469: // if the entity is standing on the pusher, it will definately be moved ! 470: if ( ! ( ((int)check->v.flags & FL_ONGROUND) ! 471: && PROG_TO_EDICT(check->v.groundentity) == pusher) ) ! 472: { ! 473: if ( check->v.absmin[0] >= maxs[0] ! 474: || check->v.absmin[1] >= maxs[1] ! 475: || check->v.absmin[2] >= maxs[2] ! 476: || check->v.absmax[0] <= mins[0] ! 477: || check->v.absmax[1] <= mins[1] ! 478: || check->v.absmax[2] <= mins[2] ) ! 479: continue; ! 480: ! 481: // see if the ent's bbox is inside the pusher's final position ! 482: if (!SV_TestEntityPosition (check)) ! 483: continue; ! 484: } ! 485: ! 486: VectorCopy (check->v.origin, moved_from[num_moved]); ! 487: moved_edict[num_moved] = check; ! 488: num_moved++; ! 489: ! 490: // try moving the contacted entity ! 491: VectorAdd (check->v.origin, move, check->v.origin); ! 492: block = SV_TestEntityPosition (check); ! 493: if (!block) ! 494: { // pushed ok ! 495: SV_LinkEdict (check, false); ! 496: continue; ! 497: } ! 498: ! 499: // if it is ok to leave in the old position, do it ! 500: VectorSubtract (check->v.origin, move, check->v.origin); ! 501: block = SV_TestEntityPosition (check); ! 502: if (!block) ! 503: { ! 504: num_moved--; ! 505: continue; ! 506: } ! 507: ! 508: // if it is still inside the pusher, block ! 509: if (check->v.mins[0] == check->v.maxs[0]) ! 510: { ! 511: SV_LinkEdict (check, false); ! 512: continue; ! 513: } ! 514: if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) ! 515: { // corpse ! 516: check->v.mins[0] = check->v.mins[1] = 0; ! 517: VectorCopy (check->v.mins, check->v.maxs); ! 518: SV_LinkEdict (check, false); ! 519: continue; ! 520: } ! 521: ! 522: VectorCopy (pushorig, pusher->v.origin); ! 523: SV_LinkEdict (pusher, false); ! 524: ! 525: // if the pusher has a "blocked" function, call it ! 526: // otherwise, just stay in place until the obstacle is gone ! 527: if (pusher->v.blocked) ! 528: { ! 529: pr_global_struct->self = EDICT_TO_PROG(pusher); ! 530: pr_global_struct->other = EDICT_TO_PROG(check); ! 531: PR_ExecuteProgram (pusher->v.blocked); ! 532: } ! 533: ! 534: // move back any entities we already moved ! 535: for (i=0 ; i<num_moved ; i++) ! 536: { ! 537: VectorCopy (moved_from[i], moved_edict[i]->v.origin); ! 538: SV_LinkEdict (moved_edict[i], false); ! 539: } ! 540: return false; ! 541: } ! 542: ! 543: return true; ! 544: } ! 545: ! 546: /* ! 547: ============ ! 548: SV_PushMove ! 549: ! 550: ============ ! 551: */ ! 552: void SV_PushMove (edict_t *pusher, float movetime) ! 553: { ! 554: int i; ! 555: vec3_t move; ! 556: ! 557: if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) ! 558: { ! 559: pusher->v.ltime += movetime; ! 560: return; ! 561: } ! 562: ! 563: for (i=0 ; i<3 ; i++) ! 564: move[i] = pusher->v.velocity[i] * movetime; ! 565: ! 566: if (SV_Push (pusher, move)) ! 567: pusher->v.ltime += movetime; ! 568: } ! 569: ! 570: ! 571: /* ! 572: ================ ! 573: SV_Physics_Pusher ! 574: ! 575: ================ ! 576: */ ! 577: void SV_Physics_Pusher (edict_t *ent) ! 578: { ! 579: float thinktime; ! 580: float oldltime; ! 581: float movetime; ! 582: vec3_t oldorg, move; ! 583: float l; ! 584: ! 585: oldltime = ent->v.ltime; ! 586: ! 587: thinktime = ent->v.nextthink; ! 588: if (thinktime < ent->v.ltime + host_frametime) ! 589: { ! 590: movetime = thinktime - ent->v.ltime; ! 591: if (movetime < 0) ! 592: movetime = 0; ! 593: } ! 594: else ! 595: movetime = host_frametime; ! 596: ! 597: if (movetime) ! 598: { ! 599: SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked ! 600: } ! 601: ! 602: if (thinktime > oldltime && thinktime <= ent->v.ltime) ! 603: { ! 604: VectorCopy (ent->v.origin, oldorg); ! 605: ent->v.nextthink = 0; ! 606: pr_global_struct->time = sv.time; ! 607: pr_global_struct->self = EDICT_TO_PROG(ent); ! 608: pr_global_struct->other = EDICT_TO_PROG(sv.edicts); ! 609: PR_ExecuteProgram (ent->v.think); ! 610: if (ent->free) ! 611: return; ! 612: VectorSubtract (ent->v.origin, oldorg, move); ! 613: ! 614: l = Length(move); ! 615: if (l > 1.0/64) ! 616: { ! 617: // Con_Printf ("**** snap: %f\n", Length (l)); ! 618: VectorCopy (oldorg, ent->v.origin); ! 619: SV_Push (ent, move); ! 620: } ! 621: ! 622: } ! 623: ! 624: } ! 625: ! 626: ! 627: /* ! 628: ============= ! 629: SV_Physics_None ! 630: ! 631: Non moving objects can only think ! 632: ============= ! 633: */ ! 634: void SV_Physics_None (edict_t *ent) ! 635: { ! 636: // regular thinking ! 637: SV_RunThink (ent); ! 638: } ! 639: ! 640: /* ! 641: ============= ! 642: SV_Physics_Noclip ! 643: ! 644: A moving object that doesn't obey physics ! 645: ============= ! 646: */ ! 647: void SV_Physics_Noclip (edict_t *ent) ! 648: { ! 649: // regular thinking ! 650: if (!SV_RunThink (ent)) ! 651: return; ! 652: ! 653: VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); ! 654: VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); ! 655: ! 656: SV_LinkEdict (ent, false); ! 657: } ! 658: ! 659: /* ! 660: ============================================================================== ! 661: ! 662: TOSS / BOUNCE ! 663: ! 664: ============================================================================== ! 665: */ ! 666: ! 667: /* ! 668: ============= ! 669: SV_CheckWaterTransition ! 670: ! 671: ============= ! 672: */ ! 673: void SV_CheckWaterTransition (edict_t *ent) ! 674: { ! 675: int cont; ! 676: ! 677: cont = SV_PointContents (ent->v.origin); ! 678: if (!ent->v.watertype) ! 679: { // just spawned here ! 680: ent->v.watertype = cont; ! 681: ent->v.waterlevel = 1; ! 682: return; ! 683: } ! 684: ! 685: if (cont <= CONTENTS_WATER) ! 686: { ! 687: if (ent->v.watertype == CONTENTS_EMPTY) ! 688: { // just crossed into water ! 689: SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); ! 690: } ! 691: ent->v.watertype = cont; ! 692: ent->v.waterlevel = 1; ! 693: } ! 694: else ! 695: { ! 696: if (ent->v.watertype != CONTENTS_EMPTY) ! 697: { // just crossed into water ! 698: SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); ! 699: } ! 700: ent->v.watertype = CONTENTS_EMPTY; ! 701: ent->v.waterlevel = cont; ! 702: } ! 703: } ! 704: ! 705: /* ! 706: ============= ! 707: SV_Physics_Toss ! 708: ! 709: Toss, bounce, and fly movement. When onground, do nothing. ! 710: ============= ! 711: */ ! 712: void SV_Physics_Toss (edict_t *ent) ! 713: { ! 714: trace_t trace; ! 715: vec3_t move; ! 716: float backoff; ! 717: ! 718: // regular thinking ! 719: if (!SV_RunThink (ent)) ! 720: return; ! 721: ! 722: if (ent->v.velocity[2] > 0) ! 723: ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; ! 724: ! 725: // if onground, return without moving ! 726: if ( ((int)ent->v.flags & FL_ONGROUND) ) ! 727: return; ! 728: ! 729: SV_CheckVelocity (ent); ! 730: ! 731: // add gravity ! 732: if (ent->v.movetype != MOVETYPE_FLY ! 733: && ent->v.movetype != MOVETYPE_FLYMISSILE) ! 734: SV_AddGravity (ent, 1.0); ! 735: ! 736: // move angles ! 737: VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); ! 738: ! 739: // move origin ! 740: VectorScale (ent->v.velocity, host_frametime, move); ! 741: trace = SV_PushEntity (ent, move); ! 742: if (trace.fraction == 1) ! 743: return; ! 744: if (ent->free) ! 745: return; ! 746: ! 747: if (ent->v.movetype == MOVETYPE_BOUNCE) ! 748: backoff = 1.5; ! 749: else ! 750: backoff = 1; ! 751: ! 752: ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); ! 753: ! 754: // stop if on ground ! 755: if (trace.plane.normal[2] > 0.7) ! 756: { ! 757: if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE ) ! 758: { ! 759: ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ! 760: ent->v.groundentity = EDICT_TO_PROG(trace.ent); ! 761: VectorCopy (vec3_origin, ent->v.velocity); ! 762: VectorCopy (vec3_origin, ent->v.avelocity); ! 763: } ! 764: } ! 765: ! 766: // check for in water ! 767: SV_CheckWaterTransition (ent); ! 768: } ! 769: ! 770: /* ! 771: =============================================================================== ! 772: ! 773: STEPPING MOVEMENT ! 774: ! 775: =============================================================================== ! 776: */ ! 777: ! 778: /* ! 779: ============= ! 780: SV_Physics_Step ! 781: ! 782: Monsters freefall when they don't have a ground entity, otherwise ! 783: all movement is done with discrete steps. ! 784: ! 785: This is also used for objects that have become still on the ground, but ! 786: will fall if the floor is pulled out from under them. ! 787: FIXME: is this true? ! 788: ============= ! 789: */ ! 790: void SV_Physics_Step (edict_t *ent) ! 791: { ! 792: qboolean hitsound; ! 793: ! 794: // frefall if not onground ! 795: if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) ! 796: { ! 797: if (ent->v.velocity[2] < movevars.gravity*-0.1) ! 798: hitsound = true; ! 799: else ! 800: hitsound = false; ! 801: ! 802: SV_AddGravity (ent, 1.0); ! 803: SV_CheckVelocity (ent); ! 804: SV_FlyMove (ent, host_frametime, NULL); ! 805: SV_LinkEdict (ent, true); ! 806: ! 807: if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground ! 808: { ! 809: if (hitsound) ! 810: SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); ! 811: } ! 812: } ! 813: ! 814: // regular thinking ! 815: SV_RunThink (ent); ! 816: ! 817: SV_CheckWaterTransition (ent); ! 818: } ! 819: ! 820: //============================================================================ ! 821: ! 822: void SV_ProgStartFrame (void) ! 823: { ! 824: // let the progs know that a new frame has started ! 825: pr_global_struct->self = EDICT_TO_PROG(sv.edicts); ! 826: pr_global_struct->other = EDICT_TO_PROG(sv.edicts); ! 827: pr_global_struct->time = sv.time; ! 828: PR_ExecuteProgram (pr_global_struct->StartFrame); ! 829: } ! 830: ! 831: /* ! 832: ================ ! 833: SV_RunEntity ! 834: ! 835: ================ ! 836: */ ! 837: void SV_RunEntity (edict_t *ent) ! 838: { ! 839: if (ent->v.lastruntime == (float)realtime) ! 840: return; ! 841: ent->v.lastruntime = (float)realtime; ! 842: ! 843: switch ( (int)ent->v.movetype) ! 844: { ! 845: case MOVETYPE_PUSH: ! 846: SV_Physics_Pusher (ent); ! 847: break; ! 848: case MOVETYPE_NONE: ! 849: SV_Physics_None (ent); ! 850: break; ! 851: case MOVETYPE_NOCLIP: ! 852: SV_Physics_Noclip (ent); ! 853: break; ! 854: case MOVETYPE_STEP: ! 855: SV_Physics_Step (ent); ! 856: break; ! 857: case MOVETYPE_TOSS: ! 858: case MOVETYPE_BOUNCE: ! 859: case MOVETYPE_FLY: ! 860: case MOVETYPE_FLYMISSILE: ! 861: SV_Physics_Toss (ent); ! 862: break; ! 863: default: ! 864: SV_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); ! 865: } ! 866: } ! 867: ! 868: /* ! 869: ================ ! 870: SV_RunNewmis ! 871: ! 872: ================ ! 873: */ ! 874: void SV_RunNewmis (void) ! 875: { ! 876: edict_t *ent; ! 877: ! 878: if (!pr_global_struct->newmis) ! 879: return; ! 880: ent = PROG_TO_EDICT(pr_global_struct->newmis); ! 881: host_frametime = 0.05; ! 882: pr_global_struct->newmis = 0; ! 883: ! 884: SV_RunEntity (ent); ! 885: } ! 886: ! 887: /* ! 888: ================ ! 889: SV_Physics ! 890: ! 891: ================ ! 892: */ ! 893: void SV_Physics (void) ! 894: { ! 895: int i; ! 896: edict_t *ent; ! 897: static double old_time; ! 898: ! 899: // don't bother running a frame if sys_ticrate seconds haven't passed ! 900: host_frametime = realtime - old_time; ! 901: if (host_frametime < sv_mintic.value) ! 902: return; ! 903: if (host_frametime > sv_maxtic.value) ! 904: host_frametime = sv_maxtic.value; ! 905: old_time = realtime; ! 906: ! 907: pr_global_struct->frametime = host_frametime; ! 908: ! 909: SV_ProgStartFrame (); ! 910: ! 911: // ! 912: // treat each object in turn ! 913: // even the world gets a chance to think ! 914: // ! 915: ent = sv.edicts; ! 916: for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) ! 917: { ! 918: if (ent->free) ! 919: continue; ! 920: ! 921: if (pr_global_struct->force_retouch) ! 922: SV_LinkEdict (ent, true); // force retouch even for stationary ! 923: ! 924: if (i > 0 && i <= MAX_CLIENTS) ! 925: continue; // clients are run directly from packets ! 926: ! 927: SV_RunEntity (ent); ! 928: SV_RunNewmis (); ! 929: } ! 930: ! 931: if (pr_global_struct->force_retouch) ! 932: pr_global_struct->force_retouch--; ! 933: } ! 934: ! 935: void SV_SetMoveVars(void) ! 936: { ! 937: movevars.gravity = sv_gravity.value; ! 938: movevars.stopspeed = sv_stopspeed.value; ! 939: movevars.maxspeed = sv_maxspeed.value; ! 940: movevars.spectatormaxspeed = sv_spectatormaxspeed.value; ! 941: movevars.accelerate = sv_accelerate.value; ! 942: movevars.airaccelerate = sv_airaccelerate.value; ! 943: movevars.wateraccelerate = sv_wateraccelerate.value; ! 944: movevars.friction = sv_friction.value; ! 945: movevars.waterfriction = sv_waterfriction.value; ! 946: movevars.entgravity = 1.0; ! 947: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.