00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <math.h>
00018 #include "mech.h"
00019 #include "mech.events.h"
00020 #include "autopilot.h"
00021 #include "create.h"
00022 #include "p.mech.startup.h"
00023 #include "p.econ.h"
00024 #include "p.econ_cmds.h"
00025 #include "p.mech.maps.h"
00026 #include "p.mech.utils.h"
00027 #include "p.eject.h"
00028 #include "p.btechstats.h"
00029 #include "p.bsuit.h"
00030 #include "p.mech.pickup.h"
00031 #include "p.mech.los.h"
00032 #include "p.ds.bay.h"
00033 #include "p.glue.h"
00034
00035
00036
00037
00038
00039
00040 ACOM acom[AUTO_NUM_COMMANDS + 1] = {
00041 {"chasetarget", 1, GOAL_CHASETARGET, NULL}
00042 ,
00043 {"dumbfollow", 1, GOAL_DUMBFOLLOW, NULL}
00044 ,
00045 {"dumbgoto", 2, GOAL_DUMBGOTO, NULL}
00046 ,
00047 {"enterbase", 1, GOAL_ENTERBASE, NULL}
00048 ,
00049 {"follow", 1, GOAL_FOLLOW, NULL}
00050 ,
00051 {"goto", 2, GOAL_GOTO, NULL}
00052 ,
00053 {"leavebase", 1, GOAL_LEAVEBASE, NULL}
00054 ,
00055 {"oldgoto", 2, GOAL_OLDGOTO, NULL}
00056 ,
00057 {"roam", 1, GOAL_ROAM, NULL}
00058 ,
00059 {"wait", 2, GOAL_WAIT, NULL}
00060 ,
00061 {"attackleg", 1, COMMAND_ATTACKLEG, NULL}
00062 ,
00063 {"autogun", 1, COMMAND_AUTOGUN, NULL}
00064 ,
00065 {"chasemode", 1, COMMAND_CHASEMODE, NULL}
00066 ,
00067 {"cmode", 2, COMMAND_CMODE, NULL}
00068 ,
00069 {"dropoff", 0, COMMAND_DROPOFF, NULL}
00070 ,
00071 {"embark", 1, COMMAND_EMBARK, NULL}
00072 ,
00073 {"enterbay", 0, COMMAND_ENTERBAY, NULL}
00074 ,
00075 {"jump", 1, COMMAND_JUMP, NULL}
00076 ,
00077 {"load", 0, COMMAND_LOAD, NULL}
00078 ,
00079 {"pickup", 1, COMMAND_PICKUP, NULL}
00080 ,
00081 {"report", 0, COMMAND_REPORT, NULL}
00082 ,
00083 {"roammode", 1, COMMAND_ROAMMODE, NULL}
00084 ,
00085 {"shutdown", 0, COMMAND_SHUTDOWN, NULL}
00086 ,
00087 {"speed", 1, COMMAND_SPEED, NULL}
00088 ,
00089 {"startup", 0, COMMAND_STARTUP, NULL}
00090 ,
00091 {"stopgun", 0, COMMAND_STOPGUN, NULL}
00092 ,
00093 {"swarm", 1, COMMAND_SWARM, NULL}
00094 ,
00095 {"swarmmode", 1, COMMAND_SWARMMODE, NULL}
00096 ,
00097 {"udisembark", 0, COMMAND_UDISEMBARK, NULL}
00098 ,
00099 {"unload", 0, COMMAND_UNLOAD, NULL}
00100 ,
00101 {NULL, 0, AUTO_NUM_COMMANDS, NULL}
00102 };
00103
00104
00105
00106 #define GSTART AUTO_GSTART
00107 #define PSTART AUTO_PSTART
00108 #define CCH AUTO_CHECKS
00109 #define REDO AUTO_COM
00110
00111
00112
00113
00114 void auto_command_startup(AUTO * autopilot, MECH * mech)
00115 {
00116
00117 if(Started(mech))
00118 return;
00119
00120 if(!Starting(mech)) {
00121 mech_startup(autopilot->mynum, mech, "");
00122 auto_goto_next_command(autopilot, AUTOPILOT_STARTUP_TICK);
00123 }
00124
00125 }
00126
00127
00128
00129
00130 void auto_command_shutdown(AUTO * autopilot, MECH * mech)
00131 {
00132
00133 if(!Started(mech))
00134 return;
00135
00136 mech_shutdown(autopilot->mynum, mech, "");
00137
00138 }
00139
00140 #if 0
00141
00143 void gradually_load(MECH * mech, int loc, int percent)
00144 {
00145 int pile[BRANDCOUNT + 1][NUM_ITEMS];
00146 float spd = (float) MMaxSpeed(mech);
00147 float nspd = (float) MechCargoMaxSpeed(mech, (float) spd);
00148 int cnt = 0;
00149 char *t;
00150 int i, j;
00151 int i1, i2, i3;
00152 int lastid = -1, lastbrand = -1;
00153
00154
00155 bzero(pile, sizeof(pile));
00156 t = silly_atr_get(loc, A_ECONPARTS);
00157 while (*t) {
00158 if(*t == '[')
00159 if((sscanf(t, "[%d,%d,%d]", &i1, &i2, &i3)) == 3) {
00160 pile[i2][i1] += i3;
00161 cnt++;
00162 }
00163 t++;
00164 }
00165 while (nspd > ((float) spd * percent / 100) && cnt) {
00166 for(j = 0; j <= BRANDCOUNT; j++) {
00167 for(i = 0; i < NUM_ITEMS; i++)
00168 if(pile[j][i])
00169 break;
00170 if(i != NUM_ITEMS)
00171 break;
00172 }
00173 if(i == NUM_ITEMS)
00174 break;
00175 lastid = i;
00176 lastbrand = j;
00177 econ_change_items(loc, i, j, -1);
00178 econ_change_items(mech->mynum, i, j, 1);
00179 pile[j][i]--;
00180 cnt--;
00181 SetCargoWeight(mech);
00182 nspd = (float) MechCargoMaxSpeed(mech, (float) spd);
00183 }
00184 if(lastid >= 0) {
00185 i = lastid;
00186 j = lastbrand;
00187 econ_change_items(loc, i, j, 1);
00188 econ_change_items(mech->mynum, i, j, -1);
00189 }
00190 SetCargoWeight(mech);
00191 }
00192
00193 void autopilot_load_cargo(dbref player, MECH * mech, int percent)
00194 {
00195 DOCHECK(fabs(MechSpeed(mech)) > MP1, "You're moving too fast!");
00196 DOCHECK(Location(mech->mynum) != mech->mapindex ||
00197 In_Character(Location(mech->mynum)), "You aren't inside hangar!");
00198 if(loading_bay_whine(player, Location(mech->mynum), mech))
00199 return;
00200 gradually_load(mech, mech->mapindex, percent);
00201 SetCargoWeight(mech);
00202 }
00203 #endif
00204
00205
00207 void auto_cal_mapindex(MECH * mech)
00208 {
00209
00210 AUTO *autopilot;
00211 char error_buf[MBUF_SIZE];
00212
00213 if(!mech) {
00214 SendError("Null pointer catch in auto_cal_mapindex");
00215 return;
00216 }
00217
00218 if(MechAuto(mech) > 0) {
00219 if(!(autopilot = FindObjectsData(MechAuto(mech))) ||
00220 !Good_obj(MechAuto(mech)) ||
00221 Location(MechAuto(mech)) != mech->mynum) {
00222 snprintf(error_buf, MBUF_SIZE,
00223 "Mech #%d thinks it has the Autopilot #%d on it"
00224 " but FindObj breaks", mech->mynum, MechAuto(mech));
00225 SendError(error_buf);
00226 MechAuto(mech) = -1;
00227 } else {
00228
00229
00230
00231
00232 switch (auto_get_command_enum(autopilot, 1)) {
00233
00234 case GOAL_LEAVEBASE:
00235 break;
00236 case GOAL_ENTERBASE:
00237 break;
00238 default:
00239 autopilot->mapindex = mech->mapindex;
00240 }
00241
00242 }
00243 }
00244 return;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254 void auto_set_chasetarget_mode(AUTO * autopilot, int mode)
00255 {
00256
00257
00258 switch (mode) {
00259
00260 case AUTO_CHASETARGET_ON:
00261
00262
00263 if(!ChasingTarget(autopilot))
00264 StartChasingTarget(autopilot);
00265
00266
00267 if(WasChasingTarget(autopilot))
00268 ForgetChasingTarget(autopilot);
00269
00270
00271 autopilot->chase_target = -10;
00272 autopilot->chasetarg_update_tick = AUTOPILOT_CHASETARG_UPDATE_TICK;
00273
00274 break;
00275
00276 case AUTO_CHASETARGET_OFF:
00277
00278
00279 if(ChasingTarget(autopilot))
00280 StopChasingTarget(autopilot);
00281
00282
00283 if(WasChasingTarget(autopilot))
00284 ForgetChasingTarget(autopilot);
00285
00286 break;
00287
00288 case AUTO_CHASETARGET_REMEMBER:
00289
00290
00291 if(WasChasingTarget(autopilot)) {
00292
00293
00294 if(!ChasingTarget(autopilot))
00295 StartChasingTarget(autopilot);
00296
00297
00298 autopilot->chase_target = -10;
00299 autopilot->chasetarg_update_tick =
00300 AUTOPILOT_CHASETARG_UPDATE_TICK;
00301
00302
00303 ForgetChasingTarget(autopilot);
00304
00305 }
00306
00307 break;
00308
00309 case AUTO_CHASETARGET_SAVE:
00310
00311
00312
00313 if(ChasingTarget(autopilot)) {
00314
00315 StopChasingTarget(autopilot);
00316 RememberChasingTarget(autopilot);
00317
00318 }
00319
00320 break;
00321
00322 }
00323
00324 }
00325
00326 #if 0
00327 void autopilot_cmode(AUTO * a, MECH * mech, int mode, int range)
00328 {
00329 static char buf[MBUF_SIZE];
00330 if(!a || !mech)
00331 return;
00332 if(mode < 0 || mode > 2)
00333 return;
00334 if(range < 0 || range > 40)
00335 return;
00336 a->auto_cdist = range;
00337 a->auto_cmode = mode;
00338 return;
00339
00340 }
00341
00342 void autopilot_swarm(MECH * mech, char *id)
00343 {
00344 if(MechType(mech) == CLASS_BSUIT)
00345 bsuit_swarm(GOD, mech, id);
00346 }
00347
00348 void autopilot_attackleg(MECH * mech, char *id)
00349 {
00350 bsuit_attackleg(GOD, mech, id);
00351 }
00352
00353 #endif
00354
00355
00356
00357
00358
00359
00360 void auto_command_autogun(AUTO * autopilot, MECH * mech)
00361 {
00362
00363 dbref target_dbref;
00364 MECH *target;
00365 char *argument;
00366 char error_buf[MBUF_SIZE];
00367 char *args[AUTOPILOT_MAX_ARGS - 1];
00368 int argc;
00369 int i;
00370
00371
00372 argument = auto_get_command_arg(autopilot, 1, 1);
00373
00374
00375 argc = proper_explodearguments(argument, args, AUTOPILOT_MAX_ARGS - 1);
00376
00377
00378 free(argument);
00379
00380
00381 if(argc == 1) {
00382
00383
00384 if(strcmp(args[0], "on") == 0) {
00385
00386
00387 autopilot->target = -1;
00388 autopilot->target_score = 0;
00389 autopilot->target_update_tick = AUTO_GUN_UPDATE_TICK;
00390
00391
00392 if(AssignedTarget(autopilot)) {
00393 UnassignTarget(autopilot);
00394 }
00395
00396
00397 AUTO_GSTART(autopilot, mech);
00398
00399 if(Gunning(autopilot)) {
00400 DoStopGun(autopilot);
00401 }
00402
00403 DoStartGun(autopilot);
00404
00405 } else if(strcmp(args[0], "off") == 0) {
00406
00407
00408 autopilot->target = -2;
00409 autopilot->target_score = 0;
00410 autopilot->target_update_tick = 0;
00411
00412
00413 if(AssignedTarget(autopilot)) {
00414 UnassignTarget(autopilot);
00415 }
00416
00417 if(Gunning(autopilot)) {
00418 DoStopGun(autopilot);
00419 }
00420
00421 } else {
00422
00423
00424 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00425 " argument for autogun command", autopilot->mynum);
00426 SendAI(error_buf);
00427
00428 }
00429
00430 } else if(argc == 2) {
00431
00432
00433 if(strcmp(args[0], "target") == 0) {
00434
00435
00436 if(Readnum(target_dbref, args[1])) {
00437
00438
00439 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00440 " argument for autogun command", autopilot->mynum);
00441 SendAI(error_buf);
00442
00443
00444 for(i = 0; i < AUTOPILOT_MAX_ARGS - 1; i++) {
00445 if(args[i])
00446 free(args[i]);
00447 }
00448
00449 return;
00450 }
00451
00452
00453 if(!(target = getMech(target_dbref))) {
00454
00455 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00456 " target for autogun command", autopilot->mynum);
00457 SendAI(error_buf);
00458
00459
00460 for(i = 0; i < AUTOPILOT_MAX_ARGS - 1; i++) {
00461 if(args[i])
00462 free(args[i]);
00463 }
00464
00465 return;
00466 }
00467
00468
00469 autopilot->target = target_dbref;
00470 autopilot->target_score = 0;
00471 autopilot->target_update_tick = 0;
00472
00473
00474 if(!AssignedTarget(autopilot)) {
00475 AssignTarget(autopilot);
00476 }
00477
00478
00479 AUTO_GSTART(autopilot, mech);
00480
00481 if(Gunning(autopilot)) {
00482 DoStopGun(autopilot);
00483 }
00484
00485 DoStartGun(autopilot);
00486
00487 } else {
00488
00489
00490 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00491 " argument for autogun command", autopilot->mynum);
00492 SendAI(error_buf);
00493
00494 }
00495
00496 }
00497
00498
00499 for(i = 0; i < AUTOPILOT_MAX_ARGS - 1; i++) {
00500 if(args[i])
00501 free(args[i]);
00502 }
00503
00504 }
00505
00506
00507
00508
00509 void auto_command_chasetarget(AUTO * autopilot)
00510 {
00511
00512
00513 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
00514 AUTOPILOT_FOLLOW_TICK, 1);
00515
00516 return;
00517 }
00518
00519
00520
00521
00522 void auto_command_pickup(AUTO * autopilot, MECH * mech)
00523 {
00524
00525 char *argument;
00526 int target;
00527 char error_buf[MBUF_SIZE];
00528 char buf[SBUF_SIZE];
00529 MECH *tempmech;
00530
00533
00534 argument = auto_get_command_arg(autopilot, 1, 1);
00535 if(Readnum(target, argument)) {
00536
00537 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00538 " argument for pickup command", autopilot->mynum);
00539 SendAI(error_buf);
00540 free(argument);
00541 return;
00542
00543 }
00544 free(argument);
00545
00546
00547 if(!(tempmech = getMech(target))) {
00548 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d unable to pickup"
00549 " unit #%d", autopilot->mynum, target);
00550 SendAI(error_buf);
00551 return;
00552 }
00553
00554
00555 strcpy(buf, MechIDS(tempmech, 1));
00556 mech_pickup(GOD, mech, buf);
00557
00561 }
00562
00563
00564
00565
00566 void auto_command_dropoff(MECH * mech)
00567 {
00568 mech_dropoff(GOD, mech, NULL);
00569 }
00570
00571
00572
00573
00574 void auto_command_speed(AUTO * autopilot)
00575 {
00576
00577 char *argument;
00578 unsigned short speed;
00579 char error_buf[MBUF_SIZE];
00580
00581
00582 argument = auto_get_command_arg(autopilot, 1, 1);
00583 if(Readnum(speed, argument)) {
00584
00585 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00586 " argument for speed command", autopilot->mynum);
00587 SendAI(error_buf);
00588 free(argument);
00589 return;
00590
00591 }
00592 free(argument);
00593
00594
00595 if(speed < 1 || speed > 100) {
00596
00597 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00598 " argument for speed command - out side of the range",
00599 autopilot->mynum);
00600 SendAI(error_buf);
00601 return;
00602
00603 }
00604
00605
00606 autopilot->speed = speed;
00607
00608 }
00609
00610
00611
00612
00613 void auto_command_embark(AUTO * autopilot, MECH * mech)
00614 {
00615
00616 char *argument;
00617 int target;
00618 char error_buf[MBUF_SIZE];
00619 char buf[SBUF_SIZE];
00620 MECH *tempmech;
00621
00622
00623 AUTO_GSTART(autopilot, mech);
00624
00625
00626 argument = auto_get_command_arg(autopilot, 1, 1);
00627 if(Readnum(target, argument)) {
00628
00629 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
00630 " argument for embark command", autopilot->mynum);
00631 SendAI(error_buf);
00632 free(argument);
00633 return;
00634
00635 }
00636 free(argument);
00637
00638
00639 if(!(tempmech = getMech(target))) {
00640 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d unable to embark"
00641 " unit #%d", autopilot->mynum, target);
00642 SendAI(error_buf);
00643 return;
00644 }
00645
00646 strcpy(buf, MechIDS(tempmech, 1));
00647 mech_embark(GOD, mech, buf);
00648
00649 }
00650
00651
00652
00653
00654 void auto_command_udisembark(MECH * mech)
00655 {
00656
00657 dbref pil = -1;
00658 char *buf;
00659
00660 buf = silly_atr_get(mech->mynum, A_PILOTNUM);
00661 sscanf(buf, "#%d", &pil);
00662 mech_udisembark(pil, mech, "");
00663
00664 }
00665
00666 #if 0
00667 void autopilot_enterbase(MECH * mech, int dir)
00668 {
00669 static char strng[2];
00670
00671 switch (dir) {
00672 case 0:
00673 strcpy(strng, "n");
00674 break;
00675 case 1:
00676 strcpy(strng, "e");
00677 break;
00678 case 2:
00679 strcpy(strng, "s");
00680 break;
00681 case 3:
00682 strcpy(strng, "w");
00683 break;
00684 default:
00685 sprintf(strng, "%c", dir);
00686 break;
00687 }
00688 mech_enterbase(GOD, mech, strng);
00689 }
00690 #endif
00691
00692
00693
00694
00695
00696 void auto_com_event(MUXEVENT * muxevent)
00697 {
00698
00699 AUTO *autopilot = (AUTO *) muxevent->data;
00700 MECH *mech = autopilot->mymech;
00701 MECH *tempmech;
00702 char buf[SBUF_SIZE];
00703 int i, j, t;
00704
00705 command_node *command;
00706
00707
00708 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
00709 return;
00710
00711
00712 if(!(FindObjectsData(mech->mapindex))) {
00713 autopilot->mapindex = mech->mapindex;
00714 PilZombify(autopilot);
00715
00716
00717
00718
00719 if(auto_get_command_enum(autopilot, 1) != COMMAND_UDISEMBARK)
00720 return;
00721 }
00722
00723
00724 if(autopilot->mapindex < 0)
00725 autopilot->mapindex = mech->mapindex;
00726
00727
00728 AUTO_CHECKS(autopilot);
00729
00730
00731 switch (auto_get_command_enum(autopilot, 1)) {
00732
00733
00734 case GOAL_CHASETARGET:
00735 auto_command_chasetarget(autopilot);
00736 return;
00737 case GOAL_DUMBGOTO:
00738 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_dumbgoto_event,
00739 AUTOPILOT_GOTO_TICK, 0);
00740 return;
00741 case GOAL_DUMBFOLLOW:
00742 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_dumbfollow_event,
00743 AUTOPILOT_FOLLOW_TICK, 0);
00744 return;
00745
00746 case GOAL_ENTERBASE:
00747 AUTOEVENT(autopilot, EVENT_AUTOENTERBASE, auto_enter_event,
00748 AUTOPILOT_NC_DELAY, 1);
00749 return;
00750
00751 case GOAL_FOLLOW:
00752 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
00753 AUTOPILOT_FOLLOW_TICK, 1);
00754 return;
00755
00756 case GOAL_GOTO:
00757 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_astar_goto_event,
00758 AUTOPILOT_GOTO_TICK, 1);
00759 return;
00760
00761 case GOAL_LEAVEBASE:
00762 AUTOEVENT(autopilot, EVENT_AUTOLEAVE, auto_leave_event,
00763 AUTOPILOT_LEAVE_TICK, 1);
00764 return;
00765
00766 case GOAL_OLDGOTO:
00767 AUTO_GSTART(autopilot, mech);
00768 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_goto_event,
00769 AUTOPILOT_GOTO_TICK, 0);
00770 return;
00771
00772 case GOAL_ROAM:
00773 auto_command_roam(autopilot, mech);
00774 return;
00775
00776 #if 0
00777 case GOAL_WAIT:
00778 i = GVAL(a, 1);
00779 j = GVAL(a, 2);
00780 if(!i) {
00781 PG(a) += CCLEN(a);
00782 AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event, MAX(1, j), 0);
00783 } else {
00784 if(i == 1) {
00785 if(MechNumSeen(mech)) {
00786 ADVANCE_PG(a);
00787 } else {
00788 AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event,
00789 AUTOPILOT_WAITFOE_TICK, 0);
00790 }
00791 } else {
00792 ADVANCE_PG(a);
00793 }
00794 }
00795 return;
00796 #endif
00797 #if 0
00798 case COMMAND_ATTACKLEG:
00799 if(!(tempmech = getMech(GVAL(a, 1)))) {
00800 SendAI(tprintf("AIAttacklegError #%d", GVAL(a, 1)));
00801
00802 auto_goto_next_command(a);
00803 return;
00804 }
00805 strcpy(buf, MechIDS(tempmech, 1));
00806 autopilot_attackleg(mech, buf);
00807
00808 auto_goto_next_command(a);
00809 return;
00810 #endif
00811
00812 case COMMAND_AUTOGUN:
00813 auto_command_autogun(autopilot, mech);
00814 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00815 break;
00816
00817 #if 0
00818 case COMMAND_CHASEMODE:
00819 if(GVAL(a, 1))
00820 a->flags |= AUTOPILOT_CHASETARG;
00821 else
00822 a->flags &= ~AUTOPILOT_CHASETARG;
00823
00824 auto_goto_next_command(a);
00825 return;
00826 #endif
00827 #if 0
00828 case COMMAND_CMODE:
00829 i = GVAL(a, 1);
00830 j = GVAL(a, 2);
00831 autopilot_cmode(a, mech, i, j);
00832
00833 auto_goto_next_command(a);
00834 return;
00835 #endif
00836
00837 case COMMAND_DROPOFF:
00838 auto_command_dropoff(mech);
00839 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00840 return;
00841
00842 case COMMAND_EMBARK:
00843 auto_command_embark(autopilot, mech);
00844 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00845 return;
00846
00847 #if 0
00848 case COMMAND_ENTERBAY:
00849 PSTART(a, mech);
00850 mech_enterbay(GOD, mech, my2string(""));
00851
00852 auto_goto_next_command(a);
00853 return;
00854 #endif
00855 #if 0
00856 case COMMAND_JUMP:
00857 if(auto_valid_progline(a, GVAL(a, 1))) {
00858 PG(a) = GVAL(a, 1);
00859 AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event,
00860 AUTOPILOT_NC_DELAY, 0);
00861 } else {
00862 ADVANCE_PG(a);
00863 }
00864 return;
00865 #endif
00866 #if 0
00867 case COMMAND_LOAD:
00868
00869 autopilot_load_cargo(GOD, mech, 50);
00870
00871 auto_goto_next_command(a);
00872 break;
00873 #endif
00874 case COMMAND_PICKUP:
00875 auto_command_pickup(autopilot, mech);
00876 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00877 return;
00878 #if 0
00879 case COMMAND_ROAMMODE:
00880 t = a->flags;
00881 if(GVAL(a, 1)) {
00882 a->flags |= AUTOPILOT_ROAMMODE;
00883 if(!(t & AUTOPILOT_ROAMMODE)) {
00884 if(MechType(mech) == CLASS_BSUIT)
00885 a->flags |= AUTOPILOT_SWARMCHARGE;
00886 auto_addcommand(a->mynum, a, tprintf("roam 0 0"));
00887 }
00888 } else {
00889 a->flags &= ~AUTOPILOT_ROAMMODE;
00890 }
00891
00892 auto_goto_next_command(a);
00893 return;
00894 #endif
00895 case COMMAND_SHUTDOWN:
00896 auto_command_shutdown(autopilot, mech);
00897 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00898 return;
00899
00900 case COMMAND_SPEED:
00901 auto_command_speed(autopilot);
00902 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00903 return;
00904
00905 case COMMAND_STARTUP:
00906 auto_command_startup(autopilot, mech);
00907 return;
00908 #if 0
00909 case COMMAND_STOPGUN:
00910 if(Gunning(a))
00911 DoStopGun(a);
00912
00913 auto_goto_next_command(a);
00914 break;
00915 #endif
00916 #if 0
00917 case COMMAND_SWARM:
00918 if(!(tempmech = getMech(GVAL(a, 1)))) {
00919 SendAI(tprintf("AISwarmError #%d", GVAL(a, 1)));
00920
00921 auto_goto_next_command(a);
00922 return;
00923 }
00924 strcpy(buf, MechIDS(tempmech, 1));
00925 autopilot_swarm(mech, buf);
00926
00927 auto_goto_next_command(a);
00928 return;
00929 #endif
00930 #if 0
00931 case COMMAND_SWARMMODE:
00932 if(MechType(mech) != CLASS_BSUIT) {
00933
00934 auto_goto_next_command(a);
00935 return;
00936 }
00937 if(GVAL(a, 1))
00938 a->flags |= AUTOPILOT_SWARMCHARGE;
00939 else
00940 a->flags &= ~AUTOPILOT_SWARMCHARGE;
00941
00942 auto_goto_next_command(a);
00943 return;
00944 #endif
00945
00946 case COMMAND_UDISEMBARK:
00947 auto_command_udisembark(mech);
00948 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
00949 return;
00950
00951 #if 0
00952 case COMMAND_UNLOAD:
00953 mech_unloadcargo(GOD, mech, my2string(" * 9999"));
00954
00955 auto_goto_next_command(a);
00956 break;
00957 #endif
00958 }
00959 }
00960
00963
00964
00965
00966 static void speed_up_if_neccessary(AUTO * a, MECH * mech, int tx, int ty,
00967 int bearing)
00968 {
00969
00970 if(bearing < 0 || abs((int) MechDesiredSpeed(mech)) < 2)
00971 if(bearing < 0 || abs(bearing - MechFacing(mech)) <= 30)
00972 if(MechX(mech) != tx || MechY(mech) != ty) {
00973 ai_set_speed(mech, a, MMaxSpeed(mech));
00974 }
00975 }
00976
00977
00978
00979
00980
00981 static void update_wanted_heading(AUTO * a, MECH * mech, int bearing)
00982 {
00983
00984 if(MechDesiredFacing(mech) != bearing)
00985 mech_heading(a->mynum, mech, tprintf("%d", bearing));
00986
00987 }
00988
00989
00990
00991
00993 static int slow_down_if_neccessary(AUTO * a, MECH * mech, float range,
00994 int bearing, int tx, int ty)
00995 {
00996
00997 if(range < 0)
00998 range = 0;
00999 if(range > 2.0)
01000 return 0;
01001 if(abs(bearing - MechFacing(mech)) > 30) {
01002
01003 ai_set_speed(mech, a, 0);
01004 update_wanted_heading(a, mech, bearing);
01005 } else if(tx == MechX(mech) && ty == MechY(mech)) {
01006 ai_set_speed(mech, a, 0);
01007 } else {
01008 ai_set_speed(mech, a, (float) (0.4 + range / 2.0) * MMaxSpeed(mech));
01009 }
01010 return 1;
01011 }
01012
01013
01014
01015
01016
01017 void figure_out_range_and_bearing(MECH * mech, int tx, int ty,
01018 float *range, int *bearing)
01019 {
01020
01021 float x, y;
01022
01023 MapCoordToRealCoord(tx, ty, &x, &y);
01024 *bearing = FindBearing(MechFX(mech), MechFY(mech), x, y);
01025 *range = FindHexRange(MechFX(mech), MechFY(mech), x, y);
01026 }
01027
01028
01029
01030
01031
01032
01033 void auto_goto_event(MUXEVENT * e)
01034 {
01035
01036 AUTO *autopilot = (AUTO *) e->data;
01037 int tx, ty;
01038 float dx, dy;
01039 MECH *mech = autopilot->mymech;
01040 float range;
01041 int bearing;
01042
01043 char *argument;
01044
01045 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
01046 return;
01047
01048
01049 AUTO_CHECKS(autopilot);
01050
01051
01052 AUTO_GSTART(autopilot, mech);
01053
01054
01055 argument = auto_get_command_arg(autopilot, 1, 1);
01056 if(Readnum(tx, argument)) {
01058 free(argument);
01059 }
01060 free(argument);
01061
01062
01063 argument = auto_get_command_arg(autopilot, 1, 2);
01064 if(Readnum(ty, argument)) {
01066 free(argument);
01067 }
01068 free(argument);
01069
01070 if(MechX(mech) == tx && MechY(mech) == ty && abs(MechSpeed(mech)) < 0.5) {
01071
01072
01073 ai_set_speed(mech, autopilot, 0);
01074
01075 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01076 return;
01077 }
01078
01079 MapCoordToRealCoord(tx, ty, &dx, &dy);
01080 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
01081 if(!slow_down_if_neccessary(autopilot, mech, range, bearing, tx, ty)) {
01082
01083
01084 if(ai_check_path(mech, autopilot, dx, dy, 0.0, 0.0))
01085 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_goto_event,
01086 AUTOPILOT_GOTO_TICK, 0);
01087
01088 } else {
01089 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_goto_event,
01090 AUTOPILOT_GOTO_TICK, 0);
01091 }
01092
01093 }
01094
01095 #if 0
01096
01097 void auto_roam_event(MUXEVENT * e)
01098 {
01099 AUTO *a = (AUTO *) e->data;
01100 int tx, ty;
01101 float dx, dy, range;
01102 MECH *mech = a->mymech;
01103 MAP *map;
01104 int bearing, i = 1, t;
01105
01106 if(!IsMech(mech->mynum) || !IsAuto(a->mynum))
01107 return;
01108
01109 CCH(a);
01110 GSTART(a, mech);
01111 tx = GVAL(a, 1);
01112 ty = GVAL(a, 2);
01113
01114 if(!mech || !(map = FindObjectsData(mech->mapindex))) {
01115 return;
01116 }
01117
01118 if(!(a->flags & AUTOPILOT_ROAMMODE) || MechTarget(mech) > 0) {
01119 return;
01120 }
01121
01122 if((tx == 0 && ty == 0) || e->data2 > 0 || (MechX(mech) == tx
01123 && MechY(mech) == ty
01124 && abs(MechSpeed(mech)) <
01125 0.5)) {
01126 while (i) {
01127 tx = BOUNDED(1, Number(20, map->map_width - 21),
01128 map->map_width - 1);
01129 ty = BOUNDED(1, Number(20, map->map_height - 21),
01130 map->map_height - 1);
01131 MapCoordToRealCoord(tx, ty, &dx, &dy);
01132 t = GetRTerrain(map, tx, ty);
01133 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech),
01134 dx, dy, ZSCALE * GetElev(map, tx, ty));
01135 if((InLineOfSight(mech, NULL, tx, ty, range) &&
01136 t != WATER && t != HIGHWATER && t != MOUNTAINS) || i > 5000) {
01137 i = 0;
01138 } else {
01139 i++;
01140 }
01141 }
01142 a->commands[a->program_counter + 1] = tx;
01143 a->commands[a->program_counter + 2] = ty;
01144 AUTOEVENT(a, EVENT_AUTOGOTO, auto_roam_event, AUTOPILOT_GOTO_TICK, 0);
01145 return;
01146 }
01147 MapCoordToRealCoord(tx, ty, &dx, &dy);
01148 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
01149 if(!slow_down_if_neccessary(a, mech, range, bearing, tx, ty)) {
01150
01151 if(ai_check_path(mech, a, dx, dy, 0.0, 0.0))
01152 AUTOEVENT(a, EVENT_AUTOGOTO, auto_roam_event, AUTOPILOT_GOTO_TICK,
01153 0);
01154 } else {
01155 AUTOEVENT(a, EVENT_AUTOGOTO, auto_roam_event, AUTOPILOT_GOTO_TICK, 0);
01156 }
01157 }
01158 #endif
01159
01160
01161
01162
01163 void auto_dumbgoto_event(MUXEVENT * muxevent)
01164 {
01165
01166 AUTO *autopilot = (AUTO *) muxevent->data;
01167 int tx, ty;
01168 MECH *mech = autopilot->mymech;
01169 MAP *map;
01170 float range;
01171 int bearing;
01172
01173 char *argument;
01174 char error_buf[MBUF_SIZE];
01175
01176 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
01177 return;
01178
01179
01180 if(Location(autopilot->mynum) != autopilot->mymechnum)
01181 return;
01182
01183
01184 if(Destroyed(mech))
01185 return;
01186
01187
01188 if(auto_get_command_enum(autopilot, 1) != GOAL_DUMBGOTO)
01189 return;
01190
01191
01192 if(!(map = getMap(autopilot->mapindex))) {
01193
01194
01195 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01196 " goto [dumbly] with AI #%d but AI is not on a valid"
01197 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
01198 SendAI(error_buf);
01199
01200 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01201 return;
01202
01203 }
01204
01205
01206 if(!Started(mech)) {
01207
01208
01209 if(!Starting(mech))
01210 auto_command_startup(autopilot, mech);
01211
01212
01213 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_dumbgoto_event,
01214 AUTOPILOT_STARTUP_TICK, 0);
01215 return;
01216 }
01217
01218
01219 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
01220 !(CountDestroyedLegs(mech) > 0)) {
01221
01222 if(!Standing(mech))
01223 mech_stand(autopilot->mynum, mech, "");
01224
01225
01226 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_dumbgoto_event,
01227 AUTOPILOT_NC_DELAY, 0);
01228 return;
01229 }
01230
01233
01234 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
01235
01236
01237
01238 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01239 " goto [dumbly] with AI #%d but was unable to - bad"
01240 " first argument - going to next command", autopilot->mynum);
01241 SendAI(error_buf);
01242 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01243 return;
01244 }
01245
01246
01247 if(Readnum(tx, argument)) {
01248
01249 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01250 " goto [dumbly] with AI #%d but was unable to - bad"
01251 " first argument '%s' - going to next command",
01252 autopilot->mynum, argument);
01253 SendAI(error_buf);
01254 free(argument);
01255 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01256 return;
01257 }
01258 free(argument);
01259
01260
01261 if(!(argument = auto_get_command_arg(autopilot, 1, 2))) {
01262
01263
01264
01265 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01266 " goto [dumbly] with AI #%d but was unable to - bad"
01267 " second argument - going to next command",
01268 autopilot->mynum);
01269 SendAI(error_buf);
01270 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01271 return;
01272 }
01273
01274
01275 if(Readnum(ty, argument)) {
01276
01277 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01278 " goto [dumbly] with AI #%d but was unable to - bad"
01279 " second argument '%s' - going to next command",
01280 autopilot->mynum, argument);
01281 SendAI(error_buf);
01282 free(argument);
01283 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01284 return;
01285 }
01286 free(argument);
01287
01288
01289 if(MechX(mech) == tx && MechY(mech) == ty && abs(MechSpeed(mech)) < 0.5) {
01290
01291
01292 ai_set_speed(mech, autopilot, 0);
01293
01294 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01295 return;
01296 }
01297
01298
01299 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
01300 speed_up_if_neccessary(autopilot, mech, tx, ty, bearing);
01301 slow_down_if_neccessary(autopilot, mech, range, bearing, tx, ty);
01302 update_wanted_heading(autopilot, mech, bearing);
01303 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_dumbgoto_event,
01304 AUTOPILOT_GOTO_TICK, 0);
01305 }
01306
01307
01308
01309
01310
01311
01312
01313 void auto_astar_goto_event(MUXEVENT * muxevent)
01314 {
01315
01316 AUTO *autopilot = (AUTO *) muxevent->data;
01317 int tx, ty;
01318 MECH *mech = autopilot->mymech;
01319 MAP *map;
01320 float range;
01321 int bearing;
01322
01323 int generate_path = (int) muxevent->data2;
01324
01325 char *argument;
01326 astar_node *temp_astar_node;
01327
01328 char error_buf[MBUF_SIZE];
01329
01330
01331 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
01332 return;
01333
01334
01335 if(Location(autopilot->mynum) != autopilot->mymechnum)
01336 return;
01337
01338
01339 if(Destroyed(mech))
01340 return;
01341
01342
01343 if(auto_get_command_enum(autopilot, 1) != GOAL_GOTO)
01344 return;
01345
01346
01347 if(!(map = getMap(autopilot->mapindex))) {
01348
01349
01350 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01351 " goto with AI #%d but AI is not on a valid"
01352 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
01353 SendAI(error_buf);
01354
01355 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01356 return;
01357
01358 }
01359
01360
01361 if(!Started(mech)) {
01362
01363
01364 if(!Starting(mech))
01365 auto_command_startup(autopilot, mech);
01366
01367
01368 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_astar_goto_event,
01369 AUTOPILOT_STARTUP_TICK, generate_path);
01370 return;
01371 }
01372
01373
01374 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
01375 !(CountDestroyedLegs(mech) > 0)) {
01376
01377 if(!Standing(mech))
01378 mech_stand(autopilot->mynum, mech, "");
01379
01380
01381 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_astar_goto_event,
01382 AUTOPILOT_NC_DELAY, generate_path);
01383 return;
01384 }
01385
01388
01389 if(generate_path) {
01390
01391
01392 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
01393
01394
01395
01396 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01397 " generate an astar path for AI #%d to hex %d,%d but was"
01398 " unable to - bad first argument - going to next command",
01399 autopilot->mynum, tx, ty);
01400 SendAI(error_buf);
01401 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01402 return;
01403 }
01404
01405
01406 if(Readnum(tx, argument)) {
01407
01408 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01409 " generate an astar path for AI #%d to hex %d,%d but was"
01410 " unable to - bad first argument '%s' - going to next command",
01411 autopilot->mynum, tx, ty, argument);
01412 SendAI(error_buf);
01413
01414 free(argument);
01415 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01416 return;
01417 }
01418 free(argument);
01419
01420
01421 if(!(argument = auto_get_command_arg(autopilot, 1, 2))) {
01422
01423
01424
01425 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01426 " generate an astar path for AI #%d to hex %d,%d but was"
01427 " unable to - bad second argument - going to next command",
01428 autopilot->mynum, tx, ty);
01429 SendAI(error_buf);
01430 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01431 return;
01432 }
01433
01434
01435 if(Readnum(ty, argument)) {
01436
01437 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01438 " generate an astar path for AI #%d to hex %d,%d but was"
01439 " unable to - bad second argument '%s' - going to next command",
01440 autopilot->mynum, tx, ty, argument);
01441 SendAI(error_buf);
01442
01443 free(argument);
01444 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01445 return;
01446 }
01447 free(argument);
01448
01449
01450 if (tx < 0 || ty < 0 || tx >= map->map_width || ty >= map->map_width) {
01451
01452
01453 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01454 " generate an astar path for AI #%d to bad hex"
01455 " (%d, %d)", autopilot->mynum, tx, ty);
01456 SendAI(error_buf);
01457 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01458 return;
01459 }
01460
01461
01462 if(!(auto_astar_generate_path(autopilot, mech, tx, ty))) {
01463
01464
01465 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01466 " generate an astar path for AI #%d to hex %d,%d but was"
01467 " unable to", autopilot->mynum, tx, ty);
01468 SendAI(error_buf);
01469
01472 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01473 return;
01474
01475 }
01476
01477 }
01478
01479
01480 if(!(autopilot->astar_path) || (dllist_size(autopilot->astar_path) <= 0)) {
01481
01482 snprintf(error_buf, MBUF_SIZE,
01483 "Internal AI Error - Attempting to follow"
01484 " Astar path for AI #%d - but the path is not there",
01485 autopilot->mynum);
01486 SendAI(error_buf);
01487
01488 auto_destroy_astar_path(autopilot);
01489 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01490 return;
01491
01492 }
01493
01494
01495 temp_astar_node =
01496 (astar_node *) dllist_get_node(autopilot->astar_path, 1);
01497
01498 if(!(temp_astar_node)) {
01499
01500 snprintf(error_buf, MBUF_SIZE,
01501 "Internal AI Error - Attemping to follow"
01502 " Astar path for AI #%d - but the current astar node does not"
01503 " exist", autopilot->mynum);
01504 SendAI(error_buf);
01505
01506 auto_destroy_astar_path(autopilot);
01507 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01508 return;
01509
01510 }
01511
01512
01513 if((MechX(mech) == temp_astar_node->x) &&
01514 (MechY(mech) == temp_astar_node->y)) {
01515
01516
01517 if(dllist_size(autopilot->astar_path) == 1) {
01518
01519
01520 ai_set_speed(mech, autopilot, 0);
01521
01522
01523 auto_destroy_astar_path(autopilot);
01524 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01525 return;
01526
01527 } else {
01528
01529
01530 temp_astar_node =
01531 (astar_node *) dllist_remove_node_at_pos(autopilot->
01532 astar_path, 1);
01533 free(temp_astar_node);
01534
01535
01536 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_astar_goto_event,
01537 AUTOPILOT_GOTO_TICK, 0);
01538 return;
01539
01540 }
01541
01542 }
01543
01544
01545
01546 tx = temp_astar_node->x;
01547 ty = temp_astar_node->y;
01548
01549
01550 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
01551 speed_up_if_neccessary(autopilot, mech, tx, ty, bearing);
01552 slow_down_if_neccessary(autopilot, mech, range, bearing, tx, ty);
01553 update_wanted_heading(autopilot, mech, bearing);
01554
01555 AUTOEVENT(autopilot, EVENT_AUTOGOTO, auto_astar_goto_event,
01556 AUTOPILOT_GOTO_TICK, 0);
01557
01558 }
01559
01560
01561
01562
01563 void auto_astar_follow_event(MUXEVENT * muxevent)
01564 {
01565
01566 AUTO *autopilot = (AUTO *) muxevent->data;
01567 MECH *mech = autopilot->mymech;
01568 MECH *target;
01569 MAP *map;
01570
01571 dbref target_dbref;
01572
01573 float range;
01574 float fx, fy;
01575 short x, y;
01576 int bearing;
01577 int destroy_path = (int) muxevent->data2;
01578
01579 char *argument;
01580 astar_node *temp_astar_node;
01581
01582 char error_buf[MBUF_SIZE];
01583
01584 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
01585 return;
01586
01587
01588 if(Location(autopilot->mynum) != autopilot->mymechnum)
01589 return;
01590
01591
01592 if(Destroyed(mech))
01593 return;
01594
01595
01596 switch (auto_get_command_enum(autopilot, 1)) {
01597
01598 case GOAL_FOLLOW:
01599 break;
01600 case GOAL_CHASETARGET:
01601 break;
01602 default:
01603 return;
01604 }
01605
01606
01607 if(!(map = getMap(autopilot->mapindex))) {
01608
01609
01610 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01611 " follow with AI #%d but AI is not on a valid"
01612 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
01613 SendAI(error_buf);
01614
01615 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01616 return;
01617
01618 }
01619
01620
01621 if(!Started(mech)) {
01622
01623
01624 if(!Starting(mech))
01625 auto_command_startup(autopilot, mech);
01626
01627
01628 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01629 AUTOPILOT_STARTUP_TICK, destroy_path);
01630 return;
01631 }
01632
01633
01634 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
01635 !(CountDestroyedLegs(mech) > 0)) {
01636
01637 if(!Standing(mech))
01638 mech_stand(autopilot->mynum, mech, "");
01639
01640
01641 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01642 AUTOPILOT_NC_DELAY, destroy_path);
01643 return;
01644 }
01645
01648
01649 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
01650
01651
01652
01653 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - AI #%d attempting"
01654 " to follow target but was unable to - bad argument - going"
01655 " to next command", autopilot->mynum);
01656 SendAI(error_buf);
01657 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01658 return;
01659 }
01660
01661
01662 if(Readnum(target_dbref, argument)) {
01663
01664 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - AI #%d attempting"
01665 " to follow target but was unable to - bad argument '%s' - going"
01666 " to next command", autopilot->mynum, argument);
01667 SendAI(error_buf);
01668 free(argument);
01669 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01670 return;
01671 }
01672 free(argument);
01673
01674
01675 if(!(target = getMech(target_dbref))) {
01676
01677
01678 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01679 " follow unit #%d with AI #%d but its not a valid unit.",
01680 target_dbref, autopilot->mynum);
01681 SendAI(error_buf);
01682
01683 ai_set_speed(mech, autopilot, 0);
01684 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01685 return;
01686 }
01687
01688
01689 if(Destroyed(target) || (target->mapindex != mech->mapindex)) {
01690
01691 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01692 " follow unit #%d with AI #%d but it is either dead or"
01693 " not on the same map.", target_dbref, autopilot->mynum);
01694 SendAI(error_buf);
01695
01696 ai_set_speed(mech, autopilot, 0);
01697 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01698 return;
01699 }
01700
01701
01702 FindXY(MechFX(target), MechFY(target),
01703 MechFacing(target) + autopilot->ofsx, autopilot->ofsy, &fx, &fy);
01704
01705 RealCoordToMapCoord(&x, &y, fx, fy);
01706
01707
01708
01709 if(x < 0 || y < 0 || x >= map->map_width || y >= map->map_height) {
01710
01711
01712 x = MechX(target);
01713 y = MechY(target);
01714
01715 }
01716
01717
01718 if((MechX(mech) == x) && (MechY(mech) == y) && (MechSpeed(target) < 0.5)) {
01719
01720
01721 ai_set_speed(mech, autopilot, 0.0);
01722
01723
01724
01725 if(autopilot->astar_path) {
01726 auto_destroy_astar_path(autopilot);
01727 }
01728
01729 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01730 AUTOPILOT_FOLLOW_TICK, 0);
01731 return;
01732 }
01733
01734
01735
01736 if(destroy_path) {
01737 auto_destroy_astar_path(autopilot);
01738 }
01739
01740
01741
01742 if(!(autopilot->astar_path) ||
01743 autopilot->follow_update_tick >= AUTOPILOT_FOLLOW_UPDATE_TICK) {
01744
01745
01746 if((x != MechX(mech)) || (y != MechY(mech))) {
01747
01748
01749 if(!(auto_astar_generate_path(autopilot, mech, x, y))) {
01750
01751
01752
01753 x = MechX(target);
01754 y = MechY(target);
01755
01756
01757
01758 autopilot->follow_update_tick = AUTOPILOT_FOLLOW_UPDATE_TICK;
01759
01760 } else {
01761
01762
01763 autopilot->follow_update_tick = 0;
01764
01765 }
01766
01767 if((autopilot->follow_update_tick != 0) &&
01768 !(auto_astar_generate_path(autopilot, mech, x, y))) {
01769
01770
01771 snprintf(error_buf, MBUF_SIZE,
01772 "Internal AI Error - Attempting to"
01773 " generate an astar path for AI #%d to hex %d,%d to follow"
01774 " unit #%d, but was unable to.", autopilot->mynum, x,
01775 y, target_dbref);
01776 SendAI(error_buf);
01777
01780 ai_set_speed(mech, autopilot, 0);
01781 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01782 return;
01783
01784 } else {
01785
01786
01787 autopilot->follow_update_tick = 0;
01788 }
01789
01790 } else {
01791
01792
01793 if(!(auto_astar_generate_path(autopilot, mech, x, y))) {
01794
01795
01796 snprintf(error_buf, MBUF_SIZE,
01797 "Internal AI Error - Attempting to"
01798 " generate an astar path for AI #%d to hex %d,%d to follow"
01799 " unit #%d, but was unable to.", autopilot->mynum, x,
01800 y, target_dbref);
01801 SendAI(error_buf);
01802
01805 ai_set_speed(mech, autopilot, 0);
01806 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01807 return;
01808
01809 } else {
01810
01811
01812 autopilot->follow_update_tick = 0;
01813
01814 }
01815
01816 }
01817
01818 }
01819
01820
01821 if(!(autopilot->astar_path) || (dllist_size(autopilot->astar_path) <= 0)) {
01822
01823 snprintf(error_buf, MBUF_SIZE,
01824 "Internal AI Error - Attempting to follow"
01825 " Astar path for AI #%d - but the path is not there",
01826 autopilot->mynum);
01827 SendAI(error_buf);
01828
01829
01830 auto_destroy_astar_path(autopilot);
01831 ai_set_speed(mech, autopilot, 0);
01832 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01833 return;
01834
01835 }
01836
01837
01838 temp_astar_node =
01839 (astar_node *) dllist_get_node(autopilot->astar_path, 1);
01840
01841 if(!(temp_astar_node)) {
01842
01843 snprintf(error_buf, MBUF_SIZE,
01844 "Internal AI Error - Attemping to follow"
01845 " Astar path for AI #%d - but the current astar node does not"
01846 " exist", autopilot->mynum);
01847 SendAI(error_buf);
01848
01849
01850 auto_destroy_astar_path(autopilot);
01851 ai_set_speed(mech, autopilot, 0);
01852 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01853 return;
01854
01855 }
01856
01857
01858 if((MechX(mech) == temp_astar_node->x) &&
01859 (MechY(mech) == temp_astar_node->y)) {
01860
01861
01862 if(dllist_size(autopilot->astar_path) == 1) {
01863
01864
01865 ai_set_speed(mech, autopilot, 0);
01866 auto_destroy_astar_path(autopilot);
01867
01868
01869 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01870 AUTOPILOT_FOLLOW_TICK, 0);
01871 return;
01872
01873 } else {
01874
01875
01876 temp_astar_node =
01877 (astar_node *) dllist_remove_node_at_pos(autopilot->
01878 astar_path, 1);
01879 free(temp_astar_node);
01880
01881
01882 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01883 AUTOPILOT_FOLLOW_TICK, 0);
01884 return;
01885
01886 }
01887
01888 }
01889
01890
01891
01892 x = temp_astar_node->x;
01893 y = temp_astar_node->y;
01894
01895
01896 figure_out_range_and_bearing(mech, x, y, &range, &bearing);
01897 speed_up_if_neccessary(autopilot, mech, x, y, bearing);
01898 slow_down_if_neccessary(autopilot, mech, range, bearing, x, y);
01899 update_wanted_heading(autopilot, mech, bearing);
01900
01901
01902 autopilot->follow_update_tick++;
01903
01904 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_astar_follow_event,
01905 AUTOPILOT_FOLLOW_TICK, 0);
01906
01907 }
01908
01909 #if 0
01910
01911 void auto_follow_event(MUXEVENT * e)
01912 {
01913 AUTO *a = (AUTO *) e->data;
01914 float fx, fy, newx, newy;
01915 int h;
01916 MECH *leader;
01917 MECH *mech = a->mymech;
01918
01919 if(!IsMech(mech->mynum) || !IsAuto(a->mynum))
01920 return;
01921
01922 CCH(a);
01923 GSTART(a, mech);
01924 if(!(leader = getMech(GVAL(a, 1)))) {
01925
01926 ADVANCE_PG(a);
01927 return;
01928 }
01929 h = MechFacing(leader);
01930 FindXY(MechFX(leader), MechFY(leader), h + a->ofsx, a->ofsy, &fx, &fy);
01931 FindComponents(MechSpeed(leader) * MOVE_MOD, MechFacing(leader),
01932 &newx, &newy);
01933 if(ai_check_path(mech, a, fx, fy, newx, newy))
01934 AUTOEVENT(a, EVENT_AUTOFOLLOW, auto_follow_event,
01935 AUTOPILOT_FOLLOW_TICK, 0);
01936 }
01937 #endif
01938
01939
01940
01941
01942 void auto_dumbfollow_event(MUXEVENT * muxevent)
01943 {
01944
01945 AUTO *autopilot = (AUTO *) muxevent->data;
01946 int tx, ty, x, y;
01947 int h;
01948 MECH *leader;
01949 MECH *mech = autopilot->mymech;
01950 MAP *map;
01951 float range;
01952 int bearing;
01953
01954 char *argument;
01955 int target;
01956
01957 char error_buf[MBUF_SIZE];
01958 char buffer[SBUF_SIZE];
01959
01960
01961 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
01962 return;
01963
01964
01965 if(Location(autopilot->mynum) != autopilot->mymechnum)
01966 return;
01967
01968
01969 if(Destroyed(mech))
01970 return;
01971
01972
01973 if(auto_get_command_enum(autopilot, 1) != GOAL_DUMBFOLLOW)
01974 return;
01975
01976
01977 if(!(map = getMap(autopilot->mapindex))) {
01978
01979
01980 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
01981 " follow [dumbly] with AI #%d but AI is not on a valid"
01982 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
01983 SendAI(error_buf);
01984
01985 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
01986 return;
01987
01988 }
01989
01990
01991 if(!Started(mech)) {
01992
01993
01994 if(!Starting(mech))
01995 auto_command_startup(autopilot, mech);
01996
01997
01998 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_dumbfollow_event,
01999 AUTOPILOT_STARTUP_TICK, 0);
02000 return;
02001 }
02002
02003
02004 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
02005 !(CountDestroyedLegs(mech) > 0)) {
02006
02007 if(!Standing(mech))
02008 mech_stand(autopilot->mynum, mech, "");
02009
02010
02011 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_dumbfollow_event,
02012 AUTOPILOT_NC_DELAY, 0);
02013 return;
02014 }
02015
02018
02019 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
02020
02021
02022
02023 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - AI #%d attempting"
02024 " to follow target [dumbly] but was unable to - bad argument - going"
02025 " to next command", autopilot->mynum);
02026 SendAI(error_buf);
02027 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02028 return;
02029 }
02030
02031
02032 if(Readnum(target, argument)) {
02033
02034
02035 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - AI #%d attempting"
02036 " to follow target [dumbly] but was unable to - bad argument '%s' - going"
02037 " to next command", autopilot->mynum, argument);
02038 SendAI(error_buf);
02039 free(argument);
02040 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02041 return;
02042
02043 }
02044 free(argument);
02045
02046
02047 if(!(leader = getMech(target)) || Destroyed(leader)) {
02048
02049
02050 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - AI #%d attempting"
02051 " to follow target [dumbly] but was unable to - bad or dead target -"
02052 " going to next command", autopilot->mynum);
02053 SendAI(error_buf);
02054 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02055 return;
02056 }
02057
02058 h = MechDesiredFacing(leader);
02059 x = autopilot->ofsy * cos(TWOPIOVER360 * (270.0 + (h + autopilot->ofsx)));
02060 y = autopilot->ofsy * sin(TWOPIOVER360 * (270.0 + (h + autopilot->ofsx)));
02061 tx = MechX(leader) + x;
02062 ty = MechY(leader) + y;
02063
02064 if(MechX(mech) == tx && MechY(mech) == ty) {
02065
02066
02067
02068
02069 if(MechSpeed(leader) > 1 || MechSpeed(leader) < -1 ||
02070 MechSpeed(mech) > 1 || MechSpeed(mech) < -1) {
02071
02072 if(MechDesiredFacing(mech) != MechFacing(leader)) {
02073 snprintf(buffer, SBUF_SIZE, "%d", MechFacing(leader));
02074 mech_heading(autopilot->mynum, mech, buffer);
02075 }
02076
02077 if(MechSpeed(mech) != MechSpeed(leader)) {
02078 snprintf(buffer, SBUF_SIZE, "%.2f", MechSpeed(leader));
02079 mech_speed(autopilot->mynum, mech, buffer);
02080 }
02081 }
02082
02083 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_dumbfollow_event,
02084 AUTOPILOT_FOLLOW_TICK, 0);
02085 return;
02086 }
02087
02088 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
02089 speed_up_if_neccessary(autopilot, mech, tx, ty, -1);
02090
02091 if(MechSpeed(leader) < MP1)
02092 slow_down_if_neccessary(autopilot, mech, range + 1, bearing, tx, ty);
02093
02094 update_wanted_heading(autopilot, mech, bearing);
02095
02096 AUTOEVENT(autopilot, EVENT_AUTOFOLLOW, auto_dumbfollow_event,
02097 AUTOPILOT_FOLLOW_TICK, 0);
02098 }
02099
02100
02101
02102
02103 void auto_leave_event(MUXEVENT * muxevent)
02104 {
02105
02106 AUTO *autopilot = (AUTO *) muxevent->data;
02107 MECH *mech = autopilot->mymech;
02108 MAP *map;
02109
02110 int dir;
02111 int reset_mapindex = (int) muxevent->data2;
02112 char *argument;
02113 char error_buf[MBUF_SIZE];
02114
02115 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
02116 return;
02117
02118
02119 if(Location(autopilot->mynum) != autopilot->mymechnum)
02120 return;
02121
02122
02123 if(Destroyed(mech))
02124 return;
02125
02126
02127 if(auto_get_command_enum(autopilot, 1) != GOAL_LEAVEBASE)
02128 return;
02129
02130
02131 if(!(map = getMap(autopilot->mapindex))) {
02132
02133
02134 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02135 " leavebase with AI #%d but AI is not on a valid"
02136 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
02137 SendAI(error_buf);
02138
02139 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02140 return;
02141
02142 }
02143
02144
02145 if(!Started(mech)) {
02146
02147
02148 if(!Starting(mech))
02149 auto_command_startup(autopilot, mech);
02150
02151
02152 AUTOEVENT(autopilot, EVENT_AUTOLEAVE, auto_leave_event,
02153 AUTOPILOT_STARTUP_TICK, reset_mapindex);
02154 return;
02155 }
02156
02157
02158 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
02159 !(CountDestroyedLegs(mech) > 0)) {
02160
02161 if(!Standing(mech))
02162 mech_stand(autopilot->mynum, mech, "");
02163
02164
02165 AUTOEVENT(autopilot, EVENT_AUTOLEAVE, auto_leave_event,
02166 AUTOPILOT_NC_DELAY, reset_mapindex);
02167 return;
02168 }
02169
02172
02173 if(reset_mapindex) {
02174 autopilot->mapindex = mech->mapindex;
02175 }
02176
02177
02178 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
02179
02180
02181
02182 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02183 " leavebase with AI #%d but was given bad argument"
02184 " defaulting to direction = 0", autopilot->mynum);
02185 SendAI(error_buf);
02186
02187 dir = 0;
02188
02189 } else if(Readnum(dir, argument)) {
02190
02191 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02192 " leavebase with AI #%d but was given bad argument '%s'"
02193 " defaulting to direction = 0", autopilot->mynum, argument);
02194 SendAI(error_buf);
02195
02196 dir = 0;
02197
02198 }
02199 free(argument);
02200
02201 if(mech->mapindex != autopilot->mapindex) {
02202
02203
02204 autopilot->mapindex = mech->mapindex;
02205 ai_set_speed(mech, autopilot, 0);
02206 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02207 return;
02208 }
02209
02210
02211 speed_up_if_neccessary(autopilot, mech, -1, -1, dir);
02212 update_wanted_heading(autopilot, mech, dir);
02213 AUTOEVENT(autopilot, EVENT_AUTOLEAVE, auto_leave_event,
02214 AUTOPILOT_LEAVE_TICK, 0);
02215 }
02216
02217
02218
02219
02220
02221 void auto_enter_event(MUXEVENT * muxevent)
02222 {
02223
02224 AUTO *autopilot = (AUTO *) muxevent->data;
02225 MECH *mech = autopilot->mymech;
02226 MAP *map;
02227 mapobj *map_object;
02228 int num;
02229 int reset_mapindex = (int) muxevent->data2;
02230
02231 char *argument;
02232 char dir[2];
02233 char error_buf[MBUF_SIZE];
02234
02235 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
02236 return;
02237
02238
02239 if(Location(autopilot->mynum) != autopilot->mymechnum)
02240 return;
02241
02242
02243 if(Destroyed(mech))
02244 return;
02245
02246
02247 if(auto_get_command_enum(autopilot, 1) != GOAL_ENTERBASE)
02248 return;
02249
02250
02251 if(!(map = getMap(autopilot->mapindex))) {
02252
02253
02254 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02255 " enterbase with AI #%d but AI is not on a valid"
02256 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
02257 SendAI(error_buf);
02258
02259 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02260 return;
02261
02262 }
02263
02264
02265 if(!(map_object = find_entrance_by_xy(map, MechX(mech), MechY(mech)))) {
02266
02267
02268 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02269 " enterbase with AI #%d but there is nothing at %d, %d"
02270 " to enter", autopilot->mynum, MechX(mech), MechY(mech));
02271 SendAI(error_buf);
02272 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02273 return;
02274 }
02275
02276
02277 if(reset_mapindex) {
02278 autopilot->mapindex = mech->mapindex;
02279 }
02280
02281
02282 if(!Started(mech)) {
02283
02284
02285 if(!Starting(mech))
02286 auto_command_startup(autopilot, mech);
02287
02288
02289 AUTOEVENT(autopilot, EVENT_AUTOENTERBASE,
02290 auto_enter_event, AUTOPILOT_STARTUP_TICK, 0);
02291 return;
02292 }
02293
02294
02295 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
02296 !(CountDestroyedLegs(mech) > 0)) {
02297
02298 if(!Standing(mech))
02299 mech_stand(autopilot->mynum, mech, "");
02300
02301
02302 AUTOEVENT(autopilot, EVENT_AUTOENTERBASE,
02303 auto_enter_event, AUTOPILOT_NC_DELAY, 0);
02304 return;
02305 }
02306
02307
02308 if(!(argument = auto_get_command_arg(autopilot, 1, 1))) {
02309
02310
02311
02312 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02313 " enterbase with AI #%d but was given bad argument -"
02314 " going to next command", autopilot->mynum);
02315 SendAI(error_buf);
02316 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02317 return;
02318 }
02319
02320
02321
02322 switch (argument[0]) {
02323
02324 case 'n':
02325 case 'N':
02326 strcpy(dir, "n");
02327 break;
02328 case 's':
02329 case 'S':
02330 strcpy(dir, "s");
02331 break;
02332 case 'w':
02333 case 'W':
02334 strcpy(dir, "w");
02335 break;
02336 case 'e':
02337 case 'E':
02338 strcpy(dir, "e");
02339 break;
02340 default:
02341 strcpy(dir, "");
02342
02343 }
02344 free(argument);
02345
02346
02347 if(mech->mapindex != autopilot->mapindex) {
02348
02349 autopilot->mapindex = mech->mapindex;
02350 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02351 return;
02352 }
02353
02354 if(MechDesiredSpeed(mech) != 0.0)
02355 ai_set_speed(mech, autopilot, 0);
02356
02357 if((MechSpeed(mech) == 0.0) && !EnteringHangar(mech)) {
02358 mech_enterbase(GOD, mech, dir);
02359 }
02360
02361
02362 AUTOEVENT(autopilot, EVENT_AUTOENTERBASE, auto_enter_event,
02363 AUTOPILOT_NC_DELAY, 0);
02364 }
02365
02366
02367
02368
02369
02370
02371 void auto_command_roam(AUTO * autopilot, MECH * mech)
02372 {
02373
02374 char *argument;
02375 char error_buf[MBUF_SIZE];
02376 char *args[4];
02377 int argc;
02378 int i;
02379 int anchor_hex_x;
02380 int anchor_hex_y;
02381 int anchor_distance;
02382
02383 MAP *map;
02384
02385
02386 argument = auto_get_command_arg(autopilot, 1, 1);
02387
02388
02389 argc = proper_explodearguments(argument, args, 4);
02390
02391
02392 free(argument);
02393
02394
02395 if(argc == 1) {
02396
02397
02398 if(strcmp(args[0], "map") == 0) {
02399
02400
02401 autopilot->roam_type = AUTO_ROAM_MAP;
02402
02403
02404 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02405 AUTO_ROAM_TICK, 1);
02406
02407 } else {
02408
02409
02410 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02411 " argument for roam command", autopilot->mynum);
02412 SendAI(error_buf);
02413
02414 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02415
02416 }
02417
02418 } else if(argc == 4) {
02419
02420
02421 if(strcmp(args[0], "radius") == 0) {
02422
02423
02424 if(Readnum(anchor_hex_x, args[1])) {
02425
02426 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02427 " argument (anchor_hex_x) for roam command",
02428 autopilot->mynum);
02429 SendAI(error_buf);
02430
02431 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02432
02433
02434 for(i = 0; i < 4; i++) {
02435 if(args[i])
02436 free(args[i]);
02437 }
02438
02439 return;
02440 }
02441
02442 if(Readnum(anchor_hex_y, args[2])) {
02443
02444 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02445 " argument (anchor_hex_y) for roam command",
02446 autopilot->mynum);
02447 SendAI(error_buf);
02448
02449 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02450
02451
02452 for(i = 0; i < 4; i++) {
02453 if(args[i])
02454 free(args[i]);
02455 }
02456
02457 return;
02458 }
02459
02460
02461 if(Readnum(anchor_distance, args[3])) {
02462
02463 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02464 " argument (anchor_distance) for roam command",
02465 autopilot->mynum);
02466 SendAI(error_buf);
02467
02468 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02469
02470
02471 for(i = 0; i < 4; i++) {
02472 if(args[i])
02473 free(args[i]);
02474 }
02475
02476 return;
02477 }
02478
02479
02480
02481
02482 if(!(map = getMap(autopilot->mapindex))) {
02483
02484
02485 snprintf(error_buf, MBUF_SIZE,
02486 "Internal AI Error - Attempting to"
02487 " roam with AI #%d but AI is not on a valid"
02488 " Map (#%d).", autopilot->mynum,
02489 autopilot->mapindex);
02490 SendAI(error_buf);
02491
02492 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02493
02494
02495 for(i = 0; i < 4; i++) {
02496 if(args[i])
02497 free(args[i]);
02498 }
02499
02500 return;
02501
02502 }
02503
02504
02505
02506 if(anchor_hex_x < 0 || anchor_hex_y < 0 ||
02507 anchor_hex_x >= map->map_width ||
02508 anchor_hex_y >= map->map_height ||
02509 anchor_distance > AUTO_ROAM_MAX_RADIUS) {
02510
02511 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02512 " argument (bad anchor hex or bad anchor distance)"
02513 " %d,%d : %d hexes for roam command",
02514 autopilot->mynum, anchor_hex_x, anchor_hex_y,
02515 anchor_distance);
02516 SendAI(error_buf);
02517
02518 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02519
02520
02521 for(i = 0; i < 4; i++) {
02522 if(args[i])
02523 free(args[i]);
02524 }
02525
02526 return;
02527 }
02528
02529
02530 autopilot->roam_type = AUTO_ROAM_SPOT;
02531 autopilot->roam_anchor_hex_x = anchor_hex_x;
02532 autopilot->roam_anchor_hex_y = anchor_hex_y;
02533 autopilot->roam_anchor_distance = anchor_distance;
02534
02535
02536 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02537 AUTO_ROAM_TICK, 1);
02538
02539 } else {
02540
02541
02542 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02543 " argument for roam command", autopilot->mynum);
02544 SendAI(error_buf);
02545
02546 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02547
02548 }
02549
02550 } else {
02551
02552
02553 snprintf(error_buf, MBUF_SIZE, "AI Error - AI #%d given bad"
02554 " argument for roam command", autopilot->mynum);
02555 SendAI(error_buf);
02556
02557 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02558
02559 }
02560
02561
02562 for(i = 0; i < 4; i++) {
02563 if(args[i])
02564 free(args[i]);
02565 }
02566
02567 }
02568
02569
02570
02571
02572 void auto_roam_generate_target_hex(AUTO * autopilot, MECH * mech, MAP * map,
02573 int attempt)
02574 {
02575
02576 short start_hex_x = 0;
02577 short start_hex_y = 0;
02578 short target_hex_x = 0;
02579 short target_hex_y = 0;
02580 float x1, y1, x2, y2;
02581 float range;
02582 int bearing;
02583 int max_range = 0;
02584 int counter;
02585
02586
02587 if(autopilot->roam_type == AUTO_ROAM_MAP) {
02588
02589 start_hex_x = MechX(mech);
02590 start_hex_y = MechY(mech);
02591 max_range = AUTO_ROAM_MAX_MAP_DISTANCE;
02592
02593 } else if(autopilot->roam_type == AUTO_ROAM_SPOT) {
02594
02595 start_hex_x = autopilot->roam_anchor_hex_x;
02596 start_hex_y = autopilot->roam_anchor_hex_y;
02597 max_range = autopilot->roam_anchor_distance;
02598
02599 } else {
02600
02602 }
02603
02604
02605
02606 max_range = max_range / (2 ^ attempt);
02607
02608 counter = 0;
02609
02610 while (counter < AUTO_ROAM_MAX_ITERATIONS) {
02611
02612
02613 counter++;
02614
02615
02616 if(max_range < 1) {
02617 range = 1.0;
02618 } else {
02619 range = (float) Number(1, max_range);
02620 }
02621
02622
02623 bearing = Number(0, 359);
02624
02625
02626 MapCoordToRealCoord(start_hex_x, start_hex_y, &x1, &y1);
02627
02628
02629 FindXY(x1, y1, bearing, range, &x2, &y2);
02630
02631
02632 RealCoordToMapCoord(&target_hex_x, &target_hex_y, x2, y2);
02633
02634
02635 if(target_hex_x < 0 || target_hex_y < 0 ||
02636 target_hex_x >= map->map_width || target_hex_y >= map->map_height)
02637 continue;
02638
02639 switch (GetTerrain(map, target_hex_x, target_hex_y)) {
02640 case LIGHT_FOREST:
02641 if((MechType(mech) == CLASS_VEH_GROUND) &&
02642 (MechMove(mech) != MOVE_TRACK))
02643 continue;
02644
02645 break;
02646
02647 case HEAVY_FOREST:
02648 if(MechType(mech) == CLASS_VEH_GROUND)
02649 continue;
02650
02651 break;
02652
02653 case WATER:
02654 if(MechMove(mech) != MOVE_HOVER)
02655 continue;
02656
02657 break;
02658
02659 }
02660
02661
02662
02663 autopilot->roam_target_hex_x = target_hex_x;
02664 autopilot->roam_target_hex_y = target_hex_y;
02665 break;
02666
02667 }
02668
02669 }
02670
02671
02672
02673
02674 void auto_astar_roam_event(MUXEVENT * muxevent)
02675 {
02676
02677 AUTO *autopilot = (AUTO *) muxevent->data;
02678 int tx, ty;
02679 MECH *mech = autopilot->mymech;
02680 MAP *map;
02681 float range;
02682 int bearing;
02683 int roam_hex_attempt;
02684 int generate_path = (int) muxevent->data2;
02685
02686 astar_node *temp_astar_node;
02687
02688 char error_buf[MBUF_SIZE];
02689
02690
02691 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
02692 return;
02693
02694
02695 if(Location(autopilot->mynum) != autopilot->mymechnum)
02696 return;
02697
02698
02699 if(Destroyed(mech))
02700 return;
02701
02702
02703 if(auto_get_command_enum(autopilot, 1) != GOAL_ROAM)
02704 return;
02705
02706
02707 if(!(map = getMap(autopilot->mapindex))) {
02708
02709
02710 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attempting to"
02711 " roam with AI #%d but AI is not on a valid"
02712 " Map (#%d).", autopilot->mynum, autopilot->mapindex);
02713 SendAI(error_buf);
02714
02715 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02716 return;
02717
02718 }
02719
02720
02721 if(!Started(mech)) {
02722
02723
02724 if(!Starting(mech))
02725 auto_command_startup(autopilot, mech);
02726
02727
02728 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02729 AUTOPILOT_STARTUP_TICK, generate_path);
02730 return;
02731 }
02732
02733
02734 if(MechType(mech) == CLASS_MECH && Fallen(mech) &&
02735 !(CountDestroyedLegs(mech) > 0)) {
02736
02737 if(!Standing(mech))
02738 mech_stand(autopilot->mynum, mech, "");
02739
02740
02741 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02742 AUTOPILOT_NC_DELAY, generate_path);
02743 return;
02744 }
02745
02748
02749 if(generate_path || autopilot->roam_update_tick >= AUTO_ROAM_NEW_HEX_TICK) {
02750
02751
02752 roam_hex_attempt = 0;
02753
02754 while (roam_hex_attempt < AUTO_ROAM_MAX_ITERATIONS) {
02755
02756
02757
02758
02759 auto_roam_generate_target_hex(autopilot, mech, map,
02760 roam_hex_attempt);
02761
02762
02763 if((autopilot->roam_target_hex_x != -1) &&
02764 (autopilot->roam_target_hex_y != -1) &&
02765 auto_astar_generate_path(autopilot, mech,
02766 autopilot->roam_target_hex_x,
02767 autopilot->roam_target_hex_y)) {
02768
02769
02770 break;
02771
02772 }
02773
02774 roam_hex_attempt++;
02775
02776 }
02777
02778
02779 if(!(autopilot->astar_path)
02780 || (dllist_size(autopilot->astar_path) <= 0)) {
02781
02782
02783 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02784 AUTO_ROAM_TICK, 1);
02785 return;
02786 }
02787
02788
02789 autopilot->roam_update_tick = 0;
02790
02791 }
02792
02793
02794 if(!(autopilot->astar_path) || (dllist_size(autopilot->astar_path) <= 0)) {
02795
02796 snprintf(error_buf, MBUF_SIZE,
02797 "Internal AI Error - Attempting to roam"
02798 " Astar path for AI #%d - but the path is not there",
02799 autopilot->mynum);
02800 SendAI(error_buf);
02801
02802 auto_destroy_astar_path(autopilot);
02803 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02804 return;
02805
02806 }
02807
02808
02809
02810
02811 temp_astar_node =
02812 (astar_node *) dllist_get_node(autopilot->astar_path, 1);
02813
02814 if(!(temp_astar_node)) {
02815
02816 snprintf(error_buf, MBUF_SIZE, "Internal AI Error - Attemping to roam"
02817 " Astar path for AI #%d - but the current astar node does not"
02818 " exist", autopilot->mynum);
02819 SendAI(error_buf);
02820
02821 auto_destroy_astar_path(autopilot);
02822 auto_goto_next_command(autopilot, AUTOPILOT_NC_DELAY);
02823 return;
02824
02825 }
02826
02827
02828 if((MechX(mech) == temp_astar_node->x) &&
02829 (MechY(mech) == temp_astar_node->y)) {
02830
02831
02832 if(dllist_size(autopilot->astar_path) == 1) {
02833
02834
02835 ai_set_speed(mech, autopilot, 0);
02836
02837
02838 auto_destroy_astar_path(autopilot);
02839 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02840 AUTO_ROAM_TICK, 1);
02841 return;
02842
02843 } else {
02844
02845
02846 temp_astar_node =
02847 (astar_node *) dllist_remove_node_at_pos(autopilot->
02848 astar_path, 1);
02849 free(temp_astar_node);
02850
02851
02852 autopilot->roam_update_tick++;
02853
02854
02855 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02856 AUTO_ROAM_TICK, 0);
02857 return;
02858
02859 }
02860
02861 }
02862
02863
02864
02865 tx = temp_astar_node->x;
02866 ty = temp_astar_node->y;
02867
02868
02869 figure_out_range_and_bearing(mech, tx, ty, &range, &bearing);
02870 speed_up_if_neccessary(autopilot, mech, tx, ty, bearing);
02871 slow_down_if_neccessary(autopilot, mech, range, bearing, tx, ty);
02872 update_wanted_heading(autopilot, mech, bearing);
02873
02874
02875 autopilot->roam_update_tick++;
02876
02877
02878 AUTOEVENT(autopilot, EVENT_AUTO_ROAM, auto_astar_roam_event,
02879 AUTO_ROAM_TICK, 0);
02880 }