parent
d00b632f48
commit
2325c0ec65
207
src/combat_ai.cc
207
src/combat_ai.cc
|
@ -16,7 +16,9 @@
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "message.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "party_member.h"
|
||||||
#include "platform_compat.h"
|
#include "platform_compat.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "proto_instance.h"
|
#include "proto_instance.h"
|
||||||
|
@ -31,17 +33,110 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define AI_PACKET_CHEM_PRIMARY_DESIRE_COUNT (3)
|
||||||
|
|
||||||
|
typedef struct AiMessageRange {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
} AiMessageRange;
|
||||||
|
|
||||||
|
typedef struct AiPacket {
|
||||||
|
char* name;
|
||||||
|
int packet_num;
|
||||||
|
int max_dist;
|
||||||
|
int min_to_hit;
|
||||||
|
int min_hp;
|
||||||
|
int aggression;
|
||||||
|
int hurt_too_much;
|
||||||
|
int secondary_freq;
|
||||||
|
int called_freq;
|
||||||
|
int font;
|
||||||
|
int color;
|
||||||
|
int outline_color;
|
||||||
|
int chance;
|
||||||
|
AiMessageRange run;
|
||||||
|
AiMessageRange move;
|
||||||
|
AiMessageRange attack;
|
||||||
|
AiMessageRange miss;
|
||||||
|
AiMessageRange hit[HIT_LOCATION_SPECIFIC_COUNT];
|
||||||
|
int area_attack_mode;
|
||||||
|
int run_away_mode;
|
||||||
|
int best_weapon;
|
||||||
|
int distance;
|
||||||
|
int attack_who;
|
||||||
|
int chem_use;
|
||||||
|
int chem_primary_desire[AI_PACKET_CHEM_PRIMARY_DESIRE_COUNT];
|
||||||
|
int disposition;
|
||||||
|
char* body_type;
|
||||||
|
char* general_type;
|
||||||
|
} AiPacket;
|
||||||
|
|
||||||
|
typedef struct STRUCT_832 {
|
||||||
|
Object* field_0;
|
||||||
|
Object* field_4;
|
||||||
|
Object* field_8[100];
|
||||||
|
int field_198[100];
|
||||||
|
int field_328;
|
||||||
|
int field_32C;
|
||||||
|
int field_330;
|
||||||
|
int field_334;
|
||||||
|
int* field_338;
|
||||||
|
int field_33C;
|
||||||
|
int field_340;
|
||||||
|
} STRUCT_832;
|
||||||
|
|
||||||
|
static void _parse_hurt_str(char* str, int* out_value);
|
||||||
|
static int _cai_match_str_to_list(const char* str, const char** list, int count, int* out_value);
|
||||||
|
static void aiPacketInit(AiPacket* ai);
|
||||||
|
static int aiPacketRead(File* stream, AiPacket* ai);
|
||||||
|
static int aiPacketWrite(File* stream, AiPacket* ai);
|
||||||
|
static AiPacket* aiGetPacket(Object* obj);
|
||||||
|
static AiPacket* aiGetPacketByNum(int aiPacketNum);
|
||||||
|
static int _ai_magic_hands(Object* a1, Object* a2, int num);
|
||||||
|
static int _ai_check_drugs(Object* critter);
|
||||||
|
static void _ai_run_away(Object* a1, Object* a2);
|
||||||
|
static int _ai_move_away(Object* a1, Object* a2, int a3);
|
||||||
|
static bool _ai_find_friend(Object* a1, int a2, int a3);
|
||||||
|
static int _compare_nearer(const void* a1, const void* a2);
|
||||||
|
static int _compare_strength(const void* p1, const void* p2);
|
||||||
|
static int _compare_weakness(const void* p1, const void* p2);
|
||||||
|
static Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3);
|
||||||
|
static Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3);
|
||||||
|
static int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4);
|
||||||
|
static Object* _ai_danger_source(Object* a1);
|
||||||
|
static int _ai_have_ammo(Object* critter_obj, Object* weapon_obj, Object** out_ammo_obj);
|
||||||
|
static bool _caiHasWeapPrefType(AiPacket* ai, int attackType);
|
||||||
|
static Object* _ai_best_weapon(Object* a1, Object* a2, Object* a3, Object* a4);
|
||||||
|
static bool _ai_can_use_weapon(Object* critter, Object* weapon, int hitMode);
|
||||||
|
static bool aiCanUseItem(Object* obj, Object* a2);
|
||||||
|
static Object* _ai_search_environ(Object* critter, int itemType);
|
||||||
|
static Object* _ai_retrieve_object(Object* a1, Object* a2);
|
||||||
|
static int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3);
|
||||||
|
static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4);
|
||||||
|
static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3);
|
||||||
|
static int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int a2);
|
||||||
|
static bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance);
|
||||||
|
static int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4);
|
||||||
|
static int _ai_called_shot(Object* a1, Object* a2, int a3);
|
||||||
|
static int _ai_attack(Object* a1, Object* a2, int a3);
|
||||||
|
static int _ai_try_attack(Object* a1, Object* a2);
|
||||||
|
static int _cai_get_min_hp(AiPacket* ai);
|
||||||
|
static int _ai_print_msg(Object* critter, int type);
|
||||||
|
static int _combatai_rating(Object* obj);
|
||||||
|
static int aiMessageListInit();
|
||||||
|
static int aiMessageListFree();
|
||||||
|
|
||||||
// 0x51805C
|
// 0x51805C
|
||||||
Object* _combat_obj = NULL;
|
static Object* _combat_obj = NULL;
|
||||||
|
|
||||||
// 0x518060
|
// 0x518060
|
||||||
int gAiPacketsLength = 0;
|
static int gAiPacketsLength = 0;
|
||||||
|
|
||||||
// 0x518064
|
// 0x518064
|
||||||
AiPacket* gAiPackets = NULL;
|
static AiPacket* gAiPackets = NULL;
|
||||||
|
|
||||||
// 0x518068
|
// 0x518068
|
||||||
bool gAiInitialized = false;
|
static bool gAiInitialized = false;
|
||||||
|
|
||||||
// 0x51806C
|
// 0x51806C
|
||||||
const char* gAreaAttackModeKeys[AREA_ATTACK_MODE_COUNT] = {
|
const char* gAreaAttackModeKeys[AREA_ATTACK_MODE_COUNT] = {
|
||||||
|
@ -124,7 +219,7 @@ const char* gHurtTooMuchKeys[HURT_COUNT] = {
|
||||||
// hurt_too_much
|
// hurt_too_much
|
||||||
//
|
//
|
||||||
// 0x518124
|
// 0x518124
|
||||||
const int _rmatchHurtVals[5] = {
|
static const int _rmatchHurtVals[5] = {
|
||||||
DAM_BLIND,
|
DAM_BLIND,
|
||||||
DAM_CRIP_LEG_LEFT | DAM_CRIP_LEG_RIGHT | DAM_CRIP_ARM_LEFT | DAM_CRIP_ARM_RIGHT,
|
DAM_CRIP_LEG_LEFT | DAM_CRIP_LEG_RIGHT | DAM_CRIP_ARM_LEFT | DAM_CRIP_ARM_RIGHT,
|
||||||
DAM_CRIP_LEG_LEFT | DAM_CRIP_LEG_RIGHT,
|
DAM_CRIP_LEG_LEFT | DAM_CRIP_LEG_RIGHT,
|
||||||
|
@ -135,7 +230,7 @@ const int _rmatchHurtVals[5] = {
|
||||||
// Hit points in percent to choose run away mode.
|
// Hit points in percent to choose run away mode.
|
||||||
//
|
//
|
||||||
// 0x518138
|
// 0x518138
|
||||||
const int _hp_run_away_value[6] = {
|
static const int _hp_run_away_value[6] = {
|
||||||
0,
|
0,
|
||||||
25,
|
25,
|
||||||
40,
|
40,
|
||||||
|
@ -145,13 +240,13 @@ const int _hp_run_away_value[6] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 0x518150
|
// 0x518150
|
||||||
Object* _attackerTeamObj = NULL;
|
static Object* _attackerTeamObj = NULL;
|
||||||
|
|
||||||
// 0x518154
|
// 0x518154
|
||||||
Object* _targetTeamObj = NULL;
|
static Object* _targetTeamObj = NULL;
|
||||||
|
|
||||||
// 0x518158
|
// 0x518158
|
||||||
const int _weapPrefOrderings[BEST_WEAPON_COUNT + 1][5] = {
|
static const int _weapPrefOrderings[BEST_WEAPON_COUNT + 1][5] = {
|
||||||
{ ATTACK_TYPE_RANGED, ATTACK_TYPE_THROW, ATTACK_TYPE_MELEE, ATTACK_TYPE_UNARMED, 0 },
|
{ ATTACK_TYPE_RANGED, ATTACK_TYPE_THROW, ATTACK_TYPE_MELEE, ATTACK_TYPE_UNARMED, 0 },
|
||||||
{ ATTACK_TYPE_RANGED, ATTACK_TYPE_THROW, ATTACK_TYPE_MELEE, ATTACK_TYPE_UNARMED, 0 }, // BEST_WEAPON_NO_PREF
|
{ ATTACK_TYPE_RANGED, ATTACK_TYPE_THROW, ATTACK_TYPE_MELEE, ATTACK_TYPE_UNARMED, 0 }, // BEST_WEAPON_NO_PREF
|
||||||
{ ATTACK_TYPE_MELEE, 0, 0, 0, 0 }, // BEST_WEAPON_MELEE
|
{ ATTACK_TYPE_MELEE, 0, 0, 0, 0 }, // BEST_WEAPON_MELEE
|
||||||
|
@ -164,7 +259,7 @@ const int _weapPrefOrderings[BEST_WEAPON_COUNT + 1][5] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 0x51820C
|
// 0x51820C
|
||||||
const int _aiPartyMemberDistances[DISTANCE_COUNT] = {
|
static const int _aiPartyMemberDistances[DISTANCE_COUNT] = {
|
||||||
5,
|
5,
|
||||||
7,
|
7,
|
||||||
7,
|
7,
|
||||||
|
@ -173,27 +268,27 @@ const int _aiPartyMemberDistances[DISTANCE_COUNT] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 0x518220
|
// 0x518220
|
||||||
int gLanguageFilter = -1;
|
static int gLanguageFilter = -1;
|
||||||
|
|
||||||
// ai.msg
|
// ai.msg
|
||||||
//
|
//
|
||||||
// 0x56D510
|
// 0x56D510
|
||||||
MessageList gCombatAiMessageList;
|
static MessageList gCombatAiMessageList;
|
||||||
|
|
||||||
// 0x56D518
|
// 0x56D518
|
||||||
char _target_str[260];
|
static char _target_str[260];
|
||||||
|
|
||||||
// 0x56D61C
|
// 0x56D61C
|
||||||
int _curr_crit_num;
|
static int _curr_crit_num;
|
||||||
|
|
||||||
// 0x56D620
|
// 0x56D620
|
||||||
Object** _curr_crit_list;
|
static Object** _curr_crit_list;
|
||||||
|
|
||||||
// 0x56D624
|
// 0x56D624
|
||||||
char _attack_str[268];
|
static char _attack_str[268];
|
||||||
|
|
||||||
// parse hurt_too_much
|
// parse hurt_too_much
|
||||||
void _parse_hurt_str(char* str, int* valuePtr)
|
static void _parse_hurt_str(char* str, int* valuePtr)
|
||||||
{
|
{
|
||||||
int v5, v10;
|
int v5, v10;
|
||||||
char tmp;
|
char tmp;
|
||||||
|
@ -232,7 +327,7 @@ void _parse_hurt_str(char* str, int* valuePtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse behaviour entry
|
// parse behaviour entry
|
||||||
int _cai_match_str_to_list(const char* str, const char** list, int count, int* valuePtr)
|
static int _cai_match_str_to_list(const char* str, const char** list, int count, int* valuePtr)
|
||||||
{
|
{
|
||||||
*valuePtr = -1;
|
*valuePtr = -1;
|
||||||
for (int index = 0; index < count; index++) {
|
for (int index = 0; index < count; index++) {
|
||||||
|
@ -245,7 +340,7 @@ int _cai_match_str_to_list(const char* str, const char** list, int count, int* v
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x426FE0
|
// 0x426FE0
|
||||||
void aiPacketInit(AiPacket* ai)
|
static void aiPacketInit(AiPacket* ai)
|
||||||
{
|
{
|
||||||
ai->name = NULL;
|
ai->name = NULL;
|
||||||
|
|
||||||
|
@ -510,7 +605,7 @@ int aiSave(File* stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x427BC8
|
// 0x427BC8
|
||||||
int aiPacketRead(File* stream, AiPacket* ai)
|
static int aiPacketRead(File* stream, AiPacket* ai)
|
||||||
{
|
{
|
||||||
if (fileReadInt32(stream, &(ai->packet_num)) == -1) return -1;
|
if (fileReadInt32(stream, &(ai->packet_num)) == -1) return -1;
|
||||||
if (fileReadInt32(stream, &(ai->max_dist)) == -1) return -1;
|
if (fileReadInt32(stream, &(ai->max_dist)) == -1) return -1;
|
||||||
|
@ -554,7 +649,7 @@ int aiPacketRead(File* stream, AiPacket* ai)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x427E1C
|
// 0x427E1C
|
||||||
int aiPacketWrite(File* stream, AiPacket* ai)
|
static int aiPacketWrite(File* stream, AiPacket* ai)
|
||||||
{
|
{
|
||||||
if (fileWriteInt32(stream, ai->packet_num) == -1) return -1;
|
if (fileWriteInt32(stream, ai->packet_num) == -1) return -1;
|
||||||
if (fileWriteInt32(stream, ai->max_dist) == -1) return -1;
|
if (fileWriteInt32(stream, ai->max_dist) == -1) return -1;
|
||||||
|
@ -602,7 +697,7 @@ int aiPacketWrite(File* stream, AiPacket* ai)
|
||||||
// Get ai from object
|
// Get ai from object
|
||||||
//
|
//
|
||||||
// 0x4280B4
|
// 0x4280B4
|
||||||
AiPacket* aiGetPacket(Object* obj)
|
static AiPacket* aiGetPacket(Object* obj)
|
||||||
{
|
{
|
||||||
// NOTE: Uninline.
|
// NOTE: Uninline.
|
||||||
AiPacket* ai = aiGetPacketByNum(obj->data.critter.combat.aiPacket);
|
AiPacket* ai = aiGetPacketByNum(obj->data.critter.combat.aiPacket);
|
||||||
|
@ -612,7 +707,7 @@ AiPacket* aiGetPacket(Object* obj)
|
||||||
// get ai packet by num
|
// get ai packet by num
|
||||||
//
|
//
|
||||||
// 0x42811C
|
// 0x42811C
|
||||||
AiPacket* aiGetPacketByNum(int aiPacketId)
|
static AiPacket* aiGetPacketByNum(int aiPacketId)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < gAiPacketsLength; index++) {
|
for (int index = 0; index < gAiPacketsLength; index++) {
|
||||||
AiPacket* ai = &(gAiPackets[index]);
|
AiPacket* ai = &(gAiPackets[index]);
|
||||||
|
@ -799,7 +894,7 @@ int aiSetDisposition(Object* obj, int disposition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428398
|
// 0x428398
|
||||||
int _ai_magic_hands(Object* critter, Object* item, int num)
|
static int _ai_magic_hands(Object* critter, Object* item, int num)
|
||||||
{
|
{
|
||||||
reg_anim_begin(2);
|
reg_anim_begin(2);
|
||||||
|
|
||||||
|
@ -834,7 +929,7 @@ int _ai_magic_hands(Object* critter, Object* item, int num)
|
||||||
|
|
||||||
// ai using drugs
|
// ai using drugs
|
||||||
// 0x428480
|
// 0x428480
|
||||||
int _ai_check_drugs(Object* critter)
|
static int _ai_check_drugs(Object* critter)
|
||||||
{
|
{
|
||||||
if (critterGetBodyType(critter) != BODY_TYPE_BIPED) {
|
if (critterGetBodyType(critter) != BODY_TYPE_BIPED) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -997,7 +1092,7 @@ int _ai_check_drugs(Object* critter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428868
|
// 0x428868
|
||||||
void _ai_run_away(Object* a1, Object* a2)
|
static void _ai_run_away(Object* a1, Object* a2)
|
||||||
{
|
{
|
||||||
if (a2 == NULL) {
|
if (a2 == NULL) {
|
||||||
a2 = gDude;
|
a2 = gDude;
|
||||||
|
@ -1045,7 +1140,7 @@ void _ai_run_away(Object* a1, Object* a2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42899C
|
// 0x42899C
|
||||||
int _ai_move_away(Object* a1, Object* a2, int a3)
|
static int _ai_move_away(Object* a1, Object* a2, int a3)
|
||||||
{
|
{
|
||||||
if (aiGetPacket(a1)->distance == DISTANCE_STAY) {
|
if (aiGetPacket(a1)->distance == DISTANCE_STAY) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1091,7 +1186,7 @@ int _ai_move_away(Object* a1, Object* a2, int a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428AC4
|
// 0x428AC4
|
||||||
bool _ai_find_friend(Object* a1, int a2, int a3)
|
static bool _ai_find_friend(Object* a1, int a2, int a3)
|
||||||
{
|
{
|
||||||
Object* v1 = _ai_find_nearest_team(a1, a1, 1);
|
Object* v1 = _ai_find_nearest_team(a1, a1, 1);
|
||||||
if (v1 == NULL) {
|
if (v1 == NULL) {
|
||||||
|
@ -1114,7 +1209,7 @@ bool _ai_find_friend(Object* a1, int a2, int a3)
|
||||||
// Compare objects by distance to origin.
|
// Compare objects by distance to origin.
|
||||||
//
|
//
|
||||||
// 0x428B1C
|
// 0x428B1C
|
||||||
int _compare_nearer(const void* a1, const void* a2)
|
static int _compare_nearer(const void* a1, const void* a2)
|
||||||
{
|
{
|
||||||
Object* v1 = *(Object**)a1;
|
Object* v1 = *(Object**)a1;
|
||||||
Object* v2 = *(Object**)a2;
|
Object* v2 = *(Object**)a2;
|
||||||
|
@ -1145,7 +1240,7 @@ int _compare_nearer(const void* a1, const void* a2)
|
||||||
// qsort compare function - melee then ranged.
|
// qsort compare function - melee then ranged.
|
||||||
//
|
//
|
||||||
// 0x428B8C
|
// 0x428B8C
|
||||||
int _compare_strength(const void* p1, const void* p2)
|
static int _compare_strength(const void* p1, const void* p2)
|
||||||
{
|
{
|
||||||
Object* a1 = *(Object**)p1;
|
Object* a1 = *(Object**)p1;
|
||||||
Object* a2 = *(Object**)p2;
|
Object* a2 = *(Object**)p2;
|
||||||
|
@ -1179,7 +1274,7 @@ int _compare_strength(const void* p1, const void* p2)
|
||||||
// qsort compare unction - ranged then melee
|
// qsort compare unction - ranged then melee
|
||||||
//
|
//
|
||||||
// 0x428BE4
|
// 0x428BE4
|
||||||
int _compare_weakness(const void* p1, const void* p2)
|
static int _compare_weakness(const void* p1, const void* p2)
|
||||||
{
|
{
|
||||||
Object* a1 = *(Object**)p1;
|
Object* a1 = *(Object**)p1;
|
||||||
Object* a2 = *(Object**)p2;
|
Object* a2 = *(Object**)p2;
|
||||||
|
@ -1211,7 +1306,7 @@ int _compare_weakness(const void* p1, const void* p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428C3C
|
// 0x428C3C
|
||||||
Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3)
|
static Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Object* obj;
|
Object* obj;
|
||||||
|
@ -1238,7 +1333,7 @@ Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428CF4
|
// 0x428CF4
|
||||||
Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3)
|
static Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3)
|
||||||
{
|
{
|
||||||
if (a2 == NULL) {
|
if (a2 == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1269,7 +1364,7 @@ Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x428DB0
|
// 0x428DB0
|
||||||
int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4)
|
static int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4)
|
||||||
{
|
{
|
||||||
if (a2 != NULL) {
|
if (a2 != NULL) {
|
||||||
*a2 = NULL;
|
*a2 = NULL;
|
||||||
|
@ -1336,7 +1431,7 @@ int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4)
|
||||||
|
|
||||||
// ai_danger_source
|
// ai_danger_source
|
||||||
// 0x428F4C
|
// 0x428F4C
|
||||||
Object* _ai_danger_source(Object* a1)
|
static Object* _ai_danger_source(Object* a1)
|
||||||
{
|
{
|
||||||
if (a1 == NULL) {
|
if (a1 == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1525,7 +1620,7 @@ void _caiTeamCombatExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x4292D4
|
// 0x4292D4
|
||||||
int _ai_have_ammo(Object* critter_obj, Object* weapon_obj, Object** out_ammo_obj)
|
static int _ai_have_ammo(Object* critter_obj, Object* weapon_obj, Object** out_ammo_obj)
|
||||||
{
|
{
|
||||||
int v9;
|
int v9;
|
||||||
Object* ammo_obj;
|
Object* ammo_obj;
|
||||||
|
@ -1566,7 +1661,7 @@ int _ai_have_ammo(Object* critter_obj, Object* weapon_obj, Object** out_ammo_obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42938C
|
// 0x42938C
|
||||||
bool _caiHasWeapPrefType(AiPacket* ai, int attackType)
|
static bool _caiHasWeapPrefType(AiPacket* ai, int attackType)
|
||||||
{
|
{
|
||||||
int bestWeapon = ai->best_weapon + 1;
|
int bestWeapon = ai->best_weapon + 1;
|
||||||
|
|
||||||
|
@ -1580,7 +1675,7 @@ bool _caiHasWeapPrefType(AiPacket* ai, int attackType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x4293BC
|
// 0x4293BC
|
||||||
Object* _ai_best_weapon(Object* attacker, Object* weapon1, Object* weapon2, Object* defender)
|
static Object* _ai_best_weapon(Object* attacker, Object* weapon1, Object* weapon2, Object* defender)
|
||||||
{
|
{
|
||||||
if (attacker == NULL) {
|
if (attacker == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1732,7 +1827,7 @@ Object* _ai_best_weapon(Object* attacker, Object* weapon1, Object* weapon2, Obje
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x4298EC
|
// 0x4298EC
|
||||||
bool _ai_can_use_weapon(Object* critter, Object* weapon, int hitMode)
|
static bool _ai_can_use_weapon(Object* critter, Object* weapon, int hitMode)
|
||||||
{
|
{
|
||||||
int damageFlags = critter->data.critter.combat.results;
|
int damageFlags = critter->data.critter.combat.results;
|
||||||
if ((damageFlags & DAM_CRIP_ARM_LEFT) != 0 && (damageFlags & DAM_CRIP_ARM_RIGHT) != 0) {
|
if ((damageFlags & DAM_CRIP_ARM_LEFT) != 0 && (damageFlags & DAM_CRIP_ARM_RIGHT) != 0) {
|
||||||
|
@ -1865,7 +1960,7 @@ Object* _ai_search_inven_armor(Object* critter)
|
||||||
// and the iteam is a something healing.
|
// and the iteam is a something healing.
|
||||||
//
|
//
|
||||||
// 0x429B44
|
// 0x429B44
|
||||||
bool aiCanUseItem(Object* critter, Object* item)
|
static bool aiCanUseItem(Object* critter, Object* item)
|
||||||
{
|
{
|
||||||
if (critter == NULL) {
|
if (critter == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1916,7 +2011,7 @@ bool aiCanUseItem(Object* critter, Object* item)
|
||||||
// Find best item type to use?
|
// Find best item type to use?
|
||||||
//
|
//
|
||||||
// 0x429C18
|
// 0x429C18
|
||||||
Object* _ai_search_environ(Object* critter, int itemType)
|
static Object* _ai_search_environ(Object* critter, int itemType)
|
||||||
{
|
{
|
||||||
if (critterGetBodyType(critter) != BODY_TYPE_BIPED) {
|
if (critterGetBodyType(critter) != BODY_TYPE_BIPED) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1975,7 +2070,7 @@ Object* _ai_search_environ(Object* critter, int itemType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x429D60
|
// 0x429D60
|
||||||
Object* _ai_retrieve_object(Object* a1, Object* a2)
|
static Object* _ai_retrieve_object(Object* a1, Object* a2)
|
||||||
{
|
{
|
||||||
if (actionPickUp(a1, a2) != 0) {
|
if (actionPickUp(a1, a2) != 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1996,7 +2091,7 @@ Object* _ai_retrieve_object(Object* a1, Object* a2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x429DB4
|
// 0x429DB4
|
||||||
int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3)
|
static int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3)
|
||||||
{
|
{
|
||||||
if (a2 == NULL) {
|
if (a2 == NULL) {
|
||||||
return HIT_MODE_PUNCH;
|
return HIT_MODE_PUNCH;
|
||||||
|
@ -2074,7 +2169,7 @@ int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x429FC8
|
// 0x429FC8
|
||||||
int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4)
|
static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4)
|
||||||
{
|
{
|
||||||
if (actionPoints <= 0) {
|
if (actionPoints <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2166,7 +2261,7 @@ int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A1D4
|
// 0x42A1D4
|
||||||
int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
|
static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
|
||||||
{
|
{
|
||||||
if (a1 == NULL) {
|
if (a1 == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2252,7 +2347,7 @@ int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A410
|
// 0x42A410
|
||||||
int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int tile)
|
static int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int tile)
|
||||||
{
|
{
|
||||||
if (a1->field_340 <= 0) {
|
if (a1->field_340 <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2278,7 +2373,7 @@ int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int tile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A518
|
// 0x42A518
|
||||||
bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance)
|
static bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance)
|
||||||
{
|
{
|
||||||
int hitMode = HIT_MODE_RIGHT_WEAPON_PRIMARY;
|
int hitMode = HIT_MODE_RIGHT_WEAPON_PRIMARY;
|
||||||
bool aiming = false;
|
bool aiming = false;
|
||||||
|
@ -2307,7 +2402,7 @@ bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A5B8
|
// 0x42A5B8
|
||||||
int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4)
|
static int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4)
|
||||||
{
|
{
|
||||||
*weapon = NULL;
|
*weapon = NULL;
|
||||||
*hitMode = HIT_MODE_PUNCH;
|
*hitMode = HIT_MODE_PUNCH;
|
||||||
|
@ -2345,7 +2440,7 @@ int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A670
|
// 0x42A670
|
||||||
int _ai_called_shot(Object* a1, Object* a2, int a3)
|
static int _ai_called_shot(Object* a1, Object* a2, int a3)
|
||||||
{
|
{
|
||||||
AiPacket* ai;
|
AiPacket* ai;
|
||||||
int v5;
|
int v5;
|
||||||
|
@ -2386,7 +2481,7 @@ int _ai_called_shot(Object* a1, Object* a2, int a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A748
|
// 0x42A748
|
||||||
int _ai_attack(Object* a1, Object* a2, int a3)
|
static int _ai_attack(Object* a1, Object* a2, int a3)
|
||||||
{
|
{
|
||||||
int v6;
|
int v6;
|
||||||
|
|
||||||
|
@ -2410,7 +2505,7 @@ int _ai_attack(Object* a1, Object* a2, int a3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42A7D8
|
// 0x42A7D8
|
||||||
int _ai_try_attack(Object* a1, Object* a2)
|
static int _ai_try_attack(Object* a1, Object* a2)
|
||||||
{
|
{
|
||||||
_critter_set_who_hit_me(a1, a2);
|
_critter_set_who_hit_me(a1, a2);
|
||||||
|
|
||||||
|
@ -2729,7 +2824,7 @@ int _cai_perform_distance_prefs(Object* a1, Object* a2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42B100
|
// 0x42B100
|
||||||
int _cai_get_min_hp(AiPacket* ai)
|
static int _cai_get_min_hp(AiPacket* ai)
|
||||||
{
|
{
|
||||||
if (ai == NULL) {
|
if (ai == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3070,7 +3165,7 @@ int _combatai_msg(Object* a1, Attack* attack, int type, int delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42B80C
|
// 0x42B80C
|
||||||
int _ai_print_msg(Object* critter, int type)
|
static int _ai_print_msg(Object* critter, int type)
|
||||||
{
|
{
|
||||||
if (textObjectsGetCount() > 0) {
|
if (textObjectsGetCount() > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3138,7 +3233,7 @@ Object* _combat_ai_random_target(Attack* attack)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x42B90C
|
// 0x42B90C
|
||||||
int _combatai_rating(Object* obj)
|
static int _combatai_rating(Object* obj)
|
||||||
{
|
{
|
||||||
int melee_damage;
|
int melee_damage;
|
||||||
Object* item;
|
Object* item;
|
||||||
|
@ -3246,7 +3341,7 @@ bool objectCanHearObject(Object* a1, Object* a2)
|
||||||
// Load combatai.msg and apply language filter.
|
// Load combatai.msg and apply language filter.
|
||||||
//
|
//
|
||||||
// 0x42BB34
|
// 0x42BB34
|
||||||
int aiMessageListInit()
|
static int aiMessageListInit()
|
||||||
{
|
{
|
||||||
if (!messageListInit(&gCombatAiMessageList)) {
|
if (!messageListInit(&gCombatAiMessageList)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -3272,7 +3367,7 @@ int aiMessageListInit()
|
||||||
// NOTE: Inlined.
|
// NOTE: Inlined.
|
||||||
//
|
//
|
||||||
// 0x42BBD8
|
// 0x42BBD8
|
||||||
int aiMessageListFree()
|
static int aiMessageListFree()
|
||||||
{
|
{
|
||||||
if (!messageListFree(&gCombatAiMessageList)) {
|
if (!messageListFree(&gCombatAiMessageList)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
111
src/combat_ai.h
111
src/combat_ai.h
|
@ -4,11 +4,7 @@
|
||||||
#include "combat_ai_defs.h"
|
#include "combat_ai_defs.h"
|
||||||
#include "combat_defs.h"
|
#include "combat_defs.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "message.h"
|
|
||||||
#include "obj_types.h"
|
#include "obj_types.h"
|
||||||
#include "party_member.h"
|
|
||||||
|
|
||||||
#define AI_PACKET_CHEM_PRIMARY_DESIRE_COUNT (3)
|
|
||||||
|
|
||||||
typedef enum AiMessageType {
|
typedef enum AiMessageType {
|
||||||
AI_MESSAGE_TYPE_RUN,
|
AI_MESSAGE_TYPE_RUN,
|
||||||
|
@ -18,60 +14,6 @@ typedef enum AiMessageType {
|
||||||
AI_MESSAGE_TYPE_HIT,
|
AI_MESSAGE_TYPE_HIT,
|
||||||
} AiMessageType;
|
} AiMessageType;
|
||||||
|
|
||||||
typedef struct AiMessageRange {
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
} AiMessageRange;
|
|
||||||
|
|
||||||
typedef struct AiPacket {
|
|
||||||
char* name;
|
|
||||||
int packet_num;
|
|
||||||
int max_dist;
|
|
||||||
int min_to_hit;
|
|
||||||
int min_hp;
|
|
||||||
int aggression;
|
|
||||||
int hurt_too_much;
|
|
||||||
int secondary_freq;
|
|
||||||
int called_freq;
|
|
||||||
int font;
|
|
||||||
int color;
|
|
||||||
int outline_color;
|
|
||||||
int chance;
|
|
||||||
AiMessageRange run;
|
|
||||||
AiMessageRange move;
|
|
||||||
AiMessageRange attack;
|
|
||||||
AiMessageRange miss;
|
|
||||||
AiMessageRange hit[HIT_LOCATION_SPECIFIC_COUNT];
|
|
||||||
int area_attack_mode;
|
|
||||||
int run_away_mode;
|
|
||||||
int best_weapon;
|
|
||||||
int distance;
|
|
||||||
int attack_who;
|
|
||||||
int chem_use;
|
|
||||||
int chem_primary_desire[AI_PACKET_CHEM_PRIMARY_DESIRE_COUNT];
|
|
||||||
int disposition;
|
|
||||||
char* body_type;
|
|
||||||
char* general_type;
|
|
||||||
} AiPacket;
|
|
||||||
|
|
||||||
typedef struct STRUCT_832 {
|
|
||||||
Object* field_0;
|
|
||||||
Object* field_4;
|
|
||||||
Object* field_8[100];
|
|
||||||
int field_198[100];
|
|
||||||
int field_328;
|
|
||||||
int field_32C;
|
|
||||||
int field_330;
|
|
||||||
int field_334;
|
|
||||||
int* field_338;
|
|
||||||
int field_33C;
|
|
||||||
int field_340;
|
|
||||||
} STRUCT_832;
|
|
||||||
|
|
||||||
extern Object* _combat_obj;
|
|
||||||
extern int gAiPacketsLength;
|
|
||||||
extern AiPacket* gAiPackets;
|
|
||||||
extern bool gAiInitialized;
|
|
||||||
extern const char* gAreaAttackModeKeys[AREA_ATTACK_MODE_COUNT];
|
extern const char* gAreaAttackModeKeys[AREA_ATTACK_MODE_COUNT];
|
||||||
extern const char* gAttackWhoKeys[ATTACK_WHO_COUNT];
|
extern const char* gAttackWhoKeys[ATTACK_WHO_COUNT];
|
||||||
extern const char* gBestWeaponKeys[BEST_WEAPON_COUNT];
|
extern const char* gBestWeaponKeys[BEST_WEAPON_COUNT];
|
||||||
|
@ -80,32 +22,12 @@ extern const char* gDistanceModeKeys[DISTANCE_COUNT];
|
||||||
extern const char* gRunAwayModeKeys[RUN_AWAY_MODE_COUNT];
|
extern const char* gRunAwayModeKeys[RUN_AWAY_MODE_COUNT];
|
||||||
extern const char* gDispositionKeys[DISPOSITION_COUNT];
|
extern const char* gDispositionKeys[DISPOSITION_COUNT];
|
||||||
extern const char* gHurtTooMuchKeys[HURT_COUNT];
|
extern const char* gHurtTooMuchKeys[HURT_COUNT];
|
||||||
extern const int _rmatchHurtVals[5];
|
|
||||||
extern const int _hp_run_away_value[6];
|
|
||||||
extern Object* _attackerTeamObj;
|
|
||||||
extern Object* _targetTeamObj;
|
|
||||||
extern const int _weapPrefOrderings[BEST_WEAPON_COUNT + 1][5];
|
|
||||||
extern const int _aiPartyMemberDistances[DISTANCE_COUNT];
|
|
||||||
extern int gLanguageFilter;
|
|
||||||
|
|
||||||
extern MessageList gCombatAiMessageList;
|
|
||||||
extern char _target_str[260];
|
|
||||||
extern int _curr_crit_num;
|
|
||||||
extern Object** _curr_crit_list;
|
|
||||||
extern char _attack_str[268];
|
|
||||||
|
|
||||||
void _parse_hurt_str(char* str, int* out_value);
|
|
||||||
int _cai_match_str_to_list(const char* str, const char** list, int count, int* out_value);
|
|
||||||
void aiPacketInit(AiPacket* ai);
|
|
||||||
int aiInit();
|
int aiInit();
|
||||||
void aiReset();
|
void aiReset();
|
||||||
int aiExit();
|
int aiExit();
|
||||||
int aiLoad(File* stream);
|
int aiLoad(File* stream);
|
||||||
int aiSave(File* stream);
|
int aiSave(File* stream);
|
||||||
int aiPacketRead(File* stream, AiPacket* ai);
|
|
||||||
int aiPacketWrite(File* stream, AiPacket* ai);
|
|
||||||
AiPacket* aiGetPacket(Object* obj);
|
|
||||||
AiPacket* aiGetPacketByNum(int aiPacketNum);
|
|
||||||
int aiGetAreaAttackMode(Object* obj);
|
int aiGetAreaAttackMode(Object* obj);
|
||||||
int aiGetRunAwayMode(Object* obj);
|
int aiGetRunAwayMode(Object* obj);
|
||||||
int aiGetBestWeapon(Object* obj);
|
int aiGetBestWeapon(Object* obj);
|
||||||
|
@ -120,58 +42,25 @@ int aiSetAttackWho(Object* critter, int attackWho);
|
||||||
int aiSetChemUse(Object* critter, int chemUse);
|
int aiSetChemUse(Object* critter, int chemUse);
|
||||||
int aiGetDisposition(Object* obj);
|
int aiGetDisposition(Object* obj);
|
||||||
int aiSetDisposition(Object* obj, int a2);
|
int aiSetDisposition(Object* obj, int a2);
|
||||||
int _ai_magic_hands(Object* a1, Object* a2, int num);
|
|
||||||
int _ai_check_drugs(Object* critter);
|
|
||||||
void _ai_run_away(Object* a1, Object* a2);
|
|
||||||
int _ai_move_away(Object* a1, Object* a2, int a3);
|
|
||||||
bool _ai_find_friend(Object* a1, int a2, int a3);
|
|
||||||
int _compare_nearer(const void* a1, const void* a2);
|
|
||||||
int _compare_strength(const void* p1, const void* p2);
|
|
||||||
int _compare_weakness(const void* p1, const void* p2);
|
|
||||||
Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3);
|
|
||||||
Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3);
|
|
||||||
int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4);
|
|
||||||
Object* _ai_danger_source(Object* a1);
|
|
||||||
int _caiSetupTeamCombat(Object* a1, Object* a2);
|
int _caiSetupTeamCombat(Object* a1, Object* a2);
|
||||||
int _caiTeamCombatInit(Object** a1, int a2);
|
int _caiTeamCombatInit(Object** a1, int a2);
|
||||||
void _caiTeamCombatExit();
|
void _caiTeamCombatExit();
|
||||||
int _ai_have_ammo(Object* critter_obj, Object* weapon_obj, Object** out_ammo_obj);
|
|
||||||
bool _caiHasWeapPrefType(AiPacket* ai, int attackType);
|
|
||||||
Object* _ai_best_weapon(Object* a1, Object* a2, Object* a3, Object* a4);
|
|
||||||
bool _ai_can_use_weapon(Object* critter, Object* weapon, int hitMode);
|
|
||||||
Object* _ai_search_inven_weap(Object* critter, int a2, Object* a3);
|
Object* _ai_search_inven_weap(Object* critter, int a2, Object* a3);
|
||||||
Object* _ai_search_inven_armor(Object* critter);
|
Object* _ai_search_inven_armor(Object* critter);
|
||||||
bool aiCanUseItem(Object* obj, Object* a2);
|
|
||||||
Object* _ai_search_environ(Object* critter, int itemType);
|
|
||||||
Object* _ai_retrieve_object(Object* a1, Object* a2);
|
|
||||||
int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3);
|
|
||||||
int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4);
|
|
||||||
int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3);
|
|
||||||
int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int a2);
|
|
||||||
bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance);
|
|
||||||
int _ai_switch_weapons(Object* a1, int* hitMode, Object** weapon, Object* a4);
|
|
||||||
int _ai_called_shot(Object* a1, Object* a2, int a3);
|
|
||||||
int _ai_attack(Object* a1, Object* a2, int a3);
|
|
||||||
int _ai_try_attack(Object* a1, Object* a2);
|
|
||||||
int _cAIPrepWeaponItem(Object* critter, Object* item);
|
int _cAIPrepWeaponItem(Object* critter, Object* item);
|
||||||
void _cai_attempt_w_reload(Object* critter_obj, int a2);
|
void _cai_attempt_w_reload(Object* critter_obj, int a2);
|
||||||
void _combat_ai_begin(int a1, void* a2);
|
void _combat_ai_begin(int a1, void* a2);
|
||||||
void _combat_ai_over();
|
void _combat_ai_over();
|
||||||
int _cai_perform_distance_prefs(Object* a1, Object* a2);
|
int _cai_perform_distance_prefs(Object* a1, Object* a2);
|
||||||
int _cai_get_min_hp(AiPacket* ai);
|
|
||||||
void _combat_ai(Object* a1, Object* a2);
|
void _combat_ai(Object* a1, Object* a2);
|
||||||
bool _combatai_want_to_join(Object* a1);
|
bool _combatai_want_to_join(Object* a1);
|
||||||
bool _combatai_want_to_stop(Object* a1);
|
bool _combatai_want_to_stop(Object* a1);
|
||||||
int critterSetTeam(Object* obj, int team);
|
int critterSetTeam(Object* obj, int team);
|
||||||
int critterSetAiPacket(Object* object, int aiPacket);
|
int critterSetAiPacket(Object* object, int aiPacket);
|
||||||
int _combatai_msg(Object* a1, Attack* attack, int a3, int a4);
|
int _combatai_msg(Object* a1, Attack* attack, int a3, int a4);
|
||||||
int _ai_print_msg(Object* critter, int type);
|
|
||||||
Object* _combat_ai_random_target(Attack* attack);
|
Object* _combat_ai_random_target(Attack* attack);
|
||||||
int _combatai_rating(Object* obj);
|
|
||||||
int _combatai_check_retaliation(Object* a1, Object* a2);
|
int _combatai_check_retaliation(Object* a1, Object* a2);
|
||||||
bool objectCanHearObject(Object* a1, Object* a2);
|
bool objectCanHearObject(Object* a1, Object* a2);
|
||||||
int aiMessageListInit();
|
|
||||||
int aiMessageListFree();
|
|
||||||
void aiMessageListReloadIfNeeded();
|
void aiMessageListReloadIfNeeded();
|
||||||
void _combatai_notify_onlookers(Object* a1);
|
void _combatai_notify_onlookers(Object* a1);
|
||||||
void _combatai_notify_friends(Object* a1);
|
void _combatai_notify_friends(Object* a1);
|
||||||
|
|
Loading…
Reference in New Issue