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_BASE.CPP
22 //Description : Firm Base
23
24 #include <OINFO.h>
25 #include <OVGA.h>
26 #include <vga_util.h>
27 #include <ODATE.h>
28 #include <OMOUSE.h>
29 #include <OIMGRES.h>
30 #include <OHELP.h>
31 #include <OSTR.h>
32 #include <OFONT.h>
33 #include <OCONFIG.h>
34 #include <OUNIT.h>
35 #include <OSPY.h>
36 #include <OGAME.h>
37 #include <OBUTT3D.h>
38 #include <ONATION.h>
39 #include <ORACERES.h>
40 #include <OWALLRES.h>
41 #include <OGODRES.h>
42 #include <OPOWER.h>
43 #include <OTOWN.h>
44 #include <OWORLD.h>
45 #include <OF_BASE.h>
46 #include <OREMOTE.h>
47 #include <OSERES.h>
48 #include <OSE.h>
49 #include "gettext.h"
50
51 //----------- Define static vars -------------//
52
53 static Button3D button_invoke, button_reward;
54 static Button3D button_vacate_firm;
55
56 //--------- Begin of function FirmBase::FirmBase ---------//
57 //
FirmBase()58 FirmBase::FirmBase()
59 {
60 firm_skill_id = SKILL_PRAYING;
61 }
62 //----------- End of function FirmBase::FirmBase -----------//
63
64
65 //--------- Begin of function FirmBase::~FirmBase ---------//
66 //
~FirmBase()67 FirmBase::~FirmBase()
68 {
69 err_when( race_id<1 || race_id>MAX_RACE );
70
71 nation_array[nation_recno]->base_count_array[race_id-1]--;
72
73 err_when( nation_array[nation_recno]->base_count_array[race_id-1] < 0 );
74 }
75 //----------- End of function FirmBase::~FirmBase -----------//
76
77
78 //--------- Begin of function FirmBase::init_derived ---------//
79 //
init_derived()80 void FirmBase::init_derived()
81 {
82 pray_points = (float) 0;
83
84 //------ increase NationBase::base_count_array[] -----//
85
86 err_when( race_id<1 || race_id>MAX_RACE );
87
88 nation_array[nation_recno]->base_count_array[race_id-1]++;
89
90 //---------- set the god id. ----------//
91
92 god_id = 0 ;
93 god_unit_recno = 0;
94
95 for( int i=1 ; i<=god_res.god_count ; i++ )
96 {
97 if( god_res[i]->race_id == race_id &&
98 god_res[i]->is_nation_know(nation_recno) )
99 {
100 god_id = i;
101 break;
102 }
103 }
104
105 err_when( god_id==0 );
106 }
107 //----------- End of function FirmBase::init_derived -----------//
108
109
110 //--------- Begin of function FirmBase::assign_unit ---------//
111 //
assign_unit(int unitRecno)112 void FirmBase::assign_unit(int unitRecno)
113 {
114 Unit* unitPtr = unit_array[unitRecno];
115
116 //### begin alex 18/9 ###//
117 /*//------ only assign units of the right race ------//
118
119 if( unitPtr->race_id != race_id )
120 return;*/
121 //#### end alex 18/9 ####//
122
123 //------- if this is a construction worker -------//
124
125 if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION )
126 {
127 set_builder(unitRecno);
128 return;
129 }
130
131 //### begin alex 18/9 ###//
132 //------ only assign units of the right race ------//
133
134 if( unitPtr->race_id != race_id )
135 return;
136 //#### end alex 18/9 ####//
137
138 //-------- assign the unit ----------//
139
140 int rankId = unit_array[unitRecno]->rank_id;
141
142 if( rankId == RANK_GENERAL || rankId==RANK_KING )
143 {
144 assign_overseer(unitRecno);
145 }
146 else
147 {
148 assign_worker(unitRecno);
149 }
150 }
151 //----------- End of function FirmBase::assign_unit -----------//
152
153
154 //--------- Begin of function FirmBase::assign_overseer ---------//
155 //
assign_overseer(int overseerRecno)156 void FirmBase::assign_overseer(int overseerRecno)
157 {
158 //---- reset the team member count of the general ----//
159
160 if( overseerRecno )
161 {
162 Unit* unitPtr = unit_array[overseerRecno];
163
164 err_when( !unitPtr->race_id );
165 err_when( unitPtr->rank_id != RANK_GENERAL && unitPtr->rank_id != RANK_KING );
166 err_when( !unitPtr->team_info );
167
168 unitPtr->team_info->member_count = 0;
169 }
170
171 //----- assign the overseer now -------//
172
173 Firm::assign_overseer(overseerRecno);
174 }
175 //----------- End of function FirmBase::assign_overseer -----------//
176
177
178 //--------- Begin of function FirmBase::put_info ---------//
179 //
put_info(int refreshFlag)180 void FirmBase::put_info(int refreshFlag)
181 {
182 disp_basic_info(INFO_Y1, refreshFlag);
183
184 if( !should_show_info() )
185 return;
186
187 disp_base_info(INFO_Y1+54, refreshFlag);
188 disp_worker_list(INFO_Y1+104, refreshFlag);
189 disp_worker_info(INFO_Y1+168, refreshFlag);
190 disp_god_info(INFO_Y1+226, refreshFlag);
191
192 //------ display button -------//
193
194 int x, y=INFO_Y1+279;
195
196 if( own_firm() )
197 {
198 if( refreshFlag==INFO_REPAINT )
199 {
200 button_invoke.paint( INFO_X1, y, 'A', "INVOKE" );
201 button_reward.paint( INFO_X1 + BUTTON_ACTION_WIDTH, y, 'A', "REWARDSP" );
202 button_vacate_firm.paint(INFO_X1 + BUTTON_ACTION_WIDTH * 2, y, 'A', "RECRUIT");
203 button_vacate_firm.set_help_code("MOBILIZE");
204 }
205
206 if( can_invoke() )
207 button_invoke.enable();
208 else
209 button_invoke.disable();
210
211 if( nation_array[nation_recno]->cash >= REWARD_COST &&
212 ( (overseer_recno && unit_array[overseer_recno]->rank_id != RANK_KING)
213 || selected_worker_id ) )
214 {
215 button_reward.enable();
216 }
217 else
218 {
219 button_reward.disable();
220 }
221
222 if( have_own_workers() )
223 button_vacate_firm.enable();
224 else
225 button_vacate_firm.disable();
226
227 x=INFO_X1+BUTTON_ACTION_WIDTH * 3;
228 }
229 else
230 x=INFO_X1;
231
232 disp_spy_button(x, y, refreshFlag);
233 }
234 //----------- End of function FirmBase::put_info -----------//
235
236
237 //--------- Begin of function FirmBase::detect_info ---------//
238 //
detect_info()239 int FirmBase::detect_info()
240 {
241 if( detect_basic_info() )
242 return 1;
243
244 if( !should_show_info() )
245 return 0;
246
247 //------ detect the overseer button -----//
248
249 int rc = mouse.any_click(INFO_X1+6, INFO_Y1+58, INFO_X1+5+UNIT_LARGE_ICON_WIDTH, INFO_Y1+57+UNIT_LARGE_ICON_HEIGHT, LEFT_BUTTON) ? 1
250 : mouse.any_click(INFO_X1+6, INFO_Y1+58, INFO_X1+5+UNIT_LARGE_ICON_WIDTH, INFO_Y1+57+UNIT_LARGE_ICON_HEIGHT, RIGHT_BUTTON) ? 2 : 0;
251
252 if( rc==1 ) // display this overseer's info
253 {
254 selected_worker_id = 0;
255 disp_base_info(INFO_Y1+54, INFO_UPDATE);
256 disp_worker_list(INFO_Y1+104, INFO_UPDATE);
257 disp_worker_info(INFO_Y1+168, INFO_UPDATE);
258 return 1;
259 }
260
261 //--------- detect soldier info ---------//
262
263 if( detect_worker_list() )
264 {
265 disp_base_info(INFO_Y1+54, INFO_UPDATE);
266 disp_worker_list(INFO_Y1+104, INFO_UPDATE);
267 disp_worker_info(INFO_Y1+168, INFO_UPDATE);
268 return 1;
269 }
270
271 //---------- detect spy button ----------//
272
273 if( detect_spy_button() )
274 return 1;
275
276 if( !own_firm() )
277 return 0;
278
279 //------ detect the overseer button -----//
280
281 if( rc==2 )
282 {
283 if(remote.is_enable())
284 {
285 // packet structure : <firm recno>
286 short *shortPtr=(short *)remote.new_send_queue_msg(MSG_FIRM_MOBL_OVERSEER, sizeof(short));
287 shortPtr[0] = firm_recno;
288 }
289 else
290 {
291 assign_overseer(0); // the overseer quits the camp
292 }
293 return 1;
294 }
295
296 //----------- detect invoke -----------//
297
298 if( button_invoke.detect() )
299 {
300 if(remote.is_enable())
301 {
302 // ##### begin Gilbert 14/10 #######//
303 // packet structure : <firm recno>
304 short *shortPtr=(short *)remote.new_send_queue_msg(MSG_F_BASE_INVOKE_GOD, sizeof(short));
305 shortPtr[0] = firm_recno;
306 // ##### end Gilbert 14/10 #######//
307 }
308 else
309 {
310 invoke_god();
311 }
312 return 1;
313 }
314
315 //----------- detect reward -----------//
316
317 if( button_reward.detect() )
318 {
319 reward(selected_worker_id, COMMAND_PLAYER);
320 // ##### begin Gilbert 26/9 ########//
321 se_ctrl.immediate_sound("TURN_ON");
322 // ##### end Gilbert 26/9 ########//
323 return 1;
324 }
325
326 //-------- detect mobilize button ----------//
327
328 if( button_vacate_firm.detect() )
329 {
330 mobilize_all_workers(COMMAND_PLAYER);
331 return 1;
332 }
333
334 return 0;
335 }
336 //----------- End of function FirmBase::detect_info -----------//
337
338
339 //--------- Begin of function FirmBase::disp_base_info ---------//
340 //
disp_base_info(int dispY1,int refreshFlag)341 void FirmBase::disp_base_info(int dispY1, int refreshFlag)
342 {
343 //---------------- paint the panel --------------//
344
345 if( refreshFlag == INFO_REPAINT )
346 vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+46);
347
348 if( !overseer_recno )
349 return;
350
351 //------------ display overseer info -------------//
352
353 Unit* overseerUnit = unit_array[overseer_recno];
354
355 int x=INFO_X1+6, y=dispY1+4, x1=x+UNIT_LARGE_ICON_WIDTH+8;
356
357 if( selected_worker_id == 0 )
358 {
359 vga_front.rect( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+1, 2, V_YELLOW );
360 }
361 else
362 {
363 vga_util.blt_buf( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y-1, 0 );
364 vga_util.blt_buf( x-2, y+UNIT_LARGE_ICON_HEIGHT+1, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
365 vga_util.blt_buf( x-2, y-2, x-1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
366 vga_util.blt_buf( x+UNIT_LARGE_ICON_WIDTH, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
367 }
368
369 //-------------------------------------//
370
371 if( refreshFlag == INFO_REPAINT )
372 {
373 vga_front.put_bitmap(x, y, unit_res[overseerUnit->unit_id]->get_large_icon_ptr(overseerUnit->rank_id) );
374 }
375
376 //-------- set help parameters --------//
377
378 if( mouse.in_area(x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3) )
379 help.set_unit_help( overseerUnit->unit_id, overseerUnit->rank_id, x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3);
380
381 //-------------------------------------//
382
383 if( overseerUnit->rank_id == RANK_KING )
384 {
385 if( refreshFlag == INFO_REPAINT )
386 font_san.put( x1, y, _("King") );
387
388 y+=14;
389 }
390
391 if( refreshFlag == INFO_REPAINT )
392 font_san.put( x1, y, overseerUnit->unit_name(0), 0, INFO_X2-2 ); // 0-ask unit_name() not to return the title of the unit
393
394 y+=14;
395
396 //------- display leadership -------//
397
398 String str;
399
400 str = _("Leadership");
401 str += ": ";
402 str += overseerUnit->skill.get_skill(SKILL_LEADING);
403
404 font_san.disp( x1, y, str, INFO_X2-10 );
405 y+=14;
406
407 //--------- display loyalty ----------//
408
409 if( overseerUnit->rank_id != RANK_KING )
410 {
411 str = _("Loyalty");
412 str += ":";
413 x1 = font_san.put( x1, y, str );
414
415 int x2 = info.disp_loyalty( x1, y-1, x1, overseerUnit->loyalty, overseerUnit->target_loyalty, nation_recno, refreshFlag );
416
417 if( overseerUnit->spy_recno )
418 {
419 //------ if this is the player's spy -------//
420
421 if( overseerUnit->true_nation_recno() == nation_array.player_recno )
422 {
423 vga_front.put_bitmap( x2+5, y+1, image_icon.get_ptr("U_SPY") );
424 x2 += 15;
425 }
426 }
427
428 vga_util.blt_buf( x2, y-1, INFO_X2-2, dispY1+44, 0 );
429 }
430 }
431 //----------- End of function FirmBase::disp_base_info -----------//
432
433
434 //--------- Begin of function FirmBase::next_day ---------//
435 //
next_day()436 void FirmBase::next_day()
437 {
438 //----- call next_day() of the base class -----//
439
440 Firm::next_day();
441
442 //--------------------------------------//
443
444 calc_productivity();
445
446 //--------------------------------------//
447
448 if( info.game_date%15 == firm_recno%15 ) // once a week
449 {
450 train_unit();
451 recover_hit_point();
452 }
453
454 //------- increase pray points --------//
455
456 if( overseer_recno && pray_points < MAX_PRAY_POINTS )
457 {
458 // ###### patch begin Gilbert 21/1 #######//
459 if( config.fast_build )
460 pray_points += productivity/10;
461 else
462 pray_points += productivity/100;
463 // ###### patch end Gilbert 21/1 #######//
464
465 if( pray_points > MAX_PRAY_POINTS )
466 pray_points = (float) MAX_PRAY_POINTS;
467 }
468
469 //------ validate god_unit_recno ------//
470
471 if( god_unit_recno )
472 {
473 if( unit_array.is_deleted(god_unit_recno) )
474 god_unit_recno = 0;
475
476 #ifdef DEBUG
477 if( god_unit_recno )
478 {
479 err_when( !unit_array[god_unit_recno]->is_visible() );
480 err_when( unit_array[god_unit_recno]->nation_recno != nation_recno );
481 }
482 #endif
483 }
484 }
485 //----------- End of function FirmBase::next_day -----------//
486
487
488 //------- Begin of function FirmBase::change_nation ---------//
489 //
change_nation(int newNationRecno)490 void FirmBase::change_nation(int newNationRecno)
491 {
492 //--- update the UnitInfo vars of the workers in this firm ---//
493
494 for( int i=0 ; i<worker_count ; i++ )
495 unit_res[ worker_array[i].unit_id ]->unit_change_nation(newNationRecno, nation_recno, worker_array[i].rank_id );
496
497 //------ update base_count_array[] --------//
498
499 err_when( race_id<1 || race_id>MAX_RACE );
500
501 nation_array[nation_recno]->base_count_array[race_id-1]--;
502
503 err_when( nation_array[nation_recno]->base_count_array[race_id-1] < 0 );
504
505 nation_array[newNationRecno]->base_count_array[race_id-1]++;
506
507 //----- change the nation recno of the god invoked by the base if there is any ----//
508
509 if( god_unit_recno && !unit_array.is_deleted(god_unit_recno) )
510 unit_array[god_unit_recno]->change_nation(newNationRecno);
511
512 //-------- change the nation of this firm now ----------//
513
514 Firm::change_nation(newNationRecno);
515 }
516 //-------- End of function FirmBase::change_nation ---------//
517
518
519 //------- Begin of function FirmBase::train_unit -------//
520 //
521 // Increase the praying skills of the prayers.
522 //
train_unit()523 void FirmBase::train_unit()
524 {
525 if( !overseer_recno )
526 return;
527
528 Unit* overseerUnit = unit_array[overseer_recno];
529 int overseerSkill = overseerUnit->skill.skill_level;
530 int incValue;
531
532 //------- increase the commander's leadership ---------//
533
534 if( worker_count > 0 && overseerUnit->skill.skill_level < 100 )
535 {
536 //-- the more soldiers this commander has, the higher the leadership will increase ---//
537
538 incValue = 3 * worker_count
539 * (int) overseerUnit->hit_points / overseerUnit->max_hit_points
540 * (100+overseerUnit->skill.skill_potential*2) / 100;
541
542 overseerUnit->skill.skill_level_minor += incValue;
543
544 if( overseerUnit->skill.skill_level_minor >= 100 )
545 {
546 overseerUnit->skill.skill_level_minor -= 100;
547 overseerUnit->skill.skill_level++;
548 }
549 }
550
551 //------- increase the prayer's skill level ------//
552
553 int levelMinor;
554 Worker* workerPtr = worker_array;
555
556 for( int i=0 ; i<worker_count ; i++, workerPtr++ )
557 {
558 //------- increase prayer skill -----------//
559
560 if( workerPtr->skill_level < overseerSkill )
561 {
562 incValue = MAX(20, overseerSkill-workerPtr->skill_level)
563 * workerPtr->hit_points / workerPtr->max_hit_points()
564 * (100+workerPtr->skill_potential*2) / 100;
565
566 levelMinor = workerPtr->skill_level_minor + incValue; // with random factors, resulting in 75% to 125% of the original
567
568 while( levelMinor >= 100 )
569 {
570 levelMinor -= 100;
571 workerPtr->skill_level++;
572 }
573
574 workerPtr->skill_level_minor = levelMinor;
575 }
576 }
577 }
578 //-------- End of function FirmBase::train_unit --------//
579
580
581 //------- Begin of function FirmBase::recover_hit_point -------//
582 //
583 // Prayers recover their hit points.
584 //
585 // No need to recover the hit points of the general here as
586 // this is taken care in the Unit class function of the general.
587 //
recover_hit_point()588 void FirmBase::recover_hit_point()
589 {
590 Worker* workerPtr = worker_array;
591
592 for( int i=0 ; i<worker_count ; i++, workerPtr++ )
593 {
594 //------- increase worker hit points --------//
595
596 if( workerPtr->hit_points < workerPtr->max_hit_points() )
597 workerPtr->hit_points++;
598 }
599 }
600 //------- End of function FirmBase::recover_hit_point -------//
601
602 //--------- Begin of function FirmBase::disp_god_info ---------//
603 //
disp_god_info(int dispY1,int refreshFlag)604 void FirmBase::disp_god_info(int dispY1, int refreshFlag)
605 {
606 //---------------- paint the panel --------------//
607
608 if( refreshFlag == INFO_REPAINT )
609 vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+50 );
610
611 //-------- display the icon of the mythical creature -------//
612
613 int x=INFO_X1+4, y=dispY1+4;
614 UnitInfo* unitInfo = unit_res[ god_res[god_id]->unit_id ];
615
616 if( refreshFlag == INFO_REPAINT )
617 {
618 vga_util.d3_panel_down( x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3, 2 );
619 vga_front.put_bitmap( x+2, y+2, unitInfo->get_large_icon_ptr(0) );
620
621 //----------- display text ------------//
622
623 x += UNIT_LARGE_ICON_WIDTH+10;
624
625 font_san.put( x, y+2, _(unitInfo->name) );
626 }
627 else
628 {
629 x += UNIT_LARGE_ICON_WIDTH+10;
630 }
631
632 vga_front.indicator( 0x00, x-3, y+18, pray_points, (float) MAX_PRAY_POINTS, 0 );
633 }
634 //----------- End of function FirmBase::disp_god_info -----------//
635
636
637 //--------- Begin of function FirmBase::invoke_god ---------//
638 //
639 // Invoke God.
640 //
invoke_god()641 void FirmBase::invoke_god()
642 {
643 god_unit_recno = god_res[god_id]->invoke(firm_recno, center_x, center_y);
644 }
645 //----------- End of function FirmBase::invoke_god -----------//
646
647
648 //--------- Begin of function FirmBase::can_invoke ---------//
649 //
can_invoke()650 int FirmBase::can_invoke()
651 {
652 //----- if the base's god creature has been destroyed -----//
653
654 if( god_unit_recno && unit_array.is_deleted(god_unit_recno) )
655 god_unit_recno = 0;
656
657 //---------------------------------------------------------//
658
659 return !god_unit_recno && // one base can only support one god
660 overseer_recno &&
661 pray_points >= MAX_PRAY_POINTS/10; // there must be at least 10% of the maximum pray points to cast a creature
662 }
663 //----------- End of function FirmBase::can_invoke -----------//
664