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 : OUNITD.CPP
22 //Description : Object Unit defense functions
23 //Owner : Alex
24
25 #include <ALL.h>
26 #include <OUNIT.h>
27 #include <OWORLD.h>
28 #include <OFIRM.h>
29 #include <ONATION.h>
30 #include <OTOWN.h>
31 #include <OF_CAMP.h>
32 #include <OF_MONS.h>
33
34 #ifdef NO_DEBUG_UNIT
35 #undef err_when
36 #undef err_here
37 #undef err_if
38 #undef err_else
39 #undef err_now
40 #define err_when(cond)
41 #define err_here()
42 #define err_if(cond)
43 #define err_else
44 #define err_now(msg)
45 #undef DEBUG
46 #endif
47
48 //=================================================================================================//
49 // Unit's defend mode generalized functions
50 //=================================================================================================//
51
52 //--------- Begin of function Unit::in_any_defense_mode ---------//
53 // check whether the unit is in defense mode
54 //
55 // return 1 if it is
56 // return 0 otherwise
57 //
in_any_defense_mode()58 int Unit::in_any_defense_mode()
59 {
60 return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM);
61 }
62 //----------- End of function Unit::in_any_defense_mode -----------//
63
64
65 //--------- Begin of function Unit::general_defend_mode_detect_target ---------//
66 // call the appropriate defend function for the current type of defend
67 //
68 // <int> checkDefendMode - flag to check defend mode or not
69 //
general_defend_mode_detect_target(int checkDefendMode)70 void Unit::general_defend_mode_detect_target(int checkDefendMode)
71 {
72 stop();
73 switch(action_mode2)
74 {
75 case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
76 defense_detect_target();
77 break;
78
79 case ACTION_DEFEND_TOWN_ATTACK_TARGET:
80 defend_town_detect_target();
81 break;
82
83 case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
84 monster_defend_detect_target();
85 break;
86
87 default: if(checkDefendMode)
88 err_here();
89 break;
90 }
91 }
92 //----------- End of function Unit::general_defend_mode_detect_target -----------//
93
94
95 //--------- Begin of function Unit::general_defend_mode_process_attack_target ---------//
96 // process unit defense action. If target is dead, action_mode changes to detect_mode
97 //
98 // return 1 if action mode changes to detect mode
99 // return 0 otherwise
100 //
general_defend_mode_process_attack_target()101 int Unit::general_defend_mode_process_attack_target()
102 {
103 Location *locPtr;
104 Unit *unitPtr;
105 Town *townPtr;
106 Firm *firmPtr;
107 SpriteInfo *spriteInfo;
108 FirmInfo *firmInfo;
109 int clearToDetect = 0;
110
111 //------------------------------------------------------------------------------//
112 // if the unit's action mode is in defensive attack action, process the corresponding
113 // checking.
114 //------------------------------------------------------------------------------//
115 switch(action_mode)
116 {
117 case ACTION_ATTACK_UNIT:
118 if(unit_array.is_deleted(action_para2))
119 clearToDetect++;
120 else
121 {
122 err_when(unit_array.is_deleted(action_para2));
123 unitPtr = unit_array[action_para2];
124
125 //if(unitPtr->cur_action==SPRITE_IDLE)
126 // clearToDetect++;
127
128 if(!nation_can_attack(unitPtr->nation_recno)) // cannot attack this nation
129 clearToDetect++;
130 }
131 break;
132
133 case ACTION_ATTACK_FIRM:
134 if(firm_array.is_deleted(action_para2))
135 clearToDetect++;
136 else
137 {
138 err_when(firm_array.is_deleted(action_para2));
139 firmPtr = firm_array[action_para2];
140
141 if(!nation_can_attack(firmPtr->nation_recno)) // cannot attack this nation
142 clearToDetect++;
143 }
144 break;
145
146 case ACTION_ATTACK_TOWN:
147 if(town_array.is_deleted(action_para2))
148 clearToDetect++;
149 else
150 {
151 err_when(town_array.is_deleted(action_para2));
152 townPtr = town_array[action_para2];
153
154 if(!nation_can_attack(townPtr->nation_recno)) // cannot attack this nation
155 clearToDetect++;
156 }
157 break;
158
159 case ACTION_ATTACK_WALL:
160 locPtr = world.get_loc(action_x_loc2, action_y_loc2);
161
162 if(!locPtr->is_wall() || !nation_can_attack(locPtr->power_nation_recno))
163 clearToDetect++;
164 break;
165
166 default: clearToDetect++;
167 break;
168 }
169
170 //------------------------------------------------------------------------------//
171 // suitation changed to defensive detecting mode
172 //------------------------------------------------------------------------------//
173 if(clearToDetect)
174 {
175 //----------------------------------------------------------//
176 // target is dead, change to detect state for another target
177 //----------------------------------------------------------//
178 reset_action_para();
179 return 1;
180 }
181 else if(waiting_term<ATTACK_WAITING_TERM)
182 waiting_term++;
183 else
184 {
185 //------------------------------------------------------------------------------//
186 // process the corresponding attacking procedure.
187 //------------------------------------------------------------------------------//
188 waiting_term = 0;
189 switch(action_mode)
190 {
191 case ACTION_ATTACK_UNIT:
192 err_when(unit_array.is_deleted(action_para2) || !unitPtr);
193 spriteInfo = unitPtr->sprite_info;
194
195 //-----------------------------------------------------------------//
196 // attack the target if able to reach the target surrounding, otherwise
197 // continue to wait
198 //-----------------------------------------------------------------//
199 action_x_loc2 = unitPtr->next_x_loc(); // update target location
200 action_y_loc2 = unitPtr->next_y_loc();
201 if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
202 attack_unit(unitPtr->sprite_recno);
203 break;
204
205 case ACTION_ATTACK_FIRM:
206 err_when(firm_array.is_deleted(action_para2) || !firmPtr);
207 firmInfo = firm_res[firmPtr->firm_id];
208
209 //-----------------------------------------------------------------//
210 // attack the target if able to reach the target surrounding, otherwise
211 // continue to wait
212 //-----------------------------------------------------------------//
213 attack_firm(action_x_loc2, action_y_loc2);
214
215 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
216 firmInfo->loc_width, firmInfo->loc_height))
217 waiting_term = 0;
218 break;
219
220 case ACTION_ATTACK_TOWN:
221 err_when(town_array.is_deleted(action_para2) || !townPtr);
222
223 //-----------------------------------------------------------------//
224 // attack the target if able to reach the target surrounding, otherwise
225 // continue to wait
226 //-----------------------------------------------------------------//
227 attack_town(action_x_loc2, action_y_loc2);
228
229 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
230 STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
231 waiting_term = 0;
232 break;
233
234 case ACTION_ATTACK_WALL:
235 err_when(action_para || action_para2);
236
237 attack_wall(action_x_loc2, action_y_loc2);
238 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, 1, 1))
239 waiting_term = 0;
240 break;
241
242 default:
243 err_here();
244 break;
245 }
246 }
247
248 return 0;
249 }
250 //----------- End of function Unit::general_defend_mode_process_attack_target -----------//
251
252
253 //=================================================================================================//
254 // Unit's defense mode
255 //=================================================================================================//
256
257 //--------- Begin of function Unit::defense_attack_unit ---------//
258 // defensive attack units
259 //
260 // <short> targetRecno - recno of the target
261 //
defense_attack_unit(short targetRecno)262 void Unit::defense_attack_unit(short targetRecno)
263 {
264 action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
265 attack_unit(targetRecno);
266 }
267 //----------- End of function Unit::defense_attack_unit -----------//
268
269
270 //--------- Begin of function Unit::defense_attack_firm ---------//
271 // defensive attack firm
272 //
273 // <short> targetXLoc - x location of the firm
274 // <short> targetYLoc - y location of the firm
275 //
defense_attack_firm(int targetXLoc,int targetYLoc)276 void Unit::defense_attack_firm(int targetXLoc, int targetYLoc)
277 {
278 action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
279 attack_firm(targetXLoc, targetYLoc);
280 }
281 //----------- End of function Unit::defense_attack_firm -----------//
282
283
284 //--------- Begin of function Unit::defense_attack_town ---------//
285 // defensive attack town
286 //
287 // <short> targetXLoc - x location of the town
288 // <short> targetYLoc - y location of the town
289 //
defense_attack_town(int targetXLoc,int targetYLoc)290 void Unit::defense_attack_town(int targetXLoc, int targetYLoc)
291 {
292 action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
293 attack_town(targetXLoc, targetYLoc);
294 }
295 //----------- End of function Unit::defense_attack_town -----------//
296
297
298 //--------- Begin of function Unit::defense_attack_wall ---------//
299 // defensive attack wall
300 //
301 // <short> targetXLoc - x location of wall
302 // <short> targetYLoc - y location of wall
303 //
defense_attack_wall(int targetXLoc,int targetYLoc)304 void Unit::defense_attack_wall(int targetXLoc, int targetYLoc)
305 {
306 action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
307 attack_wall(targetXLoc, targetYLoc);
308 }
309 //----------- End of function Unit::defense_attack_wall -----------//
310
311
312 //--------- Begin of function Unit::defense_detect_target ---------//
313 // set parameters for unit's defensive mode
314 //
defense_detect_target()315 void Unit::defense_detect_target()
316 {
317 action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET;
318 action_para2 = AUTO_DEFENSE_DETECT_COUNT;
319 action_x_loc2 = -1;
320 action_y_loc2 = -1;
321 }
322 //----------- End of function Unit::defense_detect_target -----------//
323
324
325 //--------- Begin of function Unit::defense_back_camp ---------//
326 // set parameters for unit's to return camp
327 //
328 // <int> firmXLoc - x location of the firm
329 // <int> firmYLoc - y location of the firm
330 //
defense_back_camp(int firmXLoc,int firmYLoc)331 void Unit::defense_back_camp(int firmXLoc, int firmYLoc)
332 {
333 err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_CAMP);
334 err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_recno!=action_misc_para);
335
336 assign(firmXLoc, firmYLoc);
337 action_mode2 = ACTION_AUTO_DEFENSE_BACK_CAMP;
338 }
339 //----------- End of function Unit::defense_back_camp -----------//
340
341
342 //--------- Begin of function Unit::process_auto_defense_attack_target ---------//
343 // process the action for unit's defensive attack
344 //
process_auto_defense_attack_target()345 void Unit::process_auto_defense_attack_target()
346 {
347 err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET);
348 if(general_defend_mode_process_attack_target())
349 {
350 defense_detect_target();
351 err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
352 }
353 }
354 //----------- End of function Unit::process_auto_defense_attack_target -----------//
355
356
357 //--------- Begin of function Unit::process_auto_defense_detect_target ---------//
358 // process action for unit's defensive detecet target
359 //
process_auto_defense_detect_target()360 void Unit::process_auto_defense_detect_target()
361 {
362 err_when(action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET);
363 err_when(action_mode!=ACTION_STOP);
364 err_when(action_para!=0);
365 err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1);
366
367 //----------------------------------------------------------------//
368 // no target or target is out of detect range, so change state to
369 // back camp
370 //----------------------------------------------------------------//
371 if(!action_para2)
372 {
373 err_when(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para);
374 int back = 0;
375 FirmCamp *campPtr;
376 Unit *targetPtr;
377
378 if(firm_array.is_deleted(action_misc_para))
379 back++;
380 else
381 {
382 campPtr = (FirmCamp*) firm_array[action_misc_para];
383 if(unit_array.is_deleted(campPtr->defend_target_recno))
384 back++;
385 else
386 {
387 targetPtr = unit_array[campPtr->defend_target_recno];
388 if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=campPtr->firm_recno)
389 back++;
390 }
391 }
392
393 if(!back)
394 {
395 //action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET;
396 action_para2 = AUTO_DEFENSE_DETECT_COUNT;
397 return;
398 }
399
400 process_auto_defense_back_camp();
401 return;
402 }
403
404 //----------------------------------------------------------------//
405 // defense_detecting target algorithm
406 //----------------------------------------------------------------//
407 int startLoc;
408 int dimension;
409
410 switch(action_para2%GAME_FRAMES_PER_DAY)
411 {
412 case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
413 //### begin alex 3/10 ###//
414 dimension = 7;
415 //#### end alex 3/10 ####//
416 break;
417
418 case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
419 dimension = 8;
420 break;
421
422 case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
423 dimension = EFFECTIVE_AUTO_DEFENSE_DISTANCE;
424 break;
425
426 default: action_para2--;
427 return;
428 }
429
430 //---------------------------------------------------------------//
431 // attack the target if target detected, or change the detect region
432 //---------------------------------------------------------------//
433 if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
434 action_para2--;
435 }
436 //----------- End of function Unit::process_auto_defense_detect_target -----------//
437
438
439 //--------- Begin of function Unit::process_auto_defense_back_camp ---------//
440 // process action for the units to return camp
441 //
process_auto_defense_back_camp()442 void Unit::process_auto_defense_back_camp()
443 {
444 int clearDefenseMode = 0;
445 if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it
446 {
447 Firm *firmPtr;
448 if(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para))
449 clearDefenseMode++;
450 else
451 {
452 firmPtr = firm_array[action_misc_para];
453 if(firmPtr->firm_id!=FIRM_CAMP || firmPtr->nation_recno!=nation_recno)
454 clearDefenseMode++;
455 else
456 {
457 defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp
458 err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
459 return;
460 }
461 }
462 }
463 else if(cur_action==SPRITE_IDLE)
464 {
465 if(firm_array.is_deleted(action_misc_para))
466 clearDefenseMode++;
467 else
468 {
469 Firm *firmPtr = firm_array[action_misc_para];
470 defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1);
471 err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
472 return;
473 }
474 }
475
476 err_when(!clearDefenseMode);
477 //----------------------------------------------------------------//
478 // clear order if the camp is deleted
479 //----------------------------------------------------------------//
480 stop2();
481 reset_action_misc_para();
482 err_when(in_auto_defense_mode());
483 }
484 //----------- End of function Unit::process_auto_defense_back_camp -----------//
485
486
487 //------------- Begin of function Unit::in_auto_defense_mode --------------//
488 // check whether the units in auto defense mode
489 //
in_auto_defense_mode()490 int Unit::in_auto_defense_mode()
491 {
492 return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_AUTO_DEFENSE_BACK_CAMP);
493 }
494 //----------- End of function Unit::in_auto_defense_mode -----------//
495
496
497 //------------- Begin of function Unit::defense_follow_target --------------//
498 // decide whether to follow the target
499 //
500 // return 0 if aborting attack the current target and go back to military camp
501 // return 1 otherwise
502 //
defense_follow_target()503 int Unit::defense_follow_target()
504 {
505 #define PROB_HOSTILE_RETURN 10
506 #define PROB_FRIENDLY_RETURN 20
507 #define PROB_NEUTRAL_RETURN 30
508
509 if(unit_array.is_deleted(action_para))
510 return 1;
511
512 if(cur_action==SPRITE_ATTACK)
513 return 1;
514
515 Unit *targetPtr = unit_array[action_para];
516 Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
517 if(!locPtr->has_unit(targetPtr->mobile_type))
518 return 1; // the target may be dead or invisible
519
520 int returnFactor, abortAction = 0;
521
522 //-----------------------------------------------------------------//
523 // calculate the chance to go back to military camp in following the
524 // target
525 //-----------------------------------------------------------------//
526 if(locPtr->power_nation_recno==nation_recno)
527 return 1; // target within our nation
528 else if(!locPtr->power_nation_recno) // is neutral
529 returnFactor = PROB_NEUTRAL_RETURN;
530 else
531 {
532 Nation *locNationPtr = nation_array[locPtr->power_nation_recno];
533 if(locNationPtr->get_relation_status(nation_recno)==NATION_HOSTILE)
534 returnFactor = PROB_HOSTILE_RETURN;
535 else
536 returnFactor = PROB_FRIENDLY_RETURN;
537 }
538
539 if(!abortAction)
540 {
541 SpriteInfo *targetSpriteInfo = targetPtr->sprite_info;
542
543 //-----------------------------------------------------------------//
544 // if the target moves faster than this unit, it is more likely for
545 // this unit to go back to military camp.
546 //-----------------------------------------------------------------//
547 //-**** should also consider the combat level and hit_points of both unit ****-//
548 if(targetSpriteInfo->speed > sprite_info->speed)
549 returnFactor -= 5;
550
551 if(misc.random(returnFactor)==0) // return to camp if true
552 abortAction++;
553 else
554 return 1;
555 }
556
557 err_when(!abortAction);
558 err_when(action_mode==ACTION_ASSIGN_TO_FIRM); // if so, process_auto_defense_back_camp() cannot process successfully
559 process_auto_defense_back_camp();
560 return 0; // cancel attack
561 }
562 //----------- End of function Unit::defense_follow_target -----------//
563
564
565 //------------- Begin of function Unit::clear_unit_defense_mode --------------//
566 // clear defensive mode
567 //
clear_unit_defense_mode()568 void Unit::clear_unit_defense_mode()
569 {
570 //------- cancel defense mode and continue the current action -------//
571 action_mode2 = action_mode;
572 action_para2 = action_para;
573 action_x_loc2 = action_x_loc;
574 action_y_loc2 = action_y_loc;
575
576 reset_action_misc_para();
577
578 if( unit_mode == UNIT_MODE_DEFEND_TOWN )
579 set_mode(0); // reset unit mode
580 }
581 //----------------- End of function Unit::clear_unit_defense_mode ----------------//
582
583
584 //=================================================================================================//
585 // Town unit's defend mode, eg rebel
586 //=================================================================================================//
587
588 //--------- Begin of function Unit::defend_town_attack_unit ---------//
589 // set to defensive mode
590 //
591 // <short> targetRecno - record of target
592 //
defend_town_attack_unit(short targetRecno)593 void Unit::defend_town_attack_unit(short targetRecno)
594 {
595 action_mode2 = ACTION_DEFEND_TOWN_ATTACK_TARGET;
596 attack_unit(targetRecno);
597 }
598 //----------- End of function Unit::defend_town_attack_unit -----------//
599
600
601 //------------- Begin of function Unit::defend_town_detect_target --------------//
602 // set to detect mode
603 //
defend_town_detect_target()604 void Unit::defend_town_detect_target()
605 {
606 action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
607 action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
608 action_x_loc2 = -1;
609 action_y_loc2 = -1;
610 }
611 //----------- End of function Unit::defend_town_detect_target -----------//
612
613
614 //------------- Begin of function Unit::process_defend_town_attack_target --------------//
615 // defend town units is only allowed to attack unit
616 //
process_defend_town_attack_target()617 void Unit::process_defend_town_attack_target()
618 {
619 err_when(action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET);
620 if(general_defend_mode_process_attack_target())
621 {
622 action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
623 action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
624 action_x_loc2 = action_y_loc2 = -1;
625 err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
626 }
627 }
628 //----------------- End of function Unit::process_defend_town_attack_target ----------------//
629
630
631 //------------- Begin of function Unit::process_defend_town_detect_target --------------//
632 // process detect mode
633 //
process_defend_town_detect_target()634 void Unit::process_defend_town_detect_target()
635 {
636 err_when(action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET);
637 err_when(action_mode!=ACTION_STOP);
638 err_when(action_para!=0);
639 err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc2!=-1 || action_y_loc2!=-1);
640
641 //----------------------------------------------------------------//
642 // no target or target is out of detect range, so change state to
643 // back camp
644 //----------------------------------------------------------------//
645 if(!action_para2)
646 {
647 err_when(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para);
648 err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN || !unit_mode_para);
649 int back = 0;
650 Town *townPtr;
651 Unit *targetPtr;
652
653 if(town_array.is_deleted(action_misc_para))
654 back++;
655 else
656 {
657 townPtr = town_array[action_misc_para];
658 if(unit_array.is_deleted(townPtr->defend_target_recno))
659 back++;
660 else
661 {
662 targetPtr = unit_array[townPtr->defend_target_recno];
663 if(targetPtr->action_mode!=ACTION_ATTACK_TOWN || targetPtr->action_para!=townPtr->town_recno)
664 back++;
665 }
666 }
667
668 if(!back)
669 {
670 //action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
671 action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
672 return;
673 }
674
675 process_defend_town_back_town();
676 return;
677 }
678
679 //----------------------------------------------------------------//
680 // defense_detecting target algorithm
681 //----------------------------------------------------------------//
682 int startLoc;
683 int dimension;
684
685 switch(action_para2%GAME_FRAMES_PER_DAY)
686 {
687 case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
688 //### begin alex 3/10 ###//
689 dimension = 7;
690 //#### end alex 3/10 ####//
691 break;
692
693 case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
694 dimension = 8;
695 break;
696
697 case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
698 dimension = EFFECTIVE_DEFEND_TOWN_DISTANCE;
699 break;
700
701 default: action_para2--;
702 return;
703 }
704
705 //---------------------------------------------------------------//
706 // attack the target if target detected, or change the detect region
707 //---------------------------------------------------------------//
708
709 if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
710 action_para2--;
711 }
712 //----------------- End of function Unit::process_defend_town_detect_target ----------------//
713
714
715 //------------- Begin of function Unit::process_defend_town_back_town --------------//
716 // process action to go back town
717 //
process_defend_town_back_town()718 void Unit::process_defend_town_back_town()
719 {
720 int clearDefenseMode = 0;
721 if(action_mode!=ACTION_ASSIGN_TO_TOWN) // the unit may become idle or unable to reach town, reactivate it
722 {
723 Town *townPtr;
724 if(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para || town_array.is_deleted(action_misc_para))
725 clearDefenseMode++;
726 else
727 {
728 townPtr = town_array[action_misc_para];
729 if(townPtr->nation_recno!=nation_recno)
730 clearDefenseMode++;
731 else
732 {
733 defend_town_back_town(action_misc_para); // go back to the town
734 err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
735 return;
736 }
737 }
738 }
739 else if(cur_action==SPRITE_IDLE)
740 {
741 if(town_array.is_deleted(action_misc_para))
742 clearDefenseMode++;
743 else
744 {
745 defend_town_back_town(action_misc_para);
746 err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
747 return;
748 }
749 }
750
751 err_when(!clearDefenseMode);
752 //----------------------------------------------------------------//
753 // clear order if the town is deleted
754 //----------------------------------------------------------------//
755 stop2();
756 reset_action_misc_para();
757 err_when(in_defend_town_mode());
758 }
759 //----------------- End of function Unit::process_defend_town_back_town ----------------//
760
761
762 //------------- Begin of function Unit::in_defend_town_mode --------------//
763 // check whether the unit is in defend town mode
764 //
in_defend_town_mode()765 int Unit::in_defend_town_mode()
766 {
767 return (action_mode2>=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2<=ACTION_DEFEND_TOWN_BACK_TOWN);
768 }
769 //----------------- End of function Unit::in_defend_town_mode ----------------//
770
771
772 //--------- Begin of function Unit::defend_town_back_town ---------//
773 // set action to back town
774 //
775 // <int> townRecno - recno of the town
776 //
defend_town_back_town(short townRecno)777 void Unit::defend_town_back_town(short townRecno)
778 {
779 err_when(town_array.is_deleted(townRecno));
780 Town *townPtr = town_array[townRecno];
781
782 assign(townPtr->loc_x1, townPtr->loc_y1);
783 action_mode2 = ACTION_DEFEND_TOWN_BACK_TOWN;
784 }
785 //----------- End of function Unit::defend_town_back_town -----------//
786
787
788 //------------- Begin of function Unit::defend_town_follow_target --------------//
789 // check the unit should follow the target or not
790 //
791 // return 0 if aborting attack the current target and go back to military camp
792 // return 1 otherwise
793 //
defend_town_follow_target()794 int Unit::defend_town_follow_target()
795 {
796 err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN);
797
798 if(cur_action==SPRITE_ATTACK)
799 return 1;
800
801 if(town_array.is_deleted(unit_mode_para))
802 {
803 stop2(); //**** BUGHERE
804 set_mode(0); //***BUGHERE
805 return 0;
806 }
807
808 int curXLoc = next_x_loc();
809 int curYLoc = next_y_loc();
810
811 Town *townPtr = town_array[unit_mode_para];
812 if((curXLoc<townPtr->center_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) ||
813 (curYLoc<townPtr->center_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE))
814 {
815 defend_town_back_town(unit_mode_para);
816 return 0;
817 }
818
819 return 1;
820 }
821 //----------- End of function Unit::defend_town_follow_target -----------//
822
823
824 //------------- Begin of function Unit::clear_town_defend_mode --------------//
825 // clear defend mode
826 //
clear_town_defend_mode()827 void Unit::clear_town_defend_mode()
828 {
829 //------- cancel defense mode and continue the current action -------//
830 action_mode2 = action_mode;
831 action_para2 = action_para;
832 action_x_loc2 = action_x_loc;
833 action_y_loc2 = action_y_loc;
834
835 reset_action_misc_para();
836 }
837 //----------------- End of function Unit::clear_town_defend_mode ----------------//
838
839
840 //=================================================================================================//
841 // Monster unit's defend mode
842 //=================================================================================================//
843
844 //--------- Begin of function Unit::monster_defend_attack_unit ---------//
845 // set to attack target
846 //
847 // <short> targetRecno - recno of the target
848 //
monster_defend_attack_unit(short targetRecno)849 void Unit::monster_defend_attack_unit(short targetRecno)
850 {
851 action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
852 attack_unit(targetRecno);
853 }
854 //----------- End of function Unit::monster_defend_attack_unit -----------//
855
856
857 //--------- Begin of function Unit::monster_defend_attack_firm ---------//
858 // set monster to attack firm
859 //
860 // <int> targetXLoc - x location of firm
861 // <int> targetYLoc - y location of firm
862 //
monster_defend_attack_firm(int targetXLoc,int targetYLoc)863 void Unit::monster_defend_attack_firm(int targetXLoc, int targetYLoc)
864 {
865 action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
866 attack_firm(targetXLoc, targetYLoc);
867 }
868 //----------- End of function Unit::monster_defend_attack_firm -----------//
869
870
871 //--------- Begin of function Unit::monster_defend_attack_town ---------//
872 // set monster to attack town
873 //
874 // <int> targetXLoc - x location of the town
875 // <int> targetYLoc - y location of the town
876 //
monster_defend_attack_town(int targetXLoc,int targetYLoc)877 void Unit::monster_defend_attack_town(int targetXLoc, int targetYLoc)
878 {
879 action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
880 attack_town(targetXLoc, targetYLoc);
881 }
882 //----------- End of function Unit::monster_defend_attack_town -----------//
883
884
885 //--------- Begin of function Unit::monster_defend_attack_wall ---------//
886 // set monster to attack wall
887 //
888 // <int> targetXLoc - x location of wall
889 // <int> targetYLoc - y location of wall
890 //
monster_defend_attack_wall(int targetXLoc,int targetYLoc)891 void Unit::monster_defend_attack_wall(int targetXLoc, int targetYLoc)
892 {
893 action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
894 attack_wall(targetXLoc, targetYLoc);
895 }
896 //----------- End of function Unit::monster_defend_attack_wall -----------//
897
898
899 //--------- Begin of function Unit::monster_defend_detect_target ---------//
900 // set to detect mode
901 //
monster_defend_detect_target()902 void Unit::monster_defend_detect_target()
903 {
904 action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET;
905 action_para2 = MONSTER_DEFEND_DETECT_COUNT;
906 action_x_loc2 = -1;
907 action_y_loc2 = -1;
908 }
909 //----------- End of function Unit::monster_defend_detect_target -----------//
910
911
912 //--------- Begin of function Unit::monster_defend_back_firm ---------//
913 // set to return mode
914 //
monster_defend_back_firm(int firmXLoc,int firmYLoc)915 void Unit::monster_defend_back_firm(int firmXLoc, int firmYLoc)
916 {
917 err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_MONSTER);
918
919 assign(firmXLoc, firmYLoc);
920 action_mode2 = ACTION_MONSTER_DEFEND_BACK_FIRM;
921 }
922 //----------- End of function Unit::monster_defend_back_firm -----------//
923
924
925 //--------- Begin of function Unit::process_monster_defend_attack_target ---------//
926 // proces attack mode
927 //
process_monster_defend_attack_target()928 void Unit::process_monster_defend_attack_target()
929 {
930 err_when(action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);
931 if(general_defend_mode_process_attack_target())
932 {
933 monster_defend_detect_target();
934 err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
935 }
936 }
937 //----------- End of function Unit::process_monster_defend_attack_target -----------//
938
939
940 //--------- Begin of function Unit::process_monster_defend_detect_target ---------//
941 // process detect mode
942 //
process_monster_defend_detect_target()943 void Unit::process_monster_defend_detect_target()
944 {
945 err_when(action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET);
946 err_when(action_mode!=ACTION_STOP);
947 err_when(action_para!=0);
948 err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1);
949
950 //----------------------------------------------------------------//
951 // no target or target is out of detect range, so change state to
952 // back camp
953 //----------------------------------------------------------------//
954 if(!action_para2)
955 {
956 err_when(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para);
957 err_when(unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para);
958 int back = 0;
959 Unit *targetPtr;
960 FirmMonster *firmMonsterPtr;
961
962 if(firm_array.is_deleted(action_misc_para))
963 back++;
964 else
965 {
966 firmMonsterPtr = (FirmMonster*) firm_array[action_misc_para];
967 if(unit_array.is_deleted(firmMonsterPtr->defend_target_recno))
968 back++;
969 else
970 {
971 targetPtr = unit_array[firmMonsterPtr->defend_target_recno];
972 if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=firmMonsterPtr->firm_recno)
973 back++;
974 }
975 }
976
977 if(!back)
978 {
979 //action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET;
980 action_para2 = MONSTER_DEFEND_DETECT_COUNT;
981 return;
982 }
983
984 process_monster_defend_back_firm();
985 return;
986 }
987
988 //----------------------------------------------------------------//
989 // defense_detecting target algorithm
990 //----------------------------------------------------------------//
991 int startLoc;
992 int dimension;
993
994 switch(action_para2%GAME_FRAMES_PER_DAY)
995 {
996 case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
997 //### begin alex 3/10 ###//
998 dimension = 7;
999 //#### end alex 3/10 ####//
1000 break;
1001
1002 case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
1003 dimension = 8;
1004 break;
1005
1006 case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
1007 dimension = EFFECTIVE_MONSTER_DEFEND_FIRM_DISTANCE;
1008 break;
1009
1010 default: action_para2--;
1011 return;
1012 }
1013
1014 //---------------------------------------------------------------//
1015 // attack the target if target detected, or change the detect region
1016 //---------------------------------------------------------------//
1017 if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
1018 action_para2--;
1019 }
1020 //----------- End of function Unit::process_monster_defend_detect_target -----------//
1021
1022
1023 //--------- Begin of function Unit::process_monster_defend_back_firm ---------//
1024 // process return mode
1025 //
process_monster_defend_back_firm()1026 void Unit::process_monster_defend_back_firm()
1027 {
1028 int clearDefendMode = 0;
1029 if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it
1030 {
1031 Firm *firmPtr;
1032 if(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para))
1033 clearDefendMode++;
1034 else
1035 {
1036 firmPtr = firm_array[action_misc_para];
1037 if(firmPtr->firm_id!=FIRM_MONSTER || firmPtr->nation_recno!=nation_recno)
1038 clearDefendMode++;
1039 else
1040 {
1041 monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp
1042 err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM);
1043 return;
1044 }
1045 }
1046 }
1047 else if(cur_action==SPRITE_IDLE)
1048 {
1049 if(firm_array.is_deleted(action_misc_para))
1050 clearDefendMode++;
1051 else
1052 {
1053 Firm *firmPtr = firm_array[action_misc_para];
1054 monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1);
1055 err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM);
1056 return;
1057 }
1058 }
1059
1060 err_when(!clearDefendMode);
1061 //----------------------------------------------------------------//
1062 // clear order if the camp is deleted
1063 //----------------------------------------------------------------//
1064 stop2();
1065 reset_action_misc_para();
1066 err_when(in_monster_defend_mode());
1067 }
1068 //----------- End of function Unit::process_monster_defend_back_firm -----------//
1069
1070
1071 //------------- Begin of function Unit::in_monster_defend_mode --------------//
1072 // check whether the unit is in defend mode
1073 //
in_monster_defend_mode()1074 int Unit::in_monster_defend_mode()
1075 {
1076 return (action_mode2>=ACTION_MONSTER_DEFEND_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM);
1077 }
1078 //----------- End of function Unit::in_monster_defend_mode -----------//
1079
1080
1081 //------------- Begin of function Unit::monster_defend_follow_target --------------//
1082 // make decision to choose to follow target or return
1083 //
1084 // return 0 if aborting attack the current target and go back to military camp
1085 // return 1 otherwise
1086 //
monster_defend_follow_target()1087 int Unit::monster_defend_follow_target()
1088 {
1089 //######## begin trevor 22/8 ##########//
1090 err_when( unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para );
1091
1092 if(cur_action==SPRITE_ATTACK)
1093 return 1;
1094 /*
1095 if(firm_array.is_deleted(action_misc_para))
1096 {
1097 stop2(); //**** BUGHERE
1098 //set_mode(0); //***BUGHERE
1099 if(monster_array.is_deleted(unit_mode_para))
1100 return 0;
1101
1102 Monster *monsterPtr = monster_array[unit_mode_para];
1103 monsterPtr->firm_recno = 0;
1104 return 0;
1105 }
1106 */
1107 //######## end trevor 22/8 ##########//
1108
1109 //--------------------------------------------------------------------------------//
1110 // choose to return to firm
1111 //--------------------------------------------------------------------------------//
1112 int curXLoc = next_x_loc();
1113 int curYLoc = next_y_loc();
1114
1115 Firm *firmPtr = firm_array[action_misc_para];
1116 if((curXLoc<firmPtr->center_x-MONSTER_DEFEND_FIRM_DISTANCE) || (curXLoc>firmPtr->center_x+MONSTER_DEFEND_FIRM_DISTANCE) ||
1117 (curYLoc<firmPtr->center_y-MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoc>firmPtr->center_y+MONSTER_DEFEND_FIRM_DISTANCE))
1118 {
1119 monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1);
1120 return 0;
1121 }
1122
1123 return 1;
1124 }
1125 //----------- End of function Unit::monster_defend_follow_target -----------//
1126
1127
1128 //------------- Begin of function Unit::clear_monster_defend_mode --------------//
1129 // clear defend mode
1130 //
clear_monster_defend_mode()1131 void Unit::clear_monster_defend_mode()
1132 {
1133 err_when(!in_monster_defend_mode());
1134
1135 //------- cancel defense mode and continue the current action -------//
1136 action_mode2 = action_mode;
1137 action_para2 = action_para;
1138 action_x_loc2 = action_x_loc;
1139 action_y_loc2 = action_y_loc;
1140
1141 reset_action_misc_para();
1142 }
1143 //----------------- End of function Unit::clear_monster_defend_mode ----------------//
1144