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 : OUNITRES.CPP
22 //Description : Object Sprite Frame Resource
23
24 #include <ALL.h>
25 #include <OSTR.h>
26 #include <OSYS.h>
27 #include <OGAMESET.h>
28 #include <ONATION.h>
29 #include <OSPRTRES.h>
30 #include <OUNITRES.h>
31 #include "gettext.h"
32
33 #ifdef NO_DEBUG_UNIT
34 #undef err_when
35 #undef err_here
36 #undef err_if
37 #undef err_else
38 #undef err_now
39 #define err_when(cond)
40 #define err_here()
41 #define err_if(cond)
42 #define err_else
43 #define err_now(msg)
44 #undef DEBUG
45 #endif
46
47 //-------- define file name -----------//
48
49 #define UNIT_DB "UNIT"
50 #define UNIT_ATTACK_DB "UNITATTK"
51
52 //-------- Begin of function UnitRes::init ---------//
53
init()54 void UnitRes::init()
55 {
56 deinit();
57
58 //----- open unit bitmap resource file -------//
59
60 String str;
61
62 str = DIR_RES;
63 str += "I_UNITLI.RES";
64
65 res_large_icon.init_imported(str, 1); // 1-don't read all into buffer
66
67 str = DIR_RES;
68 str += "I_UNITGI.RES";
69
70 res_general_icon.init_imported(str, 1); // 1-don't read all into buffer
71
72 str = DIR_RES;
73 str += "I_UNITKI.RES";
74
75 res_king_icon.init_imported(str, 1); // 1-don't read all into buffer
76
77 str = DIR_RES;
78 str += "I_UNITSI.RES";
79
80 res_small_icon.init_imported(str, 1); // 1-don't read all into buffer
81
82 // ######## begin Gilbert 17/10 ##########//
83 str = DIR_RES;
84 str += "I_UNITTI.RES";
85
86 res_general_small_icon.init_imported(str, 1); // 1-don't read all into buffer
87
88 str = DIR_RES;
89 str += "I_UNITUI.RES";
90
91 res_king_small_icon.init_imported(str, 1); // 1-don't read all into buffer
92 // ######## end Gilbert 17/10 ##########//
93
94 //------- load database information --------//
95
96 load_info();
97 load_attack_info();
98
99 //---------- set vars -----------//
100
101 mobile_monster_count = 0;
102
103 init_flag=1;
104 }
105 //--------- End of function UnitRes::init ----------//
106
107
108 //-------- Begin of function UnitRes::deinit ---------//
109
deinit()110 void UnitRes::deinit()
111 {
112 if( init_flag )
113 {
114 mem_del(unit_info_array);
115 mem_del(attack_info_array);
116
117 res_large_icon.deinit();
118 res_general_icon.deinit();
119 res_king_icon.deinit();
120 res_small_icon.deinit();
121 // ######## begin Gilbert 17/10 ##########//
122 res_general_small_icon.deinit();
123 res_king_small_icon.deinit();
124 // ######## end Gilbert 17/10 ##########//
125
126 init_flag=0;
127 }
128 }
129 //--------- End of function UnitRes::deinit ----------//
130
131
132 //------- Begin of function UnitRes::load_info ---------//
133
load_info()134 void UnitRes::load_info()
135 {
136 Database *dbUnit = game_set.open_db(UNIT_DB);
137 UnitRec *unitRec;
138 UnitInfo *unitInfo;
139 uint32_t bitmapOffset;
140 int i;
141
142 unit_info_count = dbUnit->rec_count();
143 unit_info_array = (UnitInfo*) mem_add(sizeof(UnitInfo) * unit_info_count);
144
145 memset( unit_info_array, 0, sizeof(UnitInfo)*unit_info_count );
146
147 //--------- read in frame information ---------//
148
149 for( i=0 ; i<dbUnit->rec_count() ; i++ )
150 {
151 unitRec = (UnitRec*) dbUnit->read(i+1);
152 unitInfo = unit_info_array+i;
153
154 misc.rtrim_fld( unitInfo->name, unitRec->name, unitRec->NAME_LEN );
155
156 unitInfo->unit_id = i+1;
157 unitInfo->sprite_id = misc.atoi(unitRec->sprite_id, unitRec->SPRITE_ID_LEN);
158 unitInfo->dll_sprite_id = misc.atoi(unitRec->dll_sprite_id, unitRec->SPRITE_ID_LEN);
159 unitInfo->race_id = misc.atoi(unitRec->race_id, unitRec->RACE_ID_LEN);
160
161 unitInfo->unit_class = unitRec->unit_class[0];
162 unitInfo->mobile_type = unitRec->mobile_type;
163
164 unitInfo->visual_range = misc.atoi(unitRec->visual_range, unitRec->UNIT_PARA_LEN);
165 unitInfo->visual_extend = misc.atoi(unitRec->visual_extend, unitRec->UNIT_PARA_LEN);
166 unitInfo->shealth = misc.atoi(unitRec->shealth, unitRec->UNIT_PARA_LEN);
167 unitInfo->hit_points = misc.atoi(unitRec->hit_points, unitRec->UNIT_PARA_LEN);
168 unitInfo->armor = misc.atoi(unitRec->armor, unitRec->UNIT_PARA_LEN);
169
170 unitInfo->build_days = misc.atoi(unitRec->build_days, unitRec->BUILD_DAYS_LEN);
171 unitInfo->year_cost = misc.atoi(unitRec->year_cost, unitRec->YEAR_COST_LEN);
172 unitInfo->build_cost = unitInfo->year_cost;
173
174 if( unitInfo->unit_class == UNIT_CLASS_WEAPON )
175 unitInfo->weapon_power = unitRec->weapon_power-'0';
176
177 unitInfo->carry_unit_capacity = misc.atoi(unitRec->carry_unit_capacity, unitRec->CARRY_CAPACITY_LEN);
178 unitInfo->carry_goods_capacity = misc.atoi(unitRec->carry_goods_capacity, unitRec->CARRY_CAPACITY_LEN);
179 unitInfo->free_weapon_count = misc.atoi(unitRec->free_weapon_count, unitRec->FREE_WEAPON_COUNT_LEN);
180
181 unitInfo->vehicle_id = misc.atoi(unitRec->vehicle_id, unitRec->SPRITE_ID_LEN);
182 unitInfo->vehicle_unit_id = misc.atoi(unitRec->vehicle_unit_id, unitRec->SPRITE_ID_LEN);
183
184 unitInfo->transform_unit_id = misc.atoi(unitRec->transform_unit_id, unitRec->SPRITE_ID_LEN);
185 unitInfo->transform_combat_level = misc.atoi(unitRec->transform_combat_level, unitRec->UNIT_PARA_LEN);
186 unitInfo->guard_combat_level = misc.atoi(unitRec->guard_combat_level, unitRec->UNIT_PARA_LEN);
187
188 memcpy( &bitmapOffset, unitRec->large_icon_ptr, sizeof(uint32_t) );
189 unitInfo->soldier_icon_ptr = res_large_icon.read_imported(bitmapOffset);
190
191 if( unitRec->general_icon_file_name[0] != '\0' && unitRec->general_icon_file_name[0] != ' ')
192 {
193 memcpy( &bitmapOffset, unitRec->general_icon_ptr, sizeof(uint32_t) );
194 unitInfo->general_icon_ptr = res_general_icon.read_imported(bitmapOffset);
195 }
196 else
197 {
198 unitInfo->general_icon_ptr = unitInfo->soldier_icon_ptr;
199 }
200
201 if( unitRec->king_icon_file_name[0] != '\0' && unitRec->king_icon_file_name[0] != ' ')
202 {
203 memcpy( &bitmapOffset, unitRec->king_icon_ptr, sizeof(uint32_t) );
204 unitInfo->king_icon_ptr = res_king_icon.read_imported(bitmapOffset);
205 }
206 else
207 {
208 unitInfo->king_icon_ptr = unitInfo->soldier_icon_ptr;
209 }
210
211 // ###### begin Gilbert 17/10 ######//
212 memcpy( &bitmapOffset, unitRec->small_icon_ptr, sizeof(uint32_t) );
213 unitInfo->soldier_small_icon_ptr = res_small_icon.read_imported(bitmapOffset);
214
215 if( unitRec->general_small_icon_file_name[0] != '\0' && unitRec->general_small_icon_file_name[0] != ' ')
216 {
217 memcpy( &bitmapOffset, unitRec->general_small_icon_ptr, sizeof(uint32_t) );
218 unitInfo->general_small_icon_ptr = res_general_small_icon.read_imported(bitmapOffset);
219 }
220 else
221 {
222 unitInfo->general_small_icon_ptr = unitInfo->soldier_small_icon_ptr;
223 }
224
225 if( unitRec->king_small_icon_file_name[0] != '\0' && unitRec->king_small_icon_file_name[0] != ' ')
226 {
227 memcpy( &bitmapOffset, unitRec->king_small_icon_ptr, sizeof(uint32_t) );
228 unitInfo->king_small_icon_ptr = res_king_small_icon.read_imported(bitmapOffset);
229 }
230 else
231 {
232 unitInfo->king_small_icon_ptr = unitInfo->soldier_small_icon_ptr;
233 }
234 // ###### end Gilbert 17/10 ######//
235
236 unitInfo->first_attack = misc.atoi(unitRec->first_attack, unitRec->UNIT_PARA_LEN);
237 unitInfo->attack_count = misc.atoi(unitRec->attack_count, unitRec->UNIT_PARA_LEN);
238 unitInfo->die_effect_id = misc.atoi(unitRec->die_effect_id, unitRec->UNIT_PARA_LEN);
239
240 if( unitRec->all_know=='1' )
241 memset( unitInfo->nation_tech_level_array, 1, sizeof(unitInfo->nation_tech_level_array) );
242 }
243
244 //--------- set vehicle info ---------//
245
246 for( i=0 ; i<unit_info_count ; i++ )
247 {
248 unitInfo = unit_info_array+i;
249
250 if( unitInfo->vehicle_unit_id )
251 {
252 unit_info_array[ unitInfo->vehicle_unit_id-1 ].vehicle_id = unitInfo->vehicle_id;
253 unit_info_array[ unitInfo->vehicle_unit_id-1 ].solider_id = i+1;
254 }
255 }
256 }
257 //-------- End of function UnitRes::load_info ---------//
258
259
260 //------- Begin of function UnitRes::load_attack_info ---------//
261
load_attack_info()262 void UnitRes::load_attack_info()
263 {
264 Database *dbUnitAttack = game_set.open_db(UNIT_ATTACK_DB);
265 UnitAttackRec *attackRec;
266 AttackInfo *attackInfo;
267 int i;
268
269 attack_info_count = dbUnitAttack->rec_count();
270 attack_info_array = (AttackInfo*) mem_add(sizeof(AttackInfo) * attack_info_count);
271
272 memset( attack_info_array, 0, sizeof(AttackInfo)*attack_info_count );
273
274 //--------- read in frame information ---------//
275
276 for( i=0 ; i<dbUnitAttack->rec_count() ; i++ )
277 {
278 attackRec = (UnitAttackRec*) dbUnitAttack->read(i+1);
279 attackInfo = attack_info_array+i;
280
281 attackInfo->combat_level = misc.atoi(attackRec->combat_level, attackRec->COMBAT_LEVEL_LEN);
282 attackInfo->attack_delay = misc.atoi(attackRec->attack_delay, attackRec->UNIT_PARA_LEN);
283 attackInfo->attack_range = misc.atoi(attackRec->attack_range, attackRec->UNIT_PARA_LEN);
284 attackInfo->attack_damage = misc.atoi(attackRec->attack_damage, attackRec->UNIT_PARA_LEN);
285 attackInfo->pierce_damage = misc.atoi(attackRec->pierce_damage, attackRec->UNIT_PARA_LEN);
286 attackInfo->bullet_out_frame = misc.atoi(attackRec->bullet_out_frame, attackRec->UNIT_PARA_LEN);
287 attackInfo->bullet_speed = misc.atoi(attackRec->bullet_speed, attackRec->UNIT_PARA_LEN);
288 attackInfo->bullet_radius = misc.atoi(attackRec->bullet_radius, attackRec->UNIT_PARA_LEN);
289 attackInfo->bullet_sprite_id = misc.atoi(attackRec->bullet_sprite_id, attackRec->UNIT_PARA_LEN);
290 attackInfo->dll_bullet_sprite_id = misc.atoi(attackRec->dll_bullet_sprite_id, attackRec->UNIT_PARA_LEN);
291 attackInfo->eqv_attack_next = misc.atoi(attackRec->eqv_attack_next, attackRec->UNIT_PARA_LEN);
292 attackInfo->min_power = misc.atoi(attackRec->min_power, attackRec->UNIT_PARA_LEN);
293 attackInfo->consume_power = misc.atoi(attackRec->consume_power, attackRec->UNIT_PARA_LEN);
294 attackInfo->fire_radius = misc.atoi(attackRec->fire_radius, attackRec->UNIT_PARA_LEN);
295 attackInfo->effect_id = misc.atoi(attackRec->effect_id, attackRec->UNIT_PARA_LEN);
296 }
297 }
298 //-------- End of function UnitRes::load_attack_info ---------//
299
300
301 //-------- Begin of function UnitRes::mobile_type_to_mask --------//
302
mobile_type_to_mask(int mobileType)303 char UnitRes::mobile_type_to_mask(int mobileType)
304 {
305 switch( mobileType)
306 {
307 case UNIT_LAND:
308 return 1;
309
310 case UNIT_SEA:
311 return 2;
312
313 case UNIT_AIR:
314 return 3;
315
316 default:
317 err_here();
318 return 0;
319 }
320 }
321 //-------- End of function UnitRes::mobile_type_to_mask --------//
322
323
324 //-------- Begin of function UnitInfo::is_loaded -------//
325
is_loaded()326 int UnitInfo::is_loaded()
327 {
328 return sprite_res[sprite_id]->is_loaded();
329 }
330 //--------- End of function UnitInfo::is_loaded --------//
331
332
333 //---- Begin of function UnitInfo::inc_nation_unit_count ----//
334
inc_nation_unit_count(int nationRecno)335 void UnitInfo::inc_nation_unit_count(int nationRecno)
336 {
337 err_when( nationRecno<1 || nationRecno>nation_array.size() );
338
339 nation_unit_count_array[nationRecno-1]++;
340
341 //------- increase the nation's unit count ---------//
342
343 Nation* nationPtr = nation_array[nationRecno];
344
345 nationPtr->total_unit_count++;
346
347 if( unit_class==UNIT_CLASS_WEAPON )
348 {
349 nationPtr->total_weapon_count++;
350 }
351 else if( unit_class==UNIT_CLASS_SHIP )
352 {
353 nationPtr->total_ship_count++;
354 }
355 else if( race_id )
356 {
357 nationPtr->total_human_count++;
358 }
359 }
360 //----- End of function UnitInfo::inc_nation_unit_count -----//
361
362
363 //---- Begin of function UnitInfo::dec_nation_unit_count ----//
364
dec_nation_unit_count(int nationRecno)365 void UnitInfo::dec_nation_unit_count(int nationRecno)
366 {
367 err_when( nationRecno<0 || nationRecno>MAX_NATION );
368
369 if( nationRecno )
370 {
371 nation_unit_count_array[nationRecno-1]--;
372
373 err_when( nation_unit_count_array[nationRecno-1] < 0 );
374
375 //------ decrease the nation's unit count -------//
376
377 Nation* nationPtr = nation_array[nationRecno];
378
379 nationPtr->total_unit_count--;
380
381 err_when( nationPtr->total_unit_count < 0 );
382
383 if( unit_class==UNIT_CLASS_WEAPON )
384 {
385 nationPtr->total_weapon_count--;
386
387 err_when( nationPtr->total_weapon_count < 0 );
388 }
389 else if( unit_class==UNIT_CLASS_SHIP )
390 {
391 nationPtr->total_ship_count--;
392
393 err_when( nationPtr->total_ship_count < 0 );
394 }
395 else if( race_id )
396 {
397 nationPtr->total_human_count--;
398
399 err_when( nationPtr->total_human_count < 0 );
400
401 if( nationPtr->total_human_count < 0 )
402 nationPtr->total_human_count = 0;
403 }
404 }
405 }
406 //----- End of function UnitInfo::dec_nation_unit_count -----//
407
408
409 //---- Begin of function UnitInfo::inc_nation_general_count ----//
410
inc_nation_general_count(int nationRecno)411 void UnitInfo::inc_nation_general_count(int nationRecno)
412 {
413 err_when( nationRecno<1 || nationRecno>nation_array.size() );
414
415 nation_general_count_array[nationRecno-1]++;
416
417 nation_array[nationRecno]->total_general_count++;
418 }
419 //----- End of function UnitInfo::inc_nation_general_count -----//
420
421
422 //---- Begin of function UnitInfo::dec_nation_general_count ----//
423
dec_nation_general_count(int nationRecno)424 void UnitInfo::dec_nation_general_count(int nationRecno)
425 {
426 err_when( nationRecno<0 || nationRecno>MAX_NATION );
427
428 if( nationRecno )
429 {
430 nation_general_count_array[nationRecno-1]--;
431
432 nation_array[nationRecno]->total_general_count--;
433
434 err_when( nation_general_count_array[nationRecno-1] < 0 );
435 }
436 }
437 //----- End of function UnitInfo::dec_nation_general_count -----//
438
439
440 //-------- Begin of function UnitInfo::unit_change_nation -------//
441 //
442 // Call this function when a unit changes its nation. This
443 // function updates the unit count vars in the UnitInfo.
444 //
445 // <int> newNationRecno - the new nation recno
446 // <int> oldNationRecno - the original nation recno
447 // <int> rankId - the rank of the unit.
448 //
unit_change_nation(int newNationRecno,int oldNationRecno,int rankId)449 void UnitInfo::unit_change_nation(int newNationRecno, int oldNationRecno, int rankId)
450 {
451 //---- update nation_unit_count_array[] ----//
452
453 if( oldNationRecno )
454 {
455 if( rankId != RANK_KING )
456 dec_nation_unit_count(oldNationRecno);
457
458 if( rankId == RANK_GENERAL )
459 dec_nation_general_count(oldNationRecno);
460 }
461
462 if( newNationRecno )
463 {
464 if( rankId != RANK_KING )
465 inc_nation_unit_count(newNationRecno);
466
467 if( rankId == RANK_GENERAL ) // if the new rank is general
468 inc_nation_general_count(newNationRecno);
469 }
470 }
471 //--------- End of function UnitInfo::unit_change_nation --------//
472
473 #ifdef DYNARRAY_DEBUG_ELEMENT_ACCESS
474
475 //-------- Begin of function UnitRes::get_attack_info -------//
476
get_attack_info(int attackId)477 AttackInfo* UnitRes::get_attack_info(int attackId)
478 {
479 if( attackId<1 || attackId>attack_info_count )
480 err.run( "UnitRes::get_attack_info[]" );
481
482 return attack_info_array+attackId-1;
483 }
484
485 //--------- End of function UnitRes::get_attack_info --------//
486
487
488 //-------- Begin of function UnitRes::operator[] -------//
489
operator [](int unitId)490 UnitInfo* UnitRes::operator[](int unitId)
491 {
492 if( unitId<1 || unitId>unit_info_count )
493 err.run( "UnitRes::operator[]" );
494
495 return unit_info_array+unitId-1;
496 }
497
498 //--------- End of function UnitRes::operator[] --------//
499
500 #endif
501
502 //-------- Begin of function UnitInfo::get_large_icon_ptr -------//
503
get_large_icon_ptr(char rankId)504 char *UnitInfo::get_large_icon_ptr(char rankId)
505 {
506 switch( rankId )
507 {
508 case RANK_KING:
509 return king_icon_ptr;
510 case RANK_GENERAL:
511 return general_icon_ptr;
512 case RANK_SOLDIER:
513 default:
514 return soldier_icon_ptr;
515 }
516 }
517 //-------- End of function UnitInfo::get_large_icon_ptr -------//
518
519 // ##### begin Gilbert 17/10 ########//
520 // -------- Begin of function UnitInfo::get_small_icon_ptr --------//
get_small_icon_ptr(char rankId)521 char *UnitInfo::get_small_icon_ptr(char rankId)
522 {
523 switch( rankId )
524 {
525 case RANK_KING:
526 return king_small_icon_ptr;
527 case RANK_GENERAL:
528 return general_small_icon_ptr;
529 case RANK_SOLDIER:
530 default:
531 return soldier_small_icon_ptr;
532 }
533 }
534 // -------- End of function UnitInfo::get_small_icon_ptr --------//
535 // ##### end Gilbert 17/10 ########//
536