Exemple #1
0
/**
 * \copydoc MapEntity::notify_added_to_map
 */
void Pickable::notify_added_to_map(Map& map) {

  Detector::notify_added_to_map(map);

  if (map.is_started()) {
    // notify the Lua item
    get_equipment().get_item(treasure.get_item_name()).notify_pickable_appeared(*this);
  }
  // otherwise, notify_map_started() will do the job
}
Exemple #2
0
/**
 * @brief Makes sure the keys effects are coherent with the hero's equipment and abilities.
 */
void Game::update_keys_effect() {

  // when the game is paused or a dialog box is shown, the sword key is not the usual one
  if (is_paused() || is_showing_message()) {
    return; // if the game is interrupted for some other reason (e.g. a transition), let the normal sword icon
  }

  // make sure the sword key is coherent with having a sword
  if (get_equipment().has_ability("sword")
      && keys_effect->get_sword_key_effect() != KeysEffect::SWORD_KEY_SWORD) {

    keys_effect->set_sword_key_effect(KeysEffect::SWORD_KEY_SWORD);
  }
  else if (!get_equipment().has_ability("sword")
      && keys_effect->get_sword_key_effect() == KeysEffect::SWORD_KEY_SWORD) {

    keys_effect->set_sword_key_effect(KeysEffect::SWORD_KEY_NONE);
  }
}
Exemple #3
0
/**
 * \brief Notifies the appropriate script that the hero is interacting with this entity.
 */
void Npc::call_script_hero_interaction() {

  if (behavior == BEHAVIOR_MAP_SCRIPT) {
    get_lua_context()->entity_on_interaction(*this);
  }
  else {
    EquipmentItem& item = get_equipment().get_item(item_name);
    get_lua_context()->item_on_npc_interaction(item, *this);
  }
}
Exemple #4
0
/**
 * \brief This function is called when the hero stops an attack with his shield.
 *
 * By default, the shield sound is played and the enemy cannot attack again for a while.
 */
void Enemy::attack_stopped_by_hero_shield() {

  Sound::play("shield");

  uint32_t now = System::now();
  can_attack = false;
  can_attack_again_date = now + 1000;

  get_equipment().notify_ability_used("shield");
}
Exemple #5
0
/**
 * \copydoc Entity::notify_created
 */
void Pickable::notify_created() {

  Detector::notify_created();

  update_ground_below();
  notify_ground_below_changed();  // Necessary if on empty ground.

  // This entity and the map are now both ready. Notify the Lua item.
  EquipmentItem& item = get_equipment().get_item(treasure.get_item_name());
  item.notify_pickable_appeared(*this);
}
Exemple #6
0
/**
 * \copydoc Entity::notify_action_command_pressed
 */
bool Npc::notify_action_command_pressed() {

  Hero& hero = get_hero();
  if (hero.is_free() &&
      get_commands_effects().get_action_key_effect() != CommandsEffects::ACTION_KEY_NONE
  ) {

    CommandsEffects::ActionKeyEffect effect = get_commands_effects().get_action_key_effect();
    get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);

    SpritePtr sprite = get_sprite();

    // if this is a usual NPC, look towards the hero
    if (subtype == USUAL_NPC) {
      int direction = (get_hero().get_animation_direction() + 2) % 4;
      if (sprite != nullptr) {
        sprite->set_current_direction(direction);
      }
    }

    if (effect != CommandsEffects::ACTION_KEY_LIFT) {
      // start the normal behavior
      if (behavior == BEHAVIOR_DIALOG) {
        get_game().start_dialog(dialog_to_show, ScopedLuaRef(), ScopedLuaRef());
      }
      else {
        call_script_hero_interaction();
      }
      return true;
    }
    else {
      // lift the entity
      if (get_equipment().has_ability(Ability::LIFT)) {

        std::string animation_set_id = "stopped";
        if (sprite != nullptr) {
          animation_set_id = sprite->get_animation_set_id();
        }
        hero.start_lifting(std::make_shared<CarriedObject>(
            hero,
            *this,
            animation_set_id,
            "stone",
            2,
            0)
        );
        Sound::play("lift");
        remove_from_map();
        return true;
      }
    }
  }
  return false;
}
/**
 * \brief Plays the sword loading sound.
 */
