Doors can run scripts now.
[supertux.git] / src / trigger / door.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
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.
8 //
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 General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "audio/sound_manager.hpp"
18 #include "object/player.hpp"
19 #include "sprite/sprite_manager.hpp"
20 #include "supertux/game_session.hpp"
21 #include "supertux/object_factory.hpp"
22 #include "supertux/sector.hpp"
23 #include "trigger/door.hpp"
24 #include "util/reader.hpp"
25
26 Door::Door(const Reader& reader) :
27   state(CLOSED),
28   target_sector(),
29   target_spawnpoint(),
30   sprite(),
31   stay_open_timer()
32 {
33   reader.get("x", bbox.p1.x);
34   reader.get("y", bbox.p1.y);
35   reader.get("sector", target_sector);
36   reader.get("spawnpoint", target_spawnpoint);
37
38   reader.get("script", script);
39
40   sprite = sprite_manager->create("images/objects/door/door.sprite");
41   sprite->set_action("closed");
42   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
43
44   sound_manager->preload("sounds/door.wav");
45 }
46
47 Door::Door(int x, int y, std::string sector, std::string spawnpoint) :
48   state(CLOSED),
49   target_sector(),
50   target_spawnpoint(),
51   sprite(),
52   stay_open_timer()
53 {
54   bbox.set_pos(Vector(x, y));
55   target_sector = sector;
56   target_spawnpoint = spawnpoint;
57
58   sprite = sprite_manager->create("images/objects/door/door.sprite");
59   sprite->set_action("closed");
60   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
61
62   sound_manager->preload("sounds/door.wav");
63 }
64
65 Door::~Door()
66 {
67 }
68
69 void
70 Door::update(float )
71 {
72   switch (state) {
73     case CLOSED:
74       break;
75     case OPENING:
76       // if door has finished opening, start timer and keep door open
77       if(sprite->animation_done()) {
78         state = OPEN;
79         sprite->set_action("open");
80         stay_open_timer.start(1.0);
81       }
82       break;
83     case OPEN:
84       // if door was open long enough, start closing it
85       if (stay_open_timer.check()) {
86         state = CLOSING;
87         sprite->set_action("closing", 1);
88       }
89       break;
90     case CLOSING:
91       // if door has finished closing, keep it shut
92       if(sprite->animation_done()) {
93         state = CLOSED;
94         sprite->set_action("closed");
95       }
96       break;
97   }
98 }
99
100 void
101 Door::draw(DrawingContext& context)
102 {
103   sprite->draw(context, bbox.p1, LAYER_BACKGROUNDTILES+1);
104 }
105
106 void
107 Door::event(Player& , EventType type)
108 {
109   switch (state) {
110     case CLOSED:
111       // if door was activated, start opening it
112       if (type == EVENT_ACTIVATE) {
113         state = OPENING;
114         sound_manager->play("sounds/door.wav");
115         sprite->set_action("opening", 1);
116       }
117       break;
118     case OPENING:
119       break;
120     case OPEN:
121       break;
122     case CLOSING:
123       break;
124   }
125 }
126
127 HitResponse
128 Door::collision(GameObject& other, const CollisionHit& hit)
129 {
130   switch (state) {
131     case CLOSED:
132       break;
133     case OPENING:
134       break;
135     case OPEN:
136     {
137       // if door is open and was touched by a player, teleport the player
138       Player* player = dynamic_cast<Player*> (&other);
139       if (player) {
140         state = CLOSING;
141         sprite->set_action("closing", 1);
142         if(script != "") {
143           std::istringstream stream(script);
144           Sector::current()->run_script(stream, "Door");
145         }
146
147         if(target_sector != "") {
148           GameSession::current()->respawn(target_sector, target_spawnpoint);
149         }
150       }
151     }
152     break;
153     case CLOSING:
154       break;
155   }
156
157   return TriggerBase::collision(other, hit);
158 }
159
160 /* EOF */