Variable naming, part 2 (#320)

This commit is contained in:
Vlad 2024-01-16 14:33:08 +01:00 committed by GitHub
parent c6565ac96a
commit 59af02cca9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 501 additions and 498 deletions

View File

@ -88,7 +88,7 @@ static int _is_next_to(Object* a1, Object* a2);
static int _action_climb_ladder(Object* a1, Object* a2); static int _action_climb_ladder(Object* a1, Object* a2);
static int _action_use_skill_in_combat_error(Object* critter); static int _action_use_skill_in_combat_error(Object* critter);
static int _pick_fall(Object* obj, int anim); static int _pick_fall(Object* obj, int anim);
static int _report_explosion(Attack* attack, Object* a2); static int _report_explosion(Attack* attack, Object* sourceObj);
static int _finished_explosion(Object* a1, Object* a2); static int _finished_explosion(Object* a1, Object* a2);
static int _compute_explosion_damage(int min, int max, Object* defender, int* knockbackDistancePtr); static int _compute_explosion_damage(int min, int max, Object* defender, int* knockbackDistancePtr);
static int _can_talk_to(Object* a1, Object* a2); static int _can_talk_to(Object* a1, Object* a2);
@ -1579,9 +1579,9 @@ bool _action_explode_running()
// action_explode // action_explode
// 0x412CF4 // 0x412CF4
int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* a5, bool a6) int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* sourceObj, bool animate)
{ {
if (a6 && _action_in_explode) { if (animate && _action_in_explode) {
return -2; return -2;
} }
@ -1656,7 +1656,7 @@ int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object*
attackComputeDeathFlags(attack); attackComputeDeathFlags(attack);
if (a6) { if (animate) {
_action_in_explode = true; _action_in_explode = true;
reg_anim_begin(ANIMATION_REQUEST_RESERVED); reg_anim_begin(ANIMATION_REQUEST_RESERVED);
@ -1678,7 +1678,7 @@ int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object*
animationRegisterHideObjectForced(adjacentExplosions[rotation]); animationRegisterHideObjectForced(adjacentExplosions[rotation]);
} }
animationRegisterCallbackForced(attack, a5, (AnimationCallback*)_report_explosion, -1); animationRegisterCallbackForced(attack, sourceObj, (AnimationCallback*)_report_explosion, -1);
animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_finished_explosion, -1); animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_finished_explosion, -1);
if (reg_anim_end() == -1) { if (reg_anim_end() == -1) {
_action_in_explode = false; _action_in_explode = false;
@ -1709,7 +1709,7 @@ int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object*
} }
} }
_report_explosion(attack, a5); _report_explosion(attack, sourceObj);
_combat_explode_scenery(explosion, NULL); _combat_explode_scenery(explosion, NULL);
@ -1724,7 +1724,7 @@ int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object*
} }
// 0x413144 // 0x413144
int _report_explosion(Attack* attack, Object* a2) int _report_explosion(Attack* attack, Object* sourceObj)
{ {
bool mainTargetWasDead; bool mainTargetWasDead;
if (attack->defender != NULL) { if (attack->defender != NULL) {
@ -1744,27 +1744,27 @@ int _report_explosion(Attack* attack, Object* a2)
Object* anyDefender = NULL; Object* anyDefender = NULL;
int xp = 0; int xp = 0;
if (a2 != NULL) { if (sourceObj != NULL) {
if (attack->defender != NULL && attack->defender != a2) { if (attack->defender != NULL && attack->defender != sourceObj) {
if ((attack->defender->data.critter.combat.results & DAM_DEAD) != 0) { if ((attack->defender->data.critter.combat.results & DAM_DEAD) != 0) {
if (a2 == gDude && !mainTargetWasDead) { if (sourceObj == gDude && !mainTargetWasDead) {
xp += critterGetExp(attack->defender); xp += critterGetExp(attack->defender);
} }
} else { } else {
_critter_set_who_hit_me(attack->defender, a2); _critter_set_who_hit_me(attack->defender, sourceObj);
anyDefender = attack->defender; anyDefender = attack->defender;
} }
} }
for (int index = 0; index < attack->extrasLength; index++) { for (int index = 0; index < attack->extrasLength; index++) {
Object* critter = attack->extras[index]; Object* critter = attack->extras[index];
if (critter != a2) { if (critter != sourceObj) {
if ((critter->data.critter.combat.results & DAM_DEAD) != 0) { if ((critter->data.critter.combat.results & DAM_DEAD) != 0) {
if (a2 == gDude && !extrasWasDead[index]) { if (sourceObj == gDude && !extrasWasDead[index]) {
xp += critterGetExp(critter); xp += critterGetExp(critter);
} }
} else { } else {
_critter_set_who_hit_me(critter, a2); _critter_set_who_hit_me(critter, sourceObj);
if (anyDefender == NULL) { if (anyDefender == NULL) {
anyDefender = critter; anyDefender = critter;
@ -1775,15 +1775,15 @@ int _report_explosion(Attack* attack, Object* a2)
if (anyDefender != NULL) { if (anyDefender != NULL) {
if (!isInCombat()) { if (!isInCombat()) {
STRUCT_664980 combat; CombatStartData combat;
combat.attacker = anyDefender; combat.attacker = anyDefender;
combat.defender = a2; combat.defender = sourceObj;
combat.actionPointsBonus = 0; combat.actionPointsBonus = 0;
combat.accuracyBonus = 0; combat.accuracyBonus = 0;
combat.damageBonus = 0; combat.damageBonus = 0;
combat.minDamage = 0; combat.minDamage = 0;
combat.maxDamage = INT_MAX; combat.maxDamage = INT_MAX;
combat.field_1C = 0; combat.overrideAttackResults = 0;
scriptsRequestCombat(&combat); scriptsRequestCombat(&combat);
} }
} }
@ -1792,7 +1792,7 @@ int _report_explosion(Attack* attack, Object* a2)
internal_free(attack); internal_free(attack);
gameUiEnable(); gameUiEnable();
if (a2 == gDude) { if (sourceObj == gDude) {
_combat_give_exps(xp); _combat_give_exps(xp);
} }

View File

@ -15,10 +15,10 @@ int actionPickUp(Object* critter, Object* item);
int _action_loot_container(Object* critter, Object* container); int _action_loot_container(Object* critter, Object* container);
int _action_skill_use(int a1); int _action_skill_use(int a1);
int actionUseSkill(Object* a1, Object* a2, int skill); int actionUseSkill(Object* a1, Object* a2, int skill);
bool _is_hit_from_front(Object* a1, Object* a2); bool _is_hit_from_front(Object* attacker, Object* defender);
bool _can_see(Object* a1, Object* a2); bool _can_see(Object* a1, Object* a2);
bool _action_explode_running(); bool _action_explode_running();
int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* a5, bool a6); int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* sourceObj, bool animate);
int actionTalk(Object* a1, Object* a2); int actionTalk(Object* a1, Object* a2);
void actionDamage(int tile, int elevation, int minDamage, int maxDamage, int damageType, bool animated, bool bypassArmor); void actionDamage(int tile, int elevation, int minDamage, int maxDamage, int damageType, bool animated, bool bypassArmor);
bool actionCheckPush(Object* a1, Object* a2); bool actionCheckPush(Object* a1, Object* a2);

View File

@ -94,13 +94,13 @@ static bool _combat_safety_invalidate_weapon_func(Object* attacker, Object* weap
static void _combatInitAIInfoList(); static void _combatInitAIInfoList();
static int aiInfoCopy(int srcIndex, int destIndex); static int aiInfoCopy(int srcIndex, int destIndex);
static int _combatAIInfoSetLastMove(Object* object, int move); static int _combatAIInfoSetLastMove(Object* object, int move);
static void _combat_begin(Object* a1); static void _combat_begin(Object* attacker);
static void _combat_begin_extra(Object* a1); static void _combat_begin_extra(Object* attacker);
static void _combat_update_critters_in_los(bool a1); static void _combat_update_critters_in_los(bool a1);
static void _combat_over(); static void _combat_over();
static void _combat_add_noncoms(); static void _combat_add_noncoms();
static int _compare_faster(const void* a1, const void* a2); static int _compare_faster(const void* critter1Ptr, const void* critter2Ptr);
static void _combat_sequence_init(Object* a1, Object* a2); static void _combat_sequence_init(Object* attacker, Object* defender);
static void _combat_sequence(); static void _combat_sequence();
static void combatAttemptEnd(); static void combatAttemptEnd();
static int _combat_input(); static int _combat_input();
@ -161,7 +161,7 @@ unsigned int gCombatState = COMBAT_STATE_0x02;
static CombatAiInfo* _aiInfoList = NULL; static CombatAiInfo* _aiInfoList = NULL;
// 0x51094C // 0x51094C
static STRUCT_664980* _gcsd = NULL; static CombatStartData* _gcsd = NULL;
// 0x510950 // 0x510950
static bool _combat_call_display = false; static bool _combat_call_display = false;
@ -2560,7 +2560,7 @@ static int _combatAIInfoSetLastMove(Object* object, int move)
} }
// 0x421A34 // 0x421A34
static void _combat_begin(Object* a1) static void _combat_begin(Object* attacker)
{ {
_combat_turn_running = 0; _combat_turn_running = 0;
animationStop(); animationStop();
@ -2610,7 +2610,7 @@ static void _combat_begin(Object* a1)
gameUiDisable(0); gameUiDisable(0);
gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH); gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH);
_combat_ending_guy = NULL; _combat_ending_guy = NULL;
_combat_begin_extra(a1); _combat_begin_extra(attacker);
_caiTeamCombatInit(_combat_list, _list_total); _caiTeamCombatInit(_combat_list, _list_total);
interfaceBarEndButtonsShow(true); interfaceBarEndButtonsShow(true);
_gmouse_enable_scrolling(); _gmouse_enable_scrolling();
@ -2636,15 +2636,15 @@ static void _combat_begin(Object* a1)
} }
// 0x421C8C // 0x421C8C
static void _combat_begin_extra(Object* a1) static void _combat_begin_extra(Object* attacker)
{ {
for (int index = 0; index < _list_total; index++) { for (int index = 0; index < _list_total; index++) {
_combat_update_critter_outline_for_los(_combat_list[index], 0); _combat_update_critter_outline_for_los(_combat_list[index], 0);
} }
attackInit(&_main_ctd, a1, NULL, 4, 3); attackInit(&_main_ctd, attacker, NULL, 4, 3);
_combat_turn_obj = a1; _combat_turn_obj = attacker;
_combat_ai_begin(_list_total, _combat_list); _combat_ai_begin(_list_total, _combat_list);
@ -2933,21 +2933,21 @@ static void _combat_add_noncoms()
// Compares critters by sequence. // Compares critters by sequence.
// //
// 0x4223C8 // 0x4223C8
static int _compare_faster(const void* a1, const void* a2) static int _compare_faster(const void* critter1Ptr, const void* critter2Ptr)
{ {
Object* v1 = *(Object**)a1; Object* critter1 = *(Object**)critter1Ptr;
Object* v2 = *(Object**)a2; Object* critter2 = *(Object**)critter2Ptr;
int sequence1 = critterGetStat(v1, STAT_SEQUENCE); int sequence1 = critterGetStat(critter1, STAT_SEQUENCE);
int sequence2 = critterGetStat(v2, STAT_SEQUENCE); int sequence2 = critterGetStat(critter2, STAT_SEQUENCE);
if (sequence1 > sequence2) { if (sequence1 > sequence2) {
return -1; return -1;
} else if (sequence1 < sequence2) { } else if (sequence1 < sequence2) {
return 1; return 1;
} }
int luck1 = critterGetStat(v1, STAT_LUCK); int luck1 = critterGetStat(critter1, STAT_LUCK);
int luck2 = critterGetStat(v2, STAT_LUCK); int luck2 = critterGetStat(critter2, STAT_LUCK);
if (luck1 > luck2) { if (luck1 > luck2) {
return -1; return -1;
} else if (luck1 < luck2) { } else if (luck1 < luck2) {
@ -2957,14 +2957,17 @@ static int _compare_faster(const void* a1, const void* a2)
return 0; return 0;
} }
// Initializes combat sequence for the first round.
//
// 0x42243C // 0x42243C
static void _combat_sequence_init(Object* a1, Object* a2) static void _combat_sequence_init(Object* attacker, Object* defender)
{ {
// Always place attacker first (swap with critter at 0 index).
int next = 0; int next = 0;
if (a1 != NULL) { if (attacker != NULL) {
for (int index = 0; index < _list_total; index++) { for (int index = 0; index < _list_total; index++) {
Object* obj = _combat_list[index]; Object* obj = _combat_list[index];
if (obj == a1) { if (obj == attacker) {
Object* temp = _combat_list[next]; Object* temp = _combat_list[next];
_combat_list[index] = temp; _combat_list[index] = temp;
_combat_list[next] = obj; _combat_list[next] = obj;
@ -2974,10 +2977,11 @@ static void _combat_sequence_init(Object* a1, Object* a2)
} }
} }
if (a2 != NULL) { // Place defender second.
if (defender != NULL) {
for (int index = 0; index < _list_total; index++) { for (int index = 0; index < _list_total; index++) {
Object* obj = _combat_list[index]; Object* obj = _combat_list[index];
if (obj == a2) { if (obj == defender) {
Object* temp = _combat_list[next]; Object* temp = _combat_list[next];
_combat_list[index] = temp; _combat_list[index] = temp;
_combat_list[next] = obj; _combat_list[next] = obj;
@ -2987,7 +2991,8 @@ static void _combat_sequence_init(Object* a1, Object* a2)
} }
} }
if (a1 != gDude && a2 != gDude) { // Place dude third, if he's neither attacker, nor defender.
if (attacker != gDude && defender != gDude) {
for (int index = 0; index < _list_total; index++) { for (int index = 0; index < _list_total; index++) {
Object* obj = _combat_list[index]; Object* obj = _combat_list[index];
if (obj == gDude) { if (obj == gDude) {
@ -3003,15 +3008,17 @@ static void _combat_sequence_init(Object* a1, Object* a2)
_list_com = next; _list_com = next;
_list_noncom -= next; _list_noncom -= next;
if (a1 != NULL) { if (attacker != NULL) {
_critter_set_who_hit_me(a1, a2); _critter_set_who_hit_me(attacker, defender);
} }
if (a2 != NULL) { if (defender != NULL) {
_critter_set_who_hit_me(a2, a1); _critter_set_who_hit_me(defender, attacker);
} }
} }
// Updates combat sequence for the next round.
//
// 0x422580 // 0x422580
static void _combat_sequence() static void _combat_sequence()
{ {
@ -3019,6 +3026,7 @@ static void _combat_sequence()
int count = _list_com; int count = _list_com;
// Remove dead critters from the combatant list.
for (int index = 0; index < count; index++) { for (int index = 0; index < count; index++) {
Object* critter = _combat_list[index]; Object* critter = _combat_list[index];
if ((critter->data.critter.combat.results & DAM_DEAD) != 0) { if ((critter->data.critter.combat.results & DAM_DEAD) != 0) {
@ -3033,6 +3041,7 @@ static void _combat_sequence()
} }
} }
// Move knocked out and disengaged critters to non-combatant list.
for (int index = 0; index < count; index++) { for (int index = 0; index < count; index++) {
Object* critter = _combat_list[index]; Object* critter = _combat_list[index];
if (critter != gDude) { if (critter != gDude) {
@ -3050,6 +3059,7 @@ static void _combat_sequence()
} }
} }
// Sort combatant list based on Sequence stat.
if (count != 0) { if (count != 0) {
_list_com = count; _list_com = count;
qsort(_combat_list, count, sizeof(*_combat_list), _compare_faster); qsort(_combat_list, count, sizeof(*_combat_list), _compare_faster);
@ -3212,16 +3222,16 @@ static void _combat_set_move_all()
} }
// 0x42299C // 0x42299C
static int _combat_turn(Object* a1, bool a2) static int _combat_turn(Object* obj, bool a2)
{ {
_combat_turn_obj = a1; _combat_turn_obj = obj;
attackInit(&_main_ctd, a1, NULL, HIT_MODE_PUNCH, HIT_LOCATION_TORSO); attackInit(&_main_ctd, obj, NULL, HIT_MODE_PUNCH, HIT_LOCATION_TORSO);
if ((a1->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_DEAD | DAM_LOSE_TURN)) != 0) { if ((obj->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_DEAD | DAM_LOSE_TURN)) != 0) {
a1->data.critter.combat.results &= ~DAM_LOSE_TURN; obj->data.critter.combat.results &= ~DAM_LOSE_TURN;
} else { } else {
if (a1 == gDude) { if (obj == gDude) {
keyboardReset(); keyboardReset();
interfaceRenderArmorClass(true); interfaceRenderArmorClass(true);
_combat_free_move = 2 * perkGetRank(gDude, PERK_BONUS_MOVE); _combat_free_move = 2 * perkGetRank(gDude, PERK_BONUS_MOVE);
@ -3231,13 +3241,13 @@ static int _combat_turn(Object* a1, bool a2)
} }
bool scriptOverrides = false; bool scriptOverrides = false;
if (a1->sid != -1) { if (obj->sid != -1) {
scriptSetObjects(a1->sid, NULL, NULL); scriptSetObjects(obj->sid, NULL, NULL);
scriptSetFixedParam(a1->sid, 4); scriptSetFixedParam(obj->sid, 4);
scriptExecProc(a1->sid, SCRIPT_PROC_COMBAT); scriptExecProc(obj->sid, SCRIPT_PROC_COMBAT);
Script* scr; Script* scr;
if (scriptGetScript(a1->sid, &scr) != -1) { if (scriptGetScript(obj->sid, &scr) != -1) {
scriptOverrides = scr->scriptOverrides; scriptOverrides = scr->scriptOverrides;
} }
@ -3247,11 +3257,11 @@ static int _combat_turn(Object* a1, bool a2)
} }
if (!scriptOverrides) { if (!scriptOverrides) {
if (!a2 && _critter_is_prone(a1)) { if (!a2 && _critter_is_prone(obj)) {
_combat_standup(a1); _combat_standup(obj);
} }
if (a1 == gDude) { if (obj == gDude) {
gameUiEnable(); gameUiEnable();
_gmouse_3d_refresh(); _gmouse_3d_refresh();
@ -3275,7 +3285,7 @@ static int _combat_turn(Object* a1, bool a2)
if (_combat_input() == -1) { if (_combat_input() == -1) {
gameUiDisable(1); gameUiDisable(1);
gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH); gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH);
a1->data.critter.combat.damageLastTurn = 0; obj->data.critter.combat.damageLastTurn = 0;
interfaceBarEndButtonsRenderRedLights(); interfaceBarEndButtonsRenderRedLights();
_combat_outline_off(); _combat_outline_off();
interfaceRenderActionPoints(-1, -1); interfaceRenderActionPoints(-1, -1);
@ -3285,18 +3295,18 @@ static int _combat_turn(Object* a1, bool a2)
} }
} else { } else {
Rect rect; Rect rect;
if (objectEnableOutline(a1, &rect) == 0) { if (objectEnableOutline(obj, &rect) == 0) {
tileWindowRefreshRect(&rect, a1->elevation); tileWindowRefreshRect(&rect, obj->elevation);
} }
_combat_ai(a1, _gcsd != NULL ? _gcsd->defender : NULL); _combat_ai(obj, _gcsd != NULL ? _gcsd->defender : NULL);
} }
} }
// NOTE: Uninline. // NOTE: Uninline.
_combat_turn_run(); _combat_turn_run();
if (a1 == gDude) { if (obj == gDude) {
gameUiDisable(1); gameUiDisable(1);
gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH); gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH);
interfaceBarEndButtonsRenderRedLights(); interfaceBarEndButtonsRenderRedLights();
@ -3307,8 +3317,8 @@ static int _combat_turn(Object* a1, bool a2)
_combat_turn_obj = gDude; _combat_turn_obj = gDude;
} else { } else {
Rect rect; Rect rect;
if (objectDisableOutline(a1, &rect) == 0) { if (objectDisableOutline(obj, &rect) == 0) {
tileWindowRefreshRect(&rect, a1->elevation); tileWindowRefreshRect(&rect, obj->elevation);
} }
} }
} }
@ -3317,7 +3327,7 @@ static int _combat_turn(Object* a1, bool a2)
return -1; return -1;
} }
if (a1 != gDude || _combat_elev == gDude->elevation) { if (obj != gDude || _combat_elev == gDude->elevation) {
_combat_free_move = 0; _combat_free_move = 0;
return 0; return 0;
} }
@ -3365,23 +3375,23 @@ static bool _combat_should_end()
} }
// 0x422D2C // 0x422D2C
void _combat(STRUCT_664980* attack) void _combat(CombatStartData* csd)
{ {
ScopedGameMode gm(GameMode::kCombat); ScopedGameMode gm(GameMode::kCombat);
if (attack == NULL if (csd == NULL
|| (attack->attacker == NULL || attack->attacker->elevation == gElevation) || (csd->attacker == NULL || csd->attacker->elevation == gElevation)
|| (attack->defender == NULL || attack->defender->elevation == gElevation)) { || (csd->defender == NULL || csd->defender->elevation == gElevation)) {
int v3 = gCombatState & 0x01; bool wasInCombat = (gCombatState & 0x01) != 0;
_combat_begin(NULL); _combat_begin(NULL);
int v6; int curIndex;
// TODO: Not sure. // If we loaded a save in combat, we need to force dude turn and then continue with the next combatant.
if (v3 != 0) { if (wasInCombat) {
if (_combat_turn(gDude, true) == -1) { if (_combat_turn(gDude, true) == -1) {
v6 = -1; curIndex = -1;
} else { } else {
int index; int index;
for (index = 0; index < _list_com; index++) { for (index = 0; index < _list_com; index++) {
@ -3389,33 +3399,33 @@ void _combat(STRUCT_664980* attack)
break; break;
} }
} }
v6 = index + 1; curIndex = index + 1;
} }
_gcsd = NULL; _gcsd = NULL;
} else { } else {
Object* v3; Object* defender;
Object* v9; Object* attacker;
if (attack != NULL) { if (csd != NULL) {
v3 = attack->defender; defender = csd->defender;
v9 = attack->attacker; attacker = csd->attacker;
} else { } else {
v3 = NULL; defender = NULL;
v9 = NULL; attacker = NULL;
} }
_combat_sequence_init(v9, v3); _combat_sequence_init(attacker, defender);
_gcsd = attack; _gcsd = csd;
v6 = 0; curIndex = 0;
} }
do { do {
if (v6 == -1) { if (curIndex == -1) {
break; break;
} }
_combat_set_move_all(); _combat_set_move_all();
for (; v6 < _list_com; v6++) { for (; curIndex < _list_com; curIndex++) {
if (_combat_turn(_combat_list[v6], false) == -1) { if (_combat_turn(_combat_list[curIndex], false) == -1) {
break; break;
} }
@ -3426,12 +3436,12 @@ void _combat(STRUCT_664980* attack)
_gcsd = NULL; _gcsd = NULL;
} }
if (v6 < _list_com) { if (curIndex < _list_com) {
break; break;
} }
_combat_sequence(); _combat_sequence();
v6 = 0; curIndex = 0;
_combatNumTurns += 1; _combatNumTurns += 1;
} while (!_combat_should_end()); } while (!_combat_should_end());
@ -3503,11 +3513,11 @@ int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocat
_main_ctd.defenderDamage = _gcsd->maxDamage; _main_ctd.defenderDamage = _gcsd->maxDamage;
} }
if (_gcsd->field_1C) { if (_gcsd->overrideAttackResults) {
// FIXME: looks like a bug, two different fields are used to set // FIXME: looks like a bug, two different fields are used to set
// one field. // one field.
_main_ctd.defenderFlags = _gcsd->field_20; _main_ctd.defenderFlags = _gcsd->attackerResults;
_main_ctd.defenderFlags = _gcsd->field_24; _main_ctd.defenderFlags = _gcsd->targetResults;
} }
} }
@ -5700,9 +5710,9 @@ bool _combat_to_hit(Object* target, int* accuracy)
} }
// 0x4267CC // 0x4267CC
void _combat_attack_this(Object* a1) void _combat_attack_this(Object* target)
{ {
if (a1 == NULL) { if (target == NULL) {
return; return;
} }
@ -5721,7 +5731,7 @@ void _combat_attack_this(Object* a1)
char formattedText[80]; char formattedText[80];
const char* sfx; const char* sfx;
int rc = _combat_check_bad_shot(gDude, a1, hitMode, aiming); int rc = _combat_check_bad_shot(gDude, target, hitMode, aiming);
switch (rc) { switch (rc) {
case COMBAT_BAD_SHOT_NO_AMMO: case COMBAT_BAD_SHOT_NO_AMMO:
item = critterGetWeaponForHitMode(gDude, hitMode); item = critterGetWeaponForHitMode(gDude, hitMode);
@ -5771,21 +5781,21 @@ void _combat_attack_this(Object* a1)
} }
if (!isInCombat()) { if (!isInCombat()) {
STRUCT_664980 stru; CombatStartData combat;
stru.attacker = gDude; combat.attacker = gDude;
stru.defender = a1; combat.defender = target;
stru.actionPointsBonus = 0; combat.actionPointsBonus = 0;
stru.accuracyBonus = 0; combat.accuracyBonus = 0;
stru.damageBonus = 0; combat.damageBonus = 0;
stru.minDamage = 0; combat.minDamage = 0;
stru.maxDamage = INT_MAX; combat.maxDamage = INT_MAX;
stru.field_1C = 0; combat.overrideAttackResults = 0;
_combat(&stru); _combat(&combat);
return; return;
} }
if (!aiming) { if (!aiming) {
_combat_attack(gDude, a1, hitMode, HIT_LOCATION_UNCALLED); _combat_attack(gDude, target, hitMode, HIT_LOCATION_UNCALLED);
return; return;
} }
@ -5794,8 +5804,8 @@ void _combat_attack_this(Object* a1)
} }
int hitLocation; int hitLocation;
if (calledShotSelectHitLocation(a1, &hitLocation, hitMode) != -1) { if (calledShotSelectHitLocation(target, &hitLocation, hitMode) != -1) {
_combat_attack(gDude, a1, hitMode, hitLocation); _combat_attack(gDude, target, hitMode, hitLocation);
} }
} }

View File

@ -33,7 +33,7 @@ void _combat_update_critter_outline_for_los(Object* critter, bool a2);
void _combat_over_from_load(); void _combat_over_from_load();
void _combat_give_exps(int exp_points); void _combat_give_exps(int exp_points);
void _combat_turn_run(); void _combat_turn_run();
void _combat(STRUCT_664980* attack); void _combat(CombatStartData* csd);
void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode, int hitLocation); void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation); int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_bullet_start(const Object* attacker, const Object* target); int _combat_bullet_start(const Object* attacker, const Object* target);
@ -48,7 +48,7 @@ void _combat_anim_begin();
void _combat_anim_finished(); void _combat_anim_finished();
int _combat_check_bad_shot(Object* attacker, Object* defender, int hitMode, bool aiming); int _combat_check_bad_shot(Object* attacker, Object* defender, int hitMode, bool aiming);
bool _combat_to_hit(Object* target, int* accuracy); bool _combat_to_hit(Object* target, int* accuracy);
void _combat_attack_this(Object* a1); void _combat_attack_this(Object* target);
void _combat_outline_on(); void _combat_outline_on();
void _combat_outline_off(); void _combat_outline_off();
void _combat_highlight_change(); void _combat_highlight_change();

View File

@ -3496,22 +3496,22 @@ void _combatai_check_retaliation(Object* a1, Object* a2)
} }
// 0x42BA04 // 0x42BA04
bool isWithinPerception(Object* a1, Object* a2) bool isWithinPerception(Object* critter, Object* target)
{ {
if (a2 == NULL) { if (target == NULL) {
return false; return false;
} }
int distance = objectGetDistanceBetween(a2, a1); int distance = objectGetDistanceBetween(target, critter);
int perception = critterGetStat(a1, STAT_PERCEPTION); int perception = critterGetStat(critter, STAT_PERCEPTION);
int sneak = skillGetValue(a2, SKILL_SNEAK); int sneak = skillGetValue(target, SKILL_SNEAK);
if (_can_see(a1, a2)) { if (_can_see(critter, target)) {
int maxDistance = perception * 5; int maxDistance = perception * 5;
if ((a2->flags & OBJECT_TRANS_GLASS) != 0) { if ((target->flags & OBJECT_TRANS_GLASS) != 0) {
maxDistance /= 2; maxDistance /= 2;
} }
if (a2 == gDude) { if (target == gDude) {
if (dudeIsSneaking()) { if (dudeIsSneaking()) {
maxDistance /= 4; maxDistance /= 4;
if (sneak > 120) { if (sneak > 120) {
@ -3534,7 +3534,7 @@ bool isWithinPerception(Object* a1, Object* a2)
maxDistance = perception; maxDistance = perception;
} }
if (a2 == gDude) { if (target == gDude) {
if (dudeIsSneaking()) { if (dudeIsSneaking()) {
maxDistance /= 4; maxDistance /= 4;
if (sneak > 120) { if (sneak > 120) {

View File

@ -86,7 +86,7 @@ typedef enum HitLocation {
HIT_LOCATION_SPECIFIC_COUNT = HIT_LOCATION_COUNT - 1, HIT_LOCATION_SPECIFIC_COUNT = HIT_LOCATION_COUNT - 1,
} HitLocation; } HitLocation;
typedef struct STRUCT_664980 { typedef struct CombatStartData {
Object* attacker; Object* attacker;
Object* defender; Object* defender;
int actionPointsBonus; int actionPointsBonus;
@ -94,10 +94,10 @@ typedef struct STRUCT_664980 {
int damageBonus; int damageBonus;
int minDamage; int minDamage;
int maxDamage; int maxDamage;
int field_1C; // probably bool, indicating field_20 and field_24 used int overrideAttackResults;
int field_20; // flags on attacker int attackerResults;
int field_24; // flags on defender int targetResults;
} STRUCT_664980; } CombatStartData;
typedef struct Attack { typedef struct Attack {
Object* attacker; Object* attacker;

View File

@ -1868,27 +1868,27 @@ static void opAttackComplex(Program* program)
combatData->whoHitMe = target; combatData->whoHitMe = target;
} }
} else { } else {
STRUCT_664980 attack; CombatStartData combat;
attack.attacker = self; combat.attacker = self;
attack.defender = target; combat.defender = target;
attack.actionPointsBonus = 0; combat.actionPointsBonus = 0;
attack.accuracyBonus = data[4]; combat.accuracyBonus = data[4];
attack.damageBonus = 0; combat.damageBonus = 0;
attack.minDamage = data[3]; combat.minDamage = data[3];
attack.maxDamage = data[2]; combat.maxDamage = data[2];
// TODO: Something is probably broken here, why it wants // TODO: Something is probably broken here, why it wants
// flags to be the same? Maybe because both of them // flags to be the same? Maybe because both of them
// are applied to defender because of the bug in 0x422F3C? // are applied to defender because of the bug in 0x422F3C?
if (data[1] == data[0]) { if (data[1] == data[0]) {
attack.field_1C = 1; combat.overrideAttackResults = 1;
attack.field_24 = data[0]; combat.targetResults = data[0];
attack.field_20 = data[1]; combat.attackerResults = data[1];
} else { } else {
attack.field_1C = 0; combat.overrideAttackResults = 0;
} }
scriptsRequestCombat(&attack); scriptsRequestCombat(&combat);
} }
program->flags &= ~PROGRAM_FLAG_0x20; program->flags &= ~PROGRAM_FLAG_0x20;
@ -4455,17 +4455,17 @@ static void opAttackSetup(Program* program)
attacker->data.critter.combat.whoHitMe = defender; attacker->data.critter.combat.whoHitMe = defender;
} }
} else { } else {
STRUCT_664980 attack; CombatStartData combat;
attack.attacker = attacker; combat.attacker = attacker;
attack.defender = defender; combat.defender = defender;
attack.actionPointsBonus = 0; combat.actionPointsBonus = 0;
attack.accuracyBonus = 0; combat.accuracyBonus = 0;
attack.damageBonus = 0; combat.damageBonus = 0;
attack.minDamage = 0; combat.minDamage = 0;
attack.maxDamage = INT_MAX; combat.maxDamage = INT_MAX;
attack.field_1C = 0; combat.overrideAttackResults = 0;
scriptsRequestCombat(&attack); scriptsRequestCombat(&combat);
} }
} }

View File

@ -238,6 +238,12 @@ typedef struct InventoryCursorData {
CacheEntry* frmHandle; CacheEntry* frmHandle;
} InventoryCursorData; } InventoryCursorData;
typedef enum InventoryMoveResult {
INVENTORY_MOVE_RESULT_FAILED,
INVENTORY_MOVE_RESULT_CAUGHT_STEALING,
INVENTORY_MOVE_RESULT_SUCCESS,
};
static int inventoryMessageListInit(); static int inventoryMessageListInit();
static int inventoryMessageListFree(); static int inventoryMessageListFree();
static bool _setup_inventory(int inventoryWindowType); static bool _setup_inventory(int inventoryWindowType);
@ -260,7 +266,7 @@ static int _inven_from_button(int a1, Object** a2, Object*** a3, Object** a4);
static void inventoryRenderItemDescription(char* string); static void inventoryRenderItemDescription(char* string);
static void inventoryExamineItem(Object* critter, Object* item); static void inventoryExamineItem(Object* critter, Object* item);
static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowType); static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowType);
static int _move_inventory(Object* a1, int a2, Object* a3, bool a4); static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting);
static int _barter_compute_value(Object* a1, Object* a2); static int _barter_compute_value(Object* a1, Object* a2);
static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Object* a4); static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Object* a4);
static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Object* a5, Object* a6, bool a7); static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Object* a5, Object* a6, bool a7);
@ -1549,38 +1555,38 @@ static void _exit_inventory(bool shouldEnableIso)
_gmouse_enable(); _gmouse_enable();
if (_dropped_explosive) { if (_dropped_explosive) {
Attack v1; Attack attack;
attackInit(&v1, gDude, NULL, HIT_MODE_PUNCH, HIT_LOCATION_TORSO); attackInit(&attack, gDude, NULL, HIT_MODE_PUNCH, HIT_LOCATION_TORSO);
v1.attackerFlags = DAM_HIT; attack.attackerFlags = DAM_HIT;
v1.tile = gDude->tile; attack.tile = gDude->tile;
_compute_explosion_on_extras(&v1, 0, 0, 1); _compute_explosion_on_extras(&attack, 0, 0, 1);
Object* v2 = NULL; Object* watcher = NULL;
for (int index = 0; index < v1.extrasLength; index++) { for (int index = 0; index < attack.extrasLength; index++) {
Object* critter = v1.extras[index]; Object* critter = attack.extras[index];
if (critter != gDude if (critter != gDude
&& critter->data.critter.combat.team != gDude->data.critter.combat.team && critter->data.critter.combat.team != gDude->data.critter.combat.team
&& statRoll(critter, STAT_PERCEPTION, 0, NULL) >= ROLL_SUCCESS) { && statRoll(critter, STAT_PERCEPTION, 0, NULL) >= ROLL_SUCCESS) {
_critter_set_who_hit_me(critter, gDude); _critter_set_who_hit_me(critter, gDude);
if (v2 == NULL) { if (watcher == NULL) {
v2 = critter; watcher = critter;
} }
} }
} }
if (v2 != NULL) { if (watcher != NULL) {
if (!isInCombat()) { if (!isInCombat()) {
STRUCT_664980 v3; CombatStartData combat;
v3.attacker = v2; combat.attacker = watcher;
v3.defender = gDude; combat.defender = gDude;
v3.actionPointsBonus = 0; combat.actionPointsBonus = 0;
v3.accuracyBonus = 0; combat.accuracyBonus = 0;
v3.damageBonus = 0; combat.damageBonus = 0;
v3.minDamage = 0; combat.minDamage = 0;
v3.maxDamage = INT_MAX; combat.maxDamage = INT_MAX;
v3.field_1C = 0; combat.overrideAttackResults = 0;
scriptsRequestCombat(&v3); scriptsRequestCombat(&combat);
} }
} }
@ -4036,7 +4042,7 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
} }
// 0x473904 // 0x473904
int inventoryOpenLooting(Object* a1, Object* a2) int inventoryOpenLooting(Object* looter, Object* target)
{ {
int arrowFrmIds[INVENTORY_ARROW_FRM_COUNT]; int arrowFrmIds[INVENTORY_ARROW_FRM_COUNT];
FrmImage arrowFrmImages[INVENTORY_ARROW_FRM_COUNT]; FrmImage arrowFrmImages[INVENTORY_ARROW_FRM_COUNT];
@ -4044,14 +4050,14 @@ int inventoryOpenLooting(Object* a1, Object* a2)
memcpy(arrowFrmIds, gInventoryArrowFrmIds, sizeof(gInventoryArrowFrmIds)); memcpy(arrowFrmIds, gInventoryArrowFrmIds, sizeof(gInventoryArrowFrmIds));
if (a1 != _inven_dude) { if (looter != _inven_dude) {
return 0; return 0;
} }
ScopedGameMode gm(GameMode::kLoot); ScopedGameMode gm(GameMode::kLoot);
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) { if (FID_TYPE(target->fid) == OBJ_TYPE_CRITTER) {
if (_critter_flag_check(a2->pid, CRITTER_NO_STEAL)) { if (_critter_flag_check(target->pid, CRITTER_NO_STEAL)) {
// You can't find anything to take from that. // You can't find anything to take from that.
messageListItem.num = 50; messageListItem.num = 50;
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
@ -4061,11 +4067,11 @@ int inventoryOpenLooting(Object* a1, Object* a2)
} }
} }
if (FID_TYPE(a2->fid) == OBJ_TYPE_ITEM) { if (FID_TYPE(target->fid) == OBJ_TYPE_ITEM) {
if (itemGetType(a2) == ITEM_TYPE_CONTAINER) { if (itemGetType(target) == ITEM_TYPE_CONTAINER) {
if (a2->frame == 0) { if (target->frame == 0) {
CacheEntry* handle; CacheEntry* handle;
Art* frm = artLock(a2->fid, &handle); Art* frm = artLock(target->fid, &handle);
if (frm != NULL) { if (frm != NULL) {
int frameCount = artGetFrameCount(frm); int frameCount = artGetFrameCount(frm);
artUnlock(handle); artUnlock(handle);
@ -4079,8 +4085,8 @@ int inventoryOpenLooting(Object* a1, Object* a2)
int sid = -1; int sid = -1;
if (!_gIsSteal) { if (!_gIsSteal) {
if (_obj_sid(a2, &sid) != -1) { if (_obj_sid(target, &sid) != -1) {
scriptSetObjects(sid, a1, NULL); scriptSetObjects(sid, looter, NULL);
scriptExecProc(sid, SCRIPT_PROC_PICKUP); scriptExecProc(sid, SCRIPT_PROC_PICKUP);
Script* script; Script* script;
@ -4096,36 +4102,36 @@ int inventoryOpenLooting(Object* a1, Object* a2)
return 0; return 0;
} }
_target_pud = &(a2->data.inventory); _target_pud = &(target->data.inventory);
_target_curr_stack = 0; _target_curr_stack = 0;
_target_stack_offset[0] = 0; _target_stack_offset[0] = 0;
_target_stack[0] = a2; _target_stack[0] = target;
Object* a1a = NULL; Object* hiddenBox = NULL;
if (objectCreateWithFidPid(&a1a, 0, 467) == -1) { if (objectCreateWithFidPid(&hiddenBox, 0, PROTO_ID_JESSE_CONTAINER) == -1) {
return 0; return 0;
} }
itemMoveAllHidden(a2, a1a); itemMoveAllHidden(target, hiddenBox);
Object* item1 = NULL; Object* item1 = NULL;
Object* item2 = NULL; Object* item2 = NULL;
Object* armor = NULL; Object* armor = NULL;
if (_gIsSteal) { if (_gIsSteal) {
item1 = critterGetItem1(a2); item1 = critterGetItem1(target);
if (item1 != NULL) { if (item1 != NULL) {
itemRemove(a2, item1, 1); itemRemove(target, item1, 1);
} }
item2 = critterGetItem2(a2); item2 = critterGetItem2(target);
if (item2 != NULL) { if (item2 != NULL) {
itemRemove(a2, item2, 1); itemRemove(target, item2, 1);
} }
armor = critterGetArmor(a2); armor = critterGetArmor(target);
if (armor != NULL) { if (armor != NULL) {
itemRemove(a2, armor, 1); itemRemove(target, armor, 1);
} }
} }
@ -4135,8 +4141,8 @@ int inventoryOpenLooting(Object* a1, Object* a2)
int critterCount = 0; int critterCount = 0;
int critterIndex = 0; int critterIndex = 0;
if (!_gIsSteal) { if (!_gIsSteal) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) { if (FID_TYPE(target->fid) == OBJ_TYPE_CRITTER) {
critterCount = objectListCreate(a2->tile, a2->elevation, OBJ_TYPE_CRITTER, &critters); critterCount = objectListCreate(target->tile, target->elevation, OBJ_TYPE_CRITTER, &critters);
int endIndex = critterCount - 1; int endIndex = critterCount - 1;
for (int index = 0; index < critterCount; index++) { for (int index = 0; index < critterCount; index++) {
Object* critter = critters[index]; Object* critter = critters[index];
@ -4213,7 +4219,7 @@ int inventoryOpenLooting(Object* a1, Object* a2)
} }
for (int index = 0; index < critterCount; index++) { for (int index = 0; index < critterCount; index++) {
if (a2 == critters[index]) { if (target == critters[index]) {
critterIndex = index; critterIndex = index;
} }
} }
@ -4223,7 +4229,7 @@ int inventoryOpenLooting(Object* a1, Object* a2)
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT);
_display_body(a2->fid, INVENTORY_WINDOW_TYPE_LOOT); _display_body(target->fid, INVENTORY_WINDOW_TYPE_LOOT);
inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND);
bool isCaughtStealing = false; bool isCaughtStealing = false;
@ -4252,11 +4258,11 @@ int inventoryOpenLooting(Object* a1, Object* a2)
if (keyCode == KEY_UPPERCASE_A) { if (keyCode == KEY_UPPERCASE_A) {
if (!_gIsSteal) { if (!_gIsSteal) {
int maxCarryWeight = critterGetStat(a1, STAT_CARRY_WEIGHT); int maxCarryWeight = critterGetStat(looter, STAT_CARRY_WEIGHT);
int currentWeight = objectGetInventoryWeight(a1); int currentWeight = objectGetInventoryWeight(looter);
int newInventoryWeight = objectGetInventoryWeight(a2); int newInventoryWeight = objectGetInventoryWeight(target);
if (newInventoryWeight <= maxCarryWeight - currentWeight) { if (newInventoryWeight <= maxCarryWeight - currentWeight) {
itemMoveAll(a2, a1); itemMoveAll(target, looter);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT);
} else { } else {
@ -4280,14 +4286,14 @@ int inventoryOpenLooting(Object* a1, Object* a2)
critterIndex = critterCount - 1; critterIndex = critterCount - 1;
} }
a2 = critters[critterIndex]; target = critters[critterIndex];
_target_pud = &(a2->data.inventory); _target_pud = &(target->data.inventory);
_target_stack[0] = a2; _target_stack[0] = target;
_target_curr_stack = 0; _target_curr_stack = 0;
_target_stack_offset[0] = 0; _target_stack_offset[0] = 0;
_display_target_inventory(0, -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_target_inventory(0, -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT);
_display_body(a2->fid, INVENTORY_WINDOW_TYPE_LOOT); _display_body(target->fid, INVENTORY_WINDOW_TYPE_LOOT);
} }
} else if (keyCode == KEY_ARROW_DOWN) { } else if (keyCode == KEY_ARROW_DOWN) {
if (_stack_offset[_curr_stack] + gInventorySlotsCount < _pud->length) { if (_stack_offset[_curr_stack] + gInventorySlotsCount < _pud->length) {
@ -4302,14 +4308,14 @@ int inventoryOpenLooting(Object* a1, Object* a2)
critterIndex = 0; critterIndex = 0;
} }
a2 = critters[critterIndex]; target = critters[critterIndex];
_target_pud = &(a2->data.inventory); _target_pud = &(target->data.inventory);
_target_stack[0] = a2; _target_stack[0] = target;
_target_curr_stack = 0; _target_curr_stack = 0;
_target_stack_offset[0] = 0; _target_stack_offset[0] = 0;
_display_target_inventory(0, -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_target_inventory(0, -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT);
_display_body(a2->fid, INVENTORY_WINDOW_TYPE_LOOT); _display_body(target->fid, INVENTORY_WINDOW_TYPE_LOOT);
} }
} else if (keyCode == KEY_CTRL_ARROW_UP) { } else if (keyCode == KEY_CTRL_ARROW_UP) {
if (_target_stack_offset[_target_curr_stack] > 0) { if (_target_stack_offset[_target_curr_stack] > 0) {
@ -4337,16 +4343,16 @@ int inventoryOpenLooting(Object* a1, Object* a2)
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_LOOT); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_LOOT);
} else { } else {
int v40 = keyCode - 1000; int slotIndex = keyCode - 1000;
if (v40 + _stack_offset[_curr_stack] < _pud->length) { if (slotIndex + _stack_offset[_curr_stack] < _pud->length) {
_gStealCount += 1; _gStealCount += 1;
_gStealSize += itemGetSize(_stack[_curr_stack]); _gStealSize += itemGetSize(_stack[_curr_stack]);
InventoryItem* inventoryItem = &(_pud->items[_pud->length - (v40 + _stack_offset[_curr_stack] + 1)]); InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + _stack_offset[_curr_stack] + 1)]);
int rc = _move_inventory(inventoryItem->item, v40, _target_stack[_target_curr_stack], true); InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], true);
if (rc == 1) { if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
isCaughtStealing = true; isCaughtStealing = true;
} else if (rc == 2) { } else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
stealingXp += stealingXpBonus; stealingXp += stealingXpBonus;
stealingXpBonus += 10; stealingXpBonus += 10;
} }
@ -4361,16 +4367,16 @@ int inventoryOpenLooting(Object* a1, Object* a2)
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_LOOT); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_LOOT);
} else { } else {
int v46 = keyCode - 2000; int slotIndex = keyCode - 2000;
if (v46 + _target_stack_offset[_target_curr_stack] < _target_pud->length) { if (slotIndex + _target_stack_offset[_target_curr_stack] < _target_pud->length) {
_gStealCount += 1; _gStealCount += 1;
_gStealSize += itemGetSize(_stack[_curr_stack]); _gStealSize += itemGetSize(_stack[_curr_stack]);
InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (v46 + _target_stack_offset[_target_curr_stack] + 1)]); InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (slotIndex + _target_stack_offset[_target_curr_stack] + 1)]);
int rc = _move_inventory(inventoryItem->item, v46, _target_stack[_target_curr_stack], false); InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], false);
if (rc == 1) { if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
isCaughtStealing = true; isCaughtStealing = true;
} else if (rc == 2) { } else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
stealingXp += stealingXpBonus; stealingXp += stealingXpBonus;
stealingXpBonus += 10; stealingXpBonus += 10;
} }
@ -4432,43 +4438,37 @@ int inventoryOpenLooting(Object* a1, Object* a2)
if (_gIsSteal) { if (_gIsSteal) {
if (item1 != NULL) { if (item1 != NULL) {
item1->flags |= OBJECT_IN_LEFT_HAND; item1->flags |= OBJECT_IN_LEFT_HAND;
itemAdd(a2, item1, 1); itemAdd(target, item1, 1);
} }
if (item2 != NULL) { if (item2 != NULL) {
item2->flags |= OBJECT_IN_RIGHT_HAND; item2->flags |= OBJECT_IN_RIGHT_HAND;
itemAdd(a2, item2, 1); itemAdd(target, item2, 1);
} }
if (armor != NULL) { if (armor != NULL) {
armor->flags |= OBJECT_WORN; armor->flags |= OBJECT_WORN;
itemAdd(a2, armor, 1); itemAdd(target, armor, 1);
} }
} }
itemMoveAll(a1a, a2); itemMoveAll(hiddenBox, target);
objectDestroy(a1a, NULL); objectDestroy(hiddenBox, NULL);
if (_gIsSteal) { if (_gIsSteal && !isCaughtStealing && stealingXp > 0 && !objectIsPartyMember(target)) {
if (!isCaughtStealing) { stealingXp = std::min(300 - skillGetValue(looter, SKILL_STEAL), stealingXp);
if (stealingXp > 0) { debugPrint("\n[[[%d]]]", 300 - skillGetValue(looter, SKILL_STEAL));
if (!objectIsPartyMember(a2)) {
stealingXp = std::min(300 - skillGetValue(a1, SKILL_STEAL), stealingXp);
debugPrint("\n[[[%d]]]", 300 - skillGetValue(a1, SKILL_STEAL));
// SFALL: Display actual xp received. // SFALL: Display actual xp received.
int xpGained; int xpGained;
pcAddExperience(stealingXp, &xpGained); pcAddExperience(stealingXp, &xpGained);
// You gain %d experience points for successfully using your Steal skill. // You gain %d experience points for successfully using your Steal skill.
messageListItem.num = 29; messageListItem.num = 29;
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
char formattedText[200]; char formattedText[200];
snprintf(formattedText, sizeof(formattedText), messageListItem.text, xpGained); snprintf(formattedText, sizeof(formattedText), messageListItem.text, xpGained);
displayMonitorAddMessage(formattedText); displayMonitorAddMessage(formattedText);
}
}
}
} }
} }
@ -4477,36 +4477,30 @@ int inventoryOpenLooting(Object* a1, Object* a2)
// NOTE: Uninline. // NOTE: Uninline.
inventoryCommonFree(); inventoryCommonFree();
if (_gIsSteal) { if (_gIsSteal && isCaughtStealing && _gStealCount > 0 && _obj_sid(target, &sid) != -1) {
if (isCaughtStealing) { scriptSetObjects(sid, looter, NULL);
if (_gStealCount > 0) { scriptExecProc(sid, SCRIPT_PROC_PICKUP);
if (_obj_sid(a2, &sid) != -1) {
scriptSetObjects(sid, a1, NULL);
scriptExecProc(sid, SCRIPT_PROC_PICKUP);
// TODO: Looks like inlining, script is not used. // TODO: Looks like inlining, script is not used.
Script* script; Script* script;
scriptGetScript(sid, &script); scriptGetScript(sid, &script);
}
}
}
} }
return 0; return 0;
} }
// 0x4746A0 // 0x4746A0
int inventoryOpenStealing(Object* a1, Object* a2) int inventoryOpenStealing(Object* thief, Object* target)
{ {
if (a1 == a2) { if (thief == target) {
return -1; return -1;
} }
_gIsSteal = PID_TYPE(a1->pid) == OBJ_TYPE_CRITTER && critterIsActive(a2); _gIsSteal = PID_TYPE(thief->pid) == OBJ_TYPE_CRITTER && critterIsActive(target);
_gStealCount = 0; _gStealCount = 0;
_gStealSize = 0; _gStealSize = 0;
int rc = inventoryOpenLooting(a1, a2); int rc = inventoryOpenLooting(thief, target);
_gIsSteal = 0; _gIsSteal = 0;
_gStealCount = 0; _gStealCount = 0;
@ -4516,37 +4510,37 @@ int inventoryOpenStealing(Object* a1, Object* a2)
} }
// 0x474708 // 0x474708
static int _move_inventory(Object* a1, int a2, Object* a3, bool a4) static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting)
{ {
bool v38 = true; bool needRefresh = true;
Rect rect; Rect rect;
int quantity; int quantity;
if (a4) { if (isPlanting) {
rect.left = INVENTORY_LOOT_LEFT_SCROLLER_X; rect.left = INVENTORY_LOOT_LEFT_SCROLLER_X;
rect.top = INVENTORY_SLOT_HEIGHT * a2 + INVENTORY_LOOT_LEFT_SCROLLER_Y; rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + INVENTORY_LOOT_LEFT_SCROLLER_Y;
InventoryItem* inventoryItem = &(_pud->items[_pud->length - (a2 + _stack_offset[_curr_stack] + 1)]); InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + _stack_offset[_curr_stack] + 1)]);
quantity = inventoryItem->quantity; quantity = inventoryItem->quantity;
if (quantity > 1) { if (quantity > 1) {
_display_inventory(_stack_offset[_curr_stack], a2, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], slotIndex, INVENTORY_WINDOW_TYPE_LOOT);
v38 = false; needRefresh = false;
} }
} else { } else {
rect.left = INVENTORY_LOOT_RIGHT_SCROLLER_X; rect.left = INVENTORY_LOOT_RIGHT_SCROLLER_X;
rect.top = INVENTORY_SLOT_HEIGHT * a2 + INVENTORY_LOOT_RIGHT_SCROLLER_Y; rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + INVENTORY_LOOT_RIGHT_SCROLLER_Y;
InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (a2 + _target_stack_offset[_target_curr_stack] + 1)]); InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (slotIndex + _target_stack_offset[_target_curr_stack] + 1)]);
quantity = inventoryItem->quantity; quantity = inventoryItem->quantity;
if (quantity > 1) { if (quantity > 1) {
_display_target_inventory(_target_stack_offset[_target_curr_stack], a2, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_target_inventory(_target_stack_offset[_target_curr_stack], slotIndex, _target_pud, INVENTORY_WINDOW_TYPE_LOOT);
windowRefresh(gInventoryWindow); windowRefresh(gInventoryWindow);
v38 = false; needRefresh = false;
} }
} }
if (v38) { if (needRefresh) {
unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow); unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow);
FrmImage backgroundFrmImage; FrmImage backgroundFrmImage;
@ -4566,7 +4560,7 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
} }
FrmImage itemInventoryFrmImage; FrmImage itemInventoryFrmImage;
int itemInventoryFid = itemGetInventoryFid(a1); int itemInventoryFid = itemGetInventoryFid(item);
if (itemInventoryFrmImage.lock(itemInventoryFid)) { if (itemInventoryFrmImage.lock(itemInventoryFid)) {
int width = itemInventoryFrmImage.getWidth(); int width = itemInventoryFrmImage.getWidth();
int height = itemInventoryFrmImage.getHeight(); int height = itemInventoryFrmImage.getHeight();
@ -4589,28 +4583,28 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
soundPlayFile("iputdown"); soundPlayFile("iputdown");
} }
int rc = 0; InventoryMoveResult result = INVENTORY_MOVE_RESULT_FAILED;
MessageListItem messageListItem; MessageListItem messageListItem;
if (a4) { if (isPlanting) {
if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_LOOT_RIGHT_SCROLLER_X, INVENTORY_LOOT_RIGHT_SCROLLER_Y, INVENTORY_LOOT_RIGHT_SCROLLER_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_LOOT_RIGHT_SCROLLER_Y)) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_LOOT_RIGHT_SCROLLER_X, INVENTORY_LOOT_RIGHT_SCROLLER_Y, INVENTORY_LOOT_RIGHT_SCROLLER_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_LOOT_RIGHT_SCROLLER_Y)) {
int quantityToMove; int quantityToMove;
if (quantity > 1) { if (quantity > 1) {
quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity); quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity);
} else { } else {
quantityToMove = 1; quantityToMove = 1;
} }
if (quantityToMove != -1) { if (quantityToMove != -1) {
if (_gIsSteal) { if (_gIsSteal) {
if (skillsPerformStealing(_inven_dude, a3, a1, true) == 0) { if (skillsPerformStealing(_inven_dude, targetObj, item, true) == 0) {
rc = 1; result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
} }
} }
if (rc != 1) { if (result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
if (itemMove(_inven_dude, a3, a1, quantityToMove) != -1) { if (itemMove(_inven_dude, targetObj, item, quantityToMove) != -1) {
rc = 2; result = INVENTORY_MOVE_RESULT_SUCCESS;
} else { } else {
// There is no space left for that item. // There is no space left for that item.
messageListItem.num = 26; messageListItem.num = 26;
@ -4625,27 +4619,27 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_LOOT_LEFT_SCROLLER_X, INVENTORY_LOOT_LEFT_SCROLLER_Y, INVENTORY_LOOT_LEFT_SCROLLER_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_LOOT_LEFT_SCROLLER_Y)) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_LOOT_LEFT_SCROLLER_X, INVENTORY_LOOT_LEFT_SCROLLER_Y, INVENTORY_LOOT_LEFT_SCROLLER_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_LOOT_LEFT_SCROLLER_Y)) {
int quantityToMove; int quantityToMove;
if (quantity > 1) { if (quantity > 1) {
quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity); quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity);
} else { } else {
quantityToMove = 1; quantityToMove = 1;
} }
if (quantityToMove != -1) { if (quantityToMove != -1) {
if (_gIsSteal) { if (_gIsSteal) {
if (skillsPerformStealing(_inven_dude, a3, a1, false) == 0) { if (skillsPerformStealing(_inven_dude, targetObj, item, false) == 0) {
rc = 1; result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
} }
} }
if (rc != 1) { if (result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
if (itemMove(a3, _inven_dude, a1, quantityToMove) == 0) { if (itemMove(targetObj, _inven_dude, item, quantityToMove) == 0) {
if ((a1->flags & OBJECT_IN_RIGHT_HAND) != 0) { if ((item->flags & OBJECT_IN_RIGHT_HAND) != 0) {
a3->fid = buildFid(FID_TYPE(a3->fid), a3->fid & 0xFFF, FID_ANIM_TYPE(a3->fid), 0, a3->rotation + 1); targetObj->fid = buildFid(FID_TYPE(targetObj->fid), targetObj->fid & 0xFFF, FID_ANIM_TYPE(targetObj->fid), 0, targetObj->rotation + 1);
} }
a3->flags &= ~OBJECT_EQUIPPED; targetObj->flags &= ~OBJECT_EQUIPPED;
rc = 2; result = INVENTORY_MOVE_RESULT_SUCCESS;
} else { } else {
// You cannot pick that up. You are at your maximum weight capacity. // You cannot pick that up. You are at your maximum weight capacity.
messageListItem.num = 25; messageListItem.num = 25;
@ -4660,7 +4654,7 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND);
return rc; return result;
} }
// 0x474B2C // 0x474B2C
@ -5022,67 +5016,67 @@ static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a
} }
// 0x4757F0 // 0x4757F0
void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5) void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* bartererTable, int barterMod)
{ {
ScopedGameMode gm(GameMode::kBarter); ScopedGameMode gm(GameMode::kBarter);
_barter_mod = a5; _barter_mod = barterMod;
if (inventoryCommonInit() == -1) { if (inventoryCommonInit() == -1) {
return; return;
} }
Object* armor = critterGetArmor(a2); Object* armor = critterGetArmor(barterer);
if (armor != NULL) { if (armor != NULL) {
itemRemove(a2, armor, 1); itemRemove(barterer, armor, 1);
} }
Object* item1 = NULL; Object* item1 = NULL;
Object* item2 = critterGetItem2(a2); Object* item2 = critterGetItem2(barterer);
if (item2 != NULL) { if (item2 != NULL) {
itemRemove(a2, item2, 1); itemRemove(barterer, item2, 1);
} else { } else {
if (!gGameDialogSpeakerIsPartyMember) { if (!gGameDialogSpeakerIsPartyMember) {
item1 = _inven_find_type(a2, ITEM_TYPE_WEAPON, NULL); item1 = _inven_find_type(barterer, ITEM_TYPE_WEAPON, NULL);
if (item1 != NULL) { if (item1 != NULL) {
itemRemove(a2, item1, 1); itemRemove(barterer, item1, 1);
} }
} }
} }
Object* a1a = NULL; Object* hiddenBox = NULL;
if (objectCreateWithFidPid(&a1a, 0, 467) == -1) { if (objectCreateWithFidPid(&hiddenBox, 0, PROTO_ID_JESSE_CONTAINER) == -1) {
return; return;
} }
_pud = &(_inven_dude->data.inventory); _pud = &(_inven_dude->data.inventory);
_btable = a4; _btable = bartererTable;
_ptable = a3; _ptable = playerTable;
_ptable_offset = 0; _ptable_offset = 0;
_btable_offset = 0; _btable_offset = 0;
_ptable_pud = &(a3->data.inventory); _ptable_pud = &(playerTable->data.inventory);
_btable_pud = &(a4->data.inventory); _btable_pud = &(bartererTable->data.inventory);
_barter_back_win = win; _barter_back_win = win;
_target_curr_stack = 0; _target_curr_stack = 0;
_target_pud = &(a2->data.inventory); _target_pud = &(barterer->data.inventory);
_target_stack[0] = a2; _target_stack[0] = barterer;
_target_stack_offset[0] = 0; _target_stack_offset[0] = 0;
bool isoWasEnabled = _setup_inventory(INVENTORY_WINDOW_TYPE_TRADE); bool isoWasEnabled = _setup_inventory(INVENTORY_WINDOW_TYPE_TRADE);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[0], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[0], -1, INVENTORY_WINDOW_TYPE_TRADE);
_display_body(a2->fid, INVENTORY_WINDOW_TYPE_TRADE); _display_body(barterer->fid, INVENTORY_WINDOW_TYPE_TRADE);
windowRefresh(_barter_back_win); windowRefresh(_barter_back_win);
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND);
int modifier; int modifier;
int npcReactionValue = reactionGetValue(a2); int npcReactionValue = reactionGetValue(barterer);
int npcReactionType = reactionTranslateValue(npcReactionValue); int npcReactionType = reactionTranslateValue(npcReactionValue);
switch (npcReactionType) { switch (npcReactionType) {
case NPC_REACTION_BAD: case NPC_REACTION_BAD:
@ -5115,19 +5109,19 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
break; break;
} }
_barter_mod = a5 + modifier; _barter_mod = barterMod + modifier;
if (keyCode == KEY_LOWERCASE_T || modifier <= -30) { if (keyCode == KEY_LOWERCASE_T || modifier <= -30) {
itemMoveAll(a4, a2); itemMoveAll(bartererTable, barterer);
itemMoveAll(a3, gDude); itemMoveAll(playerTable, gDude);
_barter_end_to_talk_to(); _barter_end_to_talk_to();
break; break;
} else if (keyCode == KEY_LOWERCASE_M) { } else if (keyCode == KEY_LOWERCASE_M) {
if (a3->data.inventory.length != 0 || _btable->data.inventory.length != 0) { if (playerTable->data.inventory.length != 0 || _btable->data.inventory.length != 0) {
if (_barter_attempt_transaction(_inven_dude, a3, a2, a4) == 0) { if (_barter_attempt_transaction(_inven_dude, playerTable, barterer, bartererTable) == 0) {
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
// Ok, that's a good trade. // Ok, that's a good trade.
MessageListItem messageListItem; MessageListItem messageListItem;
@ -5147,7 +5141,7 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
} else if (keyCode == KEY_PAGE_UP) { } else if (keyCode == KEY_PAGE_UP) {
if (_ptable_offset > 0) { if (_ptable_offset > 0) {
_ptable_offset -= 1; _ptable_offset -= 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (keyCode == KEY_ARROW_DOWN) { } else if (keyCode == KEY_ARROW_DOWN) {
if (_stack_offset[_curr_stack] + gInventorySlotsCount < _pud->length) { if (_stack_offset[_curr_stack] + gInventorySlotsCount < _pud->length) {
@ -5157,17 +5151,17 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
} else if (keyCode == KEY_PAGE_DOWN) { } else if (keyCode == KEY_PAGE_DOWN) {
if (_ptable_offset + gInventorySlotsCount < _ptable_pud->length) { if (_ptable_offset + gInventorySlotsCount < _ptable_pud->length) {
_ptable_offset += 1; _ptable_offset += 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (keyCode == KEY_CTRL_PAGE_DOWN) { } else if (keyCode == KEY_CTRL_PAGE_DOWN) {
if (_btable_offset + gInventorySlotsCount < _btable_pud->length) { if (_btable_offset + gInventorySlotsCount < _btable_pud->length) {
_btable_offset++; _btable_offset++;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (keyCode == KEY_CTRL_PAGE_UP) { } else if (keyCode == KEY_CTRL_PAGE_UP) {
if (_btable_offset > 0) { if (_btable_offset > 0) {
_btable_offset -= 1; _btable_offset -= 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (keyCode == KEY_CTRL_ARROW_UP) { } else if (keyCode == KEY_CTRL_ARROW_UP) {
if (_target_stack_offset[_target_curr_stack] > 0) { if (_target_stack_offset[_target_curr_stack] > 0) {
@ -5194,16 +5188,16 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
if (keyCode >= 1000 && keyCode <= 1000 + gInventorySlotsCount) { if (keyCode >= 1000 && keyCode <= 1000 + gInventorySlotsCount) {
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, a3, NULL, -1); inventoryWindowRenderInnerInventories(win, playerTable, NULL, -1);
} else { } else {
int v30 = keyCode - 1000; int slotIndex = keyCode - 1000;
if (v30 + _stack_offset[_curr_stack] < _pud->length) { if (slotIndex + _stack_offset[_curr_stack] < _pud->length) {
int v31 = _stack_offset[_curr_stack]; int stackOffset = _stack_offset[_curr_stack];
InventoryItem* inventoryItem = &(_pud->items[_pud->length - (v30 + v31 + 1)]); InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + stackOffset + 1)]);
_barter_move_inventory(inventoryItem->item, inventoryItem->quantity, v30, v31, a2, a3, true); _barter_move_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, stackOffset, barterer, playerTable, true);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, a3, NULL, -1); inventoryWindowRenderInnerInventories(win, playerTable, NULL, -1);
} }
} }
@ -5211,16 +5205,16 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
} else if (keyCode >= 2000 && keyCode <= 2000 + gInventorySlotsCount) { } else if (keyCode >= 2000 && keyCode <= 2000 + gInventorySlotsCount) {
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, NULL, a4, -1); inventoryWindowRenderInnerInventories(win, NULL, bartererTable, -1);
} else { } else {
int v35 = keyCode - 2000; int slotIndex = keyCode - 2000;
if (v35 + _target_stack_offset[_target_curr_stack] < _target_pud->length) { if (slotIndex + _target_stack_offset[_target_curr_stack] < _target_pud->length) {
int v36 = _target_stack_offset[_target_curr_stack]; int stackOffset = _target_stack_offset[_target_curr_stack];
InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (v35 + v36 + 1)]); InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (slotIndex + stackOffset + 1)]);
_barter_move_inventory(inventoryItem->item, inventoryItem->quantity, v35, v36, a2, a4, false); _barter_move_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, stackOffset, barterer, bartererTable, false);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, NULL, a4, -1); inventoryWindowRenderInnerInventories(win, NULL, bartererTable, -1);
} }
} }
@ -5228,15 +5222,15 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
} else if (keyCode >= 2300 && keyCode <= 2300 + gInventorySlotsCount) { } else if (keyCode >= 2300 && keyCode <= 2300 + gInventorySlotsCount) {
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, a3, NULL, -1); inventoryWindowRenderInnerInventories(win, playerTable, NULL, -1);
} else { } else {
int v41 = keyCode - 2300; int itemIndex = keyCode - 2300;
if (v41 < _ptable_pud->length) { if (itemIndex < _ptable_pud->length) {
InventoryItem* inventoryItem = &(_ptable_pud->items[_ptable_pud->length - (v41 + _ptable_offset + 1)]); InventoryItem* inventoryItem = &(_ptable_pud->items[_ptable_pud->length - (itemIndex + _ptable_offset + 1)]);
_barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, v41, a2, a3, true); _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, itemIndex, barterer, playerTable, true);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, a3, NULL, -1); inventoryWindowRenderInnerInventories(win, playerTable, NULL, -1);
} }
} }
@ -5244,15 +5238,15 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
} else if (keyCode >= 2400 && keyCode <= 2400 + gInventorySlotsCount) { } else if (keyCode >= 2400 && keyCode <= 2400 + gInventorySlotsCount) {
if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) { if (gInventoryCursor == INVENTORY_WINDOW_CURSOR_ARROW) {
inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, NULL, a4, -1); inventoryWindowRenderInnerInventories(win, NULL, bartererTable, -1);
} else { } else {
int v45 = keyCode - 2400; int v45 = keyCode - 2400;
if (v45 < _btable_pud->length) { if (v45 < _btable_pud->length) {
InventoryItem* inventoryItem = &(_btable_pud->items[_btable_pud->length - (v45 + _btable_offset + 1)]); InventoryItem* inventoryItem = &(_btable_pud->items[_btable_pud->length - (v45 + _btable_offset + 1)]);
_barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, v45, a2, a4, false); _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, v45, barterer, bartererTable, false);
_display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_TRADE);
_display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_TRADE);
inventoryWindowRenderInnerInventories(win, NULL, a4, -1); inventoryWindowRenderInnerInventories(win, NULL, bartererTable, -1);
} }
} }
@ -5281,12 +5275,12 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
if (wheelY > 0) { if (wheelY > 0) {
if (_ptable_offset > 0) { if (_ptable_offset > 0) {
_ptable_offset -= 1; _ptable_offset -= 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (wheelY < 0) { } else if (wheelY < 0) {
if (_ptable_offset + gInventorySlotsCount < _ptable_pud->length) { if (_ptable_offset + gInventorySlotsCount < _ptable_pud->length) {
_ptable_offset += 1; _ptable_offset += 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} }
} else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y)) { } else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y)) {
@ -5313,12 +5307,12 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
if (wheelY > 0) { if (wheelY > 0) {
if (_btable_offset > 0) { if (_btable_offset > 0) {
_btable_offset -= 1; _btable_offset -= 1;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} else if (wheelY < 0) { } else if (wheelY < 0) {
if (_btable_offset + gInventorySlotsCount < _btable_pud->length) { if (_btable_offset + gInventorySlotsCount < _btable_pud->length) {
_btable_offset++; _btable_offset++;
inventoryWindowRenderInnerInventories(win, a3, a4, -1); inventoryWindowRenderInnerInventories(win, playerTable, bartererTable, -1);
} }
} }
} }
@ -5329,21 +5323,21 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5)
sharedFpsLimiter.throttle(); sharedFpsLimiter.throttle();
} }
itemMoveAll(a1a, a2); itemMoveAll(hiddenBox, barterer);
objectDestroy(a1a, NULL); objectDestroy(hiddenBox, NULL);
if (armor != NULL) { if (armor != NULL) {
armor->flags |= OBJECT_WORN; armor->flags |= OBJECT_WORN;
itemAdd(a2, armor, 1); itemAdd(barterer, armor, 1);
} }
if (item2 != NULL) { if (item2 != NULL) {
item2->flags |= OBJECT_IN_RIGHT_HAND; item2->flags |= OBJECT_IN_RIGHT_HAND;
itemAdd(a2, item2, 1); itemAdd(barterer, item2, 1);
} }
if (item1 != NULL) { if (item1 != NULL) {
itemAdd(a2, item1, 1); itemAdd(barterer, item1, 1);
} }
_exit_inventory(isoWasEnabled); _exit_inventory(isoWasEnabled);

