示例#1
0
/**
 * Animates a teleportation between hexes.
 *
 * @param a          The starting hex.
 * @param b          The ending hex.
 * @param temp_unit  The unit to animate (historically, a temporary unit).
 * @param disp       The game display. Assumed neither locked nor faked.
 */
static void teleport_unit_between(const map_location& a, const map_location& b,
                                  unit& temp_unit, display& disp)
{
	if ( disp.fogged(a) && disp.fogged(b) ) {
		return;
	}

	temp_unit.set_location(a);
	if ( !disp.fogged(a) ) { // teleport
		disp.invalidate(a);
		temp_unit.set_facing(a.get_relative_dir(b));
		disp.scroll_to_tiles(a, b, game_display::ONSCREEN, true, 0.0, false);
		unit_animator animator;
		animator.add_animation(&temp_unit,"pre_teleport",a);
		animator.start_animations();
		animator.wait_for_end();
	}

	temp_unit.set_location(b);
	if ( !disp.fogged(b) ) { // teleport
		disp.invalidate(b);
		temp_unit.set_facing(a.get_relative_dir(b));
		disp.scroll_to_tiles(b, a, game_display::ONSCREEN, true, 0.0, false);
		unit_animator animator;
		animator.add_animation(&temp_unit,"post_teleport",b);
		animator.start_animations();
		animator.wait_for_end();
	}

	temp_unit.anim_comp().set_standing();
	disp.update_display();
	events::pump();
}
示例#2
0
static void teleport_unit_between( const map_location& a, const map_location& b, unit& temp_unit)
{
	game_display* disp = game_display::get_singleton();
	if(!disp || disp->video().update_locked() || disp->video().faked() || (disp->fogged(a) && disp->fogged(b))) {
		return;
	}
	disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);

	temp_unit.set_location(a);
	if (!disp->fogged(a)) { // teleport
		disp->invalidate(temp_unit.get_location());
		temp_unit.set_facing(a.get_relative_dir(b));
		unit_animator animator;
		animator.add_animation(&temp_unit,"pre_teleport",a);
		animator.start_animations();
		animator.wait_for_end();
	}

	temp_unit.set_location(b);
	if (!disp->fogged(b)) { // teleport
		disp->invalidate(temp_unit.get_location());
		temp_unit.set_facing(a.get_relative_dir(b));
		disp->scroll_to_tiles(b,a,game_display::ONSCREEN,true,0.0,false);
		unit_animator animator;
		animator.add_animation(&temp_unit,"post_teleport",b);
		animator.start_animations();
		animator.wait_for_end();
	}

	temp_unit.set_standing();
	disp->update_display();
	events::pump();
}
示例#3
0
void unit_recruited(const map_location& loc,const map_location& leader_loc)
{
	game_display* disp = game_display::get_singleton();
	if(!disp || disp->video().update_locked() || disp->video().faked() ||disp->fogged(loc)) return;
	unit_map::const_iterator u = disp->get_units().find(loc);
	if(u == disp->get_units().end()) return;
	u->set_hidden(true);

	unit_animator animator;
	if(leader_loc != map_location::null_location()) {
		unit_map::const_iterator leader = disp->get_units().find(leader_loc);
		if(leader == disp->get_units().end()) return;
		disp->scroll_to_tiles(loc,leader_loc,game_display::ONSCREEN,true,0.0,false);
		leader->set_facing(leader_loc.get_relative_dir(loc));
		animator.add_animation(&*leader, "recruiting", leader_loc, loc, 0, true);
	} else {
		disp->scroll_to_tile(loc,game_display::ONSCREEN,true,false);
	}

	disp->draw();
	u->set_hidden(false);
	animator.add_animation(&*u, "recruited", loc, leader_loc);
	animator.start_animations();
	animator.wait_for_end();
	animator.set_all_standing();
	if (loc==disp->mouseover_hex()) disp->invalidate_unit();
}
示例#4
0
void unit_draw_weapon(const map_location& loc, unit& attacker,
		const attack_type* attack,const attack_type* secondary_attack, const map_location& defender_loc,unit* defender)
{
	display* disp = display::get_singleton();
	if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(loc) || preferences::show_combat() == false) {
		return;
	}
	unit_animator animator;
	attacker.set_facing(loc.get_relative_dir(defender_loc));
	defender->set_facing(defender_loc.get_relative_dir(loc));
	animator.add_animation(&attacker,"draw_weapon",loc,defender_loc,0,false,"",0,unit_animation::hit_type::HIT,attack,secondary_attack,0);
	animator.add_animation(defender,"draw_weapon",defender_loc,loc,0,false,"",0,unit_animation::hit_type::MISS,secondary_attack,attack,0);
	animator.start_animations();
	animator.wait_for_end();

}
示例#5
0
/**
 * Animates a single step between hexes.
 * This will return before the animation actually finishes, allowing other
 * processing to occur during the animation.
 *
 * @param a          The starting hex.
 * @param b          The ending hex.
 * @param temp_unit  The unit to animate (historically, a temporary unit).
 * @param step_num   The number of steps taken so far (used to pick an animation).
 * @param step_left  The number of steps remaining (used to pick an animation).
 * @param animator   The unit_animator to use. This is assumed clear when we start,
 *                   but will likely not be clear when we return.
 * @param disp       The game display. Assumed neither locked nor faked.
 * @returns  The animation potential until this animation will finish.
 *           INT_MIN indicates that no animation is pending.
 */
