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