|
|
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.