Getting rid of nasty tabs
[supertux.git] / src / object / icecrusher.cpp
1 //  $Id$
2 //
3 //  IceCrusher - A block to stand on, which can drop down to crush the player
4 //  Copyright (C) 2008 Christoph Sommer <christoph.sommer@2008.expires.deltadevelopment.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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.  See the
14 //  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, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20
21 #include <config.h>
22
23 #include "icecrusher.hpp"
24
25 #include <stdexcept>
26 #include "log.hpp"
27 #include "video/drawing_context.hpp"
28 #include "resources.hpp"
29 #include "badguy/badguy.hpp"
30 #include "sprite/sprite.hpp"
31 #include "lisp/lisp.hpp"
32 #include "object_factory.hpp"
33 #include "sector.hpp"
34
35 namespace {
36   const float DROP_SPEED = 500;
37   const float RECOVER_SPEED = 200;
38 }
39
40 IceCrusher::IceCrusher(const lisp::Lisp& reader)
41         : MovingSprite(reader, "images/creatures/icecrusher/icecrusher.sprite", LAYER_OBJECTS, COLGROUP_STATIC), 
42         state(IDLE), speed(Vector(0,0))
43 {
44   start_position = get_bbox().p1;
45   set_state(state, true);
46 }
47
48 IceCrusher::IceCrusher(const IceCrusher& other)
49         : MovingSprite(other), 
50         state(other.state), speed(other.speed) 
51 {
52   start_position = get_bbox().p1;
53   set_state(state, true);
54 }
55
56 void 
57 IceCrusher::set_state(IceCrusherState state, bool force) 
58 {
59   if ((this->state == state) && (!force)) return;
60   switch(state) {
61     case IDLE:
62       set_group(COLGROUP_STATIC);
63       speed=Vector(0,0);
64       sprite->set_action("idle");
65       break;
66     case CRUSHING:
67       set_group(COLGROUP_MOVING_STATIC);
68       speed=Vector(0, DROP_SPEED);
69       sprite->set_action("idle");
70       break;
71     case RECOVERING:
72       set_group(COLGROUP_MOVING_STATIC);
73       speed=Vector(0, -RECOVER_SPEED);
74       sprite->set_action("idle");
75       break;
76     default:
77       log_debug << "IceCrusher in invalid state" << std::endl;
78       break;
79   }
80   this->state = state;
81 }
82
83 HitResponse
84 IceCrusher::collision(GameObject& other, const CollisionHit& hit)
85 {
86   Player* player = dynamic_cast<Player*>(&other);
87   if (player && hit.bottom) {
88     if(player->is_invincible()) {
89       if (state == CRUSHING) set_state(RECOVERING);
90       return ABORT_MOVE;
91     }
92     player->kill(false);
93     if (state == CRUSHING) set_state(RECOVERING);
94     return FORCE_MOVE;
95   }
96   BadGuy* badguy = dynamic_cast<BadGuy*>(&other);
97   if (badguy) {
98     badguy->kill_fall();
99   }
100   return FORCE_MOVE;
101 }
102     
103 void 
104 IceCrusher::collision_solid(const CollisionHit& )
105 {
106   switch(state) {
107     case IDLE:
108       break;
109     case CRUSHING:
110       set_state(RECOVERING);
111       break;
112     case RECOVERING:
113       break;
114     default:
115       log_debug << "IceCrusher in invalid state" << std::endl;
116       break;
117   }
118 }
119
120 void
121 IceCrusher::update(float elapsed_time)
122 {
123   switch(state) {
124     case IDLE:
125       if (found_victim()) set_state(CRUSHING);
126       break;
127     case CRUSHING:
128       break;
129     case RECOVERING:
130       if (get_bbox().p1.y <= start_position.y+1) {
131         set_pos(start_position);
132         set_state(IDLE);
133       }
134       break;
135     default:
136       log_debug << "IceCrusher in invalid state" << std::endl;
137       break;
138   }
139   movement = speed * elapsed_time;
140 }
141
142 Player*
143 IceCrusher::get_nearest_player()
144 {
145   // FIXME: does not really return nearest player
146
147   std::vector<Player*> players = Sector::current()->get_players();
148   for (std::vector<Player*>::iterator playerIter = players.begin(); playerIter != players.end(); ++playerIter) {
149     Player* player = *playerIter;
150     if (player->is_dying() || player->is_dead()) continue;
151     return player;
152   }
153
154   return 0;
155 }
156
157 bool
158 IceCrusher::found_victim()
159 {
160   Player* player = this->get_nearest_player();
161   if (!player) return false;
162
163   const Rect& pr = player->get_bbox();
164   const Rect& br = get_bbox();
165   if ((pr.p2.x > br.p1.x) && (pr.p1.x < br.p2.x) && (pr.p1.y >= br.p2.y)) {
166     return true;
167   }
168   return false;
169 }
170
171 IMPLEMENT_FACTORY(IceCrusher, "icecrusher");