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