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