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 : OU_MARI.CPP
22 // Description : sea unit
23
24 #include <OSYS.h>
25 #include <OTERRAIN.h>
26 #include <OU_CARA.h>
27 #include <OPOWER.h>
28 #include <OU_MARI.h>
29 #include <OREMOTE.h>
30 #include <ONATIONA.h>
31 #include <OCONFIG.h>
32 #ifdef DEBUG2
33 #include <OFONT.h>
34 #endif
35
36 //------- Define constant ----------//
37
38 const int WAVE_CYCLE = 8;
39
40 //------- Begin of function UnitMarine::UnitMarine -------//
41
UnitMarine()42 UnitMarine::UnitMarine()
43 {
44 menu_mode = 0;
45 extra_move_in_beach = NO_EXTRA_MOVE;
46 in_beach = 0;
47 selected_unit_id = 0;
48
49 //------- transporting units vars ---------//
50
51 unit_count = 0;
52 memset(unit_recno_array, 0, sizeof(short)*MAX_UNIT_IN_SHIP);
53
54 //------- transporting goods vars ---------//
55
56 memset( stop_array, 0, MAX_STOP_FOR_SHIP * sizeof(ShipStop) );
57
58 journey_status = ON_WAY_TO_FIRM;
59 dest_stop_id = 0;
60 stop_defined_num = 0;
61 wait_count = 0;
62 stop_x_loc = 0;
63 stop_y_loc = 0;
64
65 memset(raw_qty_array, 0, sizeof(short)*MAX_RAW);
66 memset(product_raw_qty_array, 0, sizeof(short)*MAX_PRODUCT);
67
68 auto_mode = 1; // there should be no button to toggle it if the ship is only for trading
69 cur_firm_recno = 0;
70 }
71 //------- End of function UnitMarine::UnitMarine -------//
72
73
74 //------- Begin of function UnitMarine::~UnitMarine -------//
75
~UnitMarine()76 UnitMarine::~UnitMarine()
77 {
78 //-------- del those units in the ship -------//
79
80 for(int i=0; i<unit_count; i++)
81 {
82 if( !unit_array.SpriteArray::is_deleted(unit_recno_array[i]) )
83 unit_array.del(unit_recno_array[i]);
84 }
85 }
86 //------- End of function UnitMarine::~UnitMarine -------//
87
88
89 //------- Begin of function UnitMarine::init -------//
90
init(int unitId,int nationRecno,int rankId,int unitLoyalty,int startX,int startY)91 void UnitMarine::init(int unitId, int nationRecno, int rankId, int unitLoyalty, int startX, int startY)
92 {
93 attack_mode_selected = 0; // for fix_attack_info() to set attack_info_array
94
95 Unit::init(unitId, nationRecno, rankId, unitLoyalty, startX, startY);
96
97 short spriteId = sprite_info->get_sub_sprite_info(1)->sprite_id;
98 splash.init( spriteId, cur_x_loc(), cur_y_loc() );
99 splash.cur_frame = 1;
100
101 //------- set carry_goods_capacity -------//
102
103 carry_goods_capacity = unit_res[unitId]->carry_goods_capacity;
104
105 //------- set menu mode of the unit -------//
106
107 UnitInfo* unitInfo = unit_res[unitId];
108
109 if( unitInfo->carry_unit_capacity==0 && unitInfo->carry_goods_capacity>0 ) // if this ship only carries goods
110 menu_mode = SHIP_MENU_GOODS;
111 else
112 menu_mode = SHIP_MENU_UNIT;
113 }
114 //------- End of function UnitMarine::init -------//
115
116
117 //------- Begin of function UnitMarine::update_abs_pos ------//
118
update_abs_pos(SpriteFrame * spriteFrame)119 void UnitMarine::update_abs_pos(SpriteFrame *spriteFrame)
120 {
121 Unit::update_abs_pos(spriteFrame);
122 short h = wave_height(6);
123 abs_y1 -= h;
124 abs_y2 -= h;
125 }
126 //------- End of function UnitMarine::update_abs_pos -------//
127
128
129 //------- Begin of function UnitMarine::draw -------//
130
draw()131 void UnitMarine::draw()
132 {
133 // -------- update splash parameter --------//
134 // ###### begin Gilbert 8/9 #######//
135 char oldSplashAction = splash.cur_action;
136
137 switch(cur_action)
138 {
139 case SPRITE_MOVE:
140 splash.cur_action = SPRITE_MOVE;
141 if( splash.cur_action != oldSplashAction)
142 splash.cur_frame = 1;
143 else
144 {
145 ++splash.cur_frame;
146 if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_move()->frame_count )
147 splash.cur_frame = 1;
148 }
149 break;
150
151 default:
152 splash.cur_action = SPRITE_IDLE;
153 if( splash.cur_action != oldSplashAction)
154 splash.cur_frame = 1;
155 else
156 {
157 ++splash.cur_frame;
158 if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_stop()->frame_count)
159 splash.cur_frame = 1;
160 }
161 break;
162 }
163 // ###### end Gilbert 8/9 #######//
164
165 splash.cur_x = cur_x;
166 splash.cur_y = cur_y - wave_height(7);
167 splash.cur_dir = cur_dir;
168 splash.final_dir = final_dir;
169 splash.turn_delay = turn_delay;
170
171 // --------- draw splash and then the unit --------//
172 // ###### begin Gilbert 24/9 #######//
173 if( cur_action != SPRITE_DIE )
174 splash.draw();
175 // ###### end Gilbert 24/9 #######//
176 Unit::draw();
177
178 #ifdef DEBUG2
179 if(selected_flag && 0)
180 {
181 vga_util.d3_panel_up( INFO_X1, INFO_Y1+144, INFO_X2, INFO_Y1+144+87 );
182
183 int x=INFO_X1+4, y=INFO_Y1+200, refreshFlag=INFO_REPAINT;
184 font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
185 font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
186 font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
187 font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);
188
189 font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
190 font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
191 font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
192 font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
193 y-=20;
194 font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
195 font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
196 font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
197 font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
198 y-=20;
199 font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
200 }
201 #endif
202 }
203 //------- End of function UnitMarine::draw -------//
204
205
206 //------- Begin of function UnitMarine::draw_outlined -------//
207
draw_outlined()208 void UnitMarine::draw_outlined()
209 {
210 // -------- update splash parameter --------//
211 // ###### begin Gilbert 8/9 #######//
212 char oldSplashAction = splash.cur_action;
213
214 switch(cur_action)
215 {
216 case SPRITE_MOVE:
217 splash.cur_action = SPRITE_MOVE;
218 if( splash.cur_action != oldSplashAction)
219 splash.cur_frame = 1;
220 else
221 {
222 ++splash.cur_frame;
223 if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_move()->frame_count )
224 splash.cur_frame = 1;
225 }
226 break;
227
228 default:
229 splash.cur_action = SPRITE_IDLE;
230 if( splash.cur_action != oldSplashAction)
231 splash.cur_frame = 1;
232 else
233 {
234 ++splash.cur_frame;
235 if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_stop()->frame_count)
236 splash.cur_frame = 1;
237 }
238 break;
239 }
240 // ###### end Gilbert 8/9 #######//
241
242 splash.cur_x = cur_x;
243 splash.cur_y = cur_y - wave_height(7);
244 splash.cur_dir = cur_dir;
245 splash.final_dir = final_dir;
246 splash.turn_delay = turn_delay;
247
248 // --------- draw splash and then the unit --------//
249 // ###### begin Gilbert 24/9 #######//
250 if( cur_action != SPRITE_DIE )
251 splash.draw();
252 // ###### end Gilbert 24/9 #######//
253 Unit::draw_outlined();
254
255 #ifdef DEBUG2
256 if(selected_flag && 0)
257 {
258 vga_util.d3_panel_up( INFO_X1, INFO_Y1+144, INFO_X2, INFO_Y1+144+87 );
259
260 int x=INFO_X1+4, y=INFO_Y1+200, refreshFlag=INFO_REPAINT;
261 font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
262 font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
263 font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
264 font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);
265
266 font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
267 font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
268 font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
269 font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
270 y-=20;
271 font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
272 font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
273 font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
274 font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
275 y-=20;
276 font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
277 }
278 #endif
279 }
280 //------- End of function UnitMarine::draw_outlined -------//
281
282
283 //------- Begin of function UnitMarine::wave_height -------//
284
wave_height(int phase)285 short UnitMarine::wave_height(int phase)
286 {
287 err_when( phase < 0);
288 static short height[WAVE_CYCLE] = { 4,3,2,1,0,1,2,3 };
289 return height[((sys.frame_count /4) + phase) % WAVE_CYCLE];
290 }
291 //------- End of function UnitMarine::wave_height -------//
292
293
294 //--------- Begin of function UnitMarine::del_unit ---------//
295 //
296 // Delete a unit from the ship. This function is called by
297 // Unit::deinit() when the unit is killed.
298 //
299 // <int> unitRecno - recno of the unit to be loaded.
300 //
del_unit(int unitRecno)301 void UnitMarine::del_unit(int unitRecno)
302 {
303 for( int i=0 ; i<unit_count ; i++ )
304 {
305 if( unit_recno_array[i] == unitRecno )
306 {
307 err_when( unit_count > MAX_UNIT_IN_SHIP );
308
309 misc.del_array_rec(unit_recno_array, unit_count, sizeof(unit_recno_array[0]), i+1);
310 return;
311 }
312 }
313
314 err_here();
315 }
316 //----------- End of function UnitMarine::del_unit -----------//
317
318
319 //--------- Begin of function UnitMarine::load_unit ---------//
320 //
321 // Load an unit to the ship.
322 //
323 // <int> unitRecno - recno of the unit to be loaded.
324 //
load_unit(int unitRecno)325 void UnitMarine::load_unit(int unitRecno)
326 {
327 if(unit_array.is_deleted(unitRecno))
328 return;
329
330 Unit *unitPtr = unit_array[unitRecno];
331
332 if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode2==ACTION_DIE)
333 return;
334
335 if( unit_count == MAX_UNIT_IN_SHIP )
336 return;
337
338 unit_recno_array[unit_count++] = unitRecno;
339
340 unitPtr->set_mode(UNIT_MODE_ON_SHIP, sprite_recno); // set unit mode
341
342 if(unitPtr->selected_flag)
343 {
344 unitPtr->selected_flag = 0;
345 unit_array.selected_count--;
346 }
347 unitPtr->deinit_sprite();
348
349 //--- if this marine unit is currently selected ---//
350
351 if(unit_array.selected_recno==sprite_recno)
352 {
353 if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info)
354 disp_info(INFO_UPDATE);
355 }
356 }
357 //----------- End of function UnitMarine::load_unit -----------//
358
359
360 //--------- Begin of function UnitMarine::unload_unit ---------//
361 //
362 // Unload an unit from the ship.
363 //
364 // <int> unitSeqId - sequence id. of the unit in unit_recno_array[]
365 //
unload_unit(int unitSeqId,char remoteAction)366 void UnitMarine::unload_unit(int unitSeqId, char remoteAction)
367 {
368 err_when(unitSeqId > unit_count);
369
370 if(!remoteAction && remote.is_enable() )
371 {
372 // packet structure : <unit recno> <unitSeqId>
373 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_UNLOAD_UNIT, 2*sizeof(short));
374 *shortPtr = sprite_recno;
375 shortPtr[1] = unitSeqId;
376 return;
377 }
378
379 //-------- unload unit now -------//
380
381 if( unloading_unit(0, unitSeqId-1) ) // unit is unloaded
382 {
383 err_when( unit_count+1 > MAX_UNIT_IN_SHIP );
384
385 misc.del_array_rec(unit_recno_array, unit_count+1, sizeof(unit_recno_array[0]), unitSeqId);
386 }
387 }
388 //----------- End of function UnitMarine::unload_unit -----------//
389
390
391 //--------- Begin of function UnitMarine::unload_all_units ---------//
unload_all_units(char remoteAction)392 void UnitMarine::unload_all_units(char remoteAction)
393 {
394 if(!remoteAction && remote.is_enable() )
395 {
396 // packet structure : <unit recno>
397 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_UNLOAD_ALL_UNITS, sizeof(short));
398 *shortPtr = sprite_recno;
399 return;
400 }
401
402 unloading_unit(1); // unload all units
403 }
404 //----------- End of function UnitMarine::unload_all_units -----------//
405
406
407 //--------- Begin of function UnitMarine::unloading_unit ---------//
408 //
409 // <int> isAll - 1 for unload all the units
410 // - otherwise 0
411 // <int> unitSeqId - if(isAll==0) unitSeqId+1 is the recno of the
412 // selected unit in unit_recno_array[]
413 //
unloading_unit(int isAll,int unitSeqId)414 int UnitMarine::unloading_unit(int isAll, int unitSeqId)
415 {
416 if( !is_on_coast() )
417 return 0;
418
419 //-------------------------------------------------------------------------//
420 // return if no territory is nearby the ship
421 //-------------------------------------------------------------------------//
422
423 int curXLoc = next_x_loc(); // ship location
424 int curYLoc = next_y_loc();
425 int unprocess = isAll ? unit_count : 1;
426 Unit *unitPtr = isAll ? unit_array[unit_recno_array[unprocess-1]] : unit_array[unit_recno_array[unitSeqId]];
427 Location *locPtr;
428 int xShift, yShift, checkXLoc, checkYLoc;
429 int regionId = 0; // unload all the units in the same territory
430 int found = 0, i = 2;
431 int sqtSize = 5, sqtArea = sqtSize*sqtSize;
432
433 #ifdef DEBUG
434 long debugCount = 0L;
435 #endif
436
437 if(isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
438 power.reset_selection();
439
440 while(unprocess) // using the calculated 'i' to reduce useless calculation
441 {
442 err_when(debugCount++ > 4*long(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC));
443
444 misc.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift);
445 checkXLoc = curXLoc+xShift;
446 checkYLoc = curYLoc+yShift;
447 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
448 {
449 i++;
450 continue;
451 }
452
453 locPtr = world.get_loc(checkXLoc, checkYLoc);
454
455 //-------------------------------------------------------------------------//
456 // check for space to unload the unit
457 //-------------------------------------------------------------------------//
458 if(!regionId || locPtr->region_id == regionId)
459 {
460 if(locPtr->walkable())
461 found = 1;
462
463 if(locPtr->can_move(UNIT_LAND))//unitPtr->mobile_type))
464 {
465 regionId = locPtr->region_id;
466
467 unitPtr->init_sprite(checkXLoc, checkYLoc);
468 unitPtr->set_mode(0);
469
470 if( isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
471 {
472 unitPtr->selected_flag = 1; // mark selected if unload all
473 unit_array.selected_count++;
474
475 if( !unit_array.selected_recno )
476 unit_array.selected_recno = unitPtr->sprite_recno;
477 }
478
479 unprocess--;
480 unit_count--;
481
482 if(unprocess)
483 unitPtr = unit_array[unit_recno_array[unprocess-1]]; // point to next unit
484 else
485 break; // finished, all have been unloaded
486 }
487 }
488
489 //-------------------------------------------------------------------------//
490 // stop checking if there is totally bouned by unacessible location
491 //-------------------------------------------------------------------------//
492 if(i==sqtArea)
493 {
494 if(found)
495 {
496 found = 0; // reset found
497 sqtSize += 2;
498 sqtArea = sqtSize*sqtSize;
499 }
500 else // no continuous location for the unit to unload, some units can't be unloaded
501 return 0;
502 }
503
504 i++;
505 }
506
507 //-------- display info --------//
508
509 if( nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
510 info.disp();
511
512 return 1;
513 }
514 //----------- End of function UnitMarine::unloading_unit -----------//
515
516
517 //--------- Begin of function UnitMarine::is_on_coast ---------//
518 //
519 // Return whether the unit is on the coast and ready for unloading.
520 //
is_on_coast()521 int UnitMarine::is_on_coast()
522 {
523 Location *locPtr;
524 int xShift, yShift, checkXLoc, checkYLoc, found=0;
525 int curXLoc = next_x_loc(); // ship location
526 int curYLoc = next_y_loc();
527
528 for(int i=2; i<=9; i++) // checking for the surrouding location
529 {
530 misc.cal_move_around_a_point(i, 3, 3, xShift, yShift);
531
532 checkXLoc = curXLoc + xShift;
533 checkYLoc = curYLoc + yShift;
534
535 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
536 continue;
537
538 locPtr = world.get_loc(checkXLoc, checkYLoc);
539
540 if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && // a territory nearby
541 locPtr->walkable())
542 {
543 return 1;
544 }
545 }
546
547 return 0;
548 }
549 //----------- End of function UnitMarine::is_on_coast -----------//
550
551
552 //--------- Begin of function UnitMarine::extra_move ---------//
extra_move()553 void UnitMarine::extra_move()
554 {
555 static char offset[3] = {0, 1, -1};
556
557 int curXLoc = next_x_loc();
558 int curYLoc = next_y_loc();
559
560 int vecX = action_x_loc2 - curXLoc;
561 int vecY = action_y_loc2 - curYLoc;
562 int checkXLoc, checkYLoc, i, found=0;
563
564 if(vecX==0 || vecY==0)
565 {
566 if(vecX==0)
567 {
568 vecY /= abs(vecY);
569 checkYLoc = curYLoc + vecY;
570 }
571 else // vecY==0
572 {
573 vecX /= abs(vecX);
574 checkXLoc = curXLoc + vecX;
575 }
576
577 for(i=0; i<3; i++)
578 {
579 if(vecX==0)
580 checkXLoc = curXLoc + offset[i];
581 else
582 checkYLoc = curYLoc + offset[i];
583
584 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
585 continue;
586
587 if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
588 {
589 found++;
590 break;
591 }
592 }
593 }
594 else
595 {
596 vecX /= abs(vecX);
597 vecY /= abs(vecY);
598 checkXLoc = curXLoc + vecX;
599 checkYLoc = curYLoc + vecY;
600
601 if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
602 found++;
603 }
604
605 if(!found)
606 return;
607
608 set_dir(curXLoc, curYLoc, checkXLoc, checkYLoc);
609 cur_action = SPRITE_SHIP_EXTRA_MOVE;
610 go_x = checkXLoc*ZOOM_LOC_WIDTH;
611 go_y = checkYLoc*ZOOM_LOC_HEIGHT;
612 err_when(cur_x==go_x && cur_y==go_y);
613 //extra_move_in_beach = EXTRA_MOVING_IN;
614 }
615 //----------- End of function UnitMarine::extra_move -----------//
616
617
618 //------- Begin of function UnitMarine::process_extra_move ------//
619
process_extra_move()620 void UnitMarine::process_extra_move()
621 {
622 static short vector_x_array[] = { 0, 1, 1, 1, 0, -1, -1, -1}; // default vectors, temporary only
623 static short vector_y_array[] = {-1, -1, 0, 1, 1, 1, 0, -1};
624
625 if(!match_dir()) // process turning
626 return;
627
628 if(cur_x!=go_x || cur_y!=go_y)
629 {
630 //------------------------------------------------------------------------//
631 // set cargo_recno, extra_move_in_beach
632 //------------------------------------------------------------------------//
633 if(cur_x==next_x && cur_y==next_y)
634 {
635 int goXLoc = go_x>>ZOOM_X_SHIFT_COUNT;
636 int goYLoc = go_y>>ZOOM_Y_SHIFT_COUNT;
637 if(!world.get_loc(goXLoc, goYLoc)->can_move(mobile_type))
638 {
639 go_x = next_x;
640 go_y = next_y;
641 return;
642 }
643
644 int curXLoc = next_x_loc();
645 int curYLoc = next_y_loc();
646 world.set_unit_recno(curXLoc, curYLoc, mobile_type, 0);
647 world.set_unit_recno(goXLoc, goYLoc, mobile_type, sprite_recno);
648 next_x = go_x;
649 next_y = go_y;
650
651 err_when( ((curXLoc%2)|(curYLoc%2)) + ((goXLoc%2)|(goYLoc%2)) != 1); // one pair location must be even, another is not even
652 in_beach = !(curXLoc%2 || curYLoc%2);
653
654 if(goXLoc%2 || goYLoc%2) // not even location
655 extra_move_in_beach = EXTRA_MOVING_IN;
656 else // even location
657 extra_move_in_beach = EXTRA_MOVING_OUT;
658 }
659 //else
660 // int debug = 0;
661
662 //---------- process moving -----------//
663 short stepX = sprite_info->speed;
664 short stepY = sprite_info->speed;
665 short vectorX = vector_x_array[final_dir] * sprite_info->speed; // cur_dir may be changed in the above set_next() call
666 short vectorY = vector_y_array[final_dir] * sprite_info->speed;
667
668 if(abs(cur_x-go_x) <= stepX)
669 cur_x = go_x;
670 else
671 cur_x += vectorX;
672
673 if(abs(cur_y-go_y) <= stepY)
674 cur_y = go_y;
675 else
676 cur_y += vectorY;
677
678 err_when(extra_move_in_beach!=EXTRA_MOVING_IN && extra_move_in_beach!=EXTRA_MOVING_OUT);
679 err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE);
680 }
681
682 if(cur_x==go_x && cur_y==go_y)
683 {
684 if(result_node_array==NULL)
685 {
686 cur_action = SPRITE_IDLE;
687 cur_frame = 1;
688 move_to_x_loc = next_x_loc();
689 move_to_y_loc = next_y_loc();
690 }
691 else
692 {
693 cur_action = SPRITE_MOVE;
694 next_move();
695 }
696
697 if(in_beach)
698 {
699 extra_move_in_beach = EXTRA_MOVE_FINISH;
700 err_when(move_to_x_loc%2==0 && move_to_y_loc%2==0);
701 err_when(result_node_array || result_path_dist);
702 }
703 else
704 {
705 extra_move_in_beach = NO_EXTRA_MOVE;
706 err_when(move_to_x_loc%2 || move_to_y_loc%2);
707 err_when(result_node_array || result_path_dist);
708 }
709
710 err_when(cur_action==SPRITE_IDLE && (extra_move_in_beach==EXTRA_MOVING_IN || extra_move_in_beach==EXTRA_MOVING_OUT));
711 }
712 }
713 //----------- End of function UnitMarine::process_extra_move -----------//
714
715
716 //------------ Begin of function UnitMarine::actual_damage --------------//
717 //
718 // This function returns the actual hit damage this unit can do to a target.
719 //
actual_damage()720 float UnitMarine::actual_damage()
721 {
722 float attackDamage = Unit::actual_damage();
723
724 //-----------------------------------------//
725 //
726 // If there is units on the ship, the units
727 // leadership will increase the attacking damage.
728 //
729 // actual damage = normal damage X (100+highest leadership unit on the ship) / 100
730 //
731 //-----------------------------------------//
732
733 Unit* unitPtr;
734 int t, highestLeadership=0;
735
736 for( int i=0 ; i<unit_count ; i++ )
737 {
738 unitPtr = unit_array[ unit_recno_array[i] ];
739
740 if( unitPtr->skill.skill_id == SKILL_LEADING )
741 {
742 if( (t=unitPtr->skill.skill_level) > highestLeadership )
743 highestLeadership = t;
744 }
745 }
746
747 return attackDamage * (100+highestLeadership) / 100;
748 }
749 //------------ End of function UnitMarine::actual_damage --------------//
750
751
752 //------- Begin of function UnitMarine::total_carried_goods -------//
753
total_carried_goods()754 int UnitMarine::total_carried_goods()
755 {
756 int totalQty=0;
757
758 for( int i=0 ; i<MAX_RAW ; i++ )
759 {
760 totalQty += raw_qty_array[i];
761 totalQty += product_raw_qty_array[i];
762 }
763
764 return totalQty;
765 }
766 //------- End of function UnitMarine::total_carried_goods -------//
767
768
769 //------- Begin of function UnitMarine::can_resign -------//
can_resign()770 int UnitMarine::can_resign()
771 {
772 err_when(unit_count < 0);
773 return unit_count == 0;
774 }
775 //------- End of function UnitMarine::can_resign -------//
776