1 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 3 of the License, or
6 // (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #include "vectormap.h"
19 #include "gui/image-helpers.h"
23 #include "playerlist.h"
24 #include "GraphicsCache.h"
26 #include "LocationBox.h"
27 #include "shieldsetlist.h"
29 VectorMap::VectorMap(City *c, enum ShowVectoring v, bool see_opponents_production)
31 d_see_opponents_production = see_opponents_production;
34 click_action = CLICK_SELECTS;
37 void VectorMap::draw_planted_standard(Vector<int> flag)
39 //it can't possibly be fogged
40 GraphicsCache *gc = GraphicsCache::getInstance();
45 start = mapToSurface(start);
47 PixMask *heropic = gc->getSmallHeroPic(true);
48 heropic->blit_centered(surface, start);
51 void VectorMap::draw_city (City *c, guint32 &type, bool &prod)
53 if (c->isVisible(Playerlist::getViewingplayer()) == false)
55 GraphicsCache *gc = GraphicsCache::getInstance();
57 if (c->isBurnt() == true)
58 tmp = gc->getSmallRuinedCityPic ();
59 //else if(type == 4 && prod == false)
60 //tmp = gc->getProdShieldPic (type, prod);
63 if (Playerlist::getInstance()->getViewingplayer() != c->getOwner())
65 guint32 s = GameMap::getInstance()->getShieldset()->getId();
66 tmp = gc->getShieldPic (s, 0, c->getOwner()->getId());
69 tmp = gc->getProdShieldPic (type, prod);
75 start = mapToSurface(start);
78 tmp->blit_centered(surface, start);
81 void VectorMap::draw_cities (std::list<City*> citylist, guint32 type)
85 std::list<City*>::iterator it;
86 for (it = citylist.begin(); it != citylist.end(); it++)
91 case CLICK_CHANGES_DESTINATION:
92 if ((*it)->canAcceptMoreVectoring() == false)
94 prod = false; //the inn is full
99 if ((*it)->getActiveProductionSlot() == -1)
106 if ((*it)->getActiveProductionSlot() == -1)
112 draw_city ((*it), type, prod);
116 void VectorMap::draw_vectoring_line(Vector<int> src, Vector<int> dest, bool to)
118 Vector<int> start = src;
119 Vector <int> end = dest;
120 start = mapToSurface(start);
121 end = mapToSurface(end);
122 Gdk::Color line_color = Gdk::Color();
124 line_color.set_rgb_p(252.0/255.0, 236.0/255.0,
127 line_color.set_rgb_p(252.0/255.0, 160.0/255.0, 0);
128 draw_line(start.x, start.y, end.x, end.y, line_color);
130 void VectorMap::draw_vectoring_line_from_here_to (Vector<int> dest)
132 draw_vectoring_line (city->getPos(), dest, true);
135 void VectorMap::draw_vectoring_line_to_here_from (Vector<int> src)
137 draw_vectoring_line (src, city->getPos(), false);
140 void VectorMap::draw_lines (std::list<City*> srcs, std::list<City*> dests)
142 Citylist *cl = Citylist::getInstance();
144 std::list<City*>::iterator it;
145 std::list<City*>::iterator cit;
146 //yellow lines first. cities vectoring units to their destinations.
147 for (it = srcs.begin(); it != srcs.end(); it++)
149 if ((*it)->getVectoring() == Vector<int>(-1, -1))
151 if ((*it)->isVisible(Playerlist::getViewingplayer()) == false)
153 City *c = cl->getNearestObjectBefore((*it)->getVectoring(), 2);
157 end = planted_standard;
159 Vector<int> pos = (*it)->getVectoring();
160 draw_vectoring_line ((*it)->getPos(), end, true);
162 //orange lines next. cities receiving units from their sources.
163 for (it = dests.begin(); it != dests.end(); it++)
165 //who is vectoring to this (*it) city?
166 std::list<City*> sources = cl->getCitiesVectoringTo(*it);
167 for (cit = sources.begin(); cit != sources.end(); cit++)
168 draw_vectoring_line ((*it)->getPos(), (*cit)->getPos(), false);
172 void VectorMap::after_draw()
178 Citylist *cl = Citylist::getInstance();
179 std::list<City*> dests; //destination cities
180 std::list<City*> srcs; //source cities
183 flag = GameMap::getInstance()->findPlantedStandard(city->getOwner());
184 planted_standard = flag;
186 //only show cities that can accept more vectoring when
187 //the click action is vector
189 std::list<City*> sources;
191 if (click_action == CLICK_CHANGES_DESTINATION)
192 sources = cl->getCitiesVectoringTo(city);
194 // draw special shield for every city that player owns.
195 for (Citylist::iterator it = cl->begin(); it != cl->end(); it++)
197 if ((*it)->getOwner() == Playerlist::getViewingplayer())
200 if ((*it)->getActiveProductionSlot() == -1)
204 if (show_vectoring == SHOW_ALL_VECTORING)
206 // first pass, identify every city that's a source or dest
207 if ((*it)->getVectoring() != Vector<int>(-1, -1))
209 City *c = cl->getNearestCity((*it)->getVectoring(), 2);
212 srcs.push_back((*it));
214 //paint them all as away first, and then overwrite them
215 //later in the second pass.
220 //is this the originating city?
221 if ((*it)->getId() == city->getId())
223 //then it's a "home" city.
226 //is this the city i'm vectoring to?
227 else if (city->getVectoring() != Vector<int>(-1, -1) &&
228 cl->getNearestCity(city->getVectoring(), 2)->getId() ==
229 (*it)->getId() && show_vectoring != SHOW_NO_VECTORING)
231 // then it's a "destination" city.
234 //is this a city that is vectoring to me?
235 else if ((*it)->getVectoring() != Vector<int>(-1, -1) &&
236 cl->getNearestCity((*it)->getVectoring(), 2)->getId() ==
237 city->getId() && show_vectoring != SHOW_NO_VECTORING)
239 //otherwise it's just another city, "away" from me
242 //show it as a ruined city if we can't vector to it.
243 if (click_action == CLICK_VECTORS && (*it)->canAcceptMoreVectoring() == false)
246 type = 4; //the inn is full
248 if (click_action == CLICK_CHANGES_DESTINATION)
250 if ((*it)->canAcceptMoreVectoring (sources.size()) == false)
252 prod = false; //the inn is full
257 draw_city ((*it), type, prod);
263 draw_city ((*it), type, prod); //an impossible combo
267 //second pass, identify all the destination and source cities
268 if (show_vectoring == SHOW_ALL_VECTORING)
270 draw_cities (dests, 2);
271 draw_cities (srcs, 3);
274 if (show_vectoring == SHOW_ORIGIN_CITY_VECTORING && click_action == CLICK_SELECTS)
276 // draw lines from origination to city/planted standard
277 for (Citylist::iterator it = cl->begin(); it != cl->end(); it++)
279 if ((*it)->isVisible(Playerlist::getViewingplayer()) == false)
281 if ((*it)->getOwner() != city->getOwner())
283 if ((*it)->getVectoring() == Vector<int>(-1, -1))
285 if ((*it)->getVectoring() == planted_standard)
288 //is this a city that is vectoring to me?
289 if (city->contains((*it)->getVectoring()))
290 draw_vectoring_line_to_here_from((*it)->getPos());
292 // draw line from city to destination
293 if (city->getVectoring().x != -1)
294 draw_vectoring_line_from_here_to(city->getVectoring());
296 else if (show_vectoring == SHOW_ALL_VECTORING && click_action == CLICK_SELECTS)
297 draw_lines (srcs, dests);
299 if (flag.x != -1 && flag.y != -1)
300 draw_planted_standard(flag);
302 draw_square_around_active_city();
303 map_changed.emit(surface);
306 void VectorMap::draw_square_around_active_city()
308 Gdk::Color box_color = Gdk::Color();
309 box_color.set_rgb_p(252.0/255.0, 1.0, 1.0);
310 Vector<int> start = city->getPos();
311 start = mapToSurface(start);
312 std::string s = GameMap::getInstance()->getShieldset()->getSubDir();
313 Shieldset *ss = Shieldsetlist::getInstance()->getShieldset(s);
314 guint32 width = ss->getSmallWidth();
315 guint32 height = ss->getSmallHeight();
316 start -= Vector<int>(width,height)/2;
317 Vector<int> end = start + Vector<int>(width,height);
318 draw_rect (start.x-3, start.y-3, end.x-start.x+4, end.y-start.y+4, box_color);
321 void VectorMap::mouse_button_event(MouseButtonEvent e)
323 Player *active = Playerlist::getActiveplayer();
324 if (e.button == MouseButtonEvent::LEFT_BUTTON &&
325 e.state == MouseButtonEvent::PRESSED)
327 Citylist *cl = Citylist::getInstance();
330 dest = mapFromScreen(e.pos);
332 switch (click_action)
336 nearestCity = cl->getNearestVisibleFriendlyCity(dest, 4);
337 if (nearestCity == NULL)
339 //no city near there. are we close to the planted standard?
340 Vector<int>flag = planted_standard;
341 if (planted_standard.x != -1 && planted_standard.y != -1)
343 unsigned int dist = 4;
344 LocationBox loc(dest - Vector<int>(dist,dist), dist * 2);
345 if (loc.contains(flag))
346 dest = planted_standard;
351 return; //no cities, no planted flag
353 else if (nearestCity == city)
354 /* clicking on own city, makes vectoring stop */
355 dest = Vector<int>(-1, -1);
357 if (dest != Vector<int>(-1, -1) && dest != planted_standard &&
360 //make sure that dest is the top left tile of the city
361 dest = nearestCity->getPos();
363 if (dest != city->getVectoring() && dest != Vector<int>(-1, -1))
365 if (active->vectorFromCity(city, dest) == true)
366 destination_chosen.emit(dest);
367 setClickAction(CLICK_SELECTS);
368 draw(Playerlist::getViewingplayer());
370 else if (dest == Vector<int>(-1, -1)) //stop vectoring
372 if (active->vectorFromCity(city, dest) == true)
373 destination_chosen.emit(dest);
374 setClickAction(CLICK_SELECTS);
375 draw(Playerlist::getViewingplayer());
379 if (d_see_opponents_production == true)
380 nearestCity = cl->getNearestVisibleCity(dest, 4);
382 nearestCity = cl->getNearestVisibleFriendlyCity(dest, 4);
383 if (nearestCity == NULL)
386 draw(Playerlist::getViewingplayer());
388 case CLICK_CHANGES_DESTINATION:
389 nearestCity = cl->getNearestVisibleFriendlyCity(dest, 4);
390 if (nearestCity == NULL)
392 //no city near there. are we close to the planted standard?
393 Vector<int>flag = planted_standard;
394 if (planted_standard.x != -1 && planted_standard.y != -1)
396 unsigned int dist = 4;
397 LocationBox loc(dest - Vector<int>(dist,dist), dist * 2);
398 if (loc.contains(flag))
399 dest = planted_standard;
404 return; //no cities, no planted flag
406 else if (nearestCity == city)
407 /* clicking on own city, makes vectoring stop */
408 dest = Vector<int>(-1, -1);
410 dest = nearestCity->getPos();
412 if (dest == Vector<int>(-1, -1)) //stop vectoring
414 //we were doing change destination,
415 //and we clicked back on our own city
416 //this is the same thing as a cancel.
417 destination_chosen.emit(dest);
418 setClickAction(CLICK_SELECTS);
419 draw(Playerlist::getViewingplayer());
422 bool is_source_city = false;
423 std::list<City*> sources = cl->getCitiesVectoringTo(city);
424 std::list<City*>::iterator cit = sources.begin();
425 for (;cit != sources.end(); cit++)
427 if ((*cit)->contains(dest))
429 is_source_city = true;
433 //if it's not one of our sources, then select it
434 //why do we care if it's one of our sources anyway?
435 if (is_source_city == false)
437 if (active->changeVectorDestination(city->getPos(), dest) == true)
438 destination_chosen.emit(dest);
439 setClickAction(CLICK_SELECTS);
440 draw(Playerlist::getViewingplayer());
441 if (dest != planted_standard)
443 draw(Playerlist::getViewingplayer());
450 void VectorMap::setCity(City *c)
453 draw(Playerlist::getViewingplayer());