static void reality_check_get_direction_helper(const map_location & loc, const map_location::DIRECTION d) { map_location lz(vz.get_direction(d)); map_location temp(loc.vector_sum(lz)); BOOST_CHECK_EQUAL(temp, loc.get_direction(d)); BOOST_CHECK(tiles_adjacent(loc,temp)); BOOST_CHECK(tiles_adjacent(temp,loc)); BOOST_CHECK_EQUAL(distance_between(loc,temp), 1); }
/** * Expose map_location tiles_adjacent */ int intf_tiles_adjacent(lua_State* L) { map_location l2 = pop_map_location(L); map_location l1 = pop_map_location(L); lua_pushboolean(L, tiles_adjacent(l1,l2)); return 1; }
/** * Expose map_location tiles_adjacent */ int intf_tiles_adjacent(lua_State* L) { map_location l1, l2; if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) { lua_pushstring(L, "vector_sum: requires two locations"); return lua_error(L); } lua_pushboolean(L, tiles_adjacent(l1,l2)); return 1; }
attack::attack(config const& cfg, bool hidden) : move(cfg,hidden) , target_hex_(cfg.child("target_hex_")["x"],cfg.child("target_hex_")["y"]) , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1 , attack_movement_cost_() , temp_movement_subtracted_(0) { // Validate target_hex if(!tiles_adjacent(target_hex_,get_dest_hex())) throw action::ctor_err("attack: Invalid target_hex_"); // Validate weapon_choice_ if(weapon_choice_ < 0 || weapon_choice_ >= static_cast<int>(get_unit()->attacks().size())) throw action::ctor_err("attack: Invalid weapon_choice_"); // Construct attack_movement_cost_ attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used(); this->init(); }
/** * Visually moves a unit from the last hex we drew to the one specified by * @a path_index. If @a path_index points to an earlier hex, we do nothing. * The moving unit will only be updated if update is set to true; otherwise, * the provided unit is merely hidden during the movement and re-shown after. * (Not updating the unit can produce smoother animations in some cases.) * If @a wait is set to false, this returns without waiting for the final * animation to finish. Call wait_for_anims() to explicitly get this final * wait (another call to proceed_to() or finish() will implicitly wait). The * unit must remain valid until the wait is finished. */ void unit_mover::proceed_to(unit_ptr u, size_t path_index, bool update, bool wait) { // Nothing to do here if animations cannot be shown. if ( !can_draw_ || !animate_ ) return; // Handle pending visibility issues before introducing new ones. wait_for_anims(); if ( update || !temp_unit_ptr_ ) // Replace the temp unit (which also hides u and shows our temporary). replace_temporary(u); else { // Just switch the display from the real unit to our fake one. temp_unit_ptr_->set_hidden(false); u->set_hidden(true); } // Safety check. path_index = std::min(path_index, path_.size()-1); for ( ; current_ < path_index; ++current_ ) // If the unit can be seen by the viewing side while making this step: if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[current_]) || !temp_unit_ptr_->invisible(path_[current_+1]) ) { // Wait for the previous step to complete before drawing the next one. wait_for_anims(); if ( !disp_->tile_fully_on_screen(path_[current_]) || !disp_->tile_fully_on_screen(path_[current_+1])) { // prevent the unit from disappearing if we scroll here with i == 0 temp_unit_ptr_->set_location(path_[current_]); disp_->invalidate(path_[current_]); // scroll in as much of the remaining path as possible if ( temp_unit_ptr_->anim_comp().get_animation() ) temp_unit_ptr_->anim_comp().get_animation()->pause_animation(); disp_->scroll_to_tiles(path_.begin() + current_, path_.end(), game_display::ONSCREEN, true, false, 0.0, force_scroll_); if ( temp_unit_ptr_->anim_comp().get_animation() ) temp_unit_ptr_->anim_comp().get_animation()->restart_animation(); } if ( tiles_adjacent(path_[current_], path_[current_+1]) ) wait_until_ = move_unit_between(path_[current_], path_[current_+1], temp_unit_ptr_.get_unit_ptr(), current_, path_.size() - (current_+2), animator_, *disp_); else if ( path_[current_] != path_[current_+1] ) teleport_unit_between(path_[current_], path_[current_+1], *temp_unit_ptr_, *disp_); } // Update the unit's facing. u->set_facing(temp_unit_ptr_->facing()); u->anim_comp().set_standing(false); // Need to reset u's animation so the new facing takes effect. // Remember the unit to unhide when the animation finishes. shown_unit_ = u; if ( wait ) wait_for_anims(); }
void attack_result::do_check_before() { LOG_AI_ACTIONS << " check_before " << *this << std::endl; const unit *attacker = get_unit(get_info(),attacker_loc_); const unit *defender = get_unit(get_info(),defender_loc_); if(attacker==NULL) { LOG_AI_ACTIONS << "attempt to attack without attacker\n"; set_error(E_EMPTY_ATTACKER); return; } if (defender==NULL) { LOG_AI_ACTIONS << "attempt to attack without defender\n"; set_error(E_EMPTY_DEFENDER); return; } if(attacker->incapacitated()) { LOG_AI_ACTIONS << "attempt to attack with unit that is petrified\n"; set_error(E_INCAPACITATED_ATTACKER); return; } if(defender->incapacitated()) { LOG_AI_ACTIONS << "attempt to attack unit that is petrified\n"; set_error(E_INCAPACITATED_DEFENDER); return; } if(!attacker->attacks_left()) { LOG_AI_ACTIONS << "attempt to attack with no attacks left\n"; set_error(E_NO_ATTACKS_LEFT); return; } if(attacker->side()!=get_side()) { LOG_AI_ACTIONS << "attempt to attack with not own unit\n"; set_error(E_NOT_OWN_ATTACKER); return; } if(!get_my_team(get_info()).is_enemy(defender->side())) { LOG_AI_ACTIONS << "attempt to attack unit that is not enemy\n"; set_error(E_NOT_ENEMY_DEFENDER); return; } if (attacker_weapon_!=-1) { if ((attacker_weapon_<0)||(attacker_weapon_ >= static_cast<int>(attacker->attacks().size()))) { LOG_AI_ACTIONS << "invalid weapon selection for the attacker\n"; set_error(E_WRONG_ATTACKER_WEAPON); return; } } if (!tiles_adjacent(attacker_loc_,defender_loc_)) { LOG_AI_ACTIONS << "attacker and defender not adjacent\n"; set_error(E_ATTACKER_AND_DEFENDER_NOT_ADJACENT); return; } }
void arrow::update_symbols() { if (!valid_path(path_)) { WRN_ARR << "arrow::update_symbols called with invalid path\n"; return; } symbols_map_.clear(); invalidate_arrow_path(path_); std::string const mods = "~RC(FF00FF>"+ color_ + ")"; //magenta to current color std::string const dirname = "arrows/"; map_location::DIRECTION exit_dir = map_location::NDIRECTIONS; map_location::DIRECTION enter_dir = map_location::NDIRECTIONS; std::string prefix = ""; std::string suffix = ""; std::string image_filename = ""; arrow_path_t::const_iterator const arrow_start_hex = path_.begin(); arrow_path_t::const_iterator const arrow_pre_end_hex = path_.end() - 2; arrow_path_t::const_iterator const arrow_end_hex = path_.end() - 1; bool start = false; bool pre_end = false; bool end = false; bool teleport_out = false; bool teleport_in = false; arrow_path_t::iterator hex; for (hex = path_.begin(); hex != path_.end(); ++hex) { prefix = ""; suffix = ""; image_filename = ""; start = pre_end = end = false; // teleport in if we teleported out last hex teleport_in = teleport_out; teleport_out = false; // Determine some special cases if (hex == arrow_start_hex) start = true; if (hex == arrow_pre_end_hex) pre_end = true; else if (hex == arrow_end_hex) end = true; if (hex != arrow_end_hex && !tiles_adjacent(*hex, *(hex + 1))) teleport_out = true; // calculate enter and exit directions, if available enter_dir = map_location::NDIRECTIONS; if (!start && !teleport_in) { enter_dir = hex->get_relative_dir(*(hex-1)); } exit_dir = map_location::NDIRECTIONS; if (!end && !teleport_out) { exit_dir = hex->get_relative_dir(*(hex+1)); } // Now figure out the actual images if (teleport_out) { prefix = "teleport-out"; if (enter_dir != map_location::NDIRECTIONS) { suffix = map_location::write_direction(enter_dir); } } else if (teleport_in) { prefix = "teleport-in"; if (exit_dir != map_location::NDIRECTIONS) { suffix = map_location::write_direction(exit_dir); } } else if (start) { prefix = "start"; suffix = map_location::write_direction(exit_dir); if (pre_end) { suffix = suffix + "_ending"; } } else if (end) { prefix = "end"; suffix = map_location::write_direction(enter_dir); } else { std::string enter, exit; enter = map_location::write_direction(enter_dir); exit = map_location::write_direction(exit_dir); if (pre_end) { exit = exit + "_ending"; } assert(abs(enter_dir - exit_dir) > 1); //impossible turn? if (enter_dir < exit_dir) { prefix = enter; suffix = exit; } else //(enter_dir > exit_dir) { prefix = exit; suffix = enter; } } image_filename = dirname + style_ + "/" + prefix; if (suffix != "") { image_filename += ("-" + suffix); } image_filename += ".png"; assert(image_filename != ""); image::locator image = image::locator(image_filename, mods); if (!image.file_exists()) { ERR_ARR << "Image " << image_filename << " not found.\n"; image = image::locator(game_config::images::missing); } symbols_map_[*hex] = image; } }
std::vector<surface> footsteps_images(const map_location& loc, const pathfind::marked_route & route_, const display_context * dc_) { std::vector<surface> res; if (route_.steps.size() < 2) { return res; // no real "route" } std::vector<map_location>::const_iterator i = std::find(route_.steps.begin(),route_.steps.end(),loc); if( i == route_.steps.end()) { return res; // not on the route } // Check which footsteps images of game_config we will use int move_cost = 1; const unit_map::const_iterator u = dc_->units().find(route_.steps.front()); if(u != dc_->units().end()) { move_cost = u->movement_cost(dc_->map().get_terrain(loc)); } int image_number = std::min<int>(move_cost, game_config::foot_speed_prefix.size()); if (image_number < 1) { return res; // Invalid movement cost or no images } const std::string foot_speed_prefix = game_config::foot_speed_prefix[image_number-1]; surface teleport = NULL; // We draw 2 half-hex (with possibly different directions), // but skip the first for the first step. const int first_half = (i == route_.steps.begin()) ? 1 : 0; // and the second for the last step const int second_half = (i+1 == route_.steps.end()) ? 0 : 1; for (int h = first_half; h <= second_half; ++h) { const std::string sense( h==0 ? "-in" : "-out" ); if (!tiles_adjacent(*(i+(h-1)), *(i+h))) { std::string teleport_image = h==0 ? game_config::foot_teleport_enter : game_config::foot_teleport_exit; teleport = image::get_image(teleport_image, image::SCALED_TO_HEX); continue; } // In function of the half, use the incoming or outgoing direction map_location::DIRECTION dir = (i+(h-1))->get_relative_dir(*(i+h)); std::string rotate; if (dir > map_location::SOUTH_EAST) { // No image, take the opposite direction and do a 180 rotation dir = i->get_opposite_dir(dir); rotate = "~FL(horiz)~FL(vert)"; } const std::string image = foot_speed_prefix + sense + "-" + i->write_direction(dir) + ".png" + rotate; res.push_back(image::get_image(image, image::SCALED_TO_HEX)); } // we draw teleport image (if any) in last if (teleport != NULL) res.push_back(teleport); return res; }