/* * 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 ---------//