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