1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 /* interface headers */
14 #include "ShotStats.h"
15
16 /* common implementation headers */
17 #include "FontManager.h"
18 #include "TextUtils.h"
19
20 /* local implementation headers */
21 #include "ShotStatsDefaultKey.h"
22 #include "HUDDialogStack.h"
23 #include "HUDuiLabel.h"
24 #include "LocalPlayer.h"
25 #include "Roster.h"
26
ShotStats()27 ShotStats::ShotStats() : HUDDialog()
28 {
29 std::vector<HUDuiControl*>& listHUD = getControls();
30
31 // add title
32 createLabel("Shot Statistics", listHUD);
33
34 // key
35 createLabel("Shots Hit/Fired", listHUD);
36
37 columns = 11;
38 rows = 0;
39
40 visible = false;
41
42 // section headings (upper)
43 createLabel("", listHUD);
44 createLabel("", listHUD);
45 createLabel("", listHUD);
46 createLabel("", listHUD);
47 createLabel("", listHUD);
48 createLabel("", listHUD);
49 createLabel("Super", listHUD);
50 createLabel("Shock", listHUD);
51 createLabel("", listHUD);
52 createLabel("Fave.", listHUD);
53 createLabel("Best", listHUD);
54 ++rows;
55
56 // section headings (lower)
57 createLabel("Player", listHUD);
58 createLabel("Hit%", listHUD);
59 createLabel("Total", listHUD);
60 createLabel("Norm", listHUD);
61 createLabel("GM", listHUD);
62 createLabel("Laser", listHUD);
63 createLabel("Bullet", listHUD);
64 createLabel("Wave", listHUD);
65 createLabel("Thief", listHUD);
66 createLabel("Flag", listHUD);
67 createLabel("Flag", listHUD);
68 ++rows;
69
70 staticLabelCount = listHUD.size();
71
72 initNavigation(listHUD, 1, 1);
73 }
74
~ShotStats()75 ShotStats::~ShotStats()
76 {
77 }
78
refresh()79 void ShotStats::refresh()
80 {
81 if (!visible)
82 return;
83
84 std::vector<HUDuiControl*>& listHUD = getControls();
85
86 // Delete all the controls apart from the headings
87 const int count = listHUD.size();
88 for (int i = staticLabelCount; i < count; i++)
89 delete listHUD[i];
90 listHUD.erase(listHUD.begin() + staticLabelCount, listHUD.end());
91
92 // my statistics first
93 LocalPlayer* myTank = LocalPlayer::getMyTank();
94 if (myTank->getTeam() != ObserverTeam)
95 addStats((Player*)myTank, listHUD);
96
97 // add statistics for each player
98 for (int i = 0; i < curMaxPlayers; ++i)
99 {
100 if (remotePlayers[i] && (remotePlayers[i]->getTeam() != ObserverTeam))
101 addStats((Player*)remotePlayers[i], listHUD);
102 }
103
104 resize(HUDDialog::getWidth(), HUDDialog::getHeight());
105 }
106
createLabel(const std::string & str,std::vector<HUDuiControl * > & _list)107 void ShotStats::createLabel(const std::string &str,
108 std::vector<HUDuiControl*> &_list)
109 {
110 HUDuiLabel* control = new HUDuiLabel;
111 control->setFontFace(getFontFace());
112 control->setString(str);
113 _list.push_back(control);
114 }
115
addStats(Player * _player,std::vector<HUDuiControl * > & _list)116 void ShotStats::addStats(Player *_player, std::vector<HUDuiControl*> &_list)
117 {
118 const ShotStatistics* stats = _player->getShotStatistics();
119 createLabel(_player->getCallSign(), _list);
120
121 createLabel(TextUtils::format("%2d%%", stats->getTotalPerc()), _list);
122 createLabel(TextUtils::format("%d/%d", stats->getTotalHit(),
123 stats->getTotalFired()), _list);
124 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Null),
125 stats->getFired(Flags::Null)), _list);
126 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::GuidedMissile),
127 stats->getFired(Flags::GuidedMissile)), _list);
128 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Laser),
129 stats->getFired(Flags::Laser)), _list);
130 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::SuperBullet),
131 stats->getFired(Flags::SuperBullet)), _list);
132 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::ShockWave),
133 stats->getFired(Flags::ShockWave)), _list);
134 createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Thief),
135 stats->getFired(Flags::Thief)), _list);
136
137 std::string flagName = stats->getFavoriteFlag()->flagAbbv;
138 if (flagName.empty())
139 flagName = "None";
140 createLabel(flagName, _list);
141
142 flagName = stats->getBestFlag()->flagAbbv;
143 if (flagName.empty())
144 flagName = "None";
145 createLabel(flagName, _list);
146
147 ++rows;
148 }
149
getFontFace()150 int ShotStats::getFontFace()
151 {
152 // create font
153 return FontManager::instance().getFaceID(BZDB.get("sansSerifFont"));
154 }
155
getDefaultKey()156 HUDuiDefaultKey* ShotStats::getDefaultKey()
157 {
158 return ShotStatsDefaultKey::getInstance();
159 }
160
execute()161 void ShotStats::execute()
162 {
163 HUDDialogStack::get()->pop();
164 }
165
dismiss()166 void ShotStats::dismiss()
167 {
168 visible = false;
169 }
170
show()171 void ShotStats::show()
172 {
173 visible = true;
174
175 refresh();
176 }
177
resize(int _width,int _height)178 void ShotStats::resize(int _width, int _height)
179 {
180 HUDDialog::resize(_width, _height);
181
182 // Reposition everything -- that's gonna be a challenge!
183
184 FontManager &fm = FontManager::instance();
185
186 // set up table
187 // total width / (number of columns + 3 columns extra for player name + 2 columns margin)
188 const float columnWidth = _width / (columns + 5.0f);
189 const float fontSize = (float) columnWidth / 6;
190 const float rowHeight = fm.getStrHeight(getFontFace(), fontSize, " ") * 1.2f;
191
192 // center title
193 const float titleFontSize = (float)_height / 15.0f;
194 std::vector<HUDuiControl*>& listHUD = getControls();
195 HUDuiLabel* title = (HUDuiLabel*)listHUD[0];
196 title->setFontSize(titleFontSize);
197 const float titleWidth = fm.getStrLength(getFontFace(), titleFontSize, title->getString());
198 const float titleHeight = fm.getStrHeight(getFontFace(), titleFontSize, " ");
199 const float titleY = (float)_height - titleHeight;
200 float x = 0.5f * ((float)_width - titleWidth);
201 float y = titleY;
202 title->setPosition(x, y);
203
204 // center key
205 HUDuiLabel* key = (HUDuiLabel*)listHUD[1];
206 key->setFontSize(fontSize);
207 const float keyCenter = ((columns / 2) + 4) * columnWidth;
208 const float keyWidth = fm.getStrLength(getFontFace(), fontSize, key->getString());
209 const float keyY = titleY - 2 * fm.getStrHeight(getFontFace(), fontSize, " ");
210 y = keyY;
211 x = keyCenter - 0.5f * keyWidth;
212 key->setPosition(x, y);
213
214 for (int i = 2; i < (int)listHUD.size(); ++i)
215 {
216 // determine row & column (i - 2 to account for title & key)
217 int row = (i - 2) / columns;
218 int column = (i - 2) - (columns * row) + 1;
219 // account for 3 extra columns in player name
220 if (column > 1)
221 column = column + 3;
222
223 // find coordinates corresponding to this row & column
224 x = column * columnWidth;
225 y = keyY - (row + 1) * rowHeight;
226
227 // move label to the specified coordinates
228 listHUD[i]->setFontSize(fontSize);
229 listHUD[i]->setPosition(x, y);
230 }
231
232 }
233
234 // Local Variables: ***
235 // mode: C++ ***
236 // tab-width: 4 ***
237 // c-basic-offset: 4 ***
238 // indent-tabs-mode: nil ***
239 // End: ***
240 // ex: shiftwidth=4 tabstop=4
241