View File

@ -23,9 +23,9 @@ int _inven_wield(Object* a1, Object* a2, int a3);
int _invenWieldFunc(Object* a1, Object* a2, int a3, bool a4); int _invenWieldFunc(Object* a1, Object* a2, int a3, bool a4);
int _inven_unwield(Object* critter_obj, int a2); int _inven_unwield(Object* critter_obj, int a2);
int _invenUnwieldFunc(Object* obj, int a2, int a3); int _invenUnwieldFunc(Object* obj, int a2, int a3);
int inventoryOpenLooting(Object* a1, Object* a2); int inventoryOpenLooting(Object* looter, Object* target);
int inventoryOpenStealing(Object* a1, Object* a2); int inventoryOpenStealing(Object* thief, Object* target);
void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5); void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* bartererTable, int barterMod);
int _inven_set_timer(Object* a1); int _inven_set_timer(Object* a1);
Object* inven_get_current_target_obj(); Object* inven_get_current_target_obj();

View File

@ -43,8 +43,8 @@ namespace fallout {
static int _item_load_(File* stream); static int _item_load_(File* stream);
static void _item_compact(int inventoryItemIndex, Inventory* inventory); static void _item_compact(int inventoryItemIndex, Inventory* inventory);
static int _item_move_func(Object* a1, Object* a2, Object* a3, int quantity, bool a5); static int _item_move_func(Object* source, Object* target, Object* item, int quantity, bool force);
static bool _item_identical(Object* a1, Object* a2); static bool _item_identical(Object* item1, Object* item2);
static int stealthBoyTurnOn(Object* object); static int stealthBoyTurnOn(Object* object);
static int stealthBoyTurnOff(Object* critter, Object* item); static int stealthBoyTurnOff(Object* critter, Object* item);
static int _insert_drug_effect(Object* critter_obj, Object* item_obj, int a3, int* stats, int* mods); static int _insert_drug_effect(Object* critter_obj, Object* item_obj, int a3, int* stats, int* mods);
@ -301,7 +301,7 @@ int itemAttemptAdd(Object* owner, Object* itemToAdd, int quantity)
return -5; return -5;
} }
if ((proto->critter.flags & 0x02) == 0) { if ((proto->critter.flags & CRITTER_BARTER) == 0) {
return -5; return -5;
} }
} }
@ -475,36 +475,36 @@ static void _item_compact(int inventoryItemIndex, Inventory* inventory)
} }
// 0x477608 // 0x477608
static int _item_move_func(Object* a1, Object* a2, Object* a3, int quantity, bool a5) static int _item_move_func(Object* source, Object* target, Object* item, int quantity, bool force)
{ {
if (itemRemove(a1, a3, quantity) == -1) { if (itemRemove(source, item, quantity) == -1) {
return -1; return -1;
} }
int rc; int rc;
if (a5) { if (force) {
rc = itemAdd(a2, a3, quantity); rc = itemAdd(target, item, quantity);
} else { } else {
rc = itemAttemptAdd(a2, a3, quantity); rc = itemAttemptAdd(target, item, quantity);
} }
if (rc != 0) { if (rc != 0) {
if (itemAdd(a1, a3, quantity) != 0) { if (itemAdd(source, item, quantity) != 0) {
Object* owner = objectGetOwner(a1); Object* owner = objectGetOwner(source);
if (owner == NULL) { if (owner == NULL) {
owner = a1; owner = source;
} }
if (owner->tile != -1) { if (owner->tile != -1) {
Rect updatedRect; Rect updatedRect;
_obj_connect(a3, owner->tile, owner->elevation, &updatedRect); _obj_connect(item, owner->tile, owner->elevation, &updatedRect);
tileWindowRefreshRect(&updatedRect, gElevation); tileWindowRefreshRect(&updatedRect, gElevation);
} }
} }
return -1; return -1;
} }
a3->owner = a2; item->owner = target;
return 0; return 0;
} }
@ -645,53 +645,53 @@ int itemDropAll(Object* critter, int tile)
} }
// 0x4779F0 // 0x4779F0
static bool _item_identical(Object* a1, Object* a2) static bool _item_identical(Object* item1, Object* item2)
{ {
if (a1->pid != a2->pid) { if (item1->pid != item2->pid) {
return false; return false;
} }
if (a1->sid != a2->sid) { if (item1->sid != item2->sid) {
return false; return false;
} }
if ((a1->flags & (OBJECT_EQUIPPED | OBJECT_QUEUED)) != 0) { if ((item1->flags & (OBJECT_EQUIPPED | OBJECT_QUEUED)) != 0) {
return false; return false;
} }
if ((a2->flags & (OBJECT_EQUIPPED | OBJECT_QUEUED)) != 0) { if ((item2->flags & (OBJECT_EQUIPPED | OBJECT_QUEUED)) != 0) {
return false; return false;
} }
Proto* proto; Proto* proto;
protoGetProto(a1->pid, &proto); protoGetProto(item1->pid, &proto);
if (proto->item.type == ITEM_TYPE_CONTAINER) { if (proto->item.type == ITEM_TYPE_CONTAINER) {
return false; return false;
} }
Inventory* inventory1 = &(a1->data.inventory); Inventory* inventory1 = &(item1->data.inventory);
Inventory* inventory2 = &(a2->data.inventory); Inventory* inventory2 = &(item2->data.inventory);
if (inventory1->length != 0 || inventory2->length != 0) { if (inventory1->length != 0 || inventory2->length != 0) {
return false; return false;
} }
int v1; int v1;
if (proto->item.type == ITEM_TYPE_AMMO || a1->pid == PROTO_ID_MONEY) { if (proto->item.type == ITEM_TYPE_AMMO || item1->pid == PROTO_ID_MONEY) {
v1 = a2->data.item.ammo.quantity; v1 = item2->data.item.ammo.quantity;
a2->data.item.ammo.quantity = a1->data.item.ammo.quantity; item2->data.item.ammo.quantity = item1->data.item.ammo.quantity;
} }
// NOTE: Probably inlined memcmp, but I'm not sure why it only checks 32 // NOTE: Probably inlined memcmp, but I'm not sure why it only checks 32
// bytes. // bytes.
int i; int i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (a1->field_2C_array[i] != a2->field_2C_array[i]) { if (item1->field_2C_array[i] != item2->field_2C_array[i]) {
break; break;
} }
} }
if (proto->item.type == ITEM_TYPE_AMMO || a1->pid == PROTO_ID_MONEY) { if (proto->item.type == ITEM_TYPE_AMMO || item1->pid == PROTO_ID_MONEY) {
a2->data.item.ammo.quantity = v1; item2->data.item.ammo.quantity = v1;
} }
return i == 8; return i == 8;

