]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/vehicles/all.qc
a4736687a6280ee020686191351ad21df8148771
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / vehicles / all.qc
1 #include "all.qh"
2 #include "../_all.qh"
3
4 #include "../movetypes.qh"
5 #include "../movetypes.qh"
6 #include "../prandom.qh"
7 #include "../scoreboard.qh"
8 #include "../t_items.qh"
9
10 #include "../../common/buffs.qh"
11 #include "../../common/constants.qh"
12 #include "../../common/stats.qh"
13 #include "../../common/util.qh"
14
15 #include "../../csqcmodellib/cl_model.qh"
16
17 .float cnt;
18
19 const string vNULL  = "gfx/vehicles/null.tga";
20 const string vFRAME = "gfx/vehicles/frame.tga";
21
22 const string vMODEL_SHIELD         = "gfx/vehicles/vh-shield.tga";
23 const string vMODEL_BUMBLE         = "gfx/vehicles/bumb.tga";
24 const string vMODEL_BUMBLE_WEAPON1 = "gfx/vehicles/bumb_lgun.tga";
25 const string vMODEL_BUMBLE_WEAPON2 = "gfx/vehicles/bumb_rgun.tga";
26 const string vMODEL_GUNNER         = "gfx/vehicles/bumb_side.tga";
27 const string vMODEL_GUNNER_WEAPON1 = "gfx/vehicles/bumb_side_gun.tga";
28 const string vMODEL_RAPTOR         = "gfx/vehicles/raptor.tga";
29 const string vMODEL_RAPTOR_WEAPON1 = "gfx/vehicles/raptor_guns.tga";
30 const string vMODEL_RAPTOR_WEAPON2 = "gfx/vehicles/raptor_bombs.tga";
31 const string vMODEL_SPIDER         = "gfx/vehicles/sbot.tga";
32 const string vMODEL_SPIDER_WEAPON1 = "gfx/vehicles/sbot_mguns.tga";
33 const string vMODEL_SPIDER_WEAPON2 = "gfx/vehicles/sbot_rpods.tga";
34 const string vMODEL_RACER          = "gfx/vehicles/waki.tga";
35 const string vMODEL_RACER_WEAPON1  = "gfx/vehicles/waki_guns.tga";
36 const string vMODEL_RACER_WEAPON2  = "gfx/vehicles/waki_rockets.tga";
37
38 const string vBAR_HEALTH = "gfx/vehicles/bar_up_left.tga";
39 const string vBAR_SHIELD = "gfx/vehicles/bar_dwn_left.tga";
40 const string vBAR_AMMO1  = "gfx/vehicles/bar_up_right.tga";
41 const string vBAR_AMMO2  = "gfx/vehicles/bar_dwn_right.tga";
42
43 const string vICON_HEALTH = "gfx/vehicles/health.tga";
44 const string vICON_SHIELD = "gfx/vehicles/shield.tga";
45 const string vICON_AMMO1  = "gfx/vehicles/bullets.tga";
46 const string vICON_AMMO2  = "gfx/vehicles/rocket.tga";
47
48 const string vCROSS_AIM  = "gfx/vehicles/axh-special1.tga";
49 const string vCROSS_DROP = "gfx/vehicles/axh-dropcross.tga";
50 const string vCROSS_HEAL = "gfx/vehicles/axh-cross.tga";
51 const string vCROSS_HINT = "gfx/vehicles/axh-ring.tga";
52 const string vCROSS_LOCK = "gfx/vehicles/axh-bracket.tga";
53 const string vCROSS_TAG  = "gfx/vehicles/axh-tag.tga";
54
55 const int SBRM_FIRST     = 1;
56 const int SBRM_VOLLY     = 1;
57 const int SBRM_GUIDE     = 2;
58 const int SBRM_ARTILLERY = 3;
59 const int SBRM_LAST      = 3;
60
61 const int RSM_FIRST = 1;
62 const int RSM_BOMB  = 1;
63 const int RSM_FLARE = 2;
64 const int RSM_LAST  = 2;
65
66 const int MAX_AXH = 4;
67 entity AuxiliaryXhairs[MAX_AXH];
68 entityclass(AuxiliaryXhair);
69 class(AuxiliaryXhair) .string axh_image;
70 class(AuxiliaryXhair) .float  axh_fadetime;
71 class(AuxiliaryXhair) .float  axh_drawflag;
72
73 entity dropmark;
74
75 float alarm1time;
76 float alarm2time;
77 int weapon2mode;
78
79
80 void AuxiliaryXhair_Draw2D()
81 {
82         if (scoreboard_showscores)
83                 return;
84
85         vector size = draw_getimagesize(self.axh_image) * autocvar_cl_vehicles_crosshair_size;
86         vector pos = project_3d_to_2d(self.move_origin) - 0.5 * size;
87
88         if (!(pos.z < 0 || pos.x < 0 || pos.y < 0 || pos.x > vid_conwidth || pos.y > vid_conheight))
89         {
90                 pos.z = 0;
91                 size.z = 0;
92                 drawpic(pos, self.axh_image, size, self.colormod, self.alpha, self.axh_drawflag);
93         }
94
95         if(time - self.cnt > self.axh_fadetime)
96                 self.draw2d = func_null;
97 }
98
99 void Net_AuXair2(bool bIsNew)
100 {
101         int axh_id = bound(0, ReadByte(), MAX_AXH);
102         entity axh = AuxiliaryXhairs[axh_id];
103
104         if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
105         {
106                 axh              = spawn();
107                 axh.draw2d       = func_null;
108                 axh.drawmask     = MASK_NORMAL;
109                 axh.axh_drawflag = DRAWFLAG_ADDITIVE;
110                 axh.axh_fadetime = 0.1;
111                 axh.axh_image    = vCROSS_HINT;
112                 axh.alpha        = 1;
113
114                 AuxiliaryXhairs[axh_id] = axh;
115         }
116
117         axh.move_origin_x = ReadCoord();
118         axh.move_origin_y = ReadCoord();
119         axh.move_origin_z = ReadCoord();
120         axh.colormod_x = ReadByte() / 255;
121         axh.colormod_y = ReadByte() / 255;
122         axh.colormod_z = ReadByte() / 255;
123         axh.cnt    = time;
124         axh.draw2d = AuxiliaryXhair_Draw2D;
125 }
126
127 void Net_VehicleSetup()
128 {
129         int hud_id = ReadByte();
130
131         // Weapon update?
132         if(hud_id > HUD_VEHICLE_LAST)
133         {
134                 weapon2mode = hud_id - HUD_VEHICLE_LAST;
135                 return;
136         }
137
138         // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
139         if(hud_id == 0)
140         {
141                 sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
142                 sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
143                 return;
144         }
145
146         hud_id  = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST);
147
148         // Init auxiliary crosshairs
149         int i;
150         for(i = 0; i < MAX_AXH; ++i)
151         {
152                 entity axh = AuxiliaryXhairs[i];
153
154                 if(axh != world && !wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
155                         remove(axh);
156
157                 axh              = spawn();
158                 axh.draw2d       = func_null;
159                 axh.drawmask     = MASK_NORMAL;
160                 axh.axh_drawflag = DRAWFLAG_NORMAL;
161                 axh.axh_fadetime = 0.1;
162                 axh.axh_image    = vCROSS_HINT;
163                 axh.alpha        = 1;
164                 AuxiliaryXhairs[i] = axh;
165         }
166
167         switch(hud_id)
168         {
169                 case HUD_SPIDERBOT:
170                         AuxiliaryXhairs[0].axh_image = vCROSS_HINT; // Minigun1
171                         AuxiliaryXhairs[1].axh_image = vCROSS_HINT; // Minigun2
172                         break;
173
174                 case HUD_WAKIZASHI:
175                         AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Rocket
176                         break;
177
178                 case HUD_RAPTOR:
179                         AuxiliaryXhairs[1].axh_image = vCROSS_LOCK;
180                         break;
181
182                 case HUD_BUMBLEBEE:
183                         AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Raygun-locked
184                         AuxiliaryXhairs[1].axh_image = vCROSS_TAG; // Gunner1
185                         AuxiliaryXhairs[2].axh_image = vCROSS_TAG; // Gunner2
186                         break;
187
188                 case HUD_BUMBLEBEE_GUN:
189                         AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Plasma cannons
190                         AuxiliaryXhairs[1].axh_image = vCROSS_LOCK; // Raygun
191                         break;
192         }
193 }
194
195 void Vehicles_drawHUD(
196         string modelBase,
197         string modelWeapon1,
198         string modelWeapon2,
199         string iconAmmo1,
200         string iconAmmo2,
201         string crosshair,
202         bool shouldDrawBumbleGunnerCrosshair,
203         bool shouldDrawRaptorBombCrosshair)
204 {
205         if(autocvar_r_letterbox)
206                 return;
207
208         if(scoreboard_showscores)
209                 return;
210
211         // Initialize
212         vector hudSize = '0 0 0';
213         vector hudPos  = '0 0 0';
214         vector tmpSize = '0 0 0';
215         vector tmpPos  = '0 0 0';
216
217         float blinkValue = 0.55 + sin(time * 7) * 0.45;
218
219         float health  = getstati(STAT_VEHICLESTAT_HEALTH)  * 0.01;
220         float shield  = getstati(STAT_VEHICLESTAT_SHIELD)  * 0.01;
221         float energy  = getstati(STAT_VEHICLESTAT_ENERGY)  * 0.01;
222         float ammo1   = getstati(STAT_VEHICLESTAT_AMMO1)   * 0.01;
223         float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01;
224         float ammo2   = getstati(STAT_VEHICLESTAT_AMMO2)   * 0.01;
225         float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
226
227         // HACK to deal with the inconcistent use of the vehicle stats
228         ammo1 = (ammo1) ? ammo1 : energy;
229
230         // Frame
231         hudSize  = draw_getimagesize(vFRAME) * autocvar_cl_vehicles_hudscale;
232         hudPos.x = (vid_conwidth - hudSize.x) / 2;
233         hudPos.y = vid_conheight - hudSize.y;
234
235         drawpic(hudPos, vFRAME, hudSize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
236
237         // Model
238         tmpSize.x = hudSize.x / 3;
239         tmpSize.y = hudSize.y;
240         tmpPos.x  = hudPos.x + hudSize.x / 3;
241         tmpPos.y  = hudPos.y;
242
243         if(health < 0.25)
244                 drawpic(tmpPos, modelBase, tmpSize, '1 0 0' + '0 1 1' * blinkValue, 1, DRAWFLAG_NORMAL);
245         else
246                 drawpic(tmpPos, modelBase, tmpSize, '1 1 1' * health  + '1 0 0' * (1 - health), 1, DRAWFLAG_NORMAL);
247
248         drawpic(tmpPos, modelWeapon1, tmpSize, '1 1 1' * ammo1 + '1 0 0' * (1 - ammo1), 1, DRAWFLAG_NORMAL);
249         drawpic(tmpPos, modelWeapon2, tmpSize, '1 1 1' * ammo2 + '1 0 0' * (1 - ammo2), 1, DRAWFLAG_NORMAL);
250         drawpic(tmpPos, vMODEL_SHIELD, tmpSize, '1 1 1', shield, DRAWFLAG_NORMAL);
251
252         // Health bar
253         tmpSize.y = hudSize.y / 2;
254         tmpPos.x  = hudPos.x + hudSize.x / 24;
255         tmpPos.y  = hudPos.y;
256
257         drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - health)), tmpPos.y, tmpSize.x, tmpSize.y);
258         drawpic(tmpPos, vBAR_HEALTH, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
259
260         // Shield bar
261         tmpPos.y = hudPos.y + hudSize.y / 2;
262
263         drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - shield)), tmpPos.y, tmpSize.x, tmpSize.y);
264         drawpic(tmpPos, vBAR_SHIELD, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
265
266         // Ammo1 bar
267         tmpPos.x = hudPos.x + hudSize.x / 1.6;
268         tmpPos.y = hudPos.y;
269
270         if(ammo1)
271                 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo1, tmpSize.y);
272         else
273                 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload1, tmpSize.y);
274
275         drawpic(tmpPos, vBAR_AMMO1, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
276
277         // Ammo2 bar
278         tmpPos.y = hudPos.y + hudSize.y / 2;
279
280         if(ammo2)
281                 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo2, tmpSize.y);
282         else
283                 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload2, tmpSize.y);
284
285         drawpic(tmpPos, vBAR_AMMO2, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
286         drawresetcliparea();
287
288         // Health icon
289         tmpSize.x = hudSize.x / 6;
290         tmpSize.y = hudSize.y / 2;
291         tmpPos.x  = hudPos.x + hudSize.x / 24;
292         tmpPos.y  = hudPos.y;
293
294         if(health < 0.25)
295         {
296                 if(alarm1time < time)
297                 {
298                         alarm1time = time + 2;
299                         sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
300                 }
301                 drawpic(tmpPos, vICON_HEALTH, tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
302         }
303         else
304         {
305                 if(alarm1time)
306                 {
307                         sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
308                         alarm1time = 0;
309                 }
310                 drawpic(tmpPos, vICON_HEALTH, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
311         }
312
313         // Shield icon
314         tmpPos.y = hudPos.y + hudSize.y / 2;
315
316         if(shield < 0.25)
317         {
318                 if(alarm2time < time)
319                 {
320                         alarm2time = time + 1;
321                         sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
322                 }
323                 drawpic(tmpPos, vICON_SHIELD, tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
324         }
325         else
326         {
327                 if(alarm2time)
328                 {
329                         sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
330                         alarm2time = 0;
331                 }
332                 drawpic(tmpPos, vICON_SHIELD, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
333         }
334
335         // Ammo1 icon
336         tmpPos.x = hudPos.x + hudSize.x * 19 / 24;
337         tmpPos.y = hudPos.y;
338
339         if(ammo1)
340                 drawpic(tmpPos, vICON_AMMO1, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
341         else
342                 drawpic(tmpPos, vICON_AMMO1, tmpSize, '1 1 1', 0.25, DRAWFLAG_NORMAL);
343
344         // Ammo2 icon
345         tmpPos.y = hudPos.y + hudSize.y / 2;
346
347         if(ammo2)
348                 drawpic(tmpPos, vICON_AMMO2, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
349         else
350                 drawpic(tmpPos, vICON_AMMO2, tmpSize, '1 1 1', 0.25, DRAWFLAG_NORMAL);
351
352         // Crosshair
353         tmpSize  = draw_getimagesize(crosshair) * autocvar_cl_vehicles_crosshair_size;
354         tmpPos.x = (vid_conwidth - tmpSize.x) / 2;
355         tmpPos.y = (vid_conheight - tmpSize.y) / 2;
356
357         drawpic(tmpPos, crosshair, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
358
359         // Bumblebee gunner crosshairs
360         if(shouldDrawBumbleGunnerCrosshair)
361         {
362                 tmpSize = '1 1 1' * hud_fontsize;
363                 tmpPos.x = hudPos.x + hudSize.x / 1.5;
364
365                 if(!AuxiliaryXhairs[1].draw2d)
366                 {
367                         tmpPos.y = hudPos.y + hudSize.y / 2 - hudSize.y / 10 - tmpSize.y;
368                         drawstring(tmpPos, _("No right gunner!"), tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
369                 }
370
371                 if(!AuxiliaryXhairs[2].draw2d)
372                 {
373                         tmpPos.y = hudPos.y + hudSize.y / 2 + hudSize.y / 10;
374                         drawstring(tmpPos, _("No left gunner!"), tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
375                 }
376         }
377
378         // Raptor bomb crosshair
379         if(shouldDrawRaptorBombCrosshair && weapon2mode != RSM_FLARE)
380         {
381                 vector where;
382
383                 if(!dropmark)
384                 {
385                         dropmark = spawn();
386                         dropmark.owner = self;
387                         dropmark.gravity = 1;
388                 }
389
390                 if(reload2 == 1)
391                 {
392                         setorigin(dropmark, pmove_org);
393                         dropmark.velocity = pmove_vel;
394                         tracetoss(dropmark, self);
395
396                         where = project_3d_to_2d(trace_endpos);
397
398                         setorigin(dropmark, trace_endpos);
399                         tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size;
400
401                         if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
402                         {
403                                 where.x -= tmpSize.x * 0.5;
404                                 where.y -= tmpSize.y * 0.5;
405                                 where.z = 0;
406                                 drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', 0.9, DRAWFLAG_ADDITIVE);
407                                 drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg
408                         }
409                         dropmark.cnt = time + 5;
410                 }
411                 else
412                 {
413                         if(dropmark.cnt > time)
414                         {
415                                 where = project_3d_to_2d(dropmark.origin);
416                                 tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size * 1.25;
417
418                                 if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
419                                 {
420                                         where.x -= tmpSize.x * 0.5;
421                                         where.y -= tmpSize.y * 0.5;
422                                         where.z = 0;
423                                         drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', 0.9, DRAWFLAG_ADDITIVE);
424                                         drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg
425                                 }
426                         }
427                 }
428         }
429 }
430
431 void CSQC_BUMBLE_HUD()
432 {
433         Vehicles_drawHUD(vMODEL_BUMBLE, vMODEL_BUMBLE_WEAPON1, vMODEL_BUMBLE_WEAPON2, vICON_AMMO1, vICON_AMMO1, vCROSS_HEAL, TRUE, FALSE);
434 }
435
436 void CSQC_BUMBLE_GUN_HUD()
437 {
438         Vehicles_drawHUD(vMODEL_GUNNER, vMODEL_GUNNER_WEAPON1, vNULL, vICON_AMMO1, vNULL, vNULL, TRUE, FALSE);
439 }
440
441 void CSQC_SPIDER_HUD()
442 {
443         string crosshair;
444
445         switch(weapon2mode)
446         {
447                 case SBRM_VOLLY: crosshair = vCROSS_LOCK; break;
448                 case SBRM_GUIDE: crosshair = vCROSS_AIM;  break;
449                 default:         crosshair = vCROSS_TAG;
450         }
451
452         Vehicles_drawHUD(vMODEL_SPIDER, vMODEL_SPIDER_WEAPON1, vMODEL_SPIDER_WEAPON2, vICON_AMMO1, vICON_AMMO2, crosshair, FALSE, FALSE);
453 }
454
455 void CSQC_RAPTOR_HUD()
456 {
457         string crosshair;
458
459         switch(weapon2mode)
460         {
461                 case RSM_FLARE: crosshair = vCROSS_LOCK; break;
462                 default:        crosshair = vCROSS_AIM;
463         }
464
465         Vehicles_drawHUD(vMODEL_RAPTOR, vMODEL_RAPTOR_WEAPON1, vMODEL_RAPTOR_WEAPON2, vICON_AMMO1, vICON_AMMO2, crosshair, FALSE, TRUE);
466 }
467
468 void CSQC_WAKIZASHI_HUD()
469 {
470         Vehicles_drawHUD(vMODEL_RACER, vMODEL_RACER_WEAPON1, vMODEL_RACER_WEAPON2, vICON_AMMO1, vICON_AMMO2, vCROSS_AIM, FALSE, FALSE);
471 }
472
473 void Vehicles_Precache()
474 {
475         precache_model("models/vehicles/bomblet.md3");
476         precache_model("models/vehicles/clusterbomb.md3");
477         precache_model("models/vehicles/clusterbomb_fragment.md3");
478         precache_model("models/vehicles/rocket01.md3");
479         precache_model("models/vehicles/rocket02.md3");
480
481         precache_sound("vehicles/alarm.wav");
482         precache_sound("vehicles/alarm_shield.wav");
483 }
484
485 void RaptorCBShellfragDraw()
486 {
487         if(wasfreed(self))
488                 return;
489
490         Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
491         self.move_avelocity += randomvec() * 15;
492         self.renderflags = 0;
493
494         if(self.cnt < time)
495                 self.alpha = bound(0, self.nextthink - time, 1);
496
497         if(self.alpha < ALPHA_MIN_VISIBLE)
498                 remove(self);
499 }
500
501 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
502 {
503         entity sfrag;
504
505         sfrag = spawn();
506         setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
507         setorigin(sfrag, _org);
508
509         sfrag.move_movetype = MOVETYPE_BOUNCE;
510         sfrag.gravity = 0.15;
511         sfrag.solid = SOLID_CORPSE;
512
513         sfrag.draw = RaptorCBShellfragDraw;
514
515         sfrag.move_origin = sfrag.origin = _org;
516         sfrag.move_velocity = _vel;
517         sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
518         sfrag.angles = self.move_angles = _ang;
519
520         sfrag.move_time = time;
521         sfrag.damageforcescale = 4;
522
523         sfrag.nextthink = time + 3;
524         sfrag.cnt = time + 2;
525         sfrag.alpha = 1;
526         sfrag.drawmask = MASK_NORMAL;
527 }