Merge branch 'terencehill/spectate_player' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / ammo.qc
1 #include "ammo.qh"
2
3 #include <client/autocvars.qh>
4 #include <client/defs.qh>
5 #include <client/miscfunctions.qh>
6 #include <client/view.qh>
7 #include <common/t_items.qh>
8 #include <common/wepent.qh>
9 #include <common/mutators/mutator/nades/nades.qh>
10
11 // Ammo (#1)
12
13 void DrawNadeProgressBar(vector myPos, vector mySize, float progress, vector color)
14 {
15         HUD_Panel_DrawProgressBar(
16                 myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
17                 mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
18                 autocvar_hud_panel_ammo_progressbar_name,
19                 progress, 0, 0, color,
20                 autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
21 }
22
23 void DrawAmmoItem(vector myPos, vector mySize, int ammoType, bool isCurrent, bool isInfinite)
24 {
25         TC(bool, isCurrent); TC(bool, isInfinite);
26         if(ammoType == RES_NONE)
27                 return;
28
29         // Initialize variables
30
31         int ammo;
32         if(autocvar__hud_configure)
33         {
34                 isCurrent = (ammoType == RES_ROCKETS); // Rockets always current
35                 ammo = 60;
36         }
37         else
38                 ammo = getstati(GetAmmoStat(ammoType));
39
40         if(!isCurrent)
41         {
42                 float scale = bound(0, autocvar_hud_panel_ammo_noncurrent_scale, 1);
43                 myPos = myPos + (mySize - mySize * scale) * 0.5;
44                 mySize = mySize * scale;
45         }
46
47         vector iconPos, textPos;
48         if(autocvar_hud_panel_ammo_iconalign)
49         {
50                 iconPos = myPos + eX * 2 * mySize.y;
51                 textPos = myPos;
52         }
53         else
54         {
55                 iconPos = myPos;
56                 textPos = myPos + eX * mySize.y;
57         }
58
59         bool isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
60
61         vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
62         vector textColor;
63         if(isInfinite)
64                 textColor = '0.2 0.95 0';
65         else if(isShadowed)
66                 textColor = '0 0 0';
67         else if(ammo < 10)
68                 textColor = '0.8 0.04 0';
69         else
70                 textColor = '1 1 1';
71
72         float alpha;
73         if(isCurrent)
74                 alpha = panel_fg_alpha;
75         else if(isShadowed)
76                 alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1) * 0.5;
77         else
78                 alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1);
79
80         string text = isInfinite ? "\xE2\x88\x9E" : ftos(ammo); // Use infinity symbol (U+221E)
81
82         // Draw item
83
84         if(isCurrent)
85                 drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
86
87         if(ammo > 0 && autocvar_hud_panel_ammo_progressbar)
88                 HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x, autocvar_hud_panel_ammo_progressbar_name, ammo/autocvar_hud_panel_ammo_maxammo, 0, 0, textColor, autocvar_hud_progressbar_alpha * alpha, DRAWFLAG_NORMAL);
89
90         if(autocvar_hud_panel_ammo_text)
91                 drawstring_aspect(textPos, text, eX * (2/3) * mySize.x + eY * mySize.y, textColor, alpha, DRAWFLAG_NORMAL);
92
93         drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize.y, iconColor, alpha, DRAWFLAG_NORMAL);
94 }
95
96 int nade_prevstatus;
97 int nade_prevframe;
98 float nade_statuschange_time;
99
100 void HUD_Ammo()
101 {
102         if(hud != HUD_NORMAL) return;
103         if(!autocvar__hud_configure)
104         {
105                 if((!autocvar_hud_panel_ammo) || (spectatee_status == -1))
106                         return;
107                 if(STAT(HEALTH) < 1 && autocvar_hud_panel_ammo_hide_ondeath)
108                         return;
109         }
110
111         HUD_Panel_LoadCvars();
112
113         draw_beginBoldFont();
114
115         vector pos, mySize;
116         pos = panel_pos;
117         mySize = panel_size;
118
119         if (autocvar_hud_panel_ammo_dynamichud)
120                 HUD_Scale_Enable();
121         else
122                 HUD_Scale_Disable();
123         HUD_Panel_DrawBg();
124         if(panel_bg_padding)
125         {
126                 pos += '1 1 0' * panel_bg_padding;
127                 mySize -= '2 2 0' * panel_bg_padding;
128         }
129
130         int rows = 0, columns, row, column;
131         float nade_cnt = STAT(NADE_BONUS), nade_score = STAT(NADE_BONUS_SCORE);
132         bool draw_nades = (nade_cnt > 0 || nade_score > 0);
133         float nade_statuschange_elapsedtime;
134         int total_ammo_count;
135
136         vector ammo_size;
137         if (autocvar_hud_panel_ammo_onlycurrent)
138                 total_ammo_count = 1;
139         else
140                 total_ammo_count = AMMO_COUNT;
141
142         if(draw_nades)
143         {
144                 ++total_ammo_count;
145                 if (nade_cnt != nade_prevframe)
146                 {
147                         nade_statuschange_time = time;
148                         nade_prevstatus = nade_prevframe;
149                         nade_prevframe = nade_cnt;
150                 }
151         }
152         else
153                 nade_prevstatus = nade_prevframe = nade_statuschange_time = 0;
154
155         rows = HUD_GetRowCount(total_ammo_count, mySize, 3);
156         columns = ceil((total_ammo_count)/rows);
157         ammo_size = vec2(mySize.x / columns, mySize.y / rows);
158
159         vector offset = '0 0 0';
160         float newSize;
161         if(ammo_size.x/ammo_size.y > 3)
162         {
163                 newSize = 3 * ammo_size.y;
164                 offset.x = ammo_size.x - newSize;
165                 pos.x += offset.x/2;
166                 ammo_size.x = newSize;
167         }
168         else
169         {
170                 newSize = 1/3 * ammo_size.x;
171                 offset.y = ammo_size.y - newSize;
172                 pos.y += offset.y/2;
173                 ammo_size.y = newSize;
174         }
175
176         entity wepent = viewmodels[0]; // TODO: unhardcode
177
178         Weapon wep = wepent.switchweapon;
179         int i;
180         bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_AMMO);
181         row = column = 0;
182         if(autocvar_hud_panel_ammo_onlycurrent)
183         {
184                 if(autocvar__hud_configure)
185                 {
186                         DrawAmmoItem(pos, ammo_size, RES_ROCKETS, true, false);
187                 }
188                 else
189                 {
190                         DrawAmmoItem(
191                                 pos,
192                                 ammo_size,
193                                 wep.ammo_type,
194                                 true,
195                                 infinite_ammo
196                         );
197                 }
198
199                 ++row;
200                 if(row >= rows)
201                 {
202                         row = 0;
203                         column = column + 1;
204                 }
205         }
206         else
207         {
208                 int ammotype;
209                 row = column = 0;
210                 for(i = 0; i < AMMO_COUNT; ++i)
211                 {
212                         ammotype = GetAmmoTypeFromNum(i);
213                         DrawAmmoItem(
214                                 pos + vec2(column * (ammo_size.x + offset.x), row * (ammo_size.y + offset.y)),
215                                 ammo_size,
216                                 ammotype,
217                                 (wep.ammo_type == ammotype),
218                                 infinite_ammo
219                         );
220
221                         ++row;
222                         if(row >= rows)
223                         {
224                                 row = 0;
225                                 column = column + 1;
226                         }
227                 }
228         }
229
230         if (draw_nades)
231         {
232                 nade_statuschange_elapsedtime = time - nade_statuschange_time;
233
234                 float f = bound(0, nade_statuschange_elapsedtime*2, 1);
235
236                 DrawAmmoNades(pos + vec2(column * (ammo_size.x + offset.x), row * (ammo_size.y + offset.y)), ammo_size, nade_prevstatus < nade_cnt && nade_cnt != 0 && f < 1, f);
237         }
238
239         draw_endBoldFont();
240 }