diff --git a/src/combat.cc b/src/combat.cc index a5b2b56..64f6da7 100644 --- a/src/combat.cc +++ b/src/combat.cc @@ -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++; } diff --git a/src/combat.h b/src/combat.h index 7eab9fe..41f231a 100644 --- a/src/combat.h +++ b/src/combat.h @@ -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); diff --git a/src/combat_ai.cc b/src/combat_ai.cc index 5958fe3..d76a1ab 100644 --- a/src/combat_ai.cc +++ b/src/combat_ai.cc @@ -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); } } } diff --git a/src/combat_defs.h b/src/combat_defs.h index ec56184..13f16f2 100644 --- a/src/combat_defs.h +++ b/src/combat_defs.h @@ -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; diff --git a/src/interpreter_extra.cc b/src/interpreter_extra.cc index 7316376..e545f39 100644 --- a/src/interpreter_extra.cc +++ b/src/interpreter_extra.cc @@ -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); }