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 : OF_RESE.CPP
22 //Description : Firm Magic Tower
23
24 #include <OINFO.h>
25 #include <OVGA.h>
26 #include <vga_util.h>
27 #include <ODATE.h>
28 #include <OSTR.h>
29 #include <ONEWS.h>
30 #include <OFONT.h>
31 #include <OCONFIG.h>
32 #include <OBUTT3D.h>
33 #include <OMOUSE.h>
34 #include <OSYS.h>
35 #include <OPOWER.h>
36 #include <OUNIT.h>
37 #include <OGAME.h>
38 #include <ONATION.h>
39 #include <OTECHRES.h>
40 #include <OF_RESE.h>
41 #include <OREMOTE.h>
42 #include <OSE.h>
43 #include <OSERES.h>
44 #include <OBUTTCUS.h>
45 #include "gettext.h"
46
47 //------------- Define constant ------------//
48
49 #define MAX_RESEARCH_OPTION 6
50 #define RESEARCH_OPTION_HEIGHT 48
51
52 //---------- Define constant ------------//
53
54 enum { RESEARCH_MENU_MAIN,
55 RESEARCH_MENU_RESEARCH,
56 };
57
58 //----------- Define static vars -------------//
59
60 static Button3D button_select_research;
61 static char research_menu_mode;
62 static char disable_refresh=0;
63 static ButtonCustom button_research_array[MAX_RESEARCH_OPTION];
64 // ######## begin Gilbert 16/8 ######//
65 static ButtonCustom button_cancel;
66 // ######## end Gilbert 16/8 ######//
67 static int added_count; // no. of buttons in button_research_array
68 static Button3D button_vacate_firm;
69
70 //---------- Declare static functions ---------//
71
72 static void i_disp_research_button(ButtonCustom *, int);
73 static void set_all_research(int techId);
74
75 //--------- Begin of function FirmResearch::FirmResearch ---------//
76 //
FirmResearch()77 FirmResearch::FirmResearch()
78 {
79 firm_skill_id = SKILL_RESEARCH;
80 }
81 //----------- End of function FirmResearch::FirmResearch -----------//
82
83
84 //--------- Begin of function FirmResearch::~FirmResearch ---------//
85 //
~FirmResearch()86 FirmResearch::~FirmResearch()
87 {
88 terminate_research();
89 }
90 //----------- End of function FirmResearch::~FirmResearch -----------//
91
92
93 //--------- Begin of function FirmResearch::init_derived ---------//
94 //
init_derived()95 void FirmResearch::init_derived()
96 {
97 tech_id = 0; // the id. of the tech this firm is currently researching
98 complete_percent = (float) 0; // percent completed on researching the current technology
99 }
100 //----------- End of function FirmResearch::init_derived -----------//
101
102
103 //--------- Begin of function FirmResearch::put_info ---------//
104 //
put_info(int refreshFlag)105 void FirmResearch::put_info(int refreshFlag)
106 {
107 if( refreshFlag==INFO_REPAINT && !disable_refresh )
108 research_menu_mode = RESEARCH_MENU_MAIN;
109
110 switch( research_menu_mode )
111 {
112 case RESEARCH_MENU_MAIN:
113 disp_main_menu(refreshFlag);
114 break;
115
116 case RESEARCH_MENU_RESEARCH:
117 disp_research_menu(refreshFlag);
118 break;
119 }
120 }
121 //----------- End of function FirmResearch::put_info -----------//
122
123
124 //--------- Begin of function FirmResearch::detect_info ---------//
125 //
detect_info()126 int FirmResearch::detect_info()
127 {
128 switch( research_menu_mode )
129 {
130 case RESEARCH_MENU_MAIN:
131 return detect_main_menu();
132
133 case RESEARCH_MENU_RESEARCH:
134 return detect_research_menu();
135 }
136
137 return 0;
138 }
139 //----------- End of function FirmResearch::detect_info -----------//
140
141
142 //--------- Begin of function FirmResearch::disp_main_menu ---------//
143 //
disp_main_menu(int refreshFlag)144 void FirmResearch::disp_main_menu(int refreshFlag)
145 {
146 disp_basic_info(INFO_Y1, refreshFlag);
147
148 if( !should_show_info() )
149 return;
150
151 disp_research_info(INFO_Y1+54, refreshFlag);
152 disp_worker_list(INFO_Y1+107, refreshFlag);
153 disp_worker_info(INFO_Y1+171, refreshFlag);
154
155 //------ display mobilize button -------//
156
157 int x = INFO_X1;
158
159 if( own_firm() )
160 {
161 if (refreshFlag == INFO_REPAINT)
162 {
163 button_select_research.paint(INFO_X1, INFO_Y1 + 235, 'A', "RESEARCH");
164 button_vacate_firm.paint(INFO_X1 + BUTTON_ACTION_WIDTH, INFO_Y1 + 235, 'A', "RECRUIT");
165 button_vacate_firm.set_help_code("MOBILIZE");
166 }
167
168 if( have_own_workers() )
169 button_vacate_firm.enable();
170 else
171 button_vacate_firm.disable();
172
173 x += (BUTTON_ACTION_WIDTH * 2);
174 }
175
176 disp_spy_button( x, INFO_Y1+235, refreshFlag );
177 }
178 //----------- End of function FirmResearch::disp_main_menu -----------//
179
180
181 //--------- Begin of function FirmResearch::detect_main_menu ---------//
182 //
detect_main_menu()183 int FirmResearch::detect_main_menu()
184 {
185 //-------- detect basic info -----------//
186
187 if( detect_basic_info() )
188 return 1;
189
190 //----------- detect worker -----------//
191
192 if( detect_worker_list() )
193 {
194 disp_research_info(INFO_Y1+54, INFO_UPDATE);
195 disp_worker_info(INFO_Y1+171, INFO_UPDATE);
196 return 1;
197 }
198
199 //-------- detect spy button ----------//
200
201 if( detect_spy_button() )
202 return 1;
203
204 if( !own_firm() )
205 return 0;
206
207 //------ detect the select research button -------//
208
209 if( button_select_research.detect(GETKEY(KEYEVENT_FIRM_BUILD)) )
210 {
211 research_menu_mode = RESEARCH_MENU_RESEARCH;
212 disable_refresh = 1; // static var for disp_info() only
213 info.disp();
214 disable_refresh = 0;
215 return 1;
216 }
217
218 //-------- detect mobilize button ----------//
219
220 if (button_vacate_firm.detect())
221 {
222 mobilize_all_workers(COMMAND_PLAYER);
223 return 1;
224 }
225
226 return 0;
227 }
228 //----------- End of function FirmResearch::detect_main_menu -----------//
229
230
231 /** \brief Make all Towers of Science research the same tech.
232 *
233 * \param[in] techId Technology to research.
234 *
235 * \note This function is only used by human players (via the Tower of Science
236 * research interface).
237 */
set_all_research(int techId)238 void set_all_research(int techId)
239 {
240 for( int i=firm_array.size() ; i>0 ; i-- )
241 {
242 if( firm_array.is_deleted(i) )
243 continue;
244
245 Firm* firmPtr = firm_array[i];
246
247 if( firmPtr->nation_recno == nation_array.player_recno &&
248 firmPtr->firm_id == FIRM_RESEARCH &&
249 !firm_array.is_deleted(i) )
250 {
251 (dynamic_cast<FirmResearch*>(firmPtr))->start_research(techId, COMMAND_PLAYER);
252 }
253 }
254 }
255
256
257 //--------- Begin of function FirmResearch::disp_research_menu ---------//
258 //
disp_research_menu(int refreshFlag)259 void FirmResearch::disp_research_menu(int refreshFlag)
260 {
261 if( refreshFlag != INFO_REPAINT )
262 return;
263
264 int techId, y=INFO_Y1;
265 added_count=0;
266
267 for( techId=1 ; techId<=tech_res.tech_count ; techId++ )
268 {
269 if( !tech_res[techId]->can_research(nation_recno) )
270 continue;
271
272 if( added_count < MAX_RESEARCH_OPTION )
273 {
274 button_research_array[added_count].paint(INFO_X1, y, INFO_X2, y+RESEARCH_OPTION_HEIGHT-2,
275 i_disp_research_button, ButtonCustomPara(this, techId) );
276 added_count++;
277 y += RESEARCH_OPTION_HEIGHT;
278 }
279 }
280
281 // ###### begin Gilbert 16/8 ######//
282 // button_cancel.paint(INFO_X1, y, "CANCEL1", "CANCEL1D" );
283 button_cancel.paint(INFO_X1, y, INFO_X2, y+RESEARCH_OPTION_HEIGHT*3/4,
284 ButtonCustom::disp_text_button_func, ButtonCustomPara((void*)_("Cancel"),0) );
285 // ###### end Gilbert 16/8 ######//
286 }
287 //----------- End of function FirmResearch::disp_research_menu -----------//
288
289
290 //--------- Begin of function FirmResearch::detect_research_menu ---------//
291 //
detect_research_menu()292 int FirmResearch::detect_research_menu()
293 {
294 int i;
295 for( i = 0; i < added_count; ++i )
296 {
297 int rc = button_research_array[i].detect(0, 0, 1, 0);
298 if( rc )
299 {
300 int techId = button_research_array[i].custom_para.value;
301 if( tech_res[techId]->can_research(nation_recno) )
302 {
303 if ( rc == 1 ) // Left click.
304 {
305 start_research(techId, COMMAND_PLAYER);
306 }
307 else if ( rc == 2 ) // Right click.
308 {
309 set_all_research(techId);
310 }
311 // ##### begin Gilbert 25/9 ######//
312 se_ctrl.immediate_sound("TURN_ON");
313 // ##### end Gilbert 25/9 ######//
314
315 research_menu_mode = RESEARCH_MENU_MAIN;
316 info.disp();
317 }
318 else
319 {
320 // ##### begin Gilbert 25/9 ######//
321 se_ctrl.immediate_sound("TURN_OFF");
322 // ##### end Gilbert 25/9 ######//
323 }
324 return 1;
325 }
326 }
327
328 //------ detect the cancel button --------//
329
330 if( i >= added_count ) // no research button has been pressed
331 {
332 if( button_cancel.detect() )
333 {
334 // ##### begin Gilbert 25/9 ######//
335 se_ctrl.immediate_sound("TURN_OFF");
336 // ##### end Gilbert 25/9 ######//
337 research_menu_mode = RESEARCH_MENU_MAIN;
338 info.disp();
339 return 1;
340 }
341 }
342
343 return 0;
344 }
345 //----------- End of function FirmResearch::detect_research_menu -----------//
346
347
348 //-------- Begin of static function i_disp_research_button --------//
349 //
i_disp_research_button(ButtonCustom * button,int repaintBody)350 void i_disp_research_button(ButtonCustom *button, int repaintBody)
351 {
352 int x1 = button->x1;
353 int y1 = button->y1;
354 int x2 = button->x2;
355 int y2 = button->y2;
356
357 if( button->pushed_flag )
358 {
359 vga_util.d3_panel2_down(x1, y1, x2, y2);
360 x1++;
361 y1++;
362 }
363 else
364 {
365 vga_util.d3_panel2_up(x1, y1, x2, y2);
366 x2--;
367 y2--;
368 }
369
370 //--------------------------------------------//
371
372 TechInfo* techInfo = tech_res[button->custom_para.value];
373
374 // Vga::active_buf->d3_panel_down(x1+2, y1+2, x1+TECH_LARGE_ICON_WIDTH+7, y1+TECH_LARGE_ICON_HEIGHT+7, 2, 0 );
375 Vga::active_buf->put_bitmap(x1+4, y1+4, techInfo->tech_large_icon() );
376
377 //------ display research description -------//
378
379 String str;
380
381 str = techInfo->tech_des();
382
383 Firm *firmPtr = (Firm *) button->custom_para.ptr;
384 int researchVersion = techInfo->get_nation_tech_level(firmPtr->nation_recno)+1; // research the next non-researched version
385
386 if( researchVersion > 1 )
387 {
388 str += " ";
389 str += misc.roman_number(researchVersion);
390 }
391
392 font_bible.put( x1+TECH_LARGE_ICON_WIDTH+12, y1+14, str );
393 }
394 //--------- End of static function i_disp_research_button ---------//
395
396
397 //--------- Begin of function FirmResearch::disp_research_info ---------//
398 //
disp_research_info(int dispY1,int refreshFlag)399 void FirmResearch::disp_research_info(int dispY1, int refreshFlag)
400 {
401 static short lastTechId=0;
402
403 if( refreshFlag==INFO_UPDATE && lastTechId != tech_id )
404 {
405 lastTechId = tech_id;
406 info.disp();
407 }
408
409 //---------------- paint the panel --------------//
410
411 if( refreshFlag == INFO_REPAINT )
412 vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+50 );
413
414 if( !tech_id )
415 return;
416
417 int x=INFO_X1+4, y=dispY1+4;
418
419 //-------- display the icon of the researching item ---------//
420
421 TechInfo* techInfo = tech_res[tech_id];
422
423 if( refreshFlag == INFO_REPAINT )
424 {
425 vga_util.d3_panel_down( x, y, x+TECH_LARGE_ICON_WIDTH+3, y+TECH_LARGE_ICON_HEIGHT+3, 2 );
426 vga_front.put_bitmap( x+2, y+2, techInfo->tech_large_icon() );
427
428 //----------- display text ------------//
429
430 x += TECH_LARGE_ICON_WIDTH+10;
431
432 String str;
433
434 str = techInfo->tech_des();
435
436 int researchVersion = techInfo->get_nation_tech_level(nation_recno)+1; // research the next non-researched version
437
438 if( researchVersion > 1 )
439 {
440 str += " ";
441 str += misc.roman_number(researchVersion);
442 }
443
444 font_san.put( x, y+4, str);
445 }
446 else
447 {
448 x += TECH_LARGE_ICON_WIDTH+10;
449 }
450
451 vga_front.indicator( 0, x-2, y+21, techInfo->get_progress(nation_recno), (float)100, VGA_GRAY );
452 }
453 //----------- End of function FirmResearch::disp_research_info -----------//
454
455
456 //--------- Begin of function FirmResearch::next_day ---------//
457 //
next_day()458 void FirmResearch::next_day()
459 {
460 //----- call next_day() of the base class -----//
461
462 Firm::next_day();
463
464 //----------- update population -------------//
465
466 recruit_worker();
467
468 //-------- train up the skill ------------//
469
470 update_worker();
471
472 //--------- calculate productivity ----------//
473
474 calc_productivity();
475
476 //--------- process research ----------//
477
478 process_research();
479 }
480 //----------- End of function FirmResearch::next_day -----------//
481
482
483 //------- Begin of function FirmResearch::change_nation ---------//
484 //
change_nation(int newNationRecno)485 void FirmResearch::change_nation(int newNationRecno)
486 {
487 terminate_research();
488
489 //-------- change the nation of this firm now ----------//
490
491 Firm::change_nation(newNationRecno);
492 }
493 //-------- End of function FirmResearch::change_nation ---------//
494
495
496 //--------- Begin of function FirmResearch::start_research --------//
497 //
498 // Start researching on the specific technology.
499 //
500 // <int> techId - id. of the technology to research.
501 //
start_research(int techId,char remoteAction)502 void FirmResearch::start_research(int techId, char remoteAction)
503 {
504 TechInfo* techInfo = tech_res[techId];
505
506 err_when( !techInfo->can_research(nation_recno) );
507
508 if( !remoteAction && remote.is_enable())
509 {
510 // packet structure : <firm recno> <tech Id>
511 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_F_RESEARCH_START, 2*sizeof(short) );
512 shortPtr[0] = firm_recno;
513 shortPtr[1] = (short) techId;
514 return;
515 }
516
517 //---- if the firm currently is already researching something ---//
518
519 if( tech_id )
520 terminate_research();
521
522 //-------- set self parameters ---------//
523
524 tech_id = techId;
525
526 //------- set TechRes parameters -------//
527
528 techInfo->inc_nation_is_researching(nation_recno);
529 }
530 //----------- End of function FirmResearch::start_research ---------//
531
532
533 //--------- Begin of function FirmResearch::process_research --------//
534 //
535 // Process the current research.
536 //
process_research()537 void FirmResearch::process_research()
538 {
539 if( !tech_id )
540 return;
541
542 //------- make a progress with the research ------//
543
544 TechInfo* techInfo = tech_res[tech_id];
545 float progressPoint;
546
547 if( config.fast_build && nation_recno==nation_array.player_recno )
548 progressPoint = (float) productivity / 100 + (float) 0.5;
549 else
550 progressPoint = (float) productivity / 300;
551
552 int newLevel = techInfo->get_nation_tech_level(nation_recno)+1;
553 float levelDivider = ((float)(newLevel+1)/2); // from 1.0 to 2.0
554
555 progressPoint = progressPoint * (float) 30
556 / techInfo->complex_level
557 / levelDivider; // more complex and higher level technology will take longer to research
558
559 int techId = tech_id; // techInfo->progress() will reset tech_id if the current research level is the MAX tech level, so we have to save it now
560
561 if( techInfo->progress(nation_recno, progressPoint) )
562 {
563 if( tech_id ) // TechRes::progress() may have called terminate_research() if the tech level reaches the maximum
564 {
565 int techId = tech_id;
566
567 research_complete();
568
569 //----- research next level technology automatically -----//
570
571 if( !firm_ai ) // for player's firm only
572 {
573 if( techInfo->get_nation_tech_level(nation_recno) < techInfo->max_tech_level )
574 {
575 start_research( techId, COMMAND_AUTO );
576
577 if( firm_recno == firm_array.selected_recno )
578 info.disp();
579 }
580 }
581 }
582
583 //--------- add news ---------//
584
585 if( own_firm() )
586 {
587 news_array.tech_researched( techId, tech_res[techId]->get_nation_tech_level(nation_recno) );
588
589 se_res.far_sound(center_x, center_y, 1, 'F', firm_id, "FINS",
590 'S', unit_res[tech_res[techId]->unit_id]->sprite_id);
591 }
592 }
593 }
594 //----------- End of function FirmResearch::process_research ---------//
595
596
597 //--------- Begin of function FirmResearch::research_complete --------//
598 //
research_complete()599 void FirmResearch::research_complete()
600 {
601 short techId = tech_id; // backup tech_id
602
603 tech_res[tech_id]->dec_nation_is_researching(nation_recno);
604
605 tech_id = 0; // reset parameters
606 complete_percent = (float) 0;
607 }
608 //----------- End of function FirmResearch::research_complete ---------//
609
610
611 //--------- Begin of function FirmResearch::terminate_research --------//
612 //
terminate_research()613 void FirmResearch::terminate_research()
614 {
615 if( !tech_id )
616 return;
617
618 tech_res[tech_id]->dec_nation_is_researching(nation_recno);
619
620 tech_id = 0; // reset parameters
621 complete_percent = (float) 0;
622 }
623 //----------- End of function FirmResearch::terminate_research ---------//
624