00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00027 #include "mech.h"
00028 #include "mech.events.h"
00029 #include "autopilot.h"
00030 #include "failures.h"
00031 #include "mech.sensor.h"
00032 #include "p.autogun.h"
00033 #include "p.bsuit.h"
00034 #include "p.glue.h"
00035 #include "p.mech.sensor.h"
00036 #include "p.mech.utils.h"
00037 #include "p.mech.physical.h"
00038 #include "p.mech.combat.h"
00039 #include "p.mech.advanced.h"
00040 #include "p.mech.bth.h"
00041
00042 #if 0
00043 static char *my2string(const char *old)
00044 {
00045 static char new[64];
00046
00047 strncpy(new, old, 63);
00048 new[63] = '\0';
00049 return new;
00050 }
00051 #endif
00052
00053
00054 int SearchLightInRange(MECH * mech, MAP * map)
00055 {
00056
00057 MECH *target;
00058 int i;
00059
00060
00061 if(!mech || !map)
00062 return 0;
00063
00064
00065 for(i = 0; i < map->first_free; i++) {
00066
00067
00068 if(!(target = FindObjectsData(map->mechsOnMap[i])))
00069 continue;
00070
00071
00072 if(!(MechSpecials(target) & SLITE_TECH)
00073 || MechCritStatus(mech) & SLITE_DEST)
00074 continue;
00075
00076
00077 if(FaMechRange(target, mech) < LITE_RANGE) {
00078
00079
00080 if((MechStatus(target) & SLITE_ON) &&
00081 InWeaponArc(target, MechFX(mech), MechFY(mech)) & FORWARDARC) {
00082
00083
00084 if(!
00085 (map->
00086 LOSinfo[target->mapnumber][mech->
00087 mapnumber] &
00088 MECHLOSFLAG_BLOCK))
00089
00090
00091 return 3;
00092 else
00093
00094 return 4;
00095
00096 } else if(!MechStatus(target) & SLITE_ON &&
00097 InWeaponArc(target, MechFX(mech),
00098 MechFY(mech)) & FORWARDARC) {
00099
00100 if(!
00101 (map->
00102 LOSinfo[target->mapnumber][mech->
00103 mapnumber] &
00104 MECHLOSFLAG_BLOCK))
00105
00106
00107 return 5;
00108
00109 else
00110
00111 return 6;
00112 }
00113
00114
00115
00116 return (MechStatus(target) & SLITE_ON ? 1 : 2);
00117 }
00118
00119 }
00120 return 0;
00121 }
00122
00123
00124 int PrefVisSens(MECH * mech, MAP * map, int slite, MECH * target)
00125 {
00126
00127
00128 if(!mech || !map)
00129 return SENSOR_VIS;
00130
00131
00132 if(MechStatus(mech) & SLITE_ON || MechCritStatus(mech) & SLITE_LIT)
00133 return SENSOR_VIS;
00134
00135
00136 if(target && MechCritStatus(target) & SLITE_LIT)
00137 return SENSOR_VIS;
00138
00139
00140 if(map->maplight <= 1 && slite != 3 && slite != 5)
00141 return SENSOR_LA;
00142
00143
00144 return SENSOR_VIS;
00145 }
00146
00147
00148
00149
00150
00152 void auto_sensor_event(AUTO *autopilot)
00153 {
00154 MECH *target = NULL;
00155 MAP *map;
00156 char buf[16];
00157 int wanted_s[2];
00158 int rvis;
00159 int slite, prefvis;
00160 float trng;
00161 int set = 0;
00162
00163 if((autopilot->mymechnum > mudstate.db_top) || (autopilot->mymechnum < 0 )) {
00164 dprintk("mymechnum is bad!");
00165 return;
00166 }
00167 if((autopilot->mynum > mudstate.db_top) || (autopilot->mynum < 0 )) {
00168 dprintk("mynum is bad!");
00169 return;
00170 }
00171
00172
00173 MECH *mech = (MECH *) autopilot->mymech;
00174
00175
00176
00177
00178 if(!mech) {
00179 dprintk("mech is bad!");
00180 return;
00181 }
00182 if(!autopilot) {
00183 dprintk("ai is bad!");
00184 return;
00185 }
00186
00187 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
00188 return;
00189
00190
00191 if(Destroyed(mech)) {
00192 DoStopGun(autopilot);
00193 return;
00194 }
00195
00196
00197 if(!Started(mech)) {
00198 Zombify(autopilot);
00199 return;
00200 }
00201
00202
00203
00204 if(autopilot->flags & AUTOPILOT_LSENS)
00205 return;
00206
00207
00208 if(!(map = getMap(mech->mapindex))) {
00209
00210
00211 Zombify(autopilot);
00212 return;
00213 }
00214
00215
00216 if(MechTarget(mech) > 0)
00217 target = getMech(MechTarget(mech));
00218
00219
00220
00221 slite = (map->mapvis != 2 ? SearchLightInRange(mech, map) : 0);
00222 rvis = (map->maplight ? (map->mapvis) : (map->mapvis * (slite ? 1 : 3)));
00223 prefvis = PrefVisSens(mech, map, slite, target);
00224
00225
00226 if(target) {
00227
00228
00229 trng = FaMechRange(mech, target);
00230
00231
00232
00233 if(!set && HeatFactor(target) > 35 && (int) trng < 15) {
00234
00235
00236
00237 }
00238
00239
00240 if(!set && MechTons(target) >= 60 && (int) trng <= 20) {
00241 wanted_s[0] = SENSOR_EM;
00242 wanted_s[1] = SENSOR_IR;
00243 set++;
00244 }
00245
00246
00247 if(!set && !Landed(target) && FlyingT(target)) {
00248 wanted_s[0] = SENSOR_RA;
00249 wanted_s[1] = prefvis;
00250 set++;
00251 }
00252
00253
00254 if(!set && (int) trng <= 4 && MechSpecials(mech) & BEAGLE_PROBE_TECH
00255 && !(MechCritStatus(mech) & BEAGLE_DESTROYED)) {
00256 wanted_s[0] = SENSOR_BAP;
00257 wanted_s[1] = SENSOR_BAP;
00258 set++;
00259 }
00260
00261
00262 if(!set && (int) trng <= 8
00263 && MechSpecials2(mech) & BLOODHOUND_PROBE_TECH
00264 && !(MechCritStatus(mech) & BLOODHOUND_DESTROYED)) {
00265 wanted_s[0] = SENSOR_BHAP;
00266 wanted_s[1] = SENSOR_BHAP;
00267 set++;
00268 }
00269
00270
00271 if(!set) {
00272 wanted_s[0] = prefvis;
00273 wanted_s[1] = (rvis <= 15 ? SENSOR_EM : prefvis);
00274 set++;
00275 }
00276
00277 }
00278
00279
00280 if(!set) {
00281 if(rvis <= 15) {
00282
00283 wanted_s[0] = SENSOR_EM;
00284 wanted_s[1] = SENSOR_IR;
00285 } else {
00286
00287 wanted_s[0] = prefvis;
00288 wanted_s[1] = prefvis;
00289 }
00290 }
00291
00292
00293 if(wanted_s[0] >= SENSOR_VIS && wanted_s[0] <= SENSOR_BHAP &&
00294 wanted_s[1] >= SENSOR_VIS && wanted_s[1] <= SENSOR_BHAP &&
00295 (MechSensor(mech)[0] != wanted_s[0]
00296 || MechSensor(mech)[1] != wanted_s[1])) {
00297
00298 wanted_s[0] = BOUNDED(SENSOR_VIS, wanted_s[0], SENSOR_BHAP);
00299 wanted_s[1] = BOUNDED(SENSOR_VIS, wanted_s[1], SENSOR_BHAP);
00300
00301 MechSensor(mech)[0] = wanted_s[0];
00302 MechSensor(mech)[1] = wanted_s[1];
00303 mech_notify(mech, MECHALL, "As your sensors change, your lock clears.");
00304 MechTarget(mech) = -1;
00305 MarkForLOSUpdate(mech);
00306 }
00307 }
00308
00309
00310
00311
00312 weapon_node *auto_create_weapon_node(short weapon_number,
00313 short weapon_db_number, short section,
00314 short critical)
00315 {
00316
00317 weapon_node *temp;
00318
00319 temp = malloc(sizeof(weapon_node));
00320
00321 if(temp == NULL) {
00322 return NULL;
00323 }
00324
00325 memset(temp, 0, sizeof(weapon_node));
00326
00327 temp->weapon_number = weapon_number;
00328 temp->weapon_db_number = weapon_db_number;
00329 temp->section = section;
00330 temp->critical = critical;
00331
00332 return temp;
00333
00334 }
00335
00336
00337
00338
00339 void auto_destroy_weapon_node(weapon_node * victim)
00340 {
00341
00342 free(victim);
00343 return;
00344 }
00345
00346
00347
00348
00349 target_node *auto_create_target_node(int target_score, dbref target_dbref)
00350 {
00351
00352 target_node *temp;
00353
00354 temp = malloc(sizeof(target_node));
00355
00356 if(temp == NULL) {
00357 return NULL;
00358 }
00359
00360 memset(temp, 0, sizeof(target_node));
00361
00362 temp->target_score = target_score;
00363 temp->target_dbref = target_dbref;
00364
00365 return temp;
00366
00367 }
00368
00369
00370
00371
00372 void auto_destroy_target_node(target_node * victim)
00373 {
00374
00375 free(victim);
00376 return;
00377
00378 }
00379
00380
00381
00382
00383 void auto_destroy_weaplist(AUTO * autopilot)
00384 {
00385
00386 weapon_node *temp_weapon_node;
00387
00388
00389 if(!(autopilot->weaplist))
00390 return;
00391
00392
00393 if(dllist_size(autopilot->weaplist) > 0) {
00394
00395 while (dllist_size(autopilot->weaplist)) {
00396 temp_weapon_node =
00397 (weapon_node *) dllist_remove_node_at_pos(autopilot->weaplist,
00398 1);
00399 auto_destroy_weapon_node(temp_weapon_node);
00400 }
00401
00402 }
00403
00404
00405 dllist_destroy_list(autopilot->weaplist);
00406 autopilot->weaplist = NULL;
00407
00408 }
00409
00410
00411
00412
00413 static int auto_targets_callback(void *key, void *data, int depth, void *arg)
00414 {
00415
00416 target_node *temp;
00417
00418 temp = (target_node *) data;
00419 auto_destroy_target_node(temp);
00420
00421 return 1;
00422
00423 }
00424
00425
00426
00427
00428 static int auto_generic_compare(void *a, void *b, void *token)
00429 {
00430
00431 int *one, *two;
00432
00433 one = (int *) a;
00434 two = (int *) b;
00435
00436 return (*one - *two);
00437 }
00438
00439
00440
00441
00442 int auto_calc_weapon_score(int weapon_db_number, int range)
00443 {
00444
00445 int weapon_score;
00446 int range_score;
00447 int damage_score;
00448 int heat_score;
00449 int minrange_score;
00450
00451 int weapon_damage;
00452 int weapon_heat;
00453
00454 int i;
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 weapon_score = 0;
00465 weapon_damage = 0;
00466 range_score = 500;
00467 damage_score = 0;
00468 heat_score = 0;
00469 minrange_score = 0;
00470
00471
00472 if(range >= MechWeapons[weapon_db_number].longrange) {
00473 return weapon_score;
00474 }
00475
00476
00477 if(range >= MechWeapons[weapon_db_number].medrange) {
00478 range_score = 215;
00479 }
00480
00481
00482 if(range >= MechWeapons[weapon_db_number].shortrange &&
00483 range < MechWeapons[weapon_db_number].medrange) {
00484 range_score = 390;
00485 }
00486
00487
00488
00489
00490
00491 if(range < MechWeapons[weapon_db_number].min) {
00492 minrange_score =
00493 -12.5 * (float) ((MechWeapons[weapon_db_number].min - range) *
00494 (MechWeapons[weapon_db_number].min - range)) -
00495 25.0 * (float) (MechWeapons[weapon_db_number].min - range);
00496 }
00497
00498
00499 if(IsMissile(weapon_db_number)) {
00500
00501
00502
00503
00504
00505
00506
00507 for(i = 0; MissileHitTable[i].key != -1; i++) {
00508 if(MissileHitTable[i].key == weapon_db_number) {
00509 weapon_damage = MissileHitTable[i].num_missiles[5] *
00510 MechWeapons[weapon_db_number].damage;
00511 break;
00512 }
00513 }
00514
00515 } else {
00516 weapon_damage = MechWeapons[weapon_db_number].damage;
00517 }
00518
00519
00520
00521 damage_score = 50 * weapon_damage;
00522
00523
00524 weapon_heat = MechWeapons[weapon_db_number].heat;
00525
00526
00527
00528 heat_score = -25 * weapon_heat + 250;
00529
00530
00531 weapon_score = range_score + damage_score + heat_score + minrange_score;
00532
00533 return weapon_score;
00534
00535 }
00536
00537
00538
00539
00540
00541
00542 void auto_update_profile_event(AUTO *autopilot) {
00543 MECH *mech = (MECH *) autopilot->mymech;
00544
00545 weapon_node *temp_weapon_node;
00546 dllist_node *temp_dllist_node;
00547
00548 int section;
00549 int weapon_count_section;
00550 unsigned char weaparray[MAX_WEAPS_SECTION];
00551 unsigned char weapdata[MAX_WEAPS_SECTION];
00552 int critical[MAX_WEAPS_SECTION];
00553
00554 int range;
00555
00556 int weapon_count;
00557 int weapon_number;
00558
00559
00560
00561
00562 if((autopilot->mymechnum > mudstate.db_top) || (autopilot->mymechnum < 1 )) {
00563
00564
00565
00566 dprintk("ap mymechnum is bad");
00567 StopGun(autopilot);
00568 return;
00569 }
00570
00571 if(!mech) {
00572 dprintk("mech is bad!");
00573 return;
00574 }
00575 if(!autopilot) {
00576 dprintk("ai is bad!");
00577 return;
00578 }
00579 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
00580 return;
00581
00582
00583 if(Destroyed(mech)) {
00584 return;
00585 }
00586
00587
00588 print_autogun_log(autopilot, "Profiling Unit #%d", mech->mynum);
00589
00590
00591
00592
00593
00594
00595 for(range = 0; range < AUTO_PROFILE_MAX_SIZE; range++) {
00596
00597 if(autopilot->profile[range]) {
00598
00599
00600 rb_destroy(autopilot->profile[range]);
00601 }
00602 autopilot->profile[range] = NULL;
00603 }
00604
00605
00606 if(autopilot->weaplist != NULL) {
00607
00608
00609 auto_destroy_weaplist(autopilot);
00610 }
00611
00612
00613 autopilot->weaplist = dllist_create_list();
00614
00615
00616 autopilot->mech_max_range = 0;
00617
00618
00619 weapon_count = -1;
00620
00621
00622 for(section = 0; section < NUM_SECTIONS; section++) {
00623
00624
00625 weapon_count_section = FindWeapons(mech, section,
00626 weaparray, weapdata, critical);
00627
00628
00629 if(weapon_count_section <= 0)
00630 continue;
00631
00632
00633 for(weapon_number = 0; weapon_number < weapon_count_section;
00634 weapon_number++) {
00635
00636
00637
00638
00639 weapon_count++;
00640
00641 if(IsAMS(weaparray[weapon_number]))
00642 continue;
00643
00644
00645 if(WeaponIsNonfunctional(mech, section, critical[weapon_number],
00646 GetWeaponCrits(mech,
00647 Weapon2I(weaparray
00648 [weapon_number])))
00649 > 0)
00650 continue;
00651
00652
00653 temp_weapon_node = auto_create_weapon_node(weapon_count,
00654 weaparray
00655 [weapon_number],
00656 section,
00657 critical
00658 [weapon_number]);
00659
00660 temp_dllist_node = dllist_create_node(temp_weapon_node);
00661 dllist_insert_end(autopilot->weaplist, temp_dllist_node);
00662
00663
00664 if(autopilot->mech_max_range <
00665 MechWeapons[weaparray[weapon_number]].longrange) {
00666 autopilot->mech_max_range =
00667 MechWeapons[weaparray[weapon_number]].longrange;
00668 }
00669
00670 }
00671
00672 }
00673
00674
00675
00676
00677
00678
00679
00680 weapon_number = 1;
00681
00682 while (weapon_number <= dllist_size(autopilot->weaplist)) {
00683
00684
00685 temp_weapon_node =
00686 (weapon_node *) dllist_get_node(autopilot->weaplist,
00687 weapon_number);
00688
00689 for(range = 0; range <
00690 MechWeapons[temp_weapon_node->weapon_db_number].longrange;
00691 range++) {
00692
00693
00694 if(range >= AUTO_PROFILE_MAX_SIZE) {
00695 break;
00696 }
00697
00698
00699 temp_weapon_node->range_scores[range] =
00700 auto_calc_weapon_score(temp_weapon_node->weapon_db_number,
00701 range);
00702
00703
00704 if(autopilot->profile[range] == NULL) {
00705 autopilot->profile[range] =
00706 rb_init(&auto_generic_compare, NULL);
00707 }
00708
00709
00710
00711
00712 while (1) {
00713
00714 if(rb_exists(autopilot->profile[range],
00715 &temp_weapon_node->range_scores[range])) {
00716 temp_weapon_node->range_scores[range]++;
00717 } else {
00718 break;
00719 }
00720
00721 }
00722
00723
00724 rb_insert(autopilot->profile[range],
00725 &temp_weapon_node->range_scores[range],
00726 temp_weapon_node);
00727
00728 }
00729
00730
00731 weapon_number++;
00732
00733 }
00734
00735
00736 print_autogun_log(autopilot, "Finished Profiling");
00737
00738 }
00739
00740
00741
00742
00743
00744 int auto_calc_target_score(AUTO * autopilot, MECH * mech, MECH * target,
00745 MAP * map)
00746 {
00747
00748 int target_score;
00749 float range;
00750 float target_speed;
00751 int target_bv;
00752
00753 int total_armor_current;
00754 int total_armor_original;
00755 int total_internal_current;
00756 int total_internal_original;
00757
00758 int section;
00759
00760 float damage_score;
00761 float bv_score;
00762 float speed_score;
00763 float range_score;
00764 float status_score;
00765
00766
00767 target_score = 0;
00768
00769 total_armor_current = 0;
00770 total_armor_original = 0;
00771 total_internal_current = 0;
00772 total_internal_original = 0;
00773
00774 damage_score = 0.0;
00775 bv_score = 0.0;
00776 speed_score = 0.0;
00777 range_score = 0.0;
00778 status_score = 0.0;
00779
00780
00781
00782
00783
00784
00785
00786
00787 if(Destroyed(target))
00788 return target_score;
00789
00790
00791 if(MechStatus(target) & COMBAT_SAFE)
00792 return target_score;
00793
00794
00795 if(MechTeam(target) == MechTeam(mech))
00796 return target_score;
00797
00798
00799
00800
00801
00802
00803 range = FindHexRange(MechFX(mech), MechFY(mech), MechFX(target),
00804 MechFY(target));
00805
00806
00807 if((range >= (float) AUTO_GUN_MAX_RANGE)) {
00808 return target_score;
00809 }
00810
00811
00812
00813 range_score = -10.0 * range + 300.0;
00814
00815
00816 target_speed = MechSpeed(target);
00817
00818
00819
00820
00822 speed_score = -2.0 * target_speed + 300.0;
00823
00824
00825 target_bv = MechBV(target);
00826
00827
00828
00829
00830 bv_score = 0.05 * ((float) target_bv);
00831
00832
00833
00834 for(section = 0; section < NUM_SECTIONS; section++) {
00835
00836
00837 total_armor_current += GetSectArmor(target, section) +
00838 GetSectRArmor(target, section);
00839 total_armor_original += GetSectOArmor(target, section) +
00840 GetSectORArmor(target, section);
00841
00842
00843 total_internal_current += GetSectInt(target, section);
00844 total_internal_original += GetSectOInt(target, section);
00845
00846 }
00847
00848
00849
00850
00851
00852
00853
00854 if(total_internal_original == 0 && total_armor_original == 0) {
00855
00856
00857 return target_score;
00858
00859 } else if(total_internal_original == 0) {
00860
00861
00862 damage_score = -3.0 * ((float) total_armor_current /
00863 (float) total_armor_original) + 300.0;
00864
00865 } else if(total_armor_original == 0) {
00866
00867
00868 damage_score = -2.0 * ((float) total_internal_current /
00869 (float) total_internal_original) + 200.0;
00870
00871 } else {
00872
00873
00874 damage_score = -3.0 * ((float) total_armor_current /
00875 (float) total_armor_original) + 300.0
00876 - 2.0 * ((float) total_internal_current /
00877 (float) total_internal_original) + 200.0;
00878
00879 }
00880
00881
00882 if(!Started(target))
00883 status_score += 100.0;
00884
00885 if(Uncon(target))
00886 status_score += 100.0;
00887
00888 if(MechToMech_LOSFlag(map, mech, target) & MECHLOSFLAG_SEEN)
00889 status_score += 500.0;
00890
00891
00892 target_score = (int) floor(range_score + speed_score + bv_score +
00893 damage_score + status_score);
00894
00895 return target_score;
00896
00897 }
00898
00899
00900
00901
00902
00903
00904
00905 void auto_gun_event(AUTO *autopilot)
00906 {
00907 MECH *mech = (MECH *) autopilot->mymech;
00908 MAP *map;
00909 MECH *target;
00910 MECH *physical_target;
00911 rbtree targets;
00912 target_node *temp_target_node;
00913 weapon_node *temp_weapon_node;
00914
00915 char buffer[LBUF_SIZE];
00916
00917 int target_score;
00918 int threshold_score;
00919
00920
00921 int elevation_diff;
00922
00923 int what_arc;
00924 int new_arc;
00925
00926 int relative_bearing;
00927
00928 int is_section_destroyed[4];
00929
00930 int section_hasbusyweap[4];
00931
00932 int rleg_bth, lleg_bth;
00933
00934 int is_rarm_ready, is_larm_ready;
00935
00936
00937
00938 int accumulate_heat;
00939 int i, j;
00940
00941 float range;
00942 float maxspeed;
00943
00944
00945 short x, y;
00946 float fx, fy;
00947 char do_chasetarget;
00948
00949
00950
00951 if(!mech || !autopilot)
00952 return;
00953
00954 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum))
00955 return;
00956
00957
00958 if(Destroyed(mech)) {
00959 DoStopGun(autopilot);
00960 return;
00961 }
00962
00964 if(!Started(mech)) {
00965 Zombify(autopilot);
00966 return;
00967 }
00968
00969
00970 if(!(map = getMap(mech->mapindex))) {
00971 Zombify(autopilot);
00972 return;
00973 }
00974
00975
00976 print_autogun_log(autopilot, "Autogun Event Started");
00977
00978
00979 if(autopilot->weaplist == NULL) {
00980 print_autogun_log(autopilot, "Autogun Event Finished");
00981 return;
00982 }
00983
00984
00985 if(OODing(mech)) {
00986
00987 print_autogun_log(autopilot, "Autogun Event Finished");
00988 return;
00989 }
00990
00991
00992 if(autopilot->target > -1) {
00993
00994 if(!(target = getMech(autopilot->target))) {
00995
00996
00997 autopilot->target = -1;
00998 autopilot->target_score = 0;
00999
01000 } else if(Destroyed(target) || (target->mapindex != mech->mapindex)) {
01001
01002
01003 autopilot->target = -1;
01004 autopilot->target_score = 0;
01005
01006 } else {
01007
01008
01009
01010
01011
01012 range = FindHexRange(MechFX(mech), MechFY(mech),
01013 MechFX(target), MechFY(target));
01014
01015 if((range >= (float) AUTO_GUN_MAX_RANGE) &&
01016 !AssignedTarget(autopilot)) {
01017
01018
01019 autopilot->target = -1;
01020 autopilot->target_score = 0;
01021
01022 }
01023
01024 }
01025
01026 }
01027
01028
01029 if(AssignedTarget(autopilot) && autopilot->target == -1) {
01030
01031
01032 UnassignTarget(autopilot);
01033
01035 }
01036
01037
01038 if(autopilot->target == -1 ||
01039 (autopilot->target_update_tick >= AUTO_GUN_UPDATE_TICK &&
01040 !AssignedTarget(autopilot))) {
01041
01042
01043
01044
01045 print_autogun_log(autopilot, "Autogun - Looking for new target");
01046
01047
01048 autopilot->target_update_tick = 0;
01049
01050
01051 targets = rb_init(&auto_generic_compare, NULL);
01052
01053
01054 for(i = 0; i < map->first_free; i++) {
01055
01056
01057 if(i != mech->mapnumber && (j = map->mechsOnMap[i]) > 0) {
01058
01059
01060 if(!(target = getMech(j)))
01061 continue;
01062
01063
01064 target_score =
01065 auto_calc_target_score(autopilot, mech, target, map);
01066
01067
01068 print_autogun_log(autopilot,
01069 "Autogun - Possible target #%d with score %d",
01070 target->mynum, target_score);
01071
01072
01073 if(target_score > 0) {
01074
01075
01076 temp_target_node = auto_create_target_node(target_score,
01077 target->mynum);
01078
01081
01082
01083 while (1) {
01084
01085 if(rb_exists
01086 (targets, &temp_target_node->target_score)) {
01087 temp_target_node->target_score++;
01088 } else {
01089 break;
01090 }
01091
01092 }
01093
01094
01095 rb_insert(targets, &temp_target_node->target_score,
01096 temp_target_node);
01097
01098 }
01099
01100
01101 if(autopilot->target == target->mynum) {
01102
01103
01104 autopilot->target_score = target_score;
01105
01106 }
01107
01108 }
01109
01110 }
01111
01112
01113
01114
01115 if(!(rb_size(targets) > 0)) {
01116
01117
01120 autopilot->target = -1;
01121 autopilot->target_score = 0;
01122 autopilot->target_update_tick = 0;
01123
01124
01125 rb_walk(targets, WALK_INORDER, &auto_targets_callback, NULL);
01126 rb_destroy(targets);
01127
01128
01129 print_autogun_log(autopilot, "Autogun in idle mode");
01130 print_autogun_log(autopilot, "Autogun Event Finished");
01131 return;
01132 }
01133
01134
01135
01136
01137
01138
01139 temp_target_node =
01140 (target_node *) rb_search(targets, SEARCH_LAST, NULL);
01141
01142
01143 print_autogun_log(autopilot,
01144 "Autogun - Best target #%d with score %d",
01145 temp_target_node->target_dbref,
01146 temp_target_node->target_score);
01147 print_autogun_log(autopilot,
01148 "Autogun - Current target #%d with score %d",
01149 autopilot->target, autopilot->target_score);
01150
01151 if(autopilot->target > -1 && autopilot->target_score > 0) {
01152
01153
01154 if(autopilot->target != temp_target_node->target_dbref) {
01155
01156
01157 threshold_score =
01158 ((100.0 +
01159 (float) autopilot->target_threshold) / 100.0) *
01160 autopilot->target_score;
01161
01162 if(temp_target_node->target_score > threshold_score) {
01163
01164
01165 autopilot->target = temp_target_node->target_dbref;
01166 autopilot->target_score = temp_target_node->target_score;
01167
01168 print_autogun_log(autopilot, "Switching Target to #%d",
01169 autopilot->target);
01170
01171 }
01172
01173
01174
01175 }
01176
01177
01178
01179 } else {
01180
01181
01182 autopilot->target = temp_target_node->target_dbref;
01183 autopilot->target_score = temp_target_node->target_score;
01184
01185 }
01186
01187
01188 rb_walk(targets, WALK_INORDER, &auto_targets_callback, NULL);
01189 rb_destroy(targets);
01190
01191 } else {
01192
01193
01194 autopilot->target_update_tick++;
01195
01196 }
01197
01198
01199
01200
01201 print_autogun_log(autopilot, "Autogun - Current target #%d with score %d",
01202 autopilot->target, autopilot->target_score);
01203
01204
01205 if(!(target = getMech(autopilot->target))) {
01206
01207
01208
01209
01210
01211 autopilot->target = -1;
01212 autopilot->target_score = 0;
01213
01214
01215 print_autogun_log(autopilot, "Autogun - No valid current targets");
01216 print_autogun_log(autopilot, "Autogun Event Finished");
01217 return;
01218
01219 }
01220
01221
01222 if(MechTarget(mech) != autopilot->target) {
01223
01224
01225 snprintf(buffer, LBUF_SIZE, "%c%c", MechID(target)[0],
01226 MechID(target)[1]);
01227 mech_settarget(autopilot->mynum, mech, buffer);
01228
01229
01230 print_autogun_log(autopilot, "Autogun - Locking target #%d",
01231 autopilot->target);
01232
01233 }
01234
01235
01236
01237
01238
01239
01240 print_autogun_log(autopilot, "Autogun - Start Physical Attack Stage");
01241
01242
01243 range =
01244 FindHexRange(MechFX(mech), MechFY(mech), MechFX(target),
01245 MechFY(target));
01246
01247
01248
01249
01250
01252 if(range < 1.0) {
01253
01254
01255 physical_target = target;
01256
01257 } else if(range > AUTO_GUN_PHYSICAL_RANGE_MIN) {
01258
01259
01260
01261 physical_target = NULL;
01262
01263
01264 for(i = 0; i < map->first_free; i++) {
01265
01266
01267 if(i != mech->mapnumber && (j = map->mechsOnMap[i]) > 0) {
01268
01269
01270 if(!(target = getMech(j)))
01271 continue;
01272
01273 if(Destroyed(target))
01274 continue;
01275
01276 if(MechStatus(target) & COMBAT_SAFE)
01277 continue;
01278
01279 if(MechTeam(target) == MechTeam(mech))
01280 continue;
01281
01282
01283 range = FindHexRange(MechFX(mech), MechFY(mech),
01284 MechFX(target), MechFY(target));
01285
01286
01287 if(range < 1.0) {
01288 physical_target = target;
01289 break;
01290 }
01291
01292 }
01293
01294 }
01295
01296 } else {
01297
01298
01299 physical_target = NULL;
01300
01301 }
01302
01303
01304 if(physical_target &&
01305 (MechToMech_LOSFlag(map, mech, physical_target) & MECHLOSFLAG_SEEN)) {
01306
01307
01308 print_autogun_log(autopilot,
01309 "Autogun - Attempting physical attack against"
01310 " target #%d", physical_target->mynum);
01311
01312
01313 elevation_diff = MechZ(mech) - MechZ(target);
01314
01315
01316 if((MechType(mech) == CLASS_MECH) && (MechMove(mech) == MOVE_BIPED)) {
01317
01318
01319 MechStatus(mech) &= ~(TORSO_RIGHT | TORSO_LEFT);
01320
01321 if(MechSpecials(mech) & FLIPABLE_ARMS) {
01322
01323
01324 MechStatus(mech) &= ~(FLIPPED_ARMS);
01325 }
01326
01327
01328 what_arc =
01329 InWeaponArc(mech, MechFX(physical_target),
01330 MechFY(physical_target));
01331
01332
01333 if(what_arc & LSIDEARC) {
01334
01335
01336 MechStatus(mech) |= TORSO_LEFT;
01337
01338 } else if(what_arc & RSIDEARC) {
01339
01340
01341 MechStatus(mech) |= TORSO_RIGHT;
01342
01343 } else if(what_arc & REARARC) {
01344
01345
01346
01347 relative_bearing =
01348 MechFacing(mech) - FindBearing(MechFX(mech), MechFY(mech),
01349 MechFX(physical_target),
01350 MechFY(physical_target));
01351
01352 if(relative_bearing > 120 && relative_bearing < 180) {
01353
01354
01355 MechStatus(mech) |= TORSO_RIGHT;
01356
01357 } else if(relative_bearing > 180 && relative_bearing < 240) {
01358
01359
01360 MechStatus(mech) |= TORSO_LEFT;
01361
01362 }
01363
01364
01365
01366 }
01367
01368
01369 new_arc =
01370 InWeaponArc(mech, MechFX(physical_target),
01371 MechFY(physical_target));
01372
01373
01374 memset(is_section_destroyed, 0, sizeof(is_section_destroyed));
01375 is_section_destroyed[0] = SectIsDestroyed(mech, RARM);
01376 is_section_destroyed[1] = SectIsDestroyed(mech, LARM);
01377 is_section_destroyed[2] = SectIsDestroyed(mech, RLEG);
01378 is_section_destroyed[3] = SectIsDestroyed(mech, LLEG);
01379
01380
01381 memset(section_hasbusyweap, 0, sizeof(section_hasbusyweap));
01382 section_hasbusyweap[0] = SectHasBusyWeap(mech, RARM);
01383 section_hasbusyweap[1] = SectHasBusyWeap(mech, LARM);
01384 section_hasbusyweap[2] = SectHasBusyWeap(mech, RLEG);
01385 section_hasbusyweap[3] = SectHasBusyWeap(mech, LLEG);
01386
01387
01388
01389
01390 if(!is_section_destroyed[0] && !section_hasbusyweap[0] &&
01391 !AnyLimbsRecycling(mech) && ((new_arc & FORWARDARC) ||
01392 (new_arc & RSIDEARC)) &&
01393 (elevation_diff == 0 || elevation_diff == -1)) {
01394
01395 snprintf(buffer, LBUF_SIZE, "r %c%c",
01396 MechID(target)[0], MechID(target)[1]);
01397
01398 if(have_axe(mech, RARM))
01399 mech_axe(autopilot->mynum, mech, buffer);
01400
01402 else if(have_sword(mech, RARM))
01403 mech_sword(autopilot->mynum, mech, buffer);
01404
01405 }
01406
01407
01408 if(!is_section_destroyed[1] && !section_hasbusyweap[1] &&
01409 !AnyLimbsRecycling(mech) && ((new_arc & FORWARDARC) ||
01410 (new_arc & LSIDEARC)) &&
01411 (elevation_diff == 0 || elevation_diff == -1)) {
01412
01413 snprintf(buffer, LBUF_SIZE, "l %c%c",
01414 MechID(target)[0], MechID(target)[1]);
01415
01416 if(have_axe(mech, LARM))
01417 mech_axe(autopilot->mynum, mech, buffer);
01418
01420 else if(have_sword(mech, LARM))
01421 mech_sword(autopilot->mynum, mech, buffer);
01422
01423 }
01424
01425
01426
01427
01428 if((!section_hasbusyweap[2] || !section_hasbusyweap[3]) &&
01429 !is_section_destroyed[2] && !is_section_destroyed[3] &&
01430 (what_arc & FORWARDARC) && !AnyLimbsRecycling(mech) &&
01431 (elevation_diff == 0 || elevation_diff == 1)) {
01432
01433 rleg_bth = 0;
01434 lleg_bth = 0;
01435
01436
01437 if(!section_hasbusyweap[2]) {
01438 if(!OkayCritSectS(RLEG, 0, SHOULDER_OR_HIP))
01439 rleg_bth += 3;
01440 if(!OkayCritSectS(RLEG, 1, UPPER_ACTUATOR))
01441 rleg_bth++;
01442 if(!OkayCritSectS(RLEG, 2, LOWER_ACTUATOR))
01443 rleg_bth++;
01444 if(!OkayCritSectS(RLEG, 3, HAND_OR_FOOT_ACTUATOR))
01445 rleg_bth++;
01446 } else {
01447 rleg_bth = 99;
01448 }
01449
01450
01451 if(!section_hasbusyweap[3]) {
01452 if(!OkayCritSectS(LLEG, 0, SHOULDER_OR_HIP))
01453 lleg_bth += 3;
01454 if(!OkayCritSectS(LLEG, 1, UPPER_ACTUATOR))
01455 lleg_bth++;
01456 if(!OkayCritSectS(LLEG, 2, LOWER_ACTUATOR))
01457 lleg_bth++;
01458 if(!OkayCritSectS(LLEG, 3, HAND_OR_FOOT_ACTUATOR))
01459 lleg_bth++;
01460 } else {
01461 rleg_bth = 99;
01462 }
01463
01464
01465
01466 if(rleg_bth <= lleg_bth) {
01467 snprintf(buffer, LBUF_SIZE, "r %c%c",
01468 MechID(physical_target)[0],
01469 MechID(physical_target)[1]);
01470 } else {
01471 snprintf(buffer, LBUF_SIZE, "l %c%c",
01472 MechID(physical_target)[0],
01473 MechID(physical_target)[1]);
01474 }
01475 mech_kick(autopilot->mynum, mech, buffer);
01476 }
01477
01478
01479 if(((!is_section_destroyed[0] && !section_hasbusyweap[0]) ||
01480 (!is_section_destroyed[1] && !section_hasbusyweap[1]))
01481 && !AnyLimbsRecycling(mech) &&
01482 (elevation_diff == 0 || elevation_diff == -1)) {
01483
01484 is_rarm_ready = 0;
01485 is_larm_ready = 0;
01486
01487 if(!is_section_destroyed[0] &&
01488 !section_hasbusyweap[0] &&
01489 ((new_arc & FORWARDARC) || (new_arc & RSIDEARC))) {
01490
01491
01492 is_rarm_ready = 1;
01493 }
01494
01495 if(!is_section_destroyed[1] &&
01496 !section_hasbusyweap[1] &&
01497 ((new_arc & FORWARDARC) || (new_arc & LSIDEARC))) {
01498
01499
01500 is_larm_ready = 1;
01501 }
01502
01503 if(is_rarm_ready == 1 && is_larm_ready == 1) {
01504 snprintf(buffer, LBUF_SIZE, "b %c%c",
01505 MechID(target)[0], MechID(target)[1]);
01506 } else if(is_rarm_ready == 1) {
01507 snprintf(buffer, LBUF_SIZE, "r %c%c",
01508 MechID(target)[0], MechID(target)[1]);
01509 } else {
01510 snprintf(buffer, LBUF_SIZE, "l %c%c",
01511 MechID(target)[0], MechID(target)[1]);
01512 }
01513
01514
01515 mech_punch(autopilot->mynum, mech, buffer);
01516
01517 }
01518
01519 } else if((MechType(mech) == CLASS_MECH) &&
01520 (MechMove(mech) == MOVE_QUAD)) {
01521
01522
01523
01524
01525
01526
01527 what_arc =
01528 InWeaponArc(mech, MechFX(physical_target),
01529 MechFY(physical_target));
01530
01531
01532 memset(is_section_destroyed, 0, sizeof(is_section_destroyed));
01533 is_section_destroyed[0] = SectIsDestroyed(mech, RARM);
01534 is_section_destroyed[1] = SectIsDestroyed(mech, LARM);
01535 is_section_destroyed[2] = SectIsDestroyed(mech, RLEG);
01536 is_section_destroyed[3] = SectIsDestroyed(mech, LLEG);
01537
01538
01539 memset(section_hasbusyweap, 0, sizeof(section_hasbusyweap));
01540 section_hasbusyweap[0] = SectHasBusyWeap(mech, RARM);
01541 section_hasbusyweap[1] = SectHasBusyWeap(mech, LARM);
01542
01543
01544
01545
01546
01547
01548 if((!section_hasbusyweap[0] || !section_hasbusyweap[0]) &&
01549 !is_section_destroyed[0] && !is_section_destroyed[1] &&
01550 !is_section_destroyed[2] && !is_section_destroyed[3] &&
01551 (what_arc & FORWARDARC) && !AnyLimbsRecycling(mech) &&
01552 (elevation_diff == 0 || elevation_diff == 1)) {
01553
01554 rleg_bth = 0;
01555 lleg_bth = 0;
01556
01557
01558 if(!section_hasbusyweap[0]) {
01559 if(!OkayCritSectS(RARM, 0, SHOULDER_OR_HIP))
01560 rleg_bth += 3;
01561 if(!OkayCritSectS(RARM, 1, UPPER_ACTUATOR))
01562 rleg_bth++;
01563 if(!OkayCritSectS(RARM, 2, LOWER_ACTUATOR))
01564 rleg_bth++;
01565 if(!OkayCritSectS(RARM, 3, HAND_OR_FOOT_ACTUATOR))
01566 rleg_bth++;
01567 } else {
01568 rleg_bth = 99;
01569 }
01570
01571
01572 if(!section_hasbusyweap[1]) {
01573 if(!OkayCritSectS(LARM, 0, SHOULDER_OR_HIP))
01574 lleg_bth += 3;
01575 if(!OkayCritSectS(LARM, 1, UPPER_ACTUATOR))
01576 lleg_bth++;
01577 if(!OkayCritSectS(LARM, 2, LOWER_ACTUATOR))
01578 lleg_bth++;
01579 if(!OkayCritSectS(LARM, 3, HAND_OR_FOOT_ACTUATOR))
01580 lleg_bth++;
01581 } else {
01582 rleg_bth = 99;
01583 }
01584
01585
01586
01587 if(rleg_bth <= lleg_bth) {
01588 snprintf(buffer, LBUF_SIZE, "r %c%c",
01589 MechID(physical_target)[0],
01590 MechID(physical_target)[1]);
01591 } else {
01592 snprintf(buffer, LBUF_SIZE, "l %c%c",
01593 MechID(physical_target)[0],
01594 MechID(physical_target)[1]);
01595 }
01596 mech_kick(autopilot->mynum, mech, buffer);
01597 }
01598
01599 } else if(MechType(mech) == CLASS_BSUIT) {
01600
01601
01602
01603 } else {
01604
01605
01606
01607
01608 }
01609
01610 }
01611
01612
01613
01614 print_autogun_log(autopilot, "Autogun - End Physical Attack Stage");
01615
01616
01617
01618
01619
01620
01621 if(!(target = getMech(autopilot->target))) {
01622
01623
01624
01625
01626
01627 autopilot->target = -1;
01628 autopilot->target_score = 0;
01629
01630
01631 print_autogun_log(autopilot, "Autogun - No valid current target");
01632 print_autogun_log(autopilot, "Autogun Event Finished");
01633 return;
01634
01635 } else if(Destroyed(target) || (target->mapindex != mech->mapindex)) {
01636
01637
01638 autopilot->target = -1;
01639 autopilot->target_score = 0;
01640
01641
01642 print_autogun_log(autopilot, "Autogun - Target Gone");
01643 print_autogun_log(autopilot, "Autogun Event Finished");
01644 return;
01645 }
01646
01647
01648 print_autogun_log(autopilot, "Autogun - Starting Weapon Attack Phase");
01649
01650
01651 range = FindHexRange(MechFX(mech), MechFY(mech),
01652 MechFX(target), MechFY(target));
01653
01654
01655
01656
01657 if((range >= (float) AUTO_GUN_MAX_RANGE) && !AssignedTarget(autopilot)) {
01658
01659
01660 autopilot->target = -1;
01661 autopilot->target_score = 0;
01662
01663
01664
01665 print_autogun_log(autopilot, "Autogun - Target out of range");
01666 print_autogun_log(autopilot, "Autogun Event Finished");
01667 return;
01668 }
01669
01670
01671 if((range < (float) AUTO_GUN_MAX_RANGE)
01672 && autopilot->profile[(int) range]) {
01673
01674
01675
01676
01677 accumulate_heat = MechWeapHeat(mech);
01678
01679
01680 if((MechType(mech) == CLASS_MECH) && (fabs(MechSpeed(mech)) > 0.0)) {
01681
01682 maxspeed = MMaxSpeed(mech);
01683 if(IsRunning(MechDesiredSpeed(mech), maxspeed))
01684 accumulate_heat += 2;
01685 else
01686 accumulate_heat += 1;
01687 }
01688
01689
01690 temp_weapon_node =
01691 (weapon_node *) rb_search(autopilot->profile[(int) range],
01692 SEARCH_LAST, NULL);
01693
01694 while (temp_weapon_node) {
01695
01696
01697 if(WeaponIsNonfunctional(mech, temp_weapon_node->section,
01698 temp_weapon_node->critical,
01699 GetWeaponCrits(mech,
01700 Weapon2I
01701 (temp_weapon_node->
01702 weapon_db_number))) >
01703 0) {
01704
01705
01706 temp_weapon_node =
01707 (weapon_node *) rb_search(autopilot->profile[(int) range],
01708 SEARCH_PREV,
01709 &temp_weapon_node->
01710 range_scores[(int) range]);
01711
01712 continue;
01713 }
01714
01715
01716 if(WpnIsRecycling
01717 (mech, temp_weapon_node->section,
01718 temp_weapon_node->critical)) {
01719
01720
01721 temp_weapon_node =
01722 (weapon_node *) rb_search(autopilot->profile[(int) range],
01723 SEARCH_PREV,
01724 &temp_weapon_node->
01725 range_scores[(int) range]);
01726
01727 continue;
01728 }
01729
01730 if(IsAMS(temp_weapon_node->weapon_db_number)) {
01731
01732
01733 temp_weapon_node =
01734 (weapon_node *) rb_search(autopilot->profile[(int) range],
01735 SEARCH_PREV,
01736 &temp_weapon_node->
01737 range_scores[(int) range]);
01738 continue;
01739 }
01740
01741
01742
01744 if((MechType(mech) == CLASS_MECH) && (((float) accumulate_heat +
01745 (float)
01746 MechWeapons
01747 [temp_weapon_node->
01748 weapon_db_number].heat -
01749 (float)
01750 MechMinusHeat(mech)) >
01751 AUTO_GUN_MAX_HEAT)) {
01752
01753
01754 temp_weapon_node =
01755 (weapon_node *) rb_search(autopilot->profile[(int) range],
01756 SEARCH_PREV,
01757 &temp_weapon_node->
01758 range_scores[(int) range]);
01759
01760 continue;
01761 }
01762
01763
01764
01765
01766 if((MechType(mech) == CLASS_MECH) &&
01767 (MechMove(mech) == MOVE_BIPED)) {
01768
01769
01770 MechStatus(mech) &= ~(TORSO_RIGHT | TORSO_LEFT);
01771 if(MechSpecials(mech) & FLIPABLE_ARMS) {
01772
01773
01774 MechStatus(mech) &= ~(FLIPPED_ARMS);
01775 }
01776
01777
01778 what_arc = InWeaponArc(mech, MechFX(target), MechFY(target));
01779
01780
01781
01782 if(what_arc & REARARC) {
01783
01784 if(temp_weapon_node->section == LARM ||
01785 temp_weapon_node->section == RARM) {
01786
01787
01788 if(MechSpecials(mech) & FLIPABLE_ARMS) {
01789
01790
01791 MechStatus(mech) |= FLIPPED_ARMS;
01792
01793 } else {
01794
01795
01796
01797
01798
01799 relative_bearing = MechFacing(mech) -
01800 FindBearing(MechFX(mech), MechFY(mech),
01801 MechFX(target), MechFY(target));
01802
01803 if(relative_bearing > 120
01804 && relative_bearing < 180
01805 && temp_weapon_node->section == RARM) {
01806
01807
01808 MechStatus(mech) |= TORSO_RIGHT;
01809
01810 } else if(relative_bearing > 180
01811 && relative_bearing < 240
01812 && temp_weapon_node->section == LARM) {
01813
01814
01815 MechStatus(mech) |= TORSO_LEFT;
01816
01817 } else {
01818
01819
01820 temp_weapon_node =
01821 (weapon_node *) rb_search(autopilot->
01822 profile[(int)
01823 range],
01824 SEARCH_PREV,
01825 &temp_weapon_node->
01826 range_scores[(int) range]);
01827
01828 continue;
01829
01830 }
01831
01832 }
01833
01834 } else
01835 if(!
01836 (GetPartFireMode
01837 (mech, temp_weapon_node->section,
01838 temp_weapon_node->critical) & REAR_MOUNT)) {
01839
01840
01841
01842 temp_weapon_node =
01843 (weapon_node *) rb_search(autopilot->
01844 profile[(int) range],
01845 SEARCH_PREV,
01846 &temp_weapon_node->
01847 range_scores[(int)
01848 range]);
01849
01850 continue;
01851
01852 }
01853
01854
01855
01856
01857 } else if(what_arc & LSIDEARC) {
01858
01859 if(temp_weapon_node->section == RLEG ||
01860 temp_weapon_node->section == LLEG) {
01861
01862
01863
01864 temp_weapon_node =
01865 (weapon_node *) rb_search(autopilot->
01866 profile[(int) range],
01867 SEARCH_PREV,
01868 &temp_weapon_node->
01869 range_scores[(int)
01870 range]);
01871
01872 continue;
01873
01874 }
01875
01876
01877 MechStatus(mech) |= TORSO_LEFT;
01878
01879 } else if(what_arc & RSIDEARC) {
01880
01881 if(temp_weapon_node->section == RLEG ||
01882 temp_weapon_node->section == LLEG) {
01883
01884
01885
01886 temp_weapon_node =
01887 (weapon_node *) rb_search(autopilot->
01888 profile[(int) range],
01889 SEARCH_PREV,
01890 &temp_weapon_node->
01891 range_scores[(int)
01892 range]);
01893
01894 continue;
01895
01896 }
01897
01898
01899 MechStatus(mech) |= TORSO_RIGHT;
01900
01901 } else {
01902
01903 if(GetPartFireMode(mech, temp_weapon_node->section,
01904 temp_weapon_node->
01905 critical) & REAR_MOUNT) {
01906
01907
01908
01909 temp_weapon_node =
01910 (weapon_node *) rb_search(autopilot->
01911 profile[(int) range],
01912 SEARCH_PREV,
01913 &temp_weapon_node->
01914 range_scores[(int)
01915 range]);
01916
01917 continue;
01918
01919 }
01920
01921 }
01922
01923 } else if((MechType(mech) == CLASS_MECH) &&
01924 (MechMove(mech) == MOVE_QUAD)) {
01925
01926
01927 what_arc = InWeaponArc(mech, MechFX(target), MechFY(target));
01928
01929 if(what_arc & REARARC) {
01930
01931 if(!(GetPartFireMode(mech, temp_weapon_node->section,
01932 temp_weapon_node->
01933 critical) & REAR_MOUNT)) {
01934
01935
01936
01937 temp_weapon_node =
01938 (weapon_node *) rb_search(autopilot->
01939 profile[(int) range],
01940 SEARCH_PREV,
01941 &temp_weapon_node->
01942 range_scores[(int)
01943 range]);
01944
01945 continue;
01946
01947 }
01948
01949 } else if(what_arc & FORWARDARC) {
01950
01951 if(GetPartFireMode(mech, temp_weapon_node->section,
01952 temp_weapon_node->
01953 critical) & REAR_MOUNT) {
01954
01955
01956
01957 temp_weapon_node =
01958 (weapon_node *) rb_search(autopilot->
01959 profile[(int) range],
01960 SEARCH_PREV,
01961 &temp_weapon_node->
01962 range_scores[(int)
01963 range]);
01964
01965 continue;
01966
01967 }
01968
01969 } else {
01970
01971
01972
01973 temp_weapon_node =
01974 (weapon_node *) rb_search(autopilot->
01975 profile[(int) range],
01976 SEARCH_PREV,
01977 &temp_weapon_node->
01978 range_scores[(int) range]);
01979
01980 continue;
01981
01982 }
01983
01984 } else if((MechType(mech) == CLASS_VEH_GROUND) ||
01985 (MechType(mech) == CLASS_VEH_NAVAL)) {
01986
01987
01988 what_arc = InWeaponArc(mech, MechFX(target), MechFY(target));
01989
01990
01991 if(GetSectInt(mech, TURRET)
01992 && temp_weapon_node->section == TURRET) {
01993
01994
01995 if(!(MechTankCritStatus(mech) & TURRET_JAMMED) &&
01996 !(MechTankCritStatus(mech) & TURRET_LOCKED) &&
01997 (AcceptableDegree
01998 (MechTurretFacing(mech) + MechFacing(mech)) !=
01999 FindBearing(MechFX(mech), MechFY(mech),
02000 MechFX(target), MechFY(target)))) {
02001
02002 snprintf(buffer, LBUF_SIZE, "%d",
02003 FindBearing(MechFX(mech), MechFY(mech),
02004 MechFX(target), MechFY(target)));
02005 mech_turret(autopilot->mynum, mech, buffer);
02006 }
02007
02008 } else {
02009
02010
02011 if(!IsInWeaponArc(mech, MechFX(target), MechFY(target),
02012 temp_weapon_node->section,
02013 temp_weapon_node->critical)) {
02014
02015
02016 temp_weapon_node =
02017 (weapon_node *) rb_search(autopilot->
02018 profile[(int) range],
02019 SEARCH_PREV,
02020 &temp_weapon_node->
02021 range_scores[(int)
02022 range]);
02023
02024 continue;
02025
02026 }
02027
02028 }
02029
02030 } else {
02031
02032
02033
02034
02035
02036 }
02037
02038
02039 snprintf(buffer, LBUF_SIZE, "%d",
02040 temp_weapon_node->weapon_number);
02041 mech_fireweapon(autopilot->mynum, mech, buffer);
02042
02043
02044 print_autogun_log(autopilot, "Autogun - Fired Weapon #%d "
02045 "at target #%d",
02046 temp_weapon_node->weapon_number,
02047 autopilot->target);
02048
02049
02050
02051 if(WpnIsRecycling
02052 (mech, temp_weapon_node->section,
02053 temp_weapon_node->critical)) {
02054 accumulate_heat +=
02055 MechWeapons[temp_weapon_node->weapon_db_number].heat;
02056 }
02057
02058
02059 temp_weapon_node =
02060 (weapon_node *) rb_search(autopilot->profile[(int) range],
02061 SEARCH_PREV,
02062 &temp_weapon_node->
02063 range_scores[(int) range]);
02064
02065 }
02066
02067 }
02068
02069
02070 print_autogun_log(autopilot, "Autogun - End Weapon Attack Phase");
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083 if(ChasingTarget(autopilot)) {
02084
02085
02086 do_chasetarget = 0;
02087
02088
02089 switch (auto_get_command_enum(autopilot, 1)) {
02090
02091 case GOAL_CHASETARGET:
02092
02093
02094 do_chasetarget = 1;
02095 break;
02096
02097 case -1:
02098
02099
02100 do_chasetarget = 1;
02101 break;
02102
02103
02104 default:
02105
02106
02107 autopilot->chase_target = -10;
02108 autopilot->chasetarg_update_tick =
02109 AUTOPILOT_CHASETARG_UPDATE_TICK;
02110 autopilot->follow_update_tick = AUTOPILOT_FOLLOW_UPDATE_TICK;
02111 break;
02112
02113 }
02114
02115
02116 if(do_chasetarget) {
02117
02118
02119
02120
02121 if((autopilot->target != autopilot->chase_target) ||
02122 (autopilot->chasetarg_update_tick >=
02123 AUTOPILOT_CHASETARG_UPDATE_TICK)) {
02124
02125
02126
02127
02128
02129
02130 autopilot->chase_target = autopilot->target;
02131
02132
02133 autopilot->chasetarg_update_tick = 0;
02134 autopilot->follow_update_tick = AUTOPILOT_FOLLOW_UPDATE_TICK;
02135
02136
02137 auto_disengage(autopilot->mynum, autopilot, "");
02138 auto_delcommand(autopilot->mynum, autopilot, "-1");
02139
02140
02141 if(AssignedTarget(autopilot) && autopilot->target != -1) {
02142 snprintf(buffer, LBUF_SIZE, "autogun target %d",
02143 autopilot->target);
02144 } else {
02145 snprintf(buffer, LBUF_SIZE, "autogun on");
02146 }
02147
02148 auto_addcommand(autopilot->mynum, autopilot, buffer);
02149 snprintf(buffer, LBUF_SIZE, "chasetarget %d",
02150 autopilot->target);
02151 auto_addcommand(autopilot->mynum, autopilot, buffer);
02152 auto_engage(autopilot->mynum, autopilot, "");
02153
02154
02155 print_autogun_log(autopilot, "Autogun Event Finished");
02156
02157 return;
02158
02159 } else {
02160
02161
02162 autopilot->chasetarg_update_tick++;
02163
02164
02165
02166
02167 if((target = getMech(autopilot->target)) &&
02168 (!Destroyed(target)
02169 && (target->mapindex == mech->mapindex))) {
02170
02171
02174 FindXY(MechFX(target), MechFY(target),
02175 MechFacing(target) + autopilot->ofsx,
02176 autopilot->ofsy, &fx, &fy);
02177
02178 RealCoordToMapCoord(&x, &y, fx, fy);
02179
02180
02181 if(x < 0 || y < 0 || x >= map->map_width
02182 || y >= map->map_height) {
02183
02184
02185
02186
02187 x = MechX(target);
02188 y = MechY(target);
02189
02190 }
02191
02192
02193 if((MechX(mech) == x) && (MechY(mech) == y)
02194 && (MechSpeed(target) < 0.5)) {
02195
02196
02197 MapCoordToRealCoord(x, y, &fx, &fy);
02198
02199
02200 if(MechDesiredFacing(mech) !=
02201 FindBearing(MechFX(mech), MechFY(mech), fx, fy)) {
02202
02203 snprintf(buffer, LBUF_SIZE, "%d",
02204 FindBearing(MechFX(mech), MechFY(mech),
02205 fx, fy));
02206 mech_heading(autopilot->mynum, mech, buffer);
02207
02208 }
02209
02210 }
02211
02212 }
02213
02214 }
02215
02216 }
02217
02218 }
02219
02220
02221
02222
02223
02224 print_autogun_log(autopilot, "Autogun Event Finished");
02225
02226
02227 }