void BadGuy::try_activate() { // Don't activate if player is dying Player* player = get_nearest_player(); if (!player) return; if (!is_offscreen()) { set_state(STATE_ACTIVE); if (!is_initialized) { // if starting direction was set to AUTO, this is our chance to re-orient the badguy if (start_dir == AUTO) { Player* player_ = get_nearest_player(); if (player_ && (player_->get_bbox().p1.x > get_bbox().p2.x)) { dir = RIGHT; } else { dir = LEFT; } } initialize(); is_initialized = true; } activate(); } }
void BadGuy::try_activate() { // Don't activate if player is dying auto player = get_nearest_player(); if (!player) return; if (!is_offscreen()) { set_state(STATE_ACTIVE); if (!m_is_initialized) { // if starting direction was set to AUTO, this is our chance to re-orient the badguy if (m_start_dir == Direction::AUTO) { auto player_ = get_nearest_player(); if (player_ && (player_->get_bbox().get_left() > m_col.m_bbox.get_right())) { m_dir = Direction::RIGHT; } else { m_dir = Direction::LEFT; } } initialize(); m_is_initialized = true; } activate(); } }
void BadGuy::update(float elapsed_time) { if(!Sector::current()->inside(bbox)) { run_dead_script(); is_active_flag = false; remove_me(); // This was removed due to fixing a bug. If is it needed somewhere, then I'm sorry. --Hume2 /**if(countMe) { // get badguy name from sprite_name ignoring path and extension std::string badguy = sprite_name.substr(0, sprite_name.length() - 7); int path_chars = badguy.rfind("/",badguy.length()); badguy = badguy.substr(path_chars + 1, badguy.length() - path_chars); // log warning since badguys_killed can no longer reach total_badguys std::string current_level = "[" + Sector::current()->get_level()->filename + "] "; log_warning << current_level << "Counted badguy " << badguy << " starting at " << start_position << " has left the sector" <<std::endl;; }*/ return; } if ((state != STATE_INACTIVE) && is_offscreen()) { if (state == STATE_ACTIVE) deactivate(); set_state(STATE_INACTIVE); } switch(state) { case STATE_ACTIVE: is_active_flag = true; if (Editor::current()) if (Editor::current()->levelloaded) { break; } active_update(elapsed_time); break; case STATE_INIT: case STATE_INACTIVE: is_active_flag = false; inactive_update(elapsed_time); try_activate(); break; case STATE_SQUISHED: is_active_flag = false; if(state_timer.check()) { remove_me(); break; } movement = physic.get_movement(elapsed_time); break; case STATE_FALLING: is_active_flag = false; movement = physic.get_movement(elapsed_time); break; } on_ground_flag = false; }
void BadGuy::update(float elapsed_time) { if(!Sector::current()->inside(bbox)) { is_active_flag = false; remove_me(); return; } if ((state != STATE_INACTIVE) && is_offscreen()) { if (state == STATE_ACTIVE) deactivate(); set_state(STATE_INACTIVE); } switch(state) { case STATE_ACTIVE: is_active_flag = true; active_update(elapsed_time); break; case STATE_INIT: case STATE_INACTIVE: is_active_flag = false; inactive_update(elapsed_time); try_activate(); break; case STATE_SQUISHED: is_active_flag = false; if(state_timer.check()) { remove_me(); break; } movement = physic.get_movement(elapsed_time); break; case STATE_FALLING: is_active_flag = false; movement = physic.get_movement(elapsed_time); break; } on_ground_flag = false; }
//TODO: Add launching velocity to certain badguys // Add themed randomizer void Dispenser::launch_badguy() { //FIXME: Does is_offscreen() work right here? if (!is_offscreen()) { if (badguy == "snowball") Sector::current()->add_object(new SnowBall(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "bouncingsnowball") Sector::current()->add_object(new BouncingSnowball(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "mrbomb") Sector::current()->add_object(new MrBomb(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "mriceblock") Sector::current()->add_object(new MrIceBlock(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "snail") Sector::current()->add_object(new Snail(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "mrrocket") { Sector::current()->add_object(new MrRocket(Vector(get_pos().x+(dir == LEFT ? -32 : 32), get_pos().y), dir));} else if (badguy == "poisonivy") Sector::current()->add_object(new PoisonIvy(Vector(get_pos().x, get_pos().y+32), dir)); else if (badguy == "skullyhop") Sector::current()->add_object(new SkullyHop(Vector(get_pos().x, get_pos().y+44), dir)); else if (badguy == "random") { switch (systemRandom.rand(7)) { case 0: Sector::current()->add_object(new SnowBall(Vector(get_pos().x, get_pos().y+32), dir)); break; case 1: Sector::current()->add_object(new BouncingSnowball(Vector(get_pos().x, get_pos().y+32), dir)); break; case 2: Sector::current()->add_object(new MrBomb(Vector(get_pos().x, get_pos().y+32), dir)); break; case 3: Sector::current()->add_object(new MrIceBlock(Vector(get_pos().x, get_pos().y+32), dir)); break; case 4: Sector::current()->add_object(new PoisonIvy(Vector(get_pos().x, get_pos().y+32), dir)); break; case 5: Sector::current()->add_object(new Snail(Vector(get_pos().x, get_pos().y+32), dir)); break; case 6: Sector::current()->add_object(new SkullyHop(Vector(get_pos().x, get_pos().y+44), dir)); break; } } } }
void Dispenser::launch_badguy() { if (frozen) { return; } //FIXME: Does is_offscreen() work right here? if (!is_offscreen()) { Direction launchdir = dir; if( !autotarget && start_dir == AUTO ){ Player* player = this->get_nearest_player(); if( player ){ launchdir = (player->get_pos().x > get_pos().x) ? RIGHT : LEFT; } } if (badguys.size() > 1) { if (random) { next_badguy = gameRandom.rand(badguys.size()); } else { next_badguy++; if (next_badguy >= badguys.size()) next_badguy = 0; } } std::string badguy = badguys[next_badguy]; if(badguy == "random") { log_warning << "random is outdated; use a list of badguys to select from." << std::endl; return; } if(badguy == "goldbomb") { log_warning << "goldbomb is not allowed to be dispensed" << std::endl; return; } try { GameObjectPtr game_object; Vector spawnpoint; Rectf object_bbox; /* Need to allocate the badguy first to figure out its bounding box. */ game_object = ObjectFactory::instance().create(badguy, get_pos(), launchdir); if (game_object == NULL) throw std::runtime_error("Creating " + badguy + " object failed."); BadGuy& bad_guy = dynamic_cast<BadGuy&>(*game_object); object_bbox = bad_guy.get_bbox(); switch (type) { case DT_DROPPER: spawnpoint = get_anchor_pos (bbox, ANCHOR_BOTTOM); spawnpoint.x -= 0.5 * object_bbox.get_width(); break; case DT_ROCKETLAUNCHER: case DT_CANNON: spawnpoint = get_pos(); /* top-left corner of the cannon */ if (launchdir == LEFT) spawnpoint.x -= object_bbox.get_width() + 1; else spawnpoint.x += bbox.get_width() + 1; break; default: break; } /* Now we set the real spawn position */ bad_guy.set_pos(spawnpoint); /* We don't want to count dispensed badguys in level stats */ bad_guy.countMe = false; Sector::current()->add_object(game_object); } catch(const std::exception& e) { log_warning << "Error dispensing badguy: " << e.what() << std::endl; return; } } }
void BadGuy::update(float dt_sec) { if (!Sector::get().inside(m_col.m_bbox)) { run_dead_script(); m_is_active_flag = false; remove_me(); // This was removed due to fixing a bug. If is it needed somewhere, then I'm sorry. --Hume2 /**if(countMe) { // get badguy name from sprite_name ignoring path and extension std::string badguy = sprite_name.substr(0, sprite_name.length() - 7); int path_chars = badguy.rfind("/",badguy.length()); badguy = badguy.substr(path_chars + 1, badguy.length() - path_chars); // log warning since badguys_killed can no longer reach total_badguys std::string current_level = "[" + Sector::get().get_level()->filename + "] "; log_warning << current_level << "Counted badguy " << badguy << " starting at " << start_position << " has left the sector" <<std::endl;; }*/ return; } if ((m_state != STATE_INACTIVE) && is_offscreen()) { if (m_state == STATE_ACTIVE) deactivate(); set_state(STATE_INACTIVE); } switch (m_state) { case STATE_ACTIVE: m_is_active_flag = true; if (Editor::is_active()) { break; } active_update(dt_sec); break; case STATE_INIT: case STATE_INACTIVE: m_is_active_flag = false; inactive_update(dt_sec); try_activate(); break; case STATE_BURNING: { m_is_active_flag = false; m_col.m_movement = m_physic.get_movement(dt_sec); if ( m_sprite->animation_done() ) { remove_me(); } } break; case STATE_GEAR: case STATE_SQUISHED: m_is_active_flag = false; if (m_state_timer.check()) { remove_me(); break; } m_col.m_movement = m_physic.get_movement(dt_sec); break; case STATE_MELTING: { m_is_active_flag = false; m_col.m_movement = m_physic.get_movement(dt_sec); if ( m_sprite->animation_done() || on_ground() ) { Sector::get().add<WaterDrop>(m_col.m_bbox.p1(), get_water_sprite(), m_physic.get_velocity()); remove_me(); break; } } break; case STATE_GROUND_MELTING: m_is_active_flag = false; m_col.m_movement = m_physic.get_movement(dt_sec); if ( m_sprite->animation_done() ) { remove_me(); } break; case STATE_INSIDE_MELTING: { m_is_active_flag = false; m_col.m_movement = m_physic.get_movement(dt_sec); if ( on_ground() && m_sprite->animation_done() ) { m_sprite->set_action(m_dir == Direction::LEFT ? "gear-left" : "gear-right", 1); set_state(STATE_GEAR); } int pa = graphicsRandom.rand(0,3); float px = graphicsRandom.randf(m_col.m_bbox.get_left(), m_col.m_bbox.get_right()); float py = graphicsRandom.randf(m_col.m_bbox.get_top(), m_col.m_bbox.get_bottom()); Vector ppos = Vector(px, py); Sector::get().add<SpriteParticle>(get_water_sprite(), "particle_" + std::to_string(pa), ppos, ANCHOR_MIDDLE, Vector(0, 0), Vector(0, 100 * Sector::get().get_gravity()), LAYER_OBJECTS-1); } break; case STATE_FALLING: m_is_active_flag = false; m_col.m_movement = m_physic.get_movement(dt_sec); break; } m_on_ground_flag = false; }
void Dispenser::launch_badguy() { if (m_badguys.empty()) return; if (m_frozen) return; if (m_limit_dispensed_badguys && m_current_badguys >= m_max_concurrent_badguys) return; //FIXME: Does is_offscreen() work right here? if (!is_offscreen() && !Editor::is_active()) { Direction launchdir = m_dir; if ( !m_autotarget && m_start_dir == Direction::AUTO ){ Player* player = get_nearest_player(); if ( player ){ launchdir = (player->get_pos().x > get_pos().x) ? Direction::RIGHT : Direction::LEFT; } } if (m_badguys.size() > 1) { if (m_random) { m_next_badguy = static_cast<unsigned int>(gameRandom.rand(static_cast<int>(m_badguys.size()))); } else { m_next_badguy++; if (m_next_badguy >= m_badguys.size()) m_next_badguy = 0; } } std::string badguy = m_badguys[m_next_badguy]; if (badguy == "random") { log_warning << "random is outdated; use a list of badguys to select from." << std::endl; return; } if (badguy == "goldbomb") { log_warning << "goldbomb is not allowed to be dispensed" << std::endl; return; } try { /* Need to allocate the badguy first to figure out its bounding box. */ auto game_object = GameObjectFactory::instance().create(badguy, get_pos(), launchdir); if (game_object == nullptr) throw std::runtime_error("Creating " + badguy + " object failed."); auto& bad_guy = dynamic_cast<BadGuy&>(*game_object); Rectf object_bbox = bad_guy.get_bbox(); Vector spawnpoint; switch (m_type) { case DispenserType::DROPPER: spawnpoint = get_anchor_pos (m_col.m_bbox, ANCHOR_BOTTOM); spawnpoint.x -= 0.5f * object_bbox.get_width(); break; case DispenserType::ROCKETLAUNCHER: case DispenserType::CANNON: spawnpoint = get_pos(); /* top-left corner of the cannon */ if (launchdir == Direction::LEFT) spawnpoint.x -= object_bbox.get_width() + 1; else spawnpoint.x += m_col.m_bbox.get_width() + 1; break; case DispenserType::POINT: spawnpoint = m_col.m_bbox.p1(); break; default: break; } /* Now we set the real spawn position */ bad_guy.set_pos(spawnpoint); /* We don't want to count dispensed badguys in level stats */ bad_guy.m_countMe = false; /* Set reference to dispenser in badguy itself */ if (m_limit_dispensed_badguys) { bad_guy.set_parent_dispenser(this); m_current_badguys++; } Sector::get().add_object(std::move(game_object)); } catch(const std::exception& e) { log_warning << "Error dispensing badguy: " << e.what() << std::endl; return; } } }