void Hero::SwordLoadingState::play_load_sound() {

  std::ostringstream oss;
  oss << "sword_spin_attack_load_" << get_equipment().get_ability(Ability::SWORD);
  std::string custom_sound_name = oss.str();
  if (Sound::exists(custom_sound_name)) {
    Sound::play(custom_sound_name); // this particular sword has a custom loading sound effect
  }
  else {
    Sound::play("sword_spin_attack_load");
  }
}
/**
 * \brief Plays the sword loading sound.
 */
void Hero::SpinAttackState::play_spin_attack_sound() {

  std::ostringstream oss;
  oss << "sword_spin_attack_release_" << get_equipment().get_ability("sword");
  std::string custom_sound_name = oss.str();
  if (Sound::exists(custom_sound_name)) {
    Sound::play(custom_sound_name); // this particular sword has a spin attack sound effect
  }
  else {
    Sound::play("sword_spin_attack_release");
  }
}
Exemple #9
0
/**
 * @brief Updates the entity.
 */
void ShopItem::update() {

  if (is_looking_item && !get_game().is_dialog_enabled()) {

    // the description message has just finished
    const std::string question_dialog_id = "_shop.question";
    get_dialog_box().start_dialog(question_dialog_id);
    get_dialog_box().set_variable(question_dialog_id, price);
    is_asking_question = true;
    is_looking_item = false;
  }
  else if (is_asking_question && !get_game().is_dialog_enabled()) {

    // the question has just finished
    is_asking_question = false;
    int answer = get_dialog_box().get_last_answer();

    if (answer == 0) {

      // the player wants to buy the item
      Equipment& equipment = get_equipment();
      EquipmentItem& item = treasure.get_item();

      if (equipment.get_money() < price) {
        // not enough rupees
        Sound::play("wrong");
        get_dialog_box().start_dialog("_shop.not_enough_money");
      }
      else if (item.has_amount() && item.get_amount() >= item.get_max_amount()) {
        // the player already has the maximum amount of this item
        Sound::play("wrong");
        get_dialog_box().start_dialog("_shop.amount_full");
      }
      else {

        bool can_buy = get_lua_context().shop_item_on_buying(*this);
        if (can_buy) {

          // give the treasure
          equipment.remove_money(price);

          get_hero().start_treasure(treasure, LUA_REFNIL);
          if (treasure.is_saved()) {
            remove_from_map();
            get_savegame().set_boolean(treasure.get_savegame_variable(), true);
          }
          get_lua_context().shop_item_on_bought(*this);
        }
      }
    }
  }
}
Exemple #10
0
/** Drachen und Seeschlangen können entstehen */
void spawn_dragons(void)
{
    region *r;
    faction *monsters = get_or_create_monsters();

    for (r = regions; r; r = r->next) {
        unit *u;

        if (fval(r->terrain, SEA_REGION) && rng_int() % 10000 < 1) {
            u = create_unit(r, monsters, 1, get_race(RC_SEASERPENT), 0, NULL, NULL);
            fset(u, UFL_ISNEW | UFL_MOVED);
            equip_unit(u, get_equipment("monster_seaserpent"));
        }

        if ((r->terrain == newterrain(T_GLACIER)
            || r->terrain == newterrain(T_SWAMP)
            || r->terrain == newterrain(T_DESERT))
            && rng_int() % 10000 < (5 + 100 * chaosfactor(r))) {
            if (chance(0.80)) {
                u = create_unit(r, monsters, nrand(60, 20) + 1, get_race(RC_FIREDRAGON), 0, NULL, NULL);
            }
            else {
                u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL);
            }
            fset(u, UFL_ISNEW | UFL_MOVED);
            equip_unit(u, get_equipment("monster_dragon"));

            log_debug("spawning %d %s in %s.\n", u->number,
                LOC(default_locale,
                rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL)), regionname(r, NULL));

            name_unit(u);

            /* add message to the region */
            ADDMSG(&r->msgs,
                msg_message("sighting", "region race number", r, u_race(u), u->number));
        }
    }
}
Exemple #11
0
/**
 * \copydoc Detector::notify_action_command_pressed
 */