static int move_unit_between(const map_location& a, const map_location& b,
                             unit_ptr temp_unit, unsigned int step_num,
                             unsigned int step_left, unit_animator & animator,
                             display& disp)
{
	if ( disp.fogged(a) && disp.fogged(b) ) {
		return INT_MIN;
	}

	temp_unit->set_location(a);
	disp.invalidate(a);
	temp_unit->set_facing(a.get_relative_dir(b));
	animator.replace_anim_if_invalid(temp_unit.get(),"movement",a,b,step_num,
			false,"",0,unit_animation::hit_type::INVALID,nullptr,nullptr,step_left);
	animator.start_animations();
	animator.pause_animation();
	disp.scroll_to_tiles(a, b, game_display::ONSCREEN, true, 0.0, false);
	animator.restart_animation();

	// useless now, previous short draw() just did one
	// new_animation_frame();

	int target_time = animator.get_animation_time_potential();
		// target_time must be short to avoid jumpy move
		// std::cout << "target time: " << target_time << "\n";
	// we round it to the next multiple of 200
	target_time += 200;
	target_time -= target_time%200;

	// This code causes backwards teleport because the time > 200 causes offset > 1.0
	// which will not match with the following -1.0
	// if(  target_time - animator.get_animation_time_potential() < 100 ) target_time +=200;

	return target_time;
}
示例#6
0
void unit_frame::redraw(const int frame_time,bool first_time,const map_location & src,const map_location & dst,int*halo_id,const frame_parameters & animation_val,const frame_parameters & engine_val,const bool primary)const
{
	const int xsrc = game_display::get_singleton()->get_location_x(src);
	const int ysrc = game_display::get_singleton()->get_location_y(src);
	const int xdst = game_display::get_singleton()->get_location_x(dst);
	const int ydst = game_display::get_singleton()->get_location_y(dst);
	const map_location::DIRECTION direction = src.get_relative_dir(dst);

	const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val,primary);
	double tmp_offset = current_data.offset;

		// debug code allowing to see the number of frames and their position
		// you need to add a '/n'
		// if (tmp_offset) std::cout << (int)(tmp_offset*100) << ",";

	int d2 = game_display::get_singleton()->hex_size() / 2;
	if(first_time ) {
		// stuff sthat should be done only once per frame
		if(!current_data.sound.empty()  ) {
			sound::play_sound(current_data.sound);
		}
		if(!current_data.text.empty()  ) {
			game_display::get_singleton()->float_label(src,current_data.text,
			(current_data.text_color & 0x00FF0000) >> 16,
			(current_data.text_color & 0x0000FF00) >> 8,
			(current_data.text_color & 0x000000FF) >> 0);
		}
	}
示例#7
0
static void move_unit_between(const map_location& a, const map_location& b, unit& temp_unit,unsigned int step_num,unsigned int step_left)
{
	game_display* disp = game_display::get_singleton();
	if(!disp || disp->video().update_locked() || disp->video().faked() || (disp->fogged(a) && disp->fogged(b))) {
		return;
	}

	temp_unit.set_location(a);
	disp->invalidate(temp_unit.get_location());
	temp_unit.set_facing(a.get_relative_dir(b));
	unit_animator animator;
	animator.replace_anim_if_invalid(&temp_unit,"movement",a,b,step_num,
			false,"",0,unit_animation::INVALID,NULL,NULL,step_left);
	animator.start_animations();
        animator.pause_animation();
	disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);
        animator.restart_animation();

	// useless now, previous short draw() just did one
	// new_animation_frame();

	int target_time = animator.get_animation_time_potential();

		// target_time must be short to avoid jumpy move
		// std::cout << "target time: " << target_time << "\n";
	// we round it to the next multile of 200
	target_time += 200;
	target_time -= target_time%200;

	// This code causes backwards teleport because the time > 200 causes offset > 1.0
	// which will not match with the following -1.0
	// if(  target_time - animator.get_animation_time_potential() < 100 ) target_time +=200;

	animator.wait_until(target_time);
		// debug code, see unit_frame::redraw()
		// std::cout << "   end\n";
	map_location arr[6];
	get_adjacent_tiles(a, arr);
	unsigned int i;
	for (i = 0; i < 6; ++i) {
		disp->invalidate(arr[i]);
	}
	get_adjacent_tiles(b, arr);
	for (i = 0; i < 6; ++i) {
		disp->invalidate(arr[i]);
	}
}
示例#8
0
void unit_attack(display * disp, game_board & board,
                 const map_location& a, const map_location& b, int damage,
                 const attack_type& attack, const attack_type* secondary_attack,
                 int swing,std::string hit_text,int drain_amount,std::string att_text, const std::vector<std::string>* extra_hit_sounds)
{
	if(!disp ||disp->video().update_locked() || disp->video().faked() ||
			(disp->fogged(a) && disp->fogged(b)) || preferences::show_combat() == false) {
		return;
	}
	//const unit_map& units = disp->get_units();
	disp->select_hex(map_location::null_location());

	// scroll such that there is at least half a hex spacing around fighters
	disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.5,false);

	log_scope("unit_attack");

	const unit_map::const_iterator att = board.units().find(a);
	assert(att.valid());
	const unit& attacker = *att;

	const unit_map::iterator def = board.find_unit(b);
	assert(def.valid());
	unit &defender = *def;
	int def_hitpoints = defender.hitpoints();

	att->set_facing(a.get_relative_dir(b));
	def->set_facing(b.get_relative_dir(a));
	defender.set_facing(b.get_relative_dir(a));


	unit_animator animator;
	unit_ability_list leaders = attacker.get_abilities("leadership");
	unit_ability_list helpers = defender.get_abilities("resistance");

	std::string text   = number_and_text(damage, hit_text);
	std::string text_2 = number_and_text(abs(drain_amount), att_text);

	unit_animation::hit_type hit_type;
	if(damage >= defender.hitpoints()) {
		hit_type = unit_animation::hit_type::KILL;
	} else if(damage > 0) {
		hit_type = unit_animation::hit_type::HIT;
	}else {
		hit_type = unit_animation::hit_type::MISS;
	}
	animator.add_animation(&attacker, "attack", att->get_location(),
		def->get_location(), damage, true,  text_2,
		(drain_amount >= 0) ? display::rgb(0, 255, 0) : display::rgb(255, 0, 0),
		hit_type, &attack, secondary_attack, swing);

	// note that we take an anim from the real unit, we'll use it later
	const unit_animation *defender_anim = def->anim_comp().choose_animation(*disp,
		def->get_location(), "defend", att->get_location(), damage,
		hit_type, &attack, secondary_attack, swing);
	animator.add_animation(&defender, defender_anim, def->get_location(),
		true,  text , display::rgb(255, 0, 0));

	for (const unit_ability & ability : leaders) {
		if(ability.second == a) continue;
		if(ability.second == b) continue;
		unit_map::const_iterator leader = board.units().find(ability.second);
		assert(leader.valid());
		leader->set_facing(ability.second.get_relative_dir(a));
		animator.add_animation(&*leader, "leading", ability.second,
			att->get_location(), damage, true,  "", 0,
			hit_type, &attack, secondary_attack, swing);
	}
	for (const unit_ability & ability : helpers) {
		if(ability.second == a) continue;
		if(ability.second == b) continue;
		unit_map::const_iterator helper = board.units().find(ability.second);
		assert(helper.valid());
		helper->set_facing(ability.second.get_relative_dir(b));
		animator.add_animation(&*helper, "resistance", ability.second,
			def->get_location(), damage, true,  "", 0,
			hit_type, &attack, secondary_attack, swing);
	}


	animator.start_animations();
	animator.wait_until(0);
	int damage_left = damage;
	bool extra_hit_sounds_played = false;
	while(damage_left > 0 && !animator.would_end()) {
		if(!extra_hit_sounds_played && extra_hit_sounds != nullptr) {
			for (std::string hit_sound : *extra_hit_sounds) {
				sound::play_sound(hit_sound);
			}
			extra_hit_sounds_played = true;
		}

		int step_left = (animator.get_end_time() - animator.get_animation_time() )/50;
		if(step_left < 1) step_left = 1;
		int removed_hp =  damage_left/step_left ;
		if(removed_hp < 1) removed_hp = 1;
		defender.take_hit(removed_hp);
		damage_left -= removed_hp;
		animator.wait_until(animator.get_animation_time_potential() +50);
	}
	animator.wait_for_end();
	// pass the animation back to the real unit
	def->anim_comp().start_animation(animator.get_end_time(), defender_anim, true);
	reset_helpers(&*att, &*def);
	def->set_hitpoints(def_hitpoints);
}
示例#9
0
void unit_attack(
                 const map_location& a, const map_location& b, int damage,
                 const attack_type& attack, const attack_type* secondary_attack,
		  int swing,std::string hit_text,bool drain,std::string att_text)
{
	game_display* disp = game_display::get_singleton();
	if(!disp ||disp->video().update_locked() || disp->video().faked() ||
			(disp->fogged(a) && disp->fogged(b)) || preferences::show_combat() == false) {
		return;
	}
	unit_map& units = disp->get_units();
	disp->select_hex(map_location::null_location);

	// scroll such that there is at least half a hex spacing around fighters
	disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.5,false);

	log_scope("unit_attack");

	const unit_map::iterator att = units.find(a);
	assert(att != units.end());
	unit& attacker = *att;

	const unit_map::iterator def = units.find(b);
	assert(def != units.end());
	unit &defender = *def;
	int def_hitpoints = defender.hitpoints();

	att->set_facing(a.get_relative_dir(b));
	def->set_facing(b.get_relative_dir(a));
	defender.set_facing(b.get_relative_dir(a));


	unit_animator animator;
	unit_ability_list leaders = attacker.get_abilities("leadership");
	unit_ability_list helpers = defender.get_abilities("resistance");

	std::string text ;
	if(damage) text = lexical_cast<std::string>(damage);
	if(!hit_text.empty()) {
		text.insert(text.begin(),hit_text.size()/2,' ');
		text = text + "\n" + hit_text;
	}

	std::string text_2 ;
	if(drain && damage) text_2 = lexical_cast<std::string>(std::min<int>(damage,defender.hitpoints())/2);
	if(!att_text.empty()) {
		text_2.insert(text_2.begin(),att_text.size()/2,' ');
		text_2 = text_2 + "\n" + att_text;
	}

	unit_animation::hit_type hit_type;
	if(damage >= defender.hitpoints()) {
		hit_type = unit_animation::KILL;
	} else if(damage > 0) {
		hit_type = unit_animation::HIT;
	}else {
		hit_type = unit_animation::MISS;
	}
	animator.add_animation(&attacker, "attack", att->get_location(),
		def->get_location(), damage, true,  text_2,
		display::rgb(0, 255, 0), hit_type, &attack, secondary_attack,
		swing);

	// note that we take an anim from the real unit, we'll use it later
	const unit_animation *defender_anim = def->choose_animation(*disp,
		def->get_location(), "defend", att->get_location(), damage,
		hit_type, &attack, secondary_attack, swing);
	animator.add_animation(&defender, defender_anim, def->get_location(),
		true,  text , display::rgb(255, 0, 0));

	for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); ++itor) {
		if(itor->second == a) continue;
		if(itor->second == b) continue;
		unit_map::iterator leader = units.find(itor->second);
		assert(leader != units.end());
		leader->set_facing(itor->second.get_relative_dir(a));
		animator.add_animation(&*leader, "leading", itor->second,
			att->get_location(), damage, true,  "", 0,
			hit_type, &attack, secondary_attack, swing);
	}
	for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); ++itor) {
		if(itor->second == a) continue;
		if(itor->second == b) continue;
		unit_map::iterator helper = units.find(itor->second);
		assert(helper != units.end());
		helper->set_facing(itor->second.get_relative_dir(b));
		animator.add_animation(&*helper, "resistance", itor->second,
			def->get_location(), damage, true,  "", 0,
			hit_type, &attack, secondary_attack, swing);
	}


	animator.start_animations();
	animator.wait_until(0);
	int damage_left = damage;
	while(damage_left > 0 && !animator.would_end()) {
		int step_left = (animator.get_end_time() - animator.get_animation_time() )/50;
		if(step_left < 1) step_left = 1;
		int removed_hp =  damage_left/step_left ;
		if(removed_hp < 1) removed_hp = 1;
		defender.take_hit(removed_hp);
		damage_left -= removed_hp;
		animator.wait_until(animator.get_animation_time_potential() +50);
	}
	animator.wait_for_end();
	// pass the animation back to the real unit
	def->start_animation(animator.get_end_time(), defender_anim, true);
	reset_helpers(&*att, &*def);
	def->set_hitpoints(def_hitpoints);
}