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 : OUNITM.CPP
22 //Description : Object Unit misc. actions excluding attacking and moving functions
23 //Owner : Alex
24
25 #include <ALL.h>
26 #include <OWORLD.h>
27 #include <OFIRM.h>
28 #include <ONATION.h>
29 #include <ORACERES.h>
30 #include <OTOWN.h>
31 #include <OU_MARI.h>
32 #include <OF_CAMP.h>
33 #include <OREMOTE.h>
34 #include <OF_MONS.h>
35 #include <OU_GOD.h>
36 #include <OF_HARB.h>
37
38 #ifdef NO_DEBUG_UNIT
39 #undef err_when
40 #undef err_here
41 #undef err_if
42 #undef err_else
43 #undef err_now
44 #define err_when(cond)
45 #define err_here()
46 #define err_if(cond)
47 #define err_else
48 #define err_now(msg)
49 #undef DEBUG
50 #endif
51
52 //--------- Begin of function Unit::build_firm ---------//
53 // Build a firm.
54 //
55 // <int> buildXLoc, buildYLoc - the location to build
56 // <int> firmId - id. of the firm to build
57 //
58 // [char] remoteAction
59 //
build_firm(int buildXLoc,int buildYLoc,int firmId,char remoteAction)60 void Unit::build_firm(int buildXLoc, int buildYLoc, int firmId, char remoteAction)
61 {
62 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
63
64 if(!remoteAction && remote.is_enable() )
65 {
66 // packet structure : <unit recno> <xLoc> <yLoc> <firmId>
67 short *shortPtr =(short *)remote.new_send_queue_msg(MSG_UNIT_BUILD_FIRM, 4*sizeof(short) );
68 shortPtr[0] = sprite_recno;
69 shortPtr[1] = buildXLoc;
70 shortPtr[2] = buildYLoc;
71 shortPtr[3] = firmId;
72 return;
73 }
74
75 //----------------------------------------------------------------//
76 // return if the unit is dead
77 //----------------------------------------------------------------//
78 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
79 return;
80
81 //----------------------------------------------------------------//
82 // location is blocked, cannot build. so move there instead
83 //----------------------------------------------------------------//
84 if(!world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno))
85 {
86 //reset_action_para2();
87 move_to(buildXLoc, buildYLoc);
88 return;
89 }
90
91 //----------------------------------------------------------------//
92 // different territory
93 //----------------------------------------------------------------//
94
95 int harborDir = world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno);
96 int goX = buildXLoc, goY = buildYLoc;
97 if( firm_res[firmId]->tera_type == 4)
98 {
99 switch(harborDir)
100 {
101 case 1: // north exit
102 goX += 1;
103 goY += 2;
104 break;
105 case 2: // south exit
106 goX += 1;
107 break;
108 case 4: // west exit
109 goX += 2;
110 goY += 1;
111 break;
112 case 8: // east exit
113 goY += 1;
114 break;
115 default:
116 err_here();
117 move_to(buildXLoc, buildYLoc);
118 return;
119 }
120 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(goX,goY)->region_id)
121 {
122 move_to(buildXLoc, buildYLoc);
123 return;
124 }
125 }
126 else
127 {
128 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(buildXLoc, buildYLoc)->region_id)
129 {
130 move_to(buildXLoc, buildYLoc);
131 return;
132 }
133 }
134
135 //----------------------------------------------------------------//
136 // action_mode2: checking for equal action or idle action
137 //----------------------------------------------------------------//
138 if(action_mode2==ACTION_BUILD_FIRM && action_para2==firmId && action_x_loc2==buildXLoc && action_y_loc2==buildYLoc)
139 {
140 if(cur_action!=SPRITE_IDLE)
141 return;
142 }
143 else
144 {
145 //----------------------------------------------------------------//
146 // action_mode2: store new order
147 //----------------------------------------------------------------//
148 action_mode2 = ACTION_BUILD_FIRM;
149 action_para2 = firmId;
150 action_x_loc2 = buildXLoc;
151 action_y_loc2 = buildYLoc;
152 }
153
154 //----- order the sprite to stop as soon as possible -----//
155 stop(); // new order
156
157 //---------------- define parameters -------------------//
158 FirmInfo* firmInfo = firm_res[firmId];
159 int firmWidth = firmInfo->loc_width;
160 int firmHeight = firmInfo->loc_height;
161
162 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, buildXLoc, buildYLoc, firmWidth, firmHeight))
163 {
164 //----------- not in the firm surrounding ---------//
165 set_move_to_surround(buildXLoc, buildYLoc, firmWidth, firmHeight, BUILDING_TYPE_FIRM_BUILD, firmId);
166 }
167 else
168 {
169 //------- the unit is in the firm surrounding -------//
170 set_cur(next_x, next_y);
171 set_dir(move_to_x_loc, move_to_y_loc, buildXLoc+firmWidth/2, buildYLoc+firmHeight/2);
172 }
173
174 //----------- set action to build the firm -----------//
175 action_mode = ACTION_BUILD_FIRM;
176 action_para = firmId;
177 action_x_loc = buildXLoc;
178 action_y_loc = buildYLoc;
179 }
180 //----------- End of function Unit::build_firm -----------//
181
182
183 //--------- Begin of function Unit::burn ---------//
184 //
185 // Burn a locaiton
186 //
187 // <int> burnXLoc, burnYLoc - the location to burn
188 //
burn(int burnXLoc,int burnYLoc,char remoteAction)189 void Unit::burn(int burnXLoc, int burnYLoc, char remoteAction)
190 {
191 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
192
193 if( !remoteAction && remote.is_enable() )
194 {
195 // packet structure : <unit recno> <xLoc> <yLoc>
196 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_BURN, 3*sizeof(short) );
197 shortPtr[0] = sprite_recno;
198 shortPtr[1] = burnXLoc;
199 shortPtr[2] = burnYLoc;
200 return;
201 }
202
203 if(move_to_x_loc==burnXLoc && move_to_y_loc==burnYLoc)
204 return; // should not burn the unit itself
205
206 //----------------------------------------------------------------//
207 // return if the unit is dead
208 //----------------------------------------------------------------//
209 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
210 return;
211
212 //----------------------------------------------------------------//
213 // move there instead if ordering to different territory
214 //----------------------------------------------------------------//
215 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(burnXLoc, burnYLoc)->region_id)
216 {
217 move_to(burnXLoc, burnYLoc);
218 return;
219 }
220
221 //----------------------------------------------------------------//
222 // action_mode2: checking for equal action or idle action
223 //----------------------------------------------------------------//
224 if(action_mode2==ACTION_BURN && action_x_loc2==burnXLoc && action_y_loc2==burnYLoc)
225 {
226 if(cur_action!=SPRITE_IDLE)
227 return;
228 }
229 else
230 {
231 //----------------------------------------------------------------//
232 // action_mode2: store new order
233 //----------------------------------------------------------------//
234 action_mode2 = ACTION_BURN;
235 action_para2 = 0;
236 action_x_loc2 = burnXLoc;
237 action_y_loc2 = burnYLoc;
238 }
239
240 //----- order the sprite to stop as soon as possible -----//
241 stop(); // new order
242
243 if(abs(burnXLoc-next_x_loc())>1 || abs(burnYLoc-next_y_loc())>1)
244 {
245 //--- if the unit is not in the burning surrounding location, move there first ---//
246 search(burnXLoc, burnYLoc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
247
248 if(move_to_x_loc != burnXLoc || move_to_y_loc != burnYLoc) // cannot reach the destination
249 {
250 action_mode = ACTION_BURN;
251 action_para = 0;
252 action_x_loc = burnXLoc;
253 action_y_loc = burnYLoc;
254 return; // just move to the closest location returned by shortest path searching
255 }
256 }
257 else
258 {
259 if(cur_x==next_x && cur_y==next_y)
260 set_dir(next_x_loc(), next_y_loc(), burnXLoc, burnYLoc);
261
262 err_when((cur_x!=next_x || cur_y!=next_y) && (check_unit_dir1=get_dir(cur_x,cur_y,next_x,next_y))!=final_dir);
263 err_when(result_node_array || result_node_count || result_path_dist);
264 }
265
266 //--------------------------------------------------------//
267 // edit the result path such that the unit can reach the
268 // burning location surrounding
269 //--------------------------------------------------------//
270 if(result_node_array && result_node_count)
271 {
272 //--------------------------------------------------------//
273 // there should be at least two nodes, and should take at
274 // least two steps to the destination
275 //--------------------------------------------------------//
276 err_when(move_to_x_loc!=burnXLoc || move_to_y_loc!=burnYLoc);
277 err_when(result_node_count<2);
278
279 ResultNode* lastNode1 = result_node_array+result_node_count-1; // the last node
280 ResultNode* lastNode2 = result_node_array+result_node_count-2; // the node before the last node
281
282 int vX = lastNode1->node_x-lastNode2->node_x; // get the vectors direction
283 int vY = lastNode1->node_y-lastNode2->node_y;
284 int vDirX = (vX) ? vX/abs(vX) : 0;
285 int vDirY = (vY) ? vY/abs(vY) : 0;
286
287 if(result_node_count>2) // go_? should not be the burning location
288 {
289 err_when(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc);
290 err_when(vX!=0 && vY!=0 && abs(vX)!=abs(vY));
291
292 if(abs(vX)>1 || abs(vY)>1)
293 {
294 lastNode1->node_x -= vDirX;
295 lastNode1->node_y -= vDirY;
296
297 move_to_x_loc = lastNode1->node_x;
298 move_to_y_loc = lastNode1->node_y;
299 }
300 else // move only one step
301 {
302 result_node_count--; // remove a node
303 move_to_x_loc = lastNode2->node_x;
304 move_to_y_loc = lastNode2->node_y;
305 }
306 }
307 else // go_? may be the burning location
308 {
309 err_when(result_node_count!=2);
310
311 lastNode1->node_x -= vDirX;
312 lastNode1->node_y -= vDirY;
313
314 if(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc) // go_? is the burning location
315 {
316 //--- edit parameters such that only moving to the nearby location to do the action ---//
317 err_when(abs(vX)<=1 && abs(vY)<=1); // this case should be handled before
318
319 go_x = lastNode1->node_x * ZOOM_LOC_WIDTH;
320 go_y = lastNode1->node_y * ZOOM_LOC_HEIGHT;
321 }
322 //else the unit is still doing sthg else, no action here
323
324 move_to_x_loc = lastNode1->node_x;
325 move_to_y_loc = lastNode1->node_y;
326 }
327
328 //--------------------------------------------------------------//
329 // reduce the result_path_dist by 1
330 //--------------------------------------------------------------//
331 result_path_dist--;
332
333 #ifdef DEBUG
334 ResultNode *preNode = result_node_array;
335 ResultNode *curNode = result_node_array+1;
336 int debugCount=1;
337 int debugDist = 0;
338 int xDist = abs(next_x_loc()-preNode->node_x);
339 int yDist = abs(next_y_loc()-preNode->node_y);
340 debugDist -= (xDist) ? xDist : yDist;
341
342 while(debugCount++ < result_node_count)
343 {
344 err_when(debugCount>1000);
345 xDist = abs(preNode->node_x - curNode->node_x);
346 yDist = abs(preNode->node_y - curNode->node_y);
347 debugDist += (xDist) ? xDist : yDist;
348 preNode++;
349 curNode++;
350 }
351
352 err_when(result_path_dist!=debugDist);
353 #endif
354
355 err_when((cur_x!=next_x || cur_y!=next_y) && // is not blocked
356 (check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
357 }
358
359 err_when(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, burnXLoc, burnYLoc, 1, 1));
360
361 //-- set action if the burning location can be reached, otherwise just move nearby --//
362 action_mode = ACTION_BURN;
363 action_para = 0;
364 action_x_loc = burnXLoc;
365 action_y_loc = burnYLoc;
366 }
367 //----------- End of function Unit::burn -----------//
368
369
370 //--------- Begin of function Unit::settle ---------//
371 //
372 // settle to a town
373 //
374 // <int> settleXLoc, settleYLoc - the location to settle
375 // [short] curSettleUnitNum - the number to call this function by
376 // a group of unit. (default: 1)
377 //
settle(int settleXLoc,int settleYLoc,short curSettleUnitNum)378 void Unit::settle(int settleXLoc, int settleYLoc, short curSettleUnitNum)
379 {
380 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
381
382 //----------------------------------------------------------------//
383 // return if the unit is dead
384 //----------------------------------------------------------------//
385 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
386 return;
387
388 //---------- no settle for non-human -----------//
389 if(unit_res[unit_id]->unit_class!=UNIT_CLASS_HUMAN)
390 return;
391
392 //----------------------------------------------------------------//
393 // move there if cannot settle
394 //----------------------------------------------------------------//
395 if(!world.can_build_town(settleXLoc, settleYLoc, sprite_recno))
396 {
397 Location *locPtr = world.get_loc(settleXLoc, settleYLoc);
398 if(locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno==nation_recno)
399 assign(settleXLoc, settleYLoc);
400 else
401 move_to(settleXLoc, settleYLoc);
402 return;
403 }
404
405 //----------------------------------------------------------------//
406 // move there if location is in different territory
407 //----------------------------------------------------------------//
408 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(settleXLoc, settleYLoc)->region_id)
409 {
410 move_to(settleXLoc, settleYLoc);
411 return;
412 }
413
414 //----------------------------------------------------------------//
415 // action_mode2: checking for equal action or idle action
416 //----------------------------------------------------------------//
417 if(action_mode2==ACTION_SETTLE && action_x_loc2==settleXLoc && action_y_loc2==settleYLoc)
418 {
419 if(cur_action!=SPRITE_IDLE)
420 return;
421 }
422 else
423 {
424 //----------------------------------------------------------------//
425 // action_mode2: store new order
426 //----------------------------------------------------------------//
427 action_mode2 = ACTION_SETTLE;
428 action_para2 = 0;
429 action_x_loc2 = settleXLoc;
430 action_y_loc2 = settleYLoc;
431 }
432
433 //----- order the sprite to stop as soon as possible -----//
434 stop(); // new order
435
436 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, settleXLoc, settleYLoc,
437 STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
438 {
439 //------------ not in the town surrounding ------------//
440 set_move_to_surround(settleXLoc, settleYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_SETTLE, 0, 0, curSettleUnitNum);
441 }
442 else
443 {
444 //------- the unit is within the settle location -------//
445 set_cur(next_x, next_y);
446 set_dir(move_to_x_loc, move_to_y_loc, settleXLoc+STD_TOWN_LOC_WIDTH/2, settleYLoc+STD_TOWN_LOC_HEIGHT/2);
447 }
448
449 //----------- set action to settle -----------//
450 action_mode = ACTION_SETTLE;
451 action_para = 0;
452 action_x_loc = settleXLoc;
453 action_y_loc = settleYLoc;
454 }
455 //----------- End of function Unit::settle -----------//
456
457
458 //--------- Begin of function Unit::assign ---------//
459 //
460 // Assign an unit to :
461 //
462 // - a firm as an overseer, as a worker
463 // - a town as a citizen
464 // - a vehicle
465 //
466 // <int> buildXLoc, buildYLoc - the location to build
467 //
assign(int assignXLoc,int assignYLoc,short curAssignUnitNum)468 void Unit::assign(int assignXLoc, int assignYLoc, short curAssignUnitNum)
469 {
470 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
471
472 //----------------------------------------------------------------//
473 // return if the unit is dead
474 //----------------------------------------------------------------//
475 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
476 return;
477
478 //----------- cannot assign for caravan -----------//
479 if(unit_id==UNIT_CARAVAN)
480 return;
481
482 //----------------------------------------------------------------//
483 // move there if the destination in other territory
484 //----------------------------------------------------------------//
485 Location *locPtr = world.get_loc(assignXLoc, assignYLoc);
486 uint8_t unitRegionId = world.get_loc(next_x_loc(), next_y_loc())->region_id;
487 if(locPtr->is_firm())
488 {
489 Firm *firmPtr = firm_array[locPtr->firm_recno()];
490 int quit = 0;
491
492 if(firmPtr->firm_id==FIRM_HARBOR)
493 {
494 FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
495 switch(unit_res[unit_id]->unit_class)
496 {
497 case UNIT_CLASS_HUMAN:
498 if(unitRegionId != harborPtr->land_region_id)
499 quit = 1;
500 break;
501
502 case UNIT_CLASS_SHIP:
503 if(unitRegionId != harborPtr->sea_region_id)
504 quit = 1;
505 break;
506
507 default: err_here();
508 break;
509 }
510 }
511 else if(unitRegionId!=locPtr->region_id)
512 quit = 1;
513
514 if(quit)
515 {
516 move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
517 return;
518 }
519 }
520 else if(unitRegionId!=locPtr->region_id)
521 {
522 if(locPtr->is_town())
523 move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
524 /*else if(locPtr->has_unit(UNIT_LAND))
525 {
526 Unit *unitPtr = unit_array[locPtr->unit_recno(UNIT_LAND)];
527 move_to_unit_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, unitPtr->sprite_recno);
528 }*/
529
530 return;
531 }
532
533 //---------------- define parameters --------------------//
534 int width, height;
535 int buildingType=0; // 1 for Firm, 2 for TownZone
536 short recno;
537 int firmNeedUnit=1;
538
539 if(locPtr->is_firm())
540 {
541 //-------------------------------------------------------//
542 // the location is firm
543 //-------------------------------------------------------//
544 recno = locPtr->firm_recno();
545
546 //----------------------------------------------------------------//
547 // action_mode2: checking for equal action or idle action
548 //----------------------------------------------------------------//
549 if(action_mode2==ACTION_ASSIGN_TO_FIRM && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
550 {
551 if(cur_action!=SPRITE_IDLE)
552 return;
553 }
554 else
555 {
556 //----------------------------------------------------------------//
557 // action_mode2: store new order
558 //----------------------------------------------------------------//
559 action_mode2 = ACTION_ASSIGN_TO_FIRM;
560 action_para2 = recno;
561 action_x_loc2 = assignXLoc;
562 action_y_loc2 = assignYLoc;
563 }
564
565 Firm *firmPtr = firm_array[recno];
566 FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
567
568 if(!firm_can_assign(recno))
569 {
570 //firmNeedUnit = 0; // move to the surrounding of the firm
571 move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
572 return;
573 }
574
575 width = firmInfo->loc_width;
576 height = firmInfo->loc_height;
577 buildingType = BUILDING_TYPE_FIRM_MOVE_TO;
578 }
579 else if(locPtr->is_town()) // there is town
580 {
581 if(unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN)
582 return;
583
584 //-------------------------------------------------------//
585 // the location is town
586 //-------------------------------------------------------//
587 recno = locPtr->town_recno();
588
589 //----------------------------------------------------------------//
590 // action_mode2: checking for equal action or idle action
591 //----------------------------------------------------------------//
592 if(action_mode2==ACTION_ASSIGN_TO_TOWN && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
593 {
594 if(cur_action!=SPRITE_IDLE)
595 return;
596 }
597 else
598 {
599 //----------------------------------------------------------------//
600 // action_mode2: store new order
601 //----------------------------------------------------------------//
602 action_mode2 = ACTION_ASSIGN_TO_TOWN;
603 action_para2 = recno;
604 action_x_loc2 = assignXLoc;
605 action_y_loc2 = assignYLoc;
606 }
607
608 Town *targetTown = town_array[recno];
609 if(town_array[recno]->nation_recno != nation_recno)
610 {
611 move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
612 return;
613 }
614
615 width = targetTown->loc_width();
616 height = targetTown->loc_height();
617 buildingType = BUILDING_TYPE_TOWN_MOVE_TO;
618 }
619 /*else if(locPtr->has_unit(UNIT_LAND)) // there is vehicle
620 {
621 //-------------------------------------------------------//
622 // the location is vehicle
623 //-------------------------------------------------------//
624 Unit* vehicleUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
625 if( vehicleUnit->unit_id!=unit_res[unit_id]->vehicle_id )
626 return;
627
628 recno = vehicleUnit->sprite_recno;
629
630 //----------------------------------------------------------------//
631 // action_mode2: checking for equal action or idle action
632 //----------------------------------------------------------------//
633 if(action_mode2==ACTION_ASSIGN_TO_VEHICLE && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
634 {
635 if(cur_action!=SPRITE_IDLE)
636 return;
637 }
638 else
639 {
640 //----------------------------------------------------------------//
641 // action_mode2: store new order
642 //----------------------------------------------------------------//
643 action_mode2 = ACTION_ASSIGN_TO_VEHICLE;
644 action_para2 = recno;
645 action_x_loc2 = assignXLoc;
646 action_y_loc2 = assignYLoc;
647 }
648
649 SpriteInfo* spriteInfo = vehicleUnit->sprite_info;
650 width = spriteInfo->loc_width;
651 height = spriteInfo->loc_height;
652 buildingType = BUILDING_TYPE_VEHICLE;
653 }*/
654 else
655 {
656 stop2(KEEP_DEFENSE_MODE);
657 return;
658 }
659
660 //-----------------------------------------------------------------//
661 // order the sprite to stop as soon as possible (new order)
662 //-----------------------------------------------------------------//
663 stop();
664 set_move_to_surround(assignXLoc, assignYLoc, width, height, buildingType, 0, 0, curAssignUnitNum);
665
666 //-----------------------------------------------------------------//
667 // able to reach building surrounding, set action parameters
668 //-----------------------------------------------------------------//
669 action_para = recno;
670 action_x_loc = assignXLoc;
671 action_y_loc = assignYLoc;
672
673 switch(buildingType)
674 {
675 case BUILDING_TYPE_FIRM_MOVE_TO:
676 action_mode = ACTION_ASSIGN_TO_FIRM;
677 break;
678
679 case BUILDING_TYPE_TOWN_MOVE_TO:
680 action_mode = ACTION_ASSIGN_TO_TOWN;
681 break;
682
683 case BUILDING_TYPE_VEHICLE:
684 action_mode = ACTION_ASSIGN_TO_VEHICLE;
685 break;
686 }
687
688 //##### begin trevor 9/10 #######//
689
690 // force_move_flag = 1; // don't stop and fight back on an assign mission
691
692 //##### end trevor 9/10 #######//
693
694 //-----------------------------------------------------------------//
695 // edit parameters for those firms don't need unit
696 //-----------------------------------------------------------------//
697 /*if(!firmNeedUnit)
698 {
699 action_mode2 = action_mode = ACTION_MOVE;
700 action_para2 = action_para = 0;
701 action_x_loc2 = action_x_loc = move_to_x_loc;
702 action_y_loc2 = action_y_loc = move_to_y_loc;
703 }*/
704 }
705 //----------- End of function Unit::assign -----------//
706
707
708 //--------- Begin of function Unit::firm_can_assign ---------//
709 // return 1 for true, i.e. unit can assign to the firm
710 // return 2 for assigning leader
711 // return 3 for repair
712 // return 4 for spy assigning to inn
713 // return 5 for capture (not used)
714 // return 0 otherwise
715 //
firm_can_assign(short firmRecno)716 int Unit::firm_can_assign(short firmRecno)
717 {
718 Firm *firmPtr = firm_array[firmRecno];
719 FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
720
721 switch( unit_res[unit_id]->unit_class )
722 {
723 case UNIT_CLASS_HUMAN:
724 if( nation_recno == firmPtr->nation_recno )
725 {
726 if( skill.skill_id == SKILL_CONSTRUCTION && firmPtr->firm_id != FIRM_MONSTER)
727 {
728 return 3;
729 }
730
731 // ###### begin Gilbert 22/10 #######//
732 //----------------------------------------//
733 // If this is a spy, then he can only be
734 // assigned to an enemy firm when there is
735 // space for the unit.
736 //----------------------------------------//
737
738 //if( spy_recno && true_nation_recno() != firmPtr->nation_recno )
739 //{
740 // if( rank_id == RANK_GENERAL )
741 // {
742 // if( firmPtr->overseer_recno )
743 // return 0;
744 // }
745 // else
746 // {
747 // if( firmPtr->worker_count == MAX_WORKER )
748 // return 0;
749 // }
750 //}
751 //--------------------------------------//
752 // ###### end Gilbert 22/10 #######//
753
754 switch( firmPtr->firm_id )
755 {
756 case FIRM_CAMP:
757 return rank_id == RANK_SOLDIER ? 1 : 2;
758
759 case FIRM_BASE:
760 if(race_id == firmPtr->race_id)
761 {
762 if( !skill.skill_id || skill.skill_id==SKILL_PRAYING) // non-skilled worker
763 return 1;
764 if( rank_id != RANK_SOLDIER )
765 return 2;
766 }
767 break;
768
769 //case FIRM_INN:
770 // shealthed soldier spy can assign to inn
771 // return rank_id == RANK_SOLDIER && nation_recno != true_nation_recno() ? 4 : 0;
772
773 default:
774 return rank_id == RANK_SOLDIER && firmInfo->need_unit() ? 1 : 0;
775 }
776 }
777 break;
778
779 case UNIT_CLASS_WEAPON:
780 if(firmPtr->firm_id == FIRM_CAMP && nation_recno == firmPtr->nation_recno)
781 return 1;
782 break;
783
784 case UNIT_CLASS_SHIP:
785 if(firmPtr->firm_id == FIRM_HARBOR && nation_recno == firmPtr->nation_recno)
786 return 1;
787 break;
788
789 case UNIT_CLASS_MONSTER:
790 if(firmPtr->firm_id == FIRM_MONSTER && mobile_type == UNIT_LAND)
791 {
792 // BUGHERE : suppose only land monster can assign
793 return rank_id == RANK_SOLDIER ? 1 : 2;
794 }
795 break;
796
797 case UNIT_CLASS_GOD:
798 case UNIT_CLASS_CARAVAN:
799 break;
800 default:
801 err_here(); // undefined unit class
802 }
803
804 return 0;
805 }
806 //----------- End of function Unit::firm_can_assign -----------//
807
808
809 //--------- Begin of function Unit::set_move_to_surround ---------//
810 // Mode 1:
811 // return 1 if the unit can reach the surrounding of the firm
812 // return 0 otherwise.
813 //
814 // Mode 2:
815 // In this mode, the unit calling this function is ordered to move to
816 // location a little bit away from the surrounding of the object.
817 //
818 // return 1 if the unit can move to there
819 // return 0 otherwise
820 //
821 // <int> buildXLoc - upper left x location of the building (firm/town)
822 // <int> buildYLoc - upper left y location of the building
823 // <int> width - width of the building
824 // <int> height - height of the building
825 // <int> buildingType - used to determine how searching is processed
826 // [int] miscNo - firm_id of firm if buildingType==BUILDING_TYPE_FIRM_BUILD
827 // - 0 for group search (for wall, firm)
828 // - 1 for a unit search
829 // [short] readyDist - the extra distance the unit stands from the building
830 // (default 0, i.e. the surrounding of the building)
831 // [short] curProcessUnitNum - the cur unit no. in a group calling this function
832 // (default 1)
833 //
834 //============================================================================//
835 // Note: This funcion should not change any action parameters
836 //============================================================================//
837 //
set_move_to_surround(int buildXLoc,int buildYLoc,int width,int height,int buildingType,int miscNo,int readyDist,short curProcessUnitNum)838 int Unit::set_move_to_surround(int buildXLoc, int buildYLoc, int width, int height, int buildingType, int miscNo, int readyDist, short curProcessUnitNum)
839 {
840 err_when(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE);
841
842 //--------------------------------------------------------------//
843 // calculate the distance from the object
844 //--------------------------------------------------------------//
845 int found=0, foundAgain=0;
846 int distance = cal_distance(buildXLoc, buildYLoc, width, height); // 0 for inside, 1 for surrounding, >1 for the rest
847
848 //--------------------------------------------------------------//
849 // inside the building
850 //--------------------------------------------------------------//
851 if(!distance)
852 {
853 reset_path();
854 if(cur_x==next_x && cur_y==next_y)
855 set_idle();
856
857 return 1;
858 }
859
860 if(distance>1)
861 {
862 //--------------------------------------------------------------//
863 // the searching is divided into 2 parts.
864 //
865 // part 1 using the firm_type and firm_id to find a shortest path.
866 //
867 // part 2
868 // if the width and height is the actual width and height of the
869 // firm, the unit move to the surrounding of the firm.
870 //
871 // if the width and height > the actual width and height of the
872 // firm, the unit move to a location far away from the surrounding
873 // of the firm.
874 //--------------------------------------------------------------//
875
876 //====================================================================//
877 // part 1
878 //====================================================================//
879
880 Location *locPtr = world.get_loc( buildXLoc, buildYLoc );
881 Firm *firmPtr = NULL;
882 Town *targetTown = NULL;
883 int searchResult;
884
885 switch(buildingType)
886 {
887 case BUILDING_TYPE_FIRM_MOVE_TO: // (assign) firm is on the location
888 firmPtr = firm_array[locPtr->firm_recno()];
889 searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, firmPtr->firm_id, curProcessUnitNum);
890 break;
891
892 case BUILDING_TYPE_FIRM_BUILD: // (build firm) no firm on the location
893 err_when(sprite_info->loc_width>1);
894 searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, miscNo);
895 break;
896
897 case BUILDING_TYPE_TOWN_MOVE_TO: // (assign) town is on the location
898 targetTown = town_array[locPtr->town_recno()];
899 searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, targetTown->town_recno, curProcessUnitNum);
900 break;
901
902 case BUILDING_TYPE_SETTLE: // (settle, first unit) no town on the location
903 //---------------------------------------------------------------------//
904 // the record number sent to the searching algorithm is used to determine
905 // the width and the height of the building. However, the standard
906 // dimension for settling is used and the building built is a type of
907 // town. Thus, passing -1 as the recno. to show that "settle" is
908 // processed
909 //---------------------------------------------------------------------//
910 err_when(sprite_info->loc_width>1);
911 searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, -1, curProcessUnitNum);
912 break;
913
914 case BUILDING_TYPE_VEHICLE:
915 err_when(sprite_info->loc_width>1);
916 searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_VEHICLE, (short)world.get_loc(buildXLoc, buildYLoc)->cargo_recno);
917 break;
918
919 case BUILDING_TYPE_WALL: // wall is on the location
920 err_when(miscNo!=0 && miscNo!=1);
921 searchResult = search(buildXLoc, buildYLoc, 1, miscNo?SEARCH_MODE_TO_WALL_FOR_UNIT:SEARCH_MODE_TO_WALL_FOR_GROUP);
922 break;
923
924 default: err_here();
925 break;
926 }
927
928 if(!searchResult)
929 return 0; // incomplete searching
930
931 //====================================================================//
932 // part 2
933 //====================================================================//
934 if(result_node_array && result_node_count)
935 return edit_path_to_surround(buildXLoc, buildYLoc, buildXLoc+width-1, buildYLoc+height-1, readyDist);
936 else
937 return 0;
938 }
939 else // in the surrounding, no need to move
940 {
941 reset_path();
942 err_when(distance!=1);
943
944 if(cur_x==next_x && cur_y==next_y)
945 {
946 move_to_x_loc = next_x_loc();
947 move_to_y_loc = next_y_loc();
948 go_x = cur_x;
949 go_y = cur_y;
950 set_idle();
951 set_dir(move_to_x_loc, move_to_y_loc, buildXLoc + width/2, buildYLoc + height/2);
952
953 err_when(result_node_array!=NULL);
954 }
955
956 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
957 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
958 return 1;
959 }
960 }
961 //----------- End of function Unit::set_move_to_surround -----------//
962
963
964 //--------- Begin of function Unit::edit_path_to_surround ---------//
965 // edit the path such that the unit only move to the surrounding of the firm
966 //
967 // <int> objectXLoc1, objectYLoc1 - object top_left position
968 // <int> objectXLoc2, objectYLoc2 - object bottom_right position
969 // <short> readyDist - the extra distance the unit stands from the building
970 // (default 0, i.e. the surrounding of the building)
971 //
972 // return 1 if able to reach object surrounding
973 // return 0 otherwise
974 //
edit_path_to_surround(int objectXLoc1,int objectYLoc1,int objectXLoc2,int objectYLoc2,int readyDist)975 int Unit::edit_path_to_surround(int objectXLoc1, int objectYLoc1, int objectXLoc2, int objectYLoc2, int readyDist)
976 {
977 err_when(!result_node_array || !result_node_count);
978 if(result_node_count<2)
979 return 0;
980
981 //----------------------------------------------------------------------------//
982 // At this moment, the unit generally has a path to the location inside the object,
983 // walk through it and extract a path to the surrounding of the object.
984 //----------------------------------------------------------------------------//
985
986 //------- calculate the surrounding top-left and bottom-right points ------//
987 int moveScale = move_step_magn();
988 int xLoc1 = objectXLoc1 - readyDist - 1;
989 int yLoc1 = objectYLoc1 - readyDist - 1;
990 int xLoc2 = objectXLoc2 + readyDist + 1;
991 int yLoc2 = objectYLoc2 + readyDist + 1;
992
993 //------------------- boundary checking -------------------//
994 if(xLoc1<0) xLoc1 = 0;
995 if(yLoc1<0) yLoc1 = 0;
996 if(xLoc2>=MAX_WORLD_X_LOC) yLoc1 = MAX_WORLD_X_LOC - moveScale;
997 if(yLoc2>=MAX_WORLD_Y_LOC) xLoc2 = MAX_WORLD_Y_LOC - moveScale;
998
999 //--------------- adjust for air and sea units -----------------//
1000 if(mobile_type!=UNIT_LAND)
1001 {
1002 //------ assume even x, y coordinate is used for UNIT_SEA and UNIT_AIR -------//
1003 if(xLoc1%2) xLoc1--;
1004 if(yLoc1%2) yLoc1--;
1005 if(xLoc2%2) xLoc2++;
1006 if(yLoc2%2) yLoc2++;
1007
1008 if(xLoc2>MAX_WORLD_X_LOC-moveScale)
1009 xLoc2 = MAX_WORLD_X_LOC-moveScale;
1010 if(yLoc2>MAX_WORLD_Y_LOC-moveScale)
1011 yLoc2 = MAX_WORLD_Y_LOC-moveScale;
1012
1013 err_when(xLoc1<0 || yLoc1<0);
1014 err_when(xLoc2>MAX_WORLD_X_LOC-moveScale || yLoc2>MAX_WORLD_Y_LOC-moveScale);
1015 }
1016
1017 int checkXLoc = next_x_loc();
1018 int checkYLoc = next_y_loc();
1019 ResultNode *editNode1 = result_node_array; // alias the unit's result_node_array
1020 ResultNode *editNode2 = result_node_array + 1; // ditto
1021
1022
1023 int hasMoveStep = 0;
1024 if(checkXLoc!=editNode1->node_x || checkYLoc!=editNode1->node_y)
1025 {
1026 err_when(abs(checkXLoc-editNode1->node_x)>moveScale || abs(checkYLoc-editNode1->node_y)>moveScale);
1027 hasMoveStep += moveScale;
1028 checkXLoc = editNode1->node_x;
1029 checkYLoc = editNode1->node_y;
1030 }
1031
1032 int i, j;
1033 int pathDist=0, found=0; // pathDist - counts the disitance of the generated path, found - whether a path to the surrounding is found
1034 int vecX, vecY, xMagn, yMagn, magn;
1035
1036 #ifdef DEBUG
1037 int debugLoop1 = 0;
1038 int debugLoop2 = 0;
1039 #endif
1040
1041 //------- find the first node that is on the surrounding of the object -------//
1042 for(i=1; i<result_node_count; ++i, editNode1++, editNode2++)
1043 {
1044 #ifdef DEBUG
1045 err_when(++debugLoop1>10000);
1046 #endif
1047
1048 //------------ calculate parameters for checking ------------//
1049 vecX = editNode2->node_x - editNode1->node_x;
1050 vecY = editNode2->node_y - editNode1->node_y;
1051 err_when(vecX==0 && vecY==0);
1052
1053 magn = ((xMagn=abs(vecX)) > (yMagn=abs(vecY))) ? xMagn : yMagn;
1054 if(xMagn)
1055 {
1056 vecX /= xMagn;
1057 vecX *= moveScale;
1058 }
1059 if(yMagn)
1060 {
1061 vecY /= yMagn;
1062 vecY *= moveScale;
1063 }
1064 err_when(abs(vecX)>moveScale && abs(vecY)>moveScale);
1065
1066 #ifdef DEBUG
1067 debugLoop2 = 0;
1068 #endif
1069 //------------- check each location bewteen editNode1 and editNode2 -------------//
1070 for(j=0; j<magn; j+=moveScale)
1071 {
1072 #ifdef DEBUG
1073 err_when(++debugLoop2>10000);
1074 #endif
1075
1076 checkXLoc += vecX;
1077 checkYLoc += vecY;
1078
1079 if(checkXLoc>=xLoc1 && checkXLoc<=xLoc2 && checkYLoc>=yLoc1 && checkYLoc<=yLoc2)
1080 {
1081 found++;
1082 break;
1083 }
1084 }
1085
1086 //-------------------------------------------------------------------------------//
1087 // a path is found, then set unit's parameters for its movement
1088 //-------------------------------------------------------------------------------//
1089 if(found)
1090 {
1091 editNode2->node_x = checkXLoc;
1092 editNode2->node_y = checkYLoc;
1093
1094 if(i==1) // first editing
1095 {
1096 ResultNode *firstNodePtr = result_node_array;
1097 if(cur_x==firstNodePtr->node_x*ZOOM_LOC_WIDTH && cur_y==firstNodePtr->node_y*ZOOM_LOC_HEIGHT)
1098 {
1099 go_x = checkXLoc * ZOOM_LOC_WIDTH;
1100 go_y = checkYLoc * ZOOM_LOC_HEIGHT;
1101 }
1102 }
1103
1104 pathDist += (j+moveScale);
1105 pathDist -= hasMoveStep;
1106 result_node_count = i+1;
1107 result_path_dist = pathDist;
1108 move_to_x_loc = checkXLoc;
1109 move_to_y_loc = checkYLoc;
1110 break;
1111 }
1112 else
1113 pathDist += magn;
1114 }
1115
1116 return found;
1117 }
1118 //----------- End of function Unit::edit_path_to_surround -----------//
1119
1120
1121 //--------- Begin of function Unit::is_in_surrounding ---------//
1122 // Test whether the location (checkXLoc, checkYLoc) is in the surrounding of an object
1123 //
1124 // <int> checkXLoc, checkYLoc - location to check
1125 // <int> width - the width of the caller
1126 // <int> ObjectXLoc, objectYLoc - object location
1127 // <int> objectWidth - object width
1128 // <int> objectHeight - object height
1129 //
1130 // Note: assume the width and the height of the caller is equal
1131 // return 1 if in object surrounding
1132 // return 0 otherwise
1133 //
is_in_surrounding(int checkXLoc,int checkYLoc,int width,int objectXLoc,int objectYLoc,int objectWidth,int objectHeight)1134 int Unit::is_in_surrounding(int checkXLoc, int checkYLoc, int width, int objectXLoc, int objectYLoc,
1135 int objectWidth, int objectHeight)
1136 {
1137 switch(move_step_magn())
1138 {
1139 case 1:
1140 if(checkXLoc>=objectXLoc-width && checkXLoc<=objectXLoc+objectWidth &&
1141 checkYLoc>=objectYLoc-width && checkYLoc<=objectYLoc+objectHeight)
1142 return 1;
1143 break;
1144
1145 case 2:
1146 if(checkXLoc>=objectXLoc-width-1 && checkXLoc<=objectXLoc+objectWidth+1 &&
1147 checkYLoc>=objectYLoc-width-1 && checkYLoc<=objectYLoc+objectHeight+1)
1148 return 1;
1149 break;
1150
1151 default: err_here();
1152 break;
1153 }
1154
1155 return 0;
1156 }
1157 //----------- End of function Unit::is_in_surrounding -----------//
1158
1159
1160 //--------- Begin of function Unit::process_build_firm ---------//
1161 // process action of building firms
1162 //
process_build_firm()1163 void Unit::process_build_firm()
1164 {
1165 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
1166 err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC || action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
1167
1168 err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC);
1169 err_when(action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
1170
1171 if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
1172 {
1173 // **BUGHERE, the unit shouldn't be hidden when building structures
1174 // otherwise, it's cargo_recno will be conflict with the structure's
1175 // cargo_recno
1176
1177 int succeedFlag=0;
1178 int shouldProceed = 1;
1179
1180 if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
1181 {
1182 FirmInfo *firmInfo = firm_res[action_para];
1183 int width = firmInfo->loc_width;
1184 int height = firmInfo->loc_height;
1185
1186 //---------------------------------------------------------//
1187 // check whether the unit in the building surrounding
1188 //---------------------------------------------------------//
1189 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc, width, height))
1190 {
1191 //---------- not in the building surrounding ---------//
1192 return;
1193 }
1194
1195 //---------------------------------------------------------//
1196 // the unit in the firm surrounding
1197 //---------------------------------------------------------//
1198 Nation* nationPtr;
1199
1200 if(nation_recno)
1201 {
1202 nationPtr = nation_array[nation_recno];
1203
1204 if(nationPtr->cash < firmInfo->setup_cost)
1205 shouldProceed = 0; // out of cash
1206 }
1207 else
1208 nationPtr = NULL;
1209
1210 //---------------------------------------------------------//
1211 // check whether the firm can be built in the specified location
1212 //---------------------------------------------------------//
1213 if( shouldProceed && world.can_build_firm(action_x_loc, action_y_loc, action_para, sprite_recno) &&
1214 firm_res[action_para]->can_build(sprite_recno) )
1215 {
1216 int aiUnit = ai_unit;
1217 int actionXLoc = action_x_loc;
1218 int actionYLoc = action_y_loc;
1219 short unitRecno = sprite_recno;
1220
1221 //---------------------------------------------------------------------------//
1222 // if unit inside the firm location, deinit the unit to free the space for
1223 // building firm
1224 //---------------------------------------------------------------------------//
1225 if(move_to_x_loc>=action_x_loc && move_to_x_loc<action_x_loc+width &&
1226 move_to_y_loc>=action_y_loc && move_to_y_loc<action_y_loc+height)
1227 deinit_sprite(0); // 0-if the unit is currently selected, deactivate it.
1228
1229 if( firm_array.build_firm(action_x_loc, action_y_loc, nation_recno,
1230 action_para, sprite_info->sprite_code, sprite_recno) ) // action_para = firm id.
1231 {
1232 //--------- able to build the firm --------//
1233
1234 reset_action_para2();
1235 succeedFlag = 1;
1236 }
1237 }
1238 }
1239
1240 //----- call action finished/failure -----//
1241
1242 if( ai_action_id && nation_recno )
1243 {
1244 if( succeedFlag )
1245 nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
1246 else
1247 nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
1248 }
1249
1250 //---------------------------------------//
1251
1252 reset_action_para();
1253 }
1254 }
1255 //----------- End of function Unit::process_build_firm -----------//
1256
1257
1258 //--------- Begin of function Unit::process_assign ---------//
1259 // process action of assigning
1260 //
process_assign()1261 void Unit::process_assign()
1262 {
1263 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
1264
1265 if(cur_action!=SPRITE_IDLE)
1266 {
1267 //------------------------------------------------------------------//
1268 // change units' action if the firm/town/unit assign to has been deleted
1269 // or has changed its nation
1270 //------------------------------------------------------------------//
1271 switch(action_mode2)
1272 {
1273 case ACTION_ASSIGN_TO_FIRM:
1274 case ACTION_AUTO_DEFENSE_BACK_CAMP:
1275 case ACTION_MONSTER_DEFEND_BACK_FIRM:
1276 if(firm_array.is_deleted(action_para))
1277 {
1278 stop2();
1279 return;
1280 }
1281 else
1282 {
1283 Firm *firmPtr = firm_array[action_para];
1284 //###### begin trevor 21/6 #######//
1285 if(firmPtr->nation_recno!=nation_recno && !firmPtr->can_assign_capture())
1286 {
1287 stop2();
1288 return;
1289 }
1290 //###### end trevor 21/6 #######//
1291 }
1292 break;
1293
1294 case ACTION_ASSIGN_TO_TOWN:
1295 case ACTION_DEFEND_TOWN_BACK_TOWN:
1296 if(town_array.is_deleted(action_para))
1297 {
1298 stop2();
1299 return;
1300 }
1301 else if(town_array[action_para]->nation_recno!=nation_recno)
1302 {
1303 stop2();
1304 return;
1305 }
1306 break;
1307
1308 case ACTION_ASSIGN_TO_VEHICLE:
1309 if(unit_array.is_deleted(action_para))
1310 {
1311 stop2();
1312 return;
1313 }
1314 else if(unit_array[action_para]->nation_recno!=nation_recno)
1315 {
1316 stop2();
1317 return;
1318 }
1319 break;
1320
1321 default: err_here();
1322 break;
1323 }
1324 }
1325 else //--------------- unit is idle -----------------//
1326 {
1327 if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
1328 {
1329 //----- first check if there is firm in the given location ------//
1330 Location* locPtr = world.get_loc( action_x_loc, action_y_loc );
1331
1332 if( locPtr->is_firm() && locPtr->firm_recno() == action_para )
1333 {
1334 //---------------- a firm on the location -----------------//
1335 Firm* firmPtr = firm_array[action_para];
1336 FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
1337
1338 //---------- resume action if the unit has not reached the firm surrounding ----------//
1339 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
1340 firmInfo->loc_width, firmInfo->loc_height))
1341 {
1342 //------------ not in the surrounding -----------//
1343 if(action_mode!=action_mode2) // for defense mode
1344 set_move_to_surround(action_x_loc, action_y_loc, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO);
1345 return;
1346 }
1347
1348 //------------ in the firm surrounding ------------//
1349 if(!firmPtr->under_construction)
1350 {
1351 //-------------------------------------------------------//
1352 // if in defense mode, update parameters in military camp
1353 //-------------------------------------------------------//
1354 if(action_mode2==ACTION_AUTO_DEFENSE_BACK_CAMP)
1355 {
1356 FirmCamp *campPtr = firmPtr->cast_to_FirmCamp();
1357 campPtr->update_defense_unit(sprite_recno);
1358 }
1359
1360 //---------------------------------------------------------------//
1361 // remainder useful parameters to do reaction to Nation.
1362 // These parameters will be destroyed after calling assign_unit()
1363 //---------------------------------------------------------------//
1364 int nationRecno = nation_recno;
1365 short unitRecno = sprite_recno;
1366 int actionXLoc = action_x_loc;
1367 int actionYLoc = action_y_loc;
1368 uint16_t aiActionId = ai_action_id;
1369 char aiUnit = ai_unit;
1370
1371 reset_action_para2();
1372
1373 firmPtr->assign_unit(sprite_recno);
1374
1375 //----------------------------------------------------------//
1376 // firm_array[]->assign_unit() must be done first. Then a
1377 // town will be created and the reaction to build other firms
1378 // requires the location of the town.
1379 //----------------------------------------------------------//
1380
1381 if(aiActionId)
1382 nation_array[nationRecno]->action_finished(aiActionId, unitRecno);
1383
1384 if( unit_array.is_deleted(unitRecno) )
1385 return;
1386
1387 //--- else the firm is full, the unit's skill level is lower than those in firm, or no space to create town ---//
1388 }
1389 else
1390 {
1391 //---------- change the builder ------------//
1392 if(ai_unit && firmPtr->under_construction)
1393 return; // not allow AI to change firm builder
1394
1395 reset_action_para2();
1396 if(skill.get_skill(SKILL_CONSTRUCTION) || skill.get_skill(firmPtr->firm_skill_id))
1397 firmPtr->set_builder(sprite_recno);
1398 }
1399
1400 //------------ update unit_array's selected parameters ------------//
1401 reset_action_para();
1402 if(selected_flag)
1403 {
1404 selected_flag = 0;
1405 unit_array.selected_count--;
1406 }
1407 }
1408 else if( locPtr->is_town() && locPtr->town_recno() == action_para )
1409 {
1410 //---------------- a town on the location -----------------//
1411 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
1412 STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
1413 {
1414 //----------- not in the surrounding ------------//
1415 return;
1416 }
1417
1418 short actionPara = action_para;
1419 short spriteRecno = sprite_recno;
1420
1421 if(ai_action_id)
1422 nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
1423
1424 //------------ update unit_array's selected parameters ------------//
1425 reset_action_para2();
1426 reset_action_para();
1427 if(selected_flag)
1428 {
1429 selected_flag = 0;
1430 unit_array.selected_count--;
1431 }
1432
1433 //-------------- assign the unit to the town -----------------//
1434 town_array[actionPara]->assign_unit(spriteRecno);
1435 }
1436
1437 //####### begin trevor 18/8 #########// the following code was called wrongly and causing bug
1438 /*
1439 //------ embarking a ground vehicle/animal ------//
1440
1441 else if(locPtr->has_unit(UNIT_LAND) && locPtr->unit_recno(UNIT_LAND) == action_para)
1442 {
1443 reset_action_para2();
1444 reset_action_para();
1445 if(selected_flag)
1446 {
1447 selected_flag = 0;
1448 unit_array.selected_count--;
1449 }
1450
1451 embark(action_para);
1452 }
1453 */
1454 //####### end trevor 18/8 #########//
1455
1456 //------ embarking a sea vehicle/animal ------//
1457
1458 else if(locPtr->has_unit(UNIT_SEA) && locPtr->unit_recno(UNIT_SEA) == action_para)
1459 {
1460 //------------ update unit_array's selected parameters ------------//
1461 reset_action_para2();
1462 reset_action_para();
1463 if(selected_flag)
1464 {
1465 selected_flag = 0;
1466 unit_array.selected_count--;
1467 }
1468
1469 //----------------- load the unit to the marine -----------------//
1470 ((UnitMarine*)unit_array[action_para])->load_unit(sprite_recno);
1471 }
1472 else
1473 {
1474 //------------------------------------------------------------------//
1475 // abort actions for ai_unit since the target location has nothing
1476 //------------------------------------------------------------------//
1477
1478 if( ai_action_id )
1479 nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
1480 }
1481 }
1482
1483 //-***** don't place codes here as unit may be removed above *****-//
1484 //reset_action_para();
1485 //selected_flag = 0;
1486 }
1487 }
1488 //----------- End of function Unit::process_assign -----------//
1489
1490
1491 //--------- Begin of function Unit::process_burn ---------//
1492 // process action of burning to a specified location
1493 //
process_burn()1494 void Unit::process_burn()
1495 {
1496 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
1497
1498 if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
1499 {
1500 if( next_x_loc()==action_x_loc && next_y_loc()==action_y_loc )
1501 {
1502 reset_action_para2();
1503 set_dir(move_to_x_loc, move_to_y_loc, action_x_loc, action_y_loc);
1504 world.setup_fire( action_x_loc, action_y_loc );
1505 }
1506
1507 reset_action_para();
1508 }
1509 }
1510 //----------- End of function Unit::process_burn -----------//
1511
1512
1513 //--------- Begin of function Unit::process_settle ---------//
1514 // process action of settling to an existing town
1515 //
process_settle()1516 void Unit::process_settle()
1517 {
1518 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
1519
1520 if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
1521 {
1522 reset_path();
1523
1524 if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
1525 {
1526 if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
1527 STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
1528 return;
1529
1530 Location* locPtr = world.get_loc(action_x_loc, action_y_loc);
1531 if(!locPtr->is_town())
1532 {
1533 //##### begin trevor 1/9 ########//
1534 int unitRecno = sprite_recno;
1535
1536 reset_action_para2();
1537 //------------ settle the unit now -------------//
1538 town_array.settle(sprite_recno, action_x_loc, action_y_loc);
1539
1540 if( unit_array.is_deleted(unitRecno) )
1541 return;
1542
1543 reset_action_para();
1544 //##### end trevor 1/9 ########//
1545 }
1546 else if(town_array[locPtr->town_recno()]->nation_recno == nation_recno)
1547 {
1548 //---------- a town zone already exists ---------//
1549 assign(action_x_loc, action_y_loc);
1550 return;
1551 }
1552 }
1553 else
1554 reset_action_para();
1555 }
1556 }
1557 //----------- End of function Unit::process_settle -----------//
1558
1559
1560 //--------- Begin of function Unit::go_cast_power ---------//
1561 // do action of god casting
1562 //
go_cast_power(int castXLoc,int castYLoc,char castPowerType,char remoteAction)1563 void Unit::go_cast_power(int castXLoc, int castYLoc, char castPowerType, char remoteAction)
1564 {
1565 err_when(mobile_type!=UNIT_AIR);
1566
1567 //----------------------------------------------------------------//
1568 // return if the unit is dead
1569 //----------------------------------------------------------------//
1570 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
1571 return;
1572
1573 if(!remoteAction && remote.is_enable() )
1574 {
1575 //------------ process multiplayer calling ---------------//
1576 // packet structure : <unit recno> <xLoc> <yLoc> <power type>
1577 short *shortPtr =(short *)remote.new_send_queue_msg(MSG_U_GOD_CAST, 4*sizeof(short) );
1578 shortPtr[0] = sprite_recno;
1579 shortPtr[1] = castXLoc;
1580 shortPtr[2] = castYLoc;
1581 shortPtr[3] = castPowerType;
1582 return;
1583 }
1584
1585 UnitGod *unitGod = (UnitGod *)this;
1586
1587 //----------------------------------------------------------------//
1588 // action_mode2: checking for equal action or idle action
1589 //----------------------------------------------------------------//
1590 if(action_mode2==ACTION_GO_CAST_POWER && action_para2==0 && action_x_loc2==castXLoc && action_y_loc2==castYLoc
1591 && unitGod->cast_power_type==castPowerType)
1592 {
1593 if(cur_action!=SPRITE_IDLE)
1594 return;
1595 }
1596 else
1597 {
1598 //----------------------------------------------------------------//
1599 // action_mode2: store new order
1600 //----------------------------------------------------------------//
1601 action_mode2 = ACTION_GO_CAST_POWER;
1602 action_para2 = 0;
1603 action_x_loc2 = castXLoc;
1604 action_y_loc2 = castYLoc;
1605 }
1606
1607 //----- order the sprite to stop as soon as possible -----//
1608 stop(); // new order
1609
1610 //------------- do searching if neccessary -------------//
1611 if(misc.points_distance(next_x_loc(), next_y_loc(), castXLoc, castYLoc)>DO_CAST_POWER_RANGE)
1612 search(castXLoc, castYLoc, 1);
1613
1614 //----------- set action to build the firm -----------//
1615 action_mode = ACTION_GO_CAST_POWER;
1616 action_para = 0;
1617 action_x_loc = castXLoc;
1618 action_y_loc = castYLoc;
1619
1620 unitGod->cast_power_type = castPowerType;
1621 unitGod->cast_origin_x = next_x_loc();
1622 unitGod->cast_origin_y = next_y_loc();
1623 unitGod->cast_target_x = castXLoc;
1624 unitGod->cast_target_y = castYLoc;
1625 }
1626 //----------- End of function Unit::go_cast_power -----------//
1627
1628
1629 //--------- Begin of function Unit::process_go_cast_power ---------//
1630 // process action of god casting
1631 //
process_go_cast_power()1632 void Unit::process_go_cast_power()
1633 {
1634 err_when(mobile_type!=UNIT_AIR);
1635 err_when(action_x_loc2<0 || action_x_loc2>=MAX_WORLD_X_LOC);
1636 err_when(action_y_loc2<0 || action_y_loc2>=MAX_WORLD_Y_LOC);
1637
1638 UnitGod *unitGod = (UnitGod *)this;
1639 if(cur_action==SPRITE_IDLE)
1640 {
1641 //----------------------------------------------------------------------------------------//
1642 // Checking condition to do casting power, Or resume action
1643 //----------------------------------------------------------------------------------------//
1644 if(misc.points_distance(cur_x_loc(), cur_y_loc(), action_x_loc2, action_y_loc2)<=DO_CAST_POWER_RANGE)
1645 {
1646 if( next_x_loc() != action_x_loc2 ||
1647 next_y_loc() != action_y_loc2 )
1648 {
1649 set_dir(next_x_loc(), next_y_loc(), action_x_loc2, action_y_loc2);
1650 }
1651 set_attack(); // set cur_action=sprite_attack to cast power
1652 cur_frame = 1;
1653 }
1654 else
1655 {
1656 err_when(action_mode2!=ACTION_GO_CAST_POWER || action_para2);
1657 go_cast_power(action_x_loc2, action_y_loc2, unitGod->cast_power_type, COMMAND_AUTO);
1658 }
1659 }
1660 else if(cur_action==SPRITE_ATTACK)
1661 {
1662 //----------------------------------------------------------------------------------------//
1663 // do casting power now
1664 //----------------------------------------------------------------------------------------//
1665 AttackInfo *attackInfo = attack_info_array + cur_attack;
1666 if(cur_frame == attackInfo->bullet_out_frame)
1667 {
1668 // add effect
1669 add_close_attack_effect();
1670
1671 unitGod->cast_power(action_x_loc2, action_y_loc2);
1672 set_remain_attack_delay();
1673 // stop2();
1674 }
1675
1676 if( cur_frame == 1 && remain_attack_delay == 0 ) // last frame of delaying
1677 stop2();
1678 }
1679 }
1680 //----------- End of function Unit::process_go_cast_power -----------//
1681