/* * 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 : OU_CARA.CPP //Description : Unit Caravan #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //------------- Define static vars ------------// static Button button_set_stop[MAX_STOP_FOR_CARAVAN]; static Button button_go_stop[MAX_STOP_FOR_CARAVAN]; static Button button_cancel_stop[MAX_STOP_FOR_CARAVAN]; static ButtonCustom button_select_array[MAX_STOP_FOR_CARAVAN][MAX_GOODS_SELECT_BUTTON]; static char button_select_enable_flag[MAX_STOP_FOR_CARAVAN][MAX_GOODS_SELECT_BUTTON]; static void i_disp_caravan_select_button(ButtonCustom *button, int repaintBody); static char goods_num[MAX_STOP_FOR_CARAVAN]; static char dummyCaravanEnableFlag[MAX_STOP_FOR_CARAVAN][MAX_GOODS_SELECT_BUTTON]; static char dummyCaravanGoodsNum[MAX_STOP_FOR_CARAVAN]; //------------- define static function ------------// static void update_caravan_stop_and_goods_to_dummy(UnitCaravan *caravanPtr) { CaravanStop *stopPtr = caravanPtr->stop_array; for(int i=0; ifirm_recno) continue; err_when(firm_array.is_deleted(stopPtr->firm_recno)); dummyCaravanGoodsNum[i] = stopPtr->update_pick_up(dummyCaravanEnableFlag[i]); } } //--------- Begin of function UnitCaravan::UnitCaravan ---------// // UnitCaravan::UnitCaravan() { memset( stop_array, 0, MAX_STOP_FOR_CARAVAN * sizeof(CaravanStop) ); journey_status = ON_WAY_TO_FIRM; dest_stop_id = 1; stop_defined_num = 0; wait_count = 0; stop_x_loc = 0; stop_y_loc = 0; memset(raw_qty_array, 0, sizeof(short)*MAX_RAW); memset(product_raw_qty_array, 0, sizeof(short)*MAX_PRODUCT); } //---------- End of function UnitCaravan::UnitCaravan ----------// //--------- Begin of function UnitCaravan::disp_info ---------// // void UnitCaravan::disp_info(int refreshFlag) { //----- for multiplayer game, skip displaying information for the first frame --------// if(remote.is_enable()) { if(unit_array.mp_first_frame_to_select_caravan && // first frame unit_array.mp_pre_selected_caravan_recno==sprite_recno) // is selected return; } disp_basic_info(INFO_Y1, refreshFlag); if( !config.show_ai_info && !is_own() ) return; disp_stop(INFO_Y1+54, refreshFlag); disp_goods(INFO_Y1+235, refreshFlag); } //---------- End of function UnitCaravan::disp_info ----------// //--------- Begin of function UnitCaravan::detect_info ---------// // void UnitCaravan::detect_info() { if(!is_visible()) return; if( detect_basic_info() ) return; if( !is_own() && !config.show_ai_info ) return; detect_stop(); } //---------- End of function UnitCaravan::detect_info ----------// //--------- Begin of function UnitCaravan::disp_stop ---------// // void UnitCaravan::disp_stop(int dispY1, int refreshFlag) { //###### begin trevor 15/9 #######// if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE) return; int i, x=INFO_X1, y=dispY1, needRefresh; Firm *firmPtr; static short last_firm_recno_array[MAX_STOP_FOR_CARAVAN]; for(i=0 ; ination_recno]->disp_nation_color(x+4, y+4); font_san.put(x+20, y+4, firmPtr->firm_name()); font_san.put(x+4, y+19, "Pick up: "); #if(defined(FRENCH)) button_set_stop[i].paint_text( x+4, y+37, x+86, y+56, "Set Stop" ); #else button_set_stop[i].paint_text( x+4, y+37, x+80, y+56, "Set Stop" ); #endif button_set_stop[i].set_help_code( "CSETSTOP" ); #if(defined(FRENCH)) button_go_stop[i].paint_text( x+90, y+37, x+180, y+56, "View Stop" ); #else button_go_stop[i].paint_text( x+84, y+37, x+180, y+56, "View Stop" ); #endif button_go_stop[i].set_help_code( "CGOSTOP" ); button_cancel_stop[i].paint_text( x+184, y+37, INFO_X2-4, y+56, "X" ); button_cancel_stop[i].set_help_code( "CDELSTOP" ); } disp_goods_select_button(i, y+1, refreshFlag); } } //###### end trevor 15/9 #######// } //---------- End of function UnitCaravan::disp_stop ----------// //--------- Begin of function UnitCaravan::detect_stop ---------// // void UnitCaravan::detect_stop() { int i, x=INFO_X1; for( i=0 ; i=stop_defined_num) continue; if(button_cancel_stop[i].detect()) { if(is_visible()) { del_stop(i+1, COMMAND_PLAYER); // ###### begin Gilbert 26/9 ######// se_ctrl.immediate_sound("TURN_OFF"); // ###### end Gilbert 26/9 ######// } } for(int b=0; bcenter_x, firmPtr->center_y ); } } } //---------- End of function UnitCaravan::detect_stop ----------// //--------- Begin of function UnitCaravan::disp_goods_select_button ---------// void UnitCaravan::disp_goods_select_button(int stopNum, int dispY1, int refreshFlag) { if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE) return; #define SHIFT_X_OFFSET 60 #define SELECT_BUTTON_WIDTH 16 #define SELECT_BUTTON_HEIGHT 16 CaravanStop *stopPtr = &stop_array[stopNum]; if( !goods_num[stopNum] ) return; int x=INFO_X1+SHIFT_X_OFFSET, y=dispY1+17, x1; char *pickUpArray = stopPtr->pick_up_array; char isPush; //-------------- draw the buttons for the cargo -------------// //###### begin trevor 13/9 #######// for(int i=1 ;i<=MAX_PICK_UP_GOODS; ++i, pickUpArray++) { x1 = x + i*SELECT_BUTTON_WIDTH; if(button_select_enable_flag[stopNum][i]) { isPush = stopPtr->pick_up_array[i-1]; err_when(isPush && (stopPtr->pick_up_type==AUTO_PICK_UP || stopPtr->pick_up_type==NO_PICK_UP)); button_select_array[stopNum][i].paint(x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, i), 0, isPush); // 0 for inelastic } else { vga.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 ); } } //---------------- draw the buttons for auto_pick_up and no_pick_up -------------// if(goods_num[stopNum]>1) { x1 = x; isPush = (stopPtr->pick_up_type==AUTO_PICK_UP); button_select_enable_flag[stopNum][AUTO_PICK_UP] = 1; button_select_array[stopNum][AUTO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, AUTO_PICK_UP), 0, isPush); // 0 for inelastic x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP; button_select_enable_flag[stopNum][NO_PICK_UP] = 1; button_select_array[stopNum][NO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, NO_PICK_UP)); } else { x1 = x; vga.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 ); x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP; vga.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 ); } //###### end trevor 13/9 #######// } //---------- End of function UnitCaravan::disp_goods_select_button ----------// //--------- Begin of function UnitCaravan::set_stop_pick_up ---------// // // Set the pickup type of a specific stop of this caravan. // // stopId - id. of the stop. (1 - MAX_STOP_FOR_CARAVAN) // newPickUpType - set the pickup type of the specific stop. (0 - MAX_GOODS_SELECT_BUTTON-1) // remoteActoin - remote action type // void UnitCaravan::set_stop_pick_up(int stopId, int newPickUpType, int remoteAction) { int remoteEnable = 0; if(remote.is_enable()) { if(!remoteAction) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_CARA_CHANGE_GOODS, 3*sizeof(short)); *shortPtr = sprite_recno; shortPtr[1] = stopId; shortPtr[2] = newPickUpType; return; } else //-------- validate remote message ----------// { //-*******************************************************-// /*char mess[255]; sprintf(mess, "Change Seed !!!! \r\n"); OutputDebugString(mess);*/ /*Firm *firmPtr = firm_array[stop_array[stopId-1].firm_recno]; switch(firmPtr->firm_id) { case FIRM_MINE: //firmPtr->sell_firm(COMMAND_AUTO); //firm_array[stop_array[0].firm_recno]->sell_firm(COMMAND_AUTO); break; case FIRM_FACTORY: break; case FIRM_MARKET: break; } update_stop_list(); if(unit_array.selected_recno == sprite_recno) { if(!remote.is_enable() || nation_renco==nation_array.player_recno || config.show_ai_info) disp_stop(INFO_Y1+54, INFO_UPDATE); }*/ //-*******************************************************-// err_when(!is_visible()); // no action if the unit is invisible if(firm_array.is_deleted(stop_array[stopId-1].firm_recno)) return; // firm is deleted if(stop_defined_numPICK_UP_PRODUCT_LAST); if(remoteEnable) stop_array[stopId-1].mp_pick_up_toggle(newPickUpType); else stop_array[stopId-1].pick_up_toggle(newPickUpType); break; } if(unit_array.selected_recno==sprite_recno) { if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info) disp_stop(INFO_Y1+54, INFO_UPDATE); } } //---------- End of function UnitCaravan::set_stop_pick_up ----------// //--------- Begin of function UnitCaravan::disp_goods ---------// // void UnitCaravan::disp_goods(int dispY1, int refreshFlag) { if( refreshFlag == INFO_REPAINT ) vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+42 ); int x=INFO_X1+20, y=dispY1+5; String str; int i; for(i=0; i stopId - the id. of the stop // stopXLoc, stopYLoc - the location of the stop // void UnitCaravan::set_stop(int stopId, int stopXLoc, int stopYLoc, char remoteAction) { //-------------------------------------------------------// // check if there is a station in the given location //-------------------------------------------------------// Location *locPtr = world.get_loc(stopXLoc, stopYLoc); if(!locPtr->is_firm()) return; Firm *firmPtr = firm_array[locPtr->firm_recno()]; if( !can_set_stop(firmPtr->firm_recno) ) return; //-------------------------------------------------------// // return if the market stop is in another territory //-------------------------------------------------------// if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id) return; //-------------------------------------------// if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_CARA_SET_STOP, 4*sizeof(short)); *shortPtr = sprite_recno; shortPtr[1] = stopId; shortPtr[2] = stopXLoc; shortPtr[3] = stopYLoc; return; } if(!stop_array[stopId-1].firm_recno) { stop_defined_num++; // no plus one if the recno is defined originally err_when( stop_defined_num > MAX_STOP_FOR_CARAVAN ); } //-------------------------------------------------------// // set the station recno of the stop //-------------------------------------------------------// CaravanStop *stopPtr = stop_array+stopId-1; if(stopPtr->firm_recno == firmPtr->firm_recno) { err_when(stopPtr->firm_loc_x1!=firmPtr->loc_x1 || stopPtr->firm_loc_y1!=firmPtr->loc_y1 || stopPtr->firm_id!=firmPtr->firm_id); return; // same stop as before } //-------------- reset ignore_power_nation -------------// ignore_power_nation = 0; memset(button_select_enable_flag[stopId-1], 0, sizeof(char)*MAX_GOODS_SELECT_BUTTON); goods_num[stopId-1] = 0; short oldStopFirmRecno = dest_stop_id ? stop_array[dest_stop_id-1].firm_recno : 0; short newStopFirmRecno; memset(stopPtr->pick_up_array, 0, sizeof(char)*MAX_PICK_UP_GOODS); stopPtr->firm_recno = firmPtr->firm_recno; stopPtr->firm_id = firmPtr->firm_id; stopPtr->firm_loc_x1 = firmPtr->loc_x1; stopPtr->firm_loc_y1 = firmPtr->loc_y1; //------------------------------------------------------------------------------------// // codes for setting pick_up_type //------------------------------------------------------------------------------------// MarketGoods *goodsPtr; int i, goodsId, goodsNum; switch(firmPtr->firm_id) { case FIRM_MINE: goodsId = ((FirmMine*)firmPtr)->raw_id; if(goodsId) stopPtr->pick_up_toggle(goodsId); // enable else stopPtr->pick_up_set_none(); break; case FIRM_FACTORY: goodsId = ((FirmFactory*)firmPtr)->product_raw_id+MAX_RAW; if(goodsId) stopPtr->pick_up_toggle(goodsId); // enable else stopPtr->pick_up_set_none(); break; case FIRM_MARKET: goodsPtr = ((FirmMarket*) firmPtr)->market_goods_array; goodsNum = 0; for(i=0; iraw_id) { if(goodsNum==0) goodsId = goodsPtr->raw_id; goodsNum++; } else if(goodsPtr->product_raw_id) { if(goodsNum==0) goodsId = goodsPtr->product_raw_id+MAX_RAW; goodsNum++; } } if(goodsNum==1) stopPtr->pick_up_toggle(goodsId); // cancel auto_pick_up else if(goodsNum==0) stopPtr->pick_up_set_none(); else stopPtr->pick_up_set_auto(); break; default: err_here(); break; } last_set_stop_date = info.game_date; //-------------------------------------------------------// // remove duplicate stop or stop change nation //-------------------------------------------------------// update_stop_list(); if(dest_stop_id) { if((newStopFirmRecno=stop_array[dest_stop_id-1].firm_recno) != oldStopFirmRecno) { firmPtr = firm_array[newStopFirmRecno]; err_when(firmPtr->firm_id!=FIRM_MARKET && firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_FACTORY); move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, stop_array[dest_stop_id-1].firm_id); journey_status = ON_WAY_TO_FIRM; } } else stop2(); if( unit_array.selected_recno == sprite_recno ) { if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info) info.disp(); } } //---------- End of function UnitCaravan::set_stop ----------// //--------- Begin of function UnitCaravan::del_stop ---------// void UnitCaravan::del_stop(int stopId, char remoteAction) { err_when(action_para || action_para2); if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_CARA_DEL_STOP, 2*sizeof(short)); *shortPtr = sprite_recno; shortPtr[1] = stopId; return; } //------ stop is deleted before receiving this message, thus, ignore invalid message -----// if(remote.is_enable() && stop_array[stopId-1].firm_recno==0) return; stop_array[stopId-1].firm_recno = 0; stop_defined_num--; err_when( stop_defined_num < 0 ); update_stop_list(); if( unit_array.selected_recno == sprite_recno ) { if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info) info.disp(); } } //---------- End of function UnitCaravan::del_stop ----------// //--------- Begin of function UnitCaravan::update_stop_list ---------// void UnitCaravan::update_stop_list() { err_when(stop_defined_num<0 || stop_defined_num>MAX_STOP_FOR_CARAVAN); //------------- used to debug for multiplayer game ------------------// #ifdef DEBUG m.random(100); #endif //-------------------------------------------------------// // backup original destination stop firm recno //-------------------------------------------------------// short nextStopRecno = stop_array[dest_stop_id-1].firm_recno; //----------------------------------------------------------------------// // check stop existence and the relationship between firm's nation //----------------------------------------------------------------------// CaravanStop *nodePtr = stop_array; Firm *firmPtr; int i; for(i=0; ifirm_recno) continue; if(firm_array.is_deleted(nodePtr->firm_recno)) { nodePtr->firm_recno = 0; // clear the recno stop_defined_num--; err_when( stop_defined_num < 0 ); continue; } firmPtr = firm_array[nodePtr->firm_recno]; if( !can_set_stop(nodePtr->firm_recno) || firmPtr->loc_x1!=nodePtr->firm_loc_x1 || firmPtr->loc_y1!=nodePtr->firm_loc_y1 ) { nodePtr->firm_recno = 0; stop_defined_num--; err_when( stop_defined_num < 0 ); continue; } } //-------------------------------------------------------// // remove duplicate node //-------------------------------------------------------// CaravanStop *insertNodePtr = stop_array; if(stop_defined_num<1) { memset(stop_array, 0, sizeof(CaravanStop)*MAX_STOP_FOR_CARAVAN); dest_stop_id = 0; return; // no stop } //-------------------------------------------------------// // pack the firm_recno to the beginning part of the array //-------------------------------------------------------// short compareRecno; for(i=0, nodePtr=stop_array; ifirm_recno) { compareRecno = nodePtr->firm_recno; break; } } if(i++) // else, the first record is already in the beginning of the array memcpy(insertNodePtr, nodePtr, sizeof(CaravanStop)); if(stop_defined_num==1) { memset(insertNodePtr+1, 0, sizeof(CaravanStop)*(MAX_STOP_FOR_CARAVAN-1)); dest_stop_id = 1; return; } short unprocessed = stop_defined_num-1; err_when(i==MAX_STOP_FOR_CARAVAN); // error if only one record err_when(!unprocessed); insertNodePtr++; nodePtr++; for(; ifirm_recno) continue; // empty err_when(!nodePtr->firm_recno); if(nodePtr->firm_recno==compareRecno) { nodePtr->firm_recno = 0; stop_defined_num--; err_when( stop_defined_num < 0 ); } else { compareRecno = nodePtr->firm_recno; if(insertNodePtr!=nodePtr) memcpy(insertNodePtr++, nodePtr, sizeof(CaravanStop)); else insertNodePtr++; } unprocessed--; } if(stop_defined_num>2) { //-------- compare the first and the end record -------// nodePtr = stop_array + stop_defined_num - 1; // point to the end if(nodePtr->firm_recno == stop_array[0].firm_recno) { nodePtr->firm_recno = 0; // remove the end record stop_defined_num--; err_when( stop_defined_num < 0 ); } } if(stop_defined_numfirm_recno)); firmPtr = firm_array[nodePtr->firm_recno]; if(firmPtr->nation_recno==nation_recno) { ourFirmExist++; break; } } if(!ourFirmExist) // none of the markets belong to our nation { memset(stop_array, 0, MAX_STOP_FOR_CARAVAN * sizeof(CaravanStop)); journey_status = ON_WAY_TO_FIRM; dest_stop_id = 0; stop_defined_num = 0; return; } //-----------------------------------------------------------------------------------------// // reset dest_stop_id since the order of the stop may be changed //-----------------------------------------------------------------------------------------// int xLoc = next_x_loc(); int yLoc = next_y_loc(); int dist, minDist=0x7FFF; for(i=0, dest_stop_id=0, nodePtr=stop_array; ifirm_recno==nextStopRecno) { dest_stop_id = i+1; break; } else { firmPtr = firm_array[nodePtr->firm_recno]; dist = m.points_distance(xLoc, yLoc, firmPtr->center_x, firmPtr->center_y); if(distMAX_STOP_FOR_CARAVAN); } //----------- End of function UnitCaravan::update_stop_list -----------// //--------- Begin of function UnitCaravan::update_stop_and_goods_info ---------// void UnitCaravan::update_stop_and_goods_info() { update_stop_list(); update_caravan_stop_and_goods_to_dummy(this); if(sprite_recno==unit_array.selected_recno && ((nation_array.player_recno && nation_recno==nation_array.player_recno) || config.show_ai_info)) { memcpy(goods_num, dummyCaravanGoodsNum, sizeof(char)*MAX_STOP_FOR_CARAVAN); memcpy(button_select_enable_flag, dummyCaravanEnableFlag, sizeof(char)*MAX_STOP_FOR_CARAVAN*MAX_GOODS_SELECT_BUTTON); } } //----------- End of function UnitCaravan::update_stop_and_goods_info -----------// //--------- Begin of function UnitCaravan::can_set_stop ---------// // // Whether can set a caravan's stop on the given firm. // int UnitCaravan::can_set_stop(int firmRecno) { Firm* firmPtr = firm_array[firmRecno]; if( firmPtr->under_construction ) return 0; switch(firmPtr->firm_id) { case FIRM_MARKET: return nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty; case FIRM_MINE: case FIRM_FACTORY: return nation_recno == firmPtr->nation_recno; default: return 0; } } //----------- End of function UnitCaravan::can_set_stop -----------// //--------- Begin of function UnitCaravan::get_next_stop_id ---------// // // Get the id. of the next defined stop. // // [int] curStopId - the id. of the current stop. // if it is MAX_STOP_FOR_CARAVAN, this function will return // the id. of the first valid stop. // // (default: MAX_STOP_FOR_CARAVAN) // return : 0 ~ MAX_STOP_FOR_CARAVAN, where 0 for no valid stop // int UnitCaravan::get_next_stop_id(int curStopId) { int nextStopId = (curStopId>=stop_defined_num) ? 1 : curStopId+1; CaravanStop *stopPtr = stop_array+nextStopId-1; int needUpdate = 0; if(firm_array.is_deleted(stopPtr->firm_recno)) { needUpdate++; } else { Firm *firmPtr = firm_array[stopPtr->firm_recno]; if( !can_set_stop( stopPtr->firm_recno ) || firmPtr->loc_x1 != stopPtr->firm_loc_x1 || firmPtr->loc_y1 != stopPtr->firm_loc_y1 ) { needUpdate++; } } //### begin alex 24/10 ###// if(needUpdate) { short preStopRecno = stop_array[curStopId-1].firm_recno; update_stop_list(); if(!stop_defined_num) return 0; // no stop is valid int i; for(i=1, stopPtr=stop_array; i<=stop_defined_num; i++, stopPtr++) { if(stopPtr->firm_recno==preStopRecno) return (i>=stop_defined_num) ? 1 : i+1; } return 1; } else return nextStopId; //#### end alex 24/10 ####// } //----------- End of function UnitCaravan::get_next_stop_id -----------// //--------- Begin of function UnitCaravan::pre_process ---------// // void UnitCaravan::pre_process() { Unit::pre_process(); if(cur_x == -1) // can't use !is_visible(), keep process if cur_x < -1 return; #define SURROUND_FIRM_WAIT_FACTOR 10 //-----------------------------------------------------------------------------// // if all the hit points are lost, die now //-----------------------------------------------------------------------------// if(hit_points <= 0) { if(action_mode != ACTION_DIE) set_die(); return; } err_when(action_mode==ACTION_DIE || cur_action==SPRITE_DIE || hit_points<=0); //-----------------------------------------------------------------------------// // stop action if no stop is defined //-----------------------------------------------------------------------------// if(!stop_defined_num) { err_when(dest_stop_id!=0); if(journey_status!=NO_STOP_DEFINED) stop(); // stop if no valid stop is defined journey_status = NO_STOP_DEFINED; return; } //-----------------------------------------------------------------------------// // wait in the surrounding of the stop if stop_defined_num==1 (only one stop) //-----------------------------------------------------------------------------// if(stop_defined_num==1) { CaravanStop *stopPtr = &stop_array[0]; err_when(!stopPtr->firm_recno); if(firm_array.is_deleted(stopPtr->firm_recno)) { update_stop_list(); return; } Firm *firmPtr = firm_array[stopPtr->firm_recno]; int firmXLoc1 = firmPtr->loc_x1; int firmYLoc1 = firmPtr->loc_y1; int firmXLoc2 = firmPtr->loc_x2; int firmYLoc2 = firmPtr->loc_y2; int firmId = firmPtr->firm_id; if(firmXLoc1!=stopPtr->firm_loc_x1 || firmYLoc1!=stopPtr->firm_loc_y1 || (firmId!=FIRM_MINE && firmId!=FIRM_FACTORY && firmId!=FIRM_MARKET)) { update_stop_list(); return; } int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); if(curXLocfirmXLoc2+1 || curYLocfirmYLoc2+1) { if(cur_action==SPRITE_IDLE) move_to_firm_surround(firmXLoc1, firmYLoc1, sprite_info->loc_width, sprite_info->loc_height, firmId); else journey_status = ON_WAY_TO_FIRM; } else { journey_status = SURROUND_FIRM; //if(firmPtr->nation_recno==nation_recno) if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty) { if(wait_count<=0) { //---------- unloading goods -------------// switch(stopPtr->firm_id) { case FIRM_MINE: break; // no goods unload to mine case FIRM_FACTORY: factory_unload_goods(); break; case FIRM_MARKET: market_unload_goods(); break; default: err_here(); break; } wait_count = MAX_CARAVAN_WAIT_TERM*SURROUND_FIRM_WAIT_FACTOR; } else wait_count--; } } return; } //-----------------------------------------------------------------------------// // at least 2 stops for the caravan to move between //-----------------------------------------------------------------------------// err_when(stop_defined_num<=1); if(journey_status==INSIDE_FIRM) caravan_in_firm(); else caravan_on_way(); } //----------- End of function UnitCaravan::pre_process -----------// //--------- Begin of function UnitCaravan::caravan_in_firm ---------// // journey_status : INSIDE_FIRM --> ON_WAY_TO_FIRM // NO_STOP_DEFINED if no valid stop // SURROUND_FIRM if only one stop // void UnitCaravan::caravan_in_firm() { //-----------------------------------------------------------------------------// // the market is deleted while the caravan is in market //-----------------------------------------------------------------------------// if(firm_array.is_deleted(action_para)) { hit_points = (float) 0; // caravan also die if the market is deleted unit_array.disappear_in_firm(sprite_recno); // caravan also die if the market is deleted return; } //-----------------------------------------------------------------------------// // waiting (time to upload/download cargo) //-----------------------------------------------------------------------------// if(wait_count>0) { wait_count--; return; } //-----------------------------------------------------------------------------// // leave the market and go to another market if possible //-----------------------------------------------------------------------------// CaravanStop *stopPtr = stop_array + dest_stop_id - 1; int xLoc = stop_x_loc; int yLoc = stop_y_loc; Location *locPtr = world.get_loc(xLoc, yLoc); Firm *firmPtr; if(locPtr->can_move(mobile_type)) init_sprite(xLoc, yLoc); // appear in the location the unit disappeared before else { //---- the entering location is blocked, select another location to leave ----// err_when(action_para==0); firmPtr = firm_array[action_para]; if(appear_in_firm_surround(xLoc, yLoc, firmPtr)) { init_sprite(xLoc, yLoc); stop(); err_when(action_para); } else { wait_count = MAX_CARAVAN_WAIT_TERM*10; //********* BUGHERE, continue to wait or .... return; } } //-------------- get next stop id. ----------------// int nextStopId = get_next_stop_id(dest_stop_id); if(!nextStopId || dest_stop_id==nextStopId) { dest_stop_id = nextStopId; journey_status = (!nextStopId) ? NO_STOP_DEFINED : SURROUND_FIRM; return; // no stop or only one stop is valid } dest_stop_id = nextStopId; firmPtr = firm_array[stop_array[dest_stop_id-1].firm_recno]; action_para = 0; // since action_para is used to store the current market recno, reset before searching move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); journey_status = ON_WAY_TO_FIRM; } //----------- End of function UnitCaravan::caravan_in_firm -----------// //--------- Begin of function UnitCaravan::caravan_on_way ---------// // journey_status : ON_WAY_TO_FIRM --> SURROUND_FIRM // SURROUND_FIRM --> INSIDE_FIRM // void UnitCaravan::caravan_on_way() { CaravanStop *stopPtr = stop_array + dest_stop_id - 1; if(cur_action==SPRITE_IDLE && journey_status!=SURROUND_FIRM) { if(!firm_array.is_deleted(stopPtr->firm_recno)) { Firm *firmPtr = firm_array[stopPtr->firm_recno]; move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); int nextXLoc = next_x_loc(); int nextYLoc = next_y_loc(); if(nextXLoc>=firmPtr->loc_x1-1 && nextXLoc<=firmPtr->loc_x2+1 && nextYLoc>=firmPtr->loc_y1-1 && nextYLoc<=firmPtr->loc_y2+1) // hard code 1 for carvan size 1x1 journey_status = SURROUND_FIRM; if(nextXLoc==move_to_x_loc && nextYLoc==move_to_y_loc && !ignore_power_nation) ignore_power_nation = 1; return; } } short unitRecno = sprite_recno; err_when(cur_action==SPRITE_ATTACK || action_mode==ACTION_ATTACK_UNIT || action_mode==ACTION_ATTACK_FIRM || action_mode==ACTION_ATTACK_TOWN || action_mode==ACTION_ATTACK_WALL); if(unit_array.is_deleted(unitRecno)) return; //-***************** BUGHERE ***************// if(firm_array.is_deleted(stopPtr->firm_recno)) { update_stop_list(); if(stop_defined_num) // move to next stop { Firm *firmPtr = firm_array[stop_array[stop_defined_num-1].firm_recno]; move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); } return; } //CaravanStop *stopPtr = stop_array + dest_stop_id - 1; Firm *firmPtr = firm_array[stopPtr->firm_recno]; int nextXLoc = next_x_loc(); int nextYLoc = next_y_loc(); if(journey_status==SURROUND_FIRM || ( nextXLoc==move_to_x_loc && nextYLoc==move_to_y_loc && cur_x==next_x && cur_y==next_y && // move in a tile exactly (nextXLoc>=firmPtr->loc_x1-1 && nextXLoc<=firmPtr->loc_x2+1 && nextYLoc>=firmPtr->loc_y1-1 && nextYLoc<=firmPtr->loc_y2+1) )) // in the surrounding of the firm { //-*************************************************************-// /*if(nation_recno==nation_array.player_recno) { OutputDebugString("surround firm\r\n"); for(int type = 0; typeupdate_pick_up(); //-------------------------------------------------------// // load/unload goods //-------------------------------------------------------// if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty) { switch(firmPtr->firm_id) { case FIRM_MINE: mine_load_goods(stopPtr->pick_up_type); break; case FIRM_FACTORY: factory_unload_goods(); factory_load_goods(stopPtr->pick_up_type); break; case FIRM_MARKET: market_unload_goods(); if(stopPtr->pick_up_type == AUTO_PICK_UP) market_auto_load_goods(); else if(stopPtr->pick_up_type!=NO_PICK_UP) market_load_goods(); break; default: err_here(); break; } } //-------------------------------------------------------// // action_para is used to store the firm_recno of the market // where the caravan move in. //-------------------------------------------------------// action_para = stopPtr->firm_recno; stop_x_loc = move_to_x_loc; // store entering location stop_y_loc = move_to_y_loc; wait_count = MAX_CARAVAN_WAIT_TERM; // set waiting term reset_path(); deinit_sprite(1); // the caravan enters the market now. 1-keep it selected if it is currently selected err_when(cur_x!=-1); cur_x--; // set cur_x to -2, such that invisible but still process pre_process() journey_status = INSIDE_FIRM; } else { if(cur_action!=SPRITE_MOVE) { //----------------------------------------------------// // blocked by something, go to the destination again // note: if return value is 0, cannot reach the firm. //*********BUGHERE //----------------------------------------------------// move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); journey_status = ON_WAY_TO_FIRM; } } } //----------- End of function UnitCaravan::caravan_on_way -----------// //--------- Begin of function UnitCaravan::appear_in_firm_surround ---------// // // This function return 1 if a suitable location is found, that means the // caravan will leave the firm there. Otherwise, return 0. // // xLoc, yLoc are reference variables for returning the location found. // int UnitCaravan::appear_in_firm_surround(int& xLoc, int& yLoc, Firm* firmPtr) { int upperLeftBoundX = firmPtr->loc_x1 - 1; // the surrounding coordinates of the firm int upperLeftBoundY = firmPtr->loc_y1 - 1; int lowerRightBoundX = firmPtr->loc_x2 + 1; int lowerRightBoundY = firmPtr->loc_y2 + 1; int count = 1, inside = 1, found = 0, i; int testXLoc = xLoc; int testYLoc = yLoc; int limit; Location *locPtr; //---------------------------------------------------------// // 9 10 11 12 the location is tested in the order // 8 1 2 13 shown, if the location is the surrounding // 7 x 3 14 of the firm and non-blocked, break // 6 5 4 ... the test //---------------------------------------------------------// while(inside) { inside = 0; limit = count<<1; err_when(limit!=count*2); //------------ upper --------------// testXLoc = xLoc - count + 1; testYLoc = yLoc - count; for(i=0; i=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC) continue; if(testXLoclowerRightBoundX || testYLoclowerRightBoundY) continue; locPtr = world.get_loc(testXLoc, testYLoc); if(locPtr->can_move(mobile_type)) { found++; break; } else xLoc++; inside++; } if(found) break; //------------ right --------------// testXLoc = xLoc + count; testYLoc = yLoc - count + 1; for(i=0; i=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC) continue; if(testXLoclowerRightBoundX || testYLoclowerRightBoundY) continue; locPtr = world.get_loc(testXLoc, testYLoc); if(locPtr->can_move(mobile_type)) { found++; break; } else yLoc++; inside++; } if(found) break; //------------- down --------------// testXLoc = xLoc + count - 1; testYLoc = yLoc + count; for(i=0; i=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC) continue; if(testXLoclowerRightBoundX || testYLoclowerRightBoundY) continue; locPtr = world.get_loc(testXLoc, testYLoc); if(locPtr->can_move(mobile_type)) { found++; break; } else xLoc--; inside++; } if(found) break; //------------- left --------------// testXLoc = xLoc - count; testYLoc = yLoc + count - 1; for(i=0; i=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC) continue; if(testXLoclowerRightBoundX || testYLoclowerRightBoundY) continue; locPtr = world.get_loc(testXLoc, testYLoc); if(locPtr->can_move(mobile_type)) { found++; break; } else yLoc--; inside++; } if(found) break; //---------------------------------------------// count++; } if(found) { xLoc = testXLoc; yLoc = testYLoc; return 1; } return 0; } //----------- End of function UnitCaravan::appear_in_firm_surround -----------// //---------- begin static function i_disp_caravan_select_button ---------------// static void i_disp_caravan_select_button(ButtonCustom *button, int repaintBody) { int x1 = button->x1; int y1 = button->y1; int x2 = button->x2; int y2 = button->y2; int shift; //------------- modify x1,y1, x2,y2 to the button body --------------// if(button->pushed_flag) { int colorDown = Vga::active_buf->color_down; // change the color of the body area to yellow to highlight the change Vga::active_buf->color_down = (char) V_YELLOW; Vga::active_buf->d3_panel_down(x1, y1, x2, y2); Vga::active_buf->color_down = (char) colorDown; x1++; y1++; shift = 2; } else { Vga::active_buf->d3_panel_up(x1, y1, x2, y2); x2--; y2--; shift = 3; } //-------------- put goods icon ---------------// int id = button->custom_para.value; char *iconName=NULL; int x = x1+shift; int y = y1+shift; if(id==AUTO_PICK_UP) { iconName = "AUTOPICK"; } else if(id==NO_PICK_UP) { iconName = "NOPICK"; } else if(id>=PICK_UP_RAW_FIRST && id<=PICK_UP_RAW_LAST) { raw_res.put_small_raw_icon( x, y, id-PICK_UP_RAW_FIRST+1 ); } else if(id>=PICK_UP_PRODUCT_FIRST && id<=PICK_UP_PRODUCT_LAST) { raw_res.put_small_product_icon( x, y, id-PICK_UP_PRODUCT_FIRST+1 ); } else err_here(); if( iconName ) { help.set_help( x, y, x+9, y+9, iconName ); Vga::active_buf->put_bitmap_trans( x, y, image_icon.get_ptr(iconName) ); } } //---------- end static function i_disp_caravan_select_button ---------------// //--------- Begin of function UnitCaravan::has_pick_up_type ---------// // // Return whether the specific stop has the specific pick up types. // int UnitCaravan::has_pick_up_type(int stopId, int pickUpType) { return stop_array[stopId-1].pick_up_array[pickUpType-1]; } //---------- End of function UnitCaravan::has_pick_up_type ----------// //--------- Begin of function UnitCaravan::carrying_qty ---------// // // Return whether the qty of the specific product/raw type that // this caravan is currently carrying. // int UnitCaravan::carrying_qty(int pickUpType) { if( pickUpType >= PICK_UP_RAW_FIRST && pickUpType <= PICK_UP_RAW_LAST ) { return raw_qty_array[pickUpType-PICK_UP_RAW_FIRST]; } else if( pickUpType >= PICK_UP_PRODUCT_FIRST && pickUpType <= PICK_UP_PRODUCT_LAST ) { return product_raw_qty_array[pickUpType-PICK_UP_PRODUCT_FIRST]; } else { err_here(); return 0; } } //---------- End of function UnitCaravan::carrying_qty ----------//