/*
* 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 : OTALKRES.CPP
//Description : Object Talk
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// #### begin Gilbert 9/10 ######//
#include
// #### end Gilbert 9/10 ######//
//---------- the subtitle area ----------//
enum { TALK_X1 = ZOOM_X1+16,
TALK_Y1 = ZOOM_Y1+252,
TALK_X2 = ZOOM_X2-16,
TALK_Y2 = ZOOM_Y2-86,
};
enum { TALK_LINE_HEIGHT = 18 };
//------- define constant --------//
#define MESSAGE_SENT_STR "The message has been sent."
//------- define static vars -------//
static String nation_name_str_array[MAX_NATION];
//---------- Begin of function TalkRes::TalkRes -----------//
//
TalkRes::TalkRes() : talk_msg_array( sizeof(TalkMsg), 100 )
{
}
//---------- End of function TalkRes::TalkRes -----------//
//---------- Begin of function TalkRes::init -----------//
//
void TalkRes::init()
{
memset( this, 0, sizeof(TalkRes) - sizeof(talk_msg_array) );
talk_msg_array.zap();
}
//---------- End of function TalkRes::init -----------//
//---------- Begin of function TalkRes::deinit -----------//
//
void TalkRes::deinit()
{
}
//---------- End of function TalkRes::deinit -----------//
//------- Begin of function TalkRes::init_conversion --------//
//
// toNationRecno - recno of the nation which the player
// is going to talk to.
//
void TalkRes::init_conversion(int toNationRecno)
{
memset( &cur_talk_msg, 0, sizeof(TalkMsg) );
cur_talk_msg.from_nation_recno = (char) nation_array.player_recno;
cur_talk_msg.to_nation_recno = toNationRecno;
reply_talk_msg_recno = 0;
set_talk_choices();
}
//-------- End of function TalkRes::init_conversion ---------//
//---- Begin of function TalkRes::set_talk_choices ------//
//
// Set the choices of the next talk.
//
// return : 1 - choices are set
// 0 - if there is no additional talk segment for this talk
//
int TalkRes::set_talk_choices()
{
//------------------------------------//
Nation* playerNation = ~nation_array;
talk_choice_count = 0;
choice_question = NULL;
choice_question_second_line = NULL;
cur_choice_id = 0;
//------------------------------------//
int rc=0;
memset( available_talk_id_array, 0, sizeof(available_talk_id_array) );
switch( cur_talk_msg.talk_id )
{
//--- add the main option choices ---//
case 0:
add_main_choices();
return 1;
case TALK_PROPOSE_TRADE_TREATY:
case TALK_PROPOSE_FRIENDLY_TREATY:
case TALK_PROPOSE_ALLIANCE_TREATY:
case TALK_END_TRADE_TREATY:
case TALK_END_FRIENDLY_TREATY:
case TALK_END_ALLIANCE_TREATY:
case TALK_REQUEST_CEASE_WAR:
case TALK_DECLARE_WAR:
case TALK_REQUEST_MILITARY_AID:
return 0;
case TALK_REQUEST_TRADE_EMBARGO:
rc = add_trade_embargo_choices();
break;
case TALK_REQUEST_DECLARE_WAR:
rc = add_declare_war_choices();
break;
case TALK_REQUEST_BUY_FOOD:
rc = add_buy_food_choices();
break;
case TALK_GIVE_TRIBUTE:
case TALK_DEMAND_TRIBUTE:
rc = add_tribute_choices();
if( rc )
choice_question = "How much tribute?"; // add the choice question here because we use the same function for both tribute and aid
break;
case TALK_GIVE_AID:
case TALK_DEMAND_AID:
rc = add_tribute_choices();
if( rc )
choice_question = "How much aid?";
break;
case TALK_GIVE_TECH:
case TALK_DEMAND_TECH:
rc = add_give_tech_choices();
break;
case TALK_REQUEST_SURRENDER:
rc = add_request_surrender_choices();
break;
case TALK_SURRENDER:
rc = add_surrender_choices();
break;
default:
err_here();
}
if( rc )
add_talk_choice( "Cancel.", 0 );
return rc;
}
//----- End of function TalkRes::set_talk_choices -------//
//---- Begin of function TalkRes::add_main_choices ------//
//
void TalkRes::add_main_choices()
{
static char* talkMsgArray[] =
{
"Propose a trade treaty.",
"Propose a friendly treaty.",
"Propose an alliance treaty.",
"Terminate our trade treaty.",
"Terminate our friendly treaty.",
"Terminate our alliance treaty.",
"Request immediate military aid.",
"Request a trade embargo.",
"Request a cease-fire.",
"Request a declaration of war against a foe.",
"Request to purchase food.",
"Declare war.",
"Offer to pay tribute.",
"Demand tribute.",
"Offer aid.",
"Request aid.",
"Offer to transfer technology.",
"Request technology.",
"Offer to purchase throne and unite kingdoms.",
"Surrender.",
};
//-----------------------------------------//
int rc;
int relationStatus = (~nation_array)->get_relation_status(cur_talk_msg.to_nation_recno);
for( int i=1 ; i<=MAX_TALK_TYPE ; i++ )
{
if( !can_send_msg(cur_talk_msg.to_nation_recno, nation_array.player_recno, i) )
continue;
rc=0;
if( !rc )
add_talk_choice( talkMsgArray[i-1], i );
available_talk_id_array[i-1] = 1;
}
}
//----- End of function TalkRes::add_main_choices -------//
//---- Begin of function TalkRes::add_trade_embargo_choices ------//
//
int TalkRes::add_trade_embargo_choices()
{
if( cur_talk_msg.talk_para1 )
return 0;
choice_question = "Request an embargo on trade with which kingdom?";
Nation* fromNation = nation_array[cur_talk_msg.from_nation_recno];
Nation* toNation = nation_array[cur_talk_msg.to_nation_recno];
for( int i=1 ; i<=nation_array.size() ; i++ )
{
if( nation_array.is_deleted(i) )
continue;
if( i==cur_talk_msg.from_nation_recno ||
i==cur_talk_msg.to_nation_recno )
{
continue;
}
if( fromNation->get_relation(i)->trade_treaty==0 &&
toNation->get_relation(i)->trade_treaty==1 )
{
//------ add color bar -------//
char colorCodeStr[] = "0 ";
colorCodeStr[0] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[i]->color_scheme_id;
nation_name_str_array[i-1] = colorCodeStr;
//------ add natino name ------//
nation_name_str_array[i-1] += nation_array[i]->nation_name();
//---- add talk choice string ------//
add_talk_choice( nation_name_str_array[i-1], i );
}
}
return 1;
}
//----- End of function TalkRes::add_trade_embargo_choices -------//
//---- Begin of function TalkRes::add_declare_war_choices ------//
//
int TalkRes::add_declare_war_choices()
{
if( cur_talk_msg.talk_para1 )
return 0;
choice_question = "Declare war on which kingdom?";
Nation* fromNation = nation_array[cur_talk_msg.from_nation_recno];
Nation* toNation = nation_array[cur_talk_msg.to_nation_recno];
for( int i=1 ; i<=nation_array.size() ; i++ )
{
if( nation_array.is_deleted(i) )
continue;
//--- can only ask another nation to declare war with a nation that is currently at war with our nation ---//
if( fromNation->get_relation_status(i) == NATION_HOSTILE &&
toNation->get_relation_status(i) != NATION_HOSTILE )
{
//------ add color bar -------//
char colorCodeStr[] = "0 ";
colorCodeStr[0] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[i]->color_scheme_id;
nation_name_str_array[i-1] = colorCodeStr;
//------ add natino name ------//
nation_name_str_array[i-1] += nation_array[i]->nation_name();
//---- add talk choice string ------//
add_talk_choice( nation_name_str_array[i-1], i );
}
}
return 1;
}
//----- End of function TalkRes::add_declare_war_choices -------//
//---- Begin of function TalkRes::add_buy_food_choices ------//
//
int TalkRes::add_buy_food_choices()
{
#define MIN_FOOD_PURCHASE_PRICE 5
if( !cur_talk_msg.talk_para1 )
{
choice_question = "How much food do you want to purchase?";
static char* qtyStrArray[] = { "500.", "1000.", "2000.", "4000." };
static short qtyArray[] = { 500, 1000, 2000, 4000 };
for( int i=0 ; i<4 ; i++ )
{
if( (~nation_array)->cash >= qtyArray[i] * MIN_FOOD_PURCHASE_PRICE / 10 )
add_talk_choice( qtyStrArray[i], qtyArray[i] );
}
return 1;
}
else if( !cur_talk_msg.talk_para2 )
{
choice_question = "How much do you offer for 10 units of food?";
static char* priceStrArray[] = { "$5.", "$10.", "$15.", "$20." };
static short priceArray[] = { 5, 10, 15, 20 };
for( int i=0 ; i<4 ; i++ )
{
if( i==0 || (~nation_array)->cash >= cur_talk_msg.talk_para1 * priceArray[i] / 10 ) // i==0 to at least add one option
add_talk_choice( priceStrArray[i], priceArray[i] );
}
return 1;
}
else
return 0;
}
//----- End of function TalkRes::add_buy_food_choices -------//
//---- Begin of function TalkRes::add_tribute_choices ------//
//
int TalkRes::add_tribute_choices()
{
if( cur_talk_msg.talk_para1 )
return 0;
static char* tributeStrArray[] = { "$500.", "$1000.", "$2000.", "$3000.", "$4000." };
static short tributeAmtArray[] = { 500, 1000, 2000, 3000, 4000 };
for( int i=0 ; i<5 ; i++ )
{
if( cur_talk_msg.talk_id == TALK_DEMAND_TRIBUTE || // when demand tribute, the amount can be sent to any
cur_talk_msg.talk_id == TALK_DEMAND_AID ||
(~nation_array)->cash >= tributeAmtArray[i] )
{
add_talk_choice( tributeStrArray[i], tributeAmtArray[i] );
}
}
return 1;
}
//----- End of function TalkRes::add_tribute_choices -------//
//---- Begin of function TalkRes::add_give_tech_choices ------//
//
int TalkRes::add_give_tech_choices()
{
int i, techNationRecno;
if( cur_talk_msg.talk_id == TALK_GIVE_TECH )
techNationRecno = cur_talk_msg.from_nation_recno;
else // demand tech
techNationRecno = cur_talk_msg.to_nation_recno;
if( !cur_talk_msg.talk_para1 )
{
choice_question = "Which technology?";
for( i=1 ; i<=tech_res.tech_count ; i++ )
{
if( tech_res[i]->get_nation_tech_level(techNationRecno) > 0 )
{
add_talk_choice( tech_res[i]->tech_des(), i );
}
}
return 1;
}
else if( !cur_talk_msg.talk_para2 && cur_talk_msg.talk_id == TALK_GIVE_TECH )
{
TechInfo* techInfo = tech_res[cur_talk_msg.talk_para1];
if( techInfo->max_tech_level==1 ) // this tech only has one level
return 0;
choice_question = "Which version?";
int nationLevel = techInfo->get_nation_tech_level(techNationRecno);
err_when( nationLevel<1 || nationLevel>3 );
static char* verStrArray[] = { "Mark I", "Mark II", "Mark III" };
for( i=1 ; i<=min(3, nationLevel) ; i++ )
add_talk_choice( verStrArray[i-1], i );
return 1;
}
else
return 0;
}
//----- End of function TalkRes::add_give_tech_choices -------//
//---- Begin of function TalkRes::add_request_surrender_choices ------//
//
int TalkRes::add_request_surrender_choices()
{
if( cur_talk_msg.talk_para1 )
return 0;
choice_question = "How much do you offer?";
static char* strArray[] = { "$5000.", "$7500.", "$10000.",
"$15000.", "$20000.", "$30000.", "$40000.", "$50000." };
static int amtArray[] = { 5000, 7500, 10000, 15000, 20000, 30000, 40000, 50000 };
for( int i=0 ; i<8 ; i++ )
{
if( (~nation_array)->cash >= amtArray[i] )
{
add_talk_choice( strArray[i], amtArray[i]/10 ); // divided by 10 to cope with the limit of
}
}
return 1;
}
//----- End of function TalkRes::add_request_surrender_choices -------//
//---- Begin of function TalkRes::add_surrender_choices ------//
//
int TalkRes::add_surrender_choices()
{
if( cur_talk_msg.talk_para1 )
return 0;
static String str;
#if(defined(GERMAN))
str = "Wollen Sie wirklich vor ";
str += nation_array[cur_talk_msg.to_nation_recno]->nation_name();
str += " kapitulieren?";
#else
// SPANISH, FRENCH and US
str = translate.process("Do you really want to Surrender to ");
str += nation_array[cur_talk_msg.to_nation_recno]->nation_name();
str += "?";
#endif
choice_question = str;
add_talk_choice( "Confirm.", 1 );
return 1;
}
//----- End of function TalkRes::add_surrender_choices -------//
//------- Begin of function TalkRes::can_send_any_msg --------//
//
int TalkRes::can_send_any_msg(int toNationRecno, int fromNationRecno)
{
return wait_msg_count(toNationRecno, fromNationRecno) < MAX_WAIT_MSG_PER_NATION;
}
//-------- End of function TalkRes::can_send_any_msg ---------//
//------- Begin of function TalkRes::can_send_msg --------//
//
// return whether one specific nation can send a specific message
// to another specific nation.
//
int TalkRes::can_send_msg(int toNationRecno, int fromNationRecno, int talkId)
{
Nation* fromNation = nation_array[fromNationRecno];
Nation* toNation = nation_array[toNationRecno];
NationRelation *nationRelation = fromNation->get_relation(toNationRecno);
int relationStatus = nationRelation->status;
switch( talkId )
{
case TALK_PROPOSE_TRADE_TREATY:
return relationStatus !=NATION_ALLIANCE && // allied nations are oblied to trade with each other
relationStatus !=NATION_HOSTILE &&
!toNation->get_relation(fromNationRecno)->trade_treaty;
case TALK_PROPOSE_FRIENDLY_TREATY:
return relationStatus==NATION_TENSE ||
relationStatus==NATION_NEUTRAL;
case TALK_PROPOSE_ALLIANCE_TREATY:
return relationStatus==NATION_FRIENDLY ||
relationStatus==NATION_NEUTRAL;
case TALK_END_TRADE_TREATY:
return relationStatus !=NATION_ALLIANCE && // allied nations are oblied to trade with each other
toNation->get_relation(fromNationRecno)->trade_treaty;
case TALK_END_FRIENDLY_TREATY:
return relationStatus==NATION_FRIENDLY;
case TALK_END_ALLIANCE_TREATY:
return relationStatus==NATION_ALLIANCE;
case TALK_REQUEST_MILITARY_AID:
return fromNation->is_at_war() &&
(relationStatus==NATION_FRIENDLY ||
relationStatus==NATION_ALLIANCE);
case TALK_REQUEST_TRADE_EMBARGO:
return relationStatus==NATION_FRIENDLY ||
relationStatus==NATION_ALLIANCE;
case TALK_REQUEST_CEASE_WAR:
return relationStatus==NATION_HOSTILE;
case TALK_REQUEST_DECLARE_WAR: // can only request an allied nation to declare war with another nation
{
if( relationStatus != NATION_ALLIANCE )
return 0;
//--- see if this nation has an enemy right now ---//
for( int i=nation_array.size() ; i>0 ; i-- )
{
if( nation_array.is_deleted(i) )
continue;
if( fromNation->get_relation(i)->status == NATION_HOSTILE )
return 1;
}
return 0;
}
case TALK_REQUEST_BUY_FOOD:
return relationStatus != NATION_HOSTILE;
case TALK_DECLARE_WAR:
return relationStatus != NATION_ALLIANCE &&
relationStatus != NATION_FRIENDLY &&
relationStatus != NATION_HOSTILE;
case TALK_GIVE_TRIBUTE:
case TALK_DEMAND_TRIBUTE:
return relationStatus <= NATION_NEUTRAL;
case TALK_GIVE_AID:
case TALK_DEMAND_AID:
return relationStatus >= NATION_FRIENDLY;
case TALK_GIVE_TECH:
return fromNation->total_tech_level() > 0;
case TALK_DEMAND_TECH:
return toNation->total_tech_level() > 0;
case TALK_REQUEST_SURRENDER:
return 1;
case TALK_SURRENDER:
return 1;
}
return 0;
}
//-------- End of function TalkRes::can_send_msg ---------//
//------- Begin of function TalkRes::add_talk_choice --------//
//
void TalkRes::add_talk_choice(char* talkStr, int talkPara)
{
err_when( talk_choice_count >= MAX_TALK_CHOICE );
talk_choice_count++;
talk_choice_array[talk_choice_count-1].str = talkStr;
talk_choice_array[talk_choice_count-1].para = talkPara;
}
//-------- End of function TalkRes::add_talk_choice ---------//
//------- Begin of function TalkRes::ai_send_talk_msg --------//
//
// toNationRecno - the nation which this message is being sent to
// fromNationRecno - the nation which this message is from
// talkId - id. of the talk
// [int] talkPara1 - talk para 1
// [int] talkPara2 - talk para 2
// [int] forceSend - if 1, then should_diplomacy_retry() won't
// be checked. (default: 0)
//
int TalkRes::ai_send_talk_msg(int toNationRecno, int fromNationRecno, int talkId, int talkPara1, int talkPara2, int forceSend)
{
Nation* fromNation = nation_array[fromNationRecno];
if( !fromNation->is_ai() )
return 0;
//--- first check again if the nation should send the message now ---//
if( !forceSend )
{
if( !fromNation->should_diplomacy_retry(talkId, toNationRecno) )
return 0;
}
//-------- avoid send opposite message too soon ----//
int oppTalkId=0;
switch( talkId )
{
case TALK_PROPOSE_ALLIANCE_TREATY:
oppTalkId = TALK_END_FRIENDLY_TREATY;
break;
case TALK_GIVE_TRIBUTE:
oppTalkId = TALK_DEMAND_TRIBUTE;
break;
case TALK_DEMAND_TRIBUTE:
oppTalkId = TALK_GIVE_TRIBUTE;
break;
case TALK_GIVE_AID:
oppTalkId = TALK_DEMAND_AID;
break;
case TALK_DEMAND_AID:
oppTalkId = TALK_GIVE_AID;
break;
case TALK_GIVE_TECH:
oppTalkId = TALK_DEMAND_TECH;
break;
case TALK_DEMAND_TECH:
oppTalkId = TALK_GIVE_TECH;
break;
}
if( oppTalkId )
{
fromNation->get_relation(toNationRecno)->
last_talk_reject_date_array[oppTalkId-1] = info.game_date;
}
//------------------------------------------//
TalkMsg talkMsg;
memset(&talkMsg, 0, sizeof(TalkMsg));
talkMsg.to_nation_recno = toNationRecno;
talkMsg.from_nation_recno = fromNationRecno;
talkMsg.talk_id = talkId;
talkMsg.talk_para1 = talkPara1;
talkMsg.talk_para2 = talkPara2;
err_when( !nation_array[fromNationRecno]->is_ai() );
send_talk_msg( &talkMsg, COMMAND_AI );
return 1;
}
//-------- End of function TalkRes::ai_send_talk_msg ---------//
//------- Begin of function TalkRes::send_talk_msg --------//
//
// Now records in talk_msg_array cannot be deleted as
// news_array.diplomacy() use recno to refer to talk_msg_array.
//
void TalkRes::send_talk_msg(TalkMsg* talkMsgPtr, char remoteAction)
{
//-------- send multiplayer -----------//
if( !remoteAction && remote.is_enable() )
{
// packet strcture :
char* dataPtr = remote.new_send_queue_msg(MSG_SEND_TALK_MSG, sizeof(TalkMsg) );
memcpy( dataPtr, talkMsgPtr, sizeof(TalkMsg) );
return;
}
//------ the TalkMsg::reply_type ------//
if( talkMsgPtr->is_reply_needed() )
talkMsgPtr->reply_type = REPLY_WAITING;
else
talkMsgPtr->reply_type = REPLY_NOT_NEEDED;
//-- If this is an AI message check if this message has already been sent --//
if( nation_array[talkMsgPtr->from_nation_recno]->nation_type == NATION_AI )
{
if( talkMsgPtr->reply_type == REPLY_WAITING ) // for messages that do not need a reply, duplication in the message log is allowed.
{
if( is_talk_msg_exist(talkMsgPtr, 0) ) // 0-don't check talk_para1 & talk_para2
return;
}
}
//--- in a multiplayer game, when the msg comes back from the network, can_send_msg might be different, so we have to check it again ---//
if( !can_send_msg( talkMsgPtr->to_nation_recno, talkMsgPtr->from_nation_recno, talkMsgPtr->talk_id ) )
return;
//-------- send the message now ---------//
send_talk_msg_now(talkMsgPtr);
//---- if it's a notification message ----//
if( talkMsgPtr->reply_type == REPLY_NOT_NEEDED )
talkMsgPtr->process_accepted_reply();
}
//-------- End of function TalkRes::send_talk_msg ---------//
//------- Begin of function TalkRes::send_talk_msg_now --------//
//
void TalkRes::send_talk_msg_now(TalkMsg* talkMsgPtr)
{
//--------- add the message ------------//
Nation* toNation = nation_array[talkMsgPtr->to_nation_recno];
talkMsgPtr->date = info.game_date;
talkMsgPtr->relation_status = toNation->get_relation_status(talkMsgPtr->from_nation_recno);
talk_msg_array.linkin( talkMsgPtr );
err_when( nation_array.is_deleted(talkMsgPtr->from_nation_recno) );
err_when( nation_array.is_deleted(talkMsgPtr->to_nation_recno) );
//--------------------------------------//
switch(toNation->nation_type)
{
case NATION_OWN: // can be from both AI or a remote player
news_array.diplomacy( talk_msg_array.recno() );
// ###### begin Gilbert 9/10 ########//
// sound effect
se_ctrl.immediate_sound(talkMsgPtr->talk_id==TALK_DECLARE_WAR ? (char*)"DECL_WAR":(char*)"GONG");
// ###### end Gilbert 9/10 ########//
break;
case NATION_AI:
if( talkMsgPtr->reply_type == REPLY_WAITING )
{
//-- put the message in the receiver's actin queue --//
toNation->add_action( 0, 0, 0, 0, ACTION_AI_PROCESS_TALK_MSG, talk_msg_array.recno() );
}
else if( talkMsgPtr->reply_type == REPLY_NOT_NEEDED )
{
//--- notify the receiver immediately ---//
toNation->notify_talk_msg( talkMsgPtr );
}
else
err_here();
break;
case NATION_REMOTE: // do nothing here as NATION_OWN handle both msg from AI and a remote player
break;
}
}
//-------- End of function TalkRes::send_talk_msg_now ---------//
//------- Begin of function TalkRes::reply_talk_msg --------//
//
// If the nation which receives this message decides to accept
// the offer of this message, this function is called.
//
// talkMsgRecno - the recno of the TalkMsg
// replyType - reply type, either REPLY_ACCEPT or REPLY_REJECT
// remoteAction - remote action type
//
void TalkRes::reply_talk_msg(int talkMsgRecno, char replyType, char remoteAction)
{
//-------- send multiplayer -----------//
if( !remoteAction && remote.is_enable() )
{
// packet structure :
char* charPtr = remote.new_send_queue_msg( MSG_REPLY_TALK_MSG, sizeof(int)+2*sizeof(char) );
*(int *)charPtr = talkMsgRecno;
charPtr[sizeof(int)] = replyType;
charPtr[sizeof(int)+sizeof(char)] = 0;
return;
}
//-------------------------------------//
err_when( is_talk_msg_deleted(talkMsgRecno) );
TalkMsg* talkMsgPtr = get_talk_msg(talkMsgRecno);
Nation* fromNation = nation_array[talkMsgPtr->from_nation_recno];
err_when( talkMsgPtr->reply_type == REPLY_NOT_NEEDED );
err_when( replyType != REPLY_ACCEPT && replyType != REPLY_REJECT );
talkMsgPtr->reply_type = replyType;
talkMsgPtr->reply_date = info.game_date;
switch( fromNation->nation_type )
{
case NATION_OWN:
news_array.diplomacy( talkMsgRecno );
// ###### begin Gilbert 9/10 ########//
// sound effect
se_ctrl.immediate_sound("GONG");
// ###### end Gilbert 9/10 ########//
break;
case NATION_AI:
fromNation->ai_notify_reply( talkMsgRecno ); // notify the AI nation about this reply.
break;
case NATION_REMOTE:
break;
}
//------- if the offer is accepted -------//
if( talkMsgPtr->reply_type == REPLY_ACCEPT )
talkMsgPtr->process_accepted_reply();
//--- if the player has replyed the message, remove it from the news display ---//
if( talkMsgPtr->to_nation_recno == nation_array.player_recno )
news_array.remove(NEWS_DIPLOMACY, talkMsgRecno);
}
//-------- End of function TalkRes::reply_talk_msg ---------//
//------- Begin of function TalkRes::disp_talk --------//
void TalkRes::disp_talk()
{
//----- if the player can send no more message to the nation ---//
if( !info.player_reply_mode &&
!can_send_any_msg(cur_talk_msg.to_nation_recno, nation_array.player_recno) )
{
if( !( choice_question && strcmp(choice_question, MESSAGE_SENT_STR)==0 ) ) // if it's currently displaying the has sent notification, display that message
{
char* msgStr = "You've sent too many messages to this kingdom. "
"You cannot send any new messages until the existing ones are processed.";
font_san.put_paragraph( TALK_X1, TALK_Y1, TALK_X2, TALK_Y2, msgStr, 4 );
return;
}
}
//--- return whether the talk choices should be refreshed. ---//
if( !reply_talk_msg_recno && !cur_talk_msg.talk_id ) // not replying and haven't selected a message type yet.
{
for( int i=0 ; i talk_msg_array.size() );
TalkMsg* talkMsg = (TalkMsg*) talk_msg_array.get(recNo);
if( !talkMsg->talk_id )
err.run( "get_talk_msg() error, the TalkMsg is deleted." );
return talkMsg;
}
//-------- End of function TalkRes::get_talk_msg ---------//
//------- Begin of function TalkRes::is_talk_msg_deleted --------//
int TalkRes::is_talk_msg_deleted(int recNo)
{
if( recNo < 1 || recNo > talk_msg_array.size() )
return 1;
TalkMsg* talkMsg = (TalkMsg*) talk_msg_array.get(recNo);
return talkMsg->talk_id==0;
}
//-------- End of function TalkRes::is_talk_msg_deleted ---------//
//------- Begin of function TalkRes::next_day --------//
void TalkRes::next_day()
{
if( info.game_date%7 == 0 )
process_talk_msg();
}
//-------- End of function TalkRes::next_day ---------//
//------ Begin of function TalkRes::process_talk_msg ------//
//
void TalkRes::process_talk_msg()
{
int i;
TalkMsg* talkMsg;
for( i=talk_msg_count() ; i>0 ; i-- )
{
if( is_talk_msg_deleted(i) )
continue;
talkMsg = get_talk_msg(i);
//--------------------------------------------------------//
// If this is an AI message and there is no response from
// the player after one month the message has been sent,
// it presumes that the message has been rejected.
//--------------------------------------------------------//
if( nation_array[talkMsg->from_nation_recno]->nation_type == NATION_AI &&
talkMsg->reply_type == REPLY_WAITING &&
info.game_date > talkMsg->date + DISP_NEWS_DAYS )
{
talkMsg->reply_type = REPLY_REJECT;
nation_array[talkMsg->from_nation_recno]->ai_notify_reply(i);
}
//--- delete the talk message after 2 months ---//
if( info.game_date > talkMsg->date + TALK_MSG_KEEP_DAYS )
del_talk_msg(i);
}
}
//-------- End of function TalkRes::process_talk_msg ---------//
//------ Begin of function TalkRes::del_talk_msg ------//
//
void TalkRes::del_talk_msg(int talkMsgRecno)
{
err_when( is_talk_msg_deleted(talkMsgRecno) );
TalkMsg* talkMsg = get_talk_msg(talkMsgRecno);
//--- if this message is sent to an AI nation ---//
Nation* nationPtr = nation_array[talkMsg->to_nation_recno];
if( nationPtr->nation_type == NATION_AI &&
(talkMsg->reply_type == REPLY_NOT_NEEDED || // even if a reply is not needed, the message will still be sent to the AI for notification.
talkMsg->reply_type == REPLY_WAITING) )
{
//--- it may still have the message in its action queue ---//
ActionNode* actionNode;
for( int i=nationPtr->action_count() ; i>0 ; i-- )
{
actionNode = nationPtr->get_action(i);
if( actionNode->action_mode == ACTION_AI_PROCESS_TALK_MSG &&
actionNode->action_para == talkMsgRecno )
{
nationPtr->del_action(i);
break;
}
}
}
//----- delete the message from the news array -----//
if( talkMsg->to_nation_recno == nation_array.player_recno ||
talkMsg->from_nation_recno == nation_array.player_recno )
{
news_array.remove( NEWS_DIPLOMACY, talkMsgRecno );
}
//----- link it out from talk_msg_array -----//
talk_msg_array.linkout(talkMsgRecno);
}
//-------- End of function TalkRes::del_talk_msg ---------//
//------- Begin of function TalkRes::is_talk_msg_exist --------//
//
// checkPara - whether check talk_para1 and talk_para2
// in comparing TalkMsg.
//
// return : >0 - the recno of the talk msg that already exists
// ==0 - not found
//
int TalkRes::is_talk_msg_exist(TalkMsg* thisTalkMsg, int checkPara)
{
int i;
TalkMsg* talkMsg;
for( i=talk_msg_count() ; i>0 ; i-- )
{
if( is_talk_msg_deleted(i) )
continue;
talkMsg = get_talk_msg(i);
if( talkMsg->reply_type == REPLY_WAITING ||
talkMsg->reply_type == REPLY_NOT_NEEDED )
{
if( talkMsg->talk_id == thisTalkMsg->talk_id &&
talkMsg->from_nation_recno == thisTalkMsg->from_nation_recno &&
talkMsg->to_nation_recno == thisTalkMsg->to_nation_recno )
{
if( checkPara )
{
if( talkMsg->talk_para1 == thisTalkMsg->talk_para1 &&
talkMsg->talk_para2 == thisTalkMsg->talk_para2 )
{
return i;
}
}
else
return i;
}
}
}
return 0;
}
//-------- End of function TalkRes::is_talk_msg_exist ---------//
//------- Begin of function TalkRes::wait_msg_count --------//
//
// Return the number of messages sent to the nation waiting
// for its reply.
//
int TalkRes::wait_msg_count(int toNationRecno, int fromNationRecno)
{
int i, waitMsgCount=0;
TalkMsg* talkMsg;
for( i=talk_msg_count() ; i>0 ; i-- )
{
if( is_talk_msg_deleted(i) )
continue;
talkMsg = get_talk_msg(i);
if( talkMsg->reply_type == REPLY_WAITING &&
talkMsg->to_nation_recno == toNationRecno &&
talkMsg->from_nation_recno == fromNationRecno &&
info.game_date < talkMsg->date + 30 ) // only count message in a month
{
waitMsgCount++;
}
}
return waitMsgCount;
}
//-------- End of function TalkRes::wait_msg_count ---------//
//------- Begin of function TalkRes::player_reply --------//
void TalkRes::player_reply(int talkMsgRecno)
{
//------- set the reply choices --------//
err_when( is_talk_msg_deleted(talkMsgRecno) );
TalkMsg* talkMsg = get_talk_msg(talkMsgRecno);
if( nation_array.is_deleted(talkMsg->from_nation_recno) )
return;
init_conversion(talkMsg->from_nation_recno);
talk_choice_count = 0;
cur_choice_id = 0;
reply_talk_msg_recno = talkMsgRecno;
//--------- add talk choices ---------//
static String msgStr, msgStr2;
msgStr = talkMsg->msg_str(nation_array.player_recno); // make a static copy of it.
choice_question = msgStr;
//---- see if this message has a second line -----//
msgStr2 = talkMsg->msg_str(nation_array.player_recno, 0, 1); // 1-display the second line of the question
if( msgStr!=msgStr2 )
choice_question_second_line = msgStr2;
else
choice_question_second_line = NULL;
//--------- add choices to the question ---------//
if( talkMsg->can_accept() ) // whether the replier can accept the request or demand of the message
add_talk_choice( "Accept.", 1 );
add_talk_choice( "Reject.", 0 );
//--- switch to the nation report mode and go to the diplomacy mode ---//
info.init_player_reply( talkMsg->from_nation_recno );
save_view_mode = sys.view_mode;
sys.set_view_mode(MODE_NATION);
}
//-------- End of function TalkRes::player_reply ---------//
//------- Begin of function TalkRes::del_all_nation_msg --------//
//
// Delete all messages related to this nation.
//
void TalkRes::del_all_nation_msg(int nationRecno)
{
int i;
TalkMsg* talkMsg;
for( i=talk_msg_count() ; i>0 ; i-- )
{
if( is_talk_msg_deleted(i) )
continue;
talkMsg = get_talk_msg(i);
if( talkMsg->from_nation_recno == nationRecno ||
talkMsg->to_nation_recno == nationRecno ||
!talkMsg->is_valid_to_disp() ) // if the nation is the talk_para1 (e.g. TRADE_EMBARGO), is_valid_to_disp() will return 0 and the talk message should than be deleted
{
del_talk_msg(i);
}
}
}
//-------- End of function TalkRes::del_all_nation_msg ---------//