View File

@ -1083,29 +1083,29 @@ static int _protinstTestDroppedExplosive(Object* a1)
_compute_explosion_on_extras(&attack, 0, 0, 1); _compute_explosion_on_extras(&attack, 0, 0, 1);
int team = gDude->data.critter.combat.team; int team = gDude->data.critter.combat.team;
Object* v2 = NULL; Object* watcher = NULL;
for (int index = 0; index < attack.extrasLength; index++) { for (int index = 0; index < attack.extrasLength; index++) {
Object* v5 = attack.extras[index]; Object* v5 = attack.extras[index];
if (v5 != gDude if (v5 != gDude
&& v5->data.critter.combat.team != team && v5->data.critter.combat.team != team
&& statRoll(v5, STAT_PERCEPTION, 0, NULL) >= 2) { && statRoll(v5, STAT_PERCEPTION, 0, NULL) >= 2) {
_critter_set_who_hit_me(v5, gDude); _critter_set_who_hit_me(v5, gDude);
if (v2 == NULL) { if (watcher == NULL) {
v2 = v5; watcher = v5;
} }
} }
} }
if (v2 != NULL && !isInCombat()) { if (watcher != NULL && !isInCombat()) {
STRUCT_664980 attack; CombatStartData combat;
attack.attacker = v2; combat.attacker = watcher;
attack.defender = gDude; combat.defender = gDude;
attack.actionPointsBonus = 0; combat.actionPointsBonus = 0;
attack.accuracyBonus = 0; combat.accuracyBonus = 0;
attack.minDamage = 0; combat.minDamage = 0;
attack.maxDamage = 99999; combat.maxDamage = 99999;
attack.field_1C = 0; combat.overrideAttackResults = 0;
scriptsRequestCombat(&attack); scriptsRequestCombat(&combat);
} }
} }
return 0; return 0;

