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