bool Destructible::notify_action_command_pressed() {

  KeysEffect::ActionKeyEffect effect = get_keys_effect().get_action_key_effect();

  if ((effect == KeysEffect::ACTION_KEY_LIFT || effect == KeysEffect::ACTION_KEY_LOOK)
      && get_weight() != -1
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating) {

    if (get_equipment().has_ability(Ability::LIFT, get_weight())) {

      uint32_t explosion_date = get_can_explode() ? System::now() + 6000 : 0;
      get_hero().start_lifting(std::make_shared<CarriedItem>(
          get_hero(),
          *this,
          get_animation_set_id(),
          get_destruction_sound(),
          get_damage_on_enemies(),
          explosion_date)
      );

      // Play the sound.
      Sound::play("lift");

      // Create the pickable treasure.
      create_treasure();

      if (!get_can_regenerate()) {
        // Remove this destructible from the map.
        remove_from_map();
      }
      else {
        // The item can actually regenerate.
        play_destroy_animation();
      }

      // Notify Lua.
      get_lua_context().destructible_on_lifting(*this);
    }
    else {
      // Cannot lift the object.
      get_hero().start_grabbing();
      get_lua_context().destructible_on_looked(*this);
    }

    return true;
  }

  return false;
}
Exemple #12
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::LiftingState::start(const State* previous_state) {

  State::start(previous_state);

  // initialize the entity that will be lifted
  lifted_item->set_map(get_map());

  get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_THROW);
  get_sprites().set_animation_lifting();
  get_sprites().set_lifted_item(lifted_item);
  get_hero().set_facing_entity(nullptr);

  get_equipment().notify_ability_used(ABILITY_LIFT);
}
Exemple #13
0
/**
 * @brief Returns whether the player is able to open this chest now.
 * @return true if this is a small chest or if the player has the big key.
 */
bool Chest::can_open() {

  switch (get_opening_method()) {

    case OPENING_BY_INTERACTION:
      // No condition: the hero can always open the chest.
      return true;

    case OPENING_BY_INTERACTION_IF_SAVEGAME_VARIABLE:
    {
      // The hero can open the chest if a savegame variable is set.
      const std::string& required_savegame_variable = get_opening_condition();
      if (required_savegame_variable.empty()) {
        return false;
      }

      Savegame& savegame = get_savegame();
      if (savegame.is_boolean(required_savegame_variable)) {
        return savegame.get_boolean(required_savegame_variable);
      }

      if (savegame.is_integer(required_savegame_variable)) {
        return savegame.get_integer(required_savegame_variable) > 0;
      }

      if (savegame.is_string(required_savegame_variable)) {
        return !savegame.get_string(required_savegame_variable).empty();
      }

      return false;
    }

    case OPENING_BY_INTERACTION_IF_ITEM:
    {
      // The hero can open the chest if he has an item.
      const std::string& required_item_name = get_opening_condition();
      if (required_item_name.empty()) {
        return false;
      }
      const EquipmentItem& item = get_equipment().get_item(required_item_name);
      return item.is_saved()
        && item.get_variant() > 0
        && (!item.has_amount() || item.get_amount() > 0);
    }

    default:
      return false;
  }
}
Exemple #14
0
static void get_villagers(region * r, unit * u)
{
  unit *newunit;
  message *msg = msg_message("encounter_villagers", "unit", u);
  const char *name = LOC(u->faction->locale, "villagers");

  r_addmessage(r, u->faction, msg);
  msg_release(msg);

  newunit =
    create_unit(r, u->faction, rng_int() % 20 + 3, u->faction->race, 0, name,
    u);
  leave(newunit, true);
  fset(newunit, UFL_ISNEW | UFL_MOVED);
  equip_unit(newunit, get_equipment("random_villagers"));
}
Exemple #15
0
/**
 * \brief Notifies this detector that the player is interacting by using an
 * equipment item.
 *
 * This function is called when the player uses an equipment item
 * while the hero is facing this NPC.
 *
 * \param item_used The equipment item used.
 * \return true if an interaction occured.
 */
