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