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