]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hud/panel/powerups.qc
Purge autocvars.qh from the client-side codebase, cvars are defined in the headers...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / powerups.qc
1 #include "powerups.qh"
2
3 #include <client/draw.qh>
4 #include <common/items/_mod.qh>
5 #include <common/util.qh>
6
7 // Powerups (#2)
8
9 void HUD_Powerups_Export(int fh)
10 {
11         // allow saving cvars that aesthetically change the panel into hud skin files
12         HUD_Write_Cvar("hud_panel_powerups_iconalign");
13         HUD_Write_Cvar("hud_panel_powerups_baralign");
14         HUD_Write_Cvar("hud_panel_powerups_progressbar");
15         HUD_Write_Cvar("hud_panel_powerups_text");
16 }
17
18 // Powerup item fields (reusing existing fields)
19 .string message;  // Human readable name
20 .string netname;  // Icon name
21 .vector colormod; // Color
22 .float count;     // Time left
23 .float lifetime;  // Maximum time
24
25 entity powerupItems;
26 int powerupItemsCount;
27
28 void resetPowerupItems()
29 {
30         entity item;
31         for(item = powerupItems; item; item = item.chain)
32                 item.count = 0;
33
34         powerupItemsCount = 0;
35 }
36
37 void addPowerupItem(string name, string icon, vector color, float currentTime, float lifeTime)
38 {
39         if(!powerupItems)
40                 powerupItems = spawn();
41
42         entity item;
43         for(item = powerupItems; item.count; item = item.chain)
44                 if(!item.chain)
45                         item.chain = spawn();
46
47         item.message  = name;
48         item.netname  = icon;
49         item.colormod = color;
50         item.count    = currentTime;
51         item.lifetime = lifeTime;
52
53         ++powerupItemsCount;
54 }
55
56 int getPowerupItemAlign(int align, int column, int row, int columns, int rows, bool isVertical)
57 {
58         TC(int, align); TC(int, column); TC(int, row); TC(int, columns); TC(int, rows); TC(bool, isVertical);
59         if(align < 2)
60                 return align;
61
62         bool isTop    =  isVertical && rows > 1 && row == 0;
63         bool isBottom =  isVertical && rows > 1 && row == rows-1;
64         bool isLeft   = !isVertical && columns > 1 && column == 0;
65         bool isRight  = !isVertical && columns > 1 && column == columns-1;
66
67         if(isTop    || isLeft)  return (align == 2) ? 1 : 0;
68         if(isBottom || isRight) return (align == 2) ? 0 : 1;
69
70         return 2;
71 }
72
73 void HUD_Powerups()
74 {
75         int allItems = STAT(ITEMS);
76         int allBuffs = STAT(BUFFS);
77         float strengthTime, shieldTime, superTime;
78
79         // Initialize items
80         if(!autocvar__hud_configure)
81         {
82                 if((!autocvar_hud_panel_powerups) || (spectatee_status == -1))
83                         return;
84                 if(STAT(HEALTH) <= 0 && autocvar_hud_panel_powerups_hide_ondeath)
85                         return;
86                 //if(!(allItems & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON)) && !allBuffs) return;
87
88                 strengthTime = bound(0, STAT(STRENGTH_FINISHED) - time, 99);
89                 shieldTime = bound(0, STAT(INVINCIBLE_FINISHED) - time, 99);
90                 superTime = bound(0, STAT(SUPERWEAPONS_FINISHED) - time, 99);
91
92                 if(allItems & IT_UNLIMITED_SUPERWEAPONS)
93                         superTime = 99;
94
95                 // Prevent stuff to show up on mismatch that will be fixed next frame
96                 if(!(allItems & IT_SUPERWEAPON))
97                         superTime = 0;
98         }
99         else
100         {
101                 strengthTime = 15;
102                 shieldTime = 27;
103                 superTime = 13;
104                 allBuffs = 0;
105         }
106
107         // Add items to linked list
108         resetPowerupItems();
109
110         if(strengthTime)
111                 addPowerupItem("Strength", "strength", autocvar_hud_progressbar_strength_color, strengthTime, 30);
112         if(shieldTime)
113                 addPowerupItem("Shield", "shield", autocvar_hud_progressbar_shield_color, shieldTime, 30);
114         if(superTime && !(allItems & IT_UNLIMITED_SUPERWEAPONS))
115                 addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
116
117         MUTATOR_CALLHOOK(HUD_Powerups_add);
118
119         if(!powerupItemsCount)
120                 return;
121
122         // Draw panel background
123         HUD_Panel_LoadCvars();
124
125         if (autocvar_hud_panel_powerups_dynamichud)
126                 HUD_Scale_Enable();
127         else
128                 HUD_Scale_Disable();
129         HUD_Panel_DrawBg();
130
131         // Set drawing area
132         vector pos = panel_pos;
133         vector size = panel_size;
134         bool isVertical = size.y > size.x;
135
136         if(panel_bg_padding)
137         {
138                 pos += '1 1 0' * panel_bg_padding;
139                 size -= '2 2 0' * panel_bg_padding;
140         }
141
142         // Find best partitioning of the drawing area
143         const float DESIRED_ASPECT = 6;
144         float aspect = 0, a;
145         int columns = 0, c;
146         int rows = 0, r;
147         int i = 1;
148
149         do
150         {
151                 c = floor(powerupItemsCount / i);
152                 r = ceil(powerupItemsCount / c);
153                 a = isVertical ? (size.y/r) / (size.x/c) : (size.x/c) / (size.y/r);
154
155                 if(i == 1 || fabs(DESIRED_ASPECT - a) < fabs(DESIRED_ASPECT - aspect))
156                 {
157                         aspect = a;
158                         columns = c;
159                         rows = r;
160                 }
161         }
162         while(++i <= powerupItemsCount);
163
164         // Prevent single items from getting too wide
165         if(powerupItemsCount == 1 && aspect > DESIRED_ASPECT)
166         {
167                 if(isVertical)
168                 {
169                         size.y *= 0.5;
170                         pos.y += size.y * 0.5;
171                 }
172                 else
173                 {
174                         size.x *= 0.5;
175                         pos.x += size.x * 0.5;
176                 }
177         }
178
179         // Draw items from linked list
180         vector itemPos = pos;
181         vector itemSize = vec2(size.x / columns, size.y / rows);
182         vector textColor = '1 1 1';
183
184         int fullSeconds = 0;
185         int align = 0;
186         int column = 0;
187         int row = 0;
188
189         draw_beginBoldFont();
190         for(entity item = powerupItems; item.count; item = item.chain)
191         {
192                 itemPos = vec2(pos.x + column * itemSize.x, pos.y + row * itemSize.y);
193
194                 // Draw progressbar
195                 if(autocvar_hud_panel_powerups_progressbar)
196                 {
197                         align = getPowerupItemAlign(autocvar_hud_panel_powerups_baralign, column, row, columns, rows, isVertical);
198                         HUD_Panel_DrawProgressBar(itemPos, itemSize, "progressbar", item.count / item.lifetime, isVertical, align, item.colormod, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
199                 }
200
201                 // Draw icon and text
202                 if(autocvar_hud_panel_powerups_text)
203                 {
204                         align = getPowerupItemAlign(autocvar_hud_panel_powerups_iconalign, column, row, columns, rows, isVertical);
205                         fullSeconds = ceil(item.count);
206                         textColor = '0.6 0.6 0.6' + (item.colormod * 0.4);
207
208                         if(item.count > 1)
209                                 DrawNumIcon(itemPos, itemSize, fullSeconds, item.netname, isVertical, align, textColor, panel_fg_alpha);
210                         if(item.count <= 5)
211                                 DrawNumIcon_expanding(itemPos, itemSize, fullSeconds, item.netname, isVertical, align, textColor, panel_fg_alpha, bound(0, (fullSeconds - item.count) / 0.5, 1));
212                 }
213
214                 // Determine next section
215                 if(isVertical)
216                 {
217                         if(++column >= columns)
218                         {
219                                 column = 0;
220                                 ++row;
221                         }
222                 }
223                 else
224                 {
225                         if(++row >= rows)
226                         {
227                                 row = 0;
228                                 ++column;
229                         }
230                 }
231         }
232         draw_endBoldFont();
233 }