/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OUNITM.CPP
//Description : Object Unit misc. actions excluding attacking and moving functions
//Owner : Alex
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef NO_DEBUG_UNIT
#undef err_when
#undef err_here
#undef err_if
#undef err_else
#undef err_now
#define err_when(cond)
#define err_here()
#define err_if(cond)
#define err_else
#define err_now(msg)
#undef DEBUG
#endif
//--------- Begin of function Unit::build_firm ---------//
// Build a firm.
//
// buildXLoc, buildYLoc - the location to build
// firmId - id. of the firm to build
//
// [char] remoteAction
//
void Unit::build_firm(int buildXLoc, int buildYLoc, int firmId, char remoteAction)
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
if(!remoteAction && remote.is_enable() )
{
// packet structure :
short *shortPtr =(short *)remote.new_send_queue_msg(MSG_UNIT_BUILD_FIRM, 4*sizeof(short) );
shortPtr[0] = sprite_recno;
shortPtr[1] = buildXLoc;
shortPtr[2] = buildYLoc;
shortPtr[3] = firmId;
return;
}
//----------------------------------------------------------------//
// return if the unit is dead
//----------------------------------------------------------------//
if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
return;
//----------------------------------------------------------------//
// location is blocked, cannot build. so move there instead
//----------------------------------------------------------------//
if(!world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno))
{
//reset_action_para2();
move_to(buildXLoc, buildYLoc);
return;
}
//----------------------------------------------------------------//
// different territory
//----------------------------------------------------------------//
int harborDir = world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno);
int goX = buildXLoc, goY = buildYLoc;
if( firm_res[firmId]->tera_type == 4)
{
switch(harborDir)
{
case 1: // north exit
goX += 1;
goY += 2;
break;
case 2: // south exit
goX += 1;
break;
case 4: // west exit
goX += 2;
goY += 1;
break;
case 8: // east exit
goY += 1;
break;
default:
err_here();
move_to(buildXLoc, buildYLoc);
return;
}
if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(goX,goY)->region_id)
{
move_to(buildXLoc, buildYLoc);
return;
}
}
else
{
if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(buildXLoc, buildYLoc)->region_id)
{
move_to(buildXLoc, buildYLoc);
return;
}
}
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_BUILD_FIRM && action_para2==firmId && action_x_loc2==buildXLoc && action_y_loc2==buildYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_BUILD_FIRM;
action_para2 = firmId;
action_x_loc2 = buildXLoc;
action_y_loc2 = buildYLoc;
}
//----- order the sprite to stop as soon as possible -----//
stop(); // new order
//---------------- define parameters -------------------//
FirmInfo* firmInfo = firm_res[firmId];
int firmWidth = firmInfo->loc_width;
int firmHeight = firmInfo->loc_height;
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, buildXLoc, buildYLoc, firmWidth, firmHeight))
{
//----------- not in the firm surrounding ---------//
set_move_to_surround(buildXLoc, buildYLoc, firmWidth, firmHeight, BUILDING_TYPE_FIRM_BUILD, firmId);
}
else
{
//------- the unit is in the firm surrounding -------//
set_cur(next_x, next_y);
set_dir(move_to_x_loc, move_to_y_loc, buildXLoc+firmWidth/2, buildYLoc+firmHeight/2);
}
//----------- set action to build the firm -----------//
action_mode = ACTION_BUILD_FIRM;
action_para = firmId;
action_x_loc = buildXLoc;
action_y_loc = buildYLoc;
}
//----------- End of function Unit::build_firm -----------//
//--------- Begin of function Unit::burn ---------//
//
// Burn a locaiton
//
// burnXLoc, burnYLoc - the location to burn
//
void Unit::burn(int burnXLoc, int burnYLoc, char remoteAction)
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
if( !remoteAction && remote.is_enable() )
{
// packet structure :
short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_BURN, 3*sizeof(short) );
shortPtr[0] = sprite_recno;
shortPtr[1] = burnXLoc;
shortPtr[2] = burnYLoc;
return;
}
if(move_to_x_loc==burnXLoc && move_to_y_loc==burnYLoc)
return; // should not burn the unit itself
//----------------------------------------------------------------//
// return if the unit is dead
//----------------------------------------------------------------//
if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
return;
//----------------------------------------------------------------//
// move there instead if ordering to different territory
//----------------------------------------------------------------//
if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(burnXLoc, burnYLoc)->region_id)
{
move_to(burnXLoc, burnYLoc);
return;
}
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_BURN && action_x_loc2==burnXLoc && action_y_loc2==burnYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_BURN;
action_para2 = 0;
action_x_loc2 = burnXLoc;
action_y_loc2 = burnYLoc;
}
//----- order the sprite to stop as soon as possible -----//
stop(); // new order
if(abs(burnXLoc-next_x_loc())>1 || abs(burnYLoc-next_y_loc())>1)
{
//--- if the unit is not in the burning surrounding location, move there first ---//
search(burnXLoc, burnYLoc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
if(move_to_x_loc != burnXLoc || move_to_y_loc != burnYLoc) // cannot reach the destination
{
action_mode = ACTION_BURN;
action_para = 0;
action_x_loc = burnXLoc;
action_y_loc = burnYLoc;
return; // just move to the closest location returned by shortest path searching
}
}
else
{
if(cur_x==next_x && cur_y==next_y)
set_dir(next_x_loc(), next_y_loc(), burnXLoc, burnYLoc);
err_when((cur_x!=next_x || cur_y!=next_y) && (check_unit_dir1=get_dir(cur_x,cur_y,next_x,next_y))!=final_dir);
err_when(result_node_array || result_node_count || result_path_dist);
}
//--------------------------------------------------------//
// edit the result path such that the unit can reach the
// burning location surrounding
//--------------------------------------------------------//
if(result_node_array && result_node_count)
{
//--------------------------------------------------------//
// there should be at least two nodes, and should take at
// least two steps to the destination
//--------------------------------------------------------//
err_when(move_to_x_loc!=burnXLoc || move_to_y_loc!=burnYLoc);
err_when(result_node_count<2);
ResultNode* lastNode1 = result_node_array+result_node_count-1; // the last node
ResultNode* lastNode2 = result_node_array+result_node_count-2; // the node before the last node
int vX = lastNode1->node_x-lastNode2->node_x; // get the vectors direction
int vY = lastNode1->node_y-lastNode2->node_y;
int vDirX = (vX) ? vX/abs(vX) : 0;
int vDirY = (vY) ? vY/abs(vY) : 0;
if(result_node_count>2) // go_? should not be the burning location
{
err_when(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc);
err_when(vX!=0 && vY!=0 && abs(vX)!=abs(vY));
if(abs(vX)>1 || abs(vY)>1)
{
lastNode1->node_x -= vDirX;
lastNode1->node_y -= vDirY;
move_to_x_loc = lastNode1->node_x;
move_to_y_loc = lastNode1->node_y;
}
else // move only one step
{
result_node_count--; // remove a node
move_to_x_loc = lastNode2->node_x;
move_to_y_loc = lastNode2->node_y;
}
}
else // go_? may be the burning location
{
err_when(result_node_count!=2);
lastNode1->node_x -= vDirX;
lastNode1->node_y -= vDirY;
if(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc) // go_? is the burning location
{
//--- edit parameters such that only moving to the nearby location to do the action ---//
err_when(abs(vX)<=1 && abs(vY)<=1); // this case should be handled before
go_x = lastNode1->node_x * ZOOM_LOC_WIDTH;
go_y = lastNode1->node_y * ZOOM_LOC_HEIGHT;
}
//else the unit is still doing sthg else, no action here
move_to_x_loc = lastNode1->node_x;
move_to_y_loc = lastNode1->node_y;
}
//--------------------------------------------------------------//
// reduce the result_path_dist by 1
//--------------------------------------------------------------//
result_path_dist--;
#ifdef DEBUG
ResultNode *preNode = result_node_array;
ResultNode *curNode = result_node_array+1;
int debugCount=1;
int debugDist = 0;
int xDist = abs(next_x_loc()-preNode->node_x);
int yDist = abs(next_y_loc()-preNode->node_y);
debugDist -= (xDist) ? xDist : yDist;
while(debugCount++ < result_node_count)
{
err_when(debugCount>1000);
xDist = abs(preNode->node_x - curNode->node_x);
yDist = abs(preNode->node_y - curNode->node_y);
debugDist += (xDist) ? xDist : yDist;
preNode++;
curNode++;
}
err_when(result_path_dist!=debugDist);
#endif
err_when((cur_x!=next_x || cur_y!=next_y) && // is not blocked
(check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
}
err_when(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, burnXLoc, burnYLoc, 1, 1));
//-- set action if the burning location can be reached, otherwise just move nearby --//
action_mode = ACTION_BURN;
action_para = 0;
action_x_loc = burnXLoc;
action_y_loc = burnYLoc;
}
//----------- End of function Unit::burn -----------//
//--------- Begin of function Unit::settle ---------//
//
// settle to a town
//
// settleXLoc, settleYLoc - the location to settle
// [short] curSettleUnitNum - the number to call this function by
// a group of unit. (default: 1)
//
void Unit::settle(int settleXLoc, int settleYLoc, short curSettleUnitNum)
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
//----------------------------------------------------------------//
// return if the unit is dead
//----------------------------------------------------------------//
if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
return;
//---------- no settle for non-human -----------//
if(unit_res[unit_id]->unit_class!=UNIT_CLASS_HUMAN)
return;
//----------------------------------------------------------------//
// move there if cannot settle
//----------------------------------------------------------------//
if(!world.can_build_town(settleXLoc, settleYLoc, sprite_recno))
{
Location *locPtr = world.get_loc(settleXLoc, settleYLoc);
if(locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno==nation_recno)
assign(settleXLoc, settleYLoc);
else
move_to(settleXLoc, settleYLoc);
return;
}
//----------------------------------------------------------------//
// move there if location is in different territory
//----------------------------------------------------------------//
if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(settleXLoc, settleYLoc)->region_id)
{
move_to(settleXLoc, settleYLoc);
return;
}
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_SETTLE && action_x_loc2==settleXLoc && action_y_loc2==settleYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_SETTLE;
action_para2 = 0;
action_x_loc2 = settleXLoc;
action_y_loc2 = settleYLoc;
}
//----- order the sprite to stop as soon as possible -----//
stop(); // new order
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, settleXLoc, settleYLoc,
STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
{
//------------ not in the town surrounding ------------//
set_move_to_surround(settleXLoc, settleYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_SETTLE, 0, 0, curSettleUnitNum);
}
else
{
//------- the unit is within the settle location -------//
set_cur(next_x, next_y);
set_dir(move_to_x_loc, move_to_y_loc, settleXLoc+STD_TOWN_LOC_WIDTH/2, settleYLoc+STD_TOWN_LOC_HEIGHT/2);
}
//----------- set action to settle -----------//
action_mode = ACTION_SETTLE;
action_para = 0;
action_x_loc = settleXLoc;
action_y_loc = settleYLoc;
}
//----------- End of function Unit::settle -----------//
//--------- Begin of function Unit::assign ---------//
//
// Assign an unit to :
//
// - a firm as an overseer, as a worker
// - a town as a citizen
// - a vehicle
//
// buildXLoc, buildYLoc - the location to build
//
void Unit::assign(int assignXLoc, int assignYLoc, short curAssignUnitNum)
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
//----------------------------------------------------------------//
// return if the unit is dead
//----------------------------------------------------------------//
if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
return;
//----------- cannot assign for caravan -----------//
if(unit_id==UNIT_CARAVAN)
return;
//----------------------------------------------------------------//
// move there if the destination in other territory
//----------------------------------------------------------------//
Location *locPtr = world.get_loc(assignXLoc, assignYLoc);
UCHAR unitRegionId = world.get_loc(next_x_loc(), next_y_loc())->region_id;
if(locPtr->is_firm())
{
Firm *firmPtr = firm_array[locPtr->firm_recno()];
int quit = 0;
if(firmPtr->firm_id==FIRM_HARBOR)
{
FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
switch(unit_res[unit_id]->unit_class)
{
case UNIT_CLASS_HUMAN:
if(unitRegionId != harborPtr->land_region_id)
quit = 1;
break;
case UNIT_CLASS_SHIP:
if(unitRegionId != harborPtr->sea_region_id)
quit = 1;
break;
default: err_here();
break;
}
}
else if(unitRegionId!=locPtr->region_id)
quit = 1;
if(quit)
{
move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
return;
}
}
else if(unitRegionId!=locPtr->region_id)
{
if(locPtr->is_town())
move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
/*else if(locPtr->has_unit(UNIT_LAND))
{
Unit *unitPtr = unit_array[locPtr->unit_recno(UNIT_LAND)];
move_to_unit_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, unitPtr->sprite_recno);
}*/
return;
}
//---------------- define parameters --------------------//
int width, height;
int buildingType=0; // 1 for Firm, 2 for TownZone
short recno;
int firmNeedUnit=1;
if(locPtr->is_firm())
{
//-------------------------------------------------------//
// the location is firm
//-------------------------------------------------------//
recno = locPtr->firm_recno();
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_ASSIGN_TO_FIRM && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_ASSIGN_TO_FIRM;
action_para2 = recno;
action_x_loc2 = assignXLoc;
action_y_loc2 = assignYLoc;
}
Firm *firmPtr = firm_array[recno];
FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
if(!firm_can_assign(recno))
{
//firmNeedUnit = 0; // move to the surrounding of the firm
move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
return;
}
width = firmInfo->loc_width;
height = firmInfo->loc_height;
buildingType = BUILDING_TYPE_FIRM_MOVE_TO;
}
else if(locPtr->is_town()) // there is town
{
if(unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN)
return;
//-------------------------------------------------------//
// the location is town
//-------------------------------------------------------//
recno = locPtr->town_recno();
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_ASSIGN_TO_TOWN && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_ASSIGN_TO_TOWN;
action_para2 = recno;
action_x_loc2 = assignXLoc;
action_y_loc2 = assignYLoc;
}
Town *targetTown = town_array[recno];
if(town_array[recno]->nation_recno != nation_recno)
{
move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
return;
}
width = targetTown->loc_width();
height = targetTown->loc_height();
buildingType = BUILDING_TYPE_TOWN_MOVE_TO;
}
/*else if(locPtr->has_unit(UNIT_LAND)) // there is vehicle
{
//-------------------------------------------------------//
// the location is vehicle
//-------------------------------------------------------//
Unit* vehicleUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
if( vehicleUnit->unit_id!=unit_res[unit_id]->vehicle_id )
return;
recno = vehicleUnit->sprite_recno;
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_ASSIGN_TO_VEHICLE && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_ASSIGN_TO_VEHICLE;
action_para2 = recno;
action_x_loc2 = assignXLoc;
action_y_loc2 = assignYLoc;
}
SpriteInfo* spriteInfo = vehicleUnit->sprite_info;
width = spriteInfo->loc_width;
height = spriteInfo->loc_height;
buildingType = BUILDING_TYPE_VEHICLE;
}*/
else
{
stop2(KEEP_DEFENSE_MODE);
return;
}
//-----------------------------------------------------------------//
// order the sprite to stop as soon as possible (new order)
//-----------------------------------------------------------------//
stop();
set_move_to_surround(assignXLoc, assignYLoc, width, height, buildingType, 0, 0, curAssignUnitNum);
//-----------------------------------------------------------------//
// able to reach building surrounding, set action parameters
//-----------------------------------------------------------------//
action_para = recno;
action_x_loc = assignXLoc;
action_y_loc = assignYLoc;
switch(buildingType)
{
case BUILDING_TYPE_FIRM_MOVE_TO:
action_mode = ACTION_ASSIGN_TO_FIRM;
break;
case BUILDING_TYPE_TOWN_MOVE_TO:
action_mode = ACTION_ASSIGN_TO_TOWN;
break;
case BUILDING_TYPE_VEHICLE:
action_mode = ACTION_ASSIGN_TO_VEHICLE;
break;
}
//##### begin trevor 9/10 #######//
// force_move_flag = 1; // don't stop and fight back on an assign mission
//##### end trevor 9/10 #######//
//-----------------------------------------------------------------//
// edit parameters for those firms don't need unit
//-----------------------------------------------------------------//
/*if(!firmNeedUnit)
{
action_mode2 = action_mode = ACTION_MOVE;
action_para2 = action_para = 0;
action_x_loc2 = action_x_loc = move_to_x_loc;
action_y_loc2 = action_y_loc = move_to_y_loc;
}*/
}
//----------- End of function Unit::assign -----------//
//--------- Begin of function Unit::firm_can_assign ---------//
// return 1 for true, i.e. unit can assign to the firm
// return 2 for assigning leader
// return 3 for repair
// return 4 for spy assigning to inn
// return 5 for capture (not used)
// return 0 otherwise
//
int Unit::firm_can_assign(short firmRecno)
{
Firm *firmPtr = firm_array[firmRecno];
FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
switch( unit_res[unit_id]->unit_class )
{
case UNIT_CLASS_HUMAN:
if( nation_recno == firmPtr->nation_recno )
{
if( skill.skill_id == SKILL_CONSTRUCTION && firmPtr->firm_id != FIRM_MONSTER)
{
return 3;
}
// ###### begin Gilbert 22/10 #######//
//----------------------------------------//
// If this is a spy, then he can only be
// assigned to an enemy firm when there is
// space for the unit.
//----------------------------------------//
//if( spy_recno && true_nation_recno() != firmPtr->nation_recno )
//{
// if( rank_id == RANK_GENERAL )
// {
// if( firmPtr->overseer_recno )
// return 0;
// }
// else
// {
// if( firmPtr->worker_count == MAX_WORKER )
// return 0;
// }
//}
//--------------------------------------//
// ###### end Gilbert 22/10 #######//
switch( firmPtr->firm_id )
{
case FIRM_CAMP:
return rank_id == RANK_SOLDIER ? 1 : 2;
case FIRM_BASE:
if(race_id == firmPtr->race_id)
{
if( !skill.skill_id || skill.skill_id==SKILL_PRAYING) // non-skilled worker
return 1;
if( rank_id != RANK_SOLDIER )
return 2;
}
break;
//case FIRM_INN:
// shealthed soldier spy can assign to inn
// return rank_id == RANK_SOLDIER && nation_recno != true_nation_recno() ? 4 : 0;
default:
return rank_id == RANK_SOLDIER && firmInfo->need_unit() ? 1 : 0;
}
}
break;
case UNIT_CLASS_WEAPON:
if(firmPtr->firm_id == FIRM_CAMP && nation_recno == firmPtr->nation_recno)
return 1;
break;
case UNIT_CLASS_SHIP:
if(firmPtr->firm_id == FIRM_HARBOR && nation_recno == firmPtr->nation_recno)
return 1;
break;
case UNIT_CLASS_MONSTER:
if(firmPtr->firm_id == FIRM_MONSTER && mobile_type == UNIT_LAND)
{
// BUGHERE : suppose only land monster can assign
return rank_id == RANK_SOLDIER ? 1 : 2;
}
break;
case UNIT_CLASS_GOD:
case UNIT_CLASS_CARAVAN:
break;
default:
err_here(); // undefined unit class
}
return 0;
}
//----------- End of function Unit::firm_can_assign -----------//
//--------- Begin of function Unit::set_move_to_surround ---------//
// Mode 1:
// return 1 if the unit can reach the surrounding of the firm
// return 0 otherwise.
//
// Mode 2:
// In this mode, the unit calling this function is ordered to move to
// location a little bit away from the surrounding of the object.
//
// return 1 if the unit can move to there
// return 0 otherwise
//
// buildXLoc - upper left x location of the building (firm/town)
// buildYLoc - upper left y location of the building
// width - width of the building
// height - height of the building
// buildingType - used to determine how searching is processed
// [int] miscNo - firm_id of firm if buildingType==BUILDING_TYPE_FIRM_BUILD
// - 0 for group search (for wall, firm)
// - 1 for a unit search
// [short] readyDist - the extra distance the unit stands from the building
// (default 0, i.e. the surrounding of the building)
// [short] curProcessUnitNum - the cur unit no. in a group calling this function
// (default 1)
//
//============================================================================//
// Note: This funcion should not change any action parameters
//============================================================================//
//
int Unit::set_move_to_surround(int buildXLoc, int buildYLoc, int width, int height, int buildingType, int miscNo, int readyDist, short curProcessUnitNum)
{
err_when(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE);
//--------------------------------------------------------------//
// calculate the distance from the object
//--------------------------------------------------------------//
int found=0, foundAgain=0;
int distance = cal_distance(buildXLoc, buildYLoc, width, height); // 0 for inside, 1 for surrounding, >1 for the rest
//--------------------------------------------------------------//
// inside the building
//--------------------------------------------------------------//
if(!distance)
{
reset_path();
if(cur_x==next_x && cur_y==next_y)
set_idle();
return 1;
}
if(distance>1)
{
//--------------------------------------------------------------//
// the searching is divided into 2 parts.
//
// part 1 using the firm_type and firm_id to find a shortest path.
//
// part 2
// if the width and height is the actual width and height of the
// firm, the unit move to the surrounding of the firm.
//
// if the width and height > the actual width and height of the
// firm, the unit move to a location far away from the surrounding
// of the firm.
//--------------------------------------------------------------//
//====================================================================//
// part 1
//====================================================================//
Location *locPtr = world.get_loc( buildXLoc, buildYLoc );
Firm *firmPtr = NULL;
Town *targetTown = NULL;
int searchResult;
switch(buildingType)
{
case BUILDING_TYPE_FIRM_MOVE_TO: // (assign) firm is on the location
firmPtr = firm_array[locPtr->firm_recno()];
searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, firmPtr->firm_id, curProcessUnitNum);
break;
case BUILDING_TYPE_FIRM_BUILD: // (build firm) no firm on the location
err_when(sprite_info->loc_width>1);
searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, miscNo);
break;
case BUILDING_TYPE_TOWN_MOVE_TO: // (assign) town is on the location
targetTown = town_array[locPtr->town_recno()];
searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, targetTown->town_recno, curProcessUnitNum);
break;
case BUILDING_TYPE_SETTLE: // (settle, first unit) no town on the location
//---------------------------------------------------------------------//
// the record number sent to the searching algorithm is used to determine
// the width and the height of the building. However, the standard
// dimension for settling is used and the building built is a type of
// town. Thus, passing -1 as the recno. to show that "settle" is
// processed
//---------------------------------------------------------------------//
err_when(sprite_info->loc_width>1);
searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, -1, curProcessUnitNum);
break;
case BUILDING_TYPE_VEHICLE:
err_when(sprite_info->loc_width>1);
searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_VEHICLE, (short)world.get_loc(buildXLoc, buildYLoc)->cargo_recno);
break;
case BUILDING_TYPE_WALL: // wall is on the location
err_when(miscNo!=0 && miscNo!=1);
searchResult = search(buildXLoc, buildYLoc, 1, miscNo?SEARCH_MODE_TO_WALL_FOR_UNIT:SEARCH_MODE_TO_WALL_FOR_GROUP);
break;
default: err_here();
break;
}
if(!searchResult)
return 0; // incomplete searching
//====================================================================//
// part 2
//====================================================================//
if(result_node_array && result_node_count)
return edit_path_to_surround(buildXLoc, buildYLoc, buildXLoc+width-1, buildYLoc+height-1, readyDist);
else
return 0;
}
else // in the surrounding, no need to move
{
reset_path();
err_when(distance!=1);
if(cur_x==next_x && cur_y==next_y)
{
move_to_x_loc = next_x_loc();
move_to_y_loc = next_y_loc();
go_x = cur_x;
go_y = cur_y;
set_idle();
set_dir(move_to_x_loc, move_to_y_loc, buildXLoc + width/2, buildYLoc + height/2);
err_when(result_node_array!=NULL);
}
err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
return 1;
}
}
//----------- End of function Unit::set_move_to_surround -----------//
//--------- Begin of function Unit::edit_path_to_surround ---------//
// edit the path such that the unit only move to the surrounding of the firm
//
// objectXLoc1, objectYLoc1 - object top_left position
// objectXLoc2, objectYLoc2 - object bottom_right position
// readyDist - the extra distance the unit stands from the building
// (default 0, i.e. the surrounding of the building)
//
// return 1 if able to reach object surrounding
// return 0 otherwise
//
int Unit::edit_path_to_surround(int objectXLoc1, int objectYLoc1, int objectXLoc2, int objectYLoc2, int readyDist)
{
err_when(!result_node_array || !result_node_count);
if(result_node_count<2)
return 0;
//----------------------------------------------------------------------------//
// At this moment, the unit generally has a path to the location inside the object,
// walk through it and extract a path to the surrounding of the object.
//----------------------------------------------------------------------------//
//------- calculate the surrounding top-left and bottom-right points ------//
int moveScale = move_step_magn();
int xLoc1 = objectXLoc1 - readyDist - 1;
int yLoc1 = objectYLoc1 - readyDist - 1;
int xLoc2 = objectXLoc2 + readyDist + 1;
int yLoc2 = objectYLoc2 + readyDist + 1;
//------------------- boundary checking -------------------//
if(xLoc1<0) xLoc1 = 0;
if(yLoc1<0) yLoc1 = 0;
if(xLoc2>=MAX_WORLD_X_LOC) yLoc1 = MAX_WORLD_X_LOC - moveScale;
if(yLoc2>=MAX_WORLD_Y_LOC) xLoc2 = MAX_WORLD_Y_LOC - moveScale;
//--------------- adjust for air and sea units -----------------//
if(mobile_type!=UNIT_LAND)
{
//------ assume even x, y coordinate is used for UNIT_SEA and UNIT_AIR -------//
if(xLoc1%2) xLoc1--;
if(yLoc1%2) yLoc1--;
if(xLoc2%2) xLoc2++;
if(yLoc2%2) yLoc2++;
if(xLoc2>MAX_WORLD_X_LOC-moveScale)
xLoc2 = MAX_WORLD_X_LOC-moveScale;
if(yLoc2>MAX_WORLD_Y_LOC-moveScale)
yLoc2 = MAX_WORLD_Y_LOC-moveScale;
err_when(xLoc1<0 || yLoc1<0);
err_when(xLoc2>MAX_WORLD_X_LOC-moveScale || yLoc2>MAX_WORLD_Y_LOC-moveScale);
}
int checkXLoc = next_x_loc();
int checkYLoc = next_y_loc();
ResultNode *editNode1 = result_node_array; // alias the unit's result_node_array
ResultNode *editNode2 = result_node_array + 1; // ditto
int hasMoveStep = 0;
if(checkXLoc!=editNode1->node_x || checkYLoc!=editNode1->node_y)
{
err_when(abs(checkXLoc-editNode1->node_x)>moveScale || abs(checkYLoc-editNode1->node_y)>moveScale);
hasMoveStep += moveScale;
checkXLoc = editNode1->node_x;
checkYLoc = editNode1->node_y;
}
int i, j;
int pathDist=0, found=0; // pathDist - counts the disitance of the generated path, found - whether a path to the surrounding is found
int vecX, vecY, xMagn, yMagn, magn;
#ifdef DEBUG
int debugLoop1 = 0;
int debugLoop2 = 0;
#endif
//------- find the first node that is on the surrounding of the object -------//
for(i=1; i10000);
#endif
//------------ calculate parameters for checking ------------//
vecX = editNode2->node_x - editNode1->node_x;
vecY = editNode2->node_y - editNode1->node_y;
err_when(vecX==0 && vecY==0);
magn = ((xMagn=abs(vecX)) > (yMagn=abs(vecY))) ? xMagn : yMagn;
if(xMagn)
{
vecX /= xMagn;
vecX *= moveScale;
}
if(yMagn)
{
vecY /= yMagn;
vecY *= moveScale;
}
err_when(abs(vecX)>moveScale && abs(vecY)>moveScale);
#ifdef DEBUG
debugLoop2 = 0;
#endif
//------------- check each location bewteen editNode1 and editNode2 -------------//
for(j=0; j10000);
#endif
checkXLoc += vecX;
checkYLoc += vecY;
if(checkXLoc>=xLoc1 && checkXLoc<=xLoc2 && checkYLoc>=yLoc1 && checkYLoc<=yLoc2)
{
found++;
break;
}
}
//-------------------------------------------------------------------------------//
// a path is found, then set unit's parameters for its movement
//-------------------------------------------------------------------------------//
if(found)
{
editNode2->node_x = checkXLoc;
editNode2->node_y = checkYLoc;
if(i==1) // first editing
{
ResultNode *firstNodePtr = result_node_array;
if(cur_x==firstNodePtr->node_x*ZOOM_LOC_WIDTH && cur_y==firstNodePtr->node_y*ZOOM_LOC_HEIGHT)
{
go_x = checkXLoc * ZOOM_LOC_WIDTH;
go_y = checkYLoc * ZOOM_LOC_HEIGHT;
}
}
pathDist += (j+moveScale);
pathDist -= hasMoveStep;
result_node_count = i+1;
result_path_dist = pathDist;
move_to_x_loc = checkXLoc;
move_to_y_loc = checkYLoc;
break;
}
else
pathDist += magn;
}
return found;
}
//----------- End of function Unit::edit_path_to_surround -----------//
//--------- Begin of function Unit::is_in_surrounding ---------//
// Test whether the location (checkXLoc, checkYLoc) is in the surrounding of an object
//
// checkXLoc, checkYLoc - location to check
// width - the width of the caller
// ObjectXLoc, objectYLoc - object location
// objectWidth - object width
// objectHeight - object height
//
// Note: assume the width and the height of the caller is equal
// return 1 if in object surrounding
// return 0 otherwise
//
int Unit::is_in_surrounding(int checkXLoc, int checkYLoc, int width, int objectXLoc, int objectYLoc,
int objectWidth, int objectHeight)
{
switch(move_step_magn())
{
case 1:
if(checkXLoc>=objectXLoc-width && checkXLoc<=objectXLoc+objectWidth &&
checkYLoc>=objectYLoc-width && checkYLoc<=objectYLoc+objectHeight)
return 1;
break;
case 2:
if(checkXLoc>=objectXLoc-width-1 && checkXLoc<=objectXLoc+objectWidth+1 &&
checkYLoc>=objectYLoc-width-1 && checkYLoc<=objectYLoc+objectHeight+1)
return 1;
break;
default: err_here();
break;
}
return 0;
}
//----------- End of function Unit::is_in_surrounding -----------//
//--------- Begin of function Unit::process_build_firm ---------//
// process action of building firms
//
void Unit::process_build_firm()
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC || action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC);
err_when(action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
{
// **BUGHERE, the unit shouldn't be hidden when building structures
// otherwise, it's cargo_recno will be conflict with the structure's
// cargo_recno
int succeedFlag=0;
if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
{
FirmInfo *firmInfo = firm_res[action_para];
int width = firmInfo->loc_width;
int height = firmInfo->loc_height;
//---------------------------------------------------------//
// check whether the unit in the building surrounding
//---------------------------------------------------------//
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc, width, height))
{
//---------- not in the building surrounding ---------//
return;
}
//---------------------------------------------------------//
// the unit in the firm surrounding
//---------------------------------------------------------//
Nation* nationPtr;
if(nation_recno)
{
nationPtr = nation_array[nation_recno];
if(nationPtr->cash < firmInfo->setup_cost)
return; // out of cash
}
else
nationPtr = NULL;
//---------------------------------------------------------//
// check whether the firm can be built in the specified location
//---------------------------------------------------------//
if( world.can_build_firm(action_x_loc, action_y_loc, action_para, sprite_recno) &&
firm_res[action_para]->can_build(sprite_recno) )
{
int aiUnit = ai_unit;
int actionXLoc = action_x_loc;
int actionYLoc = action_y_loc;
short unitRecno = sprite_recno;
//---------------------------------------------------------------------------//
// if unit inside the firm location, deinit the unit to free the space for
// building firm
//---------------------------------------------------------------------------//
if(move_to_x_loc>=action_x_loc && move_to_x_loc=action_y_loc && move_to_y_locsprite_code, sprite_recno) ) // action_para = firm id.
{
//--------- able to the firm --------//
reset_action_para2();
succeedFlag = 1;
}
}
}
//----- call action finished/failure -----//
if( ai_action_id && nation_recno )
{
if( succeedFlag )
nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
else
nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
}
//---------------------------------------//
reset_action_para();
}
}
//----------- End of function Unit::process_build_firm -----------//
//--------- Begin of function Unit::process_assign ---------//
// process action of assigning
//
void Unit::process_assign()
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
if(cur_action!=SPRITE_IDLE)
{
//------------------------------------------------------------------//
// change units' action if the firm/town/unit assign to has been deleted
// or has changed its nation
//------------------------------------------------------------------//
switch(action_mode2)
{
case ACTION_ASSIGN_TO_FIRM:
case ACTION_AUTO_DEFENSE_BACK_CAMP:
case ACTION_MONSTER_DEFEND_BACK_FIRM:
if(firm_array.is_deleted(action_para))
{
stop2();
return;
}
else
{
Firm *firmPtr = firm_array[action_para];
//###### begin trevor 21/6 #######//
if(firmPtr->nation_recno!=nation_recno && !firmPtr->can_assign_capture())
{
stop2();
return;
}
//###### end trevor 21/6 #######//
}
break;
case ACTION_ASSIGN_TO_TOWN:
case ACTION_DEFEND_TOWN_BACK_TOWN:
if(town_array.is_deleted(action_para))
{
stop2();
return;
}
else if(town_array[action_para]->nation_recno!=nation_recno)
{
stop2();
return;
}
break;
case ACTION_ASSIGN_TO_VEHICLE:
if(unit_array.is_deleted(action_para))
{
stop2();
return;
}
else if(unit_array[action_para]->nation_recno!=nation_recno)
{
stop2();
return;
}
break;
default: err_here();
break;
}
}
else //--------------- unit is idle -----------------//
{
if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
{
//----- first check if there is firm in the given location ------//
Location* locPtr = world.get_loc( action_x_loc, action_y_loc );
if( locPtr->is_firm() && locPtr->firm_recno() == action_para )
{
//---------------- a firm on the location -----------------//
Firm* firmPtr = firm_array[action_para];
FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
//---------- resume action if the unit has not reached the firm surrounding ----------//
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
firmInfo->loc_width, firmInfo->loc_height))
{
//------------ not in the surrounding -----------//
if(action_mode!=action_mode2) // for defense mode
set_move_to_surround(action_x_loc, action_y_loc, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO);
return;
}
//------------ in the firm surrounding ------------//
if(!firmPtr->under_construction)
{
//-------------------------------------------------------//
// if in defense mode, update parameters in military camp
//-------------------------------------------------------//
if(action_mode2==ACTION_AUTO_DEFENSE_BACK_CAMP)
{
FirmCamp *campPtr = firmPtr->cast_to_FirmCamp();
campPtr->update_defense_unit(sprite_recno);
}
//---------------------------------------------------------------//
// remainder useful parameters to do reaction to Nation.
// These parameters will be destroyed after calling assign_unit()
//---------------------------------------------------------------//
int nationRecno = nation_recno;
short unitRecno = sprite_recno;
int actionXLoc = action_x_loc;
int actionYLoc = action_y_loc;
short aiActionId = ai_action_id;
char aiUnit = ai_unit;
reset_action_para2();
firmPtr->assign_unit(sprite_recno);
//----------------------------------------------------------//
// firm_array[]->assign_unit() must be done first. Then a
// town will be created and the reaction to build other firms
// requires the location of the town.
//----------------------------------------------------------//
if(aiActionId)
nation_array[nationRecno]->action_finished(aiActionId, unitRecno);
if( unit_array.is_deleted(unitRecno) )
return;
//--- else the firm is full, the unit's skill level is lower than those in firm, or no space to create town ---//
}
else
{
//---------- change the builder ------------//
if(ai_unit && firmPtr->under_construction)
return; // not allow AI to change firm builder
reset_action_para2();
if(skill.get_skill(SKILL_CONSTRUCTION) || skill.get_skill(firmPtr->firm_skill_id))
firmPtr->set_builder(sprite_recno);
}
//------------ update unit_array's selected parameters ------------//
reset_action_para();
if(selected_flag)
{
selected_flag = 0;
unit_array.selected_count--;
}
}
else if( locPtr->is_town() && locPtr->town_recno() == action_para )
{
//---------------- a town on the location -----------------//
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
{
//----------- not in the surrounding ------------//
return;
}
short actionPara = action_para;
short spriteRecno = sprite_recno;
if(ai_action_id)
nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
//------------ update unit_array's selected parameters ------------//
reset_action_para2();
reset_action_para();
if(selected_flag)
{
selected_flag = 0;
unit_array.selected_count--;
}
//-------------- assign the unit to the town -----------------//
town_array[actionPara]->assign_unit(spriteRecno);
}
//####### begin trevor 18/8 #########// the following code was called wrongly and causing bug
/*
//------ embarking a ground vehicle/animal ------//
else if(locPtr->has_unit(UNIT_LAND) && locPtr->unit_recno(UNIT_LAND) == action_para)
{
reset_action_para2();
reset_action_para();
if(selected_flag)
{
selected_flag = 0;
unit_array.selected_count--;
}
embark(action_para);
}
*/
//####### end trevor 18/8 #########//
//------ embarking a sea vehicle/animal ------//
else if(locPtr->has_unit(UNIT_SEA) && locPtr->unit_recno(UNIT_SEA) == action_para)
{
//------------ update unit_array's selected parameters ------------//
reset_action_para2();
reset_action_para();
if(selected_flag)
{
selected_flag = 0;
unit_array.selected_count--;
}
//----------------- load the unit to the marine -----------------//
((UnitMarine*)unit_array[action_para])->load_unit(sprite_recno);
}
else
{
//------------------------------------------------------------------//
// abort actions for ai_unit since the target location has nothing
//------------------------------------------------------------------//
if( ai_action_id )
nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
}
}
//-***** don't place codes here as unit may be removed above *****-//
//reset_action_para();
//selected_flag = 0;
}
}
//----------- End of function Unit::process_assign -----------//
//--------- Begin of function Unit::process_burn ---------//
// process action of burning to a specified location
//
void Unit::process_burn()
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
{
if( next_x_loc()==action_x_loc && next_y_loc()==action_y_loc )
{
reset_action_para2();
set_dir(move_to_x_loc, move_to_y_loc, action_x_loc, action_y_loc);
world.setup_fire( action_x_loc, action_y_loc );
}
reset_action_para();
}
}
//----------- End of function Unit::process_burn -----------//
//--------- Begin of function Unit::process_settle ---------//
// process action of settling to an existing town
//
void Unit::process_settle()
{
err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
{
reset_path();
if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
{
if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
return;
Location* locPtr = world.get_loc(action_x_loc, action_y_loc);
if(!locPtr->is_town())
{
//##### begin trevor 1/9 ########//
int unitRecno = sprite_recno;
reset_action_para2();
//------------ settle the unit now -------------//
town_array.settle(sprite_recno, action_x_loc, action_y_loc);
if( unit_array.is_deleted(unitRecno) )
return;
reset_action_para();
//##### end trevor 1/9 ########//
}
else if(town_array[locPtr->town_recno()]->nation_recno == nation_recno)
{
//---------- a town zone already exists ---------//
assign(action_x_loc, action_y_loc);
return;
}
}
else
reset_action_para();
}
}
//----------- End of function Unit::process_settle -----------//
//--------- Begin of function Unit::go_cast_power ---------//
// do action of god casting
//
void Unit::go_cast_power(int castXLoc, int castYLoc, char castPowerType, char remoteAction)
{
err_when(mobile_type!=UNIT_AIR);
//----------------------------------------------------------------//
// return if the unit is dead
//----------------------------------------------------------------//
if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
return;
if(!remoteAction && remote.is_enable() )
{
//------------ process multiplayer calling ---------------//
// packet structure :
short *shortPtr =(short *)remote.new_send_queue_msg(MSG_U_GOD_CAST, 4*sizeof(short) );
shortPtr[0] = sprite_recno;
shortPtr[1] = castXLoc;
shortPtr[2] = castYLoc;
shortPtr[3] = castPowerType;
return;
}
UnitGod *unitGod = (UnitGod *)this;
//----------------------------------------------------------------//
// action_mode2: checking for equal action or idle action
//----------------------------------------------------------------//
if(action_mode2==ACTION_GO_CAST_POWER && action_para2==0 && action_x_loc2==castXLoc && action_y_loc2==castYLoc
&& unitGod->cast_power_type==castPowerType)
{
if(cur_action!=SPRITE_IDLE)
return;
}
else
{
//----------------------------------------------------------------//
// action_mode2: store new order
//----------------------------------------------------------------//
action_mode2 = ACTION_GO_CAST_POWER;
action_para2 = 0;
action_x_loc2 = castXLoc;
action_y_loc2 = castYLoc;
}
//----- order the sprite to stop as soon as possible -----//
stop(); // new order
//------------- do searching if neccessary -------------//
if(m.points_distance(next_x_loc(), next_y_loc(), castXLoc, castYLoc)>DO_CAST_POWER_RANGE)
search(castXLoc, castYLoc, 1);
//----------- set action to build the firm -----------//
action_mode = ACTION_GO_CAST_POWER;
action_para = 0;
action_x_loc = castXLoc;
action_y_loc = castYLoc;
unitGod->cast_power_type = castPowerType;
unitGod->cast_origin_x = next_x_loc();
unitGod->cast_origin_y = next_y_loc();
unitGod->cast_target_x = castXLoc;
unitGod->cast_target_y = castYLoc;
}
//----------- End of function Unit::go_cast_power -----------//
//--------- Begin of function Unit::process_go_cast_power ---------//
// process action of god casting
//
void Unit::process_go_cast_power()
{
err_when(mobile_type!=UNIT_AIR);
err_when(action_x_loc2<0 || action_x_loc2>=MAX_WORLD_X_LOC);
err_when(action_y_loc2<0 || action_y_loc2>=MAX_WORLD_Y_LOC);
UnitGod *unitGod = (UnitGod *)this;
if(cur_action==SPRITE_IDLE)
{
//----------------------------------------------------------------------------------------//
// Checking condition to do casting power, Or resume action
//----------------------------------------------------------------------------------------//
if(m.points_distance(cur_x_loc(), cur_y_loc(), action_x_loc2, action_y_loc2)<=DO_CAST_POWER_RANGE)
{
if( next_x_loc() != action_x_loc2 ||
next_y_loc() != action_y_loc2 )
{
set_dir(next_x_loc(), next_y_loc(), action_x_loc2, action_y_loc2);
}
set_attack(); // set cur_action=sprite_attack to cast power
cur_frame = 1;
}
else
{
err_when(action_mode2!=ACTION_GO_CAST_POWER || action_para2);
go_cast_power(action_x_loc2, action_y_loc2, unitGod->cast_power_type, COMMAND_AUTO);
}
}
else if(cur_action==SPRITE_ATTACK)
{
//----------------------------------------------------------------------------------------//
// do casting power now
//----------------------------------------------------------------------------------------//
AttackInfo *attackInfo = attack_info_array + cur_attack;
if(cur_frame == attackInfo->bullet_out_frame)
{
// add effect
add_close_attack_effect();
unitGod->cast_power(action_x_loc2, action_y_loc2);
set_remain_attack_delay();
// stop2();
}
if( cur_frame == 1 && remain_attack_delay == 0 ) // last frame of delaying
stop2();
}
}
//----------- End of function Unit::process_go_cast_power -----------//