Reconcile with reference edition

This commit is contained in:
Alexander Batalov 2022-08-02 13:31:26 +03:00
parent 66d46bd8a5
commit df5bceaf2a
5 changed files with 119 additions and 123 deletions

View File

@ -46,8 +46,15 @@
#define CALLED_SHOT_WINDOW_WIDTH (504)
#define CALLED_SHOT_WINDOW_HEIGHT (309)
typedef struct CombatAiInfo {
Object* friendlyDead;
Object* lastTarget;
Object* lastItem;
int lastMove;
} CombatAiInfo;
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6);
static int _combatCopyAIInfo(int a1, int a2);
static int aiInfoCopy(int srcIndex, int destIndex);
static void _combat_begin(Object* a1);
static void _combat_begin_extra(Object* a1);
static void _combat_over();
@ -96,7 +103,7 @@ int _combatNumTurns = 0;
unsigned int gCombatState = COMBAT_STATE_0x02;
// 0x510948
static CombatAIInfo* _aiInfoList = NULL;
static CombatAiInfo* _aiInfoList = NULL;
// 0x51094C
static STRUCT_664980* _gcsd = NULL;
@ -1989,7 +1996,6 @@ int _find_cid(int a1, int cid, Object** critterList, int critterListLength)
int combatLoad(File* stream)
{
int v14;
CombatAIInfo* ptr;
int a2;
Object* obj;
int v24;
@ -2071,42 +2077,42 @@ int combatLoad(File* stream)
internal_free(_aiInfoList);
}
_aiInfoList = (CombatAIInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
_aiInfoList = (CombatAiInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
if (_aiInfoList == NULL) {
return -1;
}
for (v14 = 0; v14 < _list_total; v14++) {
ptr = &(_aiInfoList[v14]);
CombatAiInfo* aiInfo = &(_aiInfoList[v14]);
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->friendlyDead = NULL;
aiInfo->friendlyDead = NULL;
} else {
ptr->friendlyDead = objectFindById(a2);
if (ptr->friendlyDead == NULL) return -1;
aiInfo->friendlyDead = objectFindById(a2);
if (aiInfo->friendlyDead == NULL) return -1;
}
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->lastTarget = NULL;
aiInfo->lastTarget = NULL;
} else {
ptr->lastTarget = objectFindById(a2);
if (ptr->lastTarget == NULL) return -1;
aiInfo->lastTarget = objectFindById(a2);
if (aiInfo->lastTarget == NULL) return -1;
}
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->lastItem = NULL;
aiInfo->lastItem = NULL;
} else {
ptr->lastItem = objectFindById(a2);
if (ptr->lastItem == NULL) return -1;
aiInfo->lastItem = objectFindById(a2);
if (aiInfo->lastItem == NULL) return -1;
}
if (fileReadInt32(stream, &(ptr->lastMove)) == -1) return -1;
if (fileReadInt32(stream, &(aiInfo->lastMove)) == -1) return -1;
}
_combat_begin_extra(gDude);
@ -2138,12 +2144,12 @@ int combatSave(File* stream)
}
for (int index = 0; index < _list_total; index++) {
CombatAIInfo* ptr = &(_aiInfoList[index]);
CombatAiInfo* aiInfo = &(_aiInfoList[index]);
if (fileWriteInt32(stream, ptr->friendlyDead != NULL ? ptr->friendlyDead->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastTarget != NULL ? ptr->lastTarget->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastItem != NULL ? ptr->lastItem->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastMove) == -1) return -1;
if (fileWriteInt32(stream, aiInfo->friendlyDead != NULL ? aiInfo->friendlyDead->id : -1) == -1) return -1;
if (fileWriteInt32(stream, aiInfo->lastTarget != NULL ? aiInfo->lastTarget->id : -1) == -1) return -1;
if (fileWriteInt32(stream, aiInfo->lastItem != NULL ? aiInfo->lastItem->id : -1) == -1) return -1;
if (fileWriteInt32(stream, aiInfo->lastMove) == -1) return -1;
}
return 0;
@ -2283,24 +2289,21 @@ void _combat_data_init(Object* obj)
}
// 0x421850
static int _combatCopyAIInfo(int a1, int a2)
static int aiInfoCopy(int srcIndex, int destIndex)
{
CombatAIInfo* v3;
CombatAIInfo* v4;
CombatAiInfo* src = &_aiInfoList[srcIndex];
CombatAiInfo* dest = &_aiInfoList[destIndex];
v3 = &_aiInfoList[a1];
v4 = &_aiInfoList[a2];
v4->friendlyDead = v3->friendlyDead;
v4->lastTarget = v3->lastTarget;
v4->lastItem = v3->lastItem;
v4->lastMove = v3->lastMove;
dest->friendlyDead = src->friendlyDead;
dest->lastTarget = src->lastTarget;
dest->lastItem = src->lastItem;
dest->lastMove = src->lastMove;
return 0;
}
// 0x421880
Object* _combatAIInfoGetFriendlyDead(Object* obj)
Object* aiInfoGetFriendlyDead(Object* obj)
{
if (!isInCombat()) {
return NULL;
@ -2318,7 +2321,7 @@ Object* _combatAIInfoGetFriendlyDead(Object* obj)
}
// 0x4218AC
int _combatAIInfoSetFriendlyDead(Object* a1, Object* a2)
int aiInfoSetFriendlyDead(Object* a1, Object* a2)
{
if (!isInCombat()) {
return 0;
@ -2342,7 +2345,7 @@ int _combatAIInfoSetFriendlyDead(Object* a1, Object* a2)
}
// 0x4218EC
Object* _combatAIInfoGetLastTarget(Object* obj)
Object* aiInfoGetLastTarget(Object* obj)
{
if (!isInCombat()) {
return NULL;
@ -2360,7 +2363,7 @@ Object* _combatAIInfoGetLastTarget(Object* obj)
}
// 0x421918
int _combatAIInfoSetLastTarget(Object* a1, Object* a2)
int aiInfoSetLastTarget(Object* a1, Object* a2)
{
if (!isInCombat()) {
return 0;
@ -2388,7 +2391,7 @@ int _combatAIInfoSetLastTarget(Object* a1, Object* a2)
}
// 0x42196C
Object* _combatAIInfoGetLastItem(Object* obj)
Object* aiInfoGetLastItem(Object* obj)
{
int v1;
@ -2409,7 +2412,7 @@ Object* _combatAIInfoGetLastItem(Object* obj)
}
// 0x421998
int _combatAIInfoSetLastItem(Object* obj, Object* a2)
int aiInfoSetLastItem(Object* obj, Object* a2)
{
int v2;
@ -2446,17 +2449,17 @@ static void _combat_begin(Object* a1)
_list_total = objectListCreate(-1, _combat_elev, OBJ_TYPE_CRITTER, &_combat_list);
_list_noncom = _list_total;
_list_com = 0;
_aiInfoList = (CombatAIInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
_aiInfoList = (CombatAiInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
if (_aiInfoList == NULL) {
return;
}
for (int index = 0; index < _list_total; index++) {
CombatAIInfo* ptr = &(_aiInfoList[index]);
ptr->friendlyDead = NULL;
ptr->lastTarget = NULL;
ptr->lastItem = NULL;
ptr->lastMove = 0;
CombatAiInfo* aiInfo = &(_aiInfoList[index]);
aiInfo->friendlyDead = NULL;
aiInfo->lastTarget = NULL;
aiInfo->lastItem = NULL;
aiInfo->lastMove = 0;
}
Object* v1 = NULL;
@ -3393,7 +3396,7 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
_combat_call_display = 1;
_combat_cleanup_enabled = 1;
_combatAIInfoSetLastTarget(a1, a2);
aiInfoSetLastTarget(a1, a2);
debugPrint("running attack...\n");
return 0;
@ -5791,7 +5794,7 @@ void _combat_delete_critter(Object* obj)
while (i < (_list_total - 1)) {
_combat_list[i] = _combat_list[i + 1];
_combatCopyAIInfo(i + 1, i);
aiInfoCopy(i + 1, i);
i++;
}

View File

@ -21,12 +21,12 @@ bool _combat_safety_invalidate_weapon(Object* a1, Object* a2, int hitMode, Objec
bool _combatTestIncidentalHit(Object* a1, Object* a2, Object* a3, Object* a4);
Object* _combat_whose_turn();
void _combat_data_init(Object* obj);
Object* _combatAIInfoGetFriendlyDead(Object* obj);
int _combatAIInfoSetFriendlyDead(Object* a1, Object* a2);
Object* _combatAIInfoGetLastTarget(Object* obj);
int _combatAIInfoSetLastTarget(Object* a1, Object* a2);
Object* _combatAIInfoGetLastItem(Object* obj);
int _combatAIInfoSetLastItem(Object* obj, Object* a2);
Object* aiInfoGetFriendlyDead(Object* obj);
int aiInfoSetFriendlyDead(Object* a1, Object* a2);
Object* aiInfoGetLastTarget(Object* obj);
int aiInfoSetLastTarget(Object* a1, Object* a2);
Object* aiInfoGetLastItem(Object* obj);
int aiInfoSetLastItem(Object* obj, Object* a2);
void _combat_update_critter_outline_for_los(Object* critter, bool a2);
void _combat_over_from_load();
void _combat_give_exps(int exp_points);

View File

@ -72,19 +72,19 @@ typedef struct AiPacket {
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;
typedef struct AiRetargetData {
Object* source;
Object* target;
Object* critterList[100];
int ratingList[100];
int critterCount;
int sourceTeam;
int sourceRating;
bool notSameTile;
int* tiles;
int currentTileIndex;
int sourceIntelligence;
} AiRetargetData;
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);
@ -114,8 +114,8 @@ 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 int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int* tilePtr);
static int _cai_retargetTileFromFriendlyFireSubFunc(AiRetargetData* aiRetargetData, int tile);
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);
@ -939,7 +939,7 @@ static int _ai_check_drugs(Object* critter)
int v25 = 0;
int v28 = 0;
int v29 = 0;
Object* v3 = _combatAIInfoGetLastItem(critter);
Object* v3 = aiInfoGetLastItem(critter);
if (v3 == NULL) {
AiPacket* ai = aiGetPacket(critter);
if (ai == NULL) {
@ -1467,7 +1467,7 @@ static Object* _ai_danger_source(Object* a1)
attackWho = aiGetPacket(a1)->attack_who;
switch (attackWho) {
case ATTACK_WHO_WHOMEVER_ATTACKING_ME: {
Object* candidate = _combatAIInfoGetLastTarget(gDude);
Object* candidate = aiInfoGetLastTarget(gDude);
if (candidate == NULL || a1->data.critter.combat.team == candidate->data.critter.combat.team) {
break;
}
@ -2086,7 +2086,7 @@ static Object* _ai_retrieve_object(Object* a1, Object* a2)
a2 = NULL;
}
_combatAIInfoSetLastItem(v3, a2);
aiInfoSetLastItem(v3, a2);
return v3;
}
@ -2262,21 +2262,21 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
}
// 0x42A1D4
static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
static int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int* tilePtr)
{
if (a1 == NULL) {
if (source == NULL) {
return -1;
}
if (a2 == NULL) {
if (target == NULL) {
return -1;
}
if (a3 == NULL) {
if (tilePtr == NULL) {
return -1;
}
if (*a3 == -1) {
if (*tilePtr == -1) {
return -1;
}
@ -2286,16 +2286,16 @@ static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
int tiles[32];
STRUCT_832 v1;
v1.field_0 = a1;
v1.field_4 = a2;
v1.field_32C = a1->data.critter.combat.team;
v1.field_330 = _combatai_rating(a1);
v1.field_328 = 0;
v1.field_338 = tiles;
v1.field_334 = *a3 != a1->tile;
v1.field_33C = 0;
v1.field_340 = critterGetStat(a1, STAT_INTELLIGENCE);
AiRetargetData aiRetargetData;
aiRetargetData.source = source;
aiRetargetData.target = target;
aiRetargetData.sourceTeam = source->data.critter.combat.team;
aiRetargetData.sourceRating = _combatai_rating(source);
aiRetargetData.critterCount = 0;
aiRetargetData.tiles = tiles;
aiRetargetData.notSameTile = *tilePtr != source->tile;
aiRetargetData.currentTileIndex = 0;
aiRetargetData.sourceIntelligence = critterGetStat(source, STAT_INTELLIGENCE);
for (int index = 0; index < 32; index++) {
tiles[index] = -1;
@ -2304,23 +2304,23 @@ static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
for (int index = 0; index < _curr_crit_num; index++) {
Object* obj = _curr_crit_list[index];
if ((obj->data.critter.combat.results & DAM_DEAD) == 0
&& obj->data.critter.combat.team == v1.field_32C
&& _combatAIInfoGetLastTarget(obj) == v1.field_4
&& obj != v1.field_0) {
int v10 = _combatai_rating(obj);
if (v10 >= v1.field_330) {
v1.field_8[v1.field_328] = obj;
v1.field_198[v1.field_328] = v10;
v1.field_328 += 1;
&& obj->data.critter.combat.team == aiRetargetData.sourceTeam
&& aiInfoGetLastTarget(obj) == aiRetargetData.target
&& obj != aiRetargetData.source) {
int rating = _combatai_rating(obj);
if (rating >= aiRetargetData.sourceRating) {
aiRetargetData.critterList[aiRetargetData.critterCount] = obj;
aiRetargetData.ratingList[aiRetargetData.critterCount] = rating;
aiRetargetData.critterCount += 1;
}
}
}
_combat_obj = a1;
_combat_obj = source;
qsort(v1.field_8, v1.field_328, sizeof(*v1.field_8), _compare_nearer);
qsort(aiRetargetData.critterList, aiRetargetData.critterCount, sizeof(*aiRetargetData.critterList), _compare_nearer);
if (_cai_retargetTileFromFriendlyFireSubFunc(&v1, *a3) == 0) {
if (_cai_retargetTileFromFriendlyFireSubFunc(&aiRetargetData, *tilePtr) == 0) {
int minDistance = 99999;
int minDistanceIndex = -1;
@ -2330,8 +2330,8 @@ static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
break;
}
if (_obj_blocking_at(NULL, tile, a1->elevation) == 0) {
int distance = tileDistanceBetween(*a3, tile);
if (_obj_blocking_at(NULL, tile, source->elevation) == 0) {
int distance = tileDistanceBetween(*tilePtr, tile);
if (distance < minDistance) {
minDistance = distance;
minDistanceIndex = index;
@ -2340,7 +2340,7 @@ static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
}
if (minDistanceIndex != -1) {
*a3 = tiles[minDistanceIndex];
*tilePtr = tiles[minDistanceIndex];
}
}
@ -2348,24 +2348,24 @@ static int _cai_retargetTileFromFriendlyFire(Object* a1, Object* a2, int* a3)
}
// 0x42A410
static int _cai_retargetTileFromFriendlyFireSubFunc(STRUCT_832* a1, int tile)
static int _cai_retargetTileFromFriendlyFireSubFunc(AiRetargetData* aiRetargetData, int tile)
{
if (a1->field_340 <= 0) {
if (aiRetargetData->sourceIntelligence <= 0) {
return 0;
}
int distance = 1;
for (int index = 0; index < a1->field_328; index++) {
Object* obj = a1->field_8[index];
if (_cai_attackWouldIntersect(obj, a1->field_4, a1->field_0, tile, &distance)) {
for (int index = 0; index < aiRetargetData->critterCount; index++) {
Object* obj = aiRetargetData->critterList[index];
if (_cai_attackWouldIntersect(obj, aiRetargetData->target, aiRetargetData->source, tile, &distance)) {
debugPrint("In the way!");
a1->field_338[a1->field_33C] = tileGetTileInDirection(tile, (obj->rotation + 1) % ROTATION_COUNT, distance);
a1->field_338[a1->field_33C + 1] = tileGetTileInDirection(tile, (obj->rotation + 5) % ROTATION_COUNT, distance);
aiRetargetData->tiles[aiRetargetData->currentTileIndex] = tileGetTileInDirection(tile, (obj->rotation + 1) % ROTATION_COUNT, distance);
aiRetargetData->tiles[aiRetargetData->currentTileIndex + 1] = tileGetTileInDirection(tile, (obj->rotation + 5) % ROTATION_COUNT, distance);
a1->field_340 -= 2;
a1->field_33C += 2;
aiRetargetData->sourceIntelligence -= 2;
aiRetargetData->currentTileIndex += 2;
break;
}
}
@ -2884,10 +2884,10 @@ void _combat_ai(Object* a1, Object* a2)
&& (a1->data.critter.combat.results & DAM_DEAD) == 0
&& a1->data.critter.combat.ap != 0
&& objectGetDistanceBetween(a1, a2) > ai->max_dist) {
Object* v13 = _combatAIInfoGetFriendlyDead(a1);
Object* v13 = aiInfoGetFriendlyDead(a1);
if (v13 != NULL) {
_ai_move_away(a1, v13, 10);
_combatAIInfoSetFriendlyDead(a1, NULL);
aiInfoSetFriendlyDead(a1, NULL);
} else {
int perception = critterGetStat(a1, STAT_PERCEPTION);
if (!_ai_find_friend(a1, perception * 2, 5)) {
@ -2900,10 +2900,10 @@ void _combat_ai(Object* a1, Object* a2)
Object* whoHitMe = combatData->whoHitMe;
if (whoHitMe != NULL) {
if ((whoHitMe->data.critter.combat.results & DAM_DEAD) == 0 && combatData->damageLastTurn > 0) {
Object* v16 = _combatAIInfoGetFriendlyDead(a1);
Object* v16 = aiInfoGetFriendlyDead(a1);
if (v16 != NULL) {
_ai_move_away(a1, v16, 10);
_combatAIInfoSetFriendlyDead(a1, NULL);
aiInfoSetFriendlyDead(a1, NULL);
} else {
const char* name = critterGetName(a1);
debugPrint("%s: FLEEING: Somebody is shooting at me that I can't see!");
@ -2913,11 +2913,11 @@ void _combat_ai(Object* a1, Object* a2)
}
}
Object* v18 = _combatAIInfoGetFriendlyDead(a1);
Object* v18 = aiInfoGetFriendlyDead(a1);
if (v18 != NULL) {
_ai_move_away(a1, v18, 10);
if (objectGetDistanceBetween(a1, v18) >= 10) {
_combatAIInfoSetFriendlyDead(a1, NULL);
aiInfoSetFriendlyDead(a1, NULL);
}
}
@ -3036,7 +3036,7 @@ int critterSetTeam(Object* obj, int team)
}
}
_combatAIInfoSetLastTarget(obj, NULL);
aiInfoSetLastTarget(obj, NULL);
if (isInCombat()) {
bool outlineWasEnabled = obj->outline != 0 && (obj->outline & OUTLINE_DISABLED) == 0;
@ -3408,7 +3408,7 @@ void _combatai_notify_onlookers(Object* a1)
if ((a1->data.critter.combat.results & DAM_DEAD) != 0) {
if (!objectCanHearObject(obj, obj->data.critter.combat.whoHitMe)) {
debugPrint("\nSomebody Died and I don't know why! Run!!!");
_combatAIInfoSetFriendlyDead(obj, a1);
aiInfoSetFriendlyDead(obj, a1);
}
}
}

View File

@ -84,13 +84,6 @@ typedef enum HitLocation {
HIT_LOCATION_SPECIFIC_COUNT = HIT_LOCATION_COUNT - 1,
} HitLocation;
typedef struct CombatAIInfo {
Object* friendlyDead;
Object* lastTarget;
Object* lastItem;
int lastMove;
} CombatAIInfo;
typedef struct STRUCT_664980 {
Object* attacker;
Object* defender;

View File

@ -4724,7 +4724,7 @@ static void opTerminateCombat(Program* program)
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
self->data.critter.combat.maneuver |= CRITTER_MANEUVER_STOP_ATTACKING;
self->data.critter.combat.whoHitMe = NULL;
_combatAIInfoSetLastTarget(self, NULL);
aiInfoSetLastTarget(self, NULL);
}
}
}
@ -4755,7 +4755,7 @@ static void opCritterStopAttacking(Program* program)
if (obj != NULL) {
obj->data.critter.combat.maneuver |= CRITTER_MANEUVER_STOP_ATTACKING;
obj->data.critter.combat.whoHitMe = NULL;
_combatAIInfoSetLastTarget(obj, NULL);
aiInfoSetLastTarget(obj, NULL);
} else {
scriptPredefinedError(program, "critter_stop_attacking", SCRIPT_ERROR_OBJECT_IS_NULL);
}