/*
* 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 : OF_CAMP.CPP
//Description : Firm Military Camp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//----------- Define static vars -------------//
static Button3D button_patrol, button_reward, button_defense;
static Firm* cur_firm_ptr;
//--------- Declare static functions ---------//
static int sort_soldier_function( const void *a, const void *b );
static int sort_soldier_id_function( const void *a, const void *b );
static void disp_debug_info(FirmCamp* firmPtr, int refreshFlag);
//--------- Begin of function FirmCamp::FirmCamp ---------//
//
FirmCamp::FirmCamp()
{
firm_skill_id = SKILL_LEADING;
employ_new_worker = 1;
memset(defense_array, 0, sizeof(DefenseUnit)*(MAX_WORKER+1));
defend_target_recno = 0;
defense_flag = 1;
is_attack_camp = 0;
}
//----------- End of function FirmCamp::FirmCamp -----------//
//--------- Begin of function FirmCamp::deinit ---------//
//
void FirmCamp::deinit()
{
int firmRecno = firm_recno; // save the firm_recno first for reset_unit_home_camp()
Firm::deinit();
//-------------------------------------------//
int saveOverseerRecno = overseer_recno;
overseer_recno = 0; // set overseer_recno to 0 when calling update_influence(), so this base is disregarded.
update_influence();
overseer_recno = saveOverseerRecno;
clear_defense_mode();
//---- reset all units whose home_camp_firm_recno is this firm ----//
reset_unit_home_camp(firmRecno); // this must be called at last as Firm::deinit() will create new units.
//--- if this camp is in the Nation::attack_camp_array[], remove it now ---//
reset_attack_camp(firmRecno);
}
//----------- End of function FirmCamp::deinit -----------//
//--------- Begin of function FirmCamp::reset_unit_home_camp ---------//
//
void FirmCamp::reset_unit_home_camp(int firmRecno)
{
//---- reset all units whose home_camp_firm_recno is this firm ----//
Unit* unitPtr;
for( int i=unit_array.size() ; i>0 ; i-- )
{
if( unit_array.is_deleted(i) )
continue;
unitPtr = unit_array[i];
if( unitPtr->home_camp_firm_recno == firmRecno )
unitPtr->home_camp_firm_recno = 0;
}
}
//----------- End of function FirmCamp::reset_unit_home_camp -----------//
//--------- Begin of function FirmCamp::reset_attack_camp ---------//
//
void FirmCamp::reset_attack_camp(int firmRecno)
{
//--- if this camp is in the Nation::attack_camp_array[], remove it now ---//
if( firm_ai )
{
Nation* nationPtr = nation_array[nation_recno];
for( int i=0 ; iattack_camp_count ; i++ )
{
if( nationPtr->attack_camp_array[i].firm_recno == firmRecno )
{
m.del_array_rec(nationPtr->attack_camp_array, nationPtr->attack_camp_count, sizeof(AttackCamp), i+1 );
nationPtr->attack_camp_count--;
break;
}
}
}
}
//----------- End of function FirmCamp::reset_attack_camp -----------//
//--------- Begin of function FirmCamp::clear_defense_mode ---------//
void FirmCamp::clear_defense_mode()
{
//------------------------------------------------------------------//
// change defense unit's to non-defense mode
//------------------------------------------------------------------//
Unit *unitPtr;
for(int i=unit_array.size(); i>=1; --i)
{
if(unit_array.is_deleted(i))
continue;
unitPtr = unit_array[i];
if(!unitPtr)
continue;
err_when(unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE || unitPtr->hit_points<=0);
if(unitPtr->in_auto_defense_mode() && unitPtr->action_misc==ACTION_MISC_DEFENSE_CAMP_RECNO &&
unitPtr->action_misc_para==firm_recno)
unitPtr->clear_unit_defense_mode();
}
memset(defense_array, 0, sizeof(DefenseUnit)*(MAX_WORKER+1));
}
//----------- End of function FirmCamp::clear_defense_mode -----------//
//--------- Begin of function FirmCamp::assign_unit ---------//
//
void FirmCamp::assign_unit(int unitRecno)
{
Unit* unitPtr = unit_array[unitRecno];
//------- if this is a construction worker -------//
if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION )
{
set_builder(unitRecno);
return;
}
//-------- assign the unit ----------//
int rankId = unit_array[unitRecno]->rank_id;
if( rankId == RANK_GENERAL || rankId==RANK_KING )
{
assign_overseer(unitRecno);
}
else
{
assign_worker(unitRecno);
}
}
//----------- End of function FirmCamp::assign_unit -----------//
//--------- Begin of function FirmCamp::assign_overseer ---------//
//
void FirmCamp::assign_overseer(int overseerRecno)
{
//---- reset the team member count of the general ----//
if( overseerRecno )
{
Unit* unitPtr = unit_array[overseerRecno];
err_when( !unitPtr->race_id );
err_when( unitPtr->rank_id != RANK_GENERAL && unitPtr->rank_id != RANK_KING );
err_when( !unitPtr->team_info );
unitPtr->team_info->member_count = 0;
unitPtr->home_camp_firm_recno = 0;
}
//----- assign the overseer now -------//
Firm::assign_overseer(overseerRecno);
//------------- update influence -----------//
update_influence();
}
//----------- End of function FirmCamp::assign_overseer -----------//
//--------- Begin of function FirmCamp::assign_worker --------//
//
// Increase armed unit count of the race of the worker assigned,
// as when a unit is assigned to a camp, Unit::deinit() will decrease
// the counter, so we need to increase it back here.
//
void FirmCamp::assign_worker(int workerUnitRecno)
{
Firm::assign_worker(workerUnitRecno);
//--- remove the unit from patrol_unit_array when it returns to the base ---//
validate_patrol_unit();
//-------- sort soldiers ---------//
sort_soldier();
}
//----------- End of function FirmCamp::assign_worker --------//
//------- Begin of function FirmCamp::validate_patrol_unit ---------//
//
void FirmCamp::validate_patrol_unit()
{
int unitRecno;
Unit* unitPtr;
err_when( patrol_unit_count > 9 );
for( int i=patrol_unit_count ; i>0 ; i-- )
{
unitRecno = patrol_unit_array[i-1];
if( unit_array.is_deleted(unitRecno) ||
(unitPtr=unit_array[unitRecno])->is_visible()==0 ||
unitPtr->nation_recno != nation_recno )
{
err_when( patrol_unit_count > 9 );
m.del_array_rec( patrol_unit_array, patrol_unit_count, sizeof(patrol_unit_array[0]), i );
err_when( patrol_unit_count==0 ); // it's already 0
patrol_unit_count--;
err_when( patrol_unit_count < 0 );
err_when( patrol_unit_count > 9 );
}
}
}
//-------- End of function FirmCamp::validate_patrol_unit ---------//
//------- Begin of function FirmCamp::change_nation ---------//
//
void FirmCamp::change_nation(int newNationRecno)
{
//--- update the UnitInfo vars of the workers in this firm ---//
for( int i=0 ; iunit_change_nation(newNationRecno, nation_recno, worker_array[i].rank_id );
//----- reset unit's home camp to this firm -----//
reset_unit_home_camp(firm_recno);
//--- if this camp is in the Nation::attack_camp_array[], remove it now ---//
reset_attack_camp(firm_recno);
//---- reset AI vars --------//
ai_capture_town_recno = 0;
ai_recruiting_soldier = 0;
//-------- change the nation of this firm now ----------//
Firm::change_nation(newNationRecno);
}
//-------- End of function FirmCamp::change_nation ---------//
//--------- Begin of function FirmCamp::update_influence ---------//
//
// Update this camp's influence on neighbor towns.
//
void FirmCamp::update_influence()
{
int i;
Town* townPtr;
for( i=0 ; ination_recno )
townPtr->update_target_loyalty();
else
townPtr->update_target_resistance();
}
}
}
//----------- End of function FirmCamp::update_influence -----------//
//--------- Begin of function FirmCamp::put_info ---------//
//
void FirmCamp::put_info(int refreshFlag)
{
disp_basic_info(INFO_Y1, refreshFlag);
if( !should_show_info() )
return;
disp_camp_info(INFO_Y1+54, refreshFlag);
disp_worker_list(INFO_Y1+104, refreshFlag);
disp_worker_info(INFO_Y1+168, refreshFlag);
//------ display button -------//
int x;
if( own_firm() )
{
if( refreshFlag==INFO_REPAINT )
{
button_patrol.paint( INFO_X1, INFO_Y1+242, 'A', "PATROL" );
button_reward.paint( INFO_X1+BUTTON_ACTION_WIDTH, INFO_Y1+242, 'A', "REWARDCB" );
button_defense.paint( INFO_X2-BUTTON_ACTION_WIDTH, INFO_Y1+242, 'A', defense_flag ? (char*)"DEFENSE1" : (char*)"DEFENSE0" );
}
if( overseer_recno || worker_count )
button_patrol.enable();
else
button_patrol.disable();
if( nation_array[nation_recno]->cash >= REWARD_COST &&
( (overseer_recno && unit_array[overseer_recno]->rank_id != RANK_KING)
|| selected_worker_id ) )
{
button_reward.enable();
}
else
{
button_reward.disable();
}
x=INFO_X1+BUTTON_ACTION_WIDTH*2;
}
else
x=INFO_X1;
disp_spy_button(x, INFO_Y1+242, refreshFlag);
#ifdef DEBUG
if( sys.testing_session || sys.debug_session )
disp_debug_info(this, refreshFlag);
#endif
}
//----------- End of function FirmCamp::put_info -----------//
//--------- Begin of function FirmCamp::detect_info ---------//
//
void FirmCamp::detect_info()
{
if( detect_basic_info() )
return;
if( !should_show_info() )
return;
//------ detect the overseer button -----//
int rc = mouse.single_click(INFO_X1+6, INFO_Y1+58,
INFO_X1+5+UNIT_LARGE_ICON_WIDTH, INFO_Y1+57+UNIT_LARGE_ICON_HEIGHT, 2 );
if( rc==1 ) // display this overseer's info
{
selected_worker_id = 0;
disp_camp_info(INFO_Y1+54, INFO_UPDATE);
disp_worker_list(INFO_Y1+104, INFO_UPDATE);
disp_worker_info(INFO_Y1+168, INFO_UPDATE);
}
//--------- detect soldier info ---------//
if( detect_worker_list() )
{
disp_camp_info(INFO_Y1+54, INFO_UPDATE);
disp_worker_list(INFO_Y1+104, INFO_UPDATE);
disp_worker_info(INFO_Y1+168, INFO_UPDATE);
}
//---------- detect spy button ----------//
detect_spy_button();
if( !own_firm() )
return;
//------ detect the overseer button -----//
if( rc==2 )
{
if(remote.is_enable())
{
// packet structure :
short *shortPtr=(short *)remote.new_send_queue_msg(MSG_FIRM_MOBL_OVERSEER, sizeof(short));
shortPtr[0] = firm_recno;
}
else
{
assign_overseer(0); // the overseer quits the camp
}
}
//----------- detect patrol -----------//
if( button_patrol.detect() )
{
if(remote.is_enable())
{
// packet structure :
short *shortPtr=(short *)remote.new_send_queue_msg(MSG_F_CAMP_PATROL, sizeof(short));
shortPtr[0] = firm_recno;
}
else
{
patrol();
}
}
//----------- detect reward -----------//
if( button_reward.detect() )
{
reward(selected_worker_id, COMMAND_PLAYER);
// ##### begin Gilbert 25/9 ######//
se_ctrl.immediate_sound("TURN_ON");
// ##### end Gilbert 25/9 ######//
}
//----- detect defense mode button -------//
if( button_defense.detect() )
{
// ##### begin Gilbert 25/9 ######//
se_ctrl.immediate_sound( !defense_flag?(char*)"TURN_ON":(char*)"TURN_OFF");
// ##### end Gilbert 25/9 ######//
if( !remote.is_enable() )
{
// update RemoteMsg::toggle_camp_patrol()
defense_flag = !defense_flag;
}
else
{
// packet structure :
short *shortPtr=(short *)remote.new_send_queue_msg(MSG_F_CAMP_TOGGLE_PATROL, 2*sizeof(short));
shortPtr[0] = firm_recno;
shortPtr[1] = !defense_flag;
}
button_defense.update_bitmap( defense_flag ? (char*)"DEFENSE1" : (char*)"DEFENSE0" );
}
}
//----------- End of function FirmCamp::detect_info -----------//
//--------- Begin of function FirmCamp::disp_camp_info ---------//
//
void FirmCamp::disp_camp_info(int dispY1, int refreshFlag)
{
//---------------- paint the panel --------------//
if( refreshFlag == INFO_REPAINT )
vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+46);
if( !overseer_recno )
return;
//------------ display overseer info -------------//
Unit* overseerUnit = unit_array[overseer_recno];
int x=INFO_X1+6, y=dispY1+4, x1=x+UNIT_LARGE_ICON_WIDTH+8;
if( selected_worker_id == 0 )
{
vga_front.rect( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+1, 2, V_YELLOW );
}
else
{
vga.blt_buf( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y-1, 0 );
vga.blt_buf( x-2, y+UNIT_LARGE_ICON_HEIGHT+1, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
vga.blt_buf( x-2, y-2, x-1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
vga.blt_buf( x+UNIT_LARGE_ICON_WIDTH, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
}
//-------------------------------------//
if( refreshFlag == INFO_REPAINT )
{
vga_front.put_bitmap(x, y, unit_res[overseerUnit->unit_id]->get_large_icon_ptr(overseerUnit->rank_id) );
}
//-------- set help parameters --------//
if( mouse.in_area(x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3) )
help.set_unit_help( overseerUnit->unit_id, overseerUnit->rank_id, x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3);
//-------------------------------------//
if( overseerUnit->rank_id == RANK_KING )
{
if( refreshFlag == INFO_REPAINT )
font_san.put( x1, y, "King" );
y+=14;
}
if( refreshFlag == INFO_REPAINT )
font_san.put( x1, y, overseerUnit->unit_name(0), 0, INFO_X2-2 ); // 0-ask unit_name() not to return the title of the unit
y+=14;
//------- display leadership -------//
String str;
str = translate.process("Leadership");
str += ": ";
str += overseerUnit->skill.get_skill(SKILL_LEADING);
font_san.disp( x1, y, str, INFO_X2-10 );
y+=14;
//--------- display loyalty ----------//
if( overseerUnit->rank_id != RANK_KING )
{
x1 = font_san.put( x1, y, "Loyalty:" );
int x2 = info.disp_loyalty( x1, y-1, x1, overseerUnit->loyalty, overseerUnit->target_loyalty, nation_recno, refreshFlag );
if( overseerUnit->spy_recno )
{
//------ if this is the player's spy -------//
if( overseerUnit->true_nation_recno() == nation_array.player_recno )
{
vga_front.put_bitmap( x2+5, y+1, image_icon.get_ptr("U_SPY") );
x2 += 15;
}
}
vga.blt_buf( x2, y-1, INFO_X2-2, dispY1+44, 0 );
}
}
//----------- End of function FirmCamp::disp_camp_info -----------//
//--------- Begin of function FirmCamp::next_day ---------//
//
void FirmCamp::next_day()
{
//----- call next_day() of the base class -----//
Firm::next_day();
//----- update the patrol_unit_array -----//
validate_patrol_unit();
//--------------------------------------//
if( info.game_date%15 == firm_recno%15 ) // once a week
{
train_unit();
recover_hit_point();
}
//--- if there are weapons in the firm, pay for their expenses ---//
pay_weapon_expense();
}
//----------- End of function FirmCamp::next_day -----------//
//------- Begin of function FirmCamp::train_unit -------//
//
// Increase the leadership and ocmbat level of the general and the soldiers.
//
void FirmCamp::train_unit()
{
if( !overseer_recno )
return;
Unit* overseerUnit = unit_array[overseer_recno];
if( overseerUnit->skill.skill_id != SKILL_LEADING )
return;
int overseerSkill = overseerUnit->skill.skill_level;
RaceInfo* overseerRaceInfo = race_res[overseerUnit->race_id];
int incValue;
//------- increase the commander's leadership ---------//
if( worker_count > 0 && overseerUnit->skill.skill_level < 100 )
{
//-- the more soldiers this commander has, the higher the leadership will increase ---//
incValue = 5 * worker_count
* (int) overseerUnit->hit_points / overseerUnit->max_hit_points
* (100+overseerUnit->skill.skill_potential*2) / 100;
overseerUnit->skill.skill_level_minor += incValue;
if( overseerUnit->skill.skill_level_minor >= 100 )
{
overseerUnit->skill.skill_level_minor -= 100;
overseerUnit->skill.skill_level++;
}
}
//------- increase the commander's combat level ---------//
if( overseerUnit->skill.combat_level < 100 )
{
incValue = 20 * (int) overseerUnit->hit_points / overseerUnit->max_hit_points
* (100+overseerUnit->skill.skill_potential*2) / 100;
overseerUnit->skill.combat_level_minor += incValue;
if( overseerUnit->skill.combat_level_minor >= 100 )
{
overseerUnit->skill.combat_level_minor -= 100;
overseerUnit->set_combat_level(overseerUnit->skill.combat_level+1);
}
}
//------- increase the solider's combat level -------//
int levelMinor;
Worker* workerPtr = worker_array;
for( int i=0 ; iskill_id != SKILL_LEADING )
continue;
//------- increase worker skill -----------//
if( workerPtr->combat_level < overseerSkill )
{
incValue = max(20, overseerSkill-workerPtr->combat_level)
* workerPtr->hit_points / workerPtr->max_hit_points()
* (100+workerPtr->skill_potential*2) / 100;
levelMinor = workerPtr->combat_level_minor + incValue; // with random factors, resulting in 75% to 125% of the original
while( levelMinor >= 100 )
{
levelMinor -= 100;
workerPtr->combat_level++;
}
workerPtr->combat_level_minor = levelMinor;
}
//-- if the soldier has leadership potential, he learns leadership --//
if( workerPtr->skill_potential > 0 && workerPtr->skill_level < 100 )
{
incValue = (int) max(50, overseerUnit->skill.skill_level-workerPtr->skill_level)
* workerPtr->hit_points / workerPtr->max_hit_points()
* workerPtr->skill_potential*2 / 100;
workerPtr->skill_level_minor += incValue;
err_when( workerPtr->skill_level >= 100 );
if( workerPtr->skill_level_minor > 100 )
{
workerPtr->skill_level++;
workerPtr->skill_level_minor -= 100;
}
}
}
sort_soldier();
}
//-------- End of function FirmCamp::train_unit --------//
//------- Begin of function FirmCamp::recover_hit_point -------//
//
// Soldiers recover their hit points.
//
// No need to recover the hit points of the general here as
// this is taken care in the Unit class function of the general.
//
void FirmCamp::recover_hit_point()
{
Worker* workerPtr = worker_array;
for( int i=0 ; ihit_points < workerPtr->max_hit_points() )
workerPtr->hit_points++;
}
}
//------- End of function FirmCamp::recover_hit_point -------//
//------- Begin of function FirmCamp::pay_weapon_expense -------//
//
void FirmCamp::pay_weapon_expense()
{
Worker* workerPtr = worker_array;
Nation* nationPtr = nation_array[nation_recno];
for( int i=1 ; i<=worker_count ; i++, workerPtr++ )
{
if( workerPtr->unit_id &&
unit_res[workerPtr->unit_id]->unit_class == UNIT_CLASS_WEAPON )
{
if( nationPtr->cash > 0 )
{
nationPtr->add_expense( EXPENSE_WEAPON, (float) unit_res[workerPtr->unit_id]->year_cost / 365, 1 );
}
else // decrease hit points if the nation cannot pay the unit
{
if( workerPtr->hit_points > 0 )
workerPtr->hit_points--;
if( workerPtr->hit_points == 0 )
kill_worker(i); // if its hit points is zero, delete it
err_when( workerPtr->hit_points < 0 );
}
}
}
}
//------- End of function FirmCamp::pay_weapon_expense -------//
//--------- Begin of function FirmCamp::patrol ---------//
//
void FirmCamp::patrol()
{
err_when( !overseer_recno && !worker_count );
err_when( firm_ai && ai_capture_town_recno ); // ai_capture_town_recno is set after patrol() is called
if( nation_recno == nation_array.player_recno )
power.reset_selection();
//------------------------------------------------------------//
// If the commander in this camp has units under his lead
// outside and he is now going to lead a new team, then
// the old team members should be reset.
//------------------------------------------------------------//
if(overseer_recno)
{
TeamInfo* teamInfo = unit_array[overseer_recno]->team_info;
if( worker_count>0 && teamInfo->member_count>0 )
{
int unitRecno;
for( int i=0 ; imember_count ; i++ )
{
unitRecno = teamInfo->member_unit_array[i];
if( unit_array.is_deleted(unitRecno) )
continue;
unit_array[unitRecno]->leader_unit_recno = 0;
}
}
}
//------------------------------------------------------------//
// mobilize workers first, then the overseer.
//------------------------------------------------------------//
short overseerRecno = overseer_recno;
if(patrol_all_soldier() && overseer_recno)
{
Unit* unitPtr = unit_array[overseer_recno];
err_when(unitPtr->rank_id!=RANK_GENERAL && unitPtr->rank_id!=RANK_KING);
unitPtr->team_id = unit_array.cur_team_id-1; // set it to the same team as the soldiers which are defined in mobilize_all_worker()
if( nation_recno == nation_array.player_recno )
{
unitPtr->selected_flag = 1;
unit_array.selected_recno = overseer_recno;
unit_array.selected_count++;
}
}
assign_overseer(0);
//---------------------------------------------------//
if(overseerRecno && !overseer_recno) // has overseer and the overseer is mobilized
{
Unit* overseerUnit = unit_array[overseerRecno];
if(overseerUnit->is_own() )
{
se_res.sound( overseerUnit->cur_x_loc(), overseerUnit->cur_y_loc(), 1,
'S', overseerUnit->sprite_id, "SEL");
}
err_when( patrol_unit_count > MAX_WORKER );
//--- add the overseer into the patrol_unit_array[] of this camp ---//
patrol_unit_array[patrol_unit_count++] = overseerRecno;
err_when( patrol_unit_count > 9 );
//------- set the team_info of the overseer -------//
err_when( !overseerUnit->team_info );
for( int i=0 ; iteam_info->member_unit_array[i] = patrol_unit_array[i];
overseerUnit->team_info->member_count = patrol_unit_count;
}
//-------- display info --------//
if( nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
info.disp();
err_when( patrol_unit_count < 0 );
err_when( patrol_unit_count > 9 );
}
//----------- End of function FirmCamp::patrol -----------//
//--------- Begin of function FirmCamp::patrol_all_soldier ---------//
//
// return 1 if there is enough space for patroling all soldiers
// return 0 otherwise
//
int FirmCamp::patrol_all_soldier()
{
err_when(!worker_array); // this function shouldn't be called if this firm does not need worker
//------- detect buttons on hiring firm workers -------//
err_when(worker_count>MAX_WORKER);
#ifdef DEBUG
int loopCount=0;
#endif
short unitRecno;
int mobileWorkerId = 1;
patrol_unit_count = 0; // reset it, it will be increased later
while(worker_count>0 && mobileWorkerId<=worker_count)
{
err_when(++loopCount > 100);
if(worker_array[mobileWorkerId-1].skill_id==SKILL_LEADING)
{
unitRecno = mobilize_worker(mobileWorkerId, COMMAND_AUTO);
patrol_unit_array[patrol_unit_count++] = unitRecno;
err_when(patrol_unit_count>MAX_WORKER);
}
else
{
mobileWorkerId++;
continue;
}
if(!unitRecno)
return 0; // keep the rest workers as there is no space for creating the unit
if(overseer_recno)
{
Unit* unitPtr = unit_array[unitRecno];
unitPtr->team_id = unit_array.cur_team_id; // define it as a team
unitPtr->leader_unit_recno = overseer_recno;
unitPtr->update_loyalty(); // the unit is just assigned to a new leader, set its target loyalty
err_when( unit_array[overseer_recno]->rank_id != RANK_KING &&
unit_array[overseer_recno]->rank_id != RANK_GENERAL );
if( nation_recno == nation_array.player_recno )
{
unitPtr->selected_flag = 1;
unit_array.selected_count++;
}
}
}
unit_array.cur_team_id++;
return 1;
}
//----------- End of function FirmCamp::patrol_all_soldier -----------//
//--------- Begin of function FirmCamp::mobilize_overseer --------//
//
int FirmCamp::mobilize_overseer()
{
int unitRecno = Firm::mobilize_overseer();
//--- set the home camp firm recno of the unit for later return ---//
if( unitRecno )
{
unit_array[unitRecno]->home_camp_firm_recno = firm_recno;
return unitRecno;
}
else
return 0;
}
//----------- End of function FirmCamp::mobilize_overseer --------//
//--------- Begin of function FirmCamp::mobilize_worker ---------//
//
int FirmCamp::mobilize_worker(int workerId, char remoteAction)
{
int unitRecno = Firm::mobilize_worker(workerId, remoteAction);
//--- set the home camp firm recno of the unit for later return ---//
if( unitRecno )
{
unit_array[unitRecno]->home_camp_firm_recno = firm_recno;
return unitRecno;
}
else
return 0;
}
//----------- End of function FirmCamp::mobilize_worker -----------//
//--------- Begin of function FirmCamp::defense ---------//
//### begin alex 15/10 ###//
//void FirmCamp::defense(short targetRecno)
void FirmCamp::defense(short targetRecno, int useRangeAttack)
//#### end alex 15/10 ####//
{
//### begin alex 15/10 ###//
//--******* BUGHERE , please provide a reasonable condition to set useRangeAttack to 1
if(unit_array[targetRecno]->mobile_type!=UNIT_LAND)
useRangeAttack = 1;
else
useRangeAttack = 0;
//#### end alex 15/10 ####//
if( !defense_flag )
return;
//--------------- define parameters ------------------//
DefenseUnit *defPtr, *defPtr2;
Unit *unitPtr;
short unitRecno;
int numOfUnitInside = worker_count + (overseer_recno>0);
int i, j;
if(employ_new_worker)
{
//---------- reset unit's parameters in the previous defense -----------//
defPtr = defense_array;
for(int i=0; i<=MAX_WORKER; i++, defPtr++)
{
if(defPtr->status==OUTSIDE_CAMP && defPtr->unit_recno && !unit_array.is_deleted(defPtr->unit_recno))
{
unitPtr = unit_array[defPtr->unit_recno];
if(unitPtr->nation_recno==nation_recno && unitPtr->action_misc==ACTION_MISC_DEFENSE_CAMP_RECNO &&
unitPtr->action_misc_para==firm_recno)
{
unitPtr->clear_unit_defense_mode();
err_when(unitPtr->in_auto_defense_mode());
}
}
}
memset(defense_array, 0, sizeof(DefenseUnit)*(MAX_WORKER+1));
}
//------------------------------------------------------------------//
// check all the exist(not dead) units outside the camp and arrange
// them in the front part of the array.
//------------------------------------------------------------------//
j = 0;
defPtr2 = defense_array;
if(!employ_new_worker) // some soliders may be outside the camp
{
for(i=0, defPtr=defense_array; i<=MAX_WORKER; i++, defPtr++)
{
if(!defPtr->unit_recno)
continue; // a free slot
if(unit_array.is_deleted(defPtr->unit_recno))
{
defPtr->unit_recno = 0;
continue; // unit is dead
}
//----------------------------------------------------------------//
// arrange the recno in the array front part
//----------------------------------------------------------------//
if(defPtr->status==OUTSIDE_CAMP)
{
unitPtr = unit_array[defPtr->unit_recno];
//-------------- ignore this unit if it is dead --------------------//
if(unitPtr->is_unit_dead())
continue;
if(!unitPtr->in_auto_defense_mode())
continue; // the unit is ordered by the player to do other thing, so cannot control it afterwards
//--------------- the unit is in defense mode ----------------//
defPtr2->unit_recno = defPtr->unit_recno;
defPtr2->status = OUTSIDE_CAMP;
j++;
defPtr2++;
}
}
err_when(defPtr2 + (MAX_WORKER-j+1) > defense_array + MAX_WORKER + 1);
memset(defPtr2, 0, sizeof(DefenseUnit)*(MAX_WORKER-j+1));
}
set_employ_worker(0);
//------------------------------------------------------------------//
// the unit outside the camp should be in defense mode and ready to
// attack new target
//------------------------------------------------------------------//
for(i=0, defPtr=defense_array; iunit_recno];
defense_outside_camp(defPtr->unit_recno, targetRecno);
unitPtr->action_misc = ACTION_MISC_DEFENSE_CAMP_RECNO;
unitPtr->action_misc_para = firm_recno;
}
int mobilizePos = 0;
//### begin alex 13/10 ###//
//for(; i= worker_count);
//------------------------------------------------------------------//
// order those soldier inside the firm to move to target for attacking
// keep those unable to attack inside the firm
//------------------------------------------------------------------//
//### begin alex 13/10 ###//
//if(worker_array[mobilizePos].unit_id==UNIT_EXPLOSIVE_CART)
if(worker_array[mobilizePos].unit_id==UNIT_EXPLOSIVE_CART ||
(useRangeAttack && worker_array[mobilizePos].max_attack_range()==1))
//#### end alex 13/10 ####//
{
mobilizePos++;
continue;
}
unitRecno = mobilize_worker(mobilizePos+1, COMMAND_AUTO);
//unitRecno = mobilize_worker(1, COMMAND_AUTO); // always record 1 as the workers info are moved forward from the back to the front
if(!unitRecno)
break;
Unit* unitPtr = unit_array[unitRecno];
unitPtr->team_id = unit_array.cur_team_id; // define it as a team
unitPtr->action_misc = ACTION_MISC_DEFENSE_CAMP_RECNO;
unitPtr->action_misc_para = firm_recno; // store the firm_recno for going back camp
defense_inside_camp(unitRecno, targetRecno);
defPtr->unit_recno = unitRecno;
defPtr->status = OUTSIDE_CAMP;
}
/*if(overseer_recno>0)
{
//------------------------------------------------------------------//
// order those overseer inside the firm to move to target for attacking
//------------------------------------------------------------------//
unitPtr = unit_array[overseer_recno];
assign_overseer(0);
unitPtr->team_id = unit_array.cur_team_id; // define it as a team
unitPtr->action_misc = ACTION_MISC_DEFENSE_CAMP_RECNO;
unitPtr->action_misc_para = firm_recno; // store the firm_recno for going back camp
defense_inside_camp(unitPtr->sprite_recno, targetRecno);
defPtr->unit_recno = unitPtr->sprite_recno;
defPtr->status = OUTSIDE_CAMP;
}*/
unit_array.cur_team_id++;
}
//----------- End of function FirmCamp::defense -----------//
//--------- Begin of function FirmCamp::defense_inside_camp ---------//
void FirmCamp::defense_inside_camp(short unitRecno, short targetRecno)
{
Unit *unitPtr = unit_array[unitRecno];
unitPtr->defense_attack_unit(targetRecno);
// err_when(unitPtr->action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET);
if(unitPtr->action_mode==ACTION_STOP && !unitPtr->action_para && unitPtr->action_x_loc==-1 && unitPtr->action_y_loc==-1)
unitPtr->defense_detect_target();
}
//----------- End of function FirmCamp::defense_inside_camp -----------//
//--------- Begin of function FirmCamp::defense_outside_camp ---------//
void FirmCamp::defense_outside_camp(short unitRecno, short targetRecno)
{
Unit *unitPtr = unit_array[unitRecno];
if(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET || unitPtr->action_mode2==ACTION_AUTO_DEFENSE_BACK_CAMP ||
(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET && unitPtr->cur_action==SPRITE_IDLE))
{
//----------------- attack new target now -------------------//
unitPtr->defense_attack_unit(targetRecno);
err_when(unitPtr->action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && unitPtr->action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET);
if(unitPtr->action_mode==ACTION_STOP && !unitPtr->action_para && unitPtr->action_x_loc==-1 && unitPtr->action_y_loc==-1)
unitPtr->defense_detect_target();
}
}
//----------- End of function FirmCamp::defense_outside_camp -----------//
//--------- Begin of function FirmCamp::set_employ_worker ---------//
void FirmCamp::set_employ_worker(char flag)
{
employ_new_worker = flag;
if(!flag)
ai_status = CAMP_IN_DEFENSE;
else
ai_status = FIRM_WITHOUT_ACTION;
/*
//------- a button should exist for accept new worker or not ---------//
//-*********** codes here **********-//
Town *townPtr;
for(int i=0; ination_recno)
toggle_town_link(i+1, employ_new_worker, COMMAND_AUTO); // enable links if employ_new_worker is true, otherwise disable
}
*/
}
//----------- End of function FirmCamp::set_employ_worker -----------//
//--------- Begin of function FirmCamp::update_defense_unit ---------//
void FirmCamp::update_defense_unit(short unitRecno)
{
DefenseUnit *defPtr = defense_array;
int allInCamp = 1;
int found=0;
for(int i=0; i<=MAX_WORKER; i++, defPtr++)
{
if(!defPtr->unit_recno)
continue; // empty slot
if(unit_array.is_deleted(defPtr->unit_recno))
{
defPtr->unit_recno = 0;
defPtr->status = INSIDE_CAMP;
continue;
}
if(defPtr->unit_recno==unitRecno)
{
defPtr->unit_recno = 0;
defPtr->status = INSIDE_CAMP;
Unit *unitPtr = unit_array[unitRecno];
unitPtr->stop2();
unitPtr->reset_action_misc_para();
err_when(unitPtr->in_auto_defense_mode());
found++;
}
else
allInCamp = 0; // some units are still outside camp
}
if(allInCamp)
{
set_employ_worker(1);
memset(defense_array, 0, sizeof(DefenseUnit)*(MAX_WORKER+1));
}
// err_when(!found); //**BUGHERE
}
//----------- End of function FirmCamp::update_defense_unit -----------//
//-------- Begin of function FirmCamp::is_worker_full ------//
//
int FirmCamp::is_worker_full()
{
return worker_count + patrol_unit_count + coming_unit_count >= MAX_WORKER;
}
//----------- End of function FirmCamp::is_worker_full ---------//
//--------- Begin of function FirmCamp::sort_soldier ---------//
//
// Sort units in camp by their leaderhip.
//
void FirmCamp::sort_soldier()
{
if( worker_count > 1 )
{
//--- prepare worker_id_array[] for later preserving the currently worker selected ---//
short worker_id_array[MAX_WORKER];
int i;
for( i=0 ; i worker_count );
qsort( worker_id_array, worker_count, sizeof(short), sort_soldier_id_function );
qsort( worker_array, worker_count, sizeof(Worker), sort_soldier_function );
//---- scan worker_id_array[] for preserving the currently worker selected ---//
if( selected_worker_id )
{
for( i=0 ; iskill_level - ((Worker*)a)->skill_level;
}
//----------- End of function sort_soldier_function -----------//
//--------- Begin of function sort_soldier_id_function ---------//
//
static int sort_soldier_id_function( const void *a, const void *b )
{
int workerId1 = *((short*)a);
int workerId2 = *((short*)b);
return cur_firm_ptr->worker_array[workerId2-1].skill_level -
cur_firm_ptr->worker_array[workerId1-1].skill_level;
}
//----------- End of function sort_soldier_id_function -----------//
#ifdef DEBUG
//----------- Begin of static function disp_debug_info -----------//
static void disp_debug_info(FirmCamp* firmPtr, int refreshFlag)
{
if( refreshFlag == INFO_REPAINT )
vga.d3_panel_up( INFO_X1, INFO_Y2-40, INFO_X2, INFO_Y2 );
int x=INFO_X1+3, y=INFO_Y2-37, x2=x+120;
font_san.field( x, y , "patrol unit count", x2, firmPtr->patrol_unit_count, 1, INFO_X2, refreshFlag);
font_san.field( x, y+16, "coming unit count", x2, firmPtr->coming_unit_count, 1, INFO_X2, refreshFlag);
font_san.put( x+180, y, firmPtr->firm_recno );
}
//----------- End of static function disp_debug_info -----------//
#endif