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