View File

@ -182,6 +182,7 @@ enum {
PROTO_ID_MIRRORED_SHADES = 433, PROTO_ID_MIRRORED_SHADES = 433,
PROTO_ID_RAIDERS_MAP = 444, PROTO_ID_RAIDERS_MAP = 444,
PROTO_ID_CAR_TRUNK = 455, PROTO_ID_CAR_TRUNK = 455,
PROTO_ID_JESSE_CONTAINER = 467,
PROTO_ID_PIP_BOY_LINGUAL_ENHANCER = 499, PROTO_ID_PIP_BOY_LINGUAL_ENHANCER = 499,
PROTO_ID_PIP_BOY_MEDICAL_ENHANCER = 516, PROTO_ID_PIP_BOY_MEDICAL_ENHANCER = 516,
PROTO_ID_SURVEY_MAP = 523, PROTO_ID_SURVEY_MAP = 523,

View File

@ -37,7 +37,7 @@ typedef struct EventTypeDescription {
static int flareEventProcess(Object* obj, void* data); static int flareEventProcess(Object* obj, void* data);
static int explosionEventProcess(Object* obj, void* data); static int explosionEventProcess(Object* obj, void* data);
static int _queue_explode_exit(Object* obj, void* data); static int _queue_explode_exit(Object* obj, void* data);
static int _queue_do_explosion_(Object* obj, bool a2); static int _queue_do_explosion_(Object* obj, bool animate);
static int explosionFailureEventProcess(Object* obj, void* data); static int explosionFailureEventProcess(Object* obj, void* data);
// Last queue list node found during [queueFindFirstEvent] and // Last queue list node found during [queueFindFirstEvent] and
@ -454,7 +454,7 @@ static int _queue_explode_exit(Object* obj, void* data)
} }
// 0x4A2834 // 0x4A2834
static int _queue_do_explosion_(Object* explosive, bool a2) static int _queue_do_explosion_(Object* explosive, bool animate)
{ {
int tile; int tile;
int elevation; int elevation;
@ -483,7 +483,7 @@ static int _queue_do_explosion_(Object* explosive, bool a2)
} }
} }
if (actionExplode(tile, elevation, minDamage, maxDamage, gDude, a2) == -2) { if (actionExplode(tile, elevation, minDamage, maxDamage, gDude, animate) == -2) {
queueAddEvent(50, explosive, NULL, EVENT_TYPE_EXPLOSION); queueAddEvent(50, explosive, NULL, EVENT_TYPE_EXPLOSION);
} else { } else {
_obj_destroy(explosive); _obj_destroy(explosive);

View File

@ -213,10 +213,10 @@ static char* _blank_str = byte_50D6C0;
static unsigned int gScriptsRequests; static unsigned int gScriptsRequests;
// 0x664958 // 0x664958
static STRUCT_664980 stru_664958; static CombatStartData gScriptsRequestedCSD;
// 0x664980 // 0x664980
static STRUCT_664980 stru_664980; static CombatStartData gScriptsCSD;
// 0x6649A8 // 0x6649A8
static int gScriptsRequestedElevatorType; static int gScriptsRequestedElevatorType;
@ -884,7 +884,7 @@ static int scriptsClearPendingRequests()
// 0x4A3F90 // 0x4A3F90
int _scripts_clear_combat_requests(Script* script) int _scripts_clear_combat_requests(Script* script)
{ {
if ((gScriptsRequests & SCRIPT_REQUEST_COMBAT) != 0 && stru_664958.attacker == script->owner) { if ((gScriptsRequests & SCRIPT_REQUEST_COMBAT) != 0 && gScriptsRequestedCSD.attacker == script->owner) {
gScriptsRequests &= ~(SCRIPT_REQUEST_0x0400 | SCRIPT_REQUEST_COMBAT); gScriptsRequests &= ~(SCRIPT_REQUEST_0x0400 | SCRIPT_REQUEST_COMBAT);
} }
return 0; return 0;
@ -901,14 +901,14 @@ int scriptsHandleRequests()
if (!_action_explode_running()) { if (!_action_explode_running()) {
// entering combat // entering combat
gScriptsRequests &= ~(SCRIPT_REQUEST_0x0400 | SCRIPT_REQUEST_COMBAT); gScriptsRequests &= ~(SCRIPT_REQUEST_0x0400 | SCRIPT_REQUEST_COMBAT);
memcpy(&stru_664980, &stru_664958, sizeof(stru_664980)); memcpy(&gScriptsCSD, &gScriptsRequestedCSD, sizeof(gScriptsCSD));
if ((gScriptsRequests & SCRIPT_REQUEST_0x40) != 0) { if ((gScriptsRequests & SCRIPT_REQUEST_0x40) != 0) {
gScriptsRequests &= ~SCRIPT_REQUEST_0x40; gScriptsRequests &= ~SCRIPT_REQUEST_0x40;
_combat(NULL); _combat(NULL);
} else { } else {
_combat(&stru_664980); _combat(&gScriptsCSD);
memset(&stru_664980, 0, sizeof(stru_664980)); memset(&gScriptsCSD, 0, sizeof(gScriptsCSD));
} }
} }
} }
@ -1097,14 +1097,14 @@ int _scripts_check_state_in_combat()
} }
// 0x4A457C // 0x4A457C
int scriptsRequestCombat(STRUCT_664980* a1) int scriptsRequestCombat(CombatStartData* combat)
{ {
if ((gScriptsRequests & SCRIPT_REQUEST_0x0400) != 0) { if ((gScriptsRequests & SCRIPT_REQUEST_0x0400) != 0) {
return -1; return -1;
} }
if (a1) { if (combat) {
memcpy(&stru_664958, a1, sizeof(stru_664958)); memcpy(&gScriptsRequestedCSD, combat, sizeof(gScriptsRequestedCSD));
} else { } else {
gScriptsRequests |= SCRIPT_REQUEST_0x40; gScriptsRequests |= SCRIPT_REQUEST_0x40;
} }
@ -1117,10 +1117,10 @@ int scriptsRequestCombat(STRUCT_664980* a1)
// Likely related to random encounter, ala scriptsRequestRandomEncounter RELEASE // Likely related to random encounter, ala scriptsRequestRandomEncounter RELEASE
// //
// 0x4A45D4 // 0x4A45D4
void _scripts_request_combat_locked(STRUCT_664980* a1) void _scripts_request_combat_locked(CombatStartData* combat)
{ {
if (a1 != NULL) { if (combat != NULL) {
memcpy(&stru_664958, a1, sizeof(stru_664958)); memcpy(&gScriptsRequestedCSD, combat, sizeof(gScriptsRequestedCSD));
} else { } else {
gScriptsRequests |= SCRIPT_REQUEST_0x40; gScriptsRequests |= SCRIPT_REQUEST_0x40;
} }

View File

@ -175,8 +175,8 @@ int scriptEventProcess(Object* obj, void* data);
int _scripts_clear_combat_requests(Script* script); int _scripts_clear_combat_requests(Script* script);
int scriptsHandleRequests(); int scriptsHandleRequests();
int _scripts_check_state_in_combat(); int _scripts_check_state_in_combat();
int scriptsRequestCombat(STRUCT_664980* a1); int scriptsRequestCombat(CombatStartData* combat);
void _scripts_request_combat_locked(STRUCT_664980* ptr); void _scripts_request_combat_locked(CombatStartData* combat);
void scripts_request_townmap(); void scripts_request_townmap();
void scriptsRequestWorldMap(); void scriptsRequestWorldMap();
int scriptsRequestElevator(Object* a1, int a2); int scriptsRequestElevator(Object* a1, int a2);

View File

@ -43,12 +43,12 @@ typedef struct SkillDescription {
int statModifier; int statModifier;
int stat1; int stat1;
int stat2; int stat2;
int field_20; int baseValueMult;
int experience; int experience;
int field_28; int field_28;
} SkillDescription; } SkillDescription;
static void _show_skill_use_messages(Object* obj, int skill, Object* a3, int a4, int a5); static void _show_skill_use_messages(Object* obj, int skill, Object* target, int successCount, int criticalChanceModifier);
static int skillGetFreeUsageSlot(int skill); static int skillGetFreeUsageSlot(int skill);
static int skill_use_slot_clear(); static int skill_use_slot_clear();
@ -240,16 +240,16 @@ int skillGetValue(Object* critter, int skill)
SkillDescription* skillDescription = &(gSkillDescriptions[skill]); SkillDescription* skillDescription = &(gSkillDescriptions[skill]);
int v7 = critterGetStat(critter, skillDescription->stat1); int statValueSum = critterGetStat(critter, skillDescription->stat1);
if (skillDescription->stat2 != -1) { if (skillDescription->stat2 != -1) {
v7 += critterGetStat(critter, skillDescription->stat2); statValueSum += critterGetStat(critter, skillDescription->stat2);
} }
int value = skillDescription->defaultValue + skillDescription->statModifier * v7 + baseValue * skillDescription->field_20; int value = skillDescription->defaultValue + skillDescription->statModifier * statValueSum + baseValue * skillDescription->baseValueMult;
if (critter == gDude) { if (critter == gDude) {
if (skillIsTagged(skill)) { if (skillIsTagged(skill)) {
value += baseValue * skillDescription->field_20; value += baseValue * skillDescription->baseValueMult;
if (!perkGetRank(critter, PERK_TAG) || skill != gTaggedSkills[3]) { if (!perkGetRank(critter, PERK_TAG) || skill != gTaggedSkills[3]) {
value += 20; value += 20;
@ -503,13 +503,13 @@ int skillGetFrmId(int skill)
} }
// 0x4AAC2C // 0x4AAC2C
static void _show_skill_use_messages(Object* obj, int skill, Object* a3, int a4, int criticalChanceModifier) static void _show_skill_use_messages(Object* obj, int skill, Object* target, int successCount, int criticalChanceModifier)
{ {
if (obj != gDude) { if (obj != gDude) {
return; return;
} }
if (a4 <= 0) { if (successCount <= 0) {
return; return;
} }
@ -524,11 +524,11 @@ static void _show_skill_use_messages(Object* obj, int skill, Object* a3, int a4,
baseExperience += abs(criticalChanceModifier); baseExperience += abs(criticalChanceModifier);
} }
int xpToAdd = a4 * baseExperience; int xpToAdd = successCount * baseExperience;
int before = pcGetStat(PC_STAT_EXPERIENCE); int before = pcGetStat(PC_STAT_EXPERIENCE);
if (pcAddExperience(xpToAdd) == 0 && a4 > 0) { if (pcAddExperience(xpToAdd) == 0 && successCount > 0) {
MessageListItem messageListItem; MessageListItem messageListItem;
messageListItem.num = 505; // You earn %d XP for honing your skills messageListItem.num = 505; // You earn %d XP for honing your skills
if (messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (messageListGetItem(&gSkillsMessageList, &messageListItem)) {
@ -543,14 +543,14 @@ static void _show_skill_use_messages(Object* obj, int skill, Object* a3, int a4,
// skill_use // skill_use
// 0x4AAD08 // 0x4AAD08
int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier) int skillUse(Object* obj, Object* target, int skill, int criticalChanceModifier)
{ {
MessageListItem messageListItem; MessageListItem messageListItem;
char text[60]; char text[60];
bool giveExp = true; bool giveExp = true;
int currentHp = critterGetStat(a2, STAT_CURRENT_HIT_POINTS); int currentHp = critterGetStat(target, STAT_CURRENT_HIT_POINTS);
int maximumHp = critterGetStat(a2, STAT_MAXIMUM_HIT_POINTS); int maximumHp = critterGetStat(target, STAT_MAXIMUM_HIT_POINTS);
int hpToHeal = 0; int hpToHeal = 0;
int maximumHpToHeal = 0; int maximumHpToHeal = 0;
@ -567,8 +567,8 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
int criticalChance = critterGetStat(obj, STAT_CRITICAL_CHANCE) + criticalChanceModifier; int criticalChance = critterGetStat(obj, STAT_CRITICAL_CHANCE) + criticalChanceModifier;
int damageHealingAttempts = 1; int damageHealingAttempts = 1;
int v1 = 0; int successCount = 0;
int v2 = 0; bool skillUseSlotAdded = 0;
switch (skill) { switch (skill) {
case SKILL_FIRST_AID: case SKILL_FIRST_AID:
@ -584,7 +584,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
return -1; return -1;
} }
if (critterIsDead(a2)) { if (critterIsDead(target)) {
// 512: You can't heal the dead. // 512: You can't heal the dead.
// 513: Let the dead rest in peace. // 513: Let the dead rest in peace.
// 514: It's dead, get over it. // 514: It's dead, get over it.
@ -600,7 +600,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
paletteFadeTo(gPaletteBlack); paletteFadeTo(gPaletteBlack);
int roll; int roll;
if (critterGetBodyType(a2) == BODY_TYPE_ROBOTIC) { if (critterGetBodyType(target) == BODY_TYPE_ROBOTIC) {
roll = ROLL_FAILURE; roll = ROLL_FAILURE;
} else { } else {
roll = skillRoll(obj, skill, criticalChance, &hpToHeal); roll = skillRoll(obj, skill, criticalChance, &hpToHeal);
@ -608,7 +608,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) { if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) {
hpToHeal = randomBetween(minimumHpToHeal + 1, maximumHpToHeal + 5); hpToHeal = randomBetween(minimumHpToHeal + 1, maximumHpToHeal + 5);
critterAdjustHitPoints(a2, hpToHeal); critterAdjustHitPoints(target, hpToHeal);
if (obj == gDude) { if (obj == gDude) {
// You heal %d hit points. // You heal %d hit points.
@ -625,13 +625,13 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
} }
a2->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; target->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
skillUpdateLastUse(SKILL_FIRST_AID); skillUpdateLastUse(SKILL_FIRST_AID);
v1 = 1; successCount = 1;
if (a2 == gDude) { if (target == gDude) {
interfaceRenderHitPoints(true); interfaceRenderHitPoints(true);
} }
} else { } else {
@ -651,15 +651,15 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (obj == gDude) { if (obj == gDude) {
// 501: You look healty already // 501: You look healty already
// 502: %s looks healthy already // 502: %s looks healthy already
messageListItem.num = (a2 == gDude ? 501 : 502); messageListItem.num = (target == gDude ? 501 : 502);
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
return -1; return -1;
} }
if (a2 == gDude) { if (target == gDude) {
strcpy(text, messageListItem.text); strcpy(text, messageListItem.text);
} else { } else {
snprintf(text, sizeof(text), messageListItem.text, objectGetName(a2)); snprintf(text, sizeof(text), messageListItem.text, objectGetName(target));
} }
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
@ -685,7 +685,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
return -1; return -1;
} }
if (critterIsDead(a2)) { if (critterIsDead(target)) {
// 512: You can't heal the dead. // 512: You can't heal the dead.
// 513: Let the dead rest in peace. // 513: Let the dead rest in peace.
// 514: It's dead, get over it. // 514: It's dead, get over it.
@ -696,15 +696,15 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
break; break;
} }
if (currentHp < maximumHp || critterIsCrippled(a2)) { if (currentHp < maximumHp || critterIsCrippled(target)) {
paletteFadeTo(gPaletteBlack); paletteFadeTo(gPaletteBlack);
if (critterGetBodyType(a2) != BODY_TYPE_ROBOTIC && critterIsCrippled(a2)) { if (critterGetBodyType(target) != BODY_TYPE_ROBOTIC && critterIsCrippled(target)) {
int flags[HEALABLE_DAMAGE_FLAGS_LENGTH]; int flags[HEALABLE_DAMAGE_FLAGS_LENGTH];
memcpy(flags, gHealableDamageFlags, sizeof(gHealableDamageFlags)); memcpy(flags, gHealableDamageFlags, sizeof(gHealableDamageFlags));
for (int index = 0; index < HEALABLE_DAMAGE_FLAGS_LENGTH; index++) { for (int index = 0; index < HEALABLE_DAMAGE_FLAGS_LENGTH; index++) {
if ((a2->data.critter.combat.results & flags[index]) != 0) { if ((target->data.critter.combat.results & flags[index]) != 0) {
damageHealingAttempts++; damageHealingAttempts++;
int roll = skillRoll(obj, skill, criticalChance, &hpToHeal); int roll = skillRoll(obj, skill, criticalChance, &hpToHeal);
@ -722,21 +722,21 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
MessageListItem prefix; MessageListItem prefix;
if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) { if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) {
a2->data.critter.combat.results &= ~flags[index]; target->data.critter.combat.results &= ~flags[index];
a2->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; target->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
// 520: You heal your %s. // 520: You heal your %s.
// 521: You heal the %s. // 521: You heal the %s.
prefix.num = (a2 == gDude ? 520 : 521); prefix.num = (target == gDude ? 520 : 521);
skillUpdateLastUse(SKILL_DOCTOR); skillUpdateLastUse(SKILL_DOCTOR);
v1 = 1; successCount = 1;
v2 = 1; skillUseSlotAdded = 1;
} else { } else {
// 525: You fail to heal your %s. // 525: You fail to heal your %s.
// 526: You fail to heal the %s. // 526: You fail to heal the %s.
prefix.num = (a2 == gDude ? 525 : 526); prefix.num = (target == gDude ? 525 : 526);
} }
if (!messageListGetItem(&gSkillsMessageList, &prefix)) { if (!messageListGetItem(&gSkillsMessageList, &prefix)) {
@ -745,7 +745,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
snprintf(text, sizeof(text), prefix.text, messageListItem.text); snprintf(text, sizeof(text), prefix.text, messageListItem.text);
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
_show_skill_use_messages(obj, skill, a2, v1, criticalChanceModifier); _show_skill_use_messages(obj, skill, target, successCount, criticalChanceModifier);
giveExp = false; giveExp = false;
} }
@ -753,7 +753,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
} }
int roll; int roll;
if (critterGetBodyType(a2) == BODY_TYPE_ROBOTIC) { if (critterGetBodyType(target) == BODY_TYPE_ROBOTIC) {
roll = ROLL_FAILURE; roll = ROLL_FAILURE;
} else { } else {
int skillValue = skillGetValue(obj, skill); int skillValue = skillGetValue(obj, skill);
@ -762,7 +762,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) { if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) {
hpToHeal = randomBetween(minimumHpToHeal + 4, maximumHpToHeal + 10); hpToHeal = randomBetween(minimumHpToHeal + 4, maximumHpToHeal + 10);
critterAdjustHitPoints(a2, hpToHeal); critterAdjustHitPoints(target, hpToHeal);
if (obj == gDude) { if (obj == gDude) {
// You heal %d hit points. // You heal %d hit points.
@ -778,18 +778,18 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
} }
if (!v2) { if (!skillUseSlotAdded) {
skillUpdateLastUse(SKILL_DOCTOR); skillUpdateLastUse(SKILL_DOCTOR);
} }
a2->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; target->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
if (a2 == gDude) { if (target == gDude) {
interfaceRenderHitPoints(true); interfaceRenderHitPoints(true);
} }
v1 = 1; successCount = 1;
_show_skill_use_messages(obj, skill, a2, v1, criticalChanceModifier); _show_skill_use_messages(obj, skill, target, successCount, criticalChanceModifier);
scriptsExecMapUpdateProc(); scriptsExecMapUpdateProc();
paletteFadeTo(_cmap); paletteFadeTo(_cmap);
@ -811,15 +811,15 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (obj == gDude) { if (obj == gDude) {
// 501: You look healty already // 501: You look healty already
// 502: %s looks healthy already // 502: %s looks healthy already
messageListItem.num = (a2 == gDude ? 501 : 502); messageListItem.num = (target == gDude ? 501 : 502);
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
return -1; return -1;
} }
if (a2 == gDude) { if (target == gDude) {
strcpy(text, messageListItem.text); strcpy(text, messageListItem.text);
} else { } else {
snprintf(text, sizeof(text), messageListItem.text, objectGetName(a2)); snprintf(text, sizeof(text), messageListItem.text, objectGetName(target));
} }
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
@ -837,7 +837,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
case SKILL_LOCKPICK: case SKILL_LOCKPICK:
break; break;
case SKILL_STEAL: case SKILL_STEAL:
scriptsRequestStealing(obj, a2); scriptsRequestStealing(obj, target);
break; break;
case SKILL_TRAPS: case SKILL_TRAPS:
messageListItem.num = 551; // You fail to find any traps. messageListItem.num = 551; // You fail to find any traps.
@ -854,7 +854,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
return -1; return -1;
case SKILL_REPAIR: case SKILL_REPAIR:
if (critterGetBodyType(a2) != BODY_TYPE_ROBOTIC) { if (critterGetBodyType(target) != BODY_TYPE_ROBOTIC) {
// You cannot repair that. // You cannot repair that.
messageListItem.num = 553; messageListItem.num = 553;
if (messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (messageListGetItem(&gSkillsMessageList, &messageListItem)) {
@ -874,7 +874,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
return -1; return -1;
} }
if (critterIsDead(a2)) { if (critterIsDead(target)) {
// You got it? // You got it?
messageListItem.num = 1101; messageListItem.num = 1101;
if (messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (messageListGetItem(&gSkillsMessageList, &messageListItem)) {
@ -883,14 +883,14 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
break; break;
} }
if (currentHp < maximumHp || critterIsCrippled(a2)) { if (currentHp < maximumHp || critterIsCrippled(target)) {
int flags[REPAIRABLE_DAMAGE_FLAGS_LENGTH]; int flags[REPAIRABLE_DAMAGE_FLAGS_LENGTH];
memcpy(flags, gRepairableDamageFlags, sizeof(gRepairableDamageFlags)); memcpy(flags, gRepairableDamageFlags, sizeof(gRepairableDamageFlags));
paletteFadeTo(gPaletteBlack); paletteFadeTo(gPaletteBlack);
for (int index = 0; index < REPAIRABLE_DAMAGE_FLAGS_LENGTH; index++) { for (int index = 0; index < REPAIRABLE_DAMAGE_FLAGS_LENGTH; index++) {
if ((a2->data.critter.combat.results & flags[index]) != 0) { if ((target->data.critter.combat.results & flags[index]) != 0) {
damageHealingAttempts++; damageHealingAttempts++;
int roll = skillRoll(obj, skill, criticalChance, &hpToHeal); int roll = skillRoll(obj, skill, criticalChance, &hpToHeal);
@ -908,20 +908,20 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
MessageListItem prefix; MessageListItem prefix;
if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) { if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) {
a2->data.critter.combat.results &= ~flags[index]; target->data.critter.combat.results &= ~flags[index];
a2->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; target->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
// 520: You heal your %s. // 520: You heal your %s.
// 521: You heal the %s. // 521: You heal the %s.
prefix.num = (a2 == gDude ? 520 : 521); prefix.num = (target == gDude ? 520 : 521);
skillUpdateLastUse(SKILL_REPAIR); skillUpdateLastUse(SKILL_REPAIR);
v1 = 1; successCount = 1;
v2 = 1; skillUseSlotAdded = 1;
} else { } else {
// 525: You fail to heal your %s. // 525: You fail to heal your %s.
// 526: You fail to heal the %s. // 526: You fail to heal the %s.
prefix.num = (a2 == gDude ? 525 : 526); prefix.num = (target == gDude ? 525 : 526);
} }
if (!messageListGetItem(&gSkillsMessageList, &prefix)) { if (!messageListGetItem(&gSkillsMessageList, &prefix)) {
@ -931,7 +931,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
snprintf(text, sizeof(text), prefix.text, messageListItem.text); snprintf(text, sizeof(text), prefix.text, messageListItem.text);
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
_show_skill_use_messages(obj, skill, a2, v1, criticalChanceModifier); _show_skill_use_messages(obj, skill, target, successCount, criticalChanceModifier);
giveExp = false; giveExp = false;
} }
} }
@ -941,7 +941,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) { if (roll == ROLL_SUCCESS || roll == ROLL_CRITICAL_SUCCESS) {
hpToHeal = randomBetween(minimumHpToHeal + 4, maximumHpToHeal + 10); hpToHeal = randomBetween(minimumHpToHeal + 4, maximumHpToHeal + 10);
critterAdjustHitPoints(a2, hpToHeal); critterAdjustHitPoints(target, hpToHeal);
if (obj == gDude) { if (obj == gDude) {
// You heal %d hit points. // You heal %d hit points.
@ -957,18 +957,18 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
} }
if (!v2) { if (!skillUseSlotAdded) {
skillUpdateLastUse(SKILL_REPAIR); skillUpdateLastUse(SKILL_REPAIR);
} }
a2->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; target->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
if (a2 == gDude) { if (target == gDude) {
interfaceRenderHitPoints(true); interfaceRenderHitPoints(true);
} }
v1 = 1; successCount = 1;
_show_skill_use_messages(obj, skill, a2, v1, criticalChanceModifier); _show_skill_use_messages(obj, skill, target, successCount, criticalChanceModifier);
scriptsExecMapUpdateProc(); scriptsExecMapUpdateProc();
paletteFadeTo(_cmap); paletteFadeTo(_cmap);
@ -990,12 +990,12 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
if (obj == gDude) { if (obj == gDude) {
// 501: You look healty already // 501: You look healty already
// 502: %s looks healthy already // 502: %s looks healthy already
messageListItem.num = (a2 == gDude ? 501 : 502); messageListItem.num = (target == gDude ? 501 : 502);
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) { if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
return -1; return -1;
} }
snprintf(text, sizeof(text), messageListItem.text, objectGetName(a2)); snprintf(text, sizeof(text), messageListItem.text, objectGetName(target));
displayMonitorAddMessage(text); displayMonitorAddMessage(text);
giveExp = false; giveExp = false;
@ -1017,7 +1017,7 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
} }
if (giveExp) { if (giveExp) {
_show_skill_use_messages(obj, skill, a2, v1, criticalChanceModifier); _show_skill_use_messages(obj, skill, target, successCount, criticalChanceModifier);
} }
if (skill == SKILL_FIRST_AID || skill == SKILL_DOCTOR) { if (skill == SKILL_FIRST_AID || skill == SKILL_DOCTOR) {
@ -1028,40 +1028,38 @@ int skillUse(Object* obj, Object* a2, int skill, int criticalChanceModifier)
} }
// 0x4ABBE4 // 0x4ABBE4
int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting) int skillsPerformStealing(Object* thief, Object* target, Object* item, bool isPlanting)
{ {
int howMuch; int howMuch;
int stealModifier = _gStealCount; int stealModifier = -_gStealCount + 1;
stealModifier--;
stealModifier = -stealModifier;
if (a1 != gDude || !perkHasRank(a1, PERK_PICKPOCKET)) { if (thief != gDude || !perkHasRank(thief, PERK_PICKPOCKET)) {
// -4% per item size // -4% per item size
stealModifier -= 4 * itemGetSize(item); stealModifier -= 4 * itemGetSize(item);
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) { if (FID_TYPE(target->fid) == OBJ_TYPE_CRITTER) {
// check facing: -25% if face to face // check facing: -25% if face to face
if (_is_hit_from_front(a1, a2)) { if (_is_hit_from_front(thief, target)) {
stealModifier -= 25; stealModifier -= 25;
} }
} }
} }
if ((a2->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0) { if ((target->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0) {
stealModifier += 20; stealModifier += 20;
} }
int stealChance = stealModifier + skillGetValue(a1, SKILL_STEAL); int stealChance = stealModifier + skillGetValue(thief, SKILL_STEAL);
if (stealChance > 95) { if (stealChance > 95) {
stealChance = 95; stealChance = 95;
} }
int stealRoll; int stealRoll;
if (a1 == gDude && objectIsPartyMember(a2)) { if (thief == gDude && objectIsPartyMember(target)) {
stealRoll = ROLL_CRITICAL_SUCCESS; stealRoll = ROLL_CRITICAL_SUCCESS;
} else { } else {
int criticalChance = critterGetStat(a1, STAT_CRITICAL_CHANCE); int criticalChance = critterGetStat(thief, STAT_CRITICAL_CHANCE);
stealRoll = randomRoll(stealChance, criticalChance, &howMuch); stealRoll = randomRoll(stealChance, criticalChance, &howMuch);
} }
@ -1072,8 +1070,8 @@ int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting)
catchRoll = ROLL_SUCCESS; catchRoll = ROLL_SUCCESS;
} else { } else {
int catchChance; int catchChance;
if (PID_TYPE(a2->pid) == OBJ_TYPE_CRITTER) { if (PID_TYPE(target->pid) == OBJ_TYPE_CRITTER) {
catchChance = skillGetValue(a2, SKILL_STEAL) - stealModifier; catchChance = skillGetValue(target, SKILL_STEAL) - stealModifier;
} else { } else {
catchChance = 30 - stealModifier; catchChance = 30 - stealModifier;
} }

View File

@ -34,7 +34,7 @@ char* skillGetName(int skill);
char* skillGetDescription(int skill); char* skillGetDescription(int skill);
char* skillGetAttributes(int skill); char* skillGetAttributes(int skill);
int skillGetFrmId(int skill); int skillGetFrmId(int skill);
int skillUse(Object* obj, Object* a2, int skill, int a4); int skillUse(Object* obj, Object* target, int skill, int criticalChanceModifier);
int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting); int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting);
int skillGetGameDifficultyModifier(int skill); int skillGetGameDifficultyModifier(int skill);
int skillUpdateLastUse(int skill); int skillUpdateLastUse(int skill);

View File

@ -3719,7 +3719,7 @@ int wmSetupRandomEncounter()
prevCritter->data.critter.combat.whoHitMe = critter; prevCritter->data.critter.combat.whoHitMe = critter;
critter->data.critter.combat.whoHitMe = prevCritter; critter->data.critter.combat.whoHitMe = prevCritter;
STRUCT_664980 combat; CombatStartData combat;
combat.attacker = prevCritter; combat.attacker = prevCritter;
combat.defender = critter; combat.defender = critter;
combat.actionPointsBonus = 0; combat.actionPointsBonus = 0;
@ -3727,7 +3727,7 @@ int wmSetupRandomEncounter()
combat.damageBonus = 0; combat.damageBonus = 0;
combat.minDamage = 0; combat.minDamage = 0;
combat.maxDamage = 500; combat.maxDamage = 500;
combat.field_1C = 0; combat.overrideAttackResults = 0;
_caiSetupTeamCombat(critter, prevCritter); _caiSetupTeamCombat(critter, prevCritter);
_scripts_request_combat_locked(&combat); _scripts_request_combat_locked(&combat);
@ -3736,7 +3736,7 @@ int wmSetupRandomEncounter()
if (!isInCombat()) { if (!isInCombat()) {
prevCritter->data.critter.combat.whoHitMe = gDude; prevCritter->data.critter.combat.whoHitMe = gDude;
STRUCT_664980 combat; CombatStartData combat;
combat.attacker = prevCritter; combat.attacker = prevCritter;
combat.defender = gDude; combat.defender = gDude;
combat.actionPointsBonus = 0; combat.actionPointsBonus = 0;
@ -3744,7 +3744,7 @@ int wmSetupRandomEncounter()
combat.damageBonus = 0; combat.damageBonus = 0;
combat.minDamage = 0; combat.minDamage = 0;
combat.maxDamage = 500; combat.maxDamage = 500;
combat.field_1C = 0; combat.overrideAttackResults = 0;
_caiSetupTeamCombat(gDude, prevCritter); _caiSetupTeamCombat(gDude, prevCritter);
_scripts_request_combat_locked(&combat); _scripts_request_combat_locked(&combat);