1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
5 * Copyright 2020 Jesse Allen
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 //Filename : OU_CARA.CPP
23 //Description : Unit Caravan
24
25 #include <OVGA.h>
26 #include <vga_util.h>
27 #include <OSTR.h>
28 #include <OHELP.h>
29 #include <OFONT.h>
30 #include <OINFO.h>
31 #include <OCONFIG.h>
32 #include <OIMGRES.h>
33 #include <OMOUSE.h>
34 #include <OPOWER.h>
35 #include <OBUTTON.h>
36 #include <OBUTT3D.h>
37 #include <ONATION.h>
38 #include <OU_CARA.h>
39 #include <OREMOTE.h>
40 #include <OF_MINE.h>
41 #include <OF_FACT.h>
42 #include <OBUTTCUS.h>
43 #include <OSE.h>
44 #include "gettext.h"
45
46 //------------- Define static vars ------------//
47
48 static Button button_set_stop[MAX_STOP_FOR_CARAVAN];
49 static Button button_go_stop[MAX_STOP_FOR_CARAVAN];
50 static Button button_cancel_stop[MAX_STOP_FOR_CARAVAN];
51 static ButtonCustom button_select_array[MAX_STOP_FOR_CARAVAN][MAX_GOODS_SELECT_BUTTON];
52
53 static void i_disp_caravan_select_button(ButtonCustom *button, int repaintBody);
54
55 //--------- Begin of function UnitCaravan::UnitCaravan ---------//
56 //
UnitCaravan()57 UnitCaravan::UnitCaravan()
58 {
59 memset( stop_array, 0, MAX_STOP_FOR_CARAVAN * sizeof(CaravanStop) );
60
61 journey_status = ON_WAY_TO_FIRM;
62 dest_stop_id = 1;
63 stop_defined_num = 0;
64 wait_count = 0;
65 stop_x_loc = 0;
66 stop_y_loc = 0;
67
68 memset(raw_qty_array, 0, sizeof(short)*MAX_RAW);
69 memset(product_raw_qty_array, 0, sizeof(short)*MAX_PRODUCT);
70 }
71 //---------- End of function UnitCaravan::UnitCaravan ----------//
72
73
74 //--------- Begin of function UnitCaravan::disp_info ---------//
75 //
disp_info(int refreshFlag)76 void UnitCaravan::disp_info(int refreshFlag)
77 {
78 disp_basic_info(INFO_Y1, refreshFlag);
79
80 if( !config.show_ai_info && !is_own() )
81 return;
82
83 disp_stop(INFO_Y1+54, refreshFlag);
84
85 disp_goods(INFO_Y1+234, refreshFlag);
86 }
87 //---------- End of function UnitCaravan::disp_info ----------//
88
89
90 //--------- Begin of function UnitCaravan::detect_info ---------//
91 //
detect_info()92 void UnitCaravan::detect_info()
93 {
94 if(!is_visible())
95 return;
96
97 if( detect_basic_info() )
98 return;
99
100 if( detect_select_hotkey() )
101 return;
102
103 if( !is_own() && !config.show_ai_info )
104 return;
105
106 detect_stop();
107 }
108 //---------- End of function UnitCaravan::detect_info ----------//
109
110
111 //--------- Begin of function UnitCaravan::is_in_build_menu ---------//
112 // Returns true if a unit is currently in build mode.
113 // Only reliable if this unit is the selected unit.
114 // Used by Info to detect if the build mode is opened.
115 //
is_in_build_menu()116 bool UnitCaravan::is_in_build_menu()
117 {
118 return false;
119 }
120 //----------- End of function UnitCaravan::is_in_build_menu -----------//
121
122
123 //--------- Begin of function UnitCaravan::disp_stop ---------//
124 //
disp_stop(int dispY1,int refreshFlag)125 void UnitCaravan::disp_stop(int dispY1, int refreshFlag)
126 {
127 //###### begin trevor 15/9 #######//
128
129 if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE)
130 return;
131
132 int i, x=INFO_X1, y=dispY1, needRefresh;
133 Firm *firmPtr;
134 static short last_firm_recno_array[MAX_STOP_FOR_CARAVAN];
135
136 for(i=0 ; i<MAX_STOP_FOR_CARAVAN ; i++, y+=60)
137 {
138 //---- compare with the previous display and see if an update is needed ----//
139
140 if( refreshFlag==INFO_REPAINT )
141 {
142 needRefresh = 1;
143 }
144 else if( last_firm_recno_array[i] != stop_array[i].firm_recno )
145 {
146 needRefresh = 1;
147 }
148
149 last_firm_recno_array[i] = stop_array[i].firm_recno;
150
151 //----------------------------------------//
152
153 if( !stop_array[i].firm_recno ||
154 firm_array.is_deleted(stop_array[i].firm_recno) )
155 {
156 if( refreshFlag == INFO_REPAINT )
157 {
158 vga_util.d3_panel_up(x, y, INFO_X2, y+58);
159 #if(defined(FRENCH))
160 button_set_stop[i].paint_text( x+4, y+37, x+86, y+56, "Set Stop" );
161 #else
162 button_set_stop[i].paint_text( x+4, y+37, x+80, y+56, _("Set Stop") );
163 #endif
164 button_set_stop[i].set_help_code( "CSETSTOP" );
165 }
166 }
167 else
168 {
169 if( refreshFlag == INFO_REPAINT )
170 {
171 vga_util.d3_panel_up(x, y, INFO_X2, y+58);
172
173 //-------- display name of the stop --------//
174
175 firmPtr = firm_array[ stop_array[i].firm_recno ];
176 nation_array[firmPtr->nation_recno]->disp_nation_color(x+4, y+4);
177 font_san.put(x+20, y+4, firmPtr->firm_name());
178 font_san.put(x+4, y+19, _("Pick up:"));
179
180 #if(defined(FRENCH))
181 button_set_stop[i].paint_text( x+4, y+37, x+86, y+56, "Set Stop" );
182 #else
183 button_set_stop[i].paint_text( x+4, y+37, x+80, y+56, _("Set Stop") );
184 #endif
185
186 button_set_stop[i].set_help_code( "CSETSTOP" );
187
188 #if(defined(FRENCH))
189 button_go_stop[i].paint_text( x+90, y+37, x+180, y+56, "View Stop" );
190 #else
191 button_go_stop[i].paint_text( x+84, y+37, x+180, y+56, _("View Stop") );
192 #endif
193 button_go_stop[i].set_help_code( "CGOSTOP" );
194
195 button_cancel_stop[i].paint_text( x+184, y+37, INFO_X2-4, y+56, "X" );
196 button_cancel_stop[i].set_help_code( "CDELSTOP" );
197 }
198
199 disp_goods_select_button(i, y+1, refreshFlag);
200 }
201 }
202 //###### end trevor 15/9 #######//
203
204 }
205 //---------- End of function UnitCaravan::disp_stop ----------//
206
207
208 //--------- Begin of function UnitCaravan::detect_stop ---------//
209 //
detect_stop()210 void UnitCaravan::detect_stop()
211 {
212 int i, x=INFO_X1;
213
214 for( i=0 ; i<MAX_STOP_FOR_CARAVAN ; i++ )
215 {
216 // ###### begin Gilbert 14/8 #########//
217 if( button_set_stop[i].detect() && is_own() )
218 power.issue_command( COMMAND_SET_CARAVAN_STOP, sprite_recno, i+1 ); // i+1 - stop id., passed as a parameter of the command
219 // ###### end Gilbert 14/8 #########//
220
221 if(i>=stop_defined_num)
222 continue;
223
224 if(button_cancel_stop[i].detect())
225 {
226 if(is_visible())
227 {
228 del_stop(i+1, COMMAND_PLAYER);
229 // ###### begin Gilbert 26/9 ######//
230 se_ctrl.immediate_sound("TURN_OFF");
231 // ###### end Gilbert 26/9 ######//
232 }
233 }
234
235 for(int b=0; b<MAX_GOODS_SELECT_BUTTON; ++b)
236 {
237 if(button_select_array[i][b].detect())
238 {
239 // ###### begin Gilbert 26/9 ######//
240 se_ctrl.immediate_sound(
241 button_select_array[i][b].elastic_flag || button_select_array[i][b].pushed_flag ?
242 (char*)"TURN_ON" : (char*)"TURN_OFF");
243 // ###### end Gilbert 26/9 ######//
244
245 set_stop_pick_up(i+1, b, COMMAND_PLAYER); // b = 1 - MAX_PICK_UP_GOODS
246 }
247 }
248
249 if( button_go_stop[i].detect() )
250 {
251 Firm* firmPtr = firm_array[ stop_array[i].firm_recno ];
252 world.go_loc( firmPtr->center_x, firmPtr->center_y );
253 }
254 }
255 }
256 //---------- End of function UnitCaravan::detect_stop ----------//
257
258
259 //--------- Begin of function UnitCaravan::disp_goods_select_button ---------//
260
disp_goods_select_button(int stopNum,int dispY1,int refreshFlag)261 void UnitCaravan::disp_goods_select_button(int stopNum, int dispY1, int refreshFlag)
262 {
263 if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE)
264 return;
265
266 #define SHIFT_X_OFFSET 73
267 #define SELECT_BUTTON_WIDTH 16
268 #define SELECT_BUTTON_HEIGHT 16
269
270 CaravanStop *stopPtr = &stop_array[stopNum];
271 Firm *firmPtr = firm_array[stopPtr->firm_recno];
272
273 int x=INFO_X1+SHIFT_X_OFFSET, y=dispY1+17, x1, pick_up_goods = 0;
274 char *pickUpArray = stopPtr->pick_up_array;
275 char isPush;
276
277 //-------------- draw the buttons for the cargo -------------//
278
279 //###### begin trevor 13/9 #######//
280
281 for(int i=1 ;i<=MAX_PICK_UP_GOODS; ++i, pickUpArray++)
282 {
283 int rawId = i;
284 if( rawId < 1 || rawId > MAX_RAW )
285 rawId = 0;
286 int productId = i-MAX_RAW;
287 if( productId < 1 || productId > MAX_PRODUCT )
288 productId = 0;
289
290 int stock = -1;
291
292 if( FirmMarket *firmMarket = firmPtr->cast_to_FirmMarket() )
293 {
294 MarketGoods *marketGoods;
295 if( rawId )
296 {
297 marketGoods = firmMarket->market_raw_array[rawId-1];
298 err_when( marketGoods && marketGoods->raw_id != rawId );
299 }
300 else if( productId )
301 {
302 marketGoods = firmMarket->market_product_array[productId-1];
303 err_when( marketGoods && marketGoods->product_raw_id != productId );
304 }
305 else
306 {
307 err_here();
308 marketGoods = NULL;
309 }
310
311 if( marketGoods )
312 {
313 stock = (int) marketGoods->stock_qty;
314 }
315 }
316 else if( FirmMine *firmMine = firmPtr->cast_to_FirmMine() )
317 {
318 if( rawId && firmMine->raw_id == rawId )
319 {
320 stock = (int) firmMine->stock_qty;
321 }
322 }
323 else if( FirmFactory *firmFactory = firmPtr->cast_to_FirmFactory() )
324 {
325 if( productId && firmFactory->product_raw_id == productId )
326 {
327 stock = (int) firmFactory->stock_qty;
328 }
329 //else if( rawId && firmFactory->product_raw_id == rawId )
330 //{
331 // stock = (int) firmFactory->raw_stock_qty;
332 //}
333 }
334
335 x1 = x + i*SELECT_BUTTON_WIDTH;
336
337 if( stock >= 0 )
338 {
339 isPush = stopPtr->pick_up_array[i-1];
340 err_when(isPush && (stopPtr->pick_up_type==AUTO_PICK_UP || stopPtr->pick_up_type==NO_PICK_UP));
341
342 button_select_array[stopNum][i].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
343 y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, i),
344 0, isPush); // 0 for inelastic
345 pick_up_goods++;
346 }
347 else
348 {
349 vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
350 }
351 }
352
353 //---------------- draw the buttons for auto_pick_up and no_pick_up -------------//
354
355 if( pick_up_goods>1 )
356 {
357 x1 = x;
358 isPush = (stopPtr->pick_up_type==AUTO_PICK_UP);
359 button_select_array[stopNum][AUTO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
360 y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, AUTO_PICK_UP),
361 0, isPush); // 0 for inelastic
362
363 x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP;
364 button_select_array[stopNum][NO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
365 y+SELECT_BUTTON_HEIGHT, i_disp_caravan_select_button, ButtonCustomPara(this, NO_PICK_UP));
366 }
367 else
368 {
369 x1 = x;
370 vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
371
372 x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP;
373 vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
374 }
375
376 //###### end trevor 13/9 #######//
377 }
378 //---------- End of function UnitCaravan::disp_goods_select_button ----------//
379
380
381 //--------- Begin of function UnitCaravan::set_stop_pick_up ---------//
382 //
383 // Set the pickup type of a specific stop of this caravan.
384 //
385 // <int> stopId - id. of the stop. (1 - MAX_STOP_FOR_CARAVAN)
386 // <int> newPickUpType - set the pickup type of the specific stop. (0 - MAX_GOODS_SELECT_BUTTON-1)
387 // <int> remoteActoin - remote action type
388 //
set_stop_pick_up(int stopId,int newPickUpType,int remoteAction)389 void UnitCaravan::set_stop_pick_up(int stopId, int newPickUpType, int remoteAction)
390 {
391 if(remote.is_enable())
392 {
393 if(!remoteAction)
394 {
395 // packet structure : <unit recno> <stop id> <new pick_up_type>
396 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_CARA_CHANGE_GOODS, 3*sizeof(short));
397 *shortPtr = sprite_recno;
398
399 shortPtr[1] = stopId;
400 shortPtr[2] = newPickUpType;
401 return;
402 }
403 else //-------- validate remote message ----------//
404 {
405 //-*******************************************************-//
406 /*char mess[255];
407 sprintf(mess, "Change Seed !!!! \r\n");
408 OutputDebugString(mess);*/
409
410 /*Firm *firmPtr = firm_array[stop_array[stopId-1].firm_recno];
411
412 switch(firmPtr->firm_id)
413 {
414 case FIRM_MINE:
415 //firmPtr->sell_firm(COMMAND_AUTO);
416 //firm_array[stop_array[0].firm_recno]->sell_firm(COMMAND_AUTO);
417 break;
418 case FIRM_FACTORY:
419 break;
420 case FIRM_MARKET:
421 break;
422 }
423
424 update_stop_list();
425 if(unit_array.selected_recno == sprite_recno)
426 {
427 if(!remote.is_enable() || nation_renco==nation_array.player_recno || config.show_ai_info)
428 disp_stop(INFO_Y1+54, INFO_UPDATE);
429 }*/
430 //-*******************************************************-//
431
432 err_when(!is_visible()); // no action if the unit is invisible
433 if(firm_array.is_deleted(stop_array[stopId-1].firm_recno))
434 return; // firm is deleted
435
436 if(stop_defined_num<stopId)
437 return; // stop_list is updated, stop exists no more
438
439 #ifdef DEBUG
440 //-*******************************************************-//
441 /*//char mess[255];
442 sprintf(mess, "Change Seed : %d %d %d\r\n", stopId, newPickUpType, sprite_recno);
443 OutputDebugString(mess);*/
444 //-*******************************************************-//
445
446 misc.set_random_seed(stopId + newPickUpType*(misc.random(4)+1)*10 + sprite_recno*100*misc.random(100) +
447 misc.get_random_seed());
448
449 //-*******************************************************-//
450 /*//char mess[255];
451 sprintf(mess, "Change Seed : %d\r\n", misc.random_seed);
452 OutputDebugString(mess);*/
453 //-*******************************************************-//
454 #endif
455 }
456 }
457
458 switch(newPickUpType)
459 {
460 case AUTO_PICK_UP:
461 stop_array[stopId-1].pick_up_set_auto();
462 break;
463
464 case NO_PICK_UP:
465 stop_array[stopId-1].pick_up_set_none();
466 break;
467
468 default:
469 err_when(newPickUpType<PICK_UP_RAW_FIRST || newPickUpType>PICK_UP_PRODUCT_LAST);
470 stop_array[stopId-1].pick_up_toggle(newPickUpType);
471 break;
472 }
473
474 if(unit_array.selected_recno==sprite_recno)
475 {
476 if(nation_recno==nation_array.player_recno || config.show_ai_info)
477 disp_stop(INFO_Y1+54, INFO_UPDATE);
478 }
479 }
480 //---------- End of function UnitCaravan::set_stop_pick_up ----------//
481
482
483 //--------- Begin of function UnitCaravan::disp_goods ---------//
484 //
disp_goods(int dispY1,int refreshFlag)485 void UnitCaravan::disp_goods(int dispY1, int refreshFlag)
486 {
487 if( refreshFlag == INFO_REPAINT )
488 vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+42 );
489
490 int x=INFO_X1+20, y=dispY1+5;
491 String str;
492
493 int i;
494 for(i=0; i<MAX_RAW; i++, x+=60)
495 {
496 vga_front.d3_panel_up( x, y, x+RAW_SMALL_ICON_WIDTH+5, y+RAW_SMALL_ICON_HEIGHT+5 );
497
498 raw_res.put_small_raw_icon( x+3, y+3, i+1 );
499
500 font_san.disp( x+25, y+2, raw_qty_array[i], 1, x+59 );
501 }
502
503 x =INFO_X1+20;
504 y+=19;
505
506 for( i=0; i<MAX_PRODUCT; i++, x+=60)
507 {
508 vga_front.d3_panel_up( x, y, x+RAW_SMALL_ICON_WIDTH+5, y+RAW_SMALL_ICON_HEIGHT+5 );
509
510 raw_res.put_small_product_icon( x+3, y+3, i+1 );
511
512 font_san.disp( x+25, y+2, product_raw_qty_array[i], 1, x+59 );
513 }
514 }
515 //---------- End of function UnitCaravan::disp_goods ----------//
516
517
518 //--------- Begin of function UnitCaravan::set_stop ---------//
519 //
520 // <int> stopId - the id. of the stop
521 // <int> stopXLoc, stopYLoc - the location of the stop
522 //
set_stop(int stopId,int stopXLoc,int stopYLoc,char remoteAction)523 void UnitCaravan::set_stop(int stopId, int stopXLoc, int stopYLoc, char remoteAction)
524 {
525 //-------------------------------------------------------//
526 // check if there is a station in the given location
527 //-------------------------------------------------------//
528 Location *locPtr = world.get_loc(stopXLoc, stopYLoc);
529 if(!locPtr->is_firm())
530 return;
531
532 Firm *firmPtr = firm_array[locPtr->firm_recno()];
533
534 if( !can_set_stop(firmPtr->firm_recno) )
535 return;
536
537 //-------------------------------------------------------//
538 // return if the market stop is in another territory
539 //-------------------------------------------------------//
540 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
541 return;
542
543 //-------------------------------------------//
544
545 if(!remoteAction && remote.is_enable())
546 {
547 // packet structure : <unit recno> <stop id> <stop x> <stop y>
548 short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_CARA_SET_STOP, 4*sizeof(short));
549 *shortPtr = sprite_recno;
550 shortPtr[1] = stopId;
551 shortPtr[2] = stopXLoc;
552 shortPtr[3] = stopYLoc;
553 return;
554 }
555
556 if(!stop_array[stopId-1].firm_recno)
557 {
558 stop_defined_num++; // no plus one if the recno is defined originally
559
560 err_when( stop_defined_num > MAX_STOP_FOR_CARAVAN );
561 }
562
563 //-------------------------------------------------------//
564 // set the station recno of the stop
565 //-------------------------------------------------------//
566 CaravanStop *stopPtr = stop_array+stopId-1;
567 if(stopPtr->firm_recno == firmPtr->firm_recno)
568 {
569 err_when(stopPtr->firm_loc_x1!=firmPtr->loc_x1 || stopPtr->firm_loc_y1!=firmPtr->loc_y1 ||
570 stopPtr->firm_id!=firmPtr->firm_id);
571 return; // same stop as before
572 }
573
574 //-------------- reset ignore_power_nation -------------//
575 ignore_power_nation = 0;
576
577 short oldStopFirmRecno = dest_stop_id ? stop_array[dest_stop_id-1].firm_recno : 0;
578 short newStopFirmRecno;
579 memset(stopPtr->pick_up_array, 0, sizeof(char)*MAX_PICK_UP_GOODS);
580 stopPtr->firm_recno = firmPtr->firm_recno;
581 stopPtr->firm_id = firmPtr->firm_id;
582 stopPtr->firm_loc_x1 = firmPtr->loc_x1;
583 stopPtr->firm_loc_y1 = firmPtr->loc_y1;
584
585 //------------------------------------------------------------------------------------//
586 // codes for setting pick_up_type
587 //------------------------------------------------------------------------------------//
588 MarketGoods *goodsPtr;
589 int i, goodsId, goodsNum;
590 switch(firmPtr->firm_id)
591 {
592 case FIRM_MINE:
593 goodsId = ((FirmMine*)firmPtr)->raw_id;
594 if(goodsId)
595 stopPtr->pick_up_toggle(goodsId); // enable
596 else
597 stopPtr->pick_up_set_none();
598 break;
599
600 case FIRM_FACTORY:
601 goodsId = ((FirmFactory*)firmPtr)->product_raw_id+MAX_RAW;
602 if(goodsId)
603 stopPtr->pick_up_toggle(goodsId); // enable
604 else
605 stopPtr->pick_up_set_none();
606 break;
607
608 case FIRM_MARKET:
609 goodsPtr = ((FirmMarket*) firmPtr)->market_goods_array;
610 goodsNum = 0;
611 for(i=0; i<MAX_MARKET_GOODS; ++i, goodsPtr++)
612 {
613 if(goodsPtr->raw_id)
614 {
615 if(goodsNum==0)
616 goodsId = goodsPtr->raw_id;
617
618 goodsNum++;
619 }
620 else if(goodsPtr->product_raw_id)
621 {
622 if(goodsNum==0)
623 goodsId = goodsPtr->product_raw_id+MAX_RAW;
624
625 goodsNum++;
626 }
627 }
628
629 if(goodsNum==1)
630 stopPtr->pick_up_toggle(goodsId); // cancel auto_pick_up
631 else if(goodsNum==0)
632 stopPtr->pick_up_set_none();
633 else
634 stopPtr->pick_up_set_auto();
635 break;
636
637 default: err_here();
638 break;
639 }
640
641 last_set_stop_date = info.game_date;
642
643 //-------------------------------------------------------//
644 // remove duplicate stop or stop change nation
645 //-------------------------------------------------------//
646 update_stop_list();
647
648 if(dest_stop_id)
649 {
650 if((newStopFirmRecno=stop_array[dest_stop_id-1].firm_recno) != oldStopFirmRecno)
651 {
652 firmPtr = firm_array[newStopFirmRecno];
653 err_when(firmPtr->firm_id!=FIRM_MARKET && firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_FACTORY);
654 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);
655 journey_status = ON_WAY_TO_FIRM;
656 }
657 }
658 else
659 stop2();
660
661 if( unit_array.selected_recno == sprite_recno )
662 {
663 if(nation_recno==nation_array.player_recno || config.show_ai_info)
664 info.disp();
665 }
666 }
667 //---------- End of function UnitCaravan::set_stop ----------//
668
669
670 //--------- Begin of function UnitCaravan::del_stop ---------//
del_stop(int stopId,char remoteAction)671 void UnitCaravan::del_stop(int stopId, char remoteAction)
672 {
673 err_when(action_para || action_para2);
674
675 if(!remoteAction && remote.is_enable())
676 {
677 // packet structure : <unit recno> <stop id>
678 short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_CARA_DEL_STOP, 2*sizeof(short));
679 *shortPtr = sprite_recno;
680 shortPtr[1] = stopId;
681 return;
682 }
683
684 //------ stop is deleted before receiving this message, thus, ignore invalid message -----//
685 if(remote.is_enable() && stop_array[stopId-1].firm_recno==0)
686 return;
687
688 stop_array[stopId-1].firm_recno = 0;
689 stop_defined_num--;
690 err_when( stop_defined_num < 0 );
691
692 update_stop_list();
693
694 if( unit_array.selected_recno == sprite_recno )
695 {
696 if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info)
697 info.disp();
698 }
699 }
700 //---------- End of function UnitCaravan::del_stop ----------//
701
702
703 //--------- Begin of function UnitCaravan::update_stop_list ---------//
update_stop_list()704 void UnitCaravan::update_stop_list()
705 {
706 err_when(stop_defined_num<0 || stop_defined_num>MAX_STOP_FOR_CARAVAN);
707
708 //------------- used to debug for multiplayer game ------------------//
709 #ifdef DEBUG
710 misc.random(100);
711 #endif
712
713 //-------------------------------------------------------//
714 // backup original destination stop firm recno
715 //-------------------------------------------------------//
716 short nextStopRecno = stop_array[dest_stop_id-1].firm_recno;
717
718 //----------------------------------------------------------------------//
719 // check stop existence and the relationship between firm's nation
720 //----------------------------------------------------------------------//
721 CaravanStop *nodePtr = stop_array;
722 Firm *firmPtr;
723 int i;
724 for(i=0; i<MAX_STOP_FOR_CARAVAN; i++, nodePtr++)
725 {
726 if(!nodePtr->firm_recno)
727 continue;
728
729 if(firm_array.is_deleted(nodePtr->firm_recno))
730 {
731 nodePtr->firm_recno = 0; // clear the recno
732 stop_defined_num--;
733 err_when( stop_defined_num < 0 );
734
735 continue;
736 }
737
738 firmPtr = firm_array[nodePtr->firm_recno];
739
740 if( !can_set_stop(nodePtr->firm_recno) ||
741 firmPtr->loc_x1!=nodePtr->firm_loc_x1 ||
742 firmPtr->loc_y1!=nodePtr->firm_loc_y1 )
743 {
744 nodePtr->firm_recno = 0;
745 stop_defined_num--;
746 err_when( stop_defined_num < 0 );
747
748 continue;
749 }
750 }
751
752 //-------------------------------------------------------//
753 // remove duplicate node
754 //-------------------------------------------------------//
755 CaravanStop *insertNodePtr = stop_array;
756
757 if(stop_defined_num<1)
758 {
759 memset(stop_array, 0, sizeof(CaravanStop)*MAX_STOP_FOR_CARAVAN);
760 dest_stop_id = 0;
761 return; // no stop
762 }
763
764 //-------------------------------------------------------//
765 // pack the firm_recno to the beginning part of the array
766 //-------------------------------------------------------//
767 short compareRecno;
768 for(i=0, nodePtr=stop_array; i<MAX_STOP_FOR_CARAVAN; i++, nodePtr++)
769 {
770 if(nodePtr->firm_recno)
771 {
772 compareRecno = nodePtr->firm_recno;
773 break;
774 }
775 }
776
777 if(i++) // else, the first record is already in the beginning of the array
778 memcpy(insertNodePtr, nodePtr, sizeof(CaravanStop));
779
780 if(stop_defined_num==1)
781 {
782 memset(insertNodePtr+1, 0, sizeof(CaravanStop)*(MAX_STOP_FOR_CARAVAN-1));
783 dest_stop_id = 1;
784 return;
785 }
786
787 short unprocessed = stop_defined_num-1;
788 err_when(i==MAX_STOP_FOR_CARAVAN); // error if only one record
789 err_when(!unprocessed);
790 insertNodePtr++;
791 nodePtr++;
792
793 for(; i<MAX_STOP_FOR_CARAVAN && unprocessed; i++, nodePtr++)
794 {
795 if(!nodePtr->firm_recno)
796 continue; // empty
797
798 err_when(!nodePtr->firm_recno);
799 if(nodePtr->firm_recno==compareRecno)
800 {
801 nodePtr->firm_recno = 0;
802 stop_defined_num--;
803 err_when( stop_defined_num < 0 );
804 }
805 else
806 {
807 compareRecno = nodePtr->firm_recno;
808
809 if(insertNodePtr!=nodePtr)
810 memcpy(insertNodePtr++, nodePtr, sizeof(CaravanStop));
811 else
812 insertNodePtr++;
813 }
814 unprocessed--;
815 }
816
817 if(stop_defined_num>2)
818 {
819 //-------- compare the first and the end record -------//
820 nodePtr = stop_array + stop_defined_num - 1; // point to the end
821 if(nodePtr->firm_recno == stop_array[0].firm_recno)
822 {
823 nodePtr->firm_recno = 0; // remove the end record
824 stop_defined_num--;
825 err_when( stop_defined_num < 0 );
826 }
827 }
828
829 if(stop_defined_num<MAX_STOP_FOR_CARAVAN)
830 memset(stop_array+stop_defined_num, 0, sizeof(CaravanStop)*(MAX_STOP_FOR_CARAVAN-stop_defined_num));
831
832 #ifdef DEBUG
833 int debugCount;
834 for(debugCount=0; debugCount<stop_defined_num; debugCount++)
835 err_when(!stop_array[debugCount].firm_recno);
836
837 for(; debugCount<MAX_STOP_FOR_CARAVAN; debugCount++)
838 err_when(stop_array[debugCount].firm_recno);
839
840 for(debugCount=0; debugCount<stop_defined_num; debugCount++)
841 err_when(stop_array[debugCount].firm_recno &&
842 stop_array[debugCount].firm_recno==stop_array[(debugCount+1)%MAX_STOP_FOR_CARAVAN].firm_recno);
843 #endif
844
845 //-----------------------------------------------------------------------------------------//
846 // There should be at least one stop in the list. Otherwise, clear all the stops
847 //-----------------------------------------------------------------------------------------//
848 int ourFirmExist = 0;
849 for(i=0, nodePtr=stop_array; i<stop_defined_num; i++, nodePtr++)
850 {
851 err_when(firm_array.is_deleted(nodePtr->firm_recno));
852 firmPtr = firm_array[nodePtr->firm_recno];
853 if(firmPtr->nation_recno==nation_recno)
854 {
855 ourFirmExist++;
856 break;
857 }
858 }
859
860 if(!ourFirmExist) // none of the markets belong to our nation
861 {
862 memset(stop_array, 0, MAX_STOP_FOR_CARAVAN * sizeof(CaravanStop));
863 journey_status = ON_WAY_TO_FIRM;
864 dest_stop_id = 0;
865 stop_defined_num = 0;
866 return;
867 }
868
869 //-----------------------------------------------------------------------------------------//
870 // reset dest_stop_id since the order of the stop may be changed
871 //-----------------------------------------------------------------------------------------//
872 int xLoc = next_x_loc();
873 int yLoc = next_y_loc();
874 int dist, minDist=0x7FFF;
875
876 for(i=0, dest_stop_id=0, nodePtr=stop_array; i<stop_defined_num; i++, nodePtr++)
877 {
878 if(nodePtr->firm_recno==nextStopRecno)
879 {
880 dest_stop_id = i+1;
881 break;
882 }
883 else
884 {
885 firmPtr = firm_array[nodePtr->firm_recno];
886 dist = misc.points_distance(xLoc, yLoc, firmPtr->center_x, firmPtr->center_y);
887
888 if(dist<minDist)
889 {
890 dist = minDist;
891 dest_stop_id = i+1;
892 }
893 }
894 }
895
896 err_when(dest_stop_id<0 || dest_stop_id>MAX_STOP_FOR_CARAVAN);
897 }
898 //----------- End of function UnitCaravan::update_stop_list -----------//
899
900
901 //--------- Begin of function UnitCaravan::can_set_stop ---------//
902 //
903 // Whether can set a caravan's stop on the given firm.
904 //
can_set_stop(int firmRecno)905 int UnitCaravan::can_set_stop(int firmRecno)
906 {
907 Firm* firmPtr = firm_array[firmRecno];
908
909 if( firmPtr->under_construction )
910 return 0;
911
912 switch(firmPtr->firm_id)
913 {
914 case FIRM_MARKET:
915 return nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty;
916
917 case FIRM_MINE:
918 case FIRM_FACTORY:
919 return nation_recno == firmPtr->nation_recno;
920
921 default:
922 return 0;
923 }
924 }
925 //----------- End of function UnitCaravan::can_set_stop -----------//
926
927
928 //--------- Begin of function UnitCaravan::get_next_stop_id ---------//
929 //
930 // Get the id. of the next defined stop.
931 //
932 // [int] curStopId - the id. of the current stop.
933 // if it is MAX_STOP_FOR_CARAVAN, this function will return
934 // the id. of the first valid stop.
935 //
936 // (default: MAX_STOP_FOR_CARAVAN)
937 // return : 0 ~ MAX_STOP_FOR_CARAVAN, where 0 for no valid stop
938 //
get_next_stop_id(int curStopId)939 int UnitCaravan::get_next_stop_id(int curStopId)
940 {
941 int nextStopId = (curStopId>=stop_defined_num) ? 1 : curStopId+1;
942
943 CaravanStop *stopPtr = stop_array+nextStopId-1;
944
945 int needUpdate = 0;
946
947 if(firm_array.is_deleted(stopPtr->firm_recno))
948 {
949 needUpdate++;
950 }
951 else
952 {
953 Firm *firmPtr = firm_array[stopPtr->firm_recno];
954
955 if( !can_set_stop( stopPtr->firm_recno ) ||
956 firmPtr->loc_x1 != stopPtr->firm_loc_x1 ||
957 firmPtr->loc_y1 != stopPtr->firm_loc_y1 )
958 {
959 needUpdate++;
960 }
961 }
962
963 //### begin alex 24/10 ###//
964 if(needUpdate)
965 {
966 short preStopRecno = stop_array[curStopId-1].firm_recno;
967
968 update_stop_list();
969
970 if(!stop_defined_num)
971 return 0; // no stop is valid
972
973 int i;
974 for(i=1, stopPtr=stop_array; i<=stop_defined_num; i++, stopPtr++)
975 {
976 if(stopPtr->firm_recno==preStopRecno)
977 return (i>=stop_defined_num) ? 1 : i+1;
978 }
979
980 return 1;
981 }
982 else
983 return nextStopId;
984 //#### end alex 24/10 ####//
985 }
986 //----------- End of function UnitCaravan::get_next_stop_id -----------//
987
988
989 //--------- Begin of function UnitCaravan::pre_process ---------//
990 //
pre_process()991 void UnitCaravan::pre_process()
992 {
993 Unit::pre_process();
994
995 if(cur_x == -1) // can't use !is_visible(), keep process if cur_x < -1
996 return;
997
998 #define SURROUND_FIRM_WAIT_FACTOR 10
999
1000 //-----------------------------------------------------------------------------//
1001 // if all the hit points are lost, die now
1002 //-----------------------------------------------------------------------------//
1003 if(hit_points <= 0)
1004 {
1005 if(action_mode != ACTION_DIE)
1006 set_die();
1007
1008 return;
1009 }
1010
1011 err_when(action_mode==ACTION_DIE || cur_action==SPRITE_DIE || hit_points<=0);
1012
1013 //-----------------------------------------------------------------------------//
1014 // stop action if no stop is defined
1015 //-----------------------------------------------------------------------------//
1016 if(!stop_defined_num)
1017 {
1018 err_when(dest_stop_id!=0);
1019 if(journey_status!=NO_STOP_DEFINED)
1020 stop(); // stop if no valid stop is defined
1021
1022 journey_status = NO_STOP_DEFINED;
1023 return;
1024 }
1025
1026 //-----------------------------------------------------------------------------//
1027 // wait in the surrounding of the stop if stop_defined_num==1 (only one stop)
1028 //-----------------------------------------------------------------------------//
1029 if(stop_defined_num==1)
1030 {
1031 CaravanStop *stopPtr = &stop_array[0];
1032 err_when(!stopPtr->firm_recno);
1033
1034 if(firm_array.is_deleted(stopPtr->firm_recno))
1035 {
1036 update_stop_list();
1037 return;
1038 }
1039
1040 Firm *firmPtr = firm_array[stopPtr->firm_recno];
1041 int firmXLoc1 = firmPtr->loc_x1;
1042 int firmYLoc1 = firmPtr->loc_y1;
1043 int firmXLoc2 = firmPtr->loc_x2;
1044 int firmYLoc2 = firmPtr->loc_y2;
1045 int firmId = firmPtr->firm_id;
1046 if(firmXLoc1!=stopPtr->firm_loc_x1 || firmYLoc1!=stopPtr->firm_loc_y1 ||
1047 (firmId!=FIRM_MINE && firmId!=FIRM_FACTORY && firmId!=FIRM_MARKET))
1048 {
1049 update_stop_list();
1050 return;
1051 }
1052
1053 int curXLoc = next_x_loc();
1054 int curYLoc = next_y_loc();
1055
1056 if(curXLoc<firmXLoc1-1 || curXLoc>firmXLoc2+1 || curYLoc<firmYLoc1-1 || curYLoc>firmYLoc2+1)
1057 {
1058 if(cur_action==SPRITE_IDLE)
1059 move_to_firm_surround(firmXLoc1, firmYLoc1, sprite_info->loc_width, sprite_info->loc_height, firmId);
1060 else
1061 journey_status = ON_WAY_TO_FIRM;
1062 }
1063 else
1064 {
1065 journey_status = SURROUND_FIRM;
1066 //if(firmPtr->nation_recno==nation_recno)
1067 if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty)
1068 {
1069 if(wait_count<=0)
1070 {
1071 //---------- unloading goods -------------//
1072 switch(stopPtr->firm_id)
1073 {
1074 case FIRM_MINE:
1075 break; // no goods unload to mine
1076
1077 case FIRM_FACTORY:
1078 factory_unload_goods();
1079 break;
1080
1081 case FIRM_MARKET:
1082 market_unload_goods();
1083 break;
1084
1085 default: err_here();
1086 break;
1087 }
1088
1089 wait_count = MAX_CARAVAN_WAIT_TERM*SURROUND_FIRM_WAIT_FACTOR;
1090 }
1091 else
1092 wait_count--;
1093 }
1094 }
1095 return;
1096 }
1097
1098 //-----------------------------------------------------------------------------//
1099 // at least 2 stops for the caravan to move between
1100 //-----------------------------------------------------------------------------//
1101 err_when(stop_defined_num<=1);
1102
1103 if(journey_status==INSIDE_FIRM)
1104 caravan_in_firm();
1105 else
1106 caravan_on_way();
1107 }
1108 //----------- End of function UnitCaravan::pre_process -----------//
1109
1110
1111 //--------- Begin of function UnitCaravan::caravan_in_firm ---------//
1112 // journey_status : INSIDE_FIRM --> ON_WAY_TO_FIRM
1113 // NO_STOP_DEFINED if no valid stop
1114 // SURROUND_FIRM if only one stop
1115 //
caravan_in_firm()1116 void UnitCaravan::caravan_in_firm()
1117 {
1118 //-----------------------------------------------------------------------------//
1119 // the market is deleted while the caravan is in market
1120 //-----------------------------------------------------------------------------//
1121 if(firm_array.is_deleted(action_para))
1122 {
1123 hit_points = (float) 0; // caravan also die if the market is deleted
1124 unit_array.disappear_in_firm(sprite_recno); // caravan also die if the market is deleted
1125 return;
1126 }
1127
1128 //-----------------------------------------------------------------------------//
1129 // waiting (time to upload/download cargo)
1130 //-----------------------------------------------------------------------------//
1131 if(wait_count>0)
1132 {
1133 wait_count--;
1134 return;
1135 }
1136
1137 //-----------------------------------------------------------------------------//
1138 // leave the market and go to another market if possible
1139 //-----------------------------------------------------------------------------//
1140 CaravanStop *stopPtr = stop_array + dest_stop_id - 1;
1141 int xLoc = stop_x_loc;
1142 int yLoc = stop_y_loc;
1143 Location *locPtr = world.get_loc(xLoc, yLoc);
1144 Firm *firmPtr;
1145
1146 if(locPtr->can_move(mobile_type))
1147 init_sprite(xLoc, yLoc); // appear in the location the unit disappeared before
1148 else
1149 {
1150 //---- the entering location is blocked, select another location to leave ----//
1151 err_when(action_para==0);
1152 firmPtr = firm_array[action_para];
1153
1154 if(appear_in_firm_surround(xLoc, yLoc, firmPtr))
1155 {
1156 init_sprite(xLoc, yLoc);
1157 stop();
1158 err_when(action_para);
1159 }
1160 else
1161 {
1162 wait_count = MAX_CARAVAN_WAIT_TERM*10; //********* BUGHERE, continue to wait or ....
1163 return;
1164 }
1165 }
1166
1167 //-------------- get next stop id. ----------------//
1168 int nextStopId = get_next_stop_id(dest_stop_id);
1169 if(!nextStopId || dest_stop_id==nextStopId)
1170 {
1171 dest_stop_id = nextStopId;
1172 journey_status = (!nextStopId) ? NO_STOP_DEFINED : SURROUND_FIRM;
1173 return; // no stop or only one stop is valid
1174 }
1175
1176 dest_stop_id = nextStopId;
1177 firmPtr = firm_array[stop_array[dest_stop_id-1].firm_recno];
1178
1179 action_para = 0; // since action_para is used to store the current market recno, reset before searching
1180 move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
1181
1182 journey_status = ON_WAY_TO_FIRM;
1183 }
1184 //----------- End of function UnitCaravan::caravan_in_firm -----------//
1185
1186
1187 //--------- Begin of function UnitCaravan::caravan_on_way ---------//
1188 // journey_status : ON_WAY_TO_FIRM --> SURROUND_FIRM
1189 // SURROUND_FIRM --> INSIDE_FIRM
1190 //
caravan_on_way()1191 void UnitCaravan::caravan_on_way()
1192 {
1193 CaravanStop *stopPtr = stop_array + dest_stop_id - 1;
1194
1195 if(cur_action==SPRITE_IDLE && journey_status!=SURROUND_FIRM)
1196 {
1197 if(!firm_array.is_deleted(stopPtr->firm_recno))
1198 {
1199 Firm *firmPtr = firm_array[stopPtr->firm_recno];
1200 move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
1201 int nextXLoc = next_x_loc();
1202 int nextYLoc = next_y_loc();
1203
1204 if(nextXLoc>=firmPtr->loc_x1-1 && nextXLoc<=firmPtr->loc_x2+1 &&
1205 nextYLoc>=firmPtr->loc_y1-1 && nextYLoc<=firmPtr->loc_y2+1) // hard code 1 for carvan size 1x1
1206 journey_status = SURROUND_FIRM;
1207
1208 if(nextXLoc==move_to_x_loc && nextYLoc==move_to_y_loc && !ignore_power_nation)
1209 ignore_power_nation = 1;
1210
1211 return;
1212 }
1213 }
1214
1215 short unitRecno = sprite_recno;
1216
1217 err_when(cur_action==SPRITE_ATTACK || action_mode==ACTION_ATTACK_UNIT || action_mode==ACTION_ATTACK_FIRM ||
1218 action_mode==ACTION_ATTACK_TOWN || action_mode==ACTION_ATTACK_WALL);
1219
1220 if(unit_array.is_deleted(unitRecno))
1221 return; //-***************** BUGHERE ***************//
1222
1223 if(firm_array.is_deleted(stopPtr->firm_recno))
1224 {
1225 update_stop_list();
1226
1227 if(stop_defined_num) // move to next stop
1228 {
1229 Firm *firmPtr = firm_array[stop_array[stop_defined_num-1].firm_recno];
1230 move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
1231 }
1232 return;
1233 }
1234
1235 //CaravanStop *stopPtr = stop_array + dest_stop_id - 1;
1236 Firm *firmPtr = firm_array[stopPtr->firm_recno];
1237
1238 int nextXLoc = next_x_loc();
1239 int nextYLoc = next_y_loc();
1240
1241 if(journey_status==SURROUND_FIRM ||
1242 ( nextXLoc==move_to_x_loc && nextYLoc==move_to_y_loc && cur_x==next_x && cur_y==next_y && // move in a tile exactly
1243 (nextXLoc>=firmPtr->loc_x1-1 && nextXLoc<=firmPtr->loc_x2+1 &&
1244 nextYLoc>=firmPtr->loc_y1-1 && nextYLoc<=firmPtr->loc_y2+1) )) // in the surrounding of the firm
1245 {
1246 //-------------------- update pick_up_array --------------------//
1247 stopPtr->update_pick_up();
1248
1249 //-------------------------------------------------------//
1250 // load/unload goods
1251 //-------------------------------------------------------//
1252 if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty)
1253 {
1254 switch(firmPtr->firm_id)
1255 {
1256 case FIRM_MINE:
1257 mine_load_goods(stopPtr->pick_up_type);
1258 break;
1259
1260 case FIRM_FACTORY:
1261 factory_unload_goods();
1262 factory_load_goods(stopPtr->pick_up_type);
1263 break;
1264
1265 case FIRM_MARKET:
1266 market_unload_goods();
1267
1268 if(stopPtr->pick_up_type == AUTO_PICK_UP)
1269 market_auto_load_goods();
1270 else if(stopPtr->pick_up_type!=NO_PICK_UP)
1271 market_load_goods();
1272 break;
1273
1274 default: err_here();
1275 break;
1276 }
1277 }
1278
1279 //-------------------------------------------------------//
1280 // action_para is used to store the firm_recno of the market
1281 // where the caravan move in.
1282 //-------------------------------------------------------//
1283 action_para = stopPtr->firm_recno;
1284
1285 stop_x_loc = move_to_x_loc; // store entering location
1286 stop_y_loc = move_to_y_loc;
1287 wait_count = MAX_CARAVAN_WAIT_TERM; // set waiting term
1288
1289 reset_path();
1290 deinit_sprite(1); // the caravan enters the market now. 1-keep it selected if it is currently selected
1291
1292 err_when(cur_x!=-1);
1293 cur_x--; // set cur_x to -2, such that invisible but still process pre_process()
1294
1295 journey_status = INSIDE_FIRM;
1296 }
1297 else
1298 {
1299 if(cur_action!=SPRITE_MOVE)
1300 {
1301 //----------------------------------------------------//
1302 // blocked by something, go to the destination again
1303 // note: if return value is 0, cannot reach the firm. //*********BUGHERE
1304 //----------------------------------------------------//
1305 move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
1306 journey_status = ON_WAY_TO_FIRM;
1307 }
1308 }
1309 }
1310 //----------- End of function UnitCaravan::caravan_on_way -----------//
1311
1312
1313 //--------- Begin of function UnitCaravan::appear_in_firm_surround ---------//
1314 //
1315 // This function return 1 if a suitable location is found, that means the
1316 // caravan will leave the firm there. Otherwise, return 0.
1317 //
1318 // xLoc, yLoc are reference variables for returning the location found.
1319 //
appear_in_firm_surround(int & xLoc,int & yLoc,Firm * firmPtr)1320 int UnitCaravan::appear_in_firm_surround(int& xLoc, int& yLoc, Firm* firmPtr)
1321 {
1322 int upperLeftBoundX = firmPtr->loc_x1 - 1; // the surrounding coordinates of the firm
1323 int upperLeftBoundY = firmPtr->loc_y1 - 1;
1324 int lowerRightBoundX = firmPtr->loc_x2 + 1;
1325 int lowerRightBoundY = firmPtr->loc_y2 + 1;
1326
1327 int count = 1, inside = 1, found = 0, i;
1328 int testXLoc = xLoc;
1329 int testYLoc = yLoc;
1330 int limit;
1331 Location *locPtr;
1332
1333 //---------------------------------------------------------//
1334 // 9 10 11 12 the location is tested in the order
1335 // 8 1 2 13 shown, if the location is the surrounding
1336 // 7 x 3 14 of the firm and non-blocked, break
1337 // 6 5 4 ... the test
1338 //---------------------------------------------------------//
1339
1340 while(inside)
1341 {
1342 inside = 0;
1343 limit = count<<1;
1344 err_when(limit!=count*2);
1345
1346 //------------ upper --------------//
1347 testXLoc = xLoc - count + 1;
1348 testYLoc = yLoc - count;
1349 for(i=0; i<limit; i++)
1350 {
1351 if(testXLoc<0 || testYLoc>=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC)
1352 continue;
1353
1354 if(testXLoc<upperLeftBoundX || testXLoc>lowerRightBoundX || testYLoc<upperLeftBoundY || testYLoc>lowerRightBoundY)
1355 continue;
1356
1357 locPtr = world.get_loc(testXLoc, testYLoc);
1358 if(locPtr->can_move(mobile_type))
1359 {
1360 found++;
1361 break;
1362 }
1363 else
1364 xLoc++;
1365
1366 inside++;
1367 }
1368
1369 if(found)
1370 break;
1371
1372 //------------ right --------------//
1373 testXLoc = xLoc + count;
1374 testYLoc = yLoc - count + 1;
1375 for(i=0; i<limit; i++)
1376 {
1377 if(testXLoc<0 || testYLoc>=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC)
1378 continue;
1379
1380 if(testXLoc<upperLeftBoundX || testXLoc>lowerRightBoundX || testYLoc<upperLeftBoundY || testYLoc>lowerRightBoundY)
1381 continue;
1382
1383 locPtr = world.get_loc(testXLoc, testYLoc);
1384 if(locPtr->can_move(mobile_type))
1385 {
1386 found++;
1387 break;
1388 }
1389 else
1390 yLoc++;
1391
1392 inside++;
1393 }
1394
1395 if(found)
1396 break;
1397
1398 //------------- down --------------//
1399 testXLoc = xLoc + count - 1;
1400 testYLoc = yLoc + count;
1401 for(i=0; i<limit; i++)
1402 {
1403 if(testXLoc<0 || testYLoc>=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC)
1404 continue;
1405
1406 if(testXLoc<upperLeftBoundX || testXLoc>lowerRightBoundX || testYLoc<upperLeftBoundY || testYLoc>lowerRightBoundY)
1407 continue;
1408
1409 locPtr = world.get_loc(testXLoc, testYLoc);
1410 if(locPtr->can_move(mobile_type))
1411 {
1412 found++;
1413 break;
1414 }
1415 else
1416 xLoc--;
1417
1418 inside++;
1419 }
1420
1421 if(found)
1422 break;
1423
1424 //------------- left --------------//
1425 testXLoc = xLoc - count;
1426 testYLoc = yLoc + count - 1;
1427 for(i=0; i<limit; i++)
1428 {
1429 if(testXLoc<0 || testYLoc>=MAX_WORLD_X_LOC || testYLoc<0 || testYLoc>=MAX_WORLD_Y_LOC)
1430 continue;
1431
1432 if(testXLoc<upperLeftBoundX || testXLoc>lowerRightBoundX || testYLoc<upperLeftBoundY || testYLoc>lowerRightBoundY)
1433 continue;
1434
1435 locPtr = world.get_loc(testXLoc, testYLoc);
1436 if(locPtr->can_move(mobile_type))
1437 {
1438 found++;
1439 break;
1440 }
1441 else
1442 yLoc--;
1443
1444 inside++;
1445 }
1446
1447 if(found)
1448 break;
1449
1450 //---------------------------------------------//
1451 count++;
1452 }
1453
1454 if(found)
1455 {
1456 xLoc = testXLoc;
1457 yLoc = testYLoc;
1458 return 1;
1459 }
1460
1461 return 0;
1462 }
1463 //----------- End of function UnitCaravan::appear_in_firm_surround -----------//
1464
1465
1466 //---------- begin static function i_disp_caravan_select_button ---------------//
i_disp_caravan_select_button(ButtonCustom * button,int repaintBody)1467 static void i_disp_caravan_select_button(ButtonCustom *button, int repaintBody)
1468 {
1469 int x1 = button->x1;
1470 int y1 = button->y1;
1471 int x2 = button->x2;
1472 int y2 = button->y2;
1473 int shift;
1474
1475 //------------- modify x1,y1, x2,y2 to the button body --------------//
1476 if(button->pushed_flag)
1477 {
1478 int colorDown = Vga::active_buf->color_down; // change the color of the body area to yellow to highlight the change
1479 Vga::active_buf->color_down = (char) V_YELLOW;
1480
1481 Vga::active_buf->d3_panel_down(x1, y1, x2, y2);
1482
1483 Vga::active_buf->color_down = (char) colorDown;
1484
1485 x1++;
1486 y1++;
1487 shift = 2;
1488 }
1489 else
1490 {
1491 Vga::active_buf->d3_panel_up(x1, y1, x2, y2);
1492 x2--;
1493 y2--;
1494 shift = 3;
1495 }
1496
1497 //-------------- put goods icon ---------------//
1498
1499 int id = button->custom_para.value;
1500 const char *iconName=NULL;
1501
1502 int x = x1+shift;
1503 int y = y1+shift;
1504
1505 if(id==AUTO_PICK_UP)
1506 {
1507 iconName = "AUTOPICK";
1508 }
1509 else if(id==NO_PICK_UP)
1510 {
1511 iconName = "NOPICK";
1512 }
1513 else if(id>=PICK_UP_RAW_FIRST && id<=PICK_UP_RAW_LAST)
1514 {
1515 raw_res.put_small_raw_icon( x, y, id-PICK_UP_RAW_FIRST+1 );
1516 }
1517 else if(id>=PICK_UP_PRODUCT_FIRST && id<=PICK_UP_PRODUCT_LAST)
1518 {
1519 raw_res.put_small_product_icon( x, y, id-PICK_UP_PRODUCT_FIRST+1 );
1520 }
1521 else
1522 err_here();
1523
1524 if( iconName )
1525 {
1526 help.set_help( x, y, x+9, y+9, iconName );
1527 Vga::active_buf->put_bitmap_trans( x, y, image_icon.get_ptr(iconName) );
1528 }
1529 }
1530 //---------- end static function i_disp_caravan_select_button ---------------//
1531
1532
1533 //--------- Begin of function UnitCaravan::has_pick_up_type ---------//
1534 //
1535 // Return whether the specific stop has the specific pick up types.
1536 //
has_pick_up_type(int stopId,int pickUpType)1537 int UnitCaravan::has_pick_up_type(int stopId, int pickUpType)
1538 {
1539 return stop_array[stopId-1].pick_up_array[pickUpType-1];
1540 }
1541 //---------- End of function UnitCaravan::has_pick_up_type ----------//
1542
1543
1544 //--------- Begin of function UnitCaravan::carrying_qty ---------//
1545 //
1546 // Return whether the qty of the specific product/raw type that
1547 // this caravan is currently carrying.
1548 //
carrying_qty(int pickUpType)1549 int UnitCaravan::carrying_qty(int pickUpType)
1550 {
1551 if( pickUpType >= PICK_UP_RAW_FIRST &&
1552 pickUpType <= PICK_UP_RAW_LAST )
1553 {
1554 return raw_qty_array[pickUpType-PICK_UP_RAW_FIRST];
1555 }
1556 else if( pickUpType >= PICK_UP_PRODUCT_FIRST &&
1557 pickUpType <= PICK_UP_PRODUCT_LAST )
1558 {
1559 return product_raw_qty_array[pickUpType-PICK_UP_PRODUCT_FIRST];
1560 }
1561 else
1562 {
1563 err_here();
1564 return 0;
1565 }
1566 }
1567 //---------- End of function UnitCaravan::carrying_qty ----------//
1568
1569
1570 //--------- Begin of function UnitCaravan::copy_route ---------//
1571 //
1572 // Copies trade route from copyUnitRecno to this caravan.
1573 //
copy_route(short copyUnitRecno,int remoteAction)1574 void UnitCaravan::copy_route(short copyUnitRecno, int remoteAction)
1575 {
1576 if( sprite_recno == copyUnitRecno )
1577 return;
1578
1579 UnitCaravan* copyUnit = (UnitCaravan*)unit_array[copyUnitRecno];
1580
1581 if( copyUnit->nation_recno != nation_recno )
1582 return;
1583
1584 if( remote.is_enable() && !remoteAction )
1585 {
1586 // packet structure : <unit recno> <copy recno>
1587 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_CARA_COPY_ROUTE, 2*sizeof(short));
1588 *shortPtr = sprite_recno;
1589
1590 shortPtr[1] = copyUnitRecno;
1591 return;
1592 }
1593
1594 // clear existing stops
1595 int num_stops = stop_defined_num;
1596 for( int i=0; i<num_stops; i++ )
1597 del_stop(1, COMMAND_AUTO); // stop ids shift up
1598
1599 CaravanStop* caravanStopA = copyUnit->stop_array;
1600 CaravanStop* caravanStopB = stop_array;
1601 for( int i=0; i<MAX_STOP_FOR_CARAVAN; i++, caravanStopA++, caravanStopB++ )
1602 {
1603 if( !caravanStopA->firm_recno )
1604 break;
1605
1606 if( firm_array.is_deleted(caravanStopA->firm_recno) )
1607 continue;
1608
1609 Firm* firmPtr = firm_array[caravanStopA->firm_recno];
1610 set_stop(i+1, caravanStopA->firm_loc_x1, caravanStopA->firm_loc_y1, COMMAND_AUTO);
1611
1612 if( caravanStopA->pick_up_type == AUTO_PICK_UP )
1613 {
1614 set_stop_pick_up(i+1, AUTO_PICK_UP, COMMAND_AUTO );
1615 }
1616
1617 else if( caravanStopA->pick_up_type == NO_PICK_UP )
1618 {
1619 set_stop_pick_up(i+1, NO_PICK_UP, COMMAND_AUTO );
1620 }
1621
1622 else
1623 {
1624 for( int b=0; b<MAX_PICK_UP_GOODS; ++b )
1625 {
1626 if( caravanStopA->pick_up_array[b] != caravanStopB->pick_up_array[b] )
1627 set_stop_pick_up(i+1, b+1, COMMAND_PLAYER);
1628 }
1629 }
1630 }
1631 }
1632 //---------- End of function UnitCaravan::copy_route ----------//
1633