bool Npc::notify_interaction_with_item(EquipmentItem& item_used) {

  bool interaction_occured;
  if (behavior == BEHAVIOR_ITEM_SCRIPT) {
    EquipmentItem& item_to_notify = get_equipment().get_item(item_name);
    interaction_occured = get_lua_context()->item_on_npc_interaction_item(
        item_to_notify, *this, item_used
    );
  }
  else {
    interaction_occured = get_lua_context()->entity_on_interaction_item(
        *this, item_used
    );
  }

  return interaction_occured;
}
Exemple #16
0
/**
 * \brief This function is called when this entity detects a collision with the hero.
 * \param hero the hero
 * \param collision_mode the collision mode that detected the collision
 */
void Destructible::notify_collision_with_hero(Hero& hero, CollisionMode /* collision_mode */) {

  if (get_weight() != -1
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
      && hero.is_free()) {

    if (get_equipment().has_ability(Ability::LIFT, get_weight())) {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LIFT);
    }
    else {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #17
0
/**
 * @brief Consumes the savegame variable or the equipment item that was required
 * to open the door.
 */
void Door::consume_opening_condition() {

  switch (get_opening_method()) {

    case OPENING_BY_INTERACTION_IF_SAVEGAME_VARIABLE:
    {
      // Reset or decrement the savegame variable that was required.
      const std::string& required_savegame_variable = get_opening_condition();
      Savegame& savegame = get_savegame();
      if (!required_savegame_variable.empty()) {
        if (savegame.is_boolean(required_savegame_variable)) {
          savegame.set_boolean(required_savegame_variable, false);
        }
        else if (savegame.is_integer(required_savegame_variable)) {
          int current_value = savegame.get_integer(required_savegame_variable);
          savegame.set_integer(required_savegame_variable, current_value - 1);
        }
        else if (savegame.is_string(required_savegame_variable)) {
          savegame.set_string(required_savegame_variable, "");
        }
      }
      break;
    }

    case OPENING_BY_INTERACTION_IF_ITEM:
    {
      // Remove the equipment item that was required.
      if (!opening_condition.empty()) {
        EquipmentItem& item = get_equipment().get_item(opening_condition);
        if (item.is_saved() && item.get_variant() > 0) {
          if (item.has_amount()) {
            item.set_amount(item.get_amount() - 1);
          }
          else {
            item.set_variant(0);
          }
        }
      }
      break;
    }

    default:
      // Ignored.
      break;
  }
}
Exemple #18
0
/**
 * \brief Notifies this state that the action command was just pressed.
 */
void Hero::FreeState::notify_action_command_pressed() {

  if (get_keys_effect().is_action_key_acting_on_facing_entity()) {

    // action on the facing entity
    hero.get_facing_entity()->notify_action_command_pressed();
  }
  else if (hero.is_facing_point_on_obstacle()) {

    // grab an obstacle
    hero.set_state(new GrabbingState(hero));
  }
  else if (get_equipment().has_ability("run")) {

    // run
    hero.start_running();
  }
}
Exemple #19
0
/**
 * \brief This function is called when this entity detects a collision with the hero.
 * \param hero the hero
 * \param collision_mode the collision mode that detected the collision
 */
void Destructible::notify_collision_with_hero(Hero& hero, CollisionMode collision_mode) {

  if (features[subtype].can_be_lifted
      && !is_being_cut
      && !is_disabled()
      && !is_regenerating
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
      && hero.is_free()) {

    int weight = features[subtype].weight;
    if (get_equipment().has_ability("lift", weight)) {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LIFT);
    }
    else {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #20
0
/**
 * @brief This function is called when the player interacts with this chest.
 *
 * This function is called when the player presses the action key
 * when the hero is facing this detector, and the action icon lets him do this.
 * The hero opens the chest if possible.
 */
void Chest::action_key_pressed() {

  if (is_visible() && get_hero().is_free()) {

    if (!big_chest || get_equipment().has_ability("open_dungeon_big_locks")) {
      Sound::play("chest_open");
      set_open(true);
      treasure_date = System::now() + 300;

      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
      get_hero().start_freezed();
    }
    else {
      Sound::play("wrong");
      get_dialog_box().start_dialog("_big_key_required");
    }
  }
}
Exemple #21
0
/**
 * \brief Updates the game elements.
 *
 * Updates the map, the equipment, the HUD, etc.
 */
void Game::update() {

  // update the transitions between maps
  update_transitions();

  if (restarting || !started) {
    return;
  }

  // update the map
  current_map->update();

  // call game:on_update() in Lua
  get_lua_context().game_on_update(*this);

  // update the equipment and HUD
  get_equipment().update();
  update_keys_effect();
}
Exemple #22
0
/**
 * \brief Attacks the hero if possible.
 *
 * This function is called when there is a collision between the enemy and the hero.
 *
 * \param hero The hero to attack.
 * \param this_sprite The sprite of this enemy that detected the collision with the hero,
 * or NULL if it was not a pixel-precise collision.
 */
void Enemy::attack_hero(Hero& hero, Sprite* this_sprite) {

  if (!is_immobilized()
      && can_attack
      && hero.can_be_hurt(this)) {

    bool hero_protected = false;
    if (minimum_shield_needed != 0
        && get_equipment().has_ability(ABILITY_SHIELD, minimum_shield_needed)
        && hero.can_use_shield()) {

      // Compute the direction corresponding to the angle between the enemy and the hero.
      double angle = hero.get_angle(*this, NULL, this_sprite);
      int protected_direction4 = (int) ((angle + Geometry::PI_OVER_2 / 2.0) * 4 / Geometry::TWO_PI);
      protected_direction4 = (protected_direction4 + 4) % 4;

      // Also get the direction of the enemy's sprite.
      int sprite_opposite_direction4 = -1;
      if (this_sprite != NULL) {
        sprite_opposite_direction4 = (this_sprite->get_current_direction() + 2) % 4;
      }

      // The hero is protected if he is facing the opposite of one of these directions.
      hero_protected = hero.is_facing_direction4(protected_direction4) ||
          hero.is_facing_direction4(sprite_opposite_direction4);
    }

    if (hero_protected) {
      attack_stopped_by_hero_shield();
    }
    else {
      // Let the enemy script handle this if it wants.
      const bool handled = get_lua_context().enemy_on_attacking_hero(
          *this, hero, this_sprite);
      if (!handled) {
        // Scripts did not customize the attack:
        // do the built-in hurt state of the hero.
        hero.hurt(*this, this_sprite, damage_on_hero);
      }
    }
  }
}
Exemple #23
0
/**
 * \brief Updates this state.
 */
void Hero::FallingState::update() {

    State::update();

    Hero& hero = get_hero();
    if (!is_suspended() && get_sprites().is_animation_finished()) {

        // the hero has just finished falling
        Teletransporter* teletransporter = hero.get_delayed_teletransporter();
        if (teletransporter != NULL) {
            // special hole with a teletransporter
            teletransporter->transport_hero(hero);
        }
        else {
            // normal hole that hurts the hero
            get_equipment().remove_life(2);
            hero.set_state(new BackToSolidGroundState(hero, true));
        }
    }
}
Exemple #24
0
/**
 * \brief Starts this state.
 * \param previous_state The previous state.
 */
void Hero::HurtState::start(const HeroState* previous_state) {

  HeroState::start(previous_state);

  Equipment& equipment = get_equipment();

  Sound::play("hero_hurt");

  Hero& hero = get_hero();
  const uint32_t invincibility_duration = 2000;
  hero.set_invincible(true, invincibility_duration);
  get_sprites().set_animation_hurt();
  get_sprites().blink(invincibility_duration);

  if (has_source) {
    double angle = Geometry::get_angle(source_xy, hero.get_xy());
    std::shared_ptr<StraightMovement> movement =
        std::make_shared<StraightMovement>(false, true);
    movement->set_max_distance(24);
    movement->set_speed(120);
    movement->set_angle(angle);
    hero.set_movement(movement);
  }
  end_hurt_date = System::now() + 200;

  // See if the script customizes how the hero takes damages.
  bool handled = get_lua_context().hero_on_taking_damage(get_hero(), damage);

  if (!handled && damage != 0) {
    // No customized damage: perform the default calculation.
    // The level of the tunic reduces the damage,
    // but we remove at least 1 life point.
    int life_points = std::max(1, damage / (equipment.get_ability(Ability::TUNIC)));

    equipment.remove_life(life_points);
    if (equipment.has_ability(Ability::TUNIC)) {
      equipment.notify_ability_used(Ability::TUNIC);
    }
  }
}
/**
 * @brief Starts this state.
 * @param previous_state the previous state
 */
void Hero::SpinAttackState::start(State* previous_state) {

  State::start(previous_state);

  // play the sound
  play_spin_attack_sound();

  // start the animation
  if (get_equipment().has_ability("sword_knowledge")) {
    get_sprites().set_animation_super_spin_attack();
    CircleMovement* movement = new CircleMovement(false);
    movement->set_center(hero.get_xy());
    movement->set_radius_speed(128);
    movement->set_radius(24);
    movement->set_angle_speed(540);
    movement->set_max_rotations(3);
    movement->set_clockwise(true);
    hero.set_movement(movement);
  }
  else {
    get_sprites().set_animation_spin_attack();
  }
}
/**
 * \brief Returns the damage power of the sword for the current attack.
 *
 * Redefine the function if your state changes the power of the sword
 * (typically for a spin attack).
 *
 * \return the current damage factor of the sword
 */
int Entity::State::get_sword_damage_factor() const {

  return get_equipment().get_ability(Ability::SWORD);
}
Exemple #27
0
/**
 * \brief Returns whether the player can currently pause the game.
 *
 * He can pause the game if the pause command is enabled
 * and if his life is greater than zero.
 *
 * \return \c true if the player can currently pause the game.
 */
bool Game::can_pause() const {
  return !is_suspended()
      && is_pause_allowed()               // see if the map currently allows the pause command
      && get_equipment().get_life() > 0;  // don't allow to pause the game if the gameover sequence is about to start
}
Exemple #28
0
/**
 * \brief Creates a game.
 * \param main_loop The Solarus root object.
 * \param savegame The saved data of this game. Will be deleted in the
 * destructor unless someone is still using it (the refcount info is used).
 */
Game::Game(MainLoop& main_loop, Savegame* savegame):

  main_loop(main_loop),
  savegame(savegame),
  pause_allowed(true),
  paused(false),
  dialog_box(*this),
  showing_game_over(false),
  started(false),
  restarting(false),
  keys_effect(NULL),
  current_map(NULL),
  next_map(NULL),
  previous_map_surface(NULL),
  transition_style(Transition::IMMEDIATE),
  transition(NULL),
  crystal_state(false) {

  // notify objects
  RefCountable::ref(savegame);
  savegame->set_game(this);

  // initialize members
  commands = new GameCommands(*this);
  hero = new Hero(get_equipment());
  RefCountable::ref(hero);
  keys_effect = new KeysEffect();
  update_keys_effect();

  // Maybe we are restarting after a game-over sequence.
  if (get_equipment().get_life() <= 0) {
    get_equipment().restore_all_life();
  }

  // Launch the starting map.
  std::string starting_map_id = savegame->get_string(Savegame::KEY_STARTING_MAP);
  std::string starting_destination_name = savegame->get_string(Savegame::KEY_STARTING_POINT);

  bool valid_map_saved = false;
  if (!starting_map_id.empty()) {

    if (QuestResourceList::exists(QuestResourceList::RESOURCE_MAP, starting_map_id)) {
      // We are okay: the savegame file refers to an existing map.
      valid_map_saved = true;
    }
    else {
      // The savegame refers to a map that no longer exists.
      // Maybe the quest is in an intermediate development phase.
      // Show an error and fallback to the default map.
      Debug::error(std::string("The savegame refers to a non-existing map: '") + starting_map_id + "'");
    }
  }

  if (!valid_map_saved) {
    // When no valid starting map is set, use the first one declared in the
    // resource list file.
    const std::vector<QuestResourceList::Element>& maps =
        QuestResourceList::get_elements(QuestResourceList::RESOURCE_MAP);
    if (maps.empty()) {
      Debug::die("This quest has no map");
    }
    starting_map_id = maps[0].first;
    starting_destination_name = "";  // Default destination.
  }

  set_current_map(starting_map_id, starting_destination_name, Transition::FADE);
}
Exemple #29
0
static void get_allies(region * r, unit * u)
{
  unit *newunit = NULL;
  const char *name;
  const char *equip;
  int number;
  message *msg;

  assert(u->number);

  switch (rterrain(r)) {
    case T_PLAIN:
      if (!r_isforest(r)) {
        if (get_money(u) / u->number < 100 + rng_int() % 200)
          return;
        name = "random_plain_men";
        equip = "random_plain";
        number = rng_int() % 8 + 2;
        break;
      } else {
        if (eff_skill(u, SK_LONGBOW, r) < 3
          && eff_skill(u, SK_HERBALISM, r) < 2
          && eff_skill(u, SK_MAGIC, r) < 2) {
          return;
        }
        name = "random_forest_men";
        equip = "random_forest";
        number = rng_int() % 6 + 2;
      }
      break;

    case T_SWAMP:
      if (eff_skill(u, SK_MELEE, r) <= 1) {
        return;
      }
      name = "random_swamp_men";
      equip = "random_swamp";
      number = rng_int() % 6 + 2;
      break;

    case T_DESERT:
      if (eff_skill(u, SK_RIDING, r) <= 2) {
        return;
      }
      name = "random_desert_men";
      equip = "random_desert";
      number = rng_int() % 12 + 2;
      break;

    case T_HIGHLAND:
      if (eff_skill(u, SK_MELEE, r) <= 1) {
        return;
      }
      name = "random_highland_men";
      equip = "random_highland";
      number = rng_int() % 8 + 2;
      break;

    case T_MOUNTAIN:
      if (eff_skill(u, SK_MELEE, r) <= 1 || eff_skill(u, SK_TRADE, r) <= 2) {
        return;
      }
      name = "random_mountain_men";
      equip = "random_mountain";
      number = rng_int() % 6 + 2;
      break;

    case T_GLACIER:
      if (eff_skill(u, SK_MELEE, r) <= 1 || eff_skill(u, SK_TRADE, r) <= 1) {
        return;
      }
      name = "random_glacier_men";
      equip = "random_glacier";
      number = rng_int() % 4 + 2;
      break;

    default:
      return;
  }

  newunit =
    create_unit(r, u->faction, number, u->faction->race, 0,
    LOC(u->faction->locale, name), u);
  equip_unit(newunit, get_equipment(equip));

  u_setfaction(newunit, u->faction);
  set_racename(&newunit->attribs, get_racename(u->attribs));
  if (u_race(u)->flags & RCF_SHAPESHIFT) {
    newunit->irace = u->irace;
  }
  if (fval(u, UFL_ANON_FACTION))
    fset(newunit, UFL_ANON_FACTION);
  fset(newunit, UFL_ISNEW);

  msg = msg_message("encounter_allies", "unit name", u, name);
  r_addmessage(r, u->faction, msg);
  msg_release(msg);
}
Exemple #30
0
/**
 * \brief Returns the damage power of the sword for the current attack.
 *
 * Redefine the function if your state changes the power of the sword
 * (typically for a spin attack).
 *
 * \return the current damage factor of the sword
 */
int Hero::State::get_sword_damage_factor() {

  static const int sword_factors[] = {0, 1, 2, 4, 8};
  int sword = get_equipment().get_ability("sword");
  return sword_factors[sword];
}