|
|
1.1.1.3 ! root 1: /* ! 2: Copyright (C) 1997-2001 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: */ 1.1 root 20: // g_phys.c 21: 22: #include "g_local.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: 43: /* 44: ============ 45: SV_TestEntityPosition 46: 47: ============ 48: */ 49: edict_t *SV_TestEntityPosition (edict_t *ent) 50: { 51: trace_t trace; 52: int mask; 53: 54: if (ent->clipmask) 55: mask = ent->clipmask; 56: else 57: mask = MASK_SOLID; 58: trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask); 59: 60: if (trace.startsolid) 61: return g_edicts; 62: 63: return NULL; 64: } 65: 66: 67: /* 68: ================ 69: SV_CheckVelocity 70: ================ 71: */ 72: void SV_CheckVelocity (edict_t *ent) 73: { 74: int i; 75: 76: // 77: // bound velocity 78: // 79: for (i=0 ; i<3 ; i++) 80: { 81: if (ent->velocity[i] > sv_maxvelocity->value) 82: ent->velocity[i] = sv_maxvelocity->value; 83: else if (ent->velocity[i] < -sv_maxvelocity->value) 84: ent->velocity[i] = -sv_maxvelocity->value; 85: } 86: } 87: 88: /* 89: ============= 90: SV_RunThink 91: 92: Runs thinking code for this frame if necessary 93: ============= 94: */ 95: qboolean SV_RunThink (edict_t *ent) 96: { 97: float thinktime; 98: 99: thinktime = ent->nextthink; 100: if (thinktime <= 0) 101: return true; 102: if (thinktime > level.time+0.001) 103: return true; 104: 105: ent->nextthink = 0; 106: if (!ent->think) 107: gi.error ("NULL ent->think"); 108: ent->think (ent); 109: 110: return false; 111: } 112: 113: /* 114: ================== 115: SV_Impact 116: 117: Two entities have touched, so run their touch functions 118: ================== 119: */ 120: void SV_Impact (edict_t *e1, trace_t *trace) 121: { 122: edict_t *e2; 123: // cplane_t backplane; 124: 125: e2 = trace->ent; 126: 127: if (e1->touch && e1->solid != SOLID_NOT) 128: e1->touch (e1, e2, &trace->plane, trace->surface); 129: 130: if (e2->touch && e2->solid != SOLID_NOT) 131: e2->touch (e2, e1, NULL, NULL); 132: } 133: 134: 135: /* 136: ================== 137: ClipVelocity 138: 139: Slide off of the impacting object 140: returns the blocked flags (1 = floor, 2 = step / wall) 141: ================== 142: */ 143: #define STOP_EPSILON 0.1 144: 145: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) 146: { 147: float backoff; 148: float change; 149: int i, blocked; 150: 151: blocked = 0; 152: if (normal[2] > 0) 153: blocked |= 1; // floor 154: if (!normal[2]) 155: blocked |= 2; // step 156: 157: backoff = DotProduct (in, normal) * overbounce; 158: 159: for (i=0 ; i<3 ; i++) 160: { 161: change = normal[i]*backoff; 162: out[i] = in[i] - change; 163: if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) 164: out[i] = 0; 165: } 1.1.1.2 root 166: 1.1 root 167: return blocked; 168: } 169: 170: 171: /* 172: ============ 173: SV_FlyMove 174: 175: The basic solid body movement clip that slides along multiple planes 176: Returns the clipflags if the velocity was modified (hit something solid) 177: 1 = floor 178: 2 = wall / step 179: 4 = dead stop 180: ============ 181: */ 182: #define MAX_CLIP_PLANES 5 183: int SV_FlyMove (edict_t *ent, float time, int mask) 184: { 185: edict_t *hit; 186: int bumpcount, numbumps; 187: vec3_t dir; 188: float d; 189: int numplanes; 190: vec3_t planes[MAX_CLIP_PLANES]; 191: vec3_t primal_velocity, original_velocity, new_velocity; 192: int i, j; 193: trace_t trace; 194: vec3_t end; 195: float time_left; 196: int blocked; 197: 198: numbumps = 4; 199: 200: blocked = 0; 201: VectorCopy (ent->velocity, original_velocity); 202: VectorCopy (ent->velocity, primal_velocity); 203: numplanes = 0; 204: 205: time_left = time; 206: 207: ent->groundentity = NULL; 208: for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) 209: { 210: for (i=0 ; i<3 ; i++) 211: end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; 212: 213: trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); 214: 215: if (trace.allsolid) 216: { // entity is trapped in another solid 217: VectorCopy (vec3_origin, ent->velocity); 218: return 3; 219: } 220: 221: if (trace.fraction > 0) 222: { // actually covered some distance 223: VectorCopy (trace.endpos, ent->s.origin); 224: VectorCopy (ent->velocity, original_velocity); 225: numplanes = 0; 226: } 227: 228: if (trace.fraction == 1) 229: break; // moved the entire distance 230: 231: hit = trace.ent; 232: 233: if (trace.plane.normal[2] > 0.7) 234: { 235: blocked |= 1; // floor 236: if ( hit->solid == SOLID_BSP) 237: { 238: ent->groundentity = hit; 239: ent->groundentity_linkcount = hit->linkcount; 240: } 241: } 242: if (!trace.plane.normal[2]) 243: { 244: blocked |= 2; // step 245: } 246: 247: // 248: // run the impact function 249: // 250: SV_Impact (ent, &trace); 251: if (!ent->inuse) 252: break; // removed by the impact function 253: 254: 255: time_left -= time_left * trace.fraction; 256: 257: // cliped to another plane 258: if (numplanes >= MAX_CLIP_PLANES) 259: { // this shouldn't really happen 260: VectorCopy (vec3_origin, ent->velocity); 261: return 3; 262: } 263: 264: VectorCopy (trace.plane.normal, planes[numplanes]); 265: numplanes++; 266: 267: // 268: // modify original_velocity so it parallels all of the clip planes 269: // 270: for (i=0 ; i<numplanes ; i++) 271: { 272: ClipVelocity (original_velocity, planes[i], new_velocity, 1); 1.1.1.2 root 273: 1.1 root 274: for (j=0 ; j<numplanes ; j++) 1.1.1.2 root 275: if ((j != i) && !VectorCompare (planes[i], planes[j])) 1.1 root 276: { 277: if (DotProduct (new_velocity, planes[j]) < 0) 278: break; // not ok 279: } 280: if (j == numplanes) 281: break; 282: } 283: 284: if (i != numplanes) 285: { // go along this plane 286: VectorCopy (new_velocity, ent->velocity); 287: } 288: else 289: { // go along the crease 290: if (numplanes != 2) 291: { 292: // gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); 293: VectorCopy (vec3_origin, ent->velocity); 294: return 7; 295: } 296: CrossProduct (planes[0], planes[1], dir); 297: d = DotProduct (dir, ent->velocity); 298: VectorScale (dir, d, ent->velocity); 299: } 300: 301: // 302: // if original velocity is against the original velocity, stop dead 303: // to avoid tiny occilations in sloping corners 304: // 305: if (DotProduct (ent->velocity, primal_velocity) <= 0) 306: { 307: VectorCopy (vec3_origin, ent->velocity); 308: return blocked; 309: } 310: } 311: 312: return blocked; 313: } 314: 315: 316: /* 317: ============ 318: SV_AddGravity 319: 320: ============ 321: */ 322: void SV_AddGravity (edict_t *ent) 323: { 324: ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME; 325: } 326: 327: /* 328: =============================================================================== 329: 330: PUSHMOVE 331: 332: =============================================================================== 333: */ 334: 335: /* 336: ============ 337: SV_PushEntity 338: 339: Does not change the entities velocity at all 340: ============ 341: */ 342: trace_t SV_PushEntity (edict_t *ent, vec3_t push) 343: { 344: trace_t trace; 345: vec3_t start; 346: vec3_t end; 347: int mask; 348: 349: VectorCopy (ent->s.origin, start); 350: VectorAdd (start, push, end); 351: 352: retry: 353: if (ent->clipmask) 354: mask = ent->clipmask; 355: else 356: mask = MASK_SOLID; 357: 358: trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask); 359: 360: VectorCopy (trace.endpos, ent->s.origin); 361: gi.linkentity (ent); 362: 363: if (trace.fraction != 1.0) 364: { 365: SV_Impact (ent, &trace); 366: 367: // if the pushed entity went away and the pusher is still there 368: if (!trace.ent->inuse && ent->inuse) 369: { 370: // move the pusher back and try again 371: VectorCopy (start, ent->s.origin); 372: gi.linkentity (ent); 373: goto retry; 374: } 375: } 376: 377: if (ent->inuse) 378: G_TouchTriggers (ent); 379: 380: return trace; 381: } 382: 383: 384: typedef struct 385: { 386: edict_t *ent; 387: vec3_t origin; 388: vec3_t angles; 389: float deltayaw; 390: } pushed_t; 391: pushed_t pushed[MAX_EDICTS], *pushed_p; 392: 393: edict_t *obstacle; 394: 395: /* 396: ============ 397: SV_Push 398: 399: Objects need to be moved back on a failed push, 400: otherwise riders would continue to slide. 401: ============ 402: */ 403: qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) 404: { 405: int i, e; 406: edict_t *check, *block; 407: vec3_t mins, maxs; 408: pushed_t *p; 409: vec3_t org, org2, move2, forward, right, up; 410: 411: // clamp the move to 1/8 units, so the position will 412: // be accurate for client side prediction 413: for (i=0 ; i<3 ; i++) 414: { 415: float temp; 416: temp = move[i]*8.0; 417: if (temp > 0.0) 418: temp += 0.5; 419: else 420: temp -= 0.5; 421: move[i] = 0.125 * (int)temp; 422: } 423: 424: // find the bounding box 425: for (i=0 ; i<3 ; i++) 426: { 427: mins[i] = pusher->absmin[i] + move[i]; 428: maxs[i] = pusher->absmax[i] + move[i]; 429: } 430: 431: // we need this for pushing things later 432: VectorSubtract (vec3_origin, amove, org); 433: AngleVectors (org, forward, right, up); 434: 435: // save the pusher's original position 436: pushed_p->ent = pusher; 437: VectorCopy (pusher->s.origin, pushed_p->origin); 438: VectorCopy (pusher->s.angles, pushed_p->angles); 439: if (pusher->client) 440: pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW]; 441: pushed_p++; 442: 443: // move the pusher to it's final position 444: VectorAdd (pusher->s.origin, move, pusher->s.origin); 445: VectorAdd (pusher->s.angles, amove, pusher->s.angles); 446: gi.linkentity (pusher); 447: 448: // see if any solid entities are inside the final position 449: check = g_edicts+1; 450: for (e = 1; e < globals.num_edicts; e++, check++) 451: { 452: if (!check->inuse) 453: continue; 454: if (check->movetype == MOVETYPE_PUSH 455: || check->movetype == MOVETYPE_STOP 456: || check->movetype == MOVETYPE_NONE 457: || check->movetype == MOVETYPE_NOCLIP) 458: continue; 459: 460: if (!check->area.prev) 461: continue; // not linked in anywhere 462: 463: // if the entity is standing on the pusher, it will definitely be moved 464: if (check->groundentity != pusher) 465: { 466: // see if the ent needs to be tested 467: if ( check->absmin[0] >= maxs[0] 468: || check->absmin[1] >= maxs[1] 469: || check->absmin[2] >= maxs[2] 470: || check->absmax[0] <= mins[0] 471: || check->absmax[1] <= mins[1] 472: || check->absmax[2] <= mins[2] ) 473: continue; 474: 475: // see if the ent's bbox is inside the pusher's final position 476: if (!SV_TestEntityPosition (check)) 477: continue; 478: } 479: 480: if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher)) 481: { 482: // move this entity 483: pushed_p->ent = check; 484: VectorCopy (check->s.origin, pushed_p->origin); 485: VectorCopy (check->s.angles, pushed_p->angles); 486: pushed_p++; 487: 488: // try moving the contacted entity 489: VectorAdd (check->s.origin, move, check->s.origin); 490: if (check->client) 491: { // FIXME: doesn't rotate monsters? 492: check->client->ps.pmove.delta_angles[YAW] += amove[YAW]; 493: } 494: 495: // figure movement due to the pusher's amove 496: VectorSubtract (check->s.origin, pusher->s.origin, org); 497: org2[0] = DotProduct (org, forward); 498: org2[1] = -DotProduct (org, right); 499: org2[2] = DotProduct (org, up); 500: VectorSubtract (org2, org, move2); 501: VectorAdd (check->s.origin, move2, check->s.origin); 502: 503: // may have pushed them off an edge 504: if (check->groundentity != pusher) 505: check->groundentity = NULL; 506: 507: block = SV_TestEntityPosition (check); 508: if (!block) 509: { // pushed ok 510: gi.linkentity (check); 511: // impact? 512: continue; 513: } 514: 515: // if it is ok to leave in the old position, do it 516: // this is only relevent for riding entities, not pushed 517: // FIXME: this doesn't acount for rotation 518: VectorSubtract (check->s.origin, move, check->s.origin); 519: block = SV_TestEntityPosition (check); 520: if (!block) 521: { 522: pushed_p--; 523: continue; 524: } 525: } 526: 527: // save off the obstacle so we can call the block function 528: obstacle = check; 529: 530: // move back any entities we already moved 531: // go backwards, so if the same entity was pushed 532: // twice, it goes back to the original position 533: for (p=pushed_p-1 ; p>=pushed ; p--) 534: { 535: VectorCopy (p->origin, p->ent->s.origin); 536: VectorCopy (p->angles, p->ent->s.angles); 537: if (p->ent->client) 538: { 539: p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw; 540: } 541: gi.linkentity (p->ent); 542: } 543: return false; 544: } 545: 546: //FIXME: is there a better way to handle this? 547: // see if anything we moved has touched a trigger 548: for (p=pushed_p-1 ; p>=pushed ; p--) 549: G_TouchTriggers (p->ent); 550: 551: return true; 552: } 553: 554: /* 555: ================ 556: SV_Physics_Pusher 557: 558: Bmodel objects don't interact with each other, but 559: push all box objects 560: ================ 561: */ 562: void SV_Physics_Pusher (edict_t *ent) 563: { 564: vec3_t move, amove; 565: edict_t *part, *mv; 566: 567: // if not a team captain, so movement will be handled elsewhere 568: if ( ent->flags & FL_TEAMSLAVE) 569: return; 570: 571: // make sure all team slaves can move before commiting 572: // any moves or calling any think functions 573: // if the move is blocked, all moved objects will be backed out 574: //retry: 575: pushed_p = pushed; 576: for (part = ent ; part ; part=part->teamchain) 577: { 578: if (part->velocity[0] || part->velocity[1] || part->velocity[2] || 579: part->avelocity[0] || part->avelocity[1] || part->avelocity[2] 580: ) 581: { // object is moving 582: VectorScale (part->velocity, FRAMETIME, move); 583: VectorScale (part->avelocity, FRAMETIME, amove); 584: 585: if (!SV_Push (part, move, amove)) 586: break; // move was blocked 587: } 588: } 589: if (pushed_p > &pushed[MAX_EDICTS]) 590: gi.error (ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted"); 591: 592: if (part) 593: { 594: // the move failed, bump all nextthink times and back out moves 595: for (mv = ent ; mv ; mv=mv->teamchain) 596: { 597: if (mv->nextthink > 0) 598: mv->nextthink += FRAMETIME; 599: } 600: 601: // if the pusher has a "blocked" function, call it 602: // otherwise, just stay in place until the obstacle is gone 603: if (part->blocked) 604: part->blocked (part, obstacle); 605: #if 0 606: // if the pushed entity went away and the pusher is still there 607: if (!obstacle->inuse && part->inuse) 608: goto retry; 609: #endif 610: } 611: else 612: { 613: // the move succeeded, so call all think functions 614: for (part = ent ; part ; part=part->teamchain) 615: { 616: SV_RunThink (part); 617: } 618: } 619: } 620: 621: //================================================================== 622: 623: /* 624: ============= 625: SV_Physics_None 626: 627: Non moving objects can only think 628: ============= 629: */ 630: void SV_Physics_None (edict_t *ent) 631: { 632: // regular thinking 633: SV_RunThink (ent); 634: } 635: 636: /* 637: ============= 638: SV_Physics_Noclip 639: 640: A moving object that doesn't obey physics 641: ============= 642: */ 643: void SV_Physics_Noclip (edict_t *ent) 644: { 645: // regular thinking 646: if (!SV_RunThink (ent)) 647: return; 648: 649: VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); 650: VectorMA (ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin); 651: 652: gi.linkentity (ent); 653: } 654: 655: /* 656: ============================================================================== 657: 658: TOSS / BOUNCE 659: 660: ============================================================================== 661: */ 662: 663: /* 664: ============= 665: SV_Physics_Toss 666: 667: Toss, bounce, and fly movement. When onground, do nothing. 668: ============= 669: */ 670: void SV_Physics_Toss (edict_t *ent) 671: { 672: trace_t trace; 673: vec3_t move; 674: float backoff; 675: edict_t *slave; 676: qboolean wasinwater; 677: qboolean isinwater; 678: vec3_t old_origin; 679: 680: // regular thinking 681: SV_RunThink (ent); 682: 683: // if not a team captain, so movement will be handled elsewhere 684: if ( ent->flags & FL_TEAMSLAVE) 685: return; 686: 687: if (ent->velocity[2] > 0) 688: ent->groundentity = NULL; 689: 690: // check for the groundentity going away 691: if (ent->groundentity) 692: if (!ent->groundentity->inuse) 693: ent->groundentity = NULL; 694: 695: // if onground, return without moving 696: if ( ent->groundentity ) 697: return; 698: 699: VectorCopy (ent->s.origin, old_origin); 700: 701: SV_CheckVelocity (ent); 702: 703: // add gravity 704: if (ent->movetype != MOVETYPE_FLY 705: && ent->movetype != MOVETYPE_FLYMISSILE) 706: SV_AddGravity (ent); 707: 708: // move angles 709: VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); 710: 711: // move origin 712: VectorScale (ent->velocity, FRAMETIME, move); 713: trace = SV_PushEntity (ent, move); 714: if (!ent->inuse) 715: return; 716: 717: if (trace.fraction < 1) 718: { 719: if (ent->movetype == MOVETYPE_BOUNCE) 720: backoff = 1.5; 721: else 722: backoff = 1; 723: 724: ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); 725: 726: // stop if on ground 727: if (trace.plane.normal[2] > 0.7) 728: { 729: if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) 730: { 731: ent->groundentity = trace.ent; 732: ent->groundentity_linkcount = trace.ent->linkcount; 733: VectorCopy (vec3_origin, ent->velocity); 734: VectorCopy (vec3_origin, ent->avelocity); 735: } 736: } 737: 738: // if (ent->touch) 739: // ent->touch (ent, trace.ent, &trace.plane, trace.surface); 740: } 741: 742: // check for water transition 743: wasinwater = (ent->watertype & MASK_WATER); 744: ent->watertype = gi.pointcontents (ent->s.origin); 745: isinwater = ent->watertype & MASK_WATER; 746: 747: if (isinwater) 748: ent->waterlevel = 1; 749: else 750: ent->waterlevel = 0; 751: 752: if (!wasinwater && isinwater) 753: gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); 754: else if (wasinwater && !isinwater) 755: gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); 756: 757: // move teamslaves 758: for (slave = ent->teamchain; slave; slave = slave->teamchain) 759: { 760: VectorCopy (ent->s.origin, slave->s.origin); 761: gi.linkentity (slave); 762: } 763: } 764: 765: /* 766: =============================================================================== 767: 768: STEPPING MOVEMENT 769: 770: =============================================================================== 771: */ 772: 773: /* 774: ============= 775: SV_Physics_Step 776: 777: Monsters freefall when they don't have a ground entity, otherwise 778: all movement is done with discrete steps. 779: 780: This is also used for objects that have become still on the ground, but 781: will fall if the floor is pulled out from under them. 782: FIXME: is this true? 783: ============= 784: */ 785: 786: //FIXME: hacked in for E3 demo 787: #define sv_stopspeed 100 788: #define sv_friction 6 789: #define sv_waterfriction 1 790: 791: void SV_AddRotationalFriction (edict_t *ent) 792: { 793: int n; 794: float adjustment; 795: 796: VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); 797: adjustment = FRAMETIME * sv_stopspeed * sv_friction; 798: for (n = 0; n < 3; n++) 799: { 800: if (ent->avelocity[n] > 0) 801: { 802: ent->avelocity[n] -= adjustment; 803: if (ent->avelocity[n] < 0) 804: ent->avelocity[n] = 0; 805: } 806: else 807: { 808: ent->avelocity[n] += adjustment; 809: if (ent->avelocity[n] > 0) 810: ent->avelocity[n] = 0; 811: } 812: } 813: } 814: 815: void SV_Physics_Step (edict_t *ent) 816: { 817: qboolean wasonground; 818: qboolean hitsound = false; 819: float *vel; 820: float speed, newspeed, control; 821: float friction; 822: edict_t *groundentity; 823: int mask; 824: 825: // airborn monsters should always check for ground 826: if (!ent->groundentity) 827: M_CheckGround (ent); 828: 829: groundentity = ent->groundentity; 830: 831: SV_CheckVelocity (ent); 832: 833: if (groundentity) 834: wasonground = true; 835: else 836: wasonground = false; 837: 838: if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) 839: SV_AddRotationalFriction (ent); 840: 841: // add gravity except: 842: // flying monsters 843: // swimming monsters who are in the water 844: if (! wasonground) 845: if (!(ent->flags & FL_FLY)) 846: if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) 847: { 848: if (ent->velocity[2] < sv_gravity->value*-0.1) 849: hitsound = true; 850: if (ent->waterlevel == 0) 851: SV_AddGravity (ent); 852: } 853: 854: // friction for flying monsters that have been given vertical velocity 855: if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) 856: { 857: speed = fabs(ent->velocity[2]); 858: control = speed < sv_stopspeed ? sv_stopspeed : speed; 859: friction = sv_friction/3; 860: newspeed = speed - (FRAMETIME * control * friction); 861: if (newspeed < 0) 862: newspeed = 0; 863: newspeed /= speed; 864: ent->velocity[2] *= newspeed; 865: } 866: 867: // friction for flying monsters that have been given vertical velocity 868: if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) 869: { 870: speed = fabs(ent->velocity[2]); 871: control = speed < sv_stopspeed ? sv_stopspeed : speed; 872: newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); 873: if (newspeed < 0) 874: newspeed = 0; 875: newspeed /= speed; 876: ent->velocity[2] *= newspeed; 877: } 878: 879: if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) 880: { 881: // apply friction 882: // let dead monsters who aren't completely onground slide 883: if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY))) 884: if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) 885: { 886: vel = ent->velocity; 887: speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); 888: if (speed) 889: { 890: friction = sv_friction; 891: 892: control = speed < sv_stopspeed ? sv_stopspeed : speed; 893: newspeed = speed - FRAMETIME*control*friction; 894: 895: if (newspeed < 0) 896: newspeed = 0; 897: newspeed /= speed; 898: 899: vel[0] *= newspeed; 900: vel[1] *= newspeed; 901: } 902: } 903: 904: if (ent->svflags & SVF_MONSTER) 905: mask = MASK_MONSTERSOLID; 906: else 907: mask = MASK_SOLID; 908: SV_FlyMove (ent, FRAMETIME, mask); 909: 910: gi.linkentity (ent); 911: G_TouchTriggers (ent); 1.1.1.2 root 912: if (!ent->inuse) 913: return; 1.1 root 914: 915: if (ent->groundentity) 916: if (!wasonground) 917: if (hitsound) 918: gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); 919: } 920: 921: // regular thinking 922: SV_RunThink (ent); 923: } 924: 925: //============================================================================ 926: /* 927: ================ 928: G_RunEntity 929: 930: ================ 931: */ 932: void G_RunEntity (edict_t *ent) 933: { 934: if (ent->prethink) 935: ent->prethink (ent); 936: 937: switch ( (int)ent->movetype) 938: { 939: case MOVETYPE_PUSH: 940: case MOVETYPE_STOP: 941: SV_Physics_Pusher (ent); 942: break; 943: case MOVETYPE_NONE: 944: SV_Physics_None (ent); 945: break; 946: case MOVETYPE_NOCLIP: 947: SV_Physics_Noclip (ent); 948: break; 949: case MOVETYPE_STEP: 950: SV_Physics_Step (ent); 951: break; 952: case MOVETYPE_TOSS: 953: case MOVETYPE_BOUNCE: 954: case MOVETYPE_FLY: 955: case MOVETYPE_FLYMISSILE: 956: SV_Physics_Toss (ent); 957: break; 958: default: 959: gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype); 960: } 961: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.