#include "mech.h"
#include "mech.events.h"
#include "autopilot.h"
#include "failures.h"
#include "mech.sensor.h"
#include "p.autogun.h"
#include "p.bsuit.h"
#include "p.glue.h"
#include "p.mech.sensor.h"
#include "p.mech.utils.h"
#include "p.mech.physical.h"
#include "p.mech.combat.h"
#include "p.mech.advanced.h"
#include "p.mech.bth.h"
Include dependency graph for autopilot_autogun.c:
Go to the source code of this file.
Functions | |
int | SearchLightInRange (MECH *mech, MAP *map) |
int | PrefVisSens (MECH *mech, MAP *map, int slite, MECH *target) |
void | auto_sensor_event (AUTO *autopilot) |
weapon_node * | auto_create_weapon_node (short weapon_number, short weapon_db_number, short section, short critical) |
void | auto_destroy_weapon_node (weapon_node *victim) |
target_node * | auto_create_target_node (int target_score, dbref target_dbref) |
void | auto_destroy_target_node (target_node *victim) |
void | auto_destroy_weaplist (AUTO *autopilot) |
static int | auto_targets_callback (void *key, void *data, int depth, void *arg) |
static int | auto_generic_compare (void *a, void *b, void *token) |
int | auto_calc_weapon_score (int weapon_db_number, int range) |
void | auto_update_profile_event (AUTO *autopilot) |
int | auto_calc_target_score (AUTO *autopilot, MECH *mech, MECH *target, MAP *map) |
void | auto_gun_event (AUTO *autopilot) |
Definition at line 744 of file autopilot_autogun.c.
References AUTO_GUN_MAX_RANGE, COMBAT_SAFE, Destroyed, FindHexRange(), GetSectArmor, GetSectInt, GetSectOArmor, GetSectOInt, GetSectORArmor, GetSectRArmor, MechBV, MechFX, MechFY, MECHLOSFLAG_SEEN, MechSpeed, MechStatus, MechTeam, MechToMech_LOSFlag, Started, and Uncon.
Referenced by auto_gun_event().
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 /* Default Values */ 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 /* Here is the meat of the function, basicly I gave each 00781 * part a maximum score, then fit a linear plot from the 00782 * max to a min value and score. Then I just summed 00783 * all the pieces together, very linear but should 00784 * give us a good starting point */ 00785 00786 /* Is the target dead? */ 00787 if(Destroyed(target)) 00788 return target_score; 00789 00790 /* If target is combat safe don't even try to shoot it */ 00791 if(MechStatus(target) & COMBAT_SAFE) 00792 return target_score; 00793 00794 /* Compare Teams - for now we won't try to shoot a guy on our team */ 00795 if(MechTeam(target) == MechTeam(mech)) 00796 return target_score; 00797 00798 /* Are we in los of the target - not sure really what to do about this 00799 * one, since we want the AI to be smart and all, for now, lets have 00800 * it be all seeing */ 00801 00802 /* Range to target */ 00803 range = FindHexRange(MechFX(mech), MechFY(mech), MechFX(target), 00804 MechFY(target)); 00805 00806 /* Our we outside the range of the AI's System */ 00807 if((range >= (float) AUTO_GUN_MAX_RANGE)) { 00808 return target_score; 00809 } 00810 00811 /* Range score calc */ 00812 /* Min range is 0, max range is 30, so score goes from 300 to 0 */ 00813 range_score = -10.0 * range + 300.0; 00814 00815 /* Get the Speed of the target */ 00816 target_speed = MechSpeed(target); 00817 00818 /* Speed score calc */ 00819 /* Min speed is 0, max is 150 (can go higher tho), and score goes from 00820 * 300 to 0 (can go negative if the target is faster then 150) */ 00822 speed_score = -2.0 * target_speed + 300.0; 00823 00824 /* Get the BV of the target */ 00825 target_bv = MechBV(target); 00826 00827 /* BV score calc */ 00828 /* Min bv is 0, max is around 2000 (can go higher), and score goes from 00829 * 0 to 100 (can go higher but we don't care much about bv) */ 00830 bv_score = 0.05 * ((float) target_bv); 00831 00832 /* Get the damage of the target by cycling through all the sections 00833 * and adding up the current and original values */ 00834 for(section = 0; section < NUM_SECTIONS; section++) { 00835 00836 /* Total the current armor and original armor */ 00837 total_armor_current += GetSectArmor(target, section) + 00838 GetSectRArmor(target, section); 00839 total_armor_original += GetSectOArmor(target, section) + 00840 GetSectORArmor(target, section); 00841 00842 /* Total the current internal and original internal */ 00843 total_internal_current += GetSectInt(target, section); 00844 total_internal_original += GetSectOInt(target, section); 00845 00846 } 00847 00848 /* Ok like above, we set a min and max, for armor was 100% to 0% 00849 * and scored from 0 to 300. For internal was 100% to 0% and 00850 * scored from 0 to 200. But we have to take care not to divide 00851 * by zero. */ 00852 00853 /* Check the totals before we divide so no Divide by zeros */ 00854 if(total_internal_original == 0 && total_armor_original == 0) { 00855 00856 /* Both values are zero, not going to try and shoot it */ 00857 return target_score; 00858 00859 } else if(total_internal_original == 0) { 00860 00861 /* Just use armor part of the calc */ 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 /* Just use internal part of the calc */ 00868 damage_score = -2.0 * ((float) total_internal_current / 00869 (float) total_internal_original) + 200.0; 00870 00871 } else { 00872 00873 /* Use the whole thing */ 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 /* Get the 'state' ie: shutdown, prone whatever */ 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 /* Add the individual scores and return the value */ 00892 target_score = (int) floor(range_score + speed_score + bv_score + 00893 damage_score + status_score); 00894 00895 return target_score; 00896 00897 }
int auto_calc_weapon_score | ( | int | weapon_db_number, | |
int | range | |||
) |
Definition at line 442 of file autopilot_autogun.c.
References weapon_struct::damage, weapon_struct::heat, IsMissile, missile_hit_table_struct::key, MechWeapons, and MissileHitTable.
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 /* Simple Calc */ 00457 00458 /* For the modifiers I assumed best was approx 550 00459 * 00460 * So for SR, chance of hitting is roughly 92% which is 506 rounded to 500 00461 * For MR, its 72%, so 390 and LR its 41% its 225 */ 00462 00463 /* Assume default values */ 00464 weapon_score = 0; 00465 weapon_damage = 0; 00466 range_score = 500; /* Since by default we assume its SR */ 00467 damage_score = 0; 00468 heat_score = 0; 00469 minrange_score = 0; 00470 00471 /* Don't bother trying to set a value if its outside its range */ 00472 if(range >= MechWeapons[weapon_db_number].longrange) { 00473 return weapon_score; 00474 } 00475 00476 /* Are we at LR ? */ 00477 if(range >= MechWeapons[weapon_db_number].medrange) { 00478 range_score = 215; 00479 } 00480 00481 /* Are we at MR ? */ 00482 if(range >= MechWeapons[weapon_db_number].shortrange && 00483 range < MechWeapons[weapon_db_number].medrange) { 00484 range_score = 390; 00485 } 00486 00487 /* Check min range */ 00488 /* Use a polynomial equation here because at 2 under min its equiv to MR, at 00489 * 4 under its equiv to LR, so we want it to balance out the range score */ 00490 /* score = -12.5(min - range)^2 - 25 * (min - range) */ 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 /* Get the damage for the weapon */ 00499 if(IsMissile(weapon_db_number)) { 00500 00501 /* Its a missile weapon so lookup in the Missile table get the max 00502 * number of missiles it can hit with, and multiply by the damage 00503 * per missile */ 00504 /* To make it more fair going to use the avg # of missile hits 00505 * which is when they would roll a 7, which becomes slot # 00506 * 5 */ 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 /* Get the damage score */ 00520 /* Straight linear plot */ 00521 damage_score = 50 * weapon_damage; 00522 00523 /* Get the heat */ 00524 weapon_heat = MechWeapons[weapon_db_number].heat; 00525 00526 /* Get the heat score */ 00527 /* Straight inverse linear plot - more heat bad... */ 00528 heat_score = -25 * weapon_heat + 250; 00529 00530 /* Final calc */ 00531 weapon_score = range_score + damage_score + heat_score + minrange_score; 00532 00533 return weapon_score; 00534 00535 }
target_node* auto_create_target_node | ( | int | target_score, | |
dbref | target_dbref | |||
) |
Definition at line 349 of file autopilot_autogun.c.
References target_node_t::target_dbref, and target_node_t::target_score.
Referenced by auto_gun_event().
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 }
weapon_node* auto_create_weapon_node | ( | short | weapon_number, | |
short | weapon_db_number, | |||
short | section, | |||
short | critical | |||
) |
Definition at line 312 of file autopilot_autogun.c.
References weapon_node_t::critical, weapon_node_t::section, weapon_node_t::weapon_db_number, and weapon_node_t::weapon_number.
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 }
void auto_destroy_target_node | ( | target_node * | victim | ) |
void auto_destroy_weaplist | ( | AUTO * | autopilot | ) |
Definition at line 383 of file autopilot_autogun.c.
References auto_destroy_weapon_node(), dllist_destroy_list(), dllist_remove_node_at_pos(), dllist_size(), and AUTO::weaplist.
Referenced by auto_newautopilot(), and newfreemech().
00384 { 00385 00386 weapon_node *temp_weapon_node; 00387 00388 /* Check to make sure there is a weapon list */ 00389 if(!(autopilot->weaplist)) 00390 return; 00391 00392 /* There is a weapon list - lets kill it */ 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 /* Finally destroying the list */ 00405 dllist_destroy_list(autopilot->weaplist); 00406 autopilot->weaplist = NULL; 00407 00408 }
void auto_destroy_weapon_node | ( | weapon_node * | victim | ) |
static int auto_generic_compare | ( | void * | a, | |
void * | b, | |||
void * | token | |||
) | [static] |
Definition at line 428 of file autopilot_autogun.c.
Referenced by auto_gun_event().
00429 { 00430 00431 int *one, *two; 00432 00433 one = (int *) a; 00434 two = (int *) b; 00435 00436 return (*one - *two); 00437 }
void auto_gun_event | ( | AUTO * | autopilot | ) |
Definition at line 905 of file autopilot_autogun.c.
References AssignedTarget, auto_calc_target_score(), auto_create_target_node(), auto_generic_compare(), AUTO_GUN_MAX_RANGE, AUTO_GUN_UPDATE_TICK, auto_targets_callback(), Destroyed, DoStopGun, FindHexRange(), getMap(), getMech(), IsAuto(), IsMech, LBUF_SIZE, MECH::mapindex, MECH::mapnumber, MechFX, MechFY, AUTO::mymech, AUTO::mynum, MECH::mynum, OODing, print_autogun_log, rb_destroy(), rb_exists(), rb_init(), rb_insert(), rb_search(), rb_size(), rb_walk(), SEARCH_LAST, Started, AUTO::target, AUTO::target_score, AUTO::target_threshold, AUTO::target_update_tick, UnassignTarget, WALK_INORDER, AUTO::weaplist, x, y, and Zombify.
Referenced by auto_heartbeat().
00906 { 00907 MECH *mech = (MECH *) autopilot->mymech; /* Its Mech */ 00908 MAP *map; /* The current Map */ 00909 MECH *target; /* Our current target */ 00910 MECH *physical_target; /* Our physical target */ 00911 rbtree targets; /* all the targets we're looking at */ 00912 target_node *temp_target_node; /* temp target node struct */ 00913 weapon_node *temp_weapon_node; /* temp weapon node struct */ 00914 00915 char buffer[LBUF_SIZE]; /* General use buffer */ 00916 00917 int target_score; /* variable to store temp score */ 00918 int threshold_score; /* The score to beat to switch targets */ 00919 00920 /* Stuff for Physical attacks */ 00921 int elevation_diff; /* Whats the elevation difference between 00922 the target and the mech */ 00923 int what_arc; /* What arc is the target in */ 00924 int new_arc; /* What arc now that we've twisted 00925 our torso */ 00926 int relative_bearing; /* Int to figure out which part of 00927 the rear arc hes in */ 00928 int is_section_destroyed[4]; /* Array of the different possible 00929 sections that could be destroyed */ 00930 int section_hasbusyweap[4]; /* Array to show if a section has a 00931 cycling weapon in it */ 00932 int rleg_bth, lleg_bth; /* To help us decide which leg to kick 00933 with */ 00934 int is_rarm_ready, is_larm_ready; /* To help us decide which arms to 00935 punch with */ 00936 00937 /* Stuff for Weapon Attacks */ 00938 int accumulate_heat; /* How much heat we're building up */ 00939 int i, j; 00940 00941 float range; /* General variable for range */ 00942 float maxspeed; /* So we know how fast our guy is going */ 00943 00944 /* For use with chase targ */ 00945 short x, y; 00946 float fx, fy; 00947 char do_chasetarget; /* Flag should we do chasetarget 00948 based on certain conditions */ 00949 00950 /* Basic checks */ 00951 if(!mech || !autopilot) 00952 return; 00953 00954 if(!IsMech(mech->mynum) || !IsAuto(autopilot->mynum)) 00955 return; 00956 00957 /* Ok our mech is dead we're done */ 00958 if(Destroyed(mech)) { 00959 DoStopGun(autopilot); 00960 return; 00961 } 00962 00964 if(!Started(mech)) { 00965 Zombify(autopilot); 00966 return; 00967 } 00968 00969 /* Not on map - so lets calm down */ 00970 if(!(map = getMap(mech->mapindex))) { 00971 Zombify(autopilot); 00972 return; 00973 } 00974 00975 /* Log it */ 00976 print_autogun_log(autopilot, "Autogun Event Started"); 00977 00978 /* check for a gun profile. */ 00979 if(autopilot->weaplist == NULL) { 00980 print_autogun_log(autopilot, "Autogun Event Finished"); 00981 return; 00982 } 00983 00984 /* OODing so don't shoot any guns */ 00985 if(OODing(mech)) { 00986 /* Log It */ 00987 print_autogun_log(autopilot, "Autogun Event Finished"); 00988 return; 00989 } 00990 00991 /* First check to make sure we have a valid current target */ 00992 if(autopilot->target > -1) { 00993 00994 if(!(target = getMech(autopilot->target))) { 00995 00996 /* ok its not a valid target reset */ 00997 autopilot->target = -1; 00998 autopilot->target_score = 0; 00999 01000 } else if(Destroyed(target) || (target->mapindex != mech->mapindex)) { 01001 01002 /* Target is either dead or not on the map anymore */ 01003 autopilot->target = -1; 01004 autopilot->target_score = 0; 01005 01006 } else { 01007 01008 /* Will keep on an assigned target even if its to far 01009 * away */ 01010 01011 /* Get range from mech to current target */ 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 /* Target is to far away */ 01019 autopilot->target = -1; 01020 autopilot->target_score = 0; 01021 01022 } 01023 01024 } 01025 01026 } 01027 01028 /* Were we given a target and its no longer there? */ 01029 if(AssignedTarget(autopilot) && autopilot->target == -1) { 01030 01031 /* Ok we had an assigned target but its gone now */ 01032 UnassignTarget(autopilot); 01033 01035 } 01036 01037 /* Do we need to look for a new target */ 01038 if(autopilot->target == -1 || 01039 (autopilot->target_update_tick >= AUTO_GUN_UPDATE_TICK && 01040 !AssignedTarget(autopilot))) { 01041 01042 /* Ok looking for a new target */ 01043 01044 /* Log It */ 01045 print_autogun_log(autopilot, "Autogun - Looking for new target"); 01046 01047 /* Reset the update ticker */ 01048 autopilot->target_update_tick = 0; 01049 01050 /* Setup the rbtree */ 01051 targets = rb_init(&auto_generic_compare, NULL); 01052 01053 /* Cycle through possible targets and pick something to shoot */ 01054 for(i = 0; i < map->first_free; i++) { 01055 01056 /* Make sure its on the right map */ 01057 if(i != mech->mapnumber && (j = map->mechsOnMap[i]) > 0) { 01058 01059 /* Is it a valid unit ? */ 01060 if(!(target = getMech(j))) 01061 continue; 01062 01063 /* Score the target */ 01064 target_score = 01065 auto_calc_target_score(autopilot, mech, target, map); 01066 01067 /* Log It */ 01068 print_autogun_log(autopilot, 01069 "Autogun - Possible target #%d with score %d", 01070 target->mynum, target_score); 01071 01072 /* If target has a score add it to rbtree */ 01073 if(target_score > 0) { 01074 01075 /* Create target node and fill with proper values */ 01076 temp_target_node = auto_create_target_node(target_score, 01077 target->mynum); 01078 01081 /* Add it to list but first make sure it doesn't overlap 01082 * with a current score */ 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 /* Add it */ 01095 rb_insert(targets, &temp_target_node->target_score, 01096 temp_target_node); 01097 01098 } 01099 01100 /* Check to see if its our current target */ 01101 if(autopilot->target == target->mynum) { 01102 01103 /* Save the new score */ 01104 autopilot->target_score = target_score; 01105 01106 } 01107 01108 } 01109 01110 } /* End of for loop */ 01111 01112 /* Check to see if we couldn't find ANY targets within range, 01113 * if not, cycle autogun and set the update tick to 20, so we 01114 * check again in 10 seconds */ 01115 if(!(rb_size(targets) > 0)) { 01116 01117 /* Have the AI look for a new target 10 seconds from now */ 01120 autopilot->target = -1; 01121 autopilot->target_score = 0; 01122 autopilot->target_update_tick = 0; 01123 01124 /* Don't need the target list any more so lets destroy it */ 01125 rb_walk(targets, WALK_INORDER, &auto_targets_callback, NULL); 01126 rb_destroy(targets); 01127 01128 /* Log It */ 01129 print_autogun_log(autopilot, "Autogun in idle mode"); 01130 print_autogun_log(autopilot, "Autogun Event Finished"); 01131 return; 01132 } 01133 01134 /* Now if we have a current target, compare it to best target from 01135 * the new list. If better then threshold, lock new target, else 01136 * stay on target */ 01137 01138 /* Best target */ 01139 temp_target_node = 01140 (target_node *) rb_search(targets, SEARCH_LAST, NULL); 01141 01142 /* Log It */ 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 /* Check to see if its our current target */ 01154 if(autopilot->target != temp_target_node->target_dbref) { 01155 01156 /* Calc the threshold score to beat */ 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 /* Change targets */ 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 /* Else: Don't switch targets */ 01174 01175 } 01176 01177 /* Else: Don't need to swtich targets */ 01178 01179 } else { 01180 01181 /* Don't have a good current target so lock this one */ 01182 autopilot->target = temp_target_node->target_dbref; 01183 autopilot->target_score = temp_target_node->target_score; 01184 01185 } /* End of choosing new target */ 01186 01187 /* Don't need the target list any more so lets destroy it */ 01188 rb_walk(targets, WALK_INORDER, &auto_targets_callback, NULL); 01189 rb_destroy(targets); 01190 01191 } else { 01192 01193 /* Ok didn't need to look for a new target so update the ticker */ 01194 autopilot->target_update_tick++; 01195 01196 } 01197 01198 /* End of picking a new target */ 01199 01200 /* Log It */ 01201 print_autogun_log(autopilot, "Autogun - Current target #%d with score %d", 01202 autopilot->target, autopilot->target_score); 01203 01204 /* Setup the current target */ 01205 if(!(target = getMech(autopilot->target))) { 01206 01207 /* There were no valid targets so 01208 * rerun autogun */ 01209 01210 /* Reset the AI */ 01211 autopilot->target = -1; 01212 autopilot->target_score = 0; 01213 01214 /* Log It */ 01215 print_autogun_log(autopilot, "Autogun - No valid current targets"); 01216 print_autogun_log(autopilot, "Autogun Event Finished"); 01217 return; 01218 01219 } 01220 01221 /* Check to see if we need to (re)lock our target */ 01222 if(MechTarget(mech) != autopilot->target) { 01223 01224 /* Lock Him */ 01225 snprintf(buffer, LBUF_SIZE, "%c%c", MechID(target)[0], 01226 MechID(target)[1]); 01227 mech_settarget(autopilot->mynum, mech, buffer); 01228 01229 /* Log It */ 01230 print_autogun_log(autopilot, "Autogun - Locking target #%d", 01231 autopilot->target); 01232 01233 } 01234 01235 /* Update autosensor */ 01236 01237 /* Now lets get physical */ 01238 01239 /* Log It */ 01240 print_autogun_log(autopilot, "Autogun - Start Physical Attack Stage"); 01241 01242 /* Get range from mech to current target */ 01243 range = 01244 FindHexRange(MechFX(mech), MechFY(mech), MechFX(target), 01245 MechFY(target)); 01246 01247 /* First check our range to our target, if within range attack it, else 01248 * check to see if its outside our range threshold and if so pick a target 01249 * close and attack that */ 01250 01252 if(range < 1.0) { 01253 01254 /* We're beating on our main target */ 01255 physical_target = target; 01256 01257 } else if(range > AUTO_GUN_PHYSICAL_RANGE_MIN) { 01258 01259 /* Try and find a target */ 01260 01261 physical_target = NULL; 01262 01263 /* Cycle through possible targets and pick something to beat on */ 01264 for(i = 0; i < map->first_free; i++) { 01265 01266 /* Make sure its on the right map */ 01267 if(i != mech->mapnumber && (j = map->mechsOnMap[i]) > 0) { 01268 01269 /* Is it a valid unit ? */ 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 /* Check its range */ 01283 range = FindHexRange(MechFX(mech), MechFY(mech), 01284 MechFX(target), MechFY(target)); 01285 01286 /* Just go for first one , can always add scoring later */ 01287 if(range < 1.0) { 01288 physical_target = target; 01289 break; 01290 } 01291 01292 } 01293 01294 } 01295 01296 } else { 01297 01298 /* Our target is close so dont try and physically attack anyone */ 01299 physical_target = NULL; 01300 01301 } 01302 01303 /* Now nail it with a physical attack but only if we see it */ 01304 if(physical_target && 01305 (MechToMech_LOSFlag(map, mech, physical_target) & MECHLOSFLAG_SEEN)) { 01306 01307 /* Log It */ 01308 print_autogun_log(autopilot, 01309 "Autogun - Attempting physical attack against" 01310 " target #%d", physical_target->mynum); 01311 01312 /* Calculate elevation difference */ 01313 elevation_diff = MechZ(mech) - MechZ(target); 01314 01315 /* Are we a biped Mech */ 01316 if((MechType(mech) == CLASS_MECH) && (MechMove(mech) == MOVE_BIPED)) { 01317 01318 /* Center the torso */ 01319 MechStatus(mech) &= ~(TORSO_RIGHT | TORSO_LEFT); 01320 01321 if(MechSpecials(mech) & FLIPABLE_ARMS) { 01322 01323 /* Center the arms if need be */ 01324 MechStatus(mech) &= ~(FLIPPED_ARMS); 01325 } 01326 01327 /* Find direction of bad guy */ 01328 what_arc = 01329 InWeaponArc(mech, MechFX(physical_target), 01330 MechFY(physical_target)); 01331 01332 /* Rotate if we need to */ 01333 if(what_arc & LSIDEARC) { 01334 01335 /* Rotate Left */ 01336 MechStatus(mech) |= TORSO_LEFT; 01337 01338 } else if(what_arc & RSIDEARC) { 01339 01340 /* Rotate Right */ 01341 MechStatus(mech) |= TORSO_RIGHT; 01342 01343 } else if(what_arc & REARARC) { 01344 01345 /* Find out if it would be better to 01346 * rotate left or right */ 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 /* Rotate Right */ 01355 MechStatus(mech) |= TORSO_RIGHT; 01356 01357 } else if(relative_bearing > 180 && relative_bearing < 240) { 01358 01359 /* Rotate Left */ 01360 MechStatus(mech) |= TORSO_LEFT; 01361 01362 } 01363 01364 /* ELSE: Hes directly behind us so we can't do anything */ 01365 01366 } 01367 01368 /* Calculate the new arc */ 01369 new_arc = 01370 InWeaponArc(mech, MechFX(physical_target), 01371 MechFY(physical_target)); 01372 01373 /* Check to see what sections are destroyed */ 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 /* Check to see if the sections have a busy weapon */ 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 /* Try weapon physical attacks */ 01388 01389 /* Right Arm */ 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 /* else if (have_mace(mech, RARM)) */ 01402 else if(have_sword(mech, RARM)) 01403 mech_sword(autopilot->mynum, mech, buffer); 01404 01405 } 01406 01407 /* Left Arm */ 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 /* else if (have_mace(mech, RARM)) */ 01420 else if(have_sword(mech, LARM)) 01421 mech_sword(autopilot->mynum, mech, buffer); 01422 01423 } 01424 01425 /* Try and kick but only if we got two legs, one of them 01426 * doesn't have a cycling weapon and the target is in the 01427 * front arc */ 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 /* Check the RLEG for any crits or weaps cycling */ 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 /* Check the LLEG for any crits or weaps cycling */ 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 /* Now kick depending on which one would be better 01465 * to kick with */ 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 /* Finally try to punch */ 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 /* We can use the right arm */ 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 /* We can use the left arm */ 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 /* Now punch */ 01515 mech_punch(autopilot->mynum, mech, buffer); 01516 01517 } 01518 01519 } else if((MechType(mech) == CLASS_MECH) && 01520 (MechMove(mech) == MOVE_QUAD)) { 01521 01522 /* Quad Mech - Right now only supporting kicking front style for quad */ 01523 /* Remember, the RARM becomes the Front RLEG and the LARM becomes the 01524 * Front LLEG */ 01525 01526 /* Find direction of bad guy */ 01527 what_arc = 01528 InWeaponArc(mech, MechFX(physical_target), 01529 MechFY(physical_target)); 01530 01531 /* Check to see what sections are destroyed */ 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 /* Check to see if the sections have a busy weapon */ 01539 memset(section_hasbusyweap, 0, sizeof(section_hasbusyweap)); 01540 section_hasbusyweap[0] = SectHasBusyWeap(mech, RARM); 01541 section_hasbusyweap[1] = SectHasBusyWeap(mech, LARM); 01542 //section_hasbusyweap[2] = SectHasBusyWeap(mech, RLEG); 01543 //section_hasbusyweap[3] = SectHasBusyWeap(mech, LLEG); 01544 01545 /* Try and kick but only if we got two legs, one of them 01546 * doesn't have a cycling weapon and the target is in the 01547 * front arc */ 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 /* Check the Front Right Leg for any crits or weaps cycling */ 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 /* Check the Front Left Leg for any crits or weaps cycling */ 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 /* Now kick depending on which one would be better 01586 * to kick with */ 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 /* Are we a BSuit */ 01602 01603 } else { 01604 01605 /* Eventually add code here maybe for other physical attacks for 01606 * tanks perhaps */ 01607 01608 } 01609 01610 } 01611 01612 /* End of physical attack */ 01613 /* Log It */ 01614 print_autogun_log(autopilot, "Autogun - End Physical Attack Stage"); 01615 01616 /* Now we mow down our target */ 01617 01618 /* Get our current target */ 01619 /* Check to make sure we didn't kill it with physical attack 01620 * or something */ 01621 if(!(target = getMech(autopilot->target))) { 01622 01623 /* There were no valid targets so 01624 * rerun autogun */ 01625 01626 /* Reset the AI */ 01627 autopilot->target = -1; 01628 autopilot->target_score = 0; 01629 01630 /* Log It */ 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 /* Target is either dead or not on the map anymore */ 01638 autopilot->target = -1; 01639 autopilot->target_score = 0; 01640 01641 /* Log it */ 01642 print_autogun_log(autopilot, "Autogun - Target Gone"); 01643 print_autogun_log(autopilot, "Autogun Event Finished"); 01644 return; 01645 } 01646 01647 /* Log It */ 01648 print_autogun_log(autopilot, "Autogun - Starting Weapon Attack Phase"); 01649 01650 /* Get range from mech to current target */ 01651 range = FindHexRange(MechFX(mech), MechFY(mech), 01652 MechFX(target), MechFY(target)); 01653 01654 /* This probably unnecessary but since it doesn't 01655 * take much to calc range it should be ok for 01656 * testing for now */ 01657 if((range >= (float) AUTO_GUN_MAX_RANGE) && !AssignedTarget(autopilot)) { 01658 01659 /* Target is to far - reset */ 01660 autopilot->target = -1; 01661 autopilot->target_score = 0; 01662 01663 01664 /* Log it */ 01665 print_autogun_log(autopilot, "Autogun - Target out of range"); 01666 print_autogun_log(autopilot, "Autogun Event Finished"); 01667 return; 01668 } 01669 01670 /* Cycle through Guns while watching the heat */ 01671 if((range < (float) AUTO_GUN_MAX_RANGE) 01672 && autopilot->profile[(int) range]) { 01673 01674 /* Ok we got weapons lets use them */ 01675 01676 /* Reset heat counter to current heat */ 01677 accumulate_heat = MechWeapHeat(mech); 01678 01679 /* If the unit is moving need to account for the heat of that as well */ 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 /* Get first weapon */ 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 /* Check to see if the weapon even works */ 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 /* Weapon Doesn't work so go to next one */ 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 /* Check to see if its cycling */ 01716 if(WpnIsRecycling 01717 (mech, temp_weapon_node->section, 01718 temp_weapon_node->critical)) { 01719 01720 /* Go to the next one */ 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 /* Ok its an AMS so go to next weapon */ 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 /* Check heat levels, since the heat isn't updated untill we're done 01742 * we have to manage the heat ourselves */ 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 /* Would make ourselves to hot to fire this gun */ 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 /* Ok passed the checks now setup the arcs and see if we can fire it */ 01764 01765 /* Ok the rest depends on what type of unit we driving */ 01766 if((MechType(mech) == CLASS_MECH) && 01767 (MechMove(mech) == MOVE_BIPED)) { 01768 01769 /* Center ourself and get target arc */ 01770 MechStatus(mech) &= ~(TORSO_RIGHT | TORSO_LEFT); 01771 if(MechSpecials(mech) & FLIPABLE_ARMS) { 01772 01773 /* Center the arms if need be */ 01774 MechStatus(mech) &= ~(FLIPPED_ARMS); 01775 } 01776 01777 /* Get Target Arc */ 01778 what_arc = InWeaponArc(mech, MechFX(target), MechFY(target)); 01779 01780 /* Now go through the various arcs and see if we 01781 * need to flip arm or rotorso or something */ 01782 if(what_arc & REARARC) { 01783 01784 if(temp_weapon_node->section == LARM || 01785 temp_weapon_node->section == RARM) { 01786 01787 /* First see if we can flip arms */ 01788 if(MechSpecials(mech) & FLIPABLE_ARMS) { 01789 01790 /* Flip the arms */ 01791 MechStatus(mech) |= FLIPPED_ARMS; 01792 01793 } else { 01794 01795 /* Now see if we can rotatorso */ 01796 01797 /* Find out if it would be better to 01798 * rotate left or right */ 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 /* Rotate Right */ 01808 MechStatus(mech) |= TORSO_RIGHT; 01809 01810 } else if(relative_bearing > 180 01811 && relative_bearing < 240 01812 && temp_weapon_node->section == LARM) { 01813 01814 /* Rotate Left */ 01815 MechStatus(mech) |= TORSO_LEFT; 01816 01817 } else { 01818 01819 /* Can't do anything so go to next weapon */ 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 /* Weapon is forward torso or leg mounted weapon 01841 * so no way to shoot with */ 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 /* ELSE: Weapon is rear mounted so don't need to 01855 * do anything */ 01856 01857 } else if(what_arc & LSIDEARC) { 01858 01859 if(temp_weapon_node->section == RLEG || 01860 temp_weapon_node->section == LLEG) { 01861 01862 /* No way can we hit him with leg mounted 01863 * weapons so lets go to next one */ 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 /* Rotate torso left */ 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 /* No way can we hit him with leg mounted 01885 * weapons so lets go to next one */ 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 /* Rotate torso right */ 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 /* No way can we hit the guy with a rear 01908 * gun so lets go to next one */ 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 /* Get Target Arc */ 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 /* Weapon is not rear mounted so skip it and 01936 * go to the next weapon */ 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 /* Weapon is rear mounted so skip it and 01956 * go to the next weapon */ 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 /* The attacker is in a zone we can't possibly 01972 * shoot into, so just go to next weapon */ 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 /* Get Target Arc */ 01988 what_arc = InWeaponArc(mech, MechFX(target), MechFY(target)); 01989 01990 /* Check if turret exists and weapon is there */ 01991 if(GetSectInt(mech, TURRET) 01992 && temp_weapon_node->section == TURRET) { 01993 01994 /* Rotate Turret and nail the guy */ 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 /* Check if in arc of weapon */ 02011 if(!IsInWeaponArc(mech, MechFX(target), MechFY(target), 02012 temp_weapon_node->section, 02013 temp_weapon_node->critical)) { 02014 02015 /* Not in the arc so lets go to the next weapon */ 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 /* We're either an aero, ds, bsuit, mechwarrior or vtol 02033 * 02034 * Still need to add code for them */ 02035 02036 } 02037 02038 /* Done moving around, fire the weapon */ 02039 snprintf(buffer, LBUF_SIZE, "%d", 02040 temp_weapon_node->weapon_number); 02041 mech_fireweapon(autopilot->mynum, mech, buffer); 02042 02043 /* Log It */ 02044 print_autogun_log(autopilot, "Autogun - Fired Weapon #%d " 02045 "at target #%d", 02046 temp_weapon_node->weapon_number, 02047 autopilot->target); 02048 02049 /* Ok check to see if weapon was fired if so account for the 02050 * heat */ 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 /* Ok go to the next weapon */ 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 } /* End of cycling through weapons */ 02066 02067 } 02068 02069 /* Log It */ 02070 print_autogun_log(autopilot, "Autogun - End Weapon Attack Phase"); 02071 02072 /* Setup chasetarg 02073 * 02074 * Since chasetarget uses follow but we don't want follow getting 02075 * messed up if its following a normal target. We define our own 02076 * follow (basicly its follow but with the command name chasetarget */ 02077 02078 /* Get the first command, if its chasetarget or there is no command 02079 * check to see if we need to update chasetarget, otherwise means 02080 * AI is doing something else important so don't try to chase 02081 * anything */ 02082 02083 if(ChasingTarget(autopilot)) { 02084 02085 /* Reset the flag */ 02086 do_chasetarget = 0; 02087 02088 /* Get the first command's enum and check it */ 02089 switch (auto_get_command_enum(autopilot, 1)) { 02090 02091 case GOAL_CHASETARGET: 02092 02093 /* Ok its our command so we can change it */ 02094 do_chasetarget = 1; 02095 break; 02096 02097 case -1: 02098 02099 /* No current commands so we can do our chasetarget */ 02100 do_chasetarget = 1; 02101 break; 02102 02103 /* ALl the other stuff we don't want to mess with */ 02104 default: 02105 02106 /* Reset the chase values */ 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 /* Check the flag */ 02116 if(do_chasetarget) { 02117 02118 /* Ok lets chase the guy */ 02119 02120 /* First see if we need to update */ 02121 if((autopilot->target != autopilot->chase_target) || 02122 (autopilot->chasetarg_update_tick >= 02123 AUTOPILOT_CHASETARG_UPDATE_TICK)) { 02124 02125 /* Tell the AI to follow its target */ 02126 /* Basicly remove all the commands, add in 02127 * autogun and follow and engage */ 02128 02129 /* Let the AI know we chasing this guy */ 02130 autopilot->chase_target = autopilot->target; 02131 02132 /* Reset the tickers */ 02133 autopilot->chasetarg_update_tick = 0; 02134 autopilot->follow_update_tick = AUTOPILOT_FOLLOW_UPDATE_TICK; 02135 02136 /* Reset the AI */ 02137 auto_disengage(autopilot->mynum, autopilot, ""); 02138 auto_delcommand(autopilot->mynum, autopilot, "-1"); 02139 02140 /* Add in autogun and follow and engage */ 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 /* Log it */ 02155 print_autogun_log(autopilot, "Autogun Event Finished"); 02156 02157 return; 02158 02159 } else { 02160 02161 /* Update the ticker */ 02162 autopilot->chasetarg_update_tick++; 02163 02164 /* Check to see if we need to turn to face the guy by 02165 * generating our target hex and seeing if we are in that 02166 * hex then face the bad guy */ 02167 if((target = getMech(autopilot->target)) && 02168 (!Destroyed(target) 02169 && (target->mapindex == mech->mapindex))) { 02170 02171 /* Generate the target hex */ 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 /* Make sure the hex is sane */ 02181 if(x < 0 || y < 0 || x >= map->map_width 02182 || y >= map->map_height) { 02183 02184 /* Bad Target Hex */ 02185 02186 /* Reset the hex to the Target's current hex */ 02187 x = MechX(target); 02188 y = MechY(target); 02189 02190 } 02191 02192 /* Are we in the target hex and is the target not moving */ 02193 if((MechX(mech) == x) && (MechY(mech) == y) 02194 && (MechSpeed(target) < 0.5)) { 02195 02196 /* Get his bearing and face him */ 02197 MapCoordToRealCoord(x, y, &fx, &fy); 02198 02199 /* If we're not facing him, turn towards him */ 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 /* Turn towards him */ 02210 } 02211 /* Is he moving and are we in target hex */ 02212 } 02213 /* Do we need to turn towards him */ 02214 } /* Do we need to update */ 02215 02216 } 02217 /* Do we run chasetarget */ 02218 } 02219 02220 /* Is chasetarget on */ 02221 /* Make sure multiple instances of autogun aren't running */ 02222 02223 /* Log it */ 02224 print_autogun_log(autopilot, "Autogun Event Finished"); 02225 02226 /* The End */ 02227 }
void auto_sensor_event | ( | AUTO * | autopilot | ) |
Definition at line 152 of file autopilot_autogun.c.
References AUTOPILOT_LSENS, BEAGLE_DESTROYED, BEAGLE_PROBE_TECH, BLOODHOUND_DESTROYED, BLOODHOUND_PROBE_TECH, BOUNDED(), statedata::db_top, Destroyed, DoStopGun, dprintk, FaMechRange, AUTO::flags, FlyingT, getMap(), getMech(), HeatFactor(), IsAuto(), IsMech, Landed, MECH::mapindex, MAP::maplight, MAP::mapvis, MarkForLOSUpdate(), mech_notify(), MECHALL, MechCritStatus, MechSensor, MechSpecials, MechSpecials2, MechTarget, MechTons, mudstate, AUTO::mymech, AUTO::mymechnum, MECH::mynum, AUTO::mynum, PrefVisSens(), SearchLightInRange(), SENSOR_BAP, SENSOR_BHAP, SENSOR_EM, SENSOR_IR, SENSOR_RA, SENSOR_VIS, Started, and Zombify.
Referenced by auto_heartbeat().
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 /* Make sure its a MECH Xcode Object and the AI is 00176 * an AUTOPILOT Xcode Object */ 00177 /* Basic checks */ 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 /* Mech is dead so stop trying to shoot things */ 00191 if(Destroyed(mech)) { 00192 DoStopGun(autopilot); 00193 return; 00194 } 00195 00196 /* Mech isn't started */ 00197 if(!Started(mech)) { 00198 Zombify(autopilot); 00199 return; 00200 } 00201 00202 /* The mech is using user defined sensors so don't try 00203 * and change them */ 00204 if(autopilot->flags & AUTOPILOT_LSENS) 00205 return; 00206 00207 /* Get the map */ 00208 if(!(map = getMap(mech->mapindex))) { 00209 00210 /* Bad Map */ 00211 Zombify(autopilot); 00212 return; 00213 } 00214 00215 /* Get the target if there is one */ 00216 if(MechTarget(mech) > 0) 00217 target = getMech(MechTarget(mech)); 00218 00219 /* Checks to see if there is slite, and what types of vis 00220 * and which visual sensor (V or L) to use */ 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 /* Is there a target */ 00226 if(target) { 00227 00228 /* Range to target */ 00229 trng = FaMechRange(mech, target); 00230 00231 /* Actually not gonna bother with this */ 00232 /* If the target is running hot and is close switch to IR */ 00233 if(!set && HeatFactor(target) > 35 && (int) trng < 15) { 00234 //wanted_s[0] = SENSOR_IR; 00235 //wanted_s[1] = ((MechTons(target) >= 60) ? SENSOR_EM : prefvis); 00236 //set++; 00237 } 00238 00239 /* If the target is BIG and close enough, use EM */ 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 /* If the target is flying switch to Radar */ 00247 if(!set && !Landed(target) && FlyingT(target)) { 00248 wanted_s[0] = SENSOR_RA; 00249 wanted_s[1] = prefvis; 00250 set++; 00251 } 00252 00253 /* If the target is really close and the unit has BAP, use it */ 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 /* If the target is really close and the unit has Bloodhound, use it */ 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 /* Didn't stop at any of the others so use selected visual sensors */ 00271 if(!set) { 00272 wanted_s[0] = prefvis; 00273 wanted_s[1] = (rvis <= 15 ? SENSOR_EM : prefvis); 00274 set++; 00275 } 00276 00277 } 00278 00279 /* Ok no target and no sensors set yet so lets go for defaults */ 00280 if(!set) { 00281 if(rvis <= 15) { 00282 /* Vis is less then or equal to 15 so go to E I for longer range */ 00283 wanted_s[0] = SENSOR_EM; 00284 wanted_s[1] = SENSOR_IR; 00285 } else { 00286 /* Ok lets go with default visual sensors */ 00287 wanted_s[0] = prefvis; 00288 wanted_s[1] = prefvis; 00289 } 00290 } 00291 00292 /* Check to make sure valid sensors are selected and then set them */ 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 }
static int auto_targets_callback | ( | void * | key, | |
void * | data, | |||
int | depth, | |||
void * | arg | |||
) | [static] |
Definition at line 413 of file autopilot_autogun.c.
References auto_destroy_target_node().
Referenced by auto_gun_event().
00414 { 00415 00416 target_node *temp; 00417 00418 temp = (target_node *) data; 00419 auto_destroy_target_node(temp); 00420 00421 return 1; 00422 00423 }
void auto_update_profile_event | ( | AUTO * | autopilot | ) |
Definition at line 542 of file autopilot_autogun.c.
References AUTO_PROFILE_MAX_SIZE, statedata::db_top, Destroyed, dprintk, IsAuto(), IsMech, MAX_WEAPS_SECTION, mudstate, AUTO::mymech, AUTO::mymechnum, AUTO::mynum, MECH::mynum, print_autogun_log, AUTO::profile, rb_destroy(), and StopGun.
Referenced by auto_heartbeat().
00542 { 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 /* Basic checks */ 00560 /* some accounting checks. try to prevent some race stuff */ 00561 00562 if((autopilot->mymechnum > mudstate.db_top) || (autopilot->mymechnum < 1 )) { 00563 /* most commonly, the mech is a bad memory space. 00564 * lets not try to access it 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 /* Ok our mech is dead we're done */ 00583 if(Destroyed(mech)) { 00584 return; 00585 } 00586 00587 /* Log Message */ 00588 print_autogun_log(autopilot, "Profiling Unit #%d", mech->mynum); 00589 00590 /* Destroy the arrays first, don't worry about the weap 00591 * structures because we can clear them with the ddlist 00592 * weaplist */ 00593 00594 /* Zero the array of rbtree stuff */ 00595 for(range = 0; range < AUTO_PROFILE_MAX_SIZE; range++) { 00596 00597 if(autopilot->profile[range]) { 00598 00599 /* Destroy rbtree */ 00600 rb_destroy(autopilot->profile[range]); 00601 } 00602 autopilot->profile[range] = NULL; 00603 } 00604 00605 /* Check to see if the weaplist exists */ 00606 if(autopilot->weaplist != NULL) { 00607 00608 /* Destroy the list */ 00609 auto_destroy_weaplist(autopilot); 00610 } 00611 00612 /* List doesn't exist so lets build it */ 00613 autopilot->weaplist = dllist_create_list(); 00614 00615 /* Reset the AI's max range value for its mech */ 00616 autopilot->mech_max_range = 0; 00617 00618 /* Set our counter */ 00619 weapon_count = -1; 00620 00621 /* Now loop through the weapons building a list */ 00622 for(section = 0; section < NUM_SECTIONS; section++) { 00623 00624 /* Find all the weapons for a given section */ 00625 weapon_count_section = FindWeapons(mech, section, 00626 weaparray, weapdata, critical); 00627 00628 /* No weapons here */ 00629 if(weapon_count_section <= 0) 00630 continue; 00631 00632 /* loop through the possible weapons */ 00633 for(weapon_number = 0; weapon_number < weapon_count_section; 00634 weapon_number++) { 00635 00636 /* Count it even if its not a valid weapon like AMS */ 00637 /* This is so when we go to fire the weapon we know 00638 * which one to send in the command */ 00639 weapon_count++; 00640 00641 if(IsAMS(weaparray[weapon_number])) 00642 continue; 00643 00644 /* Does it work? */ 00645 if(WeaponIsNonfunctional(mech, section, critical[weapon_number], 00646 GetWeaponCrits(mech, 00647 Weapon2I(weaparray 00648 [weapon_number]))) 00649 > 0) 00650 continue; 00651 00652 /* Ok made it this far, lets add it to our list */ 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 /* Check the max range */ 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 /* Now build the profile array, basicly loop through 00675 * all the current avail weapons, get its max range, 00676 * then loop through ranges and for each range add it 00677 * to profile */ 00678 00679 /* Our counter */ 00680 weapon_number = 1; 00681 00682 while (weapon_number <= dllist_size(autopilot->weaplist)) { 00683 00684 /* Get the weapon */ 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 /* Out side the the range of AI's profile system */ 00694 if(range >= AUTO_PROFILE_MAX_SIZE) { 00695 break; 00696 } 00697 00698 /* Score the weapon */ 00699 temp_weapon_node->range_scores[range] = 00700 auto_calc_weapon_score(temp_weapon_node->weapon_db_number, 00701 range); 00702 00703 /* If rbtree for this range doesn't exist, create it */ 00704 if(autopilot->profile[range] == NULL) { 00705 autopilot->profile[range] = 00706 rb_init(&auto_generic_compare, NULL); 00707 } 00708 00709 /* Check to see if the score exists in the tree 00710 * if so alter it slightly so we don't have 00711 * overlaping keys */ 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 /* Add it to tree */ 00724 rb_insert(autopilot->profile[range], 00725 &temp_weapon_node->range_scores[range], 00726 temp_weapon_node); 00727 00728 } 00729 00730 /* Increment */ 00731 weapon_number++; 00732 00733 } 00734 00735 /* Log Message */ 00736 print_autogun_log(autopilot, "Finished Profiling"); 00737 00738 }
Definition at line 124 of file autopilot_autogun.c.
References MAP::maplight, MechCritStatus, MechStatus, SENSOR_LA, SENSOR_VIS, SLITE_LIT, and SLITE_ON.
Referenced by auto_sensor_event().
00125 { 00126 00127 /* No map or mech so use default till we get put somewhere */ 00128 if(!mech || !map) 00129 return SENSOR_VIS; 00130 00131 /* Ok the AI is lit or using slite so use V */ 00132 if(MechStatus(mech) & SLITE_ON || MechCritStatus(mech) & SLITE_LIT) 00133 return SENSOR_VIS; 00134 00135 /* The target is lit so use V */ 00136 if(target && MechCritStatus(target) & SLITE_LIT) 00137 return SENSOR_VIS; 00138 00139 /* Ok if its night/dawn/dusk and theres no slite use L */ 00140 if(map->maplight <= 1 && slite != 3 && slite != 5) 00141 return SENSOR_LA; 00142 00143 /* Default sensor */ 00144 return SENSOR_VIS; 00145 }
Definition at line 54 of file autopilot_autogun.c.
References FaMechRange, FindObjectsData(), MAP::first_free, FORWARDARC, InWeaponArc(), LITE_RANGE, MechCritStatus, MechFX, MechFY, MECHLOSFLAG_BLOCK, MAP::mechsOnMap, MechSpecials, MechStatus, SLITE_DEST, SLITE_ON, and SLITE_TECH.
Referenced by auto_sensor_event().
00055 { 00056 00057 MECH *target; 00058 int i; 00059 00060 /* Make sure theres a valid mech or map */ 00061 if(!mech || !map) 00062 return 0; 00063 00064 /* Loop through all the units on the map */ 00065 for(i = 0; i < map->first_free; i++) { 00066 00067 /* No units on the map */ 00068 if(!(target = FindObjectsData(map->mechsOnMap[i]))) 00069 continue; 00070 00071 /* The unit doesn't have slite on */ 00072 if(!(MechSpecials(target) & SLITE_TECH) 00073 || MechCritStatus(mech) & SLITE_DEST) 00074 continue; 00075 00076 /* Is the mech close enough to be affected by the slite */ 00077 if(FaMechRange(target, mech) < LITE_RANGE) { 00078 00079 /* Returning true, but let's differentiate also between being in-arc. */ 00080 if((MechStatus(target) & SLITE_ON) && 00081 InWeaponArc(target, MechFX(mech), MechFY(mech)) & FORWARDARC) { 00082 00083 /* Make sure its in los */ 00084 if(! 00085 (map-> 00086 LOSinfo[target->mapnumber][mech-> 00087 mapnumber] & 00088 MECHLOSFLAG_BLOCK)) 00089 00090 /* Slite on and, arced, and LoS to you */ 00091 return 3; 00092 else 00093 /* Slite on, arced, but LoS blocked */ 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 /* Slite off, arced, and LoS to you */ 00107 return 5; 00108 00109 else 00110 /* Slite off, arced, and LoS blocked */ 00111 return 6; 00112 } 00113 00114 /* Slite is in range of you, but apparently not arced on you. 00115 * Return tells wether on or off */ 00116 return (MechStatus(target) & SLITE_ON ? 1 : 2); 00117 } 00118 00119 } 00120 return 0; 00121 }