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    : OUNIT.CPP
22 //Description : Object Unit
23 
24 #include <ALL.h>
25 #include <ODATE.h>
26 #include <OWORLD.h>
27 #include <OVGA.h>
28 #include <OSTR.h>
29 #include <ONEWS.h>
30 #include <OREBEL.h>
31 #include <OSPY.h>
32 #include <ONATION.h>
33 #include <OFONT.h>
34 #include <OBULLET.h>
35 #include <OGAME.h>
36 #include <OTOWN.h>
37 #include <ORACERES.h>
38 #include <ORAWRES.h>
39 #include <OPOWER.h>
40 #include <OU_VEHI.h>
41 #include <OU_MARI.h>
42 #include <OU_MONS.h>
43 #include <OF_CAMP.h>
44 #include <OF_MONS.h>
45 #include <OF_HARB.h>
46 #include <OMONSRES.h>
47 #include <OREMOTE.h>
48 #include <OSYS.h>
49 #include "gettext.h"
50 #include <ConfigAdv.h>
51 
52 #if(GAME_FRAMES_PER_DAY!=FRAMES_PER_DAY)
53 #error
54 #endif
55 
56 #ifdef NO_DEBUG_UNIT
57 #undef err_when
58 #undef err_here
59 #undef err_if
60 #undef err_else
61 #undef err_now
62 #define err_when(cond)
63 #define err_here()
64 #define err_if(cond)
65 #define err_else
66 #define err_now(msg)
67 #undef DEBUG
68 #endif
69 
70 //--------- Begin of function Unit::Unit ---------//
71 //
Unit()72 Unit::Unit()
73 {
74 	// ##### patch begin Gilbert 21/1 ######//
75    // unit_id = 0;
76 	memset( sizeof(Sprite) + (char *)this, 0, sizeof(Unit) - sizeof(Sprite));
77 	// ##### patch end Gilbert 21/1 ######//
78 }
79 //----------- End of function Unit::Unit -----------//
80 
81 
82 //--------- Begin of function Unit::~Unit ---------//
83 //
~Unit()84 Unit::~Unit()
85 {
86    deinit();
87 }
88 //----------- End of function Unit::~Unit -----------//
89 
90 
91 //--------- Begin of function Unit::init ---------//
92 //
93 // <int> unitId               - the id. of the unit
94 // <int> nationRecno          - the recno of nation
95 // [int] rankId               - rank id. of the unit (none for non-human unit)
96 // [int] unitLoyalty          - loyalty of the unit  (none for non-human unit)
97 // [int] startXLoc, startYLoc - the starting location of the unit
98 //                              (if startXLoc < 0, this is a unit for hire, and is not a unit of the game yet. init_sprite() won't be called for this unit)
99 //                              (default: -1, -1)
100 //
101 // Note: sprite_recno must be initialized first before calling Unit::init()
102 //
init(int unitId,int nationRecno,int rankId,int unitLoyalty,int startXLoc,int startYLoc)103 void Unit::init(int unitId, int nationRecno, int rankId, int unitLoyalty, int startXLoc, int startYLoc)
104 {
105    //------------ set basic vars -------------//
106 
107    nation_recno  = (char) nationRecno;
108    rank_id       = rankId;       // rank_id must be initialized before init_unit_id() as init_unit_id() may overwrite it
109    nation_contribution = 0;      // nation_contribution must be initialized before init_unit_id() as init_unit_id() may overwrite it
110 
111    if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
112    {
113       team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) );
114       team_info->member_count = 0;
115       team_info->ai_last_request_defense_date = 0;
116    }
117    else
118       team_info = NULL;
119 
120    init_unit_id(unitId);
121 
122 	group_select_id = 0;
123    unit_group_id = unit_array.cur_group_id++;
124    race_id       = (char) unit_res[unit_id]->race_id;
125 
126    //------- init unit name ---------//
127 
128    if( race_id )
129    {
130       name_id = race_res[race_id]->get_new_name_id();
131    }
132    else  //---- init non-human unit series no. ----//
133    {
134 		if( nation_recno )
135          name_id = ++nation_array[nation_recno]->last_unit_name_id_array[unit_id-1];
136       else
137          name_id = 0;
138    }
139 
140    //------- init ai_unit ----------//
141 
142    if( nation_recno )
143       ai_unit = nation_array[nation_recno]->nation_type == NATION_AI;
144    else
145       ai_unit = 0;
146 
147    err_when( unitLoyalty < 0 || unitLoyalty > 100 );
148 
149    //----------------------------------------------//
150 
151    ai_action_id = 0;
152    action_misc = ACTION_MISC_STOP;
153    action_misc_para = 0;
154 
155    action_mode2 = action_mode = ACTION_STOP;
156    action_para2 = action_para = 0;
157    action_x_loc2 = action_y_loc2 = action_x_loc = action_y_loc = -1;
158    memset(blocked_edge, 0, sizeof(char)*4);
159 
160    attack_range = 0; //store the attack range of the current attack mode if the unit is ordered to attack
161 
162 	leader_unit_recno= 0;
163    team_id          = 0;
164    selected_flag    = 0;
165 
166    waiting_term     = 0;
167    swapping         = 0;      // indicate whether swapping is processed.
168 
169    spy_recno = 0;
170 
171    range_attack_x_loc = -1;
172    range_attack_y_loc = -1;
173 
174    //------- initialize path seek vars -------//
175 
176    result_node_array = NULL;
177    result_node_count = result_node_recno = result_path_dist = 0;
178 
179 	//------- initialize way point vars -------//
180 	way_point_array	= NULL;
181 	way_point_array_size = 0;
182 	way_point_count	= 0;
183 
184    //---------- initialize game vars ----------//
185 
186    unit_mode      = 0;
187    unit_mode_para = 0;
188 
189    max_hit_points = unit_res[unit_id]->hit_points;
190    hit_points     = max_hit_points;
191 
192 	loyalty        = unitLoyalty;
193 
194 	can_guard_flag  = 0;
195 	can_attack_flag = 1;
196 	force_move_flag = 0;
197 	ai_no_suitable_action = 0;
198 	cur_power       = 0;
199 	max_power       = 0;
200 
201 	total_reward = 0;
202 
203 	home_camp_firm_recno = 0;
204 
205 	seek_path_fail_count = 0;
206 	ignore_power_nation  = 0;
207 	aggressive_mode = 1;			// the default mode is 1
208 
209 	err_when( loyalty<0 || loyalty>100 );
210 
211 	//--------- init skill potential ---------//
212 
213 	if( misc.random(10)==0 )		// 1 out of 10 has a higher than normal potential in this skill
214 	{
215 		skill.skill_potential = 50+misc.random(51);	 // 50 to 100 potential
216 	}
217 
218 	//------ initialize the base Sprite class -------//
219 
220    if( startXLoc >= 0 )
221       init_sprite( startXLoc, startYLoc );
222    else
223    {
224       cur_x = -1;
225    }
226 
227    //------------- set attack_dir ------------//
228 
229    attack_dir = final_dir;
230 
231    //-------------- update loyalty -------------//
232 
233 	update_loyalty();
234 
235    //--------------- init AI info -------------//
236 
237    if( ai_unit )
238    {
239       Nation* nationPtr = nation_array[nation_recno];
240 
241       if( rank_id==RANK_GENERAL || rank_id==RANK_KING )
242          nationPtr->add_general_info(sprite_recno);
243 
244 		switch( unit_res[unit_id]->unit_class )
245       {
246          case UNIT_CLASS_CARAVAN:
247             nationPtr->add_caravan_info(sprite_recno);
248             break;
249 
250          case UNIT_CLASS_SHIP:
251             nationPtr->add_ship_info(sprite_recno);
252 				break;
253       }
254    }
255 
256    //----------- init derived class ----------//
257 
258    init_derived();
259 }
260 //----------- End of function Unit::init -----------//
261 
262 
263 //--------- Begin of function Unit::init_unit_id ---------//
264 
init_unit_id(int unitId)265 void Unit::init_unit_id(int unitId)
266 {
267    unit_id = unitId;
268 
269    UnitInfo* unitInfo = unit_res[unit_id];
270 
271    sprite_id   = unitInfo->sprite_id;
272    sprite_info = sprite_res[sprite_id];
273 
274    mobile_type = unitInfo->mobile_type;
275 
276 	//--- if this unit is a weapon unit with multiple versions ---//
277 
278 	set_combat_level(100);     // set combat level default to 100, for human units, it will be adjusted later by individual functions
279 
280 	int techLevel;
281 	if( nation_recno &&
282 		 unitInfo->unit_class == UNIT_CLASS_WEAPON &&
283 		(techLevel=unitInfo->nation_tech_level_array[nation_recno-1]) > 0 )
284 	{
285 		set_weapon_version(techLevel);
286 	}
287 
288 	fix_attack_info();
289 
290    //-------- set unit count ----------//
291 
292    if( nation_recno )
293    {
294       if( rank_id != RANK_KING )
295          unitInfo->inc_nation_unit_count(nation_recno);
296 
297       if( rank_id == RANK_GENERAL )
298          unitInfo->inc_nation_general_count(nation_recno);
299    }
300 
301 	//--------- increase monster count ----------//
302 
303 	if( unit_res[unit_id]->unit_class == UNIT_CLASS_MONSTER )
304 		unit_res.mobile_monster_count++;
305 }
306 //----------- End of function Unit::init_unit_id -----------//
307 
308 
309 //--------- Begin of function Unit::deinit_unit_id ---------//
310 
deinit_unit_id()311 void Unit::deinit_unit_id()
312 {
313    if( sys.signal_exit_flag )
314       return;
315 
316    //-----------------------------------------//
317 
318    UnitInfo *unitInfo = unit_res[unit_id];
319 
320    if( nation_recno )
321    {
322       if( rank_id != RANK_KING )
323          unitInfo->dec_nation_unit_count(nation_recno);
324 
325       if( rank_id == RANK_GENERAL )
326          unitInfo->dec_nation_general_count(nation_recno);
327    }
328 
329    //--------- if the unit is a spy ----------//
330    //
331    // A spy has double identity and is counted
332    // by both the true controlling nation and
333    // the deceiving nation.
334    //
335    //-----------------------------------------//
336 
337    if( spy_recno && true_nation_recno() != nation_recno )
338    {
339       err_when( !race_id );
340 
341       int trueNationRecno = true_nation_recno();
342 
343       if( rank_id != RANK_KING )
344          unitInfo->dec_nation_unit_count(trueNationRecno);
345 
346       if( rank_id == RANK_GENERAL )
347          unitInfo->dec_nation_general_count(trueNationRecno);
348 	}
349 
350 	//--------- decrease monster count ----------//
351 
352 	if( unit_res[unit_id]->unit_class == UNIT_CLASS_MONSTER )
353 	{
354 		unit_res.mobile_monster_count--;
355 
356 		err_when( unit_res.mobile_monster_count < 0 );
357 	}
358 }
359 //----------- End of function Unit::deinit_unit_id -----------//
360 
361 
362 //--------- Begin of function Unit::set_spy ---------//
363 
set_spy(int spyRecno)364 void Unit::set_spy(int spyRecno)
365 {
366    spy_recno = spyRecno;
367 }
368 //---------- End of function Unit::set_spy ---------//
369 
370 
371 //--------- Begin of function Unit::init_sprite ---------//
372 //
373 // <int> startXLoc, startYLoc - the starting location of the unit
374 //
init_sprite(int startXLoc,int startYLoc)375 void Unit::init_sprite(int startXLoc, int startYLoc)
376 {
377    err_when( !world.get_loc(startXLoc, startYLoc)->can_move(unit_res[unit_id]->mobile_type) );
378    err_when(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP && (startXLoc%2 || startYLoc%2));
379 
380    Sprite::init(unit_res[unit_id]->sprite_id, startXLoc, startYLoc);
381 
382    //--------------------------------------------------------------------//
383    // move_to_?_loc is always the current location of the unit as
384    // cur_action == SPRITE_IDLE
385    //--------------------------------------------------------------------//
386 	original_action_mode = 0;
387 	ai_original_target_x_loc = -1;
388 
389 	attack_range = 0;
390 
391    move_to_x_loc = next_x_loc();
392    move_to_y_loc = next_y_loc();
393 
394    go_x = next_x;
395    go_y = next_y;
396 
397    //-------- set the cargo_recno -------------//
398 
399    char  w, h;
400    short x, y;
401 
402    err_if(!sprite_recno)      // sprite_recno must be initialized first before calling Unit::init()
403       err_here();
404 
405    for(h=0, y=startYLoc; h<sprite_info->loc_height; h++, y++)
406    {
407       for(w=0, x=startXLoc; w<sprite_info->loc_width; w++, x++)
408       {
409          err_if( world.get_unit_recno(x, y, mobile_type) )    // it must be 0 to put the sprite in this location
410             err_here();
411          world.set_unit_recno(x, y, mobile_type, sprite_recno);
412       }
413    }
414 
415    if( is_own() ||
416        (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
417    {
418       world.unveil(startXLoc, startYLoc, startXLoc+sprite_info->loc_width-1,
419                    startYLoc+sprite_info->loc_height-1 );
420 
421       world.visit(startXLoc, startYLoc, startXLoc+sprite_info->loc_width-1,
422          startYLoc+sprite_info->loc_height-1, unit_res[unit_id]->visual_range,
423          unit_res[unit_id]->visual_extend);
424    }
425 
426 	err_when(result_node_array || result_path_dist);
427 }
428 //----------- End of function Unit::init_sprite -----------//
429 
430 
431 //--------- Begin of function Unit::deinit ---------//
432 
deinit()433 void Unit::deinit()
434 {
435 	err_when( unit_array.is_truly_deleted(sprite_recno) );
436 
437    if( !unit_id )
438       return;
439 
440    //-------- if this is a king --------//
441 
442    if( !sys.signal_exit_flag && nation_recno )
443    {
444       if( rank_id == RANK_KING )    // check nation_recno because monster kings will die also.
445 		{
446          king_die();
447 			err_when( unit_array.is_truly_deleted(sprite_recno) );
448 		}
449       else if( rank_id == RANK_GENERAL )
450 		{
451          general_die();
452 			err_when( unit_array.is_truly_deleted(sprite_recno) );
453 		}
454    }
455 
456    //------------ free up team_info -----------//
457 
458    if( team_info )
459    {
460       mem_del(team_info);
461       team_info = NULL;
462    }
463 
464    //---- if this is a general, deinit its link with its soldiers ----//
465    //
466    // We do not use team_info because monsters and rebels also use
467 	// leader_unit_recno and they do not use keep the member info
468    // in team_info.
469    //
470    //-----------------------------------------------------------------//
471 
472    if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
473    {
474 		for( int i=unit_array.size() ; i>0 ; i-- )
475       {
476          if( unit_array.is_deleted(i) )
477             continue;
478 
479 			if( unit_array[i]->leader_unit_recno == sprite_recno )
480 				unit_array[i]->leader_unit_recno = 0;
481       }
482    }
483 
484    //----- if this is a unit on a ship ------//
485 
486 	if( unit_mode == UNIT_MODE_ON_SHIP )
487 	{
488 		if( !unit_array.is_deleted(unit_mode_para) )    // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all units onboard are killed and this function is called.
489 		{
490 			Unit* unitPtr = unit_array[unit_mode_para];
491 
492 			err_when( unit_res[unitPtr->unit_id]->unit_class != UNIT_CLASS_SHIP );
493 
494 			((UnitMarine*)unitPtr)->del_unit(sprite_recno);
495 		}
496 	}
497 
498 	//----- if this is a ship in the harbor -----//
499 
500 	else if( unit_mode == UNIT_MODE_IN_HARBOR )
501 	{
502 		if( !firm_array.is_deleted(unit_mode_para) )    // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all firms onboard are killed and this function is called.
503 		{
504 			Firm* firmPtr = firm_array[unit_mode_para];
505 
506 			err_when( firmPtr->firm_id != FIRM_HARBOR );
507 
508 			((FirmHarbor*)firmPtr)->del_hosted_ship(sprite_recno);
509 		}
510 	}
511 
512 	//----- if this unit is a constructor in a firm -------//
513 
514 	else if( unit_mode == UNIT_MODE_CONSTRUCT )
515 	{
516 		err_when( firm_array[unit_mode_para]->builder_recno != sprite_recno );
517 
518 		firm_array[unit_mode_para]->builder_recno = 0;
519 	}
520 
521    //-------- if this is a spy ---------//
522 
523    if( spy_recno )
524    {
525       spy_array.del_spy( spy_recno );
526 		spy_recno = 0;
527    }
528 
529    //---------- reset command ----------//
530 
531    if( power.command_unit_recno == sprite_recno )
532       power.reset_command();
533 
534    //-----------------------------------//
535 
536    deinit_unit_id();
537 
538    //-------- reset seek path ----------//
539 
540    reset_path();
541 
542    //----- if cur_x == -1, the unit has not yet been hired -----//
543 
544    if( cur_x >= 0 )
545       deinit_sprite();
546 
547    //------------------------------------------------//
548    //
549    // Prime rule:
550    //
551    // world.get_loc(next_x_loc() and next_y_loc())->cargo_recno
552    // is always = sprite_recno
553    //
554    // no matter what cur_action is.
555    //
556    //------------------------------------------------//
557    //
558    // Relationship between (next_x, next_y) and (cur_x, cur_y)
559    //
560    // when SPRITE_WAIT, SPRITE_IDLE, SPRITE_READY_TO_MOVE,
561    //      SPRITE_ATTACK, SPRITE_DIE:
562    //
563    // (next_x, next_y) == (cur_x, cur_y), it's the location of the sprite.
564    //
565    // when SPRITE_MOVE:
566    //
567    // (next_x, next_y) != (cur_x, cur_y)
568    // (next_x, next_y) is where the sprite is moving towards.
569    // (cur_x , cur_y ) is the location of the sprite.
570    //
571 	//------------------------------------------------//
572 
573 	//--------------- deinit AI info -------------//
574 
575    if( ai_unit )
576    {
577       if( !nation_array.is_deleted(nation_recno) )
578 		{
579          Nation* nationPtr = nation_array[nation_recno];
580 
581          if( rank_id==RANK_GENERAL || rank_id==RANK_KING )
582             nationPtr->del_general_info(sprite_recno);
583 
584          switch( unit_res[unit_id]->unit_class )
585          {
586             case UNIT_CLASS_CARAVAN:
587                nationPtr->del_caravan_info(sprite_recno);
588                break;
589 
590             case UNIT_CLASS_SHIP:
591                nationPtr->del_ship_info(sprite_recno);
592                break;
593          }
594       }
595    }
596 
597    //-------------- reset unit_id ---------------//
598 
599    unit_id = 0;
600 }
601 //----------- End of function Unit::deinit -----------//
602 
603 
604 //--------- Begin of function Unit::deinit_sprite ---------//
605 //
606 // [int] keepSelected - keep it selected if it is current selected.
607 //                      (default: 0)
608 //
deinit_sprite(int keepSelected)609 void Unit::deinit_sprite(int keepSelected)
610 {
611    err_when(result_node_array!=NULL);
612 
613    if( cur_x == -1 )
614       return;
615 
616    //---- if this unit is led by a leader, only mobile units has leader_unit_recno assigned to a leader -----//
617    // units are still considered mobile when boarding a ship
618 
619    if( leader_unit_recno && unit_mode != UNIT_MODE_ON_SHIP )
620    {
621       if( !unit_array.is_deleted(leader_unit_recno) )    // the leader unit may have been killed at the same time
622          unit_array[leader_unit_recno]->del_team_member(sprite_recno);
623 
624 		leader_unit_recno = 0;
625    }
626 
627    //-------- clear the cargo_recno ----------//
628 
629    short w, h;
630    short x, y;
631 
632    for(h=0, y=next_y_loc(); h<sprite_info->loc_height; h++, y++)
633    {
634       for(w=0, x=next_x_loc(); w<sprite_info->loc_width; w++, x++)
635       {
636          err_if( world.get_unit_recno(x, y, mobile_type) != sprite_recno )    // it must be 0 to put the sprite in this location
637             err_here();
638          world.set_unit_recno(x, y, mobile_type, 0);
639       }
640    }
641 
642    cur_x = -1;
643 
644    //---- reset other parameters related to this unit ----//
645 
646    if( !keepSelected )
647    {
648       if( unit_array.selected_recno == sprite_recno )
649 		{
650          unit_array.selected_recno = 0;
651          info.disp();
652       }
653 
654       if( power.command_unit_recno == sprite_recno )
655          power.command_id = 0;
656    }
657 
658 	//------- deinit unit mode -------//
659 
660 	deinit_unit_mode();
661 }
662 //----------- End of function Unit::deinit_sprite -----------//
663 
664 
665 //--------- Begin of function Unit::deinit_unit_mode ---------//
666 //
deinit_unit_mode()667 void Unit::deinit_unit_mode()
668 {
669 	if( sys.signal_exit_flag )
670 		return;
671 
672    //----- this unit was defending the town before it gets killed ----//
673 
674    if(unit_mode==UNIT_MODE_DEFEND_TOWN)
675    {
676       if(!town_array.is_deleted(unit_mode_para))
677       {
678          Town *townPtr = town_array[unit_mode_para];
679 
680          if(nation_recno == townPtr->nation_recno)
681             townPtr->reduce_defender_count();
682       }
683       set_mode(0);      // reset mode
684    }
685 
686    //----- this is a monster unit defending its town ------//
687 
688 	else if( unit_mode==UNIT_MODE_MONSTER && unit_mode_para )
689 	{
690 		if(((UnitMonster*)this)->monster_action_mode!=MONSTER_ACTION_DEFENSE)
691 			return;
692 
693 		FirmMonster* firmMonster = (FirmMonster*) firm_array[unit_mode_para];
694 
695 		err_when( firmMonster->firm_id != FIRM_MONSTER );
696 
697 		firmMonster->reduce_defender_count(rank_id);
698 	}
699 }
700 //----------- End of function Unit::deinit_unit_mode -----------//
701 
702 
703 //--------- Begin of function Unit::king_die ---------//
704 //
king_die()705 void Unit::king_die()
706 {
707    //--------- add news ---------//
708 
709    news_array.king_die(nation_recno);
710 
711    //--- see if the units, firms and towns of the nation are all destroyed ---//
712 
713    Nation* nationPtr = nation_array[nation_recno];
714 
715 	nationPtr->king_unit_recno = 0;
716 }
717 //----------- End of function Unit::king_die -----------//
718 
719 
720 //--------- Begin of function Unit::general_die ---------//
721 //
general_die()722 void Unit::general_die()
723 {
724    //--------- add news ---------//
725 
726    if( nation_recno == nation_array.player_recno )
727       news_array.general_die(sprite_recno);
728 }
729 //----------- End of function Unit::general_die -----------//
730 
731 
732 //--------- Begin of function Unit::unit_name ---------//
733 //
734 // [int] withTitle - whether return a string with the title of the unit
735 //                   or not. (default: 1)
736 //
unit_name(int withTitle)737 char* Unit::unit_name(int withTitle)
738 {
739    static String str;
740 
741    UnitInfo* unitInfo = unit_res[unit_id];
742 
743 	//------------------------------------//
744 
745    if( race_id )
746    {
747       str = "";
748 
749       if( withTitle )
750       {
751          if( unit_mode == UNIT_MODE_REBEL )
752          {
753             if( rank_id == RANK_GENERAL )
754             {
755                str = _("Rebel Leader");
756                str += " ";
757             }
758          }
759          else
760          {
761             if( rank_id == RANK_KING )
762             {
763                str = _("King");
764                str += " ";
765             }
766             else if( rank_id == RANK_GENERAL )
767             {
768                str = _("General");
769                str += " ";
770             }
771          }
772 		}
773 
774 		if( rank_id == RANK_KING )		// use the player name
775 			str += nation_array[nation_recno]->king_name();
776 		else
777 			str += race_res[race_id]->get_name(name_id);
778    }
779    else
780    {
781       str = _(unitInfo->name);
782 
783       //--- for weapons, the rank_id is used to store the version of the weapon ---//
784 
785       if( unitInfo->unit_class == UNIT_CLASS_WEAPON && get_weapon_version() > 1 )
786 		{
787 			str += " ";
788 			str += misc.roman_number(get_weapon_version());
789 		}
790 
791 		if( unitInfo->unit_class != UNIT_CLASS_GOD )		// God doesn't have any series no.
792 		{
793 			str += " ";
794 			str += name_id;      // name id is the series no. of the unit
795 		}
796    }
797 
798    return str;
799 }
800 //----------- End of function Unit::unit_name ---------//
801 
802 
803 //--------- Begin of function Unit::set_name ---------//
804 //
805 // Set the name id. of this unit.
806 //
set_name(uint16_t newNameId)807 void Unit::set_name(uint16_t newNameId)
808 {
809    //------- free up the existing name id. ------//
810 
811    race_res[race_id]->free_name_id(name_id);
812 
813    //------- set the new name id. ---------//
814 
815    name_id = newNameId;
816 
817    //-------- register usage of the new name id. ------//
818 
819    race_res[race_id]->use_name_id(name_id);
820 }
821 //----------- End of function Unit::set_name ---------//
822 
823 
824 //--------- Begin of function Unit::is_own ---------//
825 //
is_own()826 int Unit::is_own()
827 {
828    return is_nation(nation_array.player_recno);
829 }
830 //----------- End of function Unit::is_own ---------//
831 
832 
833 //--------- Begin of function Unit::is_own_spy ---------//
834 //
is_own_spy()835 int Unit::is_own_spy()
836 {
837    return spy_recno && spy_array[spy_recno]->true_nation_recno == nation_array.player_recno;
838 }
839 //----------- End of function Unit::is_own_spy ---------//
840 
841 
842 //--------- Begin of function Unit::is_nation ---------//
843 //
844 // Whether the unit belongs to the specific nation.
845 //
is_nation(int nationRecno)846 int Unit::is_nation(int nationRecno)
847 {
848    if( nation_recno == nationRecno )
849       return 1;
850 
851    if( spy_recno && spy_array[spy_recno]->true_nation_recno == nationRecno )
852       return 1;
853 
854    return 0;
855 }
856 //----------- End of function Unit::is_nation ---------//
857 
858 
859 //--------- Begin of function Unit::is_civilian ---------//
860 //
is_civilian()861 int Unit::is_civilian()
862 {
863 	return race_id>0 && skill.skill_id != SKILL_LEADING &&
864 			 unit_mode != UNIT_MODE_REBEL;
865 }
866 //----------- End of function Unit::is_civilian ---------//
867 
868 
869 //--------- Begin of function Unit::true_nation_recno ---------//
870 //
871 // The true nation recno of the unit, taking care of the
872 // situation where the unit is a spy.
873 //
true_nation_recno()874 int Unit::true_nation_recno()
875 {
876    if( spy_recno )
877       return spy_array[spy_recno]->true_nation_recno;
878    else
879       return nation_recno;
880 }
881 //----------- End of function Unit::true_nation_recno ---------//
882 
883 
884 //--------- Begin of function Unit::next_day ---------//
885 //
next_day()886 void Unit::next_day()
887 {
888 	int unitRecno = sprite_recno;
889 
890    err_when( unit_array.is_deleted(unitRecno) );
891 
892 	err_when( race_id && !is_visible() && unit_mode==0 );
893 
894 	#ifdef DEBUG
895 
896 	if( unit_mode == UNIT_MODE_UNDER_TRAINING )
897 	{
898 		Town* townPtr =town_array[unit_mode_para];
899 
900 		err_when( townPtr->train_unit_recno != sprite_recno );
901 		err_when( townPtr->nation_recno     != nation_recno );
902 	}
903 
904 	#endif
905 
906    //------- functions for non-independent nations only ------//
907 
908    if( nation_recno )
909    {
910       pay_expense();
911 
912 		if( unit_array.is_deleted(unitRecno) )		// if its hit points go down to 0, is_deleted() will return 1.
913 			return;
914 
915 		//------- update loyalty -------------//
916 
917 		if( info.game_date%30 == sprite_recno%30 )
918 		{
919 			update_loyalty();
920 		   err_when( unit_array.is_deleted(unitRecno) );
921 		}
922 
923 		//------- think about rebeling -------------//
924 
925 		if( info.game_date%15 == sprite_recno%15 )
926 		{
927 			if( think_betray() )
928 				return;
929 		}
930 	}
931 
932 	//------- recover from damage -------//
933 
934 	if( info.game_date%15 == sprite_recno%15 )   // recover one point per two weeks
935 	{
936 		process_recover();
937 	   err_when( unit_array.is_deleted(unitRecno) );
938 	}
939 
940    //------- restore cur_power --------//
941 
942    cur_power += 5;
943 
944 	if( cur_power > max_power)
945       cur_power = max_power;
946 
947    //------- king undie flag (for testing games only) --------//
948 
949    if( config.king_undie_flag && rank_id == RANK_KING &&
950        nation_recno && !nation_array[nation_recno]->is_ai() )
951    {
952 		hit_points = max_hit_points;
953 	}
954 
955 	//-------- if aggresive_mode is 1 --------//
956 
957 	if( nation_recno && is_visible() )
958 		think_aggressive_action();
959 
960 	//---------- debug ------------//
961 
962 #ifdef DEBUG
963    err_when( unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN && race_id );
964 
965    if( spy_recno )
966    {
967       err_when( spy_array.is_deleted(spy_recno) );
968 
969 		Spy* spyPtr = spy_array[spy_recno];
970 
971 		err_when( nation_recno != spyPtr->cloaked_nation_recno );
972 
973 		if( unit_mode == UNIT_MODE_OVERSEE )
974 		{
975 			err_when( spyPtr->spy_place != SPY_FIRM );
976 			err_when( spyPtr->spy_place_para != unit_mode_para );
977 		}
978 		else
979 		{
980 			err_when( spyPtr->spy_place != SPY_MOBILE );
981 			err_when( spyPtr->spy_place_para != sprite_recno );
982 		}
983    }
984 
985    if( leader_unit_recno )
986    {
987       Unit* unitPtr = unit_array[leader_unit_recno];
988 
989 		err_when( unitPtr->rank_id != RANK_GENERAL && unitPtr->rank_id != RANK_KING );
990 	}
991 
992 	err_when( (rank_id == RANK_GENERAL || rank_id == RANK_KING) &&
993 				 !team_info );
994 
995 	if( leader_unit_recno )
996 	{
997 		err_when( unit_array.is_truly_deleted(leader_unit_recno) );
998 		err_when( unit_array[leader_unit_recno]->nation_recno != nation_recno );
999 //		err_when( unit_array[leader_unit_recno]->team_id != team_id );
1000 	}
1001 
1002 	err_when( hit_points > max_hit_points );
1003 	err_when( max_hit_points == 0 );
1004 
1005    err_when( skill.combat_level<=0 );
1006 	err_when( skill.combat_level>100 );
1007 
1008 	err_when( unit_mode==UNIT_MODE_REBEL && spy_recno );			// no rebel spies
1009 	err_when( unit_mode==UNIT_MODE_REBEL && nation_recno );		// all rebels must be independent units
1010 
1011 	err_when( unit_mode==UNIT_MODE_DEFEND_TOWN && spy_recno );			// no rebel spies
1012 
1013 	err_when( loyalty < 0 || loyalty > 100 );
1014 
1015 	err_when( skill.skill_id == SKILL_SPYING );		// skill.skill_id should never be SKILL_SPYING, it will be shown in spy_recno if it's a spy
1016 
1017 	err_when( nation_contribution < 0 );
1018 	err_when( nation_contribution > MAX_NATION_CONTRIBUTION );
1019 
1020 	err_when( ai_unit && ( !nation_recno || !nation_array[nation_recno]->is_ai() ) );
1021 
1022 #else		// fix bug on fly in the release version
1023 
1024 	if( skill.combat_level > 100 )
1025 		skill.combat_level = 100;
1026 
1027 #endif
1028 }
1029 //----------- End of function Unit::next_day -----------//
1030 
1031 
1032 //--------- Begin of function Unit::process_recover ---------//
1033 //
process_recover()1034 void Unit::process_recover()
1035 {
1036 	if( hit_points==0 || hit_points == max_hit_points )      // this unit is dead already
1037 		return;
1038 
1039 	err_when( hit_points > max_hit_points );
1040 
1041 	//---- overseers in firms and ships in harbors recover faster ----//
1042 
1043    int hitPointsInc;
1044 
1045    if( unit_mode == UNIT_MODE_OVERSEE ||
1046        unit_mode == UNIT_MODE_IN_HARBOR )
1047    {
1048       hitPointsInc = 2;
1049    }
1050 
1051    //------ for units on ships --------//
1052 
1053 	else if( unit_mode == UNIT_MODE_ON_SHIP )
1054 	{
1055       //--- if the ship where the unit is on is in the harbor, the unit recovers faster ---//
1056 
1057       if( unit_array[unit_mode_para]->unit_mode == UNIT_MODE_IN_HARBOR )
1058          hitPointsInc = 2;
1059       else
1060          hitPointsInc = 1;
1061    }
1062 
1063    //----- only recover when the unit is not moving -----//
1064 
1065    else if( cur_action == SPRITE_IDLE )
1066    {
1067       hitPointsInc = 1;
1068    }
1069    else
1070       return;
1071 
1072    //---------- recover now -----------//
1073 
1074    hit_points += hitPointsInc;
1075 
1076    if( hit_points > max_hit_points )
1077       hit_points = max_hit_points;
1078 }
1079 //----------- End of function Unit::process_recover -----------//
1080 
1081 
1082 //--------- Begin of function Unit::update_loyalty ---------//
1083 //
1084 // How loyalty of units are updated:
1085 //
1086 // General: in a military camp - updated in FirmCamp::update_loyalty()
1087 //          mobile - no update
1088 //
1089 // Soldiers led by a general: in a military camp - updated in FirmCamp::update_loyalty()
1090 //                            mobile - updated here
1091 //
1092 // Other units: no update.
1093 //
update_loyalty()1094 void Unit::update_loyalty()
1095 {
1096    if( !nation_recno || rank_id==RANK_KING || !unit_res[unit_id]->race_id )
1097 		return;
1098 
1099 	if( unit_mode == UNIT_MODE_CONSTRUCT )		// constructor worker will not change their loyalty when they are in a building
1100 		return;
1101 
1102 // The following never really worked that well, since it created a dead give away due to the constant loyalty.
1103 #ifdef EASY_SPY_DETECTION
1104 	//----- if this unit is a spy, set its fake loyalty ------//
1105 
1106    if( spy_recno )      // a spy's loyalty is always >= 70
1107    {
1108       if( loyalty < 70 )
1109          loyalty = 70+misc.random(20);    // initialize it to be a number between 70 and 90
1110 
1111       target_loyalty = loyalty;
1112       return;
1113    }
1114 #endif
1115 
1116 	//-------- if this is a general ---------//
1117 
1118 	Nation* ownNation = nation_array[nation_recno];
1119 	int 	  rc=0;
1120 
1121 	if( rank_id==RANK_GENERAL )
1122 	{
1123 		//----- the general's power affect his loyalty ----//
1124 
1125 		int targetLoyalty = commander_power();
1126 
1127 		//----- the king's race affects the general's loyalty ----//
1128 
1129 		if( ownNation->race_id == race_id )
1130 			targetLoyalty += 20;
1131 
1132 		//----- the kingdom's reputation affects the general's loyalty ----//
1133 
1134 		targetLoyalty += (int)ownNation->reputation/4;
1135 
1136 		//--- the king's leadership also affect the general's loyalty -----//
1137 
1138 		if( ownNation->king_unit_recno )
1139 			targetLoyalty += unit_array[ownNation->king_unit_recno]->skill.skill_level / 4;
1140 
1141 		//-- if the unit is rewarded less than the amount of contribution he made, he will become unhappy --//
1142 
1143 		if( nation_contribution > total_reward*2 )
1144 		{
1145 			int decLoyalty = (nation_contribution - total_reward*2)/2;
1146 			targetLoyalty -= MIN(50, decLoyalty);		// this affect 50 points at maximum
1147 		}
1148 
1149 		targetLoyalty = MIN( targetLoyalty, 100 );
1150 		target_loyalty = MAX( targetLoyalty, 0 );
1151 	}
1152 
1153 	//-------- if this is a soldier ---------//
1154 
1155 	else if( rank_id==RANK_SOLDIER )
1156 	{
1157 		int leader_bonus = config_adv.unit_loyalty_require_local_leader ?
1158 			is_leader_in_range() : leader_unit_recno;
1159 		if( leader_bonus )
1160 		{
1161 			//----------------------------------------//
1162 			//
1163 			// If this soldier is led by a general,
1164 			// the targeted loyalty
1165 			//
1166 			// = race friendliness between the unit and the general / 2
1167 			//   + the leader unit's leadership / 2
1168 			//
1169 			//----------------------------------------//
1170 
1171 			Unit* leaderUnit = unit_array[leader_unit_recno];
1172 
1173 			int targetLoyalty = 30 + leaderUnit->skill.get_skill(SKILL_LEADING);
1174 
1175 			//---------------------------------------------------//
1176 			//
1177 			// Soldiers with higher combat and leadership skill
1178 			// will get discontented if they are led by a general
1179 			// with low leadership.
1180 			//
1181 			//---------------------------------------------------//
1182 
1183 			targetLoyalty -= skill.combat_level/2;
1184 			targetLoyalty -= skill.skill_level;
1185 
1186 			if( leaderUnit->rank_id == RANK_KING )
1187 				targetLoyalty += 20;
1188 
1189 			if( race_res.is_same_race(race_id, leaderUnit->race_id) )
1190 				targetLoyalty += 20;
1191 
1192 			if( targetLoyalty < 0 )
1193 				targetLoyalty = 0;
1194 
1195 			targetLoyalty = MIN( targetLoyalty, 100 );
1196 			target_loyalty = MAX( targetLoyalty, 0 );
1197 		}
1198 		else
1199 		{
1200 			target_loyalty = 0;
1201 		}
1202 	}
1203 
1204 	//--------- update loyalty ---------//
1205 
1206 	err_when( target_loyalty < 0 || target_loyalty > 100 );
1207 
1208 	if( target_loyalty > loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
1209 	{
1210 		int incValue = (target_loyalty - loyalty)/10;
1211 
1212 		int newLoyalty = (int) loyalty + MAX(1, incValue);
1213 
1214 		if( newLoyalty > target_loyalty )
1215 			newLoyalty = target_loyalty;
1216 
1217 		loyalty = newLoyalty;
1218 	}
1219 	else if( target_loyalty < loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
1220 	{
1221 		loyalty--;
1222 	}
1223 
1224 	err_when( loyalty < 0 || loyalty > 100 );
1225 }
1226 //-------- End of function Unit::update_loyalty -----------//
1227 
1228 
1229 //--------- Begin of function Unit::commander_power ---------//
1230 //
1231 // A commander's power is determined:
1232 //
1233 // -Population of the towns he controls
1234 // -The employment rate of the towns he controls, the higher the
1235 //  employment rate, the higher his power is
1236 // -If there are any other commanders controls the towns at the same time.
1237 // -the no. of soldiers led by the commander and their combat levels.
1238 //
commander_power()1239 int Unit::commander_power()
1240 {
1241 	//---- if the commander is in a military camp -----//
1242 
1243 	int commanderPower=0;
1244 
1245 	if( unit_mode == UNIT_MODE_OVERSEE )
1246 	{
1247 		Firm* firmPtr = firm_array[unit_mode_para];
1248 
1249 		if( firmPtr->firm_id == FIRM_CAMP )
1250 		{
1251 			Town* townPtr;
1252 
1253 			for( int i=firmPtr->linked_town_count-1 ; i>=0 ; i-- )
1254 			{
1255 				if( firmPtr->linked_town_enable_array[i] == LINK_EE )
1256 				{
1257 					townPtr = town_array[firmPtr->linked_town_array[i]];
1258 
1259 					commanderPower += townPtr->population / townPtr->linked_active_camp_count();
1260 				}
1261 			}
1262 
1263 			commanderPower += firmPtr->worker_count*3;		// 0 to 24
1264 		}
1265 		else if( firmPtr->firm_id == FIRM_BASE )
1266 		{
1267 			commanderPower = 60;
1268 		}
1269 	}
1270 	else
1271 	{
1272 		commanderPower = team_info->member_count*3;		// 0 to 24
1273 	}
1274 
1275 	return commanderPower;
1276 }
1277 //----------- End of function Unit::commander_power -----------//
1278 
1279 
1280 //--------- Begin of function Unit::think_betray ---------//
1281 //
think_betray()1282 int Unit::think_betray()
1283 {
1284 	int unitRecno = sprite_recno;
1285 
1286    err_when( unit_array.is_deleted(unitRecno) );
1287 
1288 	if( spy_recno )			// spies do not betray here, spy has its own functions for betrayal
1289 		return 0;
1290 
1291 	//----- if the unit is in training or is constructing a building, do not rebel -------//
1292 
1293 	if( !is_visible() && unit_mode != UNIT_MODE_OVERSEE )
1294 		return 0;
1295 
1296 	if( loyalty >= UNIT_BETRAY_LOYALTY )      // you when unit is
1297 		return 0;
1298 
1299 	if( !unit_res[unit_id]->race_id || !nation_recno ||
1300 		 rank_id==RANK_KING || spy_recno )
1301 	{
1302 		return 0;
1303 	}
1304 
1305 	err_when(unit_res[unit_id]->unit_class == UNIT_CLASS_GOD);
1306 	err_when(unit_id==UNIT_CARAVAN);
1307 
1308 	//------ turn towards other nation --------//
1309 
1310 	int    i, bestNationRecno=0, nationScore, bestScore=loyalty;      // the score must be larger than the current loyalty
1311 	Nation *curNation, *nationPtr;
1312 	int	 unitRegionId = region_id();
1313 
1314 	if( loyalty==0 )        // if the loyalty is 0, it will definitely betray
1315 		bestScore = -100;
1316 
1317 	curNation = nation_array[nation_recno];
1318 
1319 	for( i=nation_array.size() ; i>0 ; i-- )
1320 	{
1321 		if( nation_array.is_deleted(i) )
1322 			continue;
1323 
1324 		if( !curNation->get_relation(i)->has_contact || i==nation_recno )
1325 			continue;
1326 
1327 		nationPtr = nation_array[i];
1328 
1329 		//--- only if the nation has a base town in the region where the unit stands ---//
1330 
1331 		if( !region_array.nation_has_base_town(unitRegionId, i) )
1332 			continue;
1333 
1334 		//------------------------------------------------//
1335 
1336 		nationScore = (int) nationPtr->reputation
1337 						  + (nationPtr->overall_rating - curNation->overall_rating);
1338 
1339 		if( race_res.is_same_race(nationPtr->race_id, race_id) )
1340 			nationScore += 30;
1341 
1342 		if( nationScore > bestScore )
1343 		{
1344 			bestScore       = nationScore;
1345 			bestNationRecno = i;
1346 		}
1347 	}
1348 
1349 	err_when( unit_array.is_deleted(unitRecno) );
1350 
1351 	if( bestNationRecno )
1352 	{
1353 		return betray(bestNationRecno);
1354 	}
1355 	else if( loyalty==0 )
1356 	{
1357 		//----------------------------------------------//
1358 		// If there is no good nation to turn towards to and
1359 		// the loyalty has dropped to 0, resign itself and
1360 		// leave the nation.
1361 		//
1362 		// However, if the unit is spy, it will stay with the
1363 		// nation as it has never been really loyal to the nation.
1364 		//---------------------------------------------//
1365 
1366 		if( rank_id != RANK_KING && is_visible() &&
1367 			 !spy_recno )
1368 		{
1369 			resign(COMMAND_AUTO);
1370 			return 1;
1371 		}
1372 	}
1373 
1374 	return 0;
1375 }
1376 //-------- End of function Unit::think_betray -----------//
1377 
1378 
1379 //--------- Begin of function Unit::betray ---------//
1380 //
1381 // If this unit is a spy, this function betray() will be
1382 // called by Unit::spy_change_nation() or Firm::capture_firm().
1383 //
1384 // If this is not a spy, this function will only be called
1385 // by think_betray() and other nation deinit functions.
1386 //
betray(int newNationRecno)1387 int Unit::betray(int newNationRecno)
1388 {
1389 	int unitRecno = sprite_recno;
1390 
1391 	//### begin alex 18/3 ###//
1392 	//err_when( unit_array.is_deleted(unitRecno) );
1393 	err_when( unit_array.is_truly_deleted(unitRecno) );
1394 	//#### end alex 18/3 ####//
1395 
1396 	err_when( rank_id == RANK_KING );
1397 
1398 	if( nation_recno == newNationRecno )
1399 		return 0;
1400 
1401 	if( unit_mode == UNIT_MODE_CONSTRUCT ||	 // don't change nation when the unit is constructing a firm
1402 		 unit_mode == UNIT_MODE_ON_SHIP   )  	// don't change nation when the unit is constructing a firm
1403 	{
1404 		return 0;
1405 	}
1406 
1407 	//---------- add news -----------//
1408 
1409 	if( nation_recno == nation_array.player_recno ||
1410 		 newNationRecno == nation_array.player_recno )
1411 	{
1412 		//--- if this is a spy, don't display news message for betrayal as it is already displayed in Unit::spy_change_nation() ---//
1413 
1414 		if( !spy_recno )
1415 			news_array.unit_betray(sprite_recno, newNationRecno);
1416 	}
1417 
1418 	//------ change nation now ------//
1419 
1420 	//### begin alex 18/3 ###//
1421 	//err_when( unit_array.is_deleted(unitRecno) );
1422 	err_when( unit_array.is_truly_deleted(unitRecno) );
1423 	//#### end alex 18/3 ####//
1424 
1425 	change_nation(newNationRecno);
1426 
1427 	//### begin alex 18/3 ###//
1428 	//err_when( unit_array.is_deleted(unitRecno) );
1429 	err_when( unit_array.is_truly_deleted(unitRecno) );
1430 	//#### end alex 18/3 ####//
1431 
1432 	//-------- set the loyalty of the unit -------//
1433 
1434 	if( nation_recno )
1435 	{
1436 		Nation* nationPtr = nation_array[nation_recno];
1437 
1438 		loyalty = UNIT_BETRAY_LOYALTY + misc.random(5);
1439 
1440 		if( nationPtr->reputation > 0 )
1441 			change_loyalty( (int) nationPtr->reputation );
1442 
1443 		if( race_res.is_same_race( nationPtr->race_id, race_id ) )
1444 			change_loyalty( 30 );
1445 
1446 		err_when( loyalty < 0 || loyalty > 100 );
1447 
1448 		update_loyalty();		// update target loyalty
1449 	}
1450 	else  //------ if change to independent rebel -------//
1451 	{
1452 		loyalty = 0;      // no loyalty needed
1453 	}
1454 
1455 	//--- if this unit is a general, change nation for the units he commands ---//
1456 
1457 	uint32_t newTeamId = unit_array.cur_team_id++;
1458 
1459 	if( rank_id==RANK_GENERAL )
1460 	{
1461 		Unit* unitPtr;
1462 		int   i, nationReputation = (int) nation_array[nation_recno]->reputation;
1463 
1464 		for( i=unit_array.size() ; i>0 ; i-- )
1465 		{
1466 			if( unit_array.is_deleted(i) )
1467 				continue;
1468 
1469 			unitPtr = unit_array[i];
1470 
1471 			//---- capture the troop this general commands -----//
1472 
1473 			if( unitPtr->leader_unit_recno == sprite_recno &&
1474 				 unitPtr->rank_id == RANK_SOLDIER && unitPtr->is_visible() )
1475 			{
1476 				if( unitPtr->spy_recno )		// if the unit is a spy
1477 					unitPtr->spy_change_nation(newNationRecno, COMMAND_AUTO, 1); // 1-group defection of this unit, allowing us to hande the change of nation
1478 
1479 				unitPtr->change_nation(newNationRecno);
1480 
1481 				unitPtr->team_id = newTeamId; // assign new team_id or checking for nation_recno
1482 			}
1483 		}
1484 	}
1485 
1486 	team_id = newTeamId;
1487 
1488 	//### begin alex 18/3 ###//
1489 	//err_when( unit_array.is_deleted(unitRecno) );
1490 	err_when( unit_array.is_truly_deleted(unitRecno) );
1491 	//#### end alex 18/3 ####//
1492 
1493 	//------ go to meet the new master -------//
1494 
1495 	if( is_visible() && nation_recno )
1496 	{
1497 		if( !spy_recno || spy_array[spy_recno]->notify_cloaked_nation_flag )
1498 		{
1499 			if( rank_id == RANK_GENERAL )		// generals shouldn't automatically be assigned to camps, they should just move near your villages
1500 				ai_move_to_nearby_town();
1501 			else
1502 				think_normal_human_action();		// this is an AI function in OUNITAI.CPP
1503 		}
1504 	}
1505 
1506 	//### begin alex 18/3 ###//
1507 	//err_when( unit_array.is_deleted(unitRecno) );
1508 	err_when( unit_array.is_truly_deleted(unitRecno) );
1509 	//#### end alex 18/3 ####//
1510 
1511 	return 1;
1512 }
1513 //-------- End of function Unit::betray -----------//
1514 
1515 
1516 //--------- Begin of function Unit::change_nation ---------//
1517 //
1518 // This function is called when a unit change nation.
1519 // It is not necessarily a result of betray, when a spy
1520 // hands over his new nation to his parent nation, this
1521 // function will also be called.
1522 //
1523 // <int> newNationRecno - change the nation of the unit.
1524 //
change_nation(int newNationRecno)1525 void Unit::change_nation(int newNationRecno)
1526 {
1527 	err_when( newNationRecno && nation_array.is_deleted(newNationRecno) );
1528 	err_when( unit_mode == UNIT_MODE_REBEL );		// rebels do not change nation
1529 
1530 	//---------------------------------//
1531 
1532 	int oldAiUnit = ai_unit;
1533 	int oldNationRecno = nation_recno;
1534 
1535 	group_select_id = 0; // clear group select id
1536 	if(way_point_count)
1537 		reset_way_point_array();
1538 
1539 	//-- if the player is giving a command to this unit, cancel the command --//
1540 
1541    if( nation_recno == nation_array.player_recno &&
1542 		 sprite_recno == unit_array.selected_recno &&
1543 		 power.command_id )
1544    {
1545 		power.command_id = 0;
1546    }
1547 
1548 	//---------- stop all action to attack this unit ------------//
1549 
1550 	unit_array.stop_attack_unit(sprite_recno);
1551 
1552 	//---- update nation_unit_count_array[] ----//
1553 
1554 	unit_res[unit_id]->unit_change_nation(newNationRecno, nation_recno, rank_id);
1555 
1556 	//------- if the nation has an AI action -------//
1557 
1558 	stop2();       // clear the existing order
1559 
1560 	//---------------- update vars ----------------//
1561 
1562 	unit_group_id = unit_array.cur_group_id++;      // separate from the current group
1563 	nation_recno  = newNationRecno;
1564 
1565 	home_camp_firm_recno  = 0;					// reset it
1566 	original_action_mode  = 0;
1567 
1568 	if( race_id )
1569 	{
1570 		nation_contribution = 0;            // contribution to the nation
1571 		total_reward        = 0;
1572 	}
1573 
1574 	//-------- if change to one of the existing nations ------//
1575 
1576 	ai_unit = nation_recno && nation_array[nation_recno]->is_ai();
1577 
1578 	//------------ update AI info --------------//
1579 
1580 	if( oldAiUnit )
1581 	{
1582 		Nation* nationPtr = nation_array[oldNationRecno];
1583 
1584 		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
1585 			nationPtr->del_general_info(sprite_recno);
1586 
1587 		else if( unit_res[unit_id]->unit_class == UNIT_CLASS_CARAVAN )
1588 			nationPtr->del_caravan_info(sprite_recno);
1589 
1590 		else if( unit_res[unit_id]->unit_class == UNIT_CLASS_SHIP )
1591 			nationPtr->del_ship_info(sprite_recno);
1592 	}
1593 
1594 	if( ai_unit && nation_recno != 0 )
1595 	{
1596 		Nation* nationPtr = nation_array[nation_recno];
1597 
1598 		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
1599 			nationPtr->add_general_info(sprite_recno);
1600 
1601 		else if( unit_res[unit_id]->unit_class == UNIT_CLASS_CARAVAN )
1602 			nationPtr->add_caravan_info(sprite_recno);
1603 
1604 		else if( unit_res[unit_id]->unit_class == UNIT_CLASS_SHIP )
1605 			nationPtr->add_ship_info(sprite_recno);
1606 	}
1607 
1608 	//------ if this unit oversees a firm -----//
1609 
1610 	if( unit_mode==UNIT_MODE_OVERSEE )
1611 		firm_array[unit_mode_para]->change_nation(newNationRecno);
1612 
1613 	//----- this unit was defending the town before it gets killed ----//
1614 
1615 	else if( unit_mode==UNIT_MODE_DEFEND_TOWN )
1616 	{
1617 		if( !town_array.is_deleted(unit_mode_para) )
1618 			town_array[unit_mode_para]->reduce_defender_count();
1619 
1620 		set_mode(0);   // reset unit mode
1621 	}
1622 
1623 	//---- if the unit is no longer the same nation as the leader ----//
1624 
1625 	if( leader_unit_recno )
1626 	{
1627 		Unit* leaderUnit = unit_array[leader_unit_recno];
1628 
1629 		if( leaderUnit->nation_recno != nation_recno )
1630 		{
1631 			leaderUnit->del_team_member(sprite_recno);
1632 			leader_unit_recno = 0;
1633 			team_id = 0;
1634 		}
1635 	}
1636 
1637 	//------ if it is currently selected -------//
1638 
1639 	if( selected_flag )
1640 		info.disp();
1641 }
1642 //----------- End of function Unit::change_nation -----------//
1643 
1644 
1645 //--------- Begin of function Unit::pay_expense ---------//
1646 //
pay_expense()1647 void Unit::pay_expense()
1648 {
1649    if( game.game_mode == GAME_TEST )      // no deduction in testing game
1650       return;
1651 
1652    if( !nation_recno )
1653       return;
1654 
1655    //--- if it's a mobile spy or the spy is in its own firm, no need to pay salary here as Spy::pay_expense() will do that ---//
1656    //
1657    // -If your spies are mobile:
1658    //  >your nation pays them 1 food and $5 dollars per month
1659    //
1660    // -If your spies are in an enemy's town or firm:
1661    //  >the enemy pays them 1 food and the normal salary of their jobs.
1662    //
1663    //  >your nation pays them $5 dollars per month. (your nation pays them no food)
1664    //
1665    // -If your spies are in your own town or firm:
1666    //  >your nation pays them 1 food and $5 dollars per month
1667    //
1668    //------------------------------------------------------//
1669 
1670    if( spy_recno )
1671    {
1672       if( is_visible() )      // the cost will be deducted in spy_array
1673          return;
1674 
1675       if( unit_mode == UNIT_MODE_OVERSEE &&
1676           firm_array[unit_mode_para]->nation_recno == true_nation_recno() )
1677       {
1678          return;
1679       }
1680    }
1681 
1682    //---------- if it's a human unit -----------//
1683    //
1684    // The unit is paid even during its training period in a town
1685    //
1686    //-------------------------------------------//
1687 
1688    Nation* nationPtr = nation_array[nation_recno];
1689 
1690    if( unit_res[unit_id]->race_id )
1691    {
1692       //---------- reduce cash -----------//
1693 
1694       if( nationPtr->cash > 0 )
1695       {
1696          if( rank_id == RANK_SOLDIER )
1697             nationPtr->add_expense( EXPENSE_MOBILE_UNIT, (float) SOLDIER_YEAR_SALARY / 365, 1 );
1698 
1699          if( rank_id == RANK_GENERAL )
1700             nationPtr->add_expense( EXPENSE_GENERAL, (float) GENERAL_YEAR_SALARY / 365, 1 );
1701       }
1702       else     // decrease loyalty if the nation cannot pay the unit
1703       {
1704          change_loyalty(-1);
1705       }
1706 
1707       //---------- reduce food -----------//
1708 
1709       if( unit_res[unit_id]->race_id )    // if it's a human unit
1710       {
1711          if( nationPtr->food > 0 )
1712 				nationPtr->consume_food((float) PERSON_FOOD_YEAR_CONSUMPTION / 365);
1713 			else
1714 			{
1715 				if( info.game_date%NO_FOOD_LOYALTY_DECREASE_INTERVAL == 0 )		// decrease 1 loyalty point every 2 days
1716 					change_loyalty(-1);
1717          }
1718       }
1719    }
1720    else  //----- it's a non-human unit ------//
1721    {
1722       if( nationPtr->cash > 0 )
1723       {
1724          int expenseType;
1725 
1726 			switch(unit_res[unit_id]->unit_class)
1727 			{
1728 				case UNIT_CLASS_WEAPON:
1729 					expenseType = EXPENSE_WEAPON;
1730 					break;
1731 
1732 				case UNIT_CLASS_SHIP:
1733 					expenseType = EXPENSE_SHIP;
1734 					break;
1735 
1736 				case UNIT_CLASS_CARAVAN:
1737 					expenseType = EXPENSE_CARAVAN;
1738 					break;
1739 
1740 				default:
1741 					expenseType = EXPENSE_MOBILE_UNIT;
1742 			}
1743 
1744 			nationPtr->add_expense( expenseType, (float) unit_res[unit_id]->year_cost / 365, 1 );
1745 		}
1746 		else     // decrease hit points if the nation cannot pay the unit
1747 		{
1748 			if( unit_res[unit_id]->unit_class != UNIT_CLASS_CARAVAN )		// Even when caravans are not paid, they still stay in your service.
1749 			{
1750 				if( hit_points > 0 )
1751 				{
1752 					hit_points--;
1753 
1754 					if( hit_points < 0 )
1755 						hit_points = (float) 0;
1756 
1757 					//--- when the hit points drop to zero and the unit is destroyed ---//
1758 
1759 					if( hit_points==0 )
1760 					{
1761 						if( nation_recno == nation_array.player_recno )
1762 						{
1763 							int unitClass = unit_res[unit_id]->unit_class;
1764 
1765 							if( unitClass==UNIT_CLASS_WEAPON )
1766 								news_array.weapon_ship_worn_out(unit_id, get_weapon_version());
1767 
1768 							else if( unitClass==UNIT_CLASS_SHIP )
1769 								news_array.weapon_ship_worn_out(unit_id, 0);
1770 						}
1771 					}
1772 				}
1773 			}
1774       }
1775    }
1776 }
1777 //----------- End of function Unit::pay_expense -----------//
1778 
1779 
1780 //--------- Begin of function Unit::change_hit_points ---------//
1781 //
change_hit_points(float changePoints)1782 void Unit::change_hit_points(float changePoints)
1783 {
1784    hit_points += changePoints;
1785 
1786    if( hit_points < 0 )
1787       hit_points = (float) 0;
1788 
1789    if( hit_points > max_hit_points )
1790       hit_points = max_hit_points;
1791 }
1792 //-------- End of function Unit::change_hit_points -----------//
1793 
1794 
1795 //--------- Begin of function Unit::change_loyalty ---------//
1796 //
1797 // <int> changeAmt - amount of loyalty to be changed.
1798 //
change_loyalty(int changeAmt)1799 void Unit::change_loyalty(int changeAmt)
1800 {
1801    int newLoyalty = loyalty + changeAmt;
1802 
1803    newLoyalty = MAX(0, newLoyalty);
1804 
1805    loyalty = MIN(100, newLoyalty);
1806 }
1807 //----------- End of function Unit::change_loyalty -----------//
1808 
1809 
1810 //------- Begin of function Unit::inc_minor_combat_level --------//
1811 //
inc_minor_combat_level(int incLevel)1812 void Unit::inc_minor_combat_level(int incLevel)
1813 {
1814    err_when( incLevel<0 || incLevel>100 );   // it cannot be larger than 100, because the current code can't handle it
1815 
1816    skill.combat_level_minor += incLevel;
1817 
1818    if( skill.combat_level_minor > 100 )
1819    {
1820       if( skill.combat_level < 100 )
1821          set_combat_level(skill.combat_level+1);
1822 
1823       skill.combat_level_minor -= 100;
1824    }
1825 }
1826 //-------- End of function Unit::inc_minor_combat_level ---------//
1827 
1828 
1829 //------- Begin of function Unit::inc_minor_skill_level --------//
1830 //
inc_minor_skill_level(int incLevel)1831 void Unit::inc_minor_skill_level(int incLevel)
1832 {
1833    err_when( incLevel<0 || incLevel>100 );
1834 
1835    skill.skill_level_minor += incLevel;
1836 
1837    if( skill.skill_level_minor > 100 )
1838    {
1839       if( skill.skill_level < 100 )
1840          skill.skill_level++;
1841 
1842       skill.skill_level_minor -= 100;
1843    }
1844 }
1845 //-------- End of function Unit::inc_minor_skill_level ---------//
1846 
1847 
1848 //--------- Begin of function Unit::set_combat_level ---------//
1849 //
set_combat_level(int combatLevel)1850 void Unit::set_combat_level(int combatLevel)
1851 {
1852 	err_when( combatLevel<=0 || combatLevel>100 );
1853 
1854    skill.combat_level = combatLevel;
1855 
1856    UnitInfo* unitInfo = unit_res[unit_id];
1857 
1858    int oldMaxHitPoints = max_hit_points;
1859 
1860    max_hit_points = unitInfo->hit_points * combatLevel / 100;
1861 
1862    hit_points = hit_points * max_hit_points / oldMaxHitPoints;
1863 
1864    hit_points = MIN(hit_points, max_hit_points);
1865 
1866    // --------- update can_guard_flag -------//
1867 
1868    if( combatLevel >= unitInfo->guard_combat_level)
1869    {
1870       can_guard_flag = sprite_info->can_guard_flag;
1871 		if( unit_id == UNIT_ZULU )
1872 			can_guard_flag |= 4;			// shield during attack delay
1873    }
1874    else
1875    {
1876       can_guard_flag = 0;
1877    }
1878 
1879    max_power = skill.combat_level + 50;
1880    cur_power = MIN(cur_power, max_power);
1881 }
1882 //-------- End of function Unit::set_combat_level -----------//
1883 
1884 
1885 //--------- Begin of function Unit::set_rank ---------//
1886 //
1887 // Only if the unit has leadership skill, it can be a general or king.
1888 //
set_rank(int rankId)1889 void Unit::set_rank(int rankId)
1890 {
1891 	err_when( !race_id );
1892 
1893 #ifdef DEBUG
1894 	if( !is_visible() )
1895 	{
1896 		err_when( rank_id==RANK_GENERAL && rankId==RANK_SOLDIER );
1897 		err_when( rank_id==RANK_SOLDIER && rankId==RANK_GENERAL );
1898 	}
1899 #endif
1900 
1901 	if( rank_id == rankId )
1902       return;
1903 
1904    //------- promote --------//
1905 
1906    if( rankId > rank_id )
1907 		change_loyalty(PROMOTE_LOYALTY_INCREASE);
1908 
1909 	//------- demote -----------//
1910 
1911 	else if( rankId < rank_id && rank_id != RANK_KING )      // no decrease in loyalty if a spy king hands his nation to his parent nation and become a general again
1912 		change_loyalty(-DEMOTE_LOYALTY_DECREASE);
1913 
1914 	//---- update nation_general_count_array[] ----//
1915 
1916 	if( nation_recno )
1917 	{
1918 		UnitInfo* unitInfo = unit_res[unit_id];
1919 
1920 		if( rank_id == RANK_GENERAL )    // if it was a general originally
1921 			unitInfo->dec_nation_general_count(nation_recno);
1922 
1923 		if( rankId == RANK_GENERAL )     // if the new rank is general
1924 			unitInfo->inc_nation_general_count(nation_recno);
1925 
1926 		//------ if demote a king to a unit ------//
1927 
1928 		if( rank_id == RANK_KING && rankId != RANK_KING )
1929 			unitInfo->inc_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, when it is no longer a king, we need to re-increase it.
1930 
1931 		//------ if promote a unit to a king ------//
1932 
1933 		if( rank_id != RANK_KING && rankId == RANK_KING )
1934 			unitInfo->dec_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, we need to decrease it
1935 	}
1936 
1937 	//----- reset leader_unit_recno if demote a general to soldier ----//
1938 
1939 	if( rank_id == RANK_GENERAL && rankId == RANK_SOLDIER )
1940 	{
1941 		//----- reset leader_unit_recno of the units he commands ----//
1942 
1943 		for( int i=unit_array.size() ; i>0 ; i-- )
1944 		{
1945 			Unit* unitPtr = (Unit*) unit_array.get_ptr(i);		// don't use is_deleted() as it filters out units that are currently dying
1946 
1947 			if( unitPtr && unitPtr->leader_unit_recno == sprite_recno )
1948 			{
1949 				unitPtr->leader_unit_recno = 0;
1950 				unitPtr->team_id = 0;
1951 			}
1952 		}
1953 
1954 		//--------- deinit team_info ---------//
1955 
1956 		err_when( !team_info );
1957 
1958 		mem_del(team_info);
1959 		team_info = NULL;
1960 		team_id   = 0;
1961 	}
1962 
1963 	//----- if this is a soldier being promoted to a general -----//
1964 
1965 	else if( rank_id == RANK_SOLDIER && rankId == RANK_GENERAL )
1966 	{
1967 		//-- if this soldier is formerly commanded by a general, detech it ---//
1968 
1969 		if( leader_unit_recno )
1970 		{
1971 			if( !unit_array.is_deleted(leader_unit_recno) )    // the leader unit may have been killed at the same time
1972 				unit_array[leader_unit_recno]->del_team_member(sprite_recno);
1973 
1974 			leader_unit_recno = 0;
1975 		}
1976 	}
1977 
1978 	//-------------- update AI info --------------//
1979 
1980 	if( ai_unit )
1981 	{
1982 		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
1983 			nation_array[nation_recno]->del_general_info(sprite_recno);
1984 
1985 		rank_id = rankId;
1986 
1987 		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
1988 			nation_array[nation_recno]->add_general_info(sprite_recno);
1989 	}
1990    else
1991    {
1992       rank_id = rankId;
1993    }
1994 
1995    //----- if this is a general/king ------//
1996 
1997    if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
1998    {
1999       //--------- init team_info -------//
2000 
2001       if( !team_info )
2002       {
2003          team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) );
2004          team_info->member_count = 0;
2005          team_info->ai_last_request_defense_date = 0;
2006       }
2007 
2008       //--- set leadership if this unit does not have any now ----//
2009 
2010       if( skill.skill_id != SKILL_LEADING )
2011       {
2012          skill.skill_id = SKILL_LEADING;
2013 			skill.skill_level = 10 + misc.random(40);
2014       }
2015    }
2016 
2017    //------ refresh if the current unit is selected -----//
2018 
2019    if( unit_array.selected_recno == sprite_recno )
2020       info.disp();
2021 }
2022 //-------- End of function Unit::set_rank -----------//
2023 
2024 
2025 //--------- Begin of function Unit::embark ---------//
2026 //
2027 // Order this unit to embark an vehicle
2028 //
2029 // <int> vehicleRecno - recno of the vehicle.
2030 //
embark(int vehicleRecno)2031 void Unit::embark(int vehicleRecno)
2032 {
2033 	err_here();			// this function is no longer functional
2034 
2035    Unit* vehiclePtr = unit_array[vehicleRecno];
2036 
2037    if( unit_res[unit_id]->vehicle_id == vehiclePtr->unit_id )   // not the right vehicle
2038       return;
2039 
2040    int vehicleUnitId    = unit_res[unit_id]->vehicle_unit_id;
2041    float vehicleHitPoints = vehiclePtr->hit_points;
2042    int xLoc = vehiclePtr->cur_x_loc();
2043    int yLoc = vehiclePtr->cur_y_loc();
2044 
2045    //------- delete the vehicle unit --------//
2046 
2047    unit_array.del(vehicleRecno);    // delete the vehicle (e.g. horse)
2048 
2049    //--------- add the combined unit -------//
2050 
2051    int newUnitRecno = unit_array.add_unit(vehicleUnitId, nation_recno, rank_id, loyalty, xLoc, yLoc);    // add the combined unit (e.g. cavalry)
2052 
2053    UnitVehicle* unitVehicle = (UnitVehicle*) unit_array[newUnitRecno];
2054 
2055    unitVehicle->skill = skill;
2056    unitVehicle->set_combat_level(skill.combat_level);
2057 
2058    unitVehicle->solider_hit_points = (int) hit_points;
2059    unitVehicle->vehicle_hit_points = (int) vehicleHitPoints;
2060 
2061    unitVehicle->hit_points = (float) unitVehicle->solider_hit_points +
2062                              unitVehicle->vehicle_hit_points;
2063 
2064    //-------- delete the solider unit ---------//
2065 
2066    unit_array.del(sprite_recno);    // delete the embarker (e.g. knight)
2067 }
2068 //-------- End of function Unit::embark -----------//
2069 
2070 
2071 
2072 //--------- Begin of function Unit::reward ---------//
2073 //
2074 // <int> rewardNationRecno - the nation which does this reward.
2075 //
reward(int rewardNationRecno)2076 void Unit::reward(int rewardNationRecno)
2077 {
2078 	// ###### patch begin Gilbert 24/9 ########//
2079 	if( nation_array[rewardNationRecno]->cash < REWARD_COST )
2080 		return;
2081 	// ###### patch end Gilbert 24/9 ########//
2082 
2083    //--------- if this is a spy ---------//
2084 
2085    if( spy_recno && true_nation_recno() == rewardNationRecno )    // if the spy's owning nation rewards the spy
2086    {
2087       spy_array[spy_recno]->change_loyalty(REWARD_LOYALTY_INCREASE);
2088 	}
2089 
2090 	//--- if this spy's nation_recno & true_nation_recno() are both == rewardNationRecno, it's true loyalty and cloaked loyalty will both be increased ---//
2091 
2092 	if( nation_recno == rewardNationRecno )
2093 	{
2094 		total_reward += REWARD_COST;
2095 
2096 		change_loyalty(REWARD_LOYALTY_INCREASE);
2097 	}
2098 
2099    nation_array[rewardNationRecno]->add_expense(EXPENSE_REWARD_UNIT, (float)REWARD_COST);
2100 }
2101 //----------- End of function Unit::reward -----------//
2102 
2103 
2104 //------- Begin of function Unit::overseer_migrate ---------//
2105 //
2106 // Order the overseer migrate to a new town but still keeps
2107 // working for the same firm.
2108 //
2109 // <int> destTownRecno - the recno of the town the worker should
2110 //                       migrate to.
2111 //
overseer_migrate(int destTownRecno)2112 void Unit::overseer_migrate(int destTownRecno)
2113 {
2114    err_when( unit_mode!=UNIT_MODE_OVERSEE );
2115 
2116    int curTownRecno = firm_array[unit_mode_para]->overseer_town_recno;
2117 
2118    //------- decrease the population of the unit's home town ------//
2119 
2120    town_array[curTownRecno]->dec_pop(race_id, 1);
2121 
2122    //--------- increase the population of the target town ------//
2123 
2124    town_array[destTownRecno]->inc_pop(race_id, 1, loyalty );
2125 }
2126 //-------- End of function Unit::overseer_migrate ---------//
2127 
2128 
2129 //--------- Begin of function Unit::group_transform ---------//
2130 
group_transform(char remoteAction,short * selectedArray,short selectedCount)2131 void Unit::group_transform(char remoteAction, short *selectedArray, short selectedCount)
2132 {
2133 }
2134 //----------- End of function Unit::group_transform -----------//
2135 
2136 
2137 //--------- Begin of function Unit::transform ---------//
2138 //
2139 // Transform the unit into another unit type.
2140 //
transform()2141 void Unit::transform()
2142 {
2143 /*
2144    UnitInfo* unitInfo = unit_res[unit_id];
2145 
2146    if( unitInfo->transform_unit_id==0 )
2147       return;
2148 
2149    UnitInfo* newUnitInfo = unit_res[unitInfo->transform_unit_id];
2150 
2151    //--- check if the unit has the required combat level ---//
2152 
2153    if( skill.combat_level < unitInfo->transform_combat_level )
2154       return;
2155 
2156    //------ free up space on the map for the new unit -----//
2157 
2158    int xLoc=next_x_loc(), yLoc=next_y_loc();
2159 
2160    stop();
2161 
2162    deinit_sprite(1);    // 1-keep the unit selected if it is currently selected
2163 
2164    //---- locate the space for the new unit as their size, mobile type may be different ----//
2165 
2166    SpriteInfo* spriteInfo = sprite_res[newUnitInfo->sprite_id];
2167    int         xLoc2 = xLoc + spriteInfo->loc_width-1;
2168    int         yLoc2 = yLoc + spriteInfo->loc_height-1;
2169 
2170    if( !world.check_unit_space(xLoc, yLoc, xLoc2, yLoc2, newUnitInfo->mobile_type) )      // first check if if is free to create unit on the same location
2171    {
2172       if( !world.locate_space( xLoc, yLoc, xLoc+spriteInfo->loc_width-1,
2173                                yLoc+spriteInfo->loc_height-1, spriteInfo->loc_width,
2174                                spriteInfo->loc_height, newUnitInfo->mobile_type) )
2175       {
2176          init_sprite( xLoc, yLoc );    // not able to find space for the new unit, transformation cancelled.
2177          return;
2178 		}
2179 	}
2180 
2181    //--------- transform now ------------//
2182 
2183    deinit_unit_id();
2184 
2185    init_unit_id(unitInfo->transform_unit_id);
2186 
2187    init_sprite( xLoc, yLoc );
2188 */
2189 }
2190 //----------- End of function Unit::transform -----------//
2191 
2192 
2193 //--------- Begin of function Unit::spy_change_nation ---------//
2194 //
2195 // Change the deceiving nation recno of a spy unit which you control.
2196 //
2197 // <int>  newNationRecno - the new nation the spy changes its cloack to
2198 // <char> remoteAction   - remote action type
2199 // <int>  groupDefect    - if 1 this spy changed nation as part of a group defect called by Unit::betray
2200 //                         when a General-spy changes colour and takes its subordinates along
2201 //						   and the subordinate is actually an enemy spy. Supresses news notification and
2202 //						   lets the caller handle the Unit nation change (so only handles spy nation change)
2203 //
spy_change_nation(int newNationRecno,char remoteAction,int groupDefect)2204 void Unit::spy_change_nation(int newNationRecno, char remoteAction, int groupDefect)
2205 {
2206 	if( newNationRecno == nation_recno )
2207 		return;
2208 
2209 	if( newNationRecno && nation_array.is_deleted(newNationRecno) )      // this can happen in a multiplayer message
2210 		return;
2211 
2212 	//------- if this is a remote action -------//
2213 
2214 	if( !remoteAction && remote.is_enable() )
2215 	{
2216 		// packet structure <unit recno> <new nation Recno> <group defect>
2217 		short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_SPY_NATION, 3*sizeof(short) );
2218 		*shortPtr = sprite_recno;
2219 		shortPtr[1] = newNationRecno;
2220 		shortPtr[2] = groupDefect;
2221 		return;
2222 	}
2223 
2224 	//----- update the var in Spy ------//
2225 
2226 	Spy* spyPtr = spy_array[spy_recno];
2227 
2228 	//--- when a spy change cloak to another nation, he can't cloak as a general, he must become a soldier first ---//
2229 
2230 	if( is_visible() &&					// if the spy is a commander in a camp, don't set its rank to soldier
2231 		 rank_id == RANK_GENERAL &&
2232 		 newNationRecno != spyPtr->true_nation_recno )
2233 	{
2234 		set_rank(RANK_SOLDIER);
2235 	}
2236 
2237 	//---------------------------------------------------//
2238 	//
2239 	// If this spy unit is a general or an overseer of the
2240 	// cloaked nation, when he changes nation, that will
2241 	// inevitably be noticed by the cloaked nation.
2242 	//
2243 	//---------------------------------------------------//
2244 
2245 	if( spyPtr->true_nation_recno != nation_array.player_recno )	// only send news message if he is not the player's own spy
2246 	{
2247 		if( rank_id == RANK_GENERAL || unit_mode == UNIT_MODE_OVERSEE ||
2248 			 (spyPtr->notify_cloaked_nation_flag && !groupDefect) )
2249 		{
2250 			//-- if this spy's cloaked nation is the player's nation, the player will be notified --//
2251 
2252 			if( nation_recno == nation_array.player_recno )
2253 				news_array.unit_betray(sprite_recno, newNationRecno);
2254 		}
2255 
2256 		//---- send news to the cloaked nation if notify flag is on ---//
2257 
2258 		if( spyPtr->notify_cloaked_nation_flag && !groupDefect )
2259 		{
2260 			if( newNationRecno == nation_array.player_recno )    			// cloaked as the player's nation
2261 				news_array.unit_betray(sprite_recno, newNationRecno);
2262 		}
2263 	}
2264 
2265 	//--------- change nation recno now --------//
2266 
2267 	spyPtr->cloaked_nation_recno = newNationRecno;
2268 
2269 	if (!groupDefect)
2270 		betray(newNationRecno);		// call the betray function to change natino. There is no difference between a spy changing nation and a unit truly betrays
2271 }
2272 //----------- End of function Unit::spy_change_nation -----------//
2273 
2274 
2275 //--------- Begin of function Unit::can_spy_change_nation ---------//
2276 //
2277 // Whether the spy unit can change its spy cloak now or not.
2278 //
2279 // If there are enemy nearby, the unit cannot change its cloak.
2280 //
can_spy_change_nation()2281 int Unit::can_spy_change_nation()
2282 {
2283 	if( !spy_recno )
2284       return 0;
2285 
2286    //--------------------------------------------//
2287 
2288    int xLoc1=cur_x_loc()-SPY_ENEMY_RANGE, yLoc1=cur_y_loc()-SPY_ENEMY_RANGE;
2289    int xLoc2=cur_x_loc()+SPY_ENEMY_RANGE, yLoc2=cur_y_loc()+SPY_ENEMY_RANGE;
2290 
2291    xLoc1 = MAX(0, xLoc1);
2292    yLoc1 = MAX(0, yLoc1);
2293    xLoc2 = MIN(MAX_WORLD_X_LOC-1, xLoc2);
2294    yLoc2 = MIN(MAX_WORLD_Y_LOC-1, yLoc2);
2295 
2296    int       xLoc, yLoc;
2297    int       unitRecno, trueNationRecno = true_nation_recno();
2298    Location* locPtr;
2299 
2300    for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
2301    {
2302       locPtr = world.get_loc(xLoc1, yLoc);
2303 
2304       for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
2305       {
2306          if( locPtr->has_unit(UNIT_LAND) )
2307             unitRecno = locPtr->unit_recno(UNIT_LAND);
2308 
2309          else if( locPtr->has_unit(UNIT_SEA) )
2310             unitRecno = locPtr->unit_recno(UNIT_SEA);
2311 
2312          else if( locPtr->has_unit(UNIT_AIR) )
2313             unitRecno = locPtr->unit_recno(UNIT_AIR);
2314 
2315          else
2316             continue;
2317 
2318          if( unit_array.is_deleted(unitRecno) )    // the unit is dying, its recno is still in the location
2319             continue;
2320 
2321          if( unit_array[unitRecno]->true_nation_recno() != trueNationRecno )
2322             return 0;
2323       }
2324    }
2325 
2326    return 1;
2327 }
2328 //----------- End of function Unit::can_spy_change_nation -----------//
2329 
2330 
2331 //--------- Begin of function Unit::resign ---------//
2332 //
2333 // Resign the unit.
2334 //
resign(int remoteAction)2335 void Unit::resign(int remoteAction)
2336 {
2337    if( !remoteAction && remote.is_enable() )
2338    {
2339       // packet structure : <unit recno> <nation recno>
2340       short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_RESIGN, 2*sizeof(short));
2341       *shortPtr = sprite_recno;
2342 		shortPtr[1] = nation_array.player_recno;
2343 
2344       return;
2345    }
2346 
2347    //---- increase the wandering count when a unit is disbanded ----//
2348 
2349    if( race_id )
2350 		town_array.race_wander_pop_array[race_id-1] += 2;     // disbanding one resulted in two wandering units to make the effect more significant
2351 
2352 	//--- if the unit is visible, call stop2() so if it has an AI action queue, that will be reset ---//
2353 
2354 	if( is_visible() )
2355 		stop2();
2356 
2357 	//--- if the spy is resigned by an enemy, display a message ---//
2358 
2359 	if( spy_recno && true_nation_recno() != nation_recno )		// the spy is cloaked in an enemy nation when it is resigned
2360 	{
2361 		//------ decrease reputation ------//
2362 
2363 		nation_array[true_nation_recno()]->change_reputation((float)-SPY_KILLED_REPUTATION_DECREASE);
2364 
2365 		//------- add news message -------//
2366 
2367 		if( true_nation_recno() == nation_array.player_recno ||		// display when the player's spy is revealed or the player has revealed an enemy spy
2368 			 nation_recno == nation_array.player_recno )
2369 		{
2370 			//--- If a spy is caught, the spy's nation's reputation wil decrease ---//
2371 
2372 			news_array.spy_killed(spy_recno);
2373 		}
2374 	}
2375 
2376 	//----------------------------------------------//
2377 
2378 	if( rank_id == RANK_GENERAL )			// if this is a general, news_array.general_die() will be called, set news_add_flag to 0 to suppress the display of thew news
2379 		news_array.news_add_flag=0;
2380 
2381 	unit_array.del( sprite_recno );
2382 
2383 	news_array.news_add_flag=1;
2384 }
2385 //----------- End of function Unit::resign -----------//
2386 
2387 
2388 //--------- Begin of function Unit::region_id ---------//
2389 //
2390 // Return the region id. of this unit.
2391 //
region_id()2392 uint8_t Unit::region_id()
2393 {
2394    if( is_visible() )
2395    {
2396       return world.get_region_id( next_x_loc(), next_y_loc() );
2397 	}
2398 	else
2399 	{
2400 		if( unit_mode == UNIT_MODE_OVERSEE )
2401 			return firm_array[unit_mode_para]->region_id;
2402 	}
2403 
2404 	return 0;
2405 }
2406 //----------- End of function Unit::region_id -----------//
2407 
2408 
2409 //--------- Begin of function Unit::del_team_member ---------//
2410 //
2411 // Delete a specific member of the team led by this leader.
2412 //
del_team_member(int unitRecno)2413 void Unit::del_team_member(int unitRecno)
2414 {
2415 	err_when( !team_info );
2416 
2417    for( int i=0 ; i<team_info->member_count ; i++ )
2418    {
2419       if( team_info->member_unit_array[i] == unitRecno )
2420 		{
2421 			err_when( team_info->member_count > MAX_TEAM_MEMBER );
2422 
2423 			misc.del_array_rec( team_info->member_unit_array, team_info->member_count,
2424 								  sizeof( team_info->member_unit_array[0] ), i+1 );
2425 
2426          team_info->member_count--;
2427          return;
2428       }
2429    }
2430 
2431    //-------------------------------------------------------//
2432    //
2433    // Note: for rebels and monsters, although they have
2434    //       leader_unit_recno, their team_info is not used.
2435    //       So del_team_member() won't be able to match the
2436    //       unit in its member_unit_array[].
2437    //
2438    //-------------------------------------------------------//
2439 }
2440 //----------- End of function Unit::del_team_member -----------//
2441 
2442 
2443 //--------- Begin of function Unit::validate_team ---------//
2444 //
2445 // Validate the member in this commander's team. If there
2446 // are any units with hit_points <= 0, delete them.
2447 //
2448 // Those unit may just be killed, so soon that the Unit's set_die()
2449 // function hsa been called yet. validate_team() function must
2450 // be called before all issunig any new team actions.
2451 //
validate_team()2452 void Unit::validate_team()
2453 {
2454 	err_when( !team_info );
2455 
2456 	int unitRecno;
2457 
2458 	for( int i=team_info->member_count-1 ; i>=0 ; i-- )
2459 	{
2460 		unitRecno = team_info->member_unit_array[i];
2461 
2462 		if( unit_array.is_deleted(unitRecno) )
2463 		{
2464 			err_when( team_info->member_count > MAX_TEAM_MEMBER );
2465 
2466 			misc.del_array_rec( team_info->member_unit_array, team_info->member_count,
2467 								  sizeof( team_info->member_unit_array[0] ), i+1 );
2468 
2469 			team_info->member_count--;
2470 		}
2471    }
2472 }
2473 //----------- End of function Unit::validate_team -----------//
2474 
2475 
2476 //--------- Begin of function Unit::commanded_soldier_count ---------//
2477 //
2478 // Return the no. of soldiers commanded by this unit.
2479 //
commanded_soldier_count()2480 int Unit::commanded_soldier_count()
2481 {
2482 	if( rank_id != RANK_GENERAL && rank_id != RANK_KING )
2483 		return 0;
2484 
2485 	//--------------------------------------//
2486 
2487 	err_when( !team_info );
2488 
2489    int soldierCount=0;
2490 
2491    if( is_visible() )
2492    {
2493       soldierCount = team_info->member_count-1;
2494 
2495       if( soldierCount < 0 )  // member_count can be 0
2496          soldierCount = 0;
2497    }
2498    else
2499    {
2500       if( unit_mode == UNIT_MODE_OVERSEE )
2501       {
2502          Firm* firmPtr = firm_array[unit_mode_para];
2503 
2504          if( firmPtr->firm_id == FIRM_CAMP )			// it can be an overseer of a seat of powre
2505 				soldierCount = firmPtr->worker_count;
2506       }
2507    }
2508 
2509    return soldierCount;
2510 }
2511 //----------- End of function Unit::commanded_soldier_count -----------//
2512 
2513 
2514 //----------- Begin of function Unit::fix_attack_info -----------//
fix_attack_info()2515 void Unit::fix_attack_info()
2516 {
2517 	int techLevel;
2518 	UnitInfo *unitInfo = unit_res[unit_id];
2519 
2520 	attack_count = unitInfo->attack_count;
2521 
2522    if( attack_count > 0 && unitInfo->first_attack > 0)
2523       attack_info_array = unit_res.attack_info_array+unitInfo->first_attack-1;
2524    else
2525       attack_info_array = NULL;
2526 
2527    if( unitInfo->unit_class == UNIT_CLASS_WEAPON &&
2528 		(techLevel=get_weapon_version()) > 0 )
2529    {
2530       switch( unit_id )
2531       {
2532       case UNIT_BALLISTA:
2533       case UNIT_F_BALLISTA:
2534          attack_count = 2;
2535          break;
2536       case UNIT_EXPLOSIVE_CART:
2537          attack_count = 0;
2538          break;
2539       default:
2540          attack_count = 1;
2541       }
2542 
2543       if( attack_count > 0)
2544       {
2545          attack_info_array += (techLevel-1) * attack_count;
2546       }
2547       else
2548       {
2549          // no attack like explosive cart
2550          attack_info_array = NULL;
2551       }
2552    }
2553 }
2554 //----------- End of function Unit::fix_attack_info -----------//
2555 
2556 
2557 //----------- Begin of function Unit::return_camp -----------//
2558 //
2559 // Order this unit to return to the camp. For ordering many
2560 // units to return to a camp, UnitArray::return_camp() should
2561 // be called instead.
2562 //
return_camp()2563 int Unit::return_camp()
2564 {
2565 	if( !home_camp_firm_recno )
2566 		return 0;
2567 
2568 	err_when( firm_array.is_deleted(home_camp_firm_recno) );
2569 
2570 	Firm* firmPtr = firm_array[home_camp_firm_recno];
2571 
2572 	if( firmPtr->region_id != region_id() )
2573 		return 0;
2574 
2575 	err_when( firmPtr->firm_id != FIRM_CAMP );
2576 	err_when( firmPtr->nation_recno != nation_recno );
2577 
2578 	//--------- assign now ---------//
2579 
2580 	assign(firmPtr->loc_x1, firmPtr->loc_y1);
2581 
2582 	force_move_flag = 1;
2583 
2584 	return cur_action != SPRITE_IDLE;
2585 }
2586 //----------- End of function Unit::return_camp -----------//
2587 
2588 
2589 //----------- Begin of function Unit::unit_power -----------//
2590 //
2591 // Return a power index of the weapon, this is for calculating
2592 // the total combat level of a target.
2593 //
unit_power()2594 int Unit::unit_power()
2595 {
2596 	UnitInfo* unitInfo = unit_res[unit_id];
2597 
2598 	if( unitInfo->unit_class == UNIT_CLASS_WEAPON )
2599 	{
2600 		return (int) hit_points + (unitInfo->weapon_power + get_weapon_version() - 1) * 15;
2601 	}
2602 	else
2603 	{
2604 		return (int) hit_points;
2605 	}
2606 }
2607 //----------- End of function Unit::unit_power -----------//
2608 
2609 
2610 //----------- Begin of function Unit::get_cur_loc -----------//
2611 //
2612 // <short&> xLoc, yLoc - reference vars for returning the
2613 //								 location of this unit
2614 //
2615 // return : 0 - if this unit is invisible
2616 //				1 - if a location has been returned.
2617 //
get_cur_loc(short & xLoc,short & yLoc)2618 int Unit::get_cur_loc(short& xLoc, short& yLoc)
2619 {
2620 	if( is_visible() )
2621 	{
2622 		xLoc = next_x_loc();		// update location
2623 		yLoc = next_y_loc();
2624 	}
2625 	else if( unit_mode == UNIT_MODE_OVERSEE ||
2626 				unit_mode==UNIT_MODE_CONSTRUCT ||
2627 				unit_mode == UNIT_MODE_IN_HARBOR )
2628 	{
2629 		Firm* firmPtr = firm_array[unit_mode_para];
2630 
2631 		xLoc = firmPtr->center_x;
2632 		yLoc = firmPtr->center_y;
2633 	}
2634 	else if( unit_mode == UNIT_MODE_ON_SHIP )
2635 	{
2636 		Unit* unitPtr = unit_array[unit_mode_para];
2637 
2638 		//### begin alex 22/10 ###//
2639 		//xLoc = unitPtr->next_x_loc();
2640 		//yLoc = unitPtr->next_y_loc();
2641 		if(unitPtr->is_visible())
2642 		{
2643 			xLoc = unitPtr->next_x_loc();
2644 			yLoc = unitPtr->next_y_loc();
2645 		}
2646 		else
2647 		{
2648 			err_when(unitPtr->unit_mode!=UNIT_MODE_IN_HARBOR);
2649 			Firm *firmPtr = firm_array[unitPtr->unit_mode_para];
2650 			xLoc = firmPtr->center_x;
2651 			yLoc = firmPtr->center_y;
2652 		}
2653 		//#### end alex 22/10 ####//
2654 	}
2655 	else
2656 		return 0;
2657 
2658 	return 1;
2659 }
2660 //----------- End of function Unit::get_cur_loc -----------//
2661 
2662 
2663 //----------- Begin of function Unit::get_cur_loc2 -----------//
2664 //
2665 // <short&> xLoc, yLoc - reference vars for returning the
2666 //								 location of this unit
2667 //
2668 // return : 0 - if this unit is invisible
2669 //				1 - if a location has been returned.
2670 //
get_cur_loc2(short & xLoc,short & yLoc)2671 int Unit::get_cur_loc2(short& xLoc, short& yLoc)
2672 {
2673 	if( is_visible() )
2674 	{
2675 		xLoc = cur_x_loc();
2676 		yLoc = cur_y_loc();
2677 	}
2678 	else if( unit_mode == UNIT_MODE_OVERSEE ||
2679 				unit_mode==UNIT_MODE_CONSTRUCT ||
2680 				unit_mode == UNIT_MODE_IN_HARBOR )
2681 	{
2682 		Firm* firmPtr = firm_array[unit_mode_para];
2683 
2684 		xLoc = firmPtr->center_x;
2685 		yLoc = firmPtr->center_y;
2686 	}
2687 	else if( unit_mode == UNIT_MODE_ON_SHIP )
2688 	{
2689 		Unit* unitPtr = unit_array[unit_mode_para];
2690 
2691 		if( unitPtr->is_visible() )
2692 		{
2693 			xLoc = unitPtr->cur_x_loc();
2694 			yLoc = unitPtr->cur_y_loc();
2695 		}
2696 		else
2697 		{
2698 			err_when(unitPtr->unit_mode!=UNIT_MODE_IN_HARBOR);
2699 			Firm *firmPtr = firm_array[unitPtr->unit_mode_para];
2700 			xLoc = firmPtr->center_x;
2701 			yLoc = firmPtr->center_y;
2702 		}
2703 	}
2704 	else
2705 		return 0;
2706 
2707 	return 1;
2708 }
2709 //----------- End of function Unit::get_cur_loc2 -----------//
2710 
2711 
2712 //----------- Begin of function Unit::is_leader_in_range -----------//
2713 // If the leader is assigned and in range, return leader_unit_recno, otherwise
2714 // return zero for indicating the leader is not in range.
2715 //
is_leader_in_range()2716 short Unit::is_leader_in_range()
2717 {
2718 	if( !leader_unit_recno )
2719 		return 0;
2720 
2721 	if( unit_array.is_deleted(leader_unit_recno) )
2722 	{
2723 		leader_unit_recno = 0;
2724 		return 0;
2725 	}
2726 
2727 	Unit* leaderUnit = unit_array[leader_unit_recno];
2728 
2729 	if( !leaderUnit->is_visible() && leaderUnit->unit_mode == UNIT_MODE_CONSTRUCT )
2730 		return 0;
2731 
2732 	short leaderXLoc, leaderYLoc, xLoc, yLoc;
2733 	leaderUnit->get_cur_loc2(leaderXLoc, leaderYLoc);
2734 	get_cur_loc2(xLoc, yLoc);
2735 
2736 	if( leaderXLoc >= 0 && misc.points_distance(xLoc, yLoc, leaderXLoc, leaderYLoc) <= EFFECTIVE_LEADING_DISTANCE )
2737 		return leader_unit_recno;
2738 
2739 	return 0;
2740 }
2741 //----------- End of function Unit::is_leader_in_range -----------//
2742 
2743 
2744 //----------- Begin of function Unit::add_way_point -----------//
2745 // Add the point to the way_point_array if it is not in the array.
2746 // Otherwise, remove the point from the way_point_array.
2747 //
2748 // <short>	 x	- x coordinate of the point
2749 // <short>	 y - y coordinate of the point
2750 //
add_way_point(short x,short y)2751 void Unit::add_way_point(short x, short y)
2752 {
2753 	if(way_point_count>=100)
2754 		return; // too many way point
2755 
2756 	if(way_point_count>1) // don't allow to remove the 1st node, since the unit is moving there
2757 	{
2758 		ResultNode *nodePtr = way_point_array + 1;
2759 		for(int i=1; i<way_point_count; ++i, nodePtr++)
2760 		{
2761 			if(nodePtr->node_x == x && nodePtr->node_y == y) // remove this node
2762 			{
2763 				misc.del_array_rec(way_point_array, way_point_count, sizeof(ResultNode), i+1); // remove 1st node
2764 				way_point_count--;
2765 				return; // there should be one and only one node with the same value
2766 			}
2767 		}
2768 	}
2769 
2770 	//-------------- add new node -----------------//
2771 	if(way_point_count>=way_point_array_size) // buffer full
2772 	{
2773 		way_point_array_size += WAY_POINT_ADJUST_SIZE;
2774 
2775 		if(way_point_count)
2776 			way_point_array = (ResultNode*) mem_resize(way_point_array, way_point_array_size*sizeof(ResultNode));
2777 		else
2778 			way_point_array = (ResultNode*) mem_add(sizeof(ResultNode)*WAY_POINT_ADJUST_SIZE);
2779 	}
2780 
2781 	ResultNode *nodePtr = way_point_array + way_point_count;
2782 	nodePtr->node_x = x;
2783 	nodePtr->node_y = y;
2784 	way_point_count++;
2785 
2786 	if(way_point_count==1)
2787 		move_to(x, y);
2788 }
2789 //----------- End of function Unit::add_way_point -----------//
2790 
2791 
2792 //----------- Begin of function Unit::reset_way_point_array -----------//
reset_way_point_array()2793 void Unit::reset_way_point_array()
2794 {
2795 	//------------------------------------------------------------------------------------//
2796 	// There are nly two conditions to reset the way_point_array
2797 	// 1) action_mode2!=ACTION_MOVE in Unit::stop()
2798 	// 2) dest? != node_? in the first node of way_point_array in calling Unit::move_to()
2799 	//------------------------------------------------------------------------------------//
2800 	if(way_point_array_size)
2801 	{
2802 		mem_del(way_point_array);
2803 		way_point_array = NULL;
2804 		way_point_array_size = 0;
2805 		way_point_count = 0;
2806 	}
2807 }
2808 //----------- End of function Unit::reset_way_point_array -----------//
2809 
2810 
2811 //----------- Begin of function Unit::process_way_point -----------//
2812 // move to the next way point and remove this point from the
2813 // way_point_array
2814 //
process_way_point()2815 void Unit::process_way_point()
2816 {
2817 	err_when(action_mode!=ACTION_STOP || action_mode2!=ACTION_STOP || cur_action!=SPRITE_IDLE);
2818 
2819 	int destX, destY;
2820 	if(way_point_count>1)
2821 	{
2822 		ResultNode *nodePtr = way_point_array+1;
2823 		destX = nodePtr->node_x;
2824 		destY = nodePtr->node_y;
2825 		misc.del_array_rec(way_point_array, way_point_count, sizeof(ResultNode), 1); // remove 1st node
2826 		way_point_count--;
2827 	}
2828 	else // only one unprocessed node
2829 	{
2830 		ResultNode *nodePtr = way_point_array;
2831 		destX = nodePtr->node_x;
2832 		destY = nodePtr->node_y;
2833 		//misc.del_array_rec(way_point_array, way_point_count, sizeof(ResultNode), 1); // remove 1st node
2834 		//way_point_count--;
2835 	}
2836 	move_to(destX, destY);
2837 }
2838 //----------- End of function Unit::process_way_point -----------//
2839 
2840 
2841 //----------- Begin of function TeamInfo::TeamInfo ---------//
2842 
TeamInfo()2843 TeamInfo::TeamInfo()
2844 {
2845 	memset( this, 0, sizeof(TeamInfo) );
2846 }
2847 //----------- End of function TeamInfo::TeamInfo ---------//
2848 
2849