1 // Copyright (C) 2007 Ole Laursen
2 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include <glibmm/timeval.h>
25 #include "gamebigmap.h"
36 #include "bridgelist.h"
38 #include "playerlist.h"
41 #include "GraphicsCache.h"
44 #include "LocationBox.h"
45 #include "Configuration.h"
46 #include "gui/image-helpers.h"
47 #include "PathCalculator.h"
48 #include "stacktile.h"
55 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
60 // controls speed of selector rotation
61 int selection_timeout = TIMER_BIGMAP_SELECTOR;
64 GameBigMap::GameBigMap(bool intense_combat, bool see_opponents_production,
65 bool see_opponents_stacks, bool military_advisor)
66 :d_fighting(LocationBox(Vector<int>(-1,-1)))
68 path_calculator = NULL;
69 d_intense_combat = intense_combat;
70 d_see_opponents_production = see_opponents_production;
71 d_see_opponents_stacks = see_opponents_stacks;
72 d_military_advisor = military_advisor;
74 current_tile.x = current_tile.y = 0;
78 d_waypoint = disassemble_row(File::getMiscFile("various/waypoints.png"), 2);
79 prev_mouse_pos = Vector<int>(0, 0);
82 selection_timeout_handler =
83 Timing::instance().register_timer
84 (sigc::mem_fun(*this, &GameBigMap::on_selection_timeout),
86 shift_key_is_down = false;
87 control_key_is_down = false;
90 GameBigMap::~GameBigMap()
93 delete path_calculator;
96 void GameBigMap::select_active_stack()
98 Stack* stack = Playerlist::getActiveplayer()->getActivestack();
101 reset_path_calculator(stack);
103 if (stack->getPath()->checkPath(stack) == false)
105 assert (Playerlist::getActiveplayer()->getType() == Player::HUMAN);
106 //original path was blocked, so let's find a new way there.
107 //this shouldn't happen because nextTurn of stack recalculates.
108 //cerr << "original path of stack was blocked\n";
109 stack->getPath()->recalculate(stack);
112 stack_selected.emit(stack);
115 void GameBigMap::unselect_active_stack()
117 draw(Playerlist::getViewingplayer());
118 stack_selected.emit(0);
121 delete path_calculator;
122 path_calculator = NULL;
124 determine_mouse_cursor(NULL, current_tile);
127 bool GameBigMap::on_selection_timeout()
129 // redraw to update the selection
130 if (Playerlist::getActiveplayer()->getActivestack())
131 draw(Playerlist::getViewingplayer());
133 return Timing::CONTINUE;
136 void GameBigMap::mouse_button_event(MouseButtonEvent e)
141 Player *active = Playerlist::getActiveplayer();
142 Player *viewing = Playerlist::getViewingplayer();
143 Vector<int> tile = mouse_pos_to_tile(e.pos);
146 if (e.button == MouseButtonEvent::LEFT_BUTTON
147 && e.state == MouseButtonEvent::PRESSED)
149 bool double_clicked = false;
150 static Glib::TimeVal last_clicked;
151 if (last_clicked.as_double() == 0.0)
152 last_clicked.assign_current_time();
155 Glib::TimeVal clicked_now;
156 clicked_now.assign_current_time();
157 double click_delta = clicked_now.as_double() -
158 last_clicked.as_double();
159 if (click_delta <= Configuration::s_double_click_threshold / 1000.0)
160 double_clicked = true;
161 last_clicked = clicked_now;
163 if (viewing->getFogMap()->isCompletelyObscuredFogTile(tile) == true)
166 Stack* stack = Playerlist::getActiveplayer()->getActivestack();
168 if (d_cursor == GraphicsCache::HAND)
173 bool path_already_set = stack->getPath()->size() > 0;
174 // ask for military advice
175 if (d_cursor == GraphicsCache::QUESTION)
177 set_shift_key_down (false);
178 Playerlist::getActiveplayer()->stackFightAdvise
179 (stack, tile, d_intense_combat);
182 else if (d_cursor == GraphicsCache::RUIN)
184 if (Ruin *r = GameMap::getRuin(tile))
186 if ((r->isHidden() == true &&
187 r->getOwner() == viewing) ||
188 r->isHidden() == false)
190 set_shift_key_down (false);
191 ruin_queried (r, false);
194 else if (Temple *t = GameMap::getTemple(tile))
196 temple_queried (t, false);
197 set_shift_key_down (false);
201 else if (d_cursor == GraphicsCache::ROOK)
203 City* c = GameMap::getCity(tile);
208 set_control_key_down (false);
209 if (d_see_opponents_production == true)
211 city_visited.emit (c);
212 set_shift_key_down (false);
217 if (c->getOwner() == Playerlist::getActiveplayer())
219 city_visited.emit(c);
220 set_shift_key_down (false);
227 else if (d_cursor == GraphicsCache::GOTO_ARROW)
229 //set in a course, mr crusher.
230 stack->getPath()->calculate(stack, tile);
232 draw(Playerlist::getViewingplayer());
236 p.x = tile.x; p.y = tile.y;
238 // clicked on the already active stack
239 if (stack->getPos() == tile)
241 if (double_clicked == true)
243 StackTile *stile = GameMap::getStacks(stack->getPos());
244 std::list<Stack *> stks= stile->getFriendlyStacks(active);
245 if (stks.size() == 1)
246 stile->ungroup(active);
249 stile->group(active);
250 active->setActivestack(GameMap::getStack(tile));
251 stack_selected.emit(GameMap::getStack(tile));
254 delete path_calculator;
255 path_calculator = new PathCalculator(stack);
256 draw(Playerlist::getViewingplayer());
257 stack_grouped_or_ungrouped.emit(stack);
263 stack->getPath()->clear();
265 draw(Playerlist::getViewingplayer());
270 //clicked on an enemy city that is too far away
271 City *c = GameMap::getCity(tile);
274 //restrict going into enemy cities unless they're only
276 if (c->getOwner() != Playerlist::getActiveplayer())
278 int delta = abs(tile.x - stack->getPos().x);
280 delta = abs(tile.y - stack->getPos().y);
286 int dist = stack->getPath()->calculate(stack, p);
288 cerr << "error calculating path!";
290 Vector<int> dest = Vector<int>(-1,-1);
291 if (!stack->getPath()->empty())
292 dest = stack->getLastPointInPath();
294 if (dest.x == tile.x && dest.y == tile.y)
296 Playerlist::getActiveplayer()->stackMove(stack);
297 if (!Playerlist::getActiveplayer()->getActivestack())
299 unselect_active_stack();
304 //grab our stack again because maybe we joined another stack
305 stack = Playerlist::getActiveplayer()->getActivestack();
308 //1. we've moved our stack too far and we've gone as far
309 // as we can on our path.
310 //2. we've set in a second path and we've gone as far as
311 // we can on our path.
312 //3. we're next to an enemy city, out of moves, and we
313 // try to attack the city.
314 //note that special care is taken to not deselect when
315 //we've proceeded along our path and ran out of nodes
316 //to follow, but we still have moves to make.
317 bool deselect = false;
318 if (path_already_set)
320 if (!stack->getPath()->empty() &&
321 stack->enoughMoves() == false)
323 else if (!stack->getPath()->empty() &&
324 stack->getPath()->getMovesExhaustedAtPoint() == 0)
329 if (stack->getPath()->empty() == false &&
330 stack->getPath()->getMovesExhaustedAtPoint() == 0)
332 if ((d_cursor == GraphicsCache::SWORD ||
333 d_cursor == GraphicsCache::HEART) &&
334 stack->canMove() == false)
336 if ((d_cursor == GraphicsCache::FEET ||
337 d_cursor == GraphicsCache::SHIP) &&
338 stack->canMove() == false)
344 Player *player = Playerlist::getActiveplayer();
345 player->setActivestack(0);
346 unselect_active_stack();
353 draw(Playerlist::getViewingplayer());
355 // Stack hasn't been active yet
358 stack = GameMap::getStack(tile);
359 if (stack && stack->isFriend(Playerlist::getActiveplayer()) &&
360 d_cursor == GraphicsCache::TARGET)
362 Playerlist::getActiveplayer()->setActivestack(stack);
363 select_active_stack();
367 City* c = GameMap::getCity(tile);
368 if (c != NULL && d_cursor == GraphicsCache::ROOK)
372 set_control_key_down (false);
373 if (d_see_opponents_production == true)
375 city_visited.emit (c);
376 set_shift_key_down (false);
380 if (c->getOwner() == Playerlist::getActiveplayer())
382 city_visited.emit (c);
383 set_shift_key_down (false);
388 else if (Ruin *r = GameMap::getRuin(tile))
390 if ((r->isHidden() == true && r->getOwner() == viewing) ||
391 r->isHidden() == false)
392 ruin_queried (r, false);
394 else if (Temple *t = GameMap::getTemple(tile))
396 temple_queried (t, false);
401 else if (e.button == MouseButtonEvent::LEFT_BUTTON
402 && e.state == MouseButtonEvent::RELEASED)
404 if (mouse_state == DRAGGING_ENDPOINT)
407 d_cursor = GraphicsCache::FEET;
408 cursor_changed.emit(d_cursor);
411 else if (mouse_state == DRAGGING_STACK)
413 Stack* stack = Playerlist::getActiveplayer()->getActivestack();
414 //march a dragged stack!
416 d_cursor = GraphicsCache::FEET;
417 cursor_changed.emit(d_cursor);
419 //we recurse for least amount of code and most programmer confusion.
420 e.state = MouseButtonEvent::PRESSED;
421 //go get the final spot in the path
422 if (stack->getPath()->empty() == false)
424 //check if we dropped on the same tile that the stack lives on.
425 if (mouse_pos_to_tile(e.pos) != stack->getPos())
427 int ts = GameMap::getInstance()->getTileset()->getTileSize();
428 e.pos = tile_to_buffer_pos (stack->getLastPointInPath());
431 mouse_button_event(e);
440 // right mousebutton to get information about things on the map and to
441 // unselect the active stack
442 else if (e.button == MouseButtonEvent::RIGHT_BUTTON)
444 if (e.state == MouseButtonEvent::PRESSED)
446 if (viewing->getFogMap()->isCompletelyObscuredFogTile(tile) == true)
448 if (City* c = GameMap::getCity(tile))
450 city_queried.emit (tile, c);
451 mouse_state = SHOWING_CITY;
453 else if (Ruin* r = GameMap::getRuin(tile))
455 if ((r->isHidden() == true &&
456 r->getOwner() == Playerlist::getViewingplayer()) ||
457 r->isHidden() == false)
459 ruin_queried (r, true);
460 mouse_state = SHOWING_RUIN;
463 else if (Signpost* s = GameMap::getSignpost(tile))
465 signpost_queried (s);
466 mouse_state = SHOWING_SIGNPOST;
468 else if (Temple* t = GameMap::getTemple(tile))
470 temple_queried.emit(t, true);
471 mouse_state = SHOWING_TEMPLE;
473 else if (Stack *st = GameMap::getStack(tile))
475 if (d_see_opponents_stacks == true)
477 stack_queried.emit(tile);
478 mouse_state = SHOWING_STACK;
480 else if (st->getOwner() == Playerlist::getActiveplayer() &&
481 d_see_opponents_stacks == false)
483 stack_queried.emit(tile);
484 mouse_state = SHOWING_STACK;
488 else // button released
494 city_unqueried.emit();
498 ruin_queried.emit(0, true);
502 temple_queried.emit(0, true);
505 case SHOWING_SIGNPOST:
506 signpost_queried.emit(0);
510 stack_unqueried.emit();
513 case DRAGGING_ENDPOINT:
517 Stack* stack = Playerlist::getActiveplayer()->getActivestack();
520 Playerlist::getActiveplayer()->setActivestack(0);
521 unselect_active_stack();
523 determine_mouse_cursor(NULL, current_tile);
528 // in any case reset mouse state
532 else if (e.button == MouseButtonEvent::WHEEL_UP)
536 else if (e.button == MouseButtonEvent::WHEEL_DOWN)
542 void GameBigMap::zoom_in()
546 if ((zoom_step / 100.0) + magnification_factor <= max_magnification_factor / 100.0)
548 int ts = GameMap::getInstance()->getTileset()->getTileSize();
550 double mag = magnification_factor + (zoom_step / 100.0);
551 new_view.w = image.get_width() / (ts * mag) + 1;
552 new_view.h = image.get_height() / (ts * mag) + 1;
553 if (new_view.w <= GameMap::getWidth() &&
554 new_view.h <= GameMap::getHeight() &&
555 new_view.w >= 0 && new_view.h >= 0)
556 zoom_view(zoom_step);
560 void GameBigMap::zoom_out()
564 if (magnification_factor - (zoom_step / 100.0) >= min_magnification_factor / 100.0)
566 int ts = GameMap::getInstance()->getTileset()->getTileSize();
568 double mag = magnification_factor - (zoom_step / 100.0);
569 new_view.w = image.get_width() / (ts * mag) + 1;
570 new_view.h = image.get_height() / (ts * mag) + 1;
571 if (new_view.w <= GameMap::getWidth() &&
572 new_view.h <= GameMap::getHeight() &&
573 new_view.w >= 0 && new_view.h >= 0)
574 zoom_view(-(const double)zoom_step);
578 void GameBigMap::determine_mouse_cursor(Stack *stack, Vector<int> tile)
580 Player *active = Playerlist::getActiveplayer();
581 Player *viewing = Playerlist::getViewingplayer();
582 if (viewing->getFogMap()->isCompletelyObscuredFogTile(tile))
584 d_cursor = GraphicsCache::HAND;
586 else if (mouse_state == DRAGGING_MAP)
587 d_cursor = GraphicsCache::HAND;
589 (mouse_state == DRAGGING_STACK || mouse_state == DRAGGING_ENDPOINT))
591 d_cursor = GraphicsCache::GOTO_ARROW;
595 d_cursor = GraphicsCache::FEET;
596 if (stack->getPos() == tile)
597 d_cursor = GraphicsCache::TARGET;
600 City *c = GameMap::getCity(tile);
603 if (c->getOwner() == active)
604 d_cursor = GraphicsCache::FEET;
605 else if (c->isBurnt() == true)
606 d_cursor = GraphicsCache::FEET;
609 int delta = abs(tile.x - stack->getPos().x);
611 delta = abs(tile.y - stack->getPos().y);
614 if (is_shift_key_down())
615 d_cursor = GraphicsCache::QUESTION;
618 Player *me = stack->getOwner();
619 Player *them = c->getOwner();
620 bool friendly = (me->getDiplomaticState(them) ==
623 d_cursor = GraphicsCache::HEART;
625 d_cursor = GraphicsCache::SWORD;
630 //can i see other ppl's cities?
631 if (d_see_opponents_production == true)
632 d_cursor = GraphicsCache::ROOK;
634 d_cursor = GraphicsCache::HAND;
640 Maptile *t = GameMap::getInstance()->getTile(tile);
641 Stack *st = GameMap::getStack(tile);
642 if (st && st->getOwner() != active)
644 int delta = abs(stack->getPos().x - st->getPos().x);
646 delta = abs(stack->getPos().y - st->getPos().y);
649 if (is_shift_key_down())
650 d_cursor = GraphicsCache::QUESTION;
653 Player *me = stack->getOwner();
654 Player *them = st->getOwner();
655 bool friendly = (me->getDiplomaticState(them) ==
658 d_cursor = GraphicsCache::HEART;
660 d_cursor = GraphicsCache::SWORD;
664 d_cursor = GraphicsCache::HAND;
669 //why is this slower than without a stack selected?
670 //because we need to see if we can get there eventually!
672 //int moves = path.calculate(stack, tile);
673 if (path_calculator == NULL)
674 path_calculator = new PathCalculator(stack);
675 if (path_calculator->isReachable(tile) == false)
677 d_cursor = GraphicsCache::HAND;
680 if (t->getMaptileType() == Tile::WATER &&
681 GameMap::getBridge(tile) == NULL)
683 if (stack->isFlying() == true)
684 d_cursor = GraphicsCache::FEET;
686 d_cursor = GraphicsCache::SHIP;
689 d_cursor = GraphicsCache::FEET;
693 if (d_cursor == GraphicsCache::FEET && is_control_key_down())
694 d_cursor = GraphicsCache::GOTO_ARROW;
699 d_cursor = GraphicsCache::HAND;
702 st = GameMap::getStack(tile);
705 if (st->getOwner() == active)
706 d_cursor = GraphicsCache::TARGET;
708 d_cursor = GraphicsCache::HAND;
712 Maptile *t = GameMap::getInstance()->getTile(tile);
713 if (t->getBuilding() == Maptile::CITY)
715 City *c = GameMap::getCity(tile);
716 if (c->isBurnt() == true)
717 d_cursor = GraphicsCache::HAND;
718 else if (c->getOwner() == active)
719 d_cursor = GraphicsCache::ROOK;
720 else if (d_see_opponents_production == true)
721 d_cursor = GraphicsCache::ROOK;
723 else if (t->getBuilding() == Maptile::RUIN)
725 Ruin *ruin = GameMap::getRuin(tile);
726 if (ruin->isHidden() == true && ruin->getOwner() == active)
727 d_cursor = GraphicsCache::RUIN;
728 else if (ruin->isHidden() == false)
729 d_cursor = GraphicsCache::RUIN;
731 else if (t->getBuilding() == Maptile::TEMPLE)
732 d_cursor = GraphicsCache::RUIN;
736 cursor_changed.emit(d_cursor);
737 //debugFogTile(tile.x, tile.y);
740 void GameBigMap::mouse_motion_event(MouseMotionEvent e)
742 static Vector<int> last_tile;
746 Player *active = Playerlist::getActiveplayer();
747 Player *viewing = Playerlist::getViewingplayer();
748 Stack* stack = active->getActivestack();
749 Vector<int> tile = mouse_pos_to_tile(e.pos);
755 if (tile.x >= GameMap::getWidth())
756 tile.x = GameMap::getWidth() - 1;
757 if (tile.y >= GameMap::getHeight())
758 tile.y = GameMap::getHeight() - 1;
761 if (e.pressed[MouseMotionEvent::LEFT_BUTTON]
762 && (mouse_state == NONE || mouse_state == SHOWING_STACK) &&
763 stack && stack->getPos() == tile && viewing->getFogMap()->isCompletelyObscuredFogTile(tile) == false && d_cursor != GraphicsCache::HAND)
765 //initial dragging of stack from it's tile
766 mouse_state = DRAGGING_STACK;
768 else if (e.pressed[MouseMotionEvent::LEFT_BUTTON] && stack &&
769 d_cursor == GraphicsCache::GOTO_ARROW && mouse_state == NONE)
771 //initial dragging of endpoint from it's tile
772 mouse_state = DRAGGING_ENDPOINT;
774 else if (e.pressed[MouseMotionEvent::LEFT_BUTTON]
775 && (mouse_state == NONE || mouse_state == DRAGGING_MAP) && d_cursor == GraphicsCache::HAND)
777 Vector<int> delta = -(e.pos - prev_mouse_pos);
779 // ignore very small drags to ensure that a shaking mouse does not
780 // prevent the user from making right clicks
781 if (mouse_state == NONE && length(delta) <= 2)
784 int ts = GameMap::getInstance()->getTileset()->getTileSize();
785 Vector<int> screen_dim(image.get_width(), image.get_height());
786 view_pos = clip(Vector<int>(0, 0),
788 GameMap::get_dim() * ts *magnification_factor - screen_dim);
790 // calculate new view position in tiles, rounding up
791 Vector<int> new_view = (view_pos + Vector<int>(ts * magnification_factor - 1, ts * magnification_factor - 1)) / (ts * magnification_factor);
793 if (new_view != view.pos)
795 //here we have a case of the new view overlapping with the view.
796 //why redraw what we've already drawn?
797 Rectangle old_view = view;
800 view_changed.emit(view);
801 draw(Playerlist::getViewingplayer(),true);
804 draw(Playerlist::getViewingplayer(), false);
805 mouse_state = DRAGGING_MAP;
808 // the following block of code shows the correct mouse cursor
809 if (tile == last_tile)
811 prev_mouse_pos = e.pos;
815 // drag stack with left mouse button
816 if (e.pressed[MouseMotionEvent::LEFT_BUTTON]
817 && (mouse_state == DRAGGING_STACK || mouse_state == DRAGGING_ENDPOINT) &&
818 viewing->getFogMap()->isCompletelyObscuredFogTile(tile) == false)
820 //subsequent dragging
821 //alright. calculate the path, and show it but don't move
822 //be careful that we don't drop our path on bad objects
823 //also, slide the whole view if we drag out of view
824 if (is_inside(view, tile) == false)
826 Vector<int> delta(0,0);
827 if (tile.x >= view.x + view.w)
831 if (tile.y > view.y + view.h)
835 Rectangle new_view = view;
836 new_view.pos += delta;
838 view_changed.emit(view);
840 mouse_state_enum orig_state = mouse_state;
842 determine_mouse_cursor(stack, tile);
843 mouse_state = orig_state;
844 if (d_cursor == GraphicsCache::FEET ||
845 d_cursor == GraphicsCache::SHIP ||
846 d_cursor == GraphicsCache::GOTO_ARROW ||
847 d_cursor == GraphicsCache::TARGET)
849 guint32 moves = 0, turns = 0;
850 Path *new_path = path_calculator->calculate(tile, moves, turns, true);
851 if (new_path->size())
852 stack->setPath(*new_path);
854 //stack->getPath()->calculate(stack, tile);
856 draw(Playerlist::getViewingplayer());
860 determine_mouse_cursor (stack, tile);
861 if (control_key_is_down == true)
862 set_control_key_down (true);
863 if (shift_key_is_down == true)
864 set_shift_key_down (true);
866 prev_mouse_pos = e.pos;
870 void GameBigMap::reset_zoom()
872 magnification_factor = 1.0;
873 screen_size_changed(image);
874 draw(Playerlist::getViewingplayer(), true);
875 view_changed.emit(view);
878 void GameBigMap::zoom_view(double percent)
880 magnification_factor += percent / 100.0;
881 //call with +2, or -2
882 //Rectangle new_view = view;
883 //new_view.dim += Vector<int>(tiles, tiles);
884 //new_view.pos += Vector<int>(tiles*-1/2, tiles*-1/2);
885 //set_view (new_view);
886 screen_size_changed(image);
887 draw(Playerlist::getViewingplayer(), true);
888 view_changed.emit(view);
891 void GameBigMap::after_draw()
893 if (blank_screen == true)
895 GraphicsCache *gc = GraphicsCache::getInstance();
896 int tilesize = GameMap::getInstance()->getTileset()->getTileSize();
898 Stack* stack = Playerlist::getActiveplayer()->getActivestack();
901 if (stack && stack->getPath()->size() &&
902 stack->getOwner()->getType() == Player::HUMAN)
906 // draw all waypoints
907 guint32 pathcount = 0;
908 bool canMoveThere = true;
909 Path::iterator end = stack->getPath()->end();
910 //if we're dragging, we don't draw the last waypoint circle
911 if (stack->getPath()->size() > 0 &&
912 (mouse_state == DRAGGING_STACK || mouse_state == DRAGGING_ENDPOINT))
914 for (Path::iterator it = stack->getPath()->begin();
917 pos = tile_to_buffer_pos(*it);
919 canMoveThere = (pathcount < stack->getPath()->getMovesExhaustedAtPoint());
921 d_waypoint[0]->blit_centered(buffer, pos + (Vector<int>(tilesize,tilesize)/2));
923 d_waypoint[1]->blit_centered(buffer, pos + (Vector<int>(tilesize,tilesize)/2));
929 if (mouse_state == DRAGGING_STACK || mouse_state == DRAGGING_ENDPOINT
930 || d_cursor == GraphicsCache::GOTO_ARROW)
932 Path::iterator it = stack->getPath()->end();
934 //this is where the ghosted army unit picture goes.
935 PixMask *armypic = gc->getArmyPic(*stack->begin(), true);
936 pos = tile_to_buffer_pos(*it);
937 armypic->blit_centered(buffer, pos + (Vector<int>(tilesize,tilesize)/2));
941 if (stack && d_fighting.getPos() == Vector<int>(-1,-1))
943 Player *viewer = Playerlist::getViewingplayer();
944 // draw the selection
945 Vector<int> p = stack->getPos();
946 if (is_inside(buffer_view, Vector<int>(p.x, p.y)) &&
947 Playerlist::getViewingplayer()->getFogMap()->isFogged(p) == false)
949 static int bigframe = -1;
950 static int smallframe = -1;
952 Tileset *t = GameMap::getInstance()->getTileset();
954 if (bigframe >= (int)t->getNumberOfSelectorFrames())
958 if (smallframe >= (int)t->getNumberOfSmallSelectorFrames())
961 p = tile_to_buffer_pos(p);
963 draw_stack (stack, buffer, buffer_gc);
966 if (stack->size() > 1)
967 tmp = gc->getSelectorPic(0, bigframe, stack->getOwner());
969 tmp = gc->getSelectorPic(1, smallframe, stack->getOwner());
970 tmp->blit(buffer, p);
971 //now re-fog it up because we just drew over the fog.
972 if (viewer->getFogMap()->isFogged(stack->getPos()))
975 viewer->getFogMap()->getShadeTile(stack->getPos());
976 PixMask *fog = gc->getFogPic(fog_type_id);
977 fog->blit(buffer, p);
982 if (d_fighting.getPos() != Vector<int>(-1,-1))
984 Vector<int> p = tile_to_buffer_pos(d_fighting.getPos());
985 PixMask *tmp = gc->getExplosionPic()->copy();
986 if (d_fighting.getSize() > 1)
988 PixMask::scale(tmp, d_fighting.getSize() * tilesize,
989 d_fighting.getSize() * tilesize);
991 tmp->blit(buffer, p);
996 void GameBigMap::set_control_key_down (bool down)
998 control_key_is_down = down;
999 Player *active = Playerlist::getActiveplayer();
1000 Player *viewing = Playerlist::getViewingplayer();
1001 if (viewing->getFogMap()->isCompletelyObscuredFogTile(current_tile) == true)
1003 Stack* active_stack = active->getActivestack();
1004 //if the key has been released, just show what we'd normally show.
1005 if (control_key_is_down == false)
1007 determine_mouse_cursor(active_stack, current_tile);
1012 if (GameMap::getInstance()->getTile(current_tile)->getBuilding() !=
1017 stack = GameMap::getFriendlyStack(current_tile);
1021 if (d_cursor == GraphicsCache::TARGET)
1023 City *city = GameMap::getCity(current_tile);
1024 if (city->isBurnt() == false)
1026 d_cursor = GraphicsCache::ROOK;
1027 cursor_changed.emit(d_cursor);
1030 else if (d_cursor == GraphicsCache::HAND &&
1031 d_see_opponents_production == true)
1033 City *city = GameMap::getCity(current_tile);
1034 if (city->isBurnt() == false)
1036 d_cursor = GraphicsCache::ROOK;
1037 cursor_changed.emit(d_cursor);
1043 if (d_cursor == GraphicsCache::FEET)
1045 d_cursor = GraphicsCache::GOTO_ARROW;
1046 cursor_changed.emit(d_cursor);
1051 void GameBigMap::set_shift_key_down (bool down)
1053 shift_key_is_down = down;
1054 Player *active = Playerlist::getActiveplayer();
1055 Player *viewing = Playerlist::getViewingplayer();
1056 if (viewing->getFogMap()->isCompletelyObscuredFogTile(current_tile) == true)
1059 Stack* active_stack = active->getActivestack();
1061 //if the key has been released, just show what we'd normally show.
1062 if (shift_key_is_down == false)
1064 determine_mouse_cursor(active_stack, current_tile);
1068 //otherwise the shift key is down and we need to do some more checking
1069 Maptile::Building b = GameMap::getInstance()->getTile(current_tile)->getBuilding();
1070 if (b == Maptile::RUIN)
1072 Ruin *r = GameMap::getRuin(current_tile);
1075 if ((r->isHidden() == true &&
1076 r->getOwner() == Playerlist::getActiveplayer()) ||
1077 r->isHidden() == false)
1083 else if (b == Maptile::CITY)
1085 if (d_cursor == GraphicsCache::TARGET)
1087 d_cursor = GraphicsCache::ROOK;
1088 cursor_changed.emit(d_cursor);
1090 else if (d_cursor == GraphicsCache::FEET)
1092 d_cursor = GraphicsCache::ROOK;
1093 cursor_changed.emit(d_cursor);
1095 else if (d_cursor == GraphicsCache::HAND &&
1096 d_see_opponents_production == true)
1098 d_cursor = GraphicsCache::ROOK;
1099 cursor_changed.emit(d_cursor);
1105 if (d_cursor == GraphicsCache::SHIP || d_cursor == GraphicsCache::FEET)
1107 if (b == Maptile::RUIN || b == Maptile::TEMPLE)
1108 d_cursor = GraphicsCache::RUIN;
1110 d_cursor = GraphicsCache::HAND;
1111 cursor_changed.emit(d_cursor);
1116 if (d_cursor != GraphicsCache::RUIN)
1118 if (b == Maptile::RUIN || b == Maptile::TEMPLE)
1120 d_cursor = GraphicsCache::RUIN;
1121 cursor_changed.emit(d_cursor);
1126 if (d_military_advisor == true)
1128 if (active_stack && d_cursor == GraphicsCache::SWORD)
1130 d_cursor = GraphicsCache::QUESTION;
1131 cursor_changed.emit(d_cursor);
1136 void GameBigMap::reset_path_calculator(Stack *s)
1138 if (path_calculator)
1139 delete path_calculator;
1140 path_calculator = new PathCalculator(s);