/*
* 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 : OFIRMIF3.CPP
//Description : Firm interface functions - part 3
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//---------- Define constant ------------//
#define BRIBE_OPTION_HEIGHT 19
//-------- Define bribe amounts ---------//
#define BRIBE_AMOUNT_COUNT 6
#define MAX_BRIBE_AMOUNT 4000
static short bribe_amount_array[] = { 500, 1000, 1500, 2000, 3000, 4000 };
//-------- Define static vars ---------//
static Button3D button_cancel;
//------ declare static functions -------//
static void disp_bribe_button(int y, int bribeAmount, int buttonUp);
//--------- Begin of function Firm::disp_bribe_menu ---------//
//
void Firm::disp_bribe_menu(int refreshFlag)
{
//---- if the briber or bribe target is no longer valid -----//
if( bribe_result == BRIBE_NONE )
{
if( !validate_cur_bribe() )
{
firm_menu_mode = FIRM_MENU_MAIN;
bribe_result = BRIBE_NONE;
info.disp();
return;
}
}
//------------------------------------//
if( refreshFlag != INFO_REPAINT )
return;
//------ display the bribe menu ------//
if( bribe_result == BRIBE_NONE )
{
int y=INFO_Y1;
font_san.d3_put( INFO_X1, y, INFO_X2, y+19, "Bribe" );
y+=22;
disp_bribe_unit( y );
y+=49;
for( int i=0 ; i MAX_BRIBE_AMOUNT );
y += BRIBE_OPTION_HEIGHT+2;
}
disp_bribe_button( y, 0, 1);
}
//------ display the bribe result -----//
else
{
int x=INFO_X1+4, y=INFO_Y1+4, y2=y+font_san.height()-1;
if( bribe_result == BRIBE_SUCCEED )
{
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+24 );
font_san.center_put( INFO_X1, y, INFO_X2, y2, "Bribing Succeeded." );
}
else
{
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
font_san.center_put( INFO_X1, y , INFO_X2, y2, "Bribing Failed." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
}
y+=26;
button_cancel.paint( INFO_X1, y, 'A', "CONTINUE" );
}
}
//----------- End of function Firm::disp_bribe_menu -----------//
//--------- Begin of function Firm::detect_bribe_menu ---------//
//
void Firm::detect_bribe_menu()
{
//----- if it is display the bribe result right now -----//
if( bribe_result != BRIBE_NONE )
{
if( button_cancel.detect() )
{
firm_menu_mode = FIRM_MENU_MAIN;
bribe_result = BRIBE_NONE;
info.disp();
}
return;
}
//-------------------------------------------//
int i, y=INFO_Y1+22+49;
for( i=0 ; i
short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_BRIBE, 4*sizeof(short));
*shortPtr = firm_recno;
shortPtr[1] = action_spy_recno;
shortPtr[2] = selected_worker_id;
shortPtr[3] = bribe_amount_array[i];
}
// ####### end Gilbert 13/10 #######//
}
y += BRIBE_OPTION_HEIGHT+2;
}
//------ detect the cancel button --------//
if( mouse.single_click(INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1) )
{
disp_bribe_button( y, 0, 0); // 0-display pressed button
while( mouse.left_press )
{
sys.yield();
mouse.get_event();
}
firm_menu_mode = FIRM_MENU_MAIN;
info.disp();
}
}
//----------- End of function Firm::detect_bribe_menu -----------//
//--------- Begin of function Firm::validate_cur_bribe ---------//
//
// Whether the current bribe action is still valid.
//
int Firm::validate_cur_bribe()
{
if( spy_array.is_deleted(action_spy_recno) ||
spy_array[action_spy_recno]->true_nation_recno != nation_array.player_recno )
{
return 0;
}
return can_spy_bribe( selected_worker_id, spy_array[action_spy_recno]->true_nation_recno );
}
//----------- End of function Firm::validate_cur_bribe -----------//
//-------- Begin of static function disp_bribe_button --------//
//
static void disp_bribe_button(int y, int bribeAmount, int buttonUp)
{
if( buttonUp )
vga.d3_panel_up( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1 );
else
vga.d3_panel_down( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1 );
//--------- if display cancel button ---------//
if( bribeAmount==0 )
font_san.center_put( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1, "Cancel" );
else
{
String str;
#ifdef GERMAN
str = m.format(bribeAmount,2);
str += " anbieten";
#else
str = translate.process("Offer ");
str += m.format(bribeAmount,2);
#endif
font_san.center_put( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1, str );
}
}
//--------- End of static function disp_bribe_button ---------//
//--------- Begin of function Firm::can_spy_bribe ---------//
//
// bribeWorkerId - worker id. in this firm to bribe
// 0 - if bribe an overseer.
//
// briberNationRecno - the nation recno of the briber.
//
int Firm::can_spy_bribe(int bribeWorkerId, int briberNationRecno)
{
int canBribe=0;
int spyRecno;
err_when( bribeWorkerId < 0 || bribeWorkerId > MAX_WORKER );
if( bribeWorkerId ) // the overseer is selected
spyRecno = worker_array[bribeWorkerId-1].spy_recno;
else
spyRecno = unit_array[overseer_recno]->spy_recno;
if( spyRecno )
{
canBribe = spy_array[spyRecno]->true_nation_recno != briberNationRecno; // only when the unit is not yet a spy of the player. Still display the bribe button when it's a spy of another nation
}
else
{
if( bribeWorkerId )
canBribe = worker_array[bribeWorkerId-1].race_id>0; // cannot bribe if it's a weapon
else
canBribe = unit_array[overseer_recno]->rank_id != RANK_KING; // cannot bribe a king
}
return canBribe;
}
//----------- End of function Firm::can_spy_bribe -----------//
//--------- Begin of function Firm::spy_bribe ---------//
//
// The money the spy offers to bribe the unit.
//
// bribeAmount - the amount offered
// birberSpyRecno - spy recno of the briber
// workerId - if 0, then bribe the overseer,
// if >0, then bribe a worker.
//
// return: >0 - bribing succeeded, return the spy recno of the bribed unit (as it has been turned into a spy)
// 0 - bribing failed
//
int Firm::spy_bribe(int bribeAmount, short briberSpyRecno, short workerId)
{
if( !can_spy_bribe(workerId, spy_array[briberSpyRecno]->true_nation_recno) ) // this can happen in multiplayer as there is a one frame delay when the message is sent and when it is processed
return 0;
//---------------------------------------//
int succeedChance = spy_bribe_succeed_chance(bribeAmount, briberSpyRecno, workerId);
Spy* spyPtr = spy_array[briberSpyRecno];
nation_array[spyPtr->true_nation_recno]->add_expense( EXPENSE_BRIBE, (float) bribeAmount, 0 );
//------ if the bribe succeeds ------//
if( succeedChance > 0 && m.random(100) < succeedChance )
{
int spyRecno = spy_array.add_spy(); // add a new Spy record
Spy* newSpy = spy_array[spyRecno];
newSpy->spy_skill = 10;
newSpy->action_mode = SPY_IDLE;
newSpy->spy_loyalty = min( 100, max(30,succeedChance) ); // within the 30-100 range
newSpy->true_nation_recno = spyPtr->true_nation_recno;
newSpy->cloaked_nation_recno = spyPtr->cloaked_nation_recno;
if( workerId )
{
Worker* workerPtr = worker_array+workerId-1;
workerPtr->spy_recno = spyRecno;
newSpy->race_id = workerPtr->race_id;
newSpy->name_id = workerPtr->name_id;
err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE );
if( !newSpy->name_id ) // if this worker does not have a name, give him one now as a spy must reserve a name (see below on use_name_id() for reasons)
newSpy->name_id = race_res[newSpy->race_id]->get_new_name_id();
}
else if( overseer_recno )
{
Unit* unitPtr = unit_array[overseer_recno];
unitPtr->spy_recno = spyRecno;
newSpy->race_id = unitPtr->race_id;
newSpy->name_id = unitPtr->name_id;
err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE );
}
else
err_here();
newSpy->set_place( SPY_FIRM, firm_recno );
//-- Spy always registers its name twice as his name will be freed up in deinit(). Keep an additional right because when a spy is assigned to a town, the normal program will free up the name id., so we have to keep an additional copy
race_res[newSpy->race_id]->use_name_id(newSpy->name_id);
bribe_result = BRIBE_SUCCEED;
if( firm_recno == firm_array.selected_recno )
info.disp();
return newSpy->spy_recno;
}
else //------- if the bribe fails --------//
{
spyPtr->get_killed(0); // the spy gets killed when the action failed.
// 0 - don't display new message for the spy being killed, so we already display the msg on the interface
bribe_result = BRIBE_FAIL;
if( firm_recno == firm_array.selected_recno )
info.disp();
return 0;
}
}
//----------- End of function Firm::spy_bribe -----------//
//--------- Begin of function Firm::spy_birbe_succeed_chance ---------//
//
// The money the spy offers to bribe the unit.
//
// bribeAmount - the amount offered
// birberSpyRecno - spy recno of the briber
// workerId - if 0, then bribe the overseer,
// if >0, then bribe a worker.
//
// return: 1 - bribing succeeded
// 0 - bribing failed
//
int Firm::spy_bribe_succeed_chance(int bribeAmount, short briberSpyRecno, short workerId)
{
Spy* spyPtr = spy_array[briberSpyRecno];
err_when( spyPtr->spy_place != SPY_FIRM );
err_when( spyPtr->spy_place_para != firm_recno );
//---- if the bribing target is a worker ----//
int unitLoyalty, unitRaceId, targetSpyRecno, unitCommandPower;
if( workerId )
{
Worker* workerPtr = worker_array+workerId-1;
unitLoyalty = workerPtr->loyalty();
unitRaceId = workerPtr->race_id;
unitCommandPower = 0;
targetSpyRecno = workerPtr->spy_recno;
}
else if( overseer_recno )
{
Unit* unitPtr = unit_array[overseer_recno];
unitLoyalty = unitPtr->loyalty;
unitRaceId = unitPtr->race_id;
unitCommandPower = unitPtr->commander_power();
targetSpyRecno = unitPtr->spy_recno;
}
else
err_here();
err_when( unitRaceId < 1 || unitRaceId > MAX_RACE );
//---- determine whether the bribe will be successful ----//
int succeedChance;
if( targetSpyRecno ) // if the bribe target is also a spy
{
err_when( spy_array[targetSpyRecno]->true_nation_recno == spyPtr->true_nation_recno ); // the player shouldn't be able to bribe units of his own
succeedChance = 0;
}
else
{
succeedChance = spyPtr->spy_skill - unitLoyalty - unitCommandPower
+ (int) nation_array[spyPtr->true_nation_recno]->reputation
+ 200 * bribeAmount / MAX_BRIBE_AMOUNT;
//-- the chance is higher if the spy or the spy's king is racially homongenous to the bribe target,
int spyKingRaceId = nation_array[ spyPtr->true_nation_recno ]->race_id;
succeedChance += race_res.is_same_race(spyPtr->race_id, unitRaceId) * 10 +
race_res.is_same_race(spyKingRaceId, unitRaceId) * 10;
if( unitLoyalty > 60 ) // harder for bribe units with over 60 loyalty
succeedChance -= (unitLoyalty-60);
if( unitLoyalty > 70 ) // harder for bribe units with over 70 loyalty
succeedChance -= (unitLoyalty-70);
if( unitLoyalty > 80 ) // harder for bribe units with over 80 loyalty
succeedChance -= (unitLoyalty-80);
if( unitLoyalty > 90 ) // harder for bribe units with over 90 loyalty
succeedChance -= (unitLoyalty-90);
if( unitLoyalty == 100 )
succeedChance = 0;
}
return succeedChance;
}
//----------- End of function Firm::spy_birbe_succeed_chance -----------//
//--------- Begin of function Firm::disp_bribe_unit ---------//
//
void Firm::disp_bribe_unit(int dispY1)
{
//---------------- paint the panel -----------------//
vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+46);
//------- get the info of the bribe target ---------//
// ####### begin Gilbert 8/8 ########//
int raceId, unitLoyalty, unitId, rankId;
char* unitName;
if( selected_worker_id )
{
Worker* workerPtr = worker_array+selected_worker_id-1;
raceId = workerPtr->race_id;
unitId = workerPtr->unit_id;
unitLoyalty = workerPtr->loyalty();
unitName = race_res[raceId]->get_name(workerPtr->name_id);
rankId = workerPtr->rank_id;
}
else if( overseer_recno )
{
Unit* unitPtr = unit_array[overseer_recno];
raceId = unitPtr->race_id;
unitId = unitPtr->unit_id;
unitLoyalty = unitPtr->loyalty;
unitName = unitPtr->unit_name();
rankId = unitPtr->rank_id;
}
else
err_here();
//--------- display info of the bribe target ---------//
int x=INFO_X1+6, y=dispY1+4;
vga_front.put_bitmap(x, y, unit_res[unitId]->get_large_icon_ptr(rankId) );
font_san.put( x+UNIT_LARGE_ICON_WIDTH+6, y+4, unitName );
//------- display skill and productivity ---------//
String str;
str = translate.process("Loyalty: ");
str += unitLoyalty;
font_san.disp( x+UNIT_LARGE_ICON_WIDTH+6, y+20, str, INFO_X2-10 );
}
//----------- End of function Firm::disp_bribe_unit -----------//
//--------- Begin of function Firm::disp_assassinate_result ---------//
//
void Firm::disp_assassinate_result(int refreshFlag)
{
if( refreshFlag != INFO_REPAINT )
return;
int x=INFO_X1+4, y=INFO_Y1+4, y2=y+font_san.height()-1;
if( assassinate_result == ASSASSINATE_SUCCEED_AT_LARGE )
{
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+43 );
font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Escaped." );
}
else if( assassinate_result == ASSASSINATE_SUCCEED_KILLED )
{
#ifdef GERMAN
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+80 );
font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy" ); // German text is longer
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Was Caught" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
#else
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
#endif
}
else
{
#ifdef GERMAN
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+80 );
font_san.center_put( INFO_X1, y , INFO_X2, y2, "Assassination Failed." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Was Caught" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
#else
vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
font_san.center_put( INFO_X1, y , INFO_X2, y2, "Assassination Failed." );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
#endif
}
y+=26;
button_cancel.paint( INFO_X1, y, 'A', "CONTINUE" );
}
//----------- End of function Firm::disp_assassinate_result -----------//
//--------- Begin of function Firm::detect_assassinate_result ---------//
//
void Firm::detect_assassinate_result()
{
//----- if it is display the bribe result right now -----//
if( button_cancel.detect() )
{
firm_menu_mode = FIRM_MENU_MAIN;
assassinate_result = 0;
info.disp();
}
}
//----------- End of function Firm::detect_assassinate_result -----------//