void t_move_missile::on_idle() { t_uint32 new_time = get_time(); // update animation (if any) if (elapsed_time( new_time, m_last_update_time ) >= m_delay ) { int frame = m_missile.get_current_frame_num(); frame++; if (frame >= m_missile.get_frame_count()) frame = 0; m_battlefield.set_current_frame_num( m_missile, frame ); m_last_update_time = new_time; } t_map_point_3d position; t_uint32 next_time = get_next_time() - get_delay(); int skip_limit = 1; // move missile forward one space while (elapsed_time( new_time, next_time ) >= 0 && skip_limit-- > 0 ) { next_time += get_delay(); if (m_distance_left <= 0) { t_idle_ptr reference = this; suspend_idle_processing(); m_battlefield.remove_object( &m_missile ); animation_ended(); m_end_handler( m_attacker, m_target_position ); return; } t_map_point_3d delta; int distance; // limit distance moved to distance left position = m_missile.get_position(); distance = m_move_distance; if (distance > m_distance_left) distance = m_distance_left; m_distance_left -= distance; // add distance to accumulator m_sum += m_delta * distance; // find integer portion of moved distance delta = m_sum / m_distance; position += delta; m_sum -= delta * m_distance; // calculate parabolic arc if (m_is_parabolic) { position.height += m_vertical_velocity - k_gravity; m_vertical_velocity -= k_gravity << 1; } } set_next_time( next_time ); m_battlefield.move_object( m_missile, position ); }
// ------------------------------------------------------------------------ // do movement that's hidden // ------------------------------------------------------------------------ void t_army_mover::do_hidden_move() { if (m_is_visible) return; if (m_path.size() == 0) { finish_path(); return; } t_adventure_map const& map = *m_army->get_map(); t_player& player = map.get_player(); int team = player.get_team(); declare_timer( timer_1, "do_hidden_movement" ); while (!m_is_visible && !m_halted) { t_adventure_path_point& point = m_path[m_step]; m_army->move( point ); expend_movement( point.move_cost ); mark_eluded_armies(); if (m_step == m_path.size() - 1) { finish_path(); return; } trigger_event(); if (m_halted) return; m_is_visible = !m_army->hidden_by_fog_of_war( team ) && show_enemy_moves(); if (m_is_visible) break; // break here, because start_new_square will increment step. ++m_step; declare_timer( timer_2, "on_starting_new_square: hidden" ); on_starting_new_square(); } if (m_halted) return; m_army->set_action( k_adv_actor_action_walk ); m_distance = compute_overall_distance( m_path, m_step + 1 ); start_new_square(); prepare_move( 0 ); set_next_time( get_time() + get_delay() ); }
void set_step_interval(const Real value) { set_next_time(the_current_time_ + value); }
// ------------------------------------------------------------------------ // Initialize from local or derived constructor. If use_army_path is false, // m_path must already be set up. // ------------------------------------------------------------------------ void t_army_mover::initialize( t_adventure_map_window* window, t_army* army, bool limit_move, t_adventure_path_finder const* path_finder, bool use_army_path ) { m_window = window; m_army = army; m_in_trigger = false; m_exceeded_move_limit = false; m_is_visible = false; m_movement_expended = 0; m_has_trigger = false; m_landing = false; m_limit_move = limit_move; m_original_position = army->get_position(); t_adventure_map& map = *army->get_map(); if ( use_army_path ) { t_adventure_path path = army->get_path(); int i; int move_left = army->get_movement(); bool is_boat = army->is_boat(); bool enemy_enforced_dest = false; t_creature_array const* restricting_enemy = NULL; t_adv_map_point restricted_dest; t_player* owner = army->get_owner(); bool is_computer = owner && owner->is_computer(); bool built_boat = false; bool hidden_enemy = false; // copy path until we run out of movement or encounter a trigger for (i = path.size() - 1; i >= 0; i--) { t_adventure_path_point& point = path[i]; // If the path goes into the attack radius of a hidden enemy // then truncate the path if ( path_finder != 0 && point.actual_enemy_adjacent && point.actual_enemy_distance > 0 && ( !point.visible_enemy_adjacent || point.actual_enemy_direction != point.visible_enemy_direction || point.actual_enemy_distance != point.visible_enemy_distance )) { restricting_enemy = find_enemy( map, *path_finder, point, *m_army ); if (restricting_enemy != 0) { int stealth_advantage; stealth_advantage = restricting_enemy->get_stealth_level() - m_army->get_anti_stealth_level(); if (stealth_advantage <= 0) break; if (stealth_advantage == 1 || restricting_enemy->get_owner_number() < 0) hidden_enemy = true; } } if ( path_finder && ( point.visible_restricts_movement || enemy_enforced_dest ) ) { if (enemy_enforced_dest) { if ( (point != restricted_dest) && (point != restricting_enemy->get_position()) ) break; } else { restricting_enemy = find_restrictive_enemy( map, *path_finder, point, *m_army ); if (restricting_enemy != NULL) enemy_enforced_dest = true; } restricted_dest = point + get_direction_offset( point.actual_enemy_direction ); } if (point.move_cost > move_left && limit_move) { m_actual_destination = point.last_point; m_exceeded_move_limit = true; break; } if (map.get_trigger_object( point.last_point, point.direction, army )) { m_has_trigger = true; m_trigger_point = point; } if (is_boat) { if (!map.is_ocean( point )) { m_landing = true; m_trigger_point = point; break; } } else if (is_computer && !m_has_trigger && map.is_ocean( point ) && !m_exceeded_move_limit) { t_adventure_tile const& last_tile = map[point]; t_hero* most_spell_points = NULL; if ( map.has_empty_boat( *m_army->get_owner() ) ) { int most_spell_points_count = 0; for (int i = 0; i < t_creature_array::k_size; i++) { t_hero* hero = (*m_army)[i].get_hero(); if (hero && hero->can_cast( k_spell_summon_boat )) { int cur_spell_points = hero->get_spell_points(); if ( (most_spell_points == NULL) || ( cur_spell_points > most_spell_points_count ) ) { most_spell_points = hero; most_spell_points_count = cur_spell_points; } } } } if (most_spell_points != NULL) { army->get_adventure_frame()->ai_cast_summon_boat( *m_army, *most_spell_points, point ); } else if (last_tile.ai_can_build_ship()) { t_adventure_object& object = map.get_adv_object(last_tile.ai_get_shipyard_id()); t_adv_shipyard* shipyard = dynamic_cast< t_adv_shipyard* >( &object ); t_adv_map_point boat_position; if (shipyard != NULL) built_boat = shipyard->find_new_ship_position( boat_position ); else { t_town* town = object.get_town(); if (town) { if ( !town->has( k_town_shipyard) ) { if (town->has_built()) break; town->buy_building( k_town_shipyard ); } built_boat = town->find_new_ship_position( boat_position, false ); } } if (built_boat) { t_army* boat = new t_army( army->get_creatures().get_leader().get_alignment() ); boat->set_owner( army->get_owner_number() ); boat->place( map, boat_position ); owner->spend( army->get_ai()->get_boat_cost() ); // This destination pick wouldn't have been // made unless he already had the cash. } } } if (map[point].blocks_army( *army, map, point.on_bridge, k_path_search_move_army )) break; // if the path actually enters a cell of an enemy, stop. if (point.actual_enemy_adjacent && point.actual_enemy_distance == 0) break; m_path.push_back( point ); if (m_has_trigger || built_boat || hidden_enemy) break; } } m_halted = false; m_step = -1; m_distance = compute_overall_distance( m_path, 0 ); if (m_path.size() == 0) { m_cell_distance = 0; m_crossing_point = -1; m_distance = 0; m_frames = 0; m_divisor = 1; m_delta = t_screen_point(0,0); m_offset = t_screen_point(0,0); m_distance_delta = 0; m_is_visible = !m_army->hidden_by_fog_of_war( map.get_player().get_team() ); } else { m_army->set_action( k_adv_actor_action_prewalk ); start_new_square(); prepare_move( 0 ); } set_next_time( get_time() ); }
// ------------------------------------------------------------------------ // class to move army on adventure map // ------------------------------------------------------------------------ void t_army_mover::do_movement() { int frame = m_army->get_frame(); int frame_count = m_army->get_frame_count(); t_adv_actor_action_id action = m_army->get_action(); t_uint32 current_time = get_time(); t_uint32 next_time = get_next_time() - get_delay(); t_counted_ptr<t_army_mover> ref = this; t_window_ptr adv_frame = m_window->get_frame(); // temporary reference to prevent the adventure frame // from removing itself if the game is over bool entered_new_square = false; declare_timer( timer_1, "do_movement" ); while ( m_frames > 0 && (!m_is_visible || elapsed_time( current_time, next_time ) >= 0) ) { m_offset += m_delta; m_cell_distance -= m_distance_delta; if (m_cell_distance <= m_crossing_point) { enter_new_square(); } m_army->set_frame_offset( m_offset / m_divisor ); frame++; if (action == k_adv_actor_action_walk && frame == frame_count) frame = 0; if (frame < frame_count) m_army->set_frame( frame ); m_frames--; if (m_is_visible) next_time += get_delay(); } if (m_is_visible) set_next_time( next_time ); // if m_frames is zero, we've hit the center of the cell, or we've // finished a prewalk / walk / postwalk sequence if (m_frames == 0) { if ((action == k_adv_actor_action_postwalk || m_path.size() == 0) && m_distance + m_cell_distance == 0) { finish_path(); return; } if (m_cell_distance == 0) { start_new_square(); entered_new_square = true; trigger_event(); if (m_halted) return; } else { m_cell_distance /= m_divisor; m_crossing_point /= m_divisor; } prepare_move( frame ); } if (entered_new_square) { declare_timer( timer_2, "on_starting_new_square" ); on_starting_new_square(); } }