Example #1
0
//------- Begin of function Unit::think_change_attack_target -------//
//
// When the unit is attacking a firm or town, look out for enemy units
// to attack. Enemy units should be attacked first.
//
int Unit::think_change_attack_target()
{
	err_when( !nation_recno );		// only for nation units

	//----------------------------------------------//

	int attackRange	  = MAX(attack_range, 8);
	int attackScanRange = attackRange*2+1;

	int		 xOffset, yOffset;
	int		 xLoc, yLoc;
	Location* locPtr;
	int		 curXLoc = next_x_loc(), curYLoc = next_y_loc();
	BYTE	 	 regionId = world.get_region_id(curXLoc, curYLoc);

	for( int i=2 ; i<attackScanRange*attackScanRange ; i++ )
	{
		m.cal_move_around_a_point(i, attackScanRange, attackScanRange, xOffset, yOffset);

		xLoc = curXLoc + xOffset;
		yLoc = curYLoc + yOffset;

		xLoc = MAX(0, xLoc);
		xLoc = MIN(MAX_WORLD_X_LOC-1, xLoc);

		yLoc = MAX(0, yLoc);
		yLoc = MIN(MAX_WORLD_Y_LOC-1, yLoc);

		locPtr = world.get_loc(xLoc, yLoc);

		if( locPtr->region_id != regionId )
			continue;

		//----- if there is a unit on the location ------//

		if( locPtr->has_unit(UNIT_LAND) )
		{
			int unitRecno = locPtr->unit_recno(UNIT_LAND);

			if( unit_array.is_deleted(unitRecno) )
				continue;

			if( unit_array[unitRecno]->nation_recno != nation_recno &&
				 idle_detect_unit_checking(unitRecno) )
			{
				save_original_action();

				original_target_x_loc = xLoc;
				original_target_y_loc = yLoc;

				attack_unit(xLoc, yLoc);
				return 1;
			}
		}
	}

	return 0;
}
Example #2
0
void attack_result::do_execute()
{
	LOG_AI_ACTIONS << "start of execution of: "<< *this << std::endl;
	// Stop the user from issuing any commands while the unit is attacking
	const events::command_disabler disable_commands;

	//@note: yes, this is a decision done here. It's that way because we want to allow a simpler attack 'with whatever weapon is considered best', and because we want to allow the defender to pick it's weapon. That's why aggression is needed. a cleaner solution is needed.
	battle_context bc(get_info().units, attacker_loc_,
		defender_loc_, attacker_weapon_, -1, aggression_);

	int attacker_weapon = bc.get_attacker_stats().attack_num;
	int defender_weapon = bc.get_defender_stats().attack_num;

	if(attacker_weapon < 0) {
		set_error(E_UNABLE_TO_CHOOSE_ATTACKER_WEAPON);
		return;
	}

	const unit *d_ = get_unit(get_info(),defender_loc_);
	const unit *a_ = get_unit(get_info(),attacker_loc_);

	//@todo 1.9: change ToD to be location specific for the defender unit
	recorder.add_attack(attacker_loc_, defender_loc_, attacker_weapon, defender_weapon, a_->type_id(),
		d_->type_id(), a_->level(), d_->level(), resources::tod_manager->turn(),
		resources::tod_manager->get_time_of_day());
	rand_rng::invalidate_seed();
	rand_rng::clear_new_seed_callback();
	while (!rand_rng::has_valid_seed()) {
		manager::raise_user_interact();
		manager::raise_sync_network();
		SDL_Delay(10);
	}
	recorder.add_seed("attack", rand_rng::get_last_seed());
	attack_unit(attacker_loc_, defender_loc_, attacker_weapon, defender_weapon);
	dialogs::advance_unit(attacker_loc_, true);

	const unit_map::const_iterator defender = get_info().units.find(defender_loc_);
	if(defender != get_info().units.end()) {
		const size_t defender_team = size_t(defender->second.side()) - 1;
		if(defender_team < get_info().teams.size()) {
			dialogs::advance_unit(defender_loc_ , !get_info().teams[defender_team].is_human());
		}
	}

	set_gamestate_changed();
	//start of ugly hack. @todo 1.9 rework that via extended event system
	//until event system is reworked, we note the attack this way
	get_info().recent_attacks.insert(defender_loc_);
	//end of ugly hack
	try {
		manager::raise_gamestate_changed();
	} catch (...) {
		is_ok(); //Silences "unchecked result" warning
		throw;
	}
}
Example #3
0
void attack_unit_and_advance(const map_location &attacker, const map_location &defender,
                 int attack_with, int defend_with, bool update_display,
				 const ai::unit_advancements_aspect& ai_advancement)
{
	attack_unit(attacker, defender, attack_with, defend_with, update_display);
	unit_map::const_iterator atku = resources::units->find(attacker);
	if (atku != resources::units->end()) {
		advance_unit_at(advance_unit_params(attacker).ai_advancements(ai_advancement));
	}

	unit_map::const_iterator defu = resources::units->find(defender);
	if (defu != resources::units->end()) {
		advance_unit_at(advance_unit_params(defender).ai_advancements(ai_advancement));
	}
}
Example #4
0
//------ Begin of function Unit::handle_blocked_move_s11 -------//
// both blocked and blocking are size 1
//
void Unit::handle_blocked_move_s11(Unit *unitPtr)
{
	err_when( world.get_unit_recno(next_x_loc(), next_y_loc(), mobile_type) != sprite_recno );
	err_when( world.get_unit_recno(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->mobile_type) != unitPtr->sprite_recno );
	err_when(cur_x!=next_x || cur_y!=next_y);

	int waitTerm;
	int moveStep = move_step_magn();

	switch(unitPtr->cur_action)
	{
		//------------------------------------------------------------------------------------//
		// handle blocked for units belonging to the same nation.  For those belonging to other
		// nations, wait for it moving to other locations or search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_WAIT: // the blocking unit is waiting
				err_when(unitPtr->go_x==unitPtr->cur_x && unitPtr->go_y==unitPtr->cur_y);
		
		case SPRITE_TURN:
				if(unitPtr->nation_recno==nation_recno)
					handle_blocked_wait(unitPtr); // check for cycle wait for our nation
				else if(waiting_term>=MAX_WAITING_TERM_DIFF)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall searching
					waiting_term = 0;
				}
				else // wait
					set_wait();
				return;

		//------------------------------------------------------------------------------------//
		// We know from the cur_action of the blocking unit it is moving to another locations,
		// the blocked unit wait for a number of terms or search again.
		//------------------------------------------------------------------------------------//
		case SPRITE_MOVE:
		case SPRITE_READY_TO_MOVE:
		case SPRITE_SHIP_EXTRA_MOVE:
				if(unit_id!=UNIT_CARAVAN && unitPtr->unit_id==UNIT_CARAVAN) // don't wait for caravans, and caravans don't wait for other units
				{
					search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
				}
				else
				{
					waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
					if(waiting_term>=waitTerm)
					{
						search_or_wait();
						waiting_term = 0;
					}
					else
						set_wait();
				}
				return;

		//------------------------------------------------------------------------------------//
		// handling blocked for idle unit
		//------------------------------------------------------------------------------------//
		case SPRITE_IDLE:
				err_when(unitPtr->result_node_array!=NULL);
				if(unitPtr->action_mode==ACTION_SHIP_TO_BEACH)
				{
					//----------------------------------------------------------------------//
					// the blocking unit is trying to move to beach, so wait a number of terms,
					// or call searching again
					//----------------------------------------------------------------------//
					if(abs(unitPtr->next_x_loc()-unitPtr->action_x_loc2)<=moveStep &&
						abs(unitPtr->next_y_loc()-unitPtr->action_y_loc2)<=moveStep &&
						terrain_res[world.get_loc(unitPtr->action_x_loc2, unitPtr->action_y_loc2)->terrain_id]->average_type
						!=TERRAIN_OCEAN)
					{
						if(action_mode2==ACTION_SHIP_TO_BEACH && action_x_loc2==unitPtr->action_x_loc2 &&
							action_y_loc2==unitPtr->action_y_loc2)
						{
							int tempX, tempY;
							ship_to_beach(action_x_loc2, action_y_loc2, tempX, tempY);
						}
						else
						{
							waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
							if(waiting_term>=waitTerm)
								stop2();
							else
								set_wait();
						}
						return;
					}
				}

				if(unitPtr->nation_recno==nation_recno) //-------- same nation
				{
					//------------------------------------------------------------------------------------//
					// units from our nation
					//------------------------------------------------------------------------------------//
					if(unitPtr->unit_group_id==unit_group_id)
					{
						//--------------- from the same group -----------------//
						if(way_point_count && !unitPtr->way_point_count)
						{
							//------------ reset way point --------------//
							stop2();
							reset_way_point_array();
						}
						else if((unitPtr->next_x_loc() != move_to_x_loc || unitPtr->next_y_loc() != move_to_y_loc) &&
							(unitPtr->cur_action==SPRITE_IDLE && unitPtr->action_mode2==ACTION_STOP))
							move_to_my_loc(unitPtr); // push the blocking unit and exchange their destination
						else if(unitPtr->action_mode == ACTION_SETTLE)
							set_wait(); // wait for the settler
						else if(waiting_term>MAX_WAITING_TERM_SAME)
						{
							//---------- stop if wait too long ----------//
							terminate_move();
							waiting_term = 0;
						}
						else
							set_wait();
					}
					else if(unitPtr->action_mode2==ACTION_STOP)
						handle_blocked_by_idle_unit(unitPtr);
					else if(way_point_count && !unitPtr->way_point_count)
					{
						stop2();
						reset_way_point_array();
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				else // different nation
				{
					//------------------------------------------------------------------------------------//
					// units from other nations
					//------------------------------------------------------------------------------------//
					if(unitPtr->next_x_loc() == move_to_x_loc && unitPtr->next_y_loc() == move_to_y_loc)
					{  
						terminate_move(); // destination occupied by other unit

						if(action_mode==ACTION_ATTACK_UNIT && unitPtr->nation_recno!=nation_recno && unitPtr->sprite_recno==action_para)
						{
							err_when(action_x_loc!=unitPtr->next_x_loc() || action_y_loc!=unitPtr->next_y_loc());
							err_when(action_mode2!=ACTION_ATTACK_UNIT && action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET &&
										action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);
							err_when(action_para2!=action_para);
							err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
							
							set_dir(next_x, next_y, unitPtr->next_x, unitPtr->next_y);
							if(is_dir_correct())
								attack_unit(action_para);
							else
								set_turn();
							cur_frame  = 1;
						}
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				return;

		//------------------------------------------------------------------------------------//
		// don't wait for attackers from other nations, search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_ATTACK:
				//----------------------------------------------------------------//
				// don't wait for other nation unit, call searching again
				//----------------------------------------------------------------//
				if(nation_recno!=unitPtr->nation_recno)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1);
					return;
				}

				//------------------------------------------------------------------------------------//
				// for attackers owned by our commander, handled blocked case by case as follows.
				//------------------------------------------------------------------------------------//
				switch(unitPtr->action_mode)
				{
					case ACTION_ATTACK_UNIT:
							if(action_para && !unit_array.is_deleted(action_para))
							{
								Unit *targetPtr = unit_array[action_para];
								handle_blocked_attack_unit(unitPtr, targetPtr);
							}
							else
								search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
							break;

					case ACTION_ATTACK_FIRM:
							if(!unitPtr->action_para || firm_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_firm(unitPtr);
							break;

					case ACTION_ATTACK_TOWN:
							if(!unitPtr->action_para || town_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_town(unitPtr);
							break;

					case ACTION_ATTACK_WALL:
							if(unitPtr->action_para)
								set_wait();
							else
								handle_blocked_attack_wall(unitPtr);
							break;

					case ACTION_GO_CAST_POWER:
							set_wait();
							break;

					default: err_here();
								break;
				}
				return;

		//------------------------------------------------------------------------------------//
		// the blocked unit can pass after the blocking unit disappears in air.
		//------------------------------------------------------------------------------------//
		case SPRITE_DIE:
				set_wait();	// assume this unit will not wait too long
				return;

		default:
				err_here();
				break;
	}
	
	err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
}
Example #5
0
//for most cases, this takes world coordinates, but not always!!!
void g1_human_class::player_clicked(g1_object_class * obj, float gx, float gy,w32 command)
{
	g1_object_type convoy_type=g1_get_object_type(li_convoy.get());

	switch (command)
	{
		case DEFAULT:
			{
				if (obj && obj->player_num==team() && obj->get_flag(g1_object_class::SELECTABLE))
				{
					clear_selected();

					if (obj == commander())
					{
						selected_object = 0;
					}
					else
					{

						g1_convoy_class * c=(g1_convoy_class *)g1_object_type_array[convoy_type]->create_object(convoy_type,0);
						c->setup(obj);
						c->player_num=team();
						selected_object=c;
						selected_object->mark_as_selected();
					}
				}
				else if (selected_object.valid())
				{
					send_selected_units(gx,gy);
				}
				else
				{
					select_path(gx,gy);
				}
			} break;
		case ATTACK:
			{
				if (selected_object.valid()&&selected_object->player_num==team())
				{
					attack_unit(obj,gx,gy);
				}                  //remember: this only works if
				//target is in range
				break;
			}
		case GOTO:
			if (selected_object.valid()&&selected_object->player_num==team())
			{
				send_selected_units(gx,gy);
			}
			break;
		case SELECT:
			{
				//single objects can be selected, even if they don't
				//belong to the local user
				if (!obj/*||obj->player_num!=team()
						||!obj->get_flag(g1_object_class::SELECTABLE) */)
				{
					break;
				}

				clear_selected();

				g1_convoy_class * c=(g1_convoy_class *)g1_create_object(convoy_type);
				c->player_num=obj->player_num;
				if (!obj->get_flag(g1_object_class::SELECTABLE))
				{
					c->player_num=0;
				}              //a slight hack to prevent the user
							   //from actually sending commands
							   //to this unit.
				c->setup(obj);
				selected_object=c;
				selected_object->mark_as_selected();

				break;
			}

		case ADD_TO_LIST:
			{
				if ((selected_object.valid()&&selected_object->id!=g1_get_object_type(li_convoy.get())) ||
					!obj || obj->player_num!=team() ||
					!obj->get_flag(g1_object_class::SELECTABLE))
				{
					break;
				}
				if (!selected_object.valid())
				{
					g1_convoy_class * cn=(g1_convoy_class *) g1_create_object(convoy_type);
					cn->player_num=team();
					cn->setup(obj);
					selected_object=cn;
					cn->mark_as_selected();
					break;
				}
				((g1_convoy_class *)selected_object.get())->add_object(obj);

			} break;
		case START_DRAG:
			{
				dragstartx=gx; //Screen coordinates!!!
				dragstarty=gy;
				break;
			}

		case DRAGGING:
			{
				dragdestx=gx;
				dragdesty=gy;
				//w16 mod;
				//if (i4_current_app->get_window_manager()->shift_pressed())
				//  mod=ADD_TO_OLD;
				//else if (i4_current_app->get_window_manager()->alt_pressed())
				//    mod=SUB_FROM_OLD;
				//else
				//    mod=CLEAR_OLD;
				//select_objects_in_range(dragstartx,dragstarty,dragendx,dragendy,mod);
			} break;

		case END_DRAG:
			{
				dragstartx=dragstarty=dragdestx=dragdesty=-1;
			} break;

		case SELECT_PATH:
			{
				select_path(gx,gy);
			} break;

		default:
			break;
	}
}
Example #6
0
//--------- Begin of function Unit::monster_defend_attack_unit ---------//
// set to attack target
//
// <short> targetRecno	-	recno of the target
//
void Unit::monster_defend_attack_unit(short targetRecno)
{
	action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
	attack_unit(targetRecno);
}
Example #7
0
//--------- Begin of function Unit::defend_town_attack_unit ---------//
// set to defensive mode
//
// <short>	targetRecno	-	record of target
//
void Unit::defend_town_attack_unit(short targetRecno)
{
	action_mode2 = ACTION_DEFEND_TOWN_ATTACK_TARGET;
	attack_unit(targetRecno);
}
Example #8
0
//--------- Begin of function Unit::defense_attack_unit ---------//
// defensive attack units
//
// <short>	targetRecno	-	recno of the target
//
void Unit::defense_attack_unit(short targetRecno)
{
	action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
	attack_unit(targetRecno);
}
Example #9
0
//--------- Begin of function Unit::general_defend_mode_process_attack_target ---------//
// process unit defense action. If target is dead, action_mode changes to detect_mode
//
// return 1 if action mode changes to detect mode
// return 0 otherwise
//
int Unit::general_defend_mode_process_attack_target()
{
	Location *locPtr;
	Unit *unitPtr;
	Town *townPtr;
	Firm *firmPtr;
	SpriteInfo	*spriteInfo;
	FirmInfo		*firmInfo;
	int clearToDetect = 0;

	//------------------------------------------------------------------------------//
	// if the unit's action mode is in defensive attack action, process the corresponding
	// checking.
	//------------------------------------------------------------------------------//
	switch(action_mode)
	{
		case ACTION_ATTACK_UNIT:
				if(unit_array.is_deleted(action_para2))
					clearToDetect++;
				else
				{
					err_when(unit_array.is_deleted(action_para2));
					unitPtr = unit_array[action_para2];
					
					//if(unitPtr->cur_action==SPRITE_IDLE)
					//	clearToDetect++;

					if(!nation_can_attack(unitPtr->nation_recno)) // cannot attack this nation
						clearToDetect++;
				}
				break;

		case ACTION_ATTACK_FIRM:
				if(firm_array.is_deleted(action_para2))
					clearToDetect++;
				else
				{
					err_when(firm_array.is_deleted(action_para2));
					firmPtr = firm_array[action_para2];
					
					if(!nation_can_attack(firmPtr->nation_recno)) // cannot attack this nation
						clearToDetect++;
				}
				break;

		case ACTION_ATTACK_TOWN:
				if(town_array.is_deleted(action_para2))
					clearToDetect++;
				else
				{
					err_when(town_array.is_deleted(action_para2));
					townPtr = town_array[action_para2];
					
					if(!nation_can_attack(townPtr->nation_recno)) // cannot attack this nation
						clearToDetect++;
				}
				break;

		case ACTION_ATTACK_WALL:
				locPtr = world.get_loc(action_x_loc2, action_y_loc2);
				
				if(!locPtr->is_wall() || !nation_can_attack(locPtr->power_nation_recno))
					clearToDetect++;
				break;

		default: clearToDetect++;
					break;
	}

	//------------------------------------------------------------------------------//
	// suitation changed to defensive detecting mode
	//------------------------------------------------------------------------------//
	if(clearToDetect)
	{
		//----------------------------------------------------------//
		// target is dead, change to detect state for another target
		//----------------------------------------------------------//
		reset_action_para();
		return 1;
	}
	else if(waiting_term<ATTACK_WAITING_TERM)
		waiting_term++;
	else
	{
		//------------------------------------------------------------------------------//
		// process the corresponding attacking procedure.
		//------------------------------------------------------------------------------//
		waiting_term = 0;
		switch(action_mode)
		{
			case ACTION_ATTACK_UNIT:
				err_when(unit_array.is_deleted(action_para2) || !unitPtr);
				spriteInfo = unitPtr->sprite_info;
				
				//-----------------------------------------------------------------//
				// attack the target if able to reach the target surrounding, otherwise
				// continue to wait
				//-----------------------------------------------------------------//
				action_x_loc2 = unitPtr->next_x_loc(); // update target location
				action_y_loc2 = unitPtr->next_y_loc();
				if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
					attack_unit(unitPtr->sprite_recno);
				break;

			case ACTION_ATTACK_FIRM:
				err_when(firm_array.is_deleted(action_para2) || !firmPtr);
				firmInfo = firm_res[firmPtr->firm_id];
				
				//-----------------------------------------------------------------//
				// attack the target if able to reach the target surrounding, otherwise
				// continue to wait
				//-----------------------------------------------------------------//
				attack_firm(action_x_loc2, action_y_loc2);

				if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
					firmInfo->loc_width, firmInfo->loc_height))
					waiting_term = 0;
				break;

			case ACTION_ATTACK_TOWN:
				err_when(town_array.is_deleted(action_para2) || !townPtr);

				//-----------------------------------------------------------------//
				// attack the target if able to reach the target surrounding, otherwise
				// continue to wait
				//-----------------------------------------------------------------//
				attack_town(action_x_loc2, action_y_loc2);

				if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
					STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
					waiting_term = 0;
				break;

			case ACTION_ATTACK_WALL:
				err_when(action_para || action_para2);

				attack_wall(action_x_loc2, action_y_loc2);
				if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, 1, 1))
					waiting_term = 0;
				break;

			default:
				err_here();
				break;
		}
	}

	return 0;
}