1 /* SpaceportPanel.cpp
2 Copyright (c) 2014 by Michael Zahniser
3
4 Endless Sky is free software: you can redistribute it and/or modify it under the
5 terms of the GNU General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any later version.
7
8 Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
9 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 PARTICULAR PURPOSE. See the GNU General Public License for more details.
11 */
12
13 #include "SpaceportPanel.h"
14
15 #include "text/alignment.hpp"
16 #include "Color.h"
17 #include "text/FontSet.h"
18 #include "GameData.h"
19 #include "Interface.h"
20 #include "News.h"
21 #include "Planet.h"
22 #include "PlayerInfo.h"
23 #include "Point.h"
24 #include "Random.h"
25 #include "UI.h"
26
27 using namespace std;
28
29
30
SpaceportPanel(PlayerInfo & player)31 SpaceportPanel::SpaceportPanel(PlayerInfo &player)
32 : player(player)
33 {
34 SetTrapAllEvents(false);
35
36 text.SetFont(FontSet::Get(14));
37 text.SetAlignment(Alignment::JUSTIFIED);
38 text.SetWrapWidth(480);
39 text.Wrap(player.GetPlanet()->SpaceportDescription());
40
41 // Query the news interface to find out the wrap width.
42 // TODO: Allow Interface to handle wrapped text directly.
43 const Interface *newsUi = GameData::Interfaces().Get("news");
44 portraitWidth = newsUi->GetBox("message portrait").Width();
45 normalWidth = newsUi->GetBox("message").Width();
46 newsMessage.SetFont(FontSet::Get(14));
47 }
48
49
50
UpdateNews()51 void SpaceportPanel::UpdateNews()
52 {
53 const News *news = PickNews();
54 if(!news)
55 return;
56 hasNews = true;
57
58 // Randomly pick which portrait, if any, is to be shown. Depending on if
59 // this news has a portrait, different interface information gets filled in.
60 auto portrait = news->Portrait();
61 // Cache the randomly picked results until the next update is requested.
62 hasPortrait = portrait;
63 newsInfo.SetSprite("portrait", portrait);
64 newsInfo.SetString("name", news->Name() + ':');
65 newsMessage.SetWrapWidth(hasPortrait ? portraitWidth : normalWidth);
66 newsMessage.Wrap(news->Message());
67 }
68
69
70
Step()71 void SpaceportPanel::Step()
72 {
73 if(GetUI()->IsTop(this))
74 {
75 Mission *mission = player.MissionToOffer(Mission::SPACEPORT);
76 // Special case: if the player somehow got to the spaceport before all
77 // landing missions were offered, they can still be offered here:
78 if(!mission)
79 mission = player.MissionToOffer(Mission::LANDING);
80 if(mission)
81 mission->Do(Mission::OFFER, player, GetUI());
82 else
83 player.HandleBlockedMissions(Mission::SPACEPORT, GetUI());
84 }
85 }
86
87
88
Draw()89 void SpaceportPanel::Draw()
90 {
91 if(player.IsDead())
92 return;
93
94 text.Draw(Point(-300., 80.), *GameData::Colors().Get("bright"));
95
96 if(hasNews)
97 {
98 const Interface *newsUi = GameData::Interfaces().Get("news");
99 newsUi->Draw(newsInfo);
100 // Depending on if the news has a portrait, the interface box that
101 // gets filled in changes.
102 newsMessage.Draw(newsUi->GetBox(hasPortrait ? "message portrait" : "message").TopLeft(),
103 *GameData::Colors().Get("medium"));
104 }
105 }
106
107
108
109 // Pick a random news object that applies to the player's planets and conditions.
110 // If there is no applicable news, this returns null.
PickNews() const111 const News *SpaceportPanel::PickNews() const
112 {
113 vector<const News *> matches;
114 const Planet *planet = player.GetPlanet();
115 const map<string, int64_t> &conditions = player.Conditions();
116 for(const auto &it : GameData::SpaceportNews())
117 if(!it.second.IsEmpty() && it.second.Matches(planet, conditions))
118 matches.push_back(&it.second);
119
120 return matches.empty() ? nullptr : matches[Random::Int(matches.size())];
121 }
122