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 : OGAMENCY.CPP
22 // description : view encyclopedia
23
24 #include <ALL.h>
25 #include <OIMGRES.h>
26 #include <OVGA.h>
27 #include <vga_util.h>
28 #include <OSYS.h>
29 #include <OMOUSE.h>
30 #include <OMOUSECR.h>
31 #include <OVGALOCK.h>
32 #include <OGAME.h>
33 #include <OMUSIC.h>
34
35 //--------- define constant ---------//
36
37 #define ENCYC_CLASS_COUNT 7
38 #define FRYHTAN_MAX_PAGE 3
39 #define SUB_CLASS_BUTTON_MAX 10
40
41 enum
42 {
43 ENCYC_PEOPLE=1,
44 ENCYC_WEAPONS,
45 ENCYC_SHIPS,
46 ENCYC_STRUCTURES,
47 ENCYC_PALACE,
48 ENCYC_GOD,
49 ENCYC_FRYHTANS,
50 };
51
52 const int START_SLIDE_MODE_TIME = 60000; // 60 seconds
53 const int SLIDE_MODE_TIME = 10000; // 10 seconds
54
55 // static int sub_class_count_array[ENCYC_CLASS_COUNT] = { 7, 5, 4, 8, 7, 7, 1 };
56 static int sub_class_count_array[ENCYC_CLASS_COUNT] =
57 { 10, 6, 4, 8, 10, 10, 17 };
58
59 static const char *race_name[] =
60 { "CHINESE", "EGYPTIAN", "GREEK", "JAPANESE", "MAYA", "INDIAN", "NORMAN", "PERSIAN", "VIKING", "ZULU" };
61
62 static const char *weapon_name[] =
63 { "CATAPULT", "BALLISTA", "CANNON", "EXPCART", "FLAMETHR", "F_BALLIS" };
64
65 static const char *ship_name[] =
66 {
67 "VESSEL",
68 "TRANSPOR",
69 "CARAVEL",
70 "GALLEON",
71 };
72
73 static const char *firm_name[] =
74 {
75 "FORT",
76 "FACTORY",
77 "WARFACT",
78 "MARKET",
79 "MINE",
80 "INN",
81 "SCIENCE",
82 "HARBOR",
83 };
84
85 static const char *god_name[] =
86 { "CHINESE", "GREEK", "PERSIAN", "NORMAN", "JAPANESE", "MAYA", "VIKING", "EGYPTIAN", "ZULU", "INDIAN" };
87
88 static const char *monster_name[] =
89 {
90 "HOBGLOB",
91 "SKELETON",
92 "GREMJERM",
93 "GNOLL",
94 "GIANTET",
95 "HEADLESS",
96 "GOBLIN",
97
98 "MAN",
99 "GITH",
100 "LYW",
101 "ROCKMAN",
102 "LIZARD",
103 "FIREKIN",
104
105 "STRUCT_1",
106 "STRUCT_2",
107 "STRUCT_3",
108 "STRUCT_4",
109 };
110
111 static char monster_page_index[FRYHTAN_MAX_PAGE+1] = { 0, 7, 13, 17 };
112
113 static const char* button_name_array[ENCYC_CLASS_COUNT] =
114 {
115 "B_PEOP", "B_WEAP", "B_SHIP", "B_STRUCT", "B_PEOP",
116 "B_GBEING", "B_FRYH",
117 };
118
119 static const char* monster_button_name_array[FRYHTAN_MAX_PAGE] =
120 {
121 "B_FRYH", "B_FRYH2", "B_FRYH3",
122 };
123
124 static const char std_extension[] = ".ICN";
125 static const char pal_extension[] = ".COL";
126
127 //-------- define static variables ----------//
128
129 static int main_class_id;
130 static int sub_class_id_array[ENCYC_CLASS_COUNT];
131 static int fryhtan_page;
132
133 //-------- declare static functions ----------//
134
135 static int detect_main_class_button();
136 static int detect_sub_class_button(int n, int firstButton=1);
137 static void disp_class_buttons();
138 static int disp_picture( int selClass, int selSubClass, int firstDisp=0);
139
140 //-------- Begin of function Game::view_encyclopedia ---------//
141
view_encyclopedia()142 void Game::view_encyclopedia()
143 {
144 music.stop(); // no music for encyclopedia as it reads files from the CDROM
145
146 //---- load the interface into the back buffer ----//
147
148 image_encyc.put_to_buf( &vga_back, "ENCYC" );
149
150 //-------- hide and change mouse cursor --------//
151
152 mouse.hide();
153 mouse_cursor.set_icon(CURSOR_ENCYC);
154
155 main_class_id = 1;
156
157 for( int i=0 ; i<ENCYC_CLASS_COUNT ; i++ )
158 sub_class_id_array[i] = 1;
159
160 unsigned long nextDisplayTime = misc.get_time() + START_SLIDE_MODE_TIME;
161
162 //------- display the default picture ----//
163
164 disp_picture(main_class_id, sub_class_id_array[main_class_id-1], 1 );
165
166 //------ turn screen dark and blt the buffer ---------//
167
168 vga_front.bar( 0, 0, VGA_WIDTH-1, VGA_HEIGHT-1, 0 );
169 sys.blt_virtual_buf();
170
171 //------- bilt the back buffer to the front ---------//
172
173 vga_util.blt_buf( 0,0, vga_back.buf_width()-1, vga_back.buf_height()-1, 0 );
174 mouse.show();
175
176 disp_class_buttons();
177
178 //---------------------------------------------//
179
180 while(1)
181 {
182 //-------------- yield ---------------//
183
184 sys.yield();
185 vga.flip();
186 mouse.get_event();
187 sys.blt_virtual_buf();
188
189 if( sys.signal_exit_flag == 1 )
190 {
191 break;
192 }
193
194 //------ detect main class buttons -------//
195
196 int selClass = detect_main_class_button();
197
198 if( selClass && selClass != main_class_id)
199 {
200 main_class_id = selClass;
201 disp_class_buttons();
202 disp_picture(main_class_id, sub_class_id_array[main_class_id-1]);
203 }
204
205 //------ detect sub class buttons -------//
206
207 int selSubClass = 0;
208 if( main_class_id != ENCYC_FRYHTANS )
209 {
210 selSubClass = detect_sub_class_button(sub_class_count_array[main_class_id-1]);
211 }
212 else
213 {
214 // two buttons at the bottom are for switching page
215 // if in monster class, find out which page
216 int monsterSubClass;
217 for( monsterSubClass = 1; monsterSubClass <= FRYHTAN_MAX_PAGE &&
218 sub_class_id_array[main_class_id-1]-1 >= monster_page_index[monsterSubClass];
219 ++monsterSubClass);
220 err_when( monsterSubClass > FRYHTAN_MAX_PAGE );
221
222 int pictButtonCount = monster_page_index[monsterSubClass] -
223 monster_page_index[monsterSubClass-1];
224
225 int nextPageButton = SUB_CLASS_BUTTON_MAX-1;
226 int prevPageButton = SUB_CLASS_BUTTON_MAX;
227
228 // translate selSubClass from i-th button to new value of sub_class_count_array[main_class_id-1]
229 if( (selSubClass = detect_sub_class_button(pictButtonCount)) > 0)
230 {
231 // click sub-class buttons
232 selSubClass = monster_page_index[monsterSubClass-1]+(selSubClass-1)+1;
233 }
234 else if( nextPageButton <= SUB_CLASS_BUTTON_MAX &&
235 detect_sub_class_button(nextPageButton, nextPageButton) == nextPageButton )
236 {
237 // click page switching buttons
238 // increase monsterSubClass
239 if( ++monsterSubClass > FRYHTAN_MAX_PAGE )
240 monsterSubClass = 1;
241
242 // switch page, assume the first picture of that page
243 selSubClass = monster_page_index[monsterSubClass-1]+1;
244 }
245 else if( prevPageButton <= SUB_CLASS_BUTTON_MAX &&
246 detect_sub_class_button(prevPageButton, prevPageButton) == prevPageButton )
247 {
248 // decrease monsterSubClass
249 if( --monsterSubClass < 1)
250 monsterSubClass = FRYHTAN_MAX_PAGE;
251
252 // switch page, assume the first picture of that page
253 selSubClass = monster_page_index[monsterSubClass-1]+1;
254 }
255 else
256 selSubClass = 0; // as if not selected anything
257 }
258
259 if( selSubClass && selSubClass != sub_class_id_array[main_class_id-1] )
260 {
261 sub_class_id_array[main_class_id-1] = selSubClass;
262
263 disp_class_buttons();
264 disp_picture(main_class_id, selSubClass);
265
266 nextDisplayTime = misc.get_time() + START_SLIDE_MODE_TIME;
267 }
268
269 //------ detect the "Return" button -------//
270
271 if( mouse.single_click(6, 552, 165, 592) ) // return button
272 break;
273
274 //--------- F9 to capture screen ----------//
275
276 if( mouse.single_click(174, 12, 787, 587, 1) ) // right clicking on the picture to save it
277 sys.capture_screen();
278
279 //----------- auto slide show -------------//
280
281 if( misc.get_time() > nextDisplayTime )
282 {
283 //--- display next pictures ---//
284
285 if( ++sub_class_id_array[main_class_id-1] > sub_class_count_array[main_class_id-1] )
286 {
287 sub_class_id_array[main_class_id-1] = 1;
288
289 if( ++main_class_id > ENCYC_CLASS_COUNT )
290 main_class_id = 1;
291 }
292
293 disp_class_buttons();
294
295 if( disp_picture(main_class_id, sub_class_id_array[main_class_id-1]) )
296 nextDisplayTime = misc.get_time() + SLIDE_MODE_TIME;
297 }
298 }
299
300 //------- exiting: turn dark --------//
301
302 // vga.adjust_brightness(-255);
303 vga_front.bar(0,0, vga_front.buf_width()-1, vga_front.buf_height()-1, 0 );
304 sys.blt_virtual_buf();
305
306 //-------- restore mouse cursor --------//
307
308 mouse_cursor.set_icon(CURSOR_NORMAL);
309
310 //----- palette restore when backupPal destruct ----//
311 {
312 vga_front.bar( 0, 0, VGA_WIDTH-1, VGA_HEIGHT-1, 0 );
313
314 VgaFrontLock vgaLock;
315 vga.free_custom_palette();
316 }
317 }
318 //--------- End of function Game::view_encyclopedia ---------//
319
320
321 //-------- Begin of static function detect_main_class_button ---------//
322
detect_main_class_button()323 static int detect_main_class_button()
324 {
325 enum { BUTTON_X = 14, BUTTON_Y = 14, BUTTON_WIDTH = 146, BUTTON_HEIGHT = 28 };
326 enum { BUTTON_Y_SPACING = 30 };
327
328 for( int c=1 ; c<=ENCYC_CLASS_COUNT ; c++ )
329 {
330 //if( mouse.press_area( BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
331 // BUTTON_Y + c*BUTTON_Y_SPACING-1) )
332 if( mouse.single_click( BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
333 BUTTON_Y + c*BUTTON_Y_SPACING-1) )
334 {
335 vga_util.blt_buf( BUTTON_X, BUTTON_Y + (main_class_id-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
336 BUTTON_Y + main_class_id*BUTTON_Y_SPACING-1, 0);
337
338 // ###### begin Gilbert 22/9 #######//
339 // image_encyc.put_front(BUTTON_X-2, BUTTON_Y + (c-1)*BUTTON_Y_SPACING-2, "B_DOWN");
340 image_encyc.put_front(BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, "B_DOWN");
341 // ###### end Gilbert 22/9 #######//
342 return c;
343 }
344 }
345
346 return 0;
347 }
348 //-------- End of static function detect_main_class_button ---------//
349
350
351 //-------- Begin of static function detect_sub_class_button ---------//
352
detect_sub_class_button(int n,int firstButton)353 static int detect_sub_class_button(int n, int firstButton)
354 {
355 enum { BUTTON_X = 14, BUTTON_Y = 236, BUTTON_WIDTH = 146, BUTTON_HEIGHT = 28 };
356 enum { BUTTON_Y_SPACING = 31, MAX_BUTTON = 10 };
357
358 for( int c=firstButton ; c<=n && c<=SUB_CLASS_BUTTON_MAX ; c++ )
359 {
360 //if( mouse.press_area( BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
361 // BUTTON_Y + c*BUTTON_Y_SPACING-1) )
362 if( mouse.single_click( BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
363 BUTTON_Y + c*BUTTON_Y_SPACING-1) )
364 {
365 // int subClassId = sub_class_id_array[main_class_id-1];
366
367 // vga_util.blt_buf( BUTTON_X, BUTTON_Y + (subClassId-1)*BUTTON_Y_SPACING, BUTTON_X + BUTTON_WIDTH-1,
368 // BUTTON_Y + subClassId*BUTTON_Y_SPACING-1, 0);
369
370 // ###### begin Gilbert 22/9 #######//
371 // image_encyc.put_front(BUTTON_X-2, BUTTON_Y + (c-1)*BUTTON_Y_SPACING-2, "B_DOWN");
372 image_encyc.put_front(BUTTON_X, BUTTON_Y + (c-1)*BUTTON_Y_SPACING, "B_DOWN");
373 // ###### end Gilbert 22/9 #######//
374 return c;
375 }
376 }
377
378 return 0;
379 }
380 //-------- End of static function detect_sub_class_button ---------//
381
382
383 //-------- Begin of static function disp_class_buttons ---------//
384 //
disp_class_buttons()385 static void disp_class_buttons()
386 {
387 enum { BUTTON_X=14, BUTTON_WIDTH=146, CLASS_BUTTON_Y=14, CLASS_BUTTON_Y_SPACING=30,
388 SUBCLASS_BUTTON_Y=236, SUBCLASS_TOP_BORDER=3, BUTTON_Y_SPACING=31 };
389
390 int subClassId = sub_class_id_array[main_class_id-1];
391
392 if( main_class_id != ENCYC_FRYHTANS )
393 {
394 vga_back.put_bitmap(12, SUBCLASS_BUTTON_Y-SUBCLASS_TOP_BORDER,
395 image_encyc.get_ptr(button_name_array[main_class_id-1]) );
396 }
397 else
398 {
399 // if in monster class, find out which page
400 int monsterSubClass;
401 for( monsterSubClass = 1; monsterSubClass <= FRYHTAN_MAX_PAGE &&
402 sub_class_id_array[main_class_id-1]-1 >= monster_page_index[monsterSubClass];
403 ++monsterSubClass);
404 err_when( monsterSubClass > FRYHTAN_MAX_PAGE );
405 vga_back.put_bitmap(12, SUBCLASS_BUTTON_Y-SUBCLASS_TOP_BORDER,
406 image_encyc.get_ptr(monster_button_name_array[monsterSubClass-1]) );
407
408 // modify subClassId
409 subClassId -= monster_page_index[monsterSubClass-1];
410 }
411
412 vga_util.blt_buf( BUTTON_X, 14, BUTTON_X+BUTTON_WIDTH-1, VGA_HEIGHT-40, 0 );
413
414 int y=CLASS_BUTTON_Y;
415 // ###### begin Gilbert 22/9 #######//
416 image_encyc.put_front( BUTTON_X, y + (main_class_id-1)*CLASS_BUTTON_Y_SPACING, "B_DOWN");
417 // ###### end Gilbert 22/9 #######//
418
419 y=SUBCLASS_BUTTON_Y;
420 // #### begin Gilbert 22/9 #######//
421 image_encyc.put_front( BUTTON_X, y + (subClassId-1)*BUTTON_Y_SPACING, "B_DOWN");
422 // #### end Gilbert 22/9 #######//
423 }
424 //-------- End of static function disp_class_buttons ---------//
425
426
427 //-------- Begin of static function disp_picture ---------//
428 //
429 // <int> selClass, selSubClass - currently selected class and subclass id.
430 // [int] firstDisp - whether it is the first display action
431 // when the encyclopedia is called upl.
432 //
disp_picture(int selClass,int selSubClass,int firstDisp)433 static int disp_picture( int selClass, int selSubClass, int firstDisp)
434 {
435 if( !DIR_ENCYC[0] )
436 return 0;
437
438 char filename[64];
439 char palname[64];
440 filename[0] = '\0';
441
442 // alternative path
443 char filename2[64];
444 char palname2[64];
445 filename2[0] = '\0';
446
447 switch( selClass )
448 {
449 case ENCYC_PEOPLE:
450 strcpy( filename, DIR_ENCYC );
451 strcat( filename, "UNIT" PATH_DELIM );
452 strcat( filename, race_name[selSubClass-1] );
453 strcpy( palname, filename);
454 strcat( palname, pal_extension);
455 strcat( filename, std_extension );
456 if( DIR_ENCYC2[0] )
457 {
458 strcpy( filename2, DIR_ENCYC2 );
459 strcat( filename2, "UNIT" PATH_DELIM );
460 strcat( filename2, race_name[selSubClass-1] );
461 strcpy( palname2, filename2);
462 strcat( palname2, pal_extension);
463 strcat( filename2, std_extension );
464 }
465 break;
466
467 case ENCYC_WEAPONS:
468 strcpy( filename, DIR_ENCYC );
469 strcat( filename, "UNIT" PATH_DELIM );
470 strcat( filename, weapon_name[selSubClass-1] );
471 strcpy( palname, filename);
472 strcat( palname, pal_extension);
473 strcat( filename, std_extension );
474 if( DIR_ENCYC2[0] )
475 {
476 strcpy( filename2, DIR_ENCYC2 );
477 strcat( filename2, "UNIT" PATH_DELIM );
478 strcat( filename2, weapon_name[selSubClass-1] );
479 strcpy( palname2, filename2);
480 strcat( palname2, pal_extension);
481 strcat( filename2, std_extension );
482 }
483 break;
484
485 case ENCYC_SHIPS:
486 strcpy( filename, DIR_ENCYC );
487 strcat( filename, "UNIT" PATH_DELIM );
488 strcat( filename, ship_name[selSubClass-1] );
489 strcpy( palname, filename);
490 strcat( palname, pal_extension);
491 strcat( filename, std_extension );
492 if( DIR_ENCYC2[0] )
493 {
494 strcpy( filename2, DIR_ENCYC2 );
495 strcat( filename2, "UNIT" PATH_DELIM );
496 strcat( filename2, ship_name[selSubClass-1] );
497 strcpy( palname2, filename2);
498 strcat( palname2, pal_extension);
499 strcat( filename2, std_extension );
500 }
501 break;
502
503 case ENCYC_STRUCTURES:
504 strcpy( filename, DIR_ENCYC );
505 strcat( filename, "FIRM" PATH_DELIM );
506 strcat( filename, firm_name[selSubClass-1] );
507 strcpy( palname, filename);
508 strcat( palname, pal_extension);
509 strcat( filename, std_extension );
510 if( DIR_ENCYC2[0] )
511 {
512 strcpy( filename2, DIR_ENCYC2 );
513 strcat( filename2, "FIRM" PATH_DELIM );
514 strcat( filename2, firm_name[selSubClass-1] );
515 strcpy( palname2, filename2);
516 strcat( palname2, pal_extension);
517 strcat( filename2, std_extension );
518 }
519 break;
520
521 case ENCYC_PALACE:
522 strcpy( filename, DIR_ENCYC );
523 strcat( filename, "SEAT" PATH_DELIM );
524 strcat( filename, race_name[selSubClass-1] );
525 strcpy( palname, filename);
526 strcat( palname, pal_extension);
527 strcat( filename, std_extension );
528 if( DIR_ENCYC2[0] )
529 {
530 strcpy( filename2, DIR_ENCYC2 );
531 strcat( filename2, "SEAT" PATH_DELIM );
532 strcat( filename2, race_name[selSubClass-1] );
533 strcpy( palname2, filename2);
534 strcat( palname2, pal_extension);
535 strcat( filename2, std_extension );
536 }
537 break;
538
539 case ENCYC_GOD:
540 strcpy( filename, DIR_ENCYC );
541 strcat( filename, "GOD" PATH_DELIM );
542 strcat( filename, god_name[selSubClass-1] );
543 strcpy( palname, filename);
544 strcat( palname, pal_extension);
545 strcat( filename, std_extension );
546 if( DIR_ENCYC2[0] )
547 {
548 strcpy( filename2, DIR_ENCYC2 );
549 strcat( filename2, "GOD" PATH_DELIM );
550 strcat( filename2, god_name[selSubClass-1] );
551 strcpy( palname2, filename2);
552 strcat( palname2, pal_extension);
553 strcat( filename2, std_extension );
554 }
555 break;
556
557 case ENCYC_FRYHTANS:
558 strcpy( filename, DIR_ENCYC );
559 strcat( filename, "MONSTER" PATH_DELIM );
560 strcat( filename, monster_name[selSubClass-1] );
561 strcpy( palname, filename);
562 strcat( palname, pal_extension);
563 strcat( filename, std_extension );
564 if( DIR_ENCYC2[0] )
565 {
566 strcpy( filename2, DIR_ENCYC2 );
567 strcat( filename2, "MONSTER" PATH_DELIM );
568 strcat( filename2, monster_name[selSubClass-1] );
569 strcpy( palname2, filename2);
570 strcat( palname2, pal_extension);
571 strcat( filename2, std_extension );
572 }
573 break;
574
575 default:
576 err_here();
577 return 0;
578 }
579
580 File pictFile;
581 char *palNamePtr = NULL;
582
583 if(
584 // search DIR_ENCYC2 first
585 filename2[0] && misc.is_file_exist(filename2) && pictFile.file_open(filename2,0) && (palNamePtr = palname2) ||
586 filename[0] && misc.is_file_exist(filename) && pictFile.file_open(filename,0) && (palNamePtr = palname) )
587 {
588 vga_back.put_large_bitmap(174, 12, &pictFile);
589
590 if( !firstDisp )
591 vga_front.bar(174,12,787,587, 0x00); // wipe the picture screen
592
593 if( palNamePtr && misc.is_file_exist(palNamePtr) )
594 {
595 VgaFrontLock vgaLock;
596 vga.set_custom_palette(palNamePtr);
597 }
598
599 if( !firstDisp )
600 vga_util.blt_buf(174,12,787,587, 0);
601
602 return 1;
603 }
604
605 return 0;
606 }
607
608 //-------- End of static function disp_picture ---------//
609
610