1 /*
2 * This file is part of the Colobot: Gold Edition source code
3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see http://gnu.org/licenses
18 */
19
20 #include "level/scoreboard.h"
21
22 #include "common/restext.h"
23 #include "common/stringutils.h"
24
25 #include "level/robotmain.h"
26
27 #include "level/parser/parserline.h"
28
29 #include "object/object.h"
30
31 #include "ui/displaytext.h"
32
33 #include <boost/lexical_cast.hpp>
34
Read(CLevelParserLine * line)35 void CScoreboard::CScoreboardRule::Read(CLevelParserLine* line)
36 {
37 this->score = line->GetParam("score")->AsInt();
38 }
39
Read(CLevelParserLine * line)40 void CScoreboard::CScoreboardKillRule::Read(CLevelParserLine* line)
41 {
42 CScoreboardRule::Read(line);
43 CObjectCondition::Read(line);
44 this->friendlyFire = line->GetParam("friendlyFire")->AsBool(false);
45 }
46
Read(CLevelParserLine * line)47 void CScoreboard::CScoreboardObjectRule::Read(CLevelParserLine* line)
48 {
49 CScoreboardRule::Read(line);
50 CObjectCondition::Read(line);
51 this->winTeam = line->GetParam("winTeam")->AsInt();
52 }
53
Read(CLevelParserLine * line)54 void CScoreboard::CScoreboardEndTakeRule::Read(CLevelParserLine* line)
55 {
56 CScoreboardRule::Read(line);
57 this->team = line->GetParam("team")->AsInt(0);
58 this->order = line->GetParam("order")->AsInt(0);
59 }
60
AddKillRule(std::unique_ptr<CScoreboardKillRule> rule)61 void CScoreboard::AddKillRule(std::unique_ptr<CScoreboardKillRule> rule)
62 {
63 m_rulesKill.push_back(std::move(rule));
64 }
65
AddObjectRule(std::unique_ptr<CScoreboard::CScoreboardObjectRule> rule)66 void CScoreboard::AddObjectRule(std::unique_ptr<CScoreboard::CScoreboardObjectRule> rule)
67 {
68 m_rulesObject.push_back(std::move(rule));
69 }
70
AddEndTakeRule(std::unique_ptr<CScoreboardEndTakeRule> rule)71 void CScoreboard::AddEndTakeRule(std::unique_ptr<CScoreboardEndTakeRule> rule)
72 {
73 m_rulesEndTake.push_back(std::move(rule));
74 }
75
ProcessKill(CObject * target,CObject * killer)76 void CScoreboard::ProcessKill(CObject* target, CObject* killer)
77 {
78 if (killer == nullptr) return;
79 if (killer->GetTeam() == 0) return;
80 for (auto& rule : m_rulesKill)
81 {
82 if ((rule->team == killer->GetTeam() || rule->team == 0) &&
83 killer->GetTeam() != 0 &&
84 rule->CheckForObject(target))
85 {
86 if (killer->GetTeam() == target->GetTeam() && !rule->friendlyFire)
87 continue;
88 AddPoints(killer->GetTeam(), rule->score);
89 }
90 }
91 }
92
UpdateObjectCount()93 void CScoreboard::UpdateObjectCount()
94 {
95 for (auto& rule : m_rulesObject)
96 {
97 assert(rule->winTeam != 0);
98 int count = rule->CountObjects();
99 int countDiff = count - rule->lastCount;
100 if (countDiff != 0)
101 {
102 rule->lastCount = count;
103 AddPoints(rule->winTeam, rule->score * countDiff);
104 }
105 }
106 }
107
ProcessEndTake(int team)108 void CScoreboard::ProcessEndTake(int team)
109 {
110 if (team == 0) return;
111 m_finishCounter++;
112 for (auto& rule : m_rulesEndTake)
113 {
114 if ((rule->team == team || rule->team == 0) &&
115 (rule->order == m_finishCounter || rule->order == 0))
116 {
117 AddPoints(team, rule->score);
118 }
119 }
120 }
121
AddPoints(int team,int points)122 void CScoreboard::AddPoints(int team, int points)
123 {
124 GetLogger()->Info("Team %d earned %d points\n", team, points);
125
126 CRobotMain* main = CRobotMain::GetInstancePointer();
127 std::string text;
128 GetResource(RES_ERR, INFO_TEAM_SCORE, text);
129 text = StrUtils::Format(text.c_str(), main->GetTeamName(team).c_str(), points);
130 main->GetDisplayText()->DisplayText(text.c_str(), Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 10.0f, Ui::TT_WARNING);
131
132 m_score[team].points += points;
133 m_score[team].time = main->GetGameTime();
134 }
135
GetScore(int team)136 CScoreboard::Score CScoreboard::GetScore(int team)
137 {
138 return m_score[team];
139 }
140
SetScore(int team,int points)141 void CScoreboard::SetScore(int team, int points)
142 {
143 m_score[team].points = points;
144 }
145
GetSortType()146 CScoreboard::SortType CScoreboard::GetSortType()
147 {
148 return m_sortType;
149 }
150
SetSortType(SortType type)151 void CScoreboard::SetSortType(SortType type)
152 {
153 m_sortType = type;
154 }
155
GetSortedScores()156 std::vector<std::pair<int, CScoreboard::Score>> CScoreboard::GetSortedScores()
157 {
158 CRobotMain* main = CRobotMain::GetInstancePointer();
159 std::set<int> teams = main->GetAllTeams();
160 std::vector<std::pair<int, Score>> sortedTeams(teams.size());
161 std::transform(teams.begin(), teams.end(), sortedTeams.begin(), [&](int team)
162 {
163 return *m_score.find(team);
164 });
165 if (m_sortType == SortType::SORT_POINTS)
166 {
167 std::sort(sortedTeams.begin(), sortedTeams.end(), [&](std::pair<int, Score> teamA, std::pair<int, Score> teamB)
168 {
169 if (teamA.second.points > teamB.second.points) return true; // Team A have more points than B?
170 if (teamA.second.points < teamB.second.points) return false; // Team A have less points than B?
171
172 return teamA.second.time < teamB.second.time; // Team A scored slower than B?
173 });
174 }
175 return sortedTeams;
176 }
177