00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "badguy/willowisp.hpp"
00018
00019 #include "audio/sound_manager.hpp"
00020 #include "audio/sound_source.hpp"
00021 #include "object/lantern.hpp"
00022 #include "object/path_walker.hpp"
00023 #include "object/player.hpp"
00024 #include "scripting/squirrel_util.hpp"
00025 #include "sprite/sprite.hpp"
00026 #include "supertux/game_session.hpp"
00027 #include "supertux/object_factory.hpp"
00028 #include "supertux/sector.hpp"
00029 #include "util/reader.hpp"
00030
00031 static const float FLYSPEED = 64;
00032 static const float TRACK_RANGE = 384;
00033 static const float VANISH_RANGE = 512;
00034 static const std::string SOUNDFILE = "sounds/willowisp.wav";
00035
00036 WillOWisp::WillOWisp(const Reader& reader) :
00037 BadGuy(reader, "images/creatures/willowisp/willowisp.sprite", LAYER_FLOATINGOBJECTS),
00038 mystate(STATE_IDLE),
00039 target_sector("main"),
00040 target_spawnpoint("main"),
00041 hit_script(),
00042 sound_source(),
00043 path(),
00044 walker(),
00045 flyspeed(),
00046 track_range(),
00047 vanish_range()
00048 {
00049 bool running = false;
00050 flyspeed = FLYSPEED;
00051 track_range = TRACK_RANGE;
00052 vanish_range = VANISH_RANGE;
00053
00054 reader.get("sector", target_sector);
00055 reader.get("spawnpoint", target_spawnpoint);
00056 reader.get("name", name);
00057 reader.get("flyspeed", flyspeed);
00058 reader.get("track-range", track_range);
00059 reader.get("vanish-range", vanish_range);
00060 reader.get("hit-script", hit_script);
00061 reader.get("running", running);
00062
00063 const lisp::Lisp* pathLisp = reader.get_lisp("path");
00064 if(pathLisp != NULL) {
00065 path.reset(new Path());
00066 path->read(*pathLisp);
00067 walker.reset(new PathWalker(path.get(), running));
00068 if(running)
00069 mystate = STATE_PATHMOVING_TRACK;
00070 }
00071
00072 countMe = false;
00073 sound_manager->preload(SOUNDFILE);
00074 sound_manager->preload("sounds/warp.wav");
00075
00076 sprite->set_action("idle");
00077 }
00078
00079 void
00080 WillOWisp::draw(DrawingContext& context)
00081 {
00082 sprite->draw(context, get_pos(), layer);
00083
00084 context.push_target();
00085 context.set_target(DrawingContext::LIGHTMAP);
00086
00087 sprite->draw(context, get_pos(), layer);
00088
00089 context.pop_target();
00090 }
00091
00092 void
00093 WillOWisp::active_update(float elapsed_time)
00094 {
00095 Player* player = get_nearest_player();
00096 if (!player) return;
00097 Vector p1 = this->get_pos() + (this->get_bbox().p2 - this->get_bbox().p1) / 2;
00098 Vector p2 = player->get_pos() + (player->get_bbox().p2 - player->get_bbox().p1) / 2;
00099 Vector dist = (p2 - p1);
00100
00101 switch(mystate) {
00102 case STATE_STOPPED:
00103 break;
00104
00105 case STATE_IDLE:
00106 if (dist.norm() <= track_range) {
00107 mystate = STATE_TRACKING;
00108 }
00109 break;
00110
00111 case STATE_TRACKING:
00112 if (dist.norm() > vanish_range) {
00113 vanish();
00114 } else if (dist.norm() >= 1) {
00115 Vector dir = dist.unit();
00116 movement = dir * elapsed_time * flyspeed;
00117 } else {
00118
00119
00120 }
00121 sound_source->set_position(get_pos());
00122 break;
00123
00124 case STATE_WARPING:
00125 if(sprite->animation_done()) {
00126 remove_me();
00127 }
00128
00129 case STATE_VANISHING: {
00130 Vector dir = dist.unit();
00131 movement = dir * elapsed_time * flyspeed;
00132 if(sprite->animation_done()) {
00133 remove_me();
00134 }
00135 break;
00136 }
00137
00138 case STATE_PATHMOVING:
00139 case STATE_PATHMOVING_TRACK:
00140 if(walker.get() == NULL)
00141 return;
00142 movement = walker->advance(elapsed_time) - get_pos();
00143 if(mystate == STATE_PATHMOVING_TRACK && dist.norm() <= track_range) {
00144 mystate = STATE_TRACKING;
00145 }
00146 break;
00147
00148 default:
00149 assert(false);
00150 }
00151 }
00152
00153 void
00154 WillOWisp::activate()
00155 {
00156 sound_source.reset(sound_manager->create_sound_source(SOUNDFILE));
00157 sound_source->set_position(get_pos());
00158 sound_source->set_looping(true);
00159 sound_source->set_gain(2.0);
00160 sound_source->set_reference_distance(32);
00161 sound_source->play();
00162 }
00163
00164 void
00165 WillOWisp::deactivate()
00166 {
00167 sound_source.reset(NULL);
00168
00169 switch (mystate) {
00170 case STATE_STOPPED:
00171 case STATE_IDLE:
00172 case STATE_PATHMOVING:
00173 case STATE_PATHMOVING_TRACK:
00174 break;
00175 case STATE_TRACKING:
00176 mystate = STATE_IDLE;
00177 break;
00178 case STATE_WARPING:
00179 case STATE_VANISHING:
00180 remove_me();
00181 break;
00182 }
00183 }
00184
00185 void
00186 WillOWisp::vanish()
00187 {
00188 mystate = STATE_VANISHING;
00189 sprite->set_action("vanishing", 1);
00190 set_colgroup_active(COLGROUP_DISABLED);
00191 }
00192
00193 bool
00194 WillOWisp::collides(GameObject& other, const CollisionHit& ) {
00195 Lantern* lantern = dynamic_cast<Lantern*>(&other);
00196
00197 if (lantern && lantern->is_open())
00198 return true;
00199
00200 if (dynamic_cast<Player*>(&other))
00201 return true;
00202
00203 return false;
00204 }
00205
00206 HitResponse
00207 WillOWisp::collision_player(Player& player, const CollisionHit& ) {
00208 if(player.is_invincible())
00209 return ABORT_MOVE;
00210
00211 if (mystate != STATE_TRACKING)
00212 return ABORT_MOVE;
00213
00214 mystate = STATE_WARPING;
00215 sprite->set_action("warping", 1);
00216
00217 if(hit_script != "") {
00218 std::istringstream stream(hit_script);
00219 Sector::current()->run_script(stream, "hit-script");
00220 } else {
00221 GameSession::current()->respawn(target_sector, target_spawnpoint);
00222 }
00223 sound_manager->play("sounds/warp.wav");
00224
00225 return CONTINUE;
00226 }
00227
00228 void
00229 WillOWisp::goto_node(int node_no)
00230 {
00231 walker->goto_node(node_no);
00232 if(mystate != STATE_PATHMOVING && mystate != STATE_PATHMOVING_TRACK) {
00233 mystate = STATE_PATHMOVING;
00234 }
00235 }
00236
00237 void
00238 WillOWisp::start_moving()
00239 {
00240 walker->start_moving();
00241 }
00242
00243 void
00244 WillOWisp::stop_moving()
00245 {
00246 walker->stop_moving();
00247 }
00248
00249 void
00250 WillOWisp::set_state(const std::string& new_state)
00251 {
00252 if(new_state == "stopped") {
00253 mystate = STATE_STOPPED;
00254 } else if(new_state == "idle") {
00255 mystate = STATE_IDLE;
00256 } else if(new_state == "move_path") {
00257 mystate = STATE_PATHMOVING;
00258 walker->start_moving();
00259 } else if(new_state == "move_path_track") {
00260 mystate = STATE_PATHMOVING_TRACK;
00261 walker->start_moving();
00262 } else if(new_state == "normal") {
00263 mystate = STATE_IDLE;
00264 } else if(new_state == "vanish") {
00265 vanish();
00266 } else {
00267 std::ostringstream msg;
00268 msg << "Can't set unknown willowisp state '" << new_state << "', should "
00269 "be stopped, move_path, move_path_track or normal";
00270 throw new std::runtime_error(msg.str());
00271 }
00272 }
00273
00274 void
00275 WillOWisp::expose(HSQUIRRELVM vm, SQInteger table_idx)
00276 {
00277 if (name.empty())
00278 return;
00279
00280 std::cout << "Expose me '" << name << "'\n";
00281 scripting::WillOWisp* _this = static_cast<scripting::WillOWisp*> (this);
00282 expose_object(vm, table_idx, _this, name);
00283 }
00284
00285 void
00286 WillOWisp::unexpose(HSQUIRRELVM vm, SQInteger table_idx)
00287 {
00288 if (name.empty())
00289 return;
00290
00291 std::cout << "UnExpose me '" << name << "'\n";
00292 scripting::unexpose_object(vm, table_idx, name);
00293 }
00294
00295