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 ); }
time_t Schedule::GetNextTime(void) { time_t now; time(&now); time_t next_time = get_next_time(now+1); // Do not start sooner as next second if(next_time<=now) return now+86400*365; // Prevent from starting in the past return next_time; }
time_t Schedule::get_next_time(time_t now) { time_t first; struct tm now_t; struct tm first_t; int time_level_now[SCHEDULE_LEVEL_MONTH+1]; int time_level_first[SCHEDULE_LEVEL_MONTH+1]; // Extract current time localtime_r(&now,&now_t); time_level_now[SCHEDULE_LEVEL_SEC] = now_t.tm_sec; time_level_now[SCHEDULE_LEVEL_MIN] = now_t.tm_min; time_level_now[SCHEDULE_LEVEL_HOUR] = now_t.tm_hour; time_level_now[SCHEDULE_LEVEL_DAY] = now_t.tm_mday-1; time_level_now[SCHEDULE_LEVEL_MONTH] = now_t.tm_mon; // Find first possible time in each level (seconds, minutes, hours, days, months) int next_level_offset = 0, current_level_offset = 0; for(int level=0;level<=SCHEDULE_LEVEL_MONTH;level++) { // Get new level properties int offset = GetScheduleOffset(level); int length = GetScheduleLength(level); // Reset reminder current_level_offset = next_level_offset; next_level_offset = 0; // Find if all subsequent levels are possible bool next_levels_valid = true; for(int k=level+1;k<=SCHEDULE_LEVEL_MONTH;k++) { if(!schedule[GetScheduleOffset(k)+time_level_now[k]]) { next_levels_valid = false; break; } } int i,j; for(i=0;i<length;i++) { if(next_levels_valid) j = (time_level_now[level]+i+current_level_offset)%length; // If all subsequent levels are valid, we can start from now else j = i; // We have to start as soon as possible if(schedule[offset+j]) // check if schedule is possible at the current level { time_level_first[level] = j; if(next_levels_valid && j<time_level_now[level]+current_level_offset) next_level_offset = 1; // Nothing has been found between now and the end of the level, so hold a reminder (we will start +1 in the next level) break; } } } memset(&first_t,0,sizeof(struct tm)); first_t.tm_sec = time_level_first[SCHEDULE_LEVEL_SEC]; first_t.tm_min = time_level_first[SCHEDULE_LEVEL_MIN]; first_t.tm_hour = time_level_first[SCHEDULE_LEVEL_HOUR]; first_t.tm_mday = time_level_first[SCHEDULE_LEVEL_DAY]+1; first_t.tm_mon = time_level_first[SCHEDULE_LEVEL_MONTH]; first_t.tm_year = now_t.tm_year+next_level_offset; first_t.tm_isdst = -1; first = mktime(&first_t); if(first_t.tm_mday!=time_level_first[SCHEDULE_LEVEL_DAY]+1 || first_t.tm_mon!=time_level_first[SCHEDULE_LEVEL_MONTH]) { // Date is invalid, try next possible time return get_next_time(first); } if(!schedule[GetScheduleOffset(SCHEDULE_LEVEL_WDAY)+first_t.tm_wday]) { // We found a matching day but week of day is wrong, try from next day first_t.tm_min = 0; first_t.tm_hour = 0; first_t.tm_mday++; first_t.tm_isdst = -1; first = mktime(&first_t); return get_next_time(first); } // Found it ! return first; }
// ------------------------------------------------------------------------ // 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(); } }