1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 //Filename   : OU_MARI2.CPP
22 //Description: UnitMarine - functions for displaying info.
23 
24 #include <OVGA.h>
25 #include <vga_util.h>
26 #include <OINFO.h>
27 #include <OHELP.h>
28 #include <OMOUSE.h>
29 #include <OCONFIG.h>
30 #include <ORACERES.h>
31 #include <OIMGRES.h>
32 #include <ORAWRES.h>
33 #include <OPOWER.h>
34 #include <OFONT.h>
35 #include <OBUTTON.h>
36 #include <OBUTT3D.h>
37 #include <OREMOTE.h>
38 #include <OU_CARA.h>
39 #include <OU_MARI.h>
40 #include <ONATION.h>
41 #include <OF_MINE.h>
42 #include <OF_FACT.h>
43 #include <OBUTTCUS.h>
44 #include <OSE.h>
45 #include <OF_HARB.h>
46 #include "gettext.h"
47 
48 #ifdef DEBUG
49 #include <stdio.h>
50 #endif
51 
52 //--------- Define static vars ----------//
53 
54 static short  	   	unit_disp_y1, unit_info_disp_y1, stop_disp_y1;
55 static Button3D		button_unload_all;
56 static ButtonGroup	button_mode(2);
57 static Button			button_auto_trade;
58 static Button 			button_set_stop[MAX_STOP_FOR_SHIP];
59 static Button 			button_go_stop[MAX_STOP_FOR_SHIP];
60 static Button 			button_cancel_stop[MAX_STOP_FOR_SHIP];
61 //static Button			button_select_attack;
62 static ButtonCustom	button_select_array[MAX_STOP_FOR_SHIP][MAX_GOODS_SELECT_BUTTON];
63 
64 static void				i_disp_marine_select_button(ButtonCustom *button, int repaintBody);
65 
66 //--------- Begin of function UnitMarine::disp_info ---------//
67 //
disp_info(int refreshFlag)68 void UnitMarine::disp_info(int refreshFlag)
69 {
70 	disp_basic_info(INFO_Y1, refreshFlag);
71 
72 	if( !should_show_info() )
73 		return;
74 
75 	//---- display the switch between the units and goods menu ----//
76 
77 	UnitInfo* unitInfo = unit_res[unit_id];
78 
79 	int y=INFO_Y1+54;
80 
81 	if( unitInfo->carry_unit_capacity && unitInfo->carry_goods_capacity )
82 	{
83 		if( refreshFlag == INFO_REPAINT )
84 		{
85 			vga_util.d3_panel_up( INFO_X1, y, INFO_X2, y+22 );
86 
87 			button_mode[0].create_text( INFO_X1+5, y+3, INFO_X1+80, y+19, _("Units") );
88 			button_mode[1].create_text( INFO_X1+90, y+3, INFO_X1+155, y+19, _("Goods") );
89 			button_mode.paint(menu_mode);
90 
91 			button_auto_trade.paint_text( INFO_X1+165, y+3, INFO_X2-10, y+19, auto_mode ? (char*)"T" : (char*)"C");
92 		}
93 
94 		y += 25;
95 	}
96 
97 	//-------------------------------------------------------------//
98 
99 	switch( menu_mode )
100 	{
101 		case SHIP_MENU_GOODS:
102 			disp_goods_menu(y, refreshFlag);
103 			break;
104 
105 		case SHIP_MENU_UNIT:
106 			disp_unit_menu(y, refreshFlag);
107 			break;
108 	}
109 }
110 //----------- End of function UnitMarine::disp_info -----------//
111 
112 
113 //--------- Begin of function UnitMarine::detect_info ---------//
114 //
detect_info()115 void UnitMarine::detect_info()
116 {
117 	if(!is_visible())
118 		return;
119 
120 	if( detect_basic_info() )
121 		return;
122 
123 	if( detect_select_hotkey() )
124 		return;
125 
126 	if( !is_own() )
127 		return;
128 
129 	//----- detect switching the menu mode -----//
130 
131 	UnitInfo* unitInfo = unit_res[unit_id];
132 
133 	if( unitInfo->carry_unit_capacity && unitInfo->carry_goods_capacity )
134 	{
135 		int rc;
136 
137 		if( (rc=button_mode.detect()) >= 0 )
138 		{
139 			menu_mode = rc;
140 			info.disp();
141 			return;
142 		}
143 	}
144 
145 	if( !is_own() && !config.show_ai_info)
146 		return;
147 
148 	//--------- detect menu mode --------//
149 
150 	switch( menu_mode )
151 	{
152 		case SHIP_MENU_GOODS:
153 			detect_goods_menu();
154 			break;
155 
156 		case SHIP_MENU_UNIT:
157 			detect_unit_menu();
158 			break;
159 	}
160 
161 	//---- detect toggling auto trade mode ----//
162 
163 	if( button_auto_trade.detect() )
164 	{
165 		if( !remote.is_enable() )
166 		{
167 			auto_mode = !auto_mode;
168 			button_auto_trade.paint_text( INFO_X1+165, INFO_Y1+57, INFO_X2-10, INFO_Y1+73, auto_mode ? (char*)"T" : (char*)"C");
169 		}
170 		else
171 		{
172 			// packet structure <unit recno> <new mode>
173 			short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_CHANGE_MODE, 2*sizeof(short) );
174 			*shortPtr = sprite_recno;
175 			shortPtr[1] = !auto_mode;
176 		}
177 	}
178 }
179 //----------- End of function UnitMarine::detect_info -----------//
180 
181 
182 //--------- Begin of function UnitMarine::is_in_build_menu ---------//
183 // Returns true if a unit is currently in build mode.
184 // Only reliable if this unit is the selected unit.
185 // Used by Info to detect if the build mode is opened.
186 //
is_in_build_menu()187 bool UnitMarine::is_in_build_menu()
188 {
189 	return false;
190 }
191 //----------- End of function UnitMarine::is_in_build_menu -----------//
192 
193 
194 //-------- Begin of function UnitMarine::should_show_info ------//
195 //
should_show_info()196 int UnitMarine::should_show_info()
197 {
198 	if( config.show_ai_info || nation_recno==nation_array.player_recno )
199 		return 1;
200 
201 	//--- if any of the units on the ship are spies of the player ---//
202 
203 	for( int i=0 ; i<unit_count ; i++ )
204 	{
205 		if( unit_array[ unit_recno_array[i] ]->is_own() )
206 			return 1;
207 	}
208 
209 	return 0;
210 }
211 //---------- End of function UnitMarine::should_show_info --------//
212 
213 
214 //--------- Begin of function UnitMarine::disp_unit_menu ---------//
215 //
disp_unit_menu(int dispY1,int refreshFlag)216 void UnitMarine::disp_unit_menu(int dispY1, int refreshFlag)
217 {
218 	disp_unit_list(dispY1   , refreshFlag);
219 	disp_unit_info(dispY1+90, refreshFlag);
220 
221 	if( !is_own() )
222 		return;
223 
224 	if( refreshFlag==INFO_REPAINT )
225 		button_unload_all.paint( INFO_X1, dispY1+165, 'A', "OUTSHIP" );
226 
227 	if( can_unload_unit() )
228 		button_unload_all.enable();
229 	else
230 		button_unload_all.disable();
231 
232 //	if( refreshFlag == INFO_REPAINT )
233 //		button_select_attack.paint_text( INFO_X2-50, INFO_Y1+180, INFO_X2-5, INFO_Y1+200, "0" );
234 }
235 //----------- End of function UnitMarine::disp_unit_menu -----------//
236 
237 
238 //--------- Begin of function UnitMarine::can_unload_unit ---------//
239 //
can_unload_unit()240 int UnitMarine::can_unload_unit()
241 {
242 	err_when(cur_action==SPRITE_ATTACK && (cur_x!=next_x || cur_y!=next_y));
243 
244 	return unit_count>0 &&
245 			(cur_action==SPRITE_IDLE || cur_action==SPRITE_ATTACK) &&
246 			 is_on_coast();
247 }
248 //----------- End of function UnitMarine::can_unload_unit -----------//
249 
250 
251 //--------- Begin of function UnitMarine::detect_unit_menu ---------//
252 //
detect_unit_menu()253 void UnitMarine::detect_unit_menu()
254 {
255 	//------- detect clicking on the units --------//
256 
257 	if( detect_unit_list() )
258 		disp_unit_info(unit_info_disp_y1, INFO_UPDATE);
259 
260 	if( !is_own() )
261 		return;
262 
263 	//----------- detect the unload all button -----------//
264 
265 	if( button_unload_all.detect('R') )
266 	{
267 		unload_all_units(COMMAND_PLAYER);
268 		info.disp();
269 		// ##### begin Gilbert 25/9 ######//
270 		se_ctrl.immediate_sound("TURN_ON");
271 		// ##### end Gilbert 25/9 ######//
272 	}
273 /*
274 	if(button_select_attack.detect())
275 	{
276 		se_ctrl.immediate_sound("TURN_ON", 100, 0);
277 		select_attack_weapon();
278 	}
279 */
280 }
281 //----------- End of function UnitMarine::detect_unit_menu -----------//
282 
283 
284 //--------- Begin of function UnitMarine::select_attack_weapon ---------//
select_attack_weapon()285 void UnitMarine::select_attack_weapon()
286 {
287 	// ###### begin Gilbert 25/6 ########//
288 	if( attack_count == 0 )                 // TRANSPORT can't select attack weapon
289 		return;
290 	// ###### end Gilbert 25/6 ########//
291 
292 	char oldAttackRange = attack_info_array[0].attack_range;
293 	if(attack_mode_selected>unit_count)
294 		attack_mode_selected = 0;
295 	else
296 	{
297 		Unit *unitPtr;
298 		int found = 0;
299 		for(int i=attack_mode_selected+1; i<=unit_count; i++)
300 		{
301 			unitPtr = unit_array[unit_recno_array[i-1]];
302 			if(unitPtr->attack_count && unit_res[unitPtr->unit_id]->unit_class==UNIT_CLASS_WEAPON)
303 			{
304 				//ship_attack_info = *unit_res.get_attack_info(unit_res[unitPtr->unit_id]->first_attack);
305 				ship_attack_info = *unitPtr->attack_info_array;
306 				ship_attack_info.eqv_attack_next = 0;
307 				ship_attack_info.bullet_out_frame = unit_res.get_attack_info(unit_res[unit_id]->first_attack)->bullet_out_frame;
308 				attack_count = 1;
309 				attack_info_array = &ship_attack_info;
310 				found++;
311 				attack_mode_selected = i;
312 				//cur_action = SPRITE_READY_TO_MOVE;
313 				break;
314 			}
315 		}
316 
317 		if(!found)
318 			attack_mode_selected = 0;
319 	}
320 
321 	if(attack_mode_selected==0)
322 	{
323 		ship_attack_info = *unit_res.get_attack_info(unit_res[unit_id]->first_attack);
324 		attack_count = 1;
325 		attack_info_array = &ship_attack_info;
326 	}
327 
328 	//-------- update attacking if neccessary --------//
329 	if(attack_info_array[0].attack_range<oldAttackRange)
330 	{
331 		short attackXLoc, attackYLoc, attackPara;
332 		switch(action_mode)
333 		{
334 			case ACTION_ATTACK_UNIT:
335 					attackPara = action_para;
336 					stop2();
337 					attack_unit(attackPara);
338 					break;
339 
340 			case ACTION_ATTACK_FIRM:
341 					attackXLoc = action_x_loc;
342 					attackYLoc = action_y_loc;
343 					stop2();
344 					attack_firm(attackXLoc, attackYLoc);
345 					break;
346 
347 			case ACTION_ATTACK_TOWN:
348 					attackXLoc = action_x_loc;
349 					attackYLoc = action_y_loc;
350 					stop2();
351 					attack_town(attackXLoc, attackYLoc);
352 					break;
353 
354 			case ACTION_ATTACK_WALL:
355 					attackXLoc = action_x_loc;
356 					attackYLoc = action_y_loc;
357 					stop2();
358 					attack_wall(attackXLoc, attackYLoc);
359 					break;
360 		}
361 	}
362 
363 //	button_select_attack.paint_text( INFO_X2-50, INFO_Y1+180, INFO_X2-5, INFO_Y1+200, misc.format(attack_mode_selected));
364 }
365 //----------- End of function UnitMarine::select_attack_weapon -----------//
366 
367 
368 //--------- Begin of function UnitMarine::disp_unit_list ---------//
369 //
disp_unit_list(int dispY1,int refreshFlag)370 void UnitMarine::disp_unit_list(int dispY1, int refreshFlag)
371 {
372 	unit_disp_y1 = dispY1;
373 
374 	//---------------- paint the panel --------------//
375 
376 	if( refreshFlag == INFO_REPAINT )
377 		vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+88 );
378 
379 	//------ display population composition -------//
380 
381 	int	  x, y;
382 	Unit*   unitPtr;
383 	static  short last_unit_id_array[MAX_UNIT_IN_SHIP];
384 
385 	if( selected_unit_id > unit_count )
386 		selected_unit_id = 0;
387 
388 	dispY1+=4;
389 
390 	for( int i=0 ; i<MAX_UNIT_IN_SHIP ; i++ )
391 	{
392 		x = INFO_X1+6+i%3*66;
393 		y = dispY1+i/3*28;
394 
395 		if( i<unit_count )
396 		{
397 			unitPtr = unit_array[ unit_recno_array[i] ];
398 
399 			if( refreshFlag==INFO_REPAINT || last_unit_id_array[i] != unitPtr->unit_id )
400 			{
401 				vga_front.d3_panel_up( x, y, x+27, y+23, 1 );
402 				// ###### begin Gilbert 17/10 ########//
403 				vga_front.put_bitmap(x+2, y+2, unit_res[unitPtr->unit_id]->get_small_icon_ptr(unitPtr->rank_id));
404 				// ###### end Gilbert 17/10 ########//
405 			}
406 
407 			//----- highlight the selected unit -------//
408 
409 			if( selected_unit_id == i+1 )
410 				vga_front.rect( x-2, y-2, x+29, y+25, 2, V_YELLOW );
411 			else
412 				vga_front.rect( x-2, y-2, x+29, y+25, 2, vga_front.color_up );
413 
414 			//---------- display hit point ----------//
415 
416 			font_san.disp(x+32, y+6, (int) unitPtr->hit_points, 1, x+61);
417 
418 			last_unit_id_array[i] = unitPtr->unit_id;
419 
420 			//------- set help parameters ---------//
421 
422 			if( mouse.in_area(x, y, x+27, y+23) )
423 				help.set_unit_help( unitPtr->unit_id, unitPtr->rank_id, x, y, x+27, y+23 );
424 		}
425 		else
426 		{
427 			if( last_unit_id_array[i] != 0 )
428 			{
429 				vga_util.blt_buf( x-2, y-2, x+49, y+25, 0 );
430 				last_unit_id_array[i] = 0;
431 			}
432 		}
433 	}
434 }
435 //----------- End of function UnitMarine::disp_unit_list -----------//
436 
437 
438 //--------- Begin of function UnitMarine::detect_unit_list ---------//
439 //
detect_unit_list()440 int UnitMarine::detect_unit_list()
441 {
442 	//------- detect buttons on hiring firm units -------//
443 
444 	int i, x, y;
445 
446 	for( i=0 ; i<unit_count ; i++ )
447 	{
448 		x = INFO_X1+6+i%3*66;
449 		y = unit_disp_y1+4+i/3*28;
450 
451 		//---------------------------------//
452 
453 		if( mouse.press_area(x, y, x+27, y+23) )	// left click to select unit
454 		{
455 			selected_unit_id = i+1;
456 			return 1;
457 		}
458 		else if( mouse.any_click(x, y, x+27, y+23, 1) )			// 1-right button. right click to call out unit
459 		{
460 			mouse.reset_click();		// reset queued mouse click for fast single clicking
461 
462 			unload_unit( i+1, COMMAND_PLAYER );
463 			info.disp();
464 			return 1;
465 		}
466 	}
467 
468 	return 0;
469 }
470 //----------- End of function UnitMarine::detect_unit_list -----------//
471 
472 
473 //--------- Begin of function UnitMarine::disp_unit_info ---------//
474 //
disp_unit_info(int dispY1,int refreshFlag)475 void UnitMarine::disp_unit_info(int dispY1, int refreshFlag)
476 {
477 	static int lastSelected;
478 
479 	unit_info_disp_y1 = dispY1;
480 
481 	if( selected_unit_id > unit_count )
482 		selected_unit_id = unit_count;
483 
484 	//---------------- paint the panel --------------//
485 
486 	if( refreshFlag == INFO_REPAINT )
487 	{
488 		vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+71 );
489 	}
490 	else
491 	{
492 		if( lastSelected != selected_unit_id > 0 )
493 		{
494 			lastSelected = selected_unit_id > 0;
495 			vga_util.blt_buf( INFO_X1, dispY1, INFO_X2, dispY1+71, 0 );
496 		}
497 	}
498 
499 	//-----------------------------------------------//
500 
501 	if( selected_unit_id > 0 )
502 	{
503 		int x=INFO_X1+4, y=dispY1+4, x1=x+100;
504 
505 		Unit* unitPtr = unit_array[ unit_recno_array[selected_unit_id-1] ];
506 
507 		if( unitPtr->race_id && unitPtr->rank_id != RANK_KING )
508 			info.disp_loyalty( x, y, x1, unitPtr->loyalty, unitPtr->target_loyalty, nation_recno, refreshFlag);
509 		else
510 			font_san.field( x, y, _("Loyalty"), x1, _("N/A"), INFO_X2-2, refreshFlag );	// no loyalty because it does not belong to your empire
511 
512 		y+=16;
513 
514 		font_san.field( x, y, _("Combat"), x1, unitPtr->skill.combat_level, 1, INFO_X2-2, refreshFlag);
515 		y+=16;
516 
517 		//----------------------------------------------//
518 
519 		String str;
520 		str  = (int) unitPtr->hit_points;
521 		str += "/";
522 		str += unitPtr->max_hit_points;
523 
524 		font_san.field( x, y, _("Hit Points"), x1, str, INFO_X2-2, refreshFlag);
525 		y += 16;
526 
527 		//----------------------------------------------//
528 
529 		if( unitPtr->skill.skill_id )
530 		{
531 			if( refreshFlag == INFO_REPAINT )
532 				font_san.field( x, y, unitPtr->skill.skill_des(), x1, unitPtr->skill.skill_level , 1, INFO_X2-2, refreshFlag );
533 			else
534 			{
535 				font_san.put( x+2, y+2, unitPtr->skill.skill_des(), 1, x1-2 );
536 				font_san.update_field( x1, y, unitPtr->skill.skill_level, 1, INFO_X2-10);
537 			}
538 		}
539 		else
540 		{
541 			if( refreshFlag == INFO_REPAINT )
542 				font_san.field( x, y, "", x1, "", INFO_X2-2, refreshFlag );
543 			else
544 			{
545 				font_san.put( x+2, y+2, "", 1, x1-2 );
546 				font_san.update_field( x1, y, "", INFO_X2-10);
547 			}
548 		}
549 	}
550 }
551 //----------- End of function UnitMarine::disp_unit_info -----------//
552 
553 
554 //--------- Begin of function UnitMarine::disp_goods_menu ---------//
555 //
disp_goods_menu(int dispY1,int refreshFlag)556 void UnitMarine::disp_goods_menu(int dispY1, int refreshFlag)
557 {
558 	disp_stop(dispY1, refreshFlag);
559 
560 	disp_goods(dispY1+180, refreshFlag);
561 }
562 //----------- End of function UnitMarine::disp_goods_menu -----------//
563 
564 
565 //--------- Begin of function UnitMarine::detect_goods_menu ---------//
566 //
detect_goods_menu()567 void UnitMarine::detect_goods_menu()
568 {
569 	detect_stop();
570 }
571 //---------- End of function UnitMarine::detect_goods_menu ----------//
572 
573 
574 //--------- Begin of function UnitMarine::disp_stop ---------//
575 //
disp_stop(int dispY1,int refreshFlag)576 void UnitMarine::disp_stop(int dispY1, int refreshFlag)
577 {
578 //###### begin trevor 3/10 #######//
579 
580 	if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE)
581 		return;
582 
583 	int 	i, x=INFO_X1, y=dispY1, needRefresh;
584 	Firm	*firmPtr;
585 	static short last_firm_recno_array[MAX_STOP_FOR_CARAVAN];
586 
587 	for(i=0 ; i<MAX_STOP_FOR_CARAVAN ; i++, y+=60)
588 	{
589 		//---- compare with the previous display and see if an update is needed ----//
590 
591 		if( refreshFlag==INFO_REPAINT )
592 		{
593 			needRefresh = 1;
594 		}
595 		else if( last_firm_recno_array[i] != stop_array[i].firm_recno )
596 		{
597 			needRefresh = 1;
598 		}
599 
600 		last_firm_recno_array[i] = stop_array[i].firm_recno;
601 
602 		//----------------------------------------//
603 
604 		if( !stop_array[i].firm_recno ||
605 			 firm_array.is_deleted(stop_array[i].firm_recno) )
606 		{
607 			if( refreshFlag == INFO_REPAINT )
608 			{
609 				vga_util.d3_panel_up(x, y, INFO_X2, y+58);
610 #if(defined(FRENCH))
611 				button_set_stop[i].paint_text( x+4, y+37, x+90, y+56, "Faire Escale" );
612 #else
613 				button_set_stop[i].paint_text( x+4, y+37, x+80, y+56, _("Set Stop") );
614 #endif
615 			}
616 		}
617 		else
618 		{
619 			if( refreshFlag == INFO_REPAINT )
620 			{
621 				vga_util.d3_panel_up(x, y, INFO_X2, y+58);
622 
623 				//-------- display name of the stop --------//
624 
625 				firmPtr = firm_array[ stop_array[i].firm_recno ];
626 				nation_array[firmPtr->nation_recno]->disp_nation_color(x+4, y+4);
627 				font_san.put(x+20, y+4, firmPtr->firm_name());
628 				font_san.put(x+4, y+19, _("Pick up:"));
629 
630 #if(defined(FRENCH))
631 				button_set_stop[i].paint_text( x+4, y+37, x+90, y+56, "Faire Escale" );
632 #else
633 				button_set_stop[i].paint_text( x+4, y+37, x+80, y+56, _("Set Stop") );
634 #endif
635 
636 				button_set_stop[i].set_help_code( "SSETSTOP" );
637 
638 #if(defined(FRENCH))
639 				button_go_stop[i].paint_text( x+94, y+37, x+180, y+56, "Voir Escale" );
640 #else
641 				button_go_stop[i].paint_text( x+84, y+37, x+180, y+56, _("View Stop") );
642 #endif
643 				button_go_stop[i].set_help_code( "SGOSTOP" );
644 
645 				button_cancel_stop[i].paint_text( x+184, y+37, INFO_X2-4, y+56, "X" );
646 				button_cancel_stop[i].set_help_code( "SDELSTOP" );
647 			}
648 
649 			disp_goods_select_button(i, y+1, refreshFlag);
650 		}
651 	}
652 //###### end trevor 3/10 #######//
653 }
654 //---------- End of function UnitMarine::disp_stop ----------//
655 
656 
657 //------ Begin of function UnitMarine::disp_goods_select_button -------//
658 //
disp_goods_select_button(int stopNum,int dispY1,int refreshFlag)659 void UnitMarine::disp_goods_select_button(int stopNum, int dispY1, int refreshFlag)
660 {
661 	if(refreshFlag!=INFO_REPAINT && refreshFlag!=INFO_UPDATE)
662 		return;
663 
664 	#define SHIFT_X_OFFSET	73
665 	#define SELECT_BUTTON_WIDTH	16
666 	#define SELECT_BUTTON_HEIGHT	16
667 
668 	ShipStop	*stopPtr = &stop_array[stopNum];
669 	Firm *harborPtr = firm_array[stopPtr->firm_recno];
670 
671 	int  x=INFO_X1+SHIFT_X_OFFSET, y=dispY1+17, x1, pick_up_goods = 0;
672 	char *pickUpArray = stopPtr->pick_up_array;
673 	char isPush;
674 
675 	//###### begin trevor 3/10 #######//
676 
677 	for(int i=1 ;i<=MAX_PICK_UP_GOODS; ++i, pickUpArray++)
678 	{
679 		int rawId = i;
680 		if( rawId < 1 || rawId > MAX_RAW )
681 			rawId = 0;
682 		int productId = i-MAX_RAW;
683 		if( productId < 1 || productId > MAX_PRODUCT )
684 			productId = 0;
685 
686 		int stock = -1;
687 
688 		for(int j=harborPtr->linked_firm_count-1; j>=0 && stock<0; --j)
689 		{
690 			err_when(firm_array.is_deleted(harborPtr->linked_firm_array[j]));
691 			Firm *firmPtr = firm_array[harborPtr->linked_firm_array[j]];
692 			if( FirmMarket *firmMarket = firmPtr->cast_to_FirmMarket() )
693 			{
694 				MarketGoods *marketGoods;
695 				if( rawId )
696 				{
697 					marketGoods = firmMarket->market_raw_array[rawId-1];
698 					err_when( marketGoods && marketGoods->raw_id != rawId );
699 				}
700 				else if( productId )
701 				{
702 					marketGoods = firmMarket->market_product_array[productId-1];
703 					err_when( marketGoods && marketGoods->product_raw_id != productId );
704 				}
705 				else
706 				{
707 					err_here();
708 					marketGoods = NULL;
709 				}
710 
711 				if( marketGoods )
712 				{
713 					stock = (int) marketGoods->stock_qty;
714 				}
715 			}
716 			else if( FirmMine *firmMine = firmPtr->cast_to_FirmMine() )
717 			{
718 				if( rawId && firmMine->raw_id == rawId )
719 				{
720 					stock = (int) firmMine->stock_qty;
721 				}
722 			}
723 			else if( FirmFactory *firmFactory = firmPtr->cast_to_FirmFactory() )
724 			{
725 				if( productId && firmFactory->product_raw_id == productId )
726 				{
727 					stock = (int) firmFactory->stock_qty;
728 				}
729 				//else if( rawId && firmFactory->product_raw_id == rawId )
730 				//{
731 				//	stock = (int) firmFactory->raw_stock_qty;
732 				//}
733 			}
734 		}
735 
736 		x1 = x + i*SELECT_BUTTON_WIDTH;
737 
738 		if( stock >= 0 )
739 		{
740 			isPush = stopPtr->pick_up_array[i-1];
741 			err_when(isPush && (stopPtr->pick_up_type==AUTO_PICK_UP || stopPtr->pick_up_type==NO_PICK_UP));
742 
743 			button_select_array[stopNum][i].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
744 				y+SELECT_BUTTON_HEIGHT, i_disp_marine_select_button, ButtonCustomPara(this, i),
745 				0, isPush); // 0 for inelastic
746 			pick_up_goods++;
747 		}
748 		else
749 		{
750 			vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
751 		}
752 	}
753 
754 	//---------------- draw the buttons for auto_pick_up and no_pick_up -------------//
755 
756 	if( pick_up_goods>1 )
757 	{
758 		x1 = x;
759 		isPush = (stopPtr->pick_up_type==AUTO_PICK_UP);
760 		button_select_array[stopNum][AUTO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
761 			y+SELECT_BUTTON_HEIGHT, i_disp_marine_select_button, ButtonCustomPara(this, AUTO_PICK_UP),
762 			0, isPush); // 0 for inelastic
763 
764 		x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP;
765 		button_select_array[stopNum][NO_PICK_UP].paint(x1, y, x1+SELECT_BUTTON_WIDTH,
766 			y+SELECT_BUTTON_HEIGHT, i_disp_marine_select_button, ButtonCustomPara(this, NO_PICK_UP));
767 	}
768 	else
769 	{
770 		x1 = x;
771 		vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
772 
773 		x1 = x+SELECT_BUTTON_WIDTH*NO_PICK_UP;
774 		vga_util.blt_buf( x1, y, x1+SELECT_BUTTON_WIDTH, y+SELECT_BUTTON_HEIGHT, 0 );
775 	}
776 
777 	//###### end trevor 3/10 #######//
778 }
779 //---------- End of function UnitMarine::disp_goods_select_button ----------//
780 
781 
782 //--------- Begin of function UnitMarine::detect_stop ---------//
783 //
detect_stop()784 void UnitMarine::detect_stop()
785 {
786 	int i, x=INFO_X1, y=INFO_Y1+54+25;
787 
788 	for( i=0 ; i<MAX_STOP_FOR_SHIP ; i++, y+=38 )
789 	{
790 		if( button_set_stop[i].detect() && is_own() )
791 			power.issue_command( COMMAND_SET_SHIP_STOP, sprite_recno, i+1 );		// i+1 - stop id., passed as a parameter of the command
792 
793 		if(i>=stop_defined_num)
794 			continue;
795 
796 		if(button_cancel_stop[i].detect())
797 		{
798 			if(is_visible())
799 			{
800 				del_stop(i+1, COMMAND_PLAYER);
801 				// ##### begin Gilbert 25/9 ######//
802 				se_ctrl.immediate_sound("TURN_ON");
803 				// ##### end Gilbert 25/9 ######//
804 			}
805 		}
806 
807 		for(int b=0; b<MAX_GOODS_SELECT_BUTTON; ++b)
808 		{
809 			if(button_select_array[i][b].detect())
810 			{
811 				// ###### begin Gilbert 25/9 #######//
812 				se_ctrl.immediate_sound(
813 					button_select_array[i][b].elastic_flag || button_select_array[i][b].pushed_flag ?
814 					(char*)"TURN_ON" : (char*)"TURN_OFF");
815 				// ###### end Gilbert 25/9 #######//
816 				set_stop_pick_up(i+1, b, COMMAND_PLAYER); // b = 1 - MAX_PICK_UP_GOODS
817 			}
818 		}
819 
820 		if( button_go_stop[i].detect() )
821 		{
822 			Firm* firmPtr = firm_array[stop_array[i].firm_recno];
823 			world.go_loc(firmPtr->center_x, firmPtr->center_y);
824 		}
825 	}
826 }
827 //---------- End of function UnitMarine::detect_stop ----------//
828 
829 
830 //--------- Begin of function UnitMarine::set_stop_pick_up ---------//
831 //
832 // Set the pickup type of a specific stop of this marine.
833 //
834 // <int> stopId		  - id. of the stop.  (1 - MAX_STOP_FOR_SHIP)
835 // <int> newPickUpType - set the pickup type of the specific stop. (0 - MAX_GOODS_SELECT_BUTTON-1)
836 // <int> remoteActoin  - remote action type
837 //
set_stop_pick_up(int stopId,int newPickUpType,int remoteAction)838 void UnitMarine::set_stop_pick_up(int stopId, int newPickUpType, int remoteAction)
839 {
840 	if(remote.is_enable())
841 	{
842 		if(!remoteAction)
843 		{
844 			// packet structure : <unit recno> <stop id> <new pick_up_type>
845 			short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_CHANGE_GOODS, 3*sizeof(short));
846 			*shortPtr = sprite_recno;
847 
848 			shortPtr[1] = stopId;
849 			shortPtr[2] = newPickUpType;
850 			return;
851 		}
852 		else //-------- validate remote message ----------//
853 		{
854 			//-*******************************************************-//
855 			/*char mess[255];
856 			sprintf(mess, "Change Seed !!!! \r\n");
857 			OutputDebugString(mess);
858 
859 			Firm *firmPtr = firm_array[stop_array[stopId-1].firm_recno];
860 
861 			switch(firmPtr->firm_id)
862 			{
863 				case FIRM_MINE:
864 						//firmPtr->sell_firm(COMMAND_AUTO);
865 						//firm_array[stop_array[0].firm_recno]->sell_firm(COMMAND_AUTO);
866 						break;
867 				case FIRM_FACTORY:
868 						break;
869 				case FIRM_MARKET:
870 						break;
871 			}
872 
873 			update_stop_list();
874 			if(unit_array.selected_recno == sprite_recno)
875 			{
876 				if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info)
877 				{
878 					int y=INFO_Y1+54;
879 					UnitInfo* unitInfo = unit_res[unit_id];
880 					if( unitInfo->carry_unit_capacity && unitInfo->carry_goods_capacity )
881 						y+=25;
882 
883 					disp_stop(y, INFO_UPDATE);
884 				}
885 			}*/
886 			//-*******************************************************-//
887 
888 			err_when(!is_visible()); // no action if the unit is invisible
889 			if(firm_array.is_deleted(stop_array[stopId-1].firm_recno))
890 				return; // firm is deleted
891 
892 			if(stop_defined_num<stopId)
893 				return; // stop_list is updated, stop exists no more
894 
895 			#ifdef DEBUG
896 			//-*******************************************************-//
897 			/*//char mess[255];
898 			sprintf(mess, "Change Seed : %d %d %d\r\n", stopId, newPickUpType, sprite_recno);
899 			OutputDebugString(mess);*/
900 			//-*******************************************************-//
901 
902 			misc.set_random_seed(stopId + newPickUpType*(misc.random(4)+1)*10 + sprite_recno*100*misc.random(100));
903 
904 			//-*******************************************************-//
905 			/*//char mess[255];
906 			sprintf(mess, "Change Seed : %d\r\n", misc.random_seed);
907 			OutputDebugString(mess);*/
908 			//-*******************************************************-//
909 			#endif
910 		}
911 	}
912 
913 	switch(newPickUpType)
914 	{
915 	case AUTO_PICK_UP:
916 		stop_array[stopId-1].pick_up_set_auto();
917 		break;
918 
919 	case NO_PICK_UP:
920 		stop_array[stopId-1].pick_up_set_none();
921 		break;
922 
923 	default:
924 		err_when(newPickUpType<PICK_UP_RAW_FIRST || newPickUpType>PICK_UP_PRODUCT_LAST);
925 		stop_array[stopId-1].pick_up_toggle(newPickUpType);
926 		break;
927 	}
928 
929 	if( unit_array.selected_recno == sprite_recno )
930 	{
931 		if(nation_recno==nation_array.player_recno || config.show_ai_info)
932 		{
933 			int y=INFO_Y1+54;
934 			UnitInfo* unitInfo = unit_res[unit_id];
935 			if( unitInfo->carry_unit_capacity && unitInfo->carry_goods_capacity )
936 				y+=25;
937 
938 			disp_stop(y, INFO_UPDATE);
939 		}
940 	}
941 }
942 //---------- End of function UnitMarine::set_stop_pick_up ----------//
943 
944 
945 //--------- Begin of function UnitMarine::disp_goods ---------//
946 //
disp_goods(int dispY1,int refreshFlag)947 void UnitMarine::disp_goods(int dispY1, int refreshFlag)
948 {
949 	if( refreshFlag == INFO_REPAINT )
950 		vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+42 );
951 
952 	int	x=INFO_X1+20, y=dispY1+5;
953 	String str;
954 
955 	int i;
956 	for(i=0; i<MAX_RAW; i++, x+=60)
957 	{
958 		vga_front.d3_panel_up( x, y, x+RAW_SMALL_ICON_WIDTH+5, y+RAW_SMALL_ICON_HEIGHT+5 );
959 
960 		raw_res.put_small_raw_icon( x+3, y+3, i+1 );
961 
962 		font_san.disp( x+25, y+2, raw_qty_array[i], 1, x+59 );
963 	}
964 
965 	x =INFO_X1+20;
966 	y+=19;
967 
968 	for( i=0; i<MAX_PRODUCT; i++, x+=60)
969 	{
970 		vga_front.d3_panel_up( x, y, x+RAW_SMALL_ICON_WIDTH+5, y+RAW_SMALL_ICON_HEIGHT+5 );
971 
972 		raw_res.put_small_product_icon( x+3, y+3, i+1 );
973 
974 		font_san.disp( x+25, y+2, product_raw_qty_array[i], 1, x+59 );
975 	}
976 }
977 //---------- End of function UnitMarine::disp_goods ----------//
978 
979 
980 //---------- begin static function i_disp_marine_select_button ---------------//
981 
i_disp_marine_select_button(ButtonCustom * button,int repaintBody)982 static void i_disp_marine_select_button(ButtonCustom *button, int repaintBody)
983 {
984 	int x1 = button->x1;
985 	int y1 = button->y1;
986 	int x2 = button->x2;
987 	int y2 = button->y2;
988 	int shift;
989 
990 	//------------- modify x1,y1, x2,y2 to the button body ---------------//
991 	if(button->pushed_flag)
992 	{
993 		int colorDown = Vga::active_buf->color_down;		// change the color of the body area to yellow to highlight the change
994 		Vga::active_buf->color_down = (char) V_YELLOW;
995 
996 		Vga::active_buf->d3_panel_down(x1, y1, x2, y2);
997 
998 		Vga::active_buf->color_down = (char) colorDown;
999 
1000 		x1++;
1001 		y1++;
1002 		shift = 2;
1003 	}
1004 	else
1005 	{
1006 		Vga::active_buf->d3_panel_up(x1, y1, x2, y2);
1007 		x2--;
1008 		y2--;
1009 		shift = 3;
1010 	}
1011 
1012 	//-------------- put goods icon ---------------//
1013 
1014 	int id = button->custom_para.value;
1015 	const char *iconName=NULL;
1016 
1017 	int x = x1+shift;
1018 	int y = y1+shift;
1019 
1020 	if(id==AUTO_PICK_UP)
1021 	{
1022 		iconName = "AUTOPICK";
1023 	}
1024 	else if(id==NO_PICK_UP)
1025 	{
1026 		iconName = "NOPICK";
1027 	}
1028 	else if(id>=PICK_UP_RAW_FIRST && id<=PICK_UP_RAW_LAST)
1029 	{
1030 		raw_res.put_small_raw_icon( x, y, id-PICK_UP_RAW_FIRST+1 );
1031 	}
1032 	else if(id>=PICK_UP_PRODUCT_FIRST && id<=PICK_UP_PRODUCT_LAST)
1033 	{
1034 		raw_res.put_small_product_icon( x, y, id-PICK_UP_PRODUCT_FIRST+1 );
1035 	}
1036 	else
1037 		err_here();
1038 
1039 	if( iconName )
1040 	{
1041 		help.set_help( x, y, x+9, y+9, iconName );
1042 		Vga::active_buf->put_bitmap_trans( x, y, image_icon.get_ptr(iconName) );
1043 	}
1044 }
1045 //---------- end static function i_disp_marine_select_button ---------------//
1046 
1047 
1048 //---------- Begin of function UnitMarine::fix_attack_info ----------//
fix_attack_info()1049 void UnitMarine::fix_attack_info()
1050 {
1051 	Unit::fix_attack_info();
1052 
1053 	err_when( attack_mode_selected < 0 || attack_mode_selected > unit_count );
1054 	if( attack_count > 0 )
1055 	{
1056 		err_when(attack_count > 1);
1057 		if( attack_mode_selected == 0 )
1058 		{
1059 			ship_attack_info = *unit_res.get_attack_info(unit_res[unit_id]->first_attack);
1060 		}
1061 		attack_info_array = &ship_attack_info;
1062 	}
1063 }
1064 //---------- End of function UnitMarine::fix_attack_info ----------//
1065 
1066 
1067 //--------- Begin of function UnitMarine::set_stop ---------//
1068 // <int> stopId 				 - the id. of the stop
1069 // <int> stopXLoc, stopYLoc - the location of the stop
1070 //
set_stop(int stopId,int stopXLoc,int stopYLoc,char remoteAction)1071 void UnitMarine::set_stop(int stopId, int stopXLoc, int stopYLoc, char remoteAction)
1072 {
1073 	//-------------------------------------------------------//
1074 	// check if there is a station in the given location
1075 	//-------------------------------------------------------//
1076 	Location *locPtr = world.get_loc(stopXLoc, stopYLoc);
1077 	if(!locPtr->is_firm())
1078 		return;
1079 
1080 	Firm *firmPtr = firm_array[locPtr->firm_recno()];
1081 
1082 	if( !can_set_stop( firmPtr->firm_recno ) )
1083 		return;
1084 
1085 	//-------------------------------------------------------//
1086 	// return if the harbor stop is in another territory
1087 	//-------------------------------------------------------//
1088 	FirmHarbor	*harborPtr = (FirmHarbor*) firmPtr;
1089 
1090 	if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=harborPtr->sea_region_id)
1091 		return;
1092 
1093 	//-----------------------------------------//
1094 
1095 	if(!remoteAction && remote.is_enable())
1096 	{
1097 		// packet structure : <unit recno> <stop id> <stop x> <stop y>
1098 		short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_SHIP_SET_STOP, 4*sizeof(short));
1099 		*shortPtr = sprite_recno;
1100 		shortPtr[1] = stopId;
1101 		shortPtr[2] = stopXLoc;
1102 		shortPtr[3] = stopYLoc;
1103 		return;
1104 	}
1105 
1106 	if(!stop_array[stopId-1].firm_recno)
1107 		stop_defined_num++;	// no plus one if the recno is defined originally
1108 
1109 	//-------------------------------------------------------//
1110 	// set the station recno of the stop
1111 	//-------------------------------------------------------//
1112 	ShipStop *stopPtr = stop_array + stopId - 1;
1113 	if(stopPtr->firm_recno==firmPtr->firm_recno)
1114 	{
1115 		err_when(stopPtr->firm_loc_x1!=firmPtr->loc_x1 || stopPtr->firm_loc_y1!=firmPtr->loc_y1);
1116 		return; // same stop as before
1117 	}
1118 
1119 	short oldStopFirmRecno = dest_stop_id ? stop_array[dest_stop_id-1].firm_recno : 0;
1120 	stopPtr->firm_recno		= firmPtr->firm_recno;
1121 	stopPtr->firm_loc_x1		= firmPtr->loc_x1;
1122 	stopPtr->firm_loc_y1		= firmPtr->loc_y1;
1123 
1124 	//-------------------------------------------------------//
1125 	// set pick up selection based on availability
1126 	//-------------------------------------------------------//
1127 	stopPtr->pick_up_set_auto();
1128 
1129 	int goodsId, goodsNum = 0;
1130 	for(int i=harborPtr->linked_firm_count-1; i>=0 && goodsNum<2; --i)
1131 	{
1132 		MarketGoods *goodsPtr;
1133 		int id = 0;
1134 		err_when(firm_array.is_deleted(harborPtr->linked_firm_array[i]));
1135 		firmPtr = firm_array[harborPtr->linked_firm_array[i]];
1136 
1137 		switch(firmPtr->firm_id)
1138 		{
1139 		case FIRM_MINE:
1140 			id = ((FirmMine*)firmPtr)->raw_id;
1141 			if(id)
1142 			{
1143 				if(!goodsNum)
1144 					goodsId = id;
1145 				goodsNum++;
1146 			}
1147 			break;
1148 		case FIRM_FACTORY:
1149 			id = ((FirmFactory*)firmPtr)->product_raw_id+MAX_RAW;
1150 			if(id)
1151 			{
1152 				if(!goodsNum)
1153 					goodsId = id;
1154 				goodsNum++;
1155 			}
1156 			break;
1157 		case FIRM_MARKET:
1158 			goodsPtr = ((FirmMarket*) firmPtr)->market_goods_array;
1159 
1160 			for(int j=0; j<MAX_MARKET_GOODS; ++j && goodsNum<2, goodsPtr++)
1161 			{
1162 				if(goodsPtr->raw_id)
1163 				{
1164 					id = goodsPtr->raw_id;
1165 
1166 					if(!goodsNum)
1167 						goodsId = id;
1168 					goodsNum++;
1169 				}
1170 				else if(goodsPtr->product_raw_id)
1171 				{
1172 					id = goodsPtr->product_raw_id+MAX_RAW;
1173 
1174 					if(!goodsNum)
1175 						goodsId = id;
1176 					goodsNum++;
1177 				}
1178 			}
1179 			break;
1180 		default:
1181 			err_here();
1182 			break;
1183 		}
1184 	}
1185 
1186 	if(goodsNum==1)
1187 		stopPtr->pick_up_toggle(goodsId); // cancel auto_pick_up
1188 	else if(!goodsNum)
1189 		stopPtr->pick_up_set_none();
1190 
1191 	//-------------------------------------------------------//
1192 	// remove duplicate stop or stop change nation
1193 	//-------------------------------------------------------//
1194 	update_stop_list();
1195 
1196 	if(dest_stop_id)
1197 	{
1198 		short newStopFirmRecno;
1199 		err_when(firm_array.is_deleted(stop_array[dest_stop_id-1].firm_recno));
1200 		if((newStopFirmRecno=stop_array[dest_stop_id-1].firm_recno) != oldStopFirmRecno)
1201 		{
1202 			firmPtr = firm_array[newStopFirmRecno];
1203 			err_when(firmPtr->firm_id!=FIRM_HARBOR);
1204 			move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, FIRM_HARBOR);
1205 			journey_status = ON_WAY_TO_FIRM;
1206 		}
1207 	}
1208 	else
1209 		stop2();
1210 
1211 	//-------------------------------------------------------//
1212 	// refresh stop info area
1213 	//-------------------------------------------------------//
1214 	if(unit_array.selected_recno==sprite_recno)
1215 	{
1216 		if(nation_recno==nation_array.player_recno || config.show_ai_info)
1217 			info.disp();
1218 	}
1219 }
1220 //---------- End of function UnitMarine::set_stop ----------//
1221