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 */
20 // cl_view.c -- player rendering positioning
21
22 #include "client.h"
23 #include "localent.h"
24
25 extern int deferred_model_index;
26
27 //=============
28 //
29 // development tools for weapons
30 //
31 int gun_frame;
32 struct model_s *gun_model;
33
34 //=============
35
36 cvar_t *crosshair;
37 cvar_t *cl_testparticles;
38 cvar_t *cl_testentities;
39 cvar_t *cl_testlights;
40 cvar_t *cl_testblend;
41
42 cvar_t *cl_stats;
43
44 cvar_t *cl_drawfps;
45 cvar_t *cl_drawfps_x;
46 cvar_t *cl_drawfps_y;
47
48 cvar_t *cl_stfu_ilkhan;
49 cvar_t *cl_drawmaptime_x;
50 cvar_t *cl_drawmaptime_y;
51
52 cvar_t *cl_defermodels;
53 cvar_t *cl_particlecount;
54
55 cvar_t *scr_crosshair_x;
56 cvar_t *scr_crosshair_y;
57
58 extern cvar_t *scr_showturtle;
59
60 int r_numdlights;
61 dlight_t r_dlights[MAX_DLIGHTS];
62
63 int r_numentities;
64 entity_t r_entities[MAX_ENTITIES];
65
66 int r_numparticles;
67 particle_t *r_particles;//[MAX_PARTICLES];
68
69 lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
70
71 char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
72 int num_cl_weaponmodels;
73
74
75 /*
76 ====================
77 V_ClearScene
78
79 Specifies the model that will be used as the world
80 ====================
81 */
V_ClearScene(void)82 void V_ClearScene (void)
83 {
84 r_numdlights = 0;
85 r_numentities = 0;
86 r_numparticles = 0;
87 }
88
89 /*
90 =====================
91 V_AddEntity
92
93 =====================
94 */
V_AddEntity(entity_t * ent)95 void V_AddEntity (entity_t *ent)
96 {
97 if (r_numentities >= MAX_ENTITIES)
98 return;
99
100 r_entities[r_numentities++] = *ent;
101 }
102
103
104 /*
105 =====================
106 V_AddParticle
107
108 =====================
109 */
V_AddParticle(vec3_t org,unsigned color,float alpha)110 void V_AddParticle (vec3_t org, unsigned color, float alpha)
111 {
112 particle_t *p;
113
114 if (r_numparticles >= cl_particlecount->intvalue)
115 return;
116
117 if (color > 0xFF)
118 Com_Error (ERR_DROP, "V_AddParticle: bad color %d", color);
119
120 p = &r_particles[r_numparticles++];
121 FastVectorCopy (*org, p->origin);
122 p->color = color;
123 p->alpha = alpha;
124 }
125
126 /*
127 =====================
128 V_AddLight
129
130 =====================
131 */
V_AddLight(vec3_t org,float intensity,float r,float g,float b)132 void V_AddLight (vec3_t org, float intensity, float r, float g, float b)
133 {
134 dlight_t *dl;
135
136 if (r_numdlights >= MAX_DLIGHTS)
137 return;
138
139 dl = &r_dlights[r_numdlights++];
140 FastVectorCopy (*org, dl->origin);
141 dl->intensity = intensity;
142 dl->color[0] = r;
143 dl->color[1] = g;
144 dl->color[2] = b;
145 }
146
147
148 /*
149 =====================
150 V_AddLightStyle
151
152 =====================
153 */
V_AddLightStyle(int style,float r,float g,float b)154 void V_AddLightStyle (int style, float r, float g, float b)
155 {
156 lightstyle_t *ls;
157
158 if (style < 0 || style > MAX_LIGHTSTYLES)
159 Com_Error (ERR_DROP, "Bad light style %i", style);
160
161 ls = &r_lightstyles[style];
162
163 ls->white = r+g+b;
164 ls->rgb[0] = r;
165 ls->rgb[1] = g;
166 ls->rgb[2] = b;
167 }
168
169 /*
170 ================
171 V_TestParticles
172
173 If cl_testparticles is set, create 4096 particles in the view
174 ================
175 */
V_TestParticles(void)176 void V_TestParticles (void)
177 {
178 particle_t *p;
179 int i, j;
180 float d, r, u;
181
182 r_numparticles = cl_particlecount->intvalue;
183 for (i=0 ; i<r_numparticles ; i++)
184 {
185 d = i*0.25f;
186 r = 4*((i&7)-3.5f);
187 u = 4*(((i>>3)&7)-3.5f);
188 p = &r_particles[i];
189
190 for (j=0 ; j<3 ; j++)
191 p->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*d +
192 cl.v_right[j]*r + cl.v_up[j]*u;
193
194 p->color = 8;
195 p->alpha = cl_testparticles->value;
196 }
197 }
198
199 /*
200 ================
201 V_TestEntities
202
203 If cl_testentities is set, create 32 player models
204 ================
205 */
V_TestEntities(void)206 void V_TestEntities (void)
207 {
208 int i, j;
209 float f, r;
210 entity_t *ent;
211
212 r_numentities = 32;
213 memset (r_entities, 0, sizeof(r_entities));
214
215 for (i=0 ; i<r_numentities ; i++)
216 {
217 ent = &r_entities[i];
218
219 r = 64 * ( (i%4) - 1.5f );
220 f = (float)(64 * (i/4) + 128);
221
222 for (j=0 ; j<3 ; j++)
223 ent->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
224 cl.v_right[j]*r;
225
226 ent->model = cl.baseclientinfo.model;
227 ent->skin = cl.baseclientinfo.skin;
228 }
229 }
230
231 /*
232 ================
233 V_TestLights
234
235 If cl_testlights is set, create 32 lights models
236 ================
237 */
238 /*
239 ================
240 V_TestLights
241
242 If cl_testlights is set, create 32 lights models
243 ================
244 */
V_TestLights(void)245 void V_TestLights (void)
246 {
247 int i, j;
248 float f, r;
249 dlight_t *dl;
250
251 r_numdlights = 32;
252 memset (r_dlights, 0, sizeof(r_dlights));
253
254 for (i=0 ; i<r_numdlights ; i++)
255 {
256 dl = &r_dlights[i];
257
258 r = 64 * ( (i%4) - 1.5f );
259 f = 64 * (i/4.0f) + 128;
260
261 for (j=0 ; j<3 ; j++)
262 dl->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
263 cl.v_right[j]*r;
264 dl->color[0] = (float)(((i%6)+1) & 1);
265 dl->color[1] = (float)((((i%6)+1) & 2)>>1);
266 dl->color[2] = (float)((((i%6)+1) & 4)>>2);
267 dl->intensity = 200;
268 }
269 }
270
271 //===================================================================
272
273 /*
274 =================
275 CL_PrepRefresh
276
277 Call before entering a new level, or after changing dlls
278 =================
279 */
CL_PrepRefresh(void)280 void CL_PrepRefresh (void)
281 {
282 char mapname[MAX_QPATH];
283
284 int i;
285 int maxclients;
286
287 float rotate;
288 vec3_t axis;
289
290 if (!cl.configstrings[CS_MODELS+1][0])
291 return; // no map loaded
292
293 SCR_AddDirtyPoint (0, 0);
294 SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
295
296 // let the render dll load the map
297 Q_strncpy (mapname, cl.configstrings[CS_MODELS+1] + 5, sizeof(mapname)-1); // skip "maps/"
298 mapname[strlen(mapname)-4] = 0; // cut off ".bsp"
299
300 Cvar_ForceSet ("$mapname", mapname);
301
302 // register models, pics, and skins
303 Com_Printf ("Map: %s\r", LOG_CLIENT, mapname);
304 SCR_UpdateScreen ();
305
306 // clear tents - dangling model pointers
307 CL_ClearTEnts ();
308
309 re.BeginRegistration (mapname);
310
311 Com_Printf (" \r", LOG_CLIENT);
312
313 Sys_SendKeyEvents ();
314
315 Netchan_Transmit (&cls.netchan, 0, NULL);
316
317 // precache status bar pics
318 Com_Printf ("pics\r", LOG_CLIENT);
319 SCR_UpdateScreen ();
320 SCR_TouchPics ();
321 //Com_Printf (" \r", LOG_CLIENT);
322
323 Com_Printf ("models\r", LOG_CLIENT);
324 SCR_UpdateScreen ();
325 CL_RegisterTEntModels ();
326
327 num_cl_weaponmodels = 1;
328 strcpy(cl_weaponmodels[0], "weapon.md2");
329
330 for (i=1 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
331 {
332 if (cl.configstrings[CS_MODELS+i][0] == '#')
333 {
334 // special player weapon model
335 if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS)
336 {
337 strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1,
338 sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1);
339 num_cl_weaponmodels++;
340 }
341 }
342 }
343
344 Netchan_Transmit (&cls.netchan, 0, NULL);
345
346 //modelindex 1 is always world.
347 //is 0 ever used?
348
349 cl.model_clip[0] = NULL;
350 cl.model_draw[0] = NULL;
351
352 cl.model_draw[1] = re.RegisterModel (cl.configstrings[CS_MODELS+1]);
353
354 if (cl.configstrings[CS_MODELS+1][0] == '*')
355 cl.model_clip[1] = CM_InlineModel (cl.configstrings[CS_MODELS+1]);
356 else
357 cl.model_clip[1] = NULL;
358
359 if (cl_defermodels->intvalue && !cl_timedemo->intvalue)
360 {
361 deferred_model_index = 1;
362 for (i = 2; i < MAX_MODELS; i++)
363 {
364 cl.model_clip[i] = NULL;
365 cl.model_draw[i] = NULL;
366 }
367 }
368 else
369 {
370 deferred_model_index = MAX_MODELS;
371 for (i = 2; i < MAX_MODELS; i++)
372 {
373 if (!cl.configstrings[CS_MODELS+i][0])
374 continue;
375
376 if (cl.configstrings[CS_MODELS+i][0] != '#')
377 {
378 cl.model_draw[i] = re.RegisterModel (cl.configstrings[CS_MODELS+i]);
379 if (cl.configstrings[CS_MODELS+i][0] == '*')
380 cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]);
381 else
382 cl.model_clip[i] = NULL;
383 }
384
385 Com_Printf ("%s \r", LOG_CLIENT, cl.configstrings[CS_MODELS+i]);
386 //SCR_UpdateScreen ();
387 Sys_SendKeyEvents ();
388 }
389 }
390
391 Com_Printf ("images\r ", LOG_CLIENT);
392 SCR_UpdateScreen ();
393 for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
394 {
395 re.RegisterPic (cl.configstrings[CS_IMAGES+i]);
396 Sys_SendKeyEvents (); // pump message loop
397 }
398
399 Com_Printf (" \r", LOG_CLIENT);
400
401 maxclients = cl.maxclients;
402
403 Com_Printf ("clients\r", LOG_CLIENT);
404 SCR_UpdateScreen ();
405
406 //must be zeroed to flush out old model pointers
407 memset (&cl.clientinfo, 0, sizeof(cl.clientinfo));
408
409 for (i=0 ; i<maxclients ; i++)
410 {
411 if (!cl.configstrings[CS_PLAYERSKINS+i][0])
412 continue;
413
414 SCR_UpdateScreen ();
415 Sys_SendKeyEvents ();
416 CL_ParseClientinfo (i);
417 }
418
419 Netchan_Transmit (&cls.netchan, 0, NULL);
420
421 CL_LoadClientinfo (&cl.baseclientinfo, "");
422
423 // set sky textures and speed
424 Com_Printf ("sky \r", LOG_CLIENT);
425 SCR_UpdateScreen ();
426
427 rotate = (float)atof (cl.configstrings[CS_SKYROTATE]);
428
429 if (sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f",
430 &axis[0], &axis[1], &axis[2]) != 3)
431 {
432 VectorClear (axis);
433 }
434
435 re.SetSky (cl.configstrings[CS_SKY], rotate, axis);
436 Com_Printf (" \r", LOG_CLIENT);
437
438 // the renderer can now free unneeded stuff
439 if (deferred_model_index == MAX_MODELS)
440 re.EndRegistration ();
441
442 // clear any lines of console text
443 Con_ClearNotify ();
444
445 SCR_UpdateScreen ();
446
447 cl.refresh_prepped = true;
448 cl.force_refdef = true; // make sure we have a valid refdef
449
450 //probably out of date
451 cl.frame.valid = false;
452
453 //reset current list
454 cl.refdef.num_entities = 0;
455 cl.refdef.entities = NULL;
456
457 cl.refdef.num_particles = 0;
458 cl.refdef.particles = NULL;
459
460 cl.refdef.num_dlights = 0;
461 cl.refdef.dlights = NULL;
462 //cl.refdef.lightstyles = 0;
463
464 S_StopAllSounds ();
465
466 //can't use cls.realtime - could be out of date :)
467 //if (!cl_timedemo->intvalue)
468 //cl.defer_rendering = (int)(Sys_Milliseconds() + (cl_defertimer->value * 1000));
469 //else
470 cl.defer_rendering = 0;
471
472 // start the cd track
473 #ifdef CD_AUDIO
474 CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true);
475 #endif
476 }
477
478 /*
479 ====================
480 CalcFov
481 ====================
482 */
CalcFov(float fov_x,int width,int height)483 float CalcFov (float fov_x, int width, int height)
484 {
485 static float a;
486 static float last_fov;
487 static int lw, lh;
488
489 //r1: only calculate if needed
490 if (width != lw || height != lh || *(int*)&fov_x != *(int*)&last_fov)
491 {
492 float x;
493
494 if (fov_x < 1 || fov_x > 179)
495 Com_Error (ERR_DROP, "Bad fov: %f", fov_x);
496
497 x = width / (float)tan(fov_x/360*M_PI);
498
499 a = (float)atan (height/x);
500 a = a*360/M_PI;
501
502 last_fov = fov_x;
503 lw = width;
504 lh = height;
505 }
506
507 return a;
508 }
509
510 //============================================================================
511
512 // gun frame debugging functions
V_Gun_Next_f(void)513 void V_Gun_Next_f (void)
514 {
515 gun_frame++;
516 Com_Printf ("frame %i\n", LOG_CLIENT, gun_frame);
517 }
518
V_Gun_Prev_f(void)519 void V_Gun_Prev_f (void)
520 {
521 gun_frame--;
522 if (gun_frame < 0)
523 gun_frame = 0;
524 Com_Printf ("frame %i\n", LOG_CLIENT, gun_frame);
525 }
526
V_Gun_Model_f(void)527 void V_Gun_Model_f (void)
528 {
529 char name[MAX_QPATH];
530
531 if (Cmd_Argc() != 2)
532 {
533 gun_model = NULL;
534 return;
535 }
536 Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
537 gun_model = re.RegisterModel (name);
538 }
539
540 //============================================================================
541
542
543 /*
544 =================
545 SCR_DrawCrosshair
546 =================
547 */
SCR_DrawCrosshair(void)548 __inline void SCR_DrawCrosshair (void)
549 {
550 if (!crosshair->intvalue)
551 return;
552
553 /*if (crosshair->modified)
554 {
555 crosshair->modified = false;
556 SCR_TouchPics ();
557 }*/
558
559 if (!crosshair_pic[0])
560 return;
561
562 re.DrawPic (scr_vrect.x + scr_crosshair_x->intvalue + ((scr_vrect.width - crosshair_width)>>1)
563 , scr_vrect.y + + scr_crosshair_y->intvalue + ((scr_vrect.height - crosshair_height)>>1), crosshair_pic);
564 }
565
566 int spc = 0;
567 int fps = 0;
568 int frames_this_second = 0;
569 uint32 frames_seconds = 0;
570
571 static const char rateMsg[] = "RATEDROP";
572 static const char frameMsg[] = "OLDFRAME";
573 static const char parseMsg[] = "OLDPARSE";
574 static const char overflowMsg[] = "OVERFLOW";
575
576 extern int EXPORT entitycmpfnc( const entity_t *, const entity_t * );
577 extern int scr_draw_loading;
578 /*
579 ==================
580 V_RenderView
581
582 ==================
583 */
584 #ifdef CL_STEREO_SUPPORT
V_RenderView(float stereo_separation)585 void V_RenderView( float stereo_separation )
586 #else
587 void V_RenderView(void)
588 #endif
589 {
590 if (cls.state != ca_active)
591 return;
592
593 if (!cl.refresh_prepped)
594 return; // still loading
595
596 if (cl_timedemo->intvalue)
597 {
598 if (!cl.timedemo_start)
599 cl.timedemo_start = Sys_Milliseconds ();
600 cl.timedemo_frames++;
601 }
602
603 // an invalid frame will just use the exact previous refdef
604 // we can't use the old frame if the video mode has changed, though...
605 if ( cl.frame.valid && (cl.force_refdef || !cl_paused->intvalue) )
606 {
607 cl.force_refdef = false;
608
609 V_ClearScene ();
610
611 // build a refresh entity list and calc cl.sim*
612 // this also calls CL_CalcViewValues which loads
613 // v_forward, etc.
614 CL_AddEntities ();
615
616 if (cl_testparticles->intvalue)
617 V_TestParticles ();
618
619 if (cl_testentities->intvalue)
620 V_TestEntities ();
621
622 if (cl_testlights->intvalue)
623 V_TestLights ();
624
625 if (cl_testblend->value)
626 {
627 cl.refdef.blend[0] = 1;
628 cl.refdef.blend[1] = 0.5;
629 cl.refdef.blend[2] = 0.25;
630 cl.refdef.blend[3] = 0.5;
631 }
632
633 // offset vieworg appropriately if we're doing stereo separation
634 #ifdef CL_STEREO_SUPPORT
635 if ( stereo_separation != 0 )
636 {
637 vec3_t tmp;
638
639 VectorScale( cl.v_right, stereo_separation, tmp );
640 VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
641 }
642 #endif
643
644 // never let it sit exactly on a node line, because a water plane can
645 // dissapear when viewed with the eye exactly on it.
646 // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
647 cl.refdef.vieworg[0] += 1.0f/16;
648 cl.refdef.vieworg[1] += 1.0f/16;
649 cl.refdef.vieworg[2] += 1.0f/16;
650
651 cl.refdef.x = scr_vrect.x;
652 cl.refdef.y = scr_vrect.y;
653 cl.refdef.width = scr_vrect.width;
654 cl.refdef.height = scr_vrect.height;
655 cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
656 cl.refdef.time = cl.time * 0.001f;
657
658 cl.refdef.areabits = cl.frame.areabits;
659
660 if (!cl_add_entities->intvalue)
661 r_numentities = 0;
662 if (!cl_add_particles->intvalue)
663 r_numparticles = 0;
664 if (!cl_add_lights->intvalue)
665 r_numdlights = 0;
666 if (!cl_add_blend->intvalue)
667 {
668 VectorClear (cl.refdef.blend);
669 }
670
671 if (cl.defer_rendering > cls.realtime)
672 r_numentities = 0;
673
674 cl.refdef.num_entities = r_numentities;
675 cl.refdef.entities = r_entities;
676 cl.refdef.num_particles = r_numparticles;
677 cl.refdef.particles = r_particles;
678 cl.refdef.num_dlights = r_numdlights;
679 cl.refdef.dlights = r_dlights;
680 cl.refdef.lightstyles = r_lightstyles;
681
682 cl.refdef.rdflags = cl.frame.playerstate.rdflags;
683
684 // sort entities for better cache locality
685 qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (EXPORT *)(const void *, const void *))entitycmpfnc );
686 }
687
688 if (!cl.force_refdef)
689 re.RenderFrame (&cl.refdef);
690
691 if (cl_stats->intvalue)
692 Com_Printf ("ent:%i lt:%i part:%i\n", LOG_CLIENT, r_numentities, r_numdlights, r_numparticles);
693 //if ( log_stats->value && ( log_stats_file != 0 ) )
694 // fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles);
695
696 if ((unsigned)(curtime - frames_seconds) >= 1000)
697 {
698 spc = serverPacketCount;
699 fps = frames_this_second;
700 frames_this_second = 0;
701 serverPacketCount = 0;
702 frames_seconds = curtime;
703 }
704
705 if (cl_shownet->intvalue == -1)
706 {
707 char buff[16];
708 int x;
709 Com_sprintf (buff, sizeof(buff), "%d", spc);
710 for (x = 0; x < strlen(buff); x++) {
711 re.DrawChar (viddef.width-26+x*8, viddef.height / 2, 128 + buff[x]);
712 }
713 }
714
715 //r1: fps display
716 if (cl_drawfps->intvalue)
717 {
718 int x, len;
719 char buff[16];
720
721 frames_this_second++;
722
723 if (cl_drawfps->intvalue == 2)
724 {
725 fps = (int)(1.0f / cls.frametime);
726 }
727
728 len = Com_sprintf (buff, sizeof(buff), "%d", fps);
729 for (x = 0; x < len; x++)
730 {
731 re.DrawChar (viddef.width-26+x*8+cl_drawfps_x->intvalue, viddef.height - 16 + cl_drawfps_y->intvalue, 128 + buff[x]);
732 }
733 }
734
735 //r1: map timer (don't ask)
736 if (cl_stfu_ilkhan->intvalue)
737 {
738 char buff[16];
739 int x, len;
740 int secs = (cl.frame.serverframe % 600) / 10;
741 int mins = cl.frame.serverframe / 600;
742
743 len = Com_sprintf (buff, sizeof(buff), "%d:%.2d", mins, secs);
744 for (x = 0; x < len; x++)
745 {
746 re.DrawChar (x * 8 + cl_drawmaptime_x->intvalue, viddef.height - 8 + cl_drawmaptime_y->intvalue, 128 + buff[x]);
747 }
748 }
749
750 //FIXME: incorrect use of scr_ prefix
751 if (scr_showturtle->intvalue && !scr_draw_loading && cls.state == ca_active)
752 {
753 frame_t *old;
754
755 if (cl.surpressCount)
756 {
757 int x;
758 for (x=0 ; x<sizeof(rateMsg)-1; x++)
759 re.DrawChar (1+(x*8), 250, 128 + rateMsg[x] );
760 }
761
762 old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
763 if (old->serverframe != cl.frame.deltaframe)
764 {
765 // The frame that the server did the delta from
766 // is too old, so we can't reconstruct it properly.
767 int x;
768 for (x=0 ; x<sizeof(frameMsg)-1; x++)
769 re.DrawChar (1+(x*8), 266, 128 + frameMsg[x] );
770 }
771
772 if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128)
773 {
774 int x;
775 for (x=0 ; x<sizeof(parseMsg)-1; x++)
776 re.DrawChar (1+(x*8), 282, 128 + parseMsg[x] );
777 }
778
779 if (noFrameFromServerPacket > 2)
780 {
781 int x;
782 for (x=0 ; x<sizeof(overflowMsg)-1; x++)
783 re.DrawChar (1+(x*8), 298, 128 + overflowMsg[x] );
784 }
785 }
786
787 SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y);
788 SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1,
789 scr_vrect.y+scr_vrect.height-1);
790
791 SCR_DrawCrosshair ();
792 }
793
794
795 /*
796 =============
797 V_Viewpos_f
798 =============
799 */
V_Viewpos_f(void)800 void V_Viewpos_f (void)
801 {
802 Com_Printf ("(%i %i %i) : %i\n", LOG_CLIENT, (int)cl.refdef.vieworg[0],
803 (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2],
804 (int)cl.refdef.viewangles[YAW]);
805 }
806
OnCrossHairChange(cvar_t * self,char * old,char * newValue)807 void OnCrossHairChange (cvar_t *self, char *old, char *newValue)
808 {
809 self->modified = false;
810 SCR_TouchPics();
811 }
812
813 //ick
814 extern cparticle_t *particles;
815 void CL_ClearParticles (int num);
816 static int num_particles;
_particlecount_changed(cvar_t * self,char * old,char * newValue)817 void _particlecount_changed (cvar_t *self, char *old, char *newValue)
818 {
819 int count;
820
821 //update cvar if we had to cap
822 if (self->intvalue < 1024)
823 {
824 Cvar_Set (self->name, "1024");
825 return;
826 }
827 else if (self->intvalue > 1048576)
828 {
829 Cvar_Set (self->name, "1048576");
830 return;
831 }
832
833 if (particles)
834 {
835 CL_ClearParticles (num_particles);
836 Z_Free (particles);
837 }
838
839 if (r_particles)
840 {
841 r_numparticles = 0;
842 Z_Free (r_particles);
843 }
844
845 count = self->intvalue;
846
847 particles = Z_TagMalloc (count * sizeof(*particles), TAGMALLOC_CL_PARTICLES);
848 r_particles = Z_TagMalloc (count * sizeof(*r_particles), TAGMALLOC_CL_PARTICLES);
849
850 //allocated uninit
851 CL_ClearParticles (count);
852
853 num_particles = count;
854 }
855
856 /*
857 =============
858 V_Init
859 =============
860 */
V_Init(void)861 void V_Init (void)
862 {
863 Cmd_AddCommand ("gun_next", V_Gun_Next_f);
864 Cmd_AddCommand ("gun_prev", V_Gun_Prev_f);
865 Cmd_AddCommand ("gun_model", V_Gun_Model_f);
866
867 Cmd_AddCommand ("viewpos", V_Viewpos_f);
868
869 crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE);
870 crosshair->changed = OnCrossHairChange;
871
872 cl_particlecount = Cvar_Get ("cl_particlecount", "16384", 0);
873 cl_particlecount->changed = _particlecount_changed;
874 _particlecount_changed (cl_particlecount, cl_particlecount->string, cl_particlecount->string);
875
876 cl_testblend = Cvar_Get ("cl_testblend", "0", 0);
877 cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0);
878 cl_testentities = Cvar_Get ("cl_testentities", "0", 0);
879 cl_testlights = Cvar_Get ("cl_testlights", "0", 0);
880
881 cl_stats = Cvar_Get ("cl_stats", "0", 0);
882
883 cl_drawfps = Cvar_Get ("cl_drawfps", "0", 0);
884 cl_drawfps_x = Cvar_Get ("cl_drawfps_x", "0", 0);
885 cl_drawfps_y = Cvar_Get ("cl_drawfps_y", "0", 0);
886
887 cl_stfu_ilkhan = Cvar_Get ("cl_drawmaptime", "0", 0);
888 cl_drawmaptime_x = Cvar_Get ("cl_drawmaptime_x", "0", 0);
889 cl_drawmaptime_y = Cvar_Get ("cl_drawmaptime_y", "0", 0);
890
891 cl_defermodels = Cvar_Get ("cl_defermodels", "1", 0);
892
893 scr_crosshair_x = Cvar_Get ("scr_crosshair_x", "0", 0);
894 scr_crosshair_y = Cvar_Get ("scr_crosshair_y", "0", 0);
895 }
896