From 080f99962681dae5388e11421615d8f371bf9800 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 9 Feb 2025 17:20:53 +0100 Subject: [PATCH] Code deobfuscation/decyphering (3) (#374) --- src/actions.cc | 112 +++--- src/actions.h | 8 +- src/animation.cc | 17 +- src/art.cc | 55 +-- src/art.h | 2 +- src/combat_ai.cc | 2 +- src/critter.cc | 8 +- src/game_dialog.cc | 101 +++--- src/game_mouse.cc | 148 ++++---- src/interface.h | 8 - src/interpreter_extra.cc | 6 +- src/inventory.cc | 765 ++++++++++++++++++++------------------- src/inventory.h | 37 +- src/item.cc | 77 ++-- src/map.cc | 26 +- src/map.h | 2 +- src/mouse.cc | 10 +- src/mouse.h | 2 +- src/obj_types.h | 4 +- src/object.cc | 8 +- src/object.h | 2 +- src/party_member.cc | 178 ++++----- src/perk.cc | 32 +- src/pipboy.cc | 19 +- src/proto_instance.cc | 299 +++++++-------- src/proto_instance.h | 10 +- src/scripts.cc | 32 +- src/scripts.h | 8 +- src/sfall_opcodes.cc | 2 +- src/skill.h | 2 +- src/worldmap.cc | 129 +++---- 31 files changed, 1075 insertions(+), 1036 deletions(-) diff --git a/src/actions.cc b/src/actions.cc index c9f3847..99ded11 100644 --- a/src/actions.cc +++ b/src/actions.cc @@ -1060,21 +1060,21 @@ int _action_climb_ladder(Object* a1, Object* a2) } // 0x411F2C -int _action_use_an_item_on_object(Object* a1, Object* a2, Object* a3) +int _action_use_an_item_on_object(Object* user, Object* targetObj, Object* item) { Proto* proto = nullptr; - int type = FID_TYPE(a2->fid); + int type = FID_TYPE(targetObj->fid); int sceneryType = -1; if (type == OBJ_TYPE_SCENERY) { - if (protoGetProto(a2->pid, &proto) == -1) { + if (protoGetProto(targetObj->pid, &proto) == -1) { return -1; } sceneryType = proto->scenery.type; } - if (sceneryType != SCENERY_TYPE_LADDER_UP || a3 != nullptr) { - if (a1 == gDude) { + if (sceneryType != SCENERY_TYPE_LADDER_UP || item != nullptr) { + if (user == gDude) { int anim = FID_ANIM_TYPE(gDude->fid); if (anim == ANIM_WALK || anim == ANIM_RUNNING) { reg_anim_clear(gDude); @@ -1085,40 +1085,40 @@ int _action_use_an_item_on_object(Object* a1, Object* a2, Object* a3) int actionPoints; if (isInCombat()) { animationRequestOptions = ANIMATION_REQUEST_RESERVED; - actionPoints = a1->data.critter.combat.ap; + actionPoints = user->data.critter.combat.ap; } else { animationRequestOptions = ANIMATION_REQUEST_UNRESERVED; actionPoints = -1; } - if (a1 == gDude) { + if (user == gDude) { animationRequestOptions = ANIMATION_REQUEST_RESERVED; } reg_anim_begin(animationRequestOptions); - if (actionPoints != -1 || objectGetDistanceBetween(a1, a2) < 5) { - animationRegisterMoveToObject(a1, a2, actionPoints, 0); + if (actionPoints != -1 || objectGetDistanceBetween(user, targetObj) < 5) { + animationRegisterMoveToObject(user, targetObj, actionPoints, 0); } else { - animationRegisterRunToObject(a1, a2, -1, 0); + animationRegisterRunToObject(user, targetObj, -1, 0); } - animationRegisterCallbackForced(a1, a2, (AnimationCallback*)_is_next_to, -1); + animationRegisterCallbackForced(user, targetObj, (AnimationCallback*)_is_next_to, -1); - if (a3 == nullptr) { - animationRegisterCallback(a1, a2, (AnimationCallback*)_check_scenery_ap_cost, -1); + if (item == nullptr) { + animationRegisterCallback(user, targetObj, (AnimationCallback*)_check_scenery_ap_cost, -1); } - int a2a = (a1->fid & 0xF000) >> 12; - if (a2a != 0) { - const char* sfx = sfxBuildCharName(a1, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED); - animationRegisterPlaySoundEffect(a1, sfx, -1); - animationRegisterAnimate(a1, ANIM_PUT_AWAY, 0); + int weaponAnimCode = (user->fid & 0xF000) >> 12; + if (weaponAnimCode != 0) { + const char* sfx = sfxBuildCharName(user, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED); + animationRegisterPlaySoundEffect(user, sfx, -1); + animationRegisterAnimate(user, ANIM_PUT_AWAY, 0); } int anim; - int objectType = FID_TYPE(a2->fid); - if (objectType == OBJ_TYPE_CRITTER && _critter_is_prone(a2)) { + int objectType = FID_TYPE(targetObj->fid); + if (objectType == OBJ_TYPE_CRITTER && _critter_is_prone(targetObj)) { anim = ANIM_MAGIC_HANDS_GROUND; } else if (objectType == OBJ_TYPE_SCENERY && (proto->scenery.extendedFlags & 0x01) != 0) { anim = ANIM_MAGIC_HANDS_GROUND; @@ -1126,31 +1126,31 @@ int _action_use_an_item_on_object(Object* a1, Object* a2, Object* a3) anim = ANIM_MAGIC_HANDS_MIDDLE; } - if (sceneryType != SCENERY_TYPE_STAIRS && a3 == nullptr) { - animationRegisterAnimate(a1, anim, -1); + if (sceneryType != SCENERY_TYPE_STAIRS && item == nullptr) { + animationRegisterAnimate(user, anim, -1); } - if (a3 != nullptr) { + if (item != nullptr) { // TODO: Get rid of cast. - animationRegisterCallback3(a1, a2, a3, (AnimationCallback3*)_obj_use_item_on, -1); + animationRegisterCallback3(user, targetObj, item, (AnimationCallback3*)_obj_use_item_on, -1); } else { - animationRegisterCallback(a1, a2, (AnimationCallback*)_obj_use, -1); + animationRegisterCallback(user, targetObj, (AnimationCallback*)_obj_use, -1); } - if (a2a != 0) { - animationRegisterTakeOutWeapon(a1, a2a, -1); + if (weaponAnimCode != 0) { + animationRegisterTakeOutWeapon(user, weaponAnimCode, -1); } return reg_anim_end(); } - return _action_climb_ladder(a1, a2); + return _action_climb_ladder(user, targetObj); } // 0x412114 -int _action_use_an_object(Object* a1, Object* a2) +int _action_use_an_object(Object* user, Object* targetObj) { - return _action_use_an_item_on_object(a1, a2, nullptr); + return _action_use_an_item_on_object(user, targetObj, nullptr); } // 0x412134 @@ -1322,27 +1322,27 @@ static int _action_use_skill_in_combat_error(Object* critter) // skill_use // 0x41255C -int actionUseSkill(Object* a1, Object* a2, int skill) +int actionUseSkill(Object* user, Object* target, int skill) { switch (skill) { case SKILL_FIRST_AID: case SKILL_DOCTOR: if (isInCombat()) { // NOTE: Uninline. - return _action_use_skill_in_combat_error(a1); + return _action_use_skill_in_combat_error(user); } - if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) { + if (PID_TYPE(target->pid) != OBJ_TYPE_CRITTER) { return -1; } break; case SKILL_LOCKPICK: if (isInCombat()) { // NOTE: Uninline. - return _action_use_skill_in_combat_error(a1); + return _action_use_skill_in_combat_error(user); } - if (PID_TYPE(a2->pid) != OBJ_TYPE_ITEM && PID_TYPE(a2->pid) != OBJ_TYPE_SCENERY) { + if (PID_TYPE(target->pid) != OBJ_TYPE_ITEM && PID_TYPE(target->pid) != OBJ_TYPE_SCENERY) { return -1; } @@ -1350,14 +1350,14 @@ int actionUseSkill(Object* a1, Object* a2, int skill) case SKILL_STEAL: if (isInCombat()) { // NOTE: Uninline. - return _action_use_skill_in_combat_error(a1); + return _action_use_skill_in_combat_error(user); } - if (PID_TYPE(a2->pid) != OBJ_TYPE_ITEM && PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) { + if (PID_TYPE(target->pid) != OBJ_TYPE_ITEM && PID_TYPE(target->pid) != OBJ_TYPE_CRITTER) { return -1; } - if (a2 == a1) { + if (target == user) { return -1; } @@ -1365,10 +1365,10 @@ int actionUseSkill(Object* a1, Object* a2, int skill) case SKILL_TRAPS: if (isInCombat()) { // NOTE: Uninline. - return _action_use_skill_in_combat_error(a1); + return _action_use_skill_in_combat_error(user); } - if (PID_TYPE(a2->pid) == OBJ_TYPE_CRITTER) { + if (PID_TYPE(target->pid) == OBJ_TYPE_CRITTER) { return -1; } @@ -1377,18 +1377,18 @@ int actionUseSkill(Object* a1, Object* a2, int skill) case SKILL_REPAIR: if (isInCombat()) { // NOTE: Uninline. - return _action_use_skill_in_combat_error(a1); + return _action_use_skill_in_combat_error(user); } - if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) { + if (PID_TYPE(target->pid) != OBJ_TYPE_CRITTER) { break; } - if (critterGetKillType(a2) == KILL_TYPE_ROBOT) { + if (critterGetKillType(target) == KILL_TYPE_ROBOT) { break; } - if (critterGetKillType(a2) == KILL_TYPE_BRAHMIN + if (critterGetKillType(target) == KILL_TYPE_BRAHMIN && skill == SKILL_SCIENCE) { break; } @@ -1398,7 +1398,7 @@ int actionUseSkill(Object* a1, Object* a2, int skill) int targetType = SCIENCE_REPAIR_TARGET_TYPE_DEFAULT; configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SCIENCE_REPAIR_TARGET_TYPE_KEY, &targetType); if (targetType == SCIENCE_REPAIR_TARGET_TYPE_DUDE) { - if (a2 == gDude) { + if (target == gDude) { break; } } else if (targetType == SCIENCE_REPAIR_TARGET_TYPE_ANYONE) { @@ -1418,7 +1418,7 @@ int actionUseSkill(Object* a1, Object* a2, int skill) // skill in entire party, and this skill is his/her own best. Object* performer = gDude; - if (a1 == gDude) { + if (user == gDude) { Object* partyMember = partyMemberGetBestInSkill(skill); if (partyMember == gDude) { @@ -1451,7 +1451,7 @@ int actionUseSkill(Object* a1, Object* a2, int skill) if (partyMember != nullptr) { bool isDude = false; - if (objectGetDistanceBetween(gDude, a2) <= 1) { + if (objectGetDistanceBetween(gDude, target) <= 1) { isDude = true; } @@ -1478,21 +1478,21 @@ int actionUseSkill(Object* a1, Object* a2, int skill) if (isInCombat()) { reg_anim_begin(ANIMATION_REQUEST_RESERVED); - animationRegisterMoveToObject(performer, a2, performer->data.critter.combat.ap, 0); + animationRegisterMoveToObject(performer, target, performer->data.critter.combat.ap, 0); } else { - reg_anim_begin(a1 == gDude ? ANIMATION_REQUEST_RESERVED : ANIMATION_REQUEST_UNRESERVED); - if (a2 != gDude) { - if (objectGetDistanceBetween(performer, a2) >= 5) { - animationRegisterRunToObject(performer, a2, -1, 0); + reg_anim_begin(user == gDude ? ANIMATION_REQUEST_RESERVED : ANIMATION_REQUEST_UNRESERVED); + if (target != gDude) { + if (objectGetDistanceBetween(performer, target) >= 5) { + animationRegisterRunToObject(performer, target, -1, 0); } else { - animationRegisterMoveToObject(performer, a2, -1, 0); + animationRegisterMoveToObject(performer, target, -1, 0); } } } - animationRegisterCallbackForced(performer, a2, (AnimationCallback*)_is_next_to, -1); + animationRegisterCallbackForced(performer, target, (AnimationCallback*)_is_next_to, -1); - int anim = (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER && _critter_is_prone(a2)) ? ANIM_MAGIC_HANDS_GROUND : ANIM_MAGIC_HANDS_MIDDLE; + int anim = (FID_TYPE(target->fid) == OBJ_TYPE_CRITTER && _critter_is_prone(target)) ? ANIM_MAGIC_HANDS_GROUND : ANIM_MAGIC_HANDS_MIDDLE; int fid = buildFid(OBJ_TYPE_CRITTER, performer->fid & 0xFFF, anim, 0, performer->rotation + 1); CacheEntry* artHandle; @@ -1504,7 +1504,7 @@ int actionUseSkill(Object* a1, Object* a2, int skill) animationRegisterAnimate(performer, anim, -1); // TODO: Get rid of casts. - animationRegisterCallback3(performer, a2, (void*)skill, (AnimationCallback3*)_obj_use_skill_on, -1); + animationRegisterCallback3(performer, target, (void*)skill, (AnimationCallback3*)_obj_use_skill_on, -1); return reg_anim_end(); } diff --git a/src/actions.h b/src/actions.h index c499a73..cadbf33 100644 --- a/src/actions.h +++ b/src/actions.h @@ -9,12 +9,12 @@ namespace fallout { extern int rotation; int _action_attack(Attack* attack); -int _action_use_an_item_on_object(Object* a1, Object* a2, Object* a3); -int _action_use_an_object(Object* a1, Object* a2); +int _action_use_an_item_on_object(Object* user, Object* targetObj, Object* item); +int _action_use_an_object(Object* user, Object* targetObj); int actionPickUp(Object* critter, Object* item); int _action_loot_container(Object* critter, Object* container); -int _action_skill_use(int a1); -int actionUseSkill(Object* a1, Object* a2, int skill); +int _action_skill_use(int skill); +int actionUseSkill(Object* user, Object* target, int skill); bool _is_hit_from_front(Object* attacker, Object* defender); bool _can_see(Object* a1, Object* a2); bool _action_explode_running(); diff --git a/src/animation.cc b/src/animation.cc index b216c54..71877b3 100644 --- a/src/animation.cc +++ b/src/animation.cc @@ -34,6 +34,7 @@ #include "tile.h" #include "trait.h" #include "vcr.h" +#include "worldmap.h" namespace fallout { @@ -1033,7 +1034,7 @@ int animationRegisterHideObjectForced(Object* object) } // 0x414E98 -int animationRegisterCallback(void* a1, void* a2, AnimationCallback* proc, int delay) +int animationRegisterCallback(void* param1, void* param2, AnimationCallback* proc, int delay) { if (_check_registry(nullptr) == -1 || proc == nullptr) { _anim_cleanup(); @@ -1045,8 +1046,8 @@ int animationRegisterCallback(void* a1, void* a2, AnimationCallback* proc, int d animationDescription->kind = ANIM_KIND_CALLBACK; animationDescription->extendedFlags = 0; animationDescription->artCacheKey = nullptr; - animationDescription->param2 = a2; - animationDescription->param1 = a1; + animationDescription->param2 = param2; + animationDescription->param1 = param1; animationDescription->callback = proc; animationDescription->delay = delay; @@ -1058,7 +1059,7 @@ int animationRegisterCallback(void* a1, void* a2, AnimationCallback* proc, int d // Same as `animationRegisterCallback` but accepting 3 parameters. // // 0x414F20 -int animationRegisterCallback3(void* a1, void* a2, void* a3, AnimationCallback3* proc, int delay) +int animationRegisterCallback3(void* param1, void* param2, void* param3, AnimationCallback3* proc, int delay) { if (_check_registry(nullptr) == -1 || proc == nullptr) { _anim_cleanup(); @@ -1070,10 +1071,10 @@ int animationRegisterCallback3(void* a1, void* a2, void* a3, AnimationCallback3* animationDescription->kind = ANIM_KIND_CALLBACK3; animationDescription->extendedFlags = 0; animationDescription->artCacheKey = nullptr; - animationDescription->param2 = a2; - animationDescription->param1 = a1; + animationDescription->param2 = param2; + animationDescription->param1 = param1; animationDescription->callback3 = proc; - animationDescription->param3 = a3; + animationDescription->param3 = param3; animationDescription->delay = delay; gAnimationDescriptionCurrentIndex++; @@ -3062,7 +3063,7 @@ void _dude_fidget() objectGetRect(object, &rect); Rect intersection; - if (rectIntersection(&rect, &_scr_size, &intersection) == 0 && (gMapHeader.field_34 != 97 || object->pid != 0x10000FA)) { + if (rectIntersection(&rect, &_scr_size, &intersection) == 0 && (gMapHeader.index != MAP_SPECIAL_RND_WOODSMAN || object->pid != 0x10000FA)) { candidates[candidatesLength++] = object; } } diff --git a/src/art.cc b/src/art.cc index 696aa00..205b360 100644 --- a/src/art.cc +++ b/src/art.cc @@ -1006,45 +1006,28 @@ static void artCacheFreeImpl(void* ptr) internal_free(ptr); } -// 0x419C88 -int buildFid(int objectType, int frmId, int animType, int a3, int rotation) +static int buildFidInternal(unsigned short frmId, unsigned char weaponCode, unsigned char animType, unsigned char objectType, unsigned char rotation) { - int v7, v8, v9, v10; + return ((rotation << 28) & 0x70000000) | (objectType << 24) | ((animType << 16) & 0xFF0000) | ((weaponCode << 12) & 0xF000) | (frmId & 0xFFF); +} - v10 = rotation; - - if (objectType != OBJ_TYPE_CRITTER) { - goto zero; +// 0x419C88 +int buildFid(int objectType, int frmId, int animType, int weaponCode, int rotation) +{ + // Always use rotation 0 (NE) for non-critters, for certain critter animations. + // For other critter animations, check if art for the given rotation exists, if not try rotation 1 (E) and if that also doesn't exist, then default to 0 (NE). + if (objectType != OBJ_TYPE_CRITTER + || animType == ANIM_FIRE_DANCE + || animType < ANIM_FALL_BACK + || animType > ANIM_FALL_FRONT_BLOOD) { + rotation = ROTATION_NE; + } else if (!artExists(buildFidInternal(frmId, weaponCode, animType, OBJ_TYPE_CRITTER, rotation))) { + rotation = rotation != ROTATION_E + && artExists(buildFidInternal(frmId, weaponCode, animType, OBJ_TYPE_CRITTER, ROTATION_E)) + ? ROTATION_E + : ROTATION_NE; } - - if (animType == ANIM_FIRE_DANCE || animType < ANIM_FALL_BACK || animType > ANIM_FALL_FRONT_BLOOD) { - goto zero; - } - - v7 = ((a3 << 12) & 0xF000) | ((animType << 16) & 0xFF0000) | 0x1000000; - v8 = ((rotation << 28) & 0x70000000) | v7; - v9 = frmId & 0xFFF; - - if (artExists(v9 | v8) != 0) { - goto out; - } - - if (objectType == rotation) { - goto zero; - } - - v10 = objectType; - if (artExists(v9 | v7 | 0x10000000) != 0) { - goto out; - } - -zero: - - v10 = 0; - -out: - - return ((v10 << 28) & 0x70000000) | (objectType << 24) | ((animType << 16) & 0xFF0000) | ((a3 << 12) & 0xF000) | (frmId & 0xFFF); + return buildFidInternal(frmId, weaponCode, animType, objectType, rotation); } // 0x419D60 diff --git a/src/art.h b/src/art.h index 650b241..6fb665d 100644 --- a/src/art.h +++ b/src/art.h @@ -147,7 +147,7 @@ bool _art_fid_valid(int fid); int _art_alias_num(int a1); int artCritterFidShouldRun(int a1); int artAliasFid(int fid); -int buildFid(int objectType, int frmId, int animType, int a4, int rotation); +int buildFid(int objectType, int frmId, int animType, int weaponCode, int rotation); Art* artLoad(const char* path); int artRead(const char* path, unsigned char* data); int artWrite(const char* path, unsigned char* data); diff --git a/src/combat_ai.cc b/src/combat_ai.cc index ea3e836..5d7dd0f 100644 --- a/src/combat_ai.cc +++ b/src/combat_ai.cc @@ -2620,7 +2620,7 @@ static int _ai_switch_weapons(Object* attacker, int* hitMode, Object** weapon, O } if (*weapon != nullptr) { - _inven_wield(attacker, *weapon, 1); + _inven_wield(attacker, *weapon, HAND_RIGHT); _combat_turn_run(); if (weaponGetActionPointCost(attacker, *hitMode, 0) <= attacker->data.critter.combat.ap) { return 0; diff --git a/src/critter.cc b/src/critter.cc index a99af5e..5e53852 100644 --- a/src/critter.cc +++ b/src/critter.cc @@ -238,19 +238,19 @@ char* critterGetName(Object* obj) return gDudeName; } - if (obj->field_80 == -1) { + if (obj->scriptIndex == -1) { if (obj->sid != -1) { Script* script; if (scriptGetScript(obj->sid, &script) != -1) { - obj->field_80 = script->field_14; + obj->scriptIndex = script->index; } } } char* name = nullptr; - if (obj->field_80 != -1) { + if (obj->scriptIndex != -1) { MessageListItem messageListItem; - messageListItem.num = 101 + obj->field_80; + messageListItem.num = 101 + obj->scriptIndex; if (messageListGetItem(&gCritterMessageList, &messageListItem)) { name = messageListItem.text; } diff --git a/src/game_dialog.cc b/src/game_dialog.cc index 4a1cafa..545c271 100644 --- a/src/game_dialog.cc +++ b/src/game_dialog.cc @@ -587,7 +587,10 @@ static void _demo_copy_title(int win); static void _demo_copy_options(int win); static void _gDialogRefreshOptionsRect(int win, Rect* drawRect); static void gameDialogTicker(); -static void _gdialog_scroll_subwin(int a1, int a2, unsigned char* a3, unsigned char* a4, unsigned char* a5, int a6, int a7); +// Animates scroll up or down of a given dialog sub-window. +// If scrolling up - only uses subWindowFrmData to gradually fill the window (must be pre-filled with bg window contents). +// If scroliing down - uses both subWindowFrmData and bgWindowFrmData to fill parts of window buffer. +static void _gdialog_scroll_subwin(int windowIdx, bool scrollUp, unsigned char* subWindowFrmData, unsigned char* windowBuf, unsigned char* bgWindowFrmData, int windowHeight, bool instantScrollUp = false); static int _text_num_lines(const char* a1, int a2); static int text_to_rect_wrapped(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color); static int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color, int a7); @@ -2932,44 +2935,42 @@ void _talk_to_critter_reacts(int a1) } // 0x447D98 -void _gdialog_scroll_subwin(int win, int a2, unsigned char* a3, unsigned char* a4, unsigned char* a5, int a6, int a7) +void _gdialog_scroll_subwin(int windowIdx, bool scrollUp, unsigned char* windowFrmData, unsigned char* windowBuf, unsigned char* bgWindowFrmData, int windowHeight, bool instantScrollUp) { - int v7; - unsigned char* v9; + constexpr int stripHeight = 10; + int height = windowHeight; + unsigned char* dest = windowBuf; Rect rect; - v7 = a6; - v9 = a4; - - if (a2 == 1) { + if (scrollUp) { rect.left = 0; rect.right = GAME_DIALOG_WINDOW_WIDTH - 1; - rect.bottom = a6 - 1; + rect.bottom = windowHeight - 1; - int v18 = a6 / 10; - if (a7 == -1) { - rect.top = 10; - v18 = 0; + int strips = windowHeight / stripHeight; + if (instantScrollUp) { + rect.top = stripHeight; + strips = 0; } else { - rect.top = v18 * 10; - v7 = a6 % 10; - v9 += GAME_DIALOG_WINDOW_WIDTH * rect.top; + rect.top = strips * stripHeight; + height = windowHeight % stripHeight; + dest += GAME_DIALOG_WINDOW_WIDTH * rect.top; } - for (; v18 >= 0; v18--) { + for (; strips >= 0; strips--) { sharedFpsLimiter.mark(); soundContinueAll(); - blitBufferToBuffer(a3, + blitBufferToBuffer(windowFrmData, GAME_DIALOG_WINDOW_WIDTH, - v7, + height, GAME_DIALOG_WINDOW_WIDTH, - v9, + dest, GAME_DIALOG_WINDOW_WIDTH); - rect.top -= 10; - windowRefreshRect(win, &rect); - v7 += 10; - v9 -= 10 * (GAME_DIALOG_WINDOW_WIDTH); + rect.top -= stripHeight; + windowRefreshRect(windowIdx, &rect); + height += stripHeight; + dest -= stripHeight * (GAME_DIALOG_WINDOW_WIDTH); delay_ms(33); @@ -2978,36 +2979,36 @@ void _gdialog_scroll_subwin(int win, int a2, unsigned char* a3, unsigned char* a } } else { rect.right = GAME_DIALOG_WINDOW_WIDTH - 1; - rect.bottom = a6 - 1; + rect.bottom = windowHeight - 1; rect.left = 0; rect.top = 0; - for (int index = a6 / 10; index > 0; index--) { + for (int strips = windowHeight / stripHeight; strips > 0; strips--) { sharedFpsLimiter.mark(); soundContinueAll(); - blitBufferToBuffer(a5, + blitBufferToBuffer(bgWindowFrmData, GAME_DIALOG_WINDOW_WIDTH, - 10, + stripHeight, GAME_DIALOG_WINDOW_WIDTH, - v9, + dest, GAME_DIALOG_WINDOW_WIDTH); - v9 += 10 * (GAME_DIALOG_WINDOW_WIDTH); - v7 -= 10; - a5 += 10 * (GAME_DIALOG_WINDOW_WIDTH); + dest += stripHeight * (GAME_DIALOG_WINDOW_WIDTH); + height -= stripHeight; + bgWindowFrmData += stripHeight * (GAME_DIALOG_WINDOW_WIDTH); - blitBufferToBuffer(a3, + blitBufferToBuffer(windowFrmData, GAME_DIALOG_WINDOW_WIDTH, - v7, + height, GAME_DIALOG_WINDOW_WIDTH, - v9, + dest, GAME_DIALOG_WINDOW_WIDTH); - windowRefreshRect(win, &rect); + windowRefreshRect(windowIdx, &rect); - rect.top += 10; + rect.top += stripHeight; delay_ms(33); @@ -3228,7 +3229,7 @@ int _gdialog_barter_create_win() unsigned char* backgroundWindowBuffer = windowGetBuffer(gGameDialogBackgroundWindow); blitBufferToBuffer(backgroundWindowBuffer + width * (480 - _dialogue_subwin_len), width, _dialogue_subwin_len, width, windowBuffer, width); - _gdialog_scroll_subwin(gGameDialogWindow, 1, backgroundData, windowBuffer, nullptr, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, true, backgroundData, windowBuffer, nullptr, _dialogue_subwin_len); backgroundFrmImage.unlock(); @@ -3306,7 +3307,7 @@ void _gdialog_barter_destroy_win() int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { unsigned char* windowBuffer = windowGetBuffer(gGameDialogWindow); - _gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmImage.getData(), windowBuffer, backgroundWindowBuffer, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, false, backgroundFrmImage.getData(), windowBuffer, backgroundWindowBuffer, _dialogue_subwin_len); } windowDestroy(gGameDialogWindow); @@ -3380,7 +3381,7 @@ int partyMemberControlWindowInit() unsigned char* windowBuffer = windowGetBuffer(gGameDialogWindow); unsigned char* src = windowGetBuffer(gGameDialogBackgroundWindow); blitBufferToBuffer(src + (GAME_DIALOG_WINDOW_WIDTH) * (GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len), GAME_DIALOG_WINDOW_WIDTH, _dialogue_subwin_len, GAME_DIALOG_WINDOW_WIDTH, windowBuffer, GAME_DIALOG_WINDOW_WIDTH); - _gdialog_scroll_subwin(gGameDialogWindow, 1, backgroundData, windowBuffer, nullptr, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, true, backgroundData, windowBuffer, nullptr, _dialogue_subwin_len); backgroundFrmImage.unlock(); // TALK @@ -3529,7 +3530,7 @@ void partyMemberControlWindowFree() FrmImage backgroundFrmImage; int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 390, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { - _gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmImage.getData(), windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, false, backgroundFrmImage.getData(), windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len); } windowDestroy(gGameDialogWindow); @@ -3715,7 +3716,7 @@ void partyMemberControlWindowHandleEvents() Object* weapon = _ai_search_inven_weap(gGameDialogSpeaker, 0, nullptr); if (weapon != nullptr) { - _inven_wield(gGameDialogSpeaker, weapon, 1); + _inven_wield(gGameDialogSpeaker, weapon, HAND_RIGHT); aiAttemptWeaponReload(gGameDialogSpeaker, 0); int num = _gdPickAIUpdateMsg(gGameDialogSpeaker); @@ -3826,7 +3827,7 @@ int partyMemberCustomizationWindowInit() windowBuffer, GAME_DIALOG_WINDOW_WIDTH); - _gdialog_scroll_subwin(gGameDialogWindow, 1, backgroundFrmData, windowBuffer, nullptr, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, true, backgroundFrmData, windowBuffer, nullptr, _dialogue_subwin_len); backgroundFrmImage.unlock(); _gdialog_buttons[0] = buttonCreate(gGameDialogWindow, 593, 101, 14, 14, -1, -1, -1, 13, _redButtonNormalFrmImage.getData(), _redButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT); @@ -3934,7 +3935,7 @@ void partyMemberCustomizationWindowFree() // custom.frm - party member control interface int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 391, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { - _gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmImage.getData(), windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, false, backgroundFrmImage.getData(), windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len); } windowDestroy(gGameDialogWindow); @@ -4339,17 +4340,17 @@ int _gdialog_window_create() gGameDialogWindow = windowCreate(dialogSubwindowX, dialogSubwindowY, screenWidth, _dialogue_subwin_len, 256, WINDOW_DONT_MOVE_TOP); if (gGameDialogWindow != -1) { - unsigned char* v10 = windowGetBuffer(gGameDialogWindow); - unsigned char* v14 = windowGetBuffer(gGameDialogBackgroundWindow); + unsigned char* windowBuf = windowGetBuffer(gGameDialogWindow); + unsigned char* bgWindowBuf = windowGetBuffer(gGameDialogBackgroundWindow); // TODO: Not sure about offsets. - blitBufferToBuffer(v14 + screenWidth * (GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len), screenWidth, _dialogue_subwin_len, screenWidth, v10, screenWidth); + blitBufferToBuffer(bgWindowBuf + screenWidth * (GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len), screenWidth, _dialogue_subwin_len, screenWidth, windowBuf, screenWidth); if (_dialogue_just_started) { windowRefresh(gGameDialogBackgroundWindow); - _gdialog_scroll_subwin(gGameDialogWindow, 1, backgroundFrmData, v10, nullptr, _dialogue_subwin_len, -1); + _gdialog_scroll_subwin(gGameDialogWindow, true, backgroundFrmData, windowBuf, nullptr, _dialogue_subwin_len, true); _dialogue_just_started = 0; } else { - _gdialog_scroll_subwin(gGameDialogWindow, 1, backgroundFrmData, v10, nullptr, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, true, backgroundFrmData, windowBuf, nullptr, _dialogue_subwin_len, false); } // BARTER/TRADE @@ -4438,7 +4439,7 @@ void _gdialog_window_destroy() int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { unsigned char* windowBuffer = windowGetBuffer(gGameDialogWindow); - _gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmImage.getData(), windowBuffer, backgroundWindowBuffer, _dialogue_subwin_len, 0); + _gdialog_scroll_subwin(gGameDialogWindow, false, backgroundFrmImage.getData(), windowBuffer, backgroundWindowBuffer, _dialogue_subwin_len); windowDestroy(gGameDialogWindow); _gdialog_window_created = 0; gGameDialogWindow = -1; diff --git a/src/game_mouse.cc b/src/game_mouse.cc index 659b7ae..a80ec3c 100644 --- a/src/game_mouse.cc +++ b/src/game_mouse.cc @@ -318,7 +318,7 @@ static int gameMouseActionMenuInit(); static void gameMouseActionMenuFree(); static int gmouse_3d_set_flat_fid(int fid, Rect* rect); static int gameMouseUpdateHexCursorFid(Rect* rect); -static int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4); +static int _gmouse_3d_move_to(int x, int y, int elevation, Rect* rect); static int gameMouseHandleScrolling(int x, int y, int cursor); static int objectIsDoor(Object* object); static bool gameMouseClickOnInterfaceBar(); @@ -950,46 +950,46 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) } if (gGameMouseMode == GAME_MOUSE_MODE_ARROW) { - Object* v5 = gameMouseGetObjectUnderCursor(-1, true, gElevation); - if (v5 != nullptr) { - switch (FID_TYPE(v5->fid)) { + Object* targetObj = gameMouseGetObjectUnderCursor(-1, true, gElevation); + if (targetObj != nullptr) { + switch (FID_TYPE(targetObj->fid)) { case OBJ_TYPE_ITEM: - actionPickUp(gDude, v5); + actionPickUp(gDude, targetObj); break; case OBJ_TYPE_CRITTER: - if (v5 == gDude) { + if (targetObj == gDude) { if (FID_ANIM_TYPE(gDude->fid) == ANIM_STAND) { - Rect a1; - if (objectRotateClockwise(v5, &a1) == 0) { - tileWindowRefreshRect(&a1, v5->elevation); + Rect dudeRect; + if (objectRotateClockwise(targetObj, &dudeRect) == 0) { + tileWindowRefreshRect(&dudeRect, targetObj->elevation); } } } else { - if (_obj_action_can_talk_to(v5)) { + if (_obj_action_can_talk_to(targetObj)) { if (isInCombat()) { - if (_obj_examine(gDude, v5) == -1) { - _obj_look_at(gDude, v5); + if (_obj_examine(gDude, targetObj) == -1) { + _obj_look_at(gDude, targetObj); } } else { - actionTalk(gDude, v5); + actionTalk(gDude, targetObj); } } else { - _action_loot_container(gDude, v5); + _action_loot_container(gDude, targetObj); } } break; case OBJ_TYPE_SCENERY: - if (_obj_action_can_use(v5)) { - _action_use_an_object(gDude, v5); + if (_obj_action_can_use(targetObj)) { + _action_use_an_object(gDude, targetObj); } else { - if (_obj_examine(gDude, v5) == -1) { - _obj_look_at(gDude, v5); + if (_obj_examine(gDude, targetObj) == -1) { + _obj_look_at(gDude, targetObj); } } break; case OBJ_TYPE_WALL: - if (_obj_examine(gDude, v5) == -1) { - _obj_look_at(gDude, v5); + if (_obj_examine(gDude, targetObj) == -1) { + _obj_look_at(gDude, targetObj); } break; } @@ -998,16 +998,16 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) } if (gGameMouseMode == GAME_MOUSE_MODE_CROSSHAIR) { - Object* v7 = gameMouseGetObjectUnderCursor(OBJ_TYPE_CRITTER, false, gElevation); - if (v7 == nullptr) { - v7 = gameMouseGetObjectUnderCursor(-1, false, gElevation); - if (!objectIsDoor(v7)) { - v7 = nullptr; + Object* targetObj = gameMouseGetObjectUnderCursor(OBJ_TYPE_CRITTER, false, gElevation); + if (targetObj == nullptr) { + targetObj = gameMouseGetObjectUnderCursor(-1, false, gElevation); + if (!objectIsDoor(targetObj)) { + targetObj = nullptr; } } - if (v7 != nullptr) { - _combat_attack_this(v7); + if (targetObj != nullptr) { + _combat_attack_this(targetObj); _gmouse_3d_hover_test = true; gGameMouseLastY = mouseY; gGameMouseLastX = mouseX; @@ -1065,35 +1065,35 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) } if ((mouseState & MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT) == MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT && gGameMouseMode == GAME_MOUSE_MODE_ARROW) { - Object* v16 = gameMouseGetObjectUnderCursor(-1, true, gElevation); - if (v16 != nullptr) { + Object* targetObj = gameMouseGetObjectUnderCursor(-1, true, gElevation); + if (targetObj != nullptr) { int actionMenuItemsCount = 0; int actionMenuItems[6]; - switch (FID_TYPE(v16->fid)) { + switch (FID_TYPE(targetObj->fid)) { case OBJ_TYPE_ITEM: actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE; actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_LOOK; - if (itemGetType(v16) == ITEM_TYPE_CONTAINER) { + if (itemGetType(targetObj) == ITEM_TYPE_CONTAINER) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_INVENTORY; actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE_SKILL; } actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_CANCEL; break; case OBJ_TYPE_CRITTER: - if (v16 == gDude) { + if (targetObj == gDude) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_ROTATE; } else { - if (_obj_action_can_talk_to(v16)) { + if (_obj_action_can_talk_to(targetObj)) { if (!isInCombat()) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_TALK; } } else { - if (!_critter_flag_check(v16->pid, CRITTER_NO_STEAL)) { + if (!_critter_flag_check(targetObj->pid, CRITTER_NO_STEAL)) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE; } } - if (actionCheckPush(gDude, v16)) { + if (actionCheckPush(gDude, targetObj)) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_PUSH; } } @@ -1104,7 +1104,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_CANCEL; break; case OBJ_TYPE_SCENERY: - if (_obj_action_can_use(v16)) { + if (_obj_action_can_use(targetObj)) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE; } @@ -1115,7 +1115,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) break; case OBJ_TYPE_WALL: actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_LOOK; - if (_obj_action_can_use(v16)) { + if (_obj_action_can_use(targetObj)) { actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_INVENTORY; } actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_CANCEL; @@ -1123,14 +1123,14 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) } if (gameMouseRenderActionMenuItems(mouseX, mouseY, actionMenuItems, actionMenuItemsCount, _scr_size.right - _scr_size.left + 1, _scr_size.bottom - _scr_size.top - 99) == 0) { - Rect v43; + Rect cursorRect; int fid = buildFid(OBJ_TYPE_INTERFACE, 283, 0, 0, 0); // NOTE: Uninline. - if (gmouse_3d_set_flat_fid(fid, &v43) == 0 && _gmouse_3d_move_to(mouseX, mouseY, gElevation, &v43) == 0) { - tileWindowRefreshRect(&v43, gElevation); + if (gmouse_3d_set_flat_fid(fid, &cursorRect) == 0 && _gmouse_3d_move_to(mouseX, mouseY, gElevation, &cursorRect) == 0) { + tileWindowRefreshRect(&cursorRect, gElevation); isoDisable(); - int v33 = mouseY; + int newMouseY = mouseY; int actionIndex = 0; while ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_UP) == 0) { sharedFpsLimiter.mark(); @@ -1141,21 +1141,21 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) actionMenuItems[actionIndex] = 0; } - int v48; - int v47; - mouseGetPosition(&v48, &v47); + int updatedMouseX; + int updatedMouseY; + mouseGetPosition(&updatedMouseX, &updatedMouseY); - if (abs(v47 - v33) > 10) { - if (v33 >= v47) { + if (abs(updatedMouseY - newMouseY) > 10) { + if (newMouseY >= updatedMouseY) { actionIndex -= 1; } else { actionIndex += 1; } if (gameMouseHighlightActionMenuItemAtIndex(actionIndex) == 0) { - tileWindowRefreshRect(&v43, gElevation); + tileWindowRefreshRect(&cursorRect, gElevation); } - v33 = v47; + newMouseY = updatedMouseY; } renderPresent(); @@ -1169,39 +1169,39 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) gGameMouseLastY = mouseY; _gmouse_3d_last_move_time = getTicks(); - _mouse_set_position(mouseX, v33); + _mouse_set_position(mouseX, newMouseY); - if (gameMouseUpdateHexCursorFid(&v43) == 0) { - tileWindowRefreshRect(&v43, gElevation); + if (gameMouseUpdateHexCursorFid(&cursorRect) == 0) { + tileWindowRefreshRect(&cursorRect, gElevation); } switch (actionMenuItems[actionIndex]) { case GAME_MOUSE_ACTION_MENU_ITEM_INVENTORY: - inventoryOpenUseItemOn(v16); + inventoryOpenUseItemOn(targetObj); break; case GAME_MOUSE_ACTION_MENU_ITEM_LOOK: - if (_obj_examine(gDude, v16) == -1) { - _obj_look_at(gDude, v16); + if (_obj_examine(gDude, targetObj) == -1) { + _obj_look_at(gDude, targetObj); } break; case GAME_MOUSE_ACTION_MENU_ITEM_ROTATE: - if (objectRotateClockwise(v16, &v43) == 0) { - tileWindowRefreshRect(&v43, v16->elevation); + if (objectRotateClockwise(targetObj, &cursorRect) == 0) { + tileWindowRefreshRect(&cursorRect, targetObj->elevation); } break; case GAME_MOUSE_ACTION_MENU_ITEM_TALK: - actionTalk(gDude, v16); + actionTalk(gDude, targetObj); break; case GAME_MOUSE_ACTION_MENU_ITEM_USE: - switch (FID_TYPE(v16->fid)) { + switch (FID_TYPE(targetObj->fid)) { case OBJ_TYPE_SCENERY: - _action_use_an_object(gDude, v16); + _action_use_an_object(gDude, targetObj); break; case OBJ_TYPE_CRITTER: - _action_loot_container(gDude, v16); + _action_loot_container(gDude, targetObj); break; default: - actionPickUp(gDude, v16); + actionPickUp(gDude, targetObj); break; } break; @@ -1238,12 +1238,12 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState) } if (skill != -1) { - actionUseSkill(gDude, v16, skill); + actionUseSkill(gDude, targetObj, skill); } } break; case GAME_MOUSE_ACTION_MENU_ITEM_PUSH: - actionPush(gDude, v16); + actionPush(gDude, targetObj); break; } } @@ -1370,9 +1370,9 @@ void gameMouseSetMode(int mode) int mouseY; mouseGetPosition(&mouseX, &mouseY); - Rect r2; - if (_gmouse_3d_move_to(mouseX, mouseY, gElevation, &r2) == 0) { - rectUnion(&rect, &r2, &rect); + Rect cursorRect; + if (_gmouse_3d_move_to(mouseX, mouseY, gElevation, &cursorRect) == 0) { + rectUnion(&rect, &cursorRect, &rect); } int v5 = 0; @@ -1386,13 +1386,13 @@ void gameMouseSetMode(int mode) } if (gGameMouseMode == 0) { - if (objectDisableOutline(gGameMouseHexCursor, &r2) == 0) { - rectUnion(&rect, &r2, &rect); + if (objectDisableOutline(gGameMouseHexCursor, &cursorRect) == 0) { + rectUnion(&rect, &cursorRect, &rect); } } } else { - if (objectEnableOutline(gGameMouseHexCursor, &r2) == 0) { - rectUnion(&rect, &r2, &rect); + if (objectEnableOutline(gGameMouseHexCursor, &cursorRect) == 0) { + rectUnion(&rect, &cursorRect, &rect); } } @@ -2193,7 +2193,7 @@ int gameMouseUpdateHexCursorFid(Rect* rect) } // 0x44DF94 -int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4) +int _gmouse_3d_move_to(int x, int y, int elevation, Rect* rect) { if (_gmouse_mapper_mode == 0) { if (gGameMouseMode != GAME_MOUSE_MODE_MOVE) { @@ -2214,7 +2214,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4) artUnlock(hexCursorFrmHandle); } - _obj_move(gGameMouseHexCursor, x + offsetX, y + offsetY, elevation, a4); + _obj_move(gGameMouseHexCursor, x + offsetX, y + offsetY, elevation, rect); } else { int tile = tileFromScreenXY(x, y, 0); if (tile != -1) { @@ -2237,7 +2237,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4) rectCopy(&rect1, &rect2); } - rectCopy(a4, &rect1); + rectCopy(rect, &rect1); } } } @@ -2323,7 +2323,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4) } if (v1) { - rectCopy(a4, &rect1); + rectCopy(rect, &rect1); } } diff --git a/src/interface.h b/src/interface.h index acec2df..a813c8f 100644 --- a/src/interface.h +++ b/src/interface.h @@ -6,14 +6,6 @@ namespace fallout { -typedef enum Hand { - // Item1 (Punch) - HAND_LEFT, - // Item2 (Kick) - HAND_RIGHT, - HAND_COUNT, -} Hand; - #define INDICATOR_BOX_WIDTH 130 #define INDICATOR_BOX_HEIGHT 21 diff --git a/src/interpreter_extra.cc b/src/interpreter_extra.cc index 124583b..3229538 100644 --- a/src/interpreter_extra.cc +++ b/src/interpreter_extra.cc @@ -482,7 +482,7 @@ static void opScrReturn(Program* program) Script* script; if (scriptGetScript(sid, &script) != -1) { - script->field_28 = data; + script->returnValue = data; } } @@ -934,7 +934,7 @@ static void opCreateObject(Program* program) goto out; } - script->field_14 = sid - 1; + script->index = sid - 1; if (scriptType == SCRIPT_TYPE_SPATIAL) { script->sp.built_tile = builtTileCreate(object->tile, object->elevation); @@ -942,7 +942,7 @@ static void opCreateObject(Program* program) } object->id = scriptsNewObjectId(); - script->field_1C = object->id; + script->ownerId = object->id; script->owner = object; _scr_find_str_run_info(sid - 1, &(script->field_50), object->sid); }; diff --git a/src/inventory.cc b/src/inventory.cc index 0fd74d4..7afc8cf 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -221,7 +221,7 @@ typedef enum InventoryWindowType { } InventoryWindowType; typedef struct InventoryWindowConfiguration { - int field_0; // artId + int frmId; // artId int width; int height; int x; @@ -242,47 +242,47 @@ typedef enum InventoryMoveResult { INVENTORY_MOVE_RESULT_FAILED, INVENTORY_MOVE_RESULT_CAUGHT_STEALING, INVENTORY_MOVE_RESULT_SUCCESS, -}; +} InventoryMoveResult; static int inventoryMessageListInit(); static int inventoryMessageListFree(); static bool _setup_inventory(int inventoryWindowType); -static void _exit_inventory(bool a1); -static void _display_inventory(int a1, int a2, int inventoryWindowType); -static void _display_target_inventory(int a1, int a2, Inventory* a3, int a4); -static void _display_inventory_info(Object* item, int quantity, unsigned char* dest, int pitch, bool a5); +static void _exit_inventory(bool shouldEnableIso); +static void _display_inventory(int stackOffset, int draggedSlotIndex, int inventoryWindowType); +static void _display_target_inventory(int stackOffset, int dragSlotIndex, Inventory* inventory, int inventoryWindowType); +static void _display_inventory_info(Object* item, int quantity, unsigned char* dest, int pitch, bool isDragged); static void _display_body(int fid, int inventoryWindowType); static int inventoryCommonInit(); static void inventoryCommonFree(); static void inventorySetCursor(int cursor); static void inventoryItemSlotOnMouseEnter(int btn, int keyCode); static void inventoryItemSlotOnMouseExit(int btn, int keyCode); -static void _inven_update_lighting(Object* a1); -static void _inven_pickup(int keyCode, int a2); -static void _switch_hand(Object* a1, Object** a2, Object** a3, int a4); +static void _inven_update_lighting(Object* activeItem); +static void _inven_pickup(int keyCode, int indexOffset); +static void _switch_hand(Object* sourceItem, Object** targetSlot, Object** sourceSlot, int itemIndex); static void _adjust_fid(); static void inventoryRenderSummary(); -static int _inven_from_button(int a1, Object** a2, Object*** a3, Object** a4); +static int _inven_from_button(int keyCode, Object** outItem, Object*** outItemSlot, Object** outOwner); static void inventoryRenderItemDescription(char* string); static void inventoryExamineItem(Object* critter, Object* item); static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowType); static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting); -static int _barter_compute_value(Object* a1, Object* a2); -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_from_table_inventory(Object* a1, int quantity, int a3, Object* a4, Object* a5, bool a6); -static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a3, int a4); -static void _container_enter(int a1, int a2); +static int _barter_compute_value(Object* dude, Object* npc); +static int _barter_attempt_transaction(Object* dude, Object* offerTable, Object* npc, Object* barterTable); +static void _barter_move_inventory(Object* item, int quantity, int slotIndex, int indexOffset, Object* npc, Object* sourceTable, bool fromDude); +static void _barter_move_from_table_inventory(Object* item, int quantity, int slotIndex, Object* npc, Object* sourceTable, bool fromDude); +static void inventoryWindowRenderInnerInventories(int win, Object* leftTable, Object* rightTable, int draggedSlotIndex); +static void _container_enter(int keyCode, int inventoryWindowType); static void _container_exit(int keyCode, int inventoryWindowType); -static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int quantity); -static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int quantity, int keyCode); +static int _drop_into_container(Object* container, Object* item, int sourceIndex, Object** itemSlot, int quantity); +static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** ammoItemSlot, int quantity, int keyCode); static void _draw_amount(int value, int inventoryWindowType); -static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int a3); +static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int maximum); static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item); static int inventoryQuantityWindowFree(int inventoryWindowType); // 0x46E6D0 -static const int dword_46E6D0[7] = { +static const int gSummaryStats[7] = { STAT_CURRENT_HIT_POINTS, STAT_ARMOR_CLASS, STAT_DAMAGE_THRESHOLD, @@ -293,7 +293,7 @@ static const int dword_46E6D0[7] = { }; // 0x46E6EC -static const int dword_46E6EC[7] = { +static const int gSummaryStats2[7] = { STAT_MAXIMUM_HIT_POINTS, -1, STAT_DAMAGE_RESISTANCE, @@ -416,6 +416,7 @@ static const int _act_weap2[3] = { GAME_MOUSE_ACTION_MENU_ITEM_CANCEL, }; +// Scroll offsets to target inventory for every container nesting level (stack). // 0x59E7EC static int _target_stack_offset[10]; @@ -424,18 +425,22 @@ static int _target_stack_offset[10]; // 0x59E814 static MessageList gInventoryMessageList; +// Current target critter or container for every nesting level (stack). // 0x59E81C static Object* _target_stack[10]; +// Scroll offsets to main inventory for every container nesting level (stack). // 0x59E844 static int _stack_offset[10]; +// Current critter or container for every nesting level (stack). // 0x59E86C static Object* _stack[10]; // 0x59E894 static int _mt_wid; +// Current barter price modifier, set from scripts. // 0x59E898 static int _barter_mod; @@ -466,6 +471,7 @@ static int gInventoryCursor; // 0x59E944 static Object* _btable; +// Current nesting level for viewing target's bag/backpack contents. // 0x59E948 static int _target_curr_stack; @@ -496,6 +502,7 @@ static int gInventoryWindow; // 0x59E968 static Object* gInventoryRightHandItem; +// Current nesting level for viewing bag/backpack contents. // 0x59E96C static int _curr_stack; @@ -756,7 +763,7 @@ static bool _setup_inventory(int inventoryWindowType) unsigned char* dest = windowGetBuffer(gInventoryWindow); FrmImage backgroundFrmImage; - int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0); + int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->frmId, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { blitBufferToBuffer(backgroundFrmImage.getData(), windowDescription->width, windowDescription->height, windowDescription->width, dest, windowDescription->width); } @@ -1595,7 +1602,7 @@ static void _exit_inventory(bool shouldEnableIso) } // 0x46FDF4 -static void _display_inventory(int a1, int a2, int inventoryWindowType) +static void _display_inventory(int stackOffset, int dragSlotIndex, int inventoryWindowType) { unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow); int pitch; @@ -1684,7 +1691,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) || inventoryWindowType == INVENTORY_WINDOW_TYPE_USE_ITEM_ON || inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) { if (gInventoryScrollUpButton != -1) { - if (a1 <= 0) { + if (stackOffset <= 0) { buttonDisable(gInventoryScrollUpButton); } else { buttonEnable(gInventoryScrollUpButton); @@ -1692,7 +1699,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) } if (gInventoryScrollDownButton != -1) { - if (_pud->length - a1 <= gInventorySlotsCount) { + if (_pud->length - stackOffset <= gInventorySlotsCount) { buttonDisable(gInventoryScrollDownButton); } else { buttonEnable(gInventoryScrollDownButton); @@ -1701,8 +1708,8 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) } int y = 0; - for (int v19 = 0; v19 + a1 < _pud->length && v19 < gInventorySlotsCount; v19 += 1) { - int v21 = v19 + a1 + 1; + for (int slotIndex = 0; slotIndex + stackOffset < _pud->length && slotIndex < gInventorySlotsCount; slotIndex += 1) { + int itemIndex = slotIndex + stackOffset + 1; int offset; if (inventoryWindowType == INVENTORY_WINDOW_TYPE_TRADE) { @@ -1715,7 +1722,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) } } - InventoryItem* inventoryItem = &(_pud->items[_pud->length - v21]); + InventoryItem* inventoryItem = &(_pud->items[_pud->length - itemIndex]); int inventoryFid = itemGetInventoryFid(inventoryItem->item); artRender(inventoryFid, windowBuffer + offset, INVENTORY_SLOT_WIDTH_PAD, INVENTORY_SLOT_HEIGHT_PAD, pitch); @@ -1728,7 +1735,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) offset = pitch * (y + INVENTORY_SCROLLER_Y_PAD) + INVENTORY_SCROLLER_X_PAD; } - _display_inventory_info(inventoryItem->item, inventoryItem->quantity, windowBuffer + offset, pitch, v19 == a2); + _display_inventory_info(inventoryItem->item, inventoryItem->quantity, windowBuffer + offset, pitch, slotIndex == dragSlotIndex); y += INVENTORY_SLOT_HEIGHT; } @@ -1795,11 +1802,11 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType) // Render inventory item. // -// [a1] is likely an index of the first visible item in the scrolling view. -// [a2] is likely an index of selected item or moving item (it decreases displayed number of items in inner functions). +// [stackOffset] is an index of the first visible item in the scrolling view. +// [dragSlotIndex] is an index of item being dragged (it decreases displayed number of items in inner functions). // // 0x47036C -static void _display_target_inventory(int a1, int a2, Inventory* inventory, int inventoryWindowType) +static void _display_target_inventory(int stackOffset, int dragSlotIndex, Inventory* inventory, int inventoryWindowType) { unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow); @@ -1827,9 +1834,9 @@ static void _display_target_inventory(int a1, int a2, Inventory* inventory, int } int y = 0; - for (int index = 0; index < gInventorySlotsCount; index++) { - int v27 = a1 + index; - if (v27 >= inventory->length) { + for (int slotIndex = 0; slotIndex < gInventorySlotsCount; slotIndex++) { + int itemIndex = stackOffset + slotIndex; + if (itemIndex >= inventory->length) { break; } @@ -1842,17 +1849,17 @@ static void _display_target_inventory(int a1, int a2, Inventory* inventory, int assert(false && "Should be unreachable"); } - InventoryItem* inventoryItem = &(inventory->items[inventory->length - (v27 + 1)]); + InventoryItem* inventoryItem = &(inventory->items[inventory->length - (itemIndex + 1)]); int inventoryFid = itemGetInventoryFid(inventoryItem->item); artRender(inventoryFid, windowBuffer + offset, INVENTORY_SLOT_WIDTH_PAD, INVENTORY_SLOT_HEIGHT_PAD, pitch); - _display_inventory_info(inventoryItem->item, inventoryItem->quantity, windowBuffer + offset, pitch, index == a2); + _display_inventory_info(inventoryItem->item, inventoryItem->quantity, windowBuffer + offset, pitch, slotIndex == dragSlotIndex); y += INVENTORY_SLOT_HEIGHT; } if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) { if (gSecondaryInventoryScrollUpButton != -1) { - if (a1 <= 0) { + if (stackOffset <= 0) { buttonDisable(gSecondaryInventoryScrollUpButton); } else { buttonEnable(gSecondaryInventoryScrollUpButton); @@ -1860,7 +1867,7 @@ static void _display_target_inventory(int a1, int a2, Inventory* inventory, int } if (gSecondaryInventoryScrollDownButton != -1) { - if (inventory->length - a1 <= gInventorySlotsCount) { + if (inventory->length - stackOffset <= gInventorySlotsCount) { buttonDisable(gSecondaryInventoryScrollDownButton); } else { buttonEnable(gSecondaryInventoryScrollDownButton); @@ -1923,7 +1930,7 @@ static void _display_target_inventory(int a1, int a2, Inventory* inventory, int // Renders inventory item quantity. // // 0x4705A0 -static void _display_inventory_info(Object* item, int quantity, unsigned char* dest, int pitch, bool a5) +static void _display_inventory_info(Object* item, int quantity, unsigned char* dest, int pitch, bool isDragged) { int oldFont = fontGetCurrent(); fontSetCurrent(101); @@ -1936,7 +1943,7 @@ static void _display_inventory_info(Object* item, int quantity, unsigned char* d if (itemGetType(item) == ITEM_TYPE_AMMO) { int ammoQuantity = ammoGetCapacity(item) * (quantity - 1); - if (!a5) { + if (!isDragged) { ammoQuantity += ammoGetQuantity(item); } @@ -1949,7 +1956,7 @@ static void _display_inventory_info(Object* item, int quantity, unsigned char* d } else { if (quantity > 1) { int v9 = quantity; - if (a5) { + if (isDragged) { v9 -= 1; } @@ -2204,8 +2211,8 @@ static void inventoryItemSlotOnMouseEnter(int btn, int keyCode) int y; mouseGetPositionInWindow(gInventoryWindow, &x, &y); - Object* a2a = nullptr; - if (_inven_from_button(keyCode, &a2a, nullptr, nullptr) != 0) { + Object* item = nullptr; + if (_inven_from_button(keyCode, &item, nullptr, nullptr) != 0) { gameMouseRenderPrimaryAction(x, y, 3, gInventoryWindowMaxX, gInventoryWindowMaxY); int v5 = 0; @@ -2215,15 +2222,15 @@ static void inventoryItemSlotOnMouseEnter(int btn, int keyCode) InventoryCursorData* cursorData = &(gInventoryCursorData[INVENTORY_WINDOW_CURSOR_PICK]); mouseSetFrame(cursorData->frmData, cursorData->width, cursorData->height, cursorData->width, v5, v6, 0); - if (a2a != _last_target) { - _obj_look_at_func(_stack[0], a2a, gInventoryPrintItemDescriptionHandler); + if (item != _last_target) { + _obj_look_at_func(_stack[0], item, gInventoryPrintItemDescriptionHandler); } } else { InventoryCursorData* cursorData = &(gInventoryCursorData[INVENTORY_WINDOW_CURSOR_ARROW]); mouseSetFrame(cursorData->frmData, cursorData->width, cursorData->height, cursorData->width, cursorData->offsetX, cursorData->offsetY, 0); } - _last_target = a2a; + _last_target = item; } _im_value = keyCode; @@ -2241,12 +2248,12 @@ static void inventoryItemSlotOnMouseExit(int btn, int keyCode) } // 0x470D5C -static void _inven_update_lighting(Object* a1) +static void _inven_update_lighting(Object* activeItem) { if (gDude == _inven_dude) { int lightDistance; - if (a1 != nullptr && a1->lightDistance > 4) { - lightDistance = a1->lightDistance; + if (activeItem != nullptr && activeItem->lightDistance > 4) { + lightDistance = activeItem->lightDistance; } else { lightDistance = 4; } @@ -2258,32 +2265,32 @@ static void _inven_update_lighting(Object* a1) } // 0x470DB8 -static void _inven_pickup(int keyCode, int a2) +static void _inven_pickup(int buttonCode, int indexOffset) { - Object* a1a; - Object** v29 = nullptr; - int count = _inven_from_button(keyCode, &a1a, &v29, nullptr); + Object* item; + Object** itemSlot = nullptr; + int count = _inven_from_button(buttonCode, &item, &itemSlot, nullptr); if (count == 0) { return; } - int v3 = -1; - Object* v39 = nullptr; + int itemIndex = -1; + Object* itemInHand = nullptr; Rect rect; - switch (keyCode) { + switch (buttonCode) { case 1006: rect.left = 245; rect.top = 286; if (_inven_dude == gDude && interfaceGetCurrentHand() != HAND_LEFT) { - v39 = a1a; + itemInHand = item; } break; case 1007: rect.left = 154; rect.top = 286; if (_inven_dude == gDude && interfaceGetCurrentHand() == HAND_LEFT) { - v39 = a1a; + itemInHand = item; } break; case 1008: @@ -2293,18 +2300,18 @@ static void _inven_pickup(int keyCode, int a2) default: // NOTE: Original code a little bit different, this code path // is only for key codes below 1006. - v3 = keyCode - 1000; + itemIndex = buttonCode - 1000; rect.left = INVENTORY_SCROLLER_X; - rect.top = INVENTORY_SLOT_HEIGHT * v3 + INVENTORY_SCROLLER_Y; + rect.top = INVENTORY_SLOT_HEIGHT * itemIndex + INVENTORY_SCROLLER_Y; break; } - if (v3 == -1 || _pud->items[a2 + v3].quantity <= 1) { + if (itemIndex == -1 || _pud->items[indexOffset + itemIndex].quantity <= 1) { unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow); - if (gInventoryRightHandItem != gInventoryLeftHandItem || a1a != gInventoryLeftHandItem) { + if (gInventoryRightHandItem != gInventoryLeftHandItem || item != gInventoryLeftHandItem) { int height; int width; - if (v3 == -1) { + if (itemIndex == -1) { height = INVENTORY_LARGE_SLOT_HEIGHT; width = INVENTORY_LARGE_SLOT_WIDTH; } else { @@ -2344,11 +2351,11 @@ static void _inven_pickup(int keyCode, int a2) } windowRefreshRect(gInventoryWindow, &rect); } else { - _display_inventory(a2, v3, INVENTORY_WINDOW_TYPE_NORMAL); + _display_inventory(indexOffset, itemIndex, INVENTORY_WINDOW_TYPE_NORMAL); } FrmImage itemInventoryFrmImage; - int itemInventoryFid = itemGetInventoryFid(a1a); + int itemInventoryFid = itemGetInventoryFid(item); if (itemInventoryFrmImage.lock(itemInventoryFid)) { int width = itemInventoryFrmImage.getWidth(); int height = itemInventoryFrmImage.getHeight(); @@ -2357,7 +2364,7 @@ static void _inven_pickup(int keyCode, int a2) soundPlayFile("ipickup1"); } - if (v39 != nullptr) { + if (itemInHand != nullptr) { _inven_update_lighting(nullptr); } @@ -2381,88 +2388,89 @@ static void _inven_pickup(int keyCode, int a2) int y; mouseGetPositionInWindow(gInventoryWindow, &x, &y); - int v18 = (y - 39) / INVENTORY_SLOT_HEIGHT + a2; - if (v18 < _pud->length) { - Object* v19 = _pud->items[v18].item; - if (v19 != a1a) { - // TODO: Needs checking usage of v19 - if (itemGetType(v19) == ITEM_TYPE_CONTAINER) { - if (_drop_into_container(v19, a1a, v3, v29, count) == 0) { - v3 = 0; + int targetIndex = (y - 39) / INVENTORY_SLOT_HEIGHT + indexOffset; + if (targetIndex < _pud->length) { + Object* targetItem = _pud->items[targetIndex].item; + if (targetItem != item) { + // Dropping item on top of another item. + if (itemGetType(targetItem) == ITEM_TYPE_CONTAINER) { + if (_drop_into_container(targetItem, item, itemIndex, itemSlot, count) == 0) { + itemIndex = 0; } } else { - if (_drop_ammo_into_weapon(v19, a1a, v29, count, keyCode) == 0) { - v3 = 0; + if (_drop_ammo_into_weapon(targetItem, item, itemSlot, count, buttonCode) == 0) { + itemIndex = 0; } } } } - if (v3 == -1) { + if (itemIndex == -1) { // TODO: Holy shit, needs refactoring. - *v29 = nullptr; - if (itemAdd(_inven_dude, a1a, 1)) { - *v29 = a1a; - } else if (v29 == &gInventoryArmor) { - _adjust_ac(_stack[0], a1a, nullptr); + *itemSlot = nullptr; + if (itemAdd(_inven_dude, item, 1)) { + *itemSlot = item; + } else if (itemSlot == &gInventoryArmor) { + _adjust_ac(_stack[0], item, nullptr); } else if (gInventoryRightHandItem == gInventoryLeftHandItem) { gInventoryLeftHandItem = nullptr; gInventoryRightHandItem = nullptr; } } } else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_LEFT_HAND_SLOT_X, INVENTORY_LEFT_HAND_SLOT_Y, INVENTORY_LEFT_HAND_SLOT_MAX_X, INVENTORY_LEFT_HAND_SLOT_MAX_Y)) { - if (gInventoryLeftHandItem != nullptr && itemGetType(gInventoryLeftHandItem) == ITEM_TYPE_CONTAINER && gInventoryLeftHandItem != a1a) { - _drop_into_container(gInventoryLeftHandItem, a1a, v3, v29, count); - } else if (gInventoryLeftHandItem == nullptr || _drop_ammo_into_weapon(gInventoryLeftHandItem, a1a, v29, count, keyCode)) { - _switch_hand(a1a, &gInventoryLeftHandItem, v29, keyCode); + if (gInventoryLeftHandItem != nullptr && itemGetType(gInventoryLeftHandItem) == ITEM_TYPE_CONTAINER && gInventoryLeftHandItem != item) { + _drop_into_container(gInventoryLeftHandItem, item, itemIndex, itemSlot, count); + } else if (gInventoryLeftHandItem == nullptr || _drop_ammo_into_weapon(gInventoryLeftHandItem, item, itemSlot, count, buttonCode)) { + _switch_hand(item, &gInventoryLeftHandItem, itemSlot, buttonCode); } } else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_RIGHT_HAND_SLOT_X, INVENTORY_RIGHT_HAND_SLOT_Y, INVENTORY_RIGHT_HAND_SLOT_MAX_X, INVENTORY_RIGHT_HAND_SLOT_MAX_Y)) { - if (gInventoryRightHandItem != nullptr && itemGetType(gInventoryRightHandItem) == ITEM_TYPE_CONTAINER && gInventoryRightHandItem != a1a) { - _drop_into_container(gInventoryRightHandItem, a1a, v3, v29, count); - } else if (gInventoryRightHandItem == nullptr || _drop_ammo_into_weapon(gInventoryRightHandItem, a1a, v29, count, keyCode)) { - _switch_hand(a1a, &gInventoryRightHandItem, v29, v3); + if (gInventoryRightHandItem != nullptr && itemGetType(gInventoryRightHandItem) == ITEM_TYPE_CONTAINER && gInventoryRightHandItem != item) { + _drop_into_container(gInventoryRightHandItem, item, itemIndex, itemSlot, count); + } else if (gInventoryRightHandItem == nullptr || _drop_ammo_into_weapon(gInventoryRightHandItem, item, itemSlot, count, buttonCode)) { + _switch_hand(item, &gInventoryRightHandItem, itemSlot, itemIndex); } } else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_ARMOR_SLOT_X, INVENTORY_ARMOR_SLOT_Y, INVENTORY_ARMOR_SLOT_MAX_X, INVENTORY_ARMOR_SLOT_MAX_Y)) { - if (itemGetType(a1a) == ITEM_TYPE_ARMOR) { - Object* v21 = gInventoryArmor; - int v22 = 0; - if (v3 != -1) { - itemRemove(_inven_dude, a1a, 1); + if (itemGetType(item) == ITEM_TYPE_ARMOR) { + Object* currentArmor = gInventoryArmor; + int itemAddResult = 0; + if (itemIndex != -1) { + itemRemove(_inven_dude, item, 1); } if (gInventoryArmor != nullptr) { - if (v29 != nullptr) { - *v29 = gInventoryArmor; + if (itemSlot != nullptr) { + *itemSlot = gInventoryArmor; } else { gInventoryArmor = nullptr; - v22 = itemAdd(_inven_dude, v21, 1); + itemAddResult = itemAdd(_inven_dude, currentArmor, 1); } } else { - if (v29 != nullptr) { - *v29 = gInventoryArmor; + if (itemSlot != nullptr) { + *itemSlot = gInventoryArmor; } } - if (v22 != 0) { - gInventoryArmor = v21; - if (v3 != -1) { - itemAdd(_inven_dude, a1a, 1); + if (itemAddResult != 0) { + gInventoryArmor = currentArmor; + if (itemIndex != -1) { + itemAdd(_inven_dude, item, 1); } } else { - _adjust_ac(_stack[0], v21, a1a); - gInventoryArmor = a1a; + _adjust_ac(_stack[0], currentArmor, item); + gInventoryArmor = item; } } } else if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_PC_BODY_VIEW_X, INVENTORY_PC_BODY_VIEW_Y, INVENTORY_PC_BODY_VIEW_MAX_X, INVENTORY_PC_BODY_VIEW_MAX_Y)) { if (_curr_stack != 0) { - // TODO: Check this _curr_stack - 1, not sure. - _drop_into_container(_stack[_curr_stack - 1], a1a, v3, v29, count); + // If we are looking inside nested inventory (such as backpack item), we see this item in the PC Body View instead of the player. + // So we drop item into it. + _drop_into_container(_stack[_curr_stack - 1], item, itemIndex, itemSlot, count); } } _adjust_fid(); inventoryRenderSummary(); - _display_inventory(a2, -1, INVENTORY_WINDOW_TYPE_NORMAL); + _display_inventory(indexOffset, -1, INVENTORY_WINDOW_TYPE_NORMAL); inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); if (_inven_dude == gDude) { Object* item; @@ -2479,52 +2487,52 @@ static void _inven_pickup(int keyCode, int a2) } // 0x4714E0 -static void _switch_hand(Object* a1, Object** a2, Object** a3, int a4) +static void _switch_hand(Object* sourceItem, Object** targetSlot, Object** sourceSlot, int itemIndex) { - if (*a2 != nullptr) { - if (itemGetType(*a2) == ITEM_TYPE_WEAPON && itemGetType(a1) == ITEM_TYPE_AMMO) { + if (*targetSlot != nullptr) { + if (itemGetType(*targetSlot) == ITEM_TYPE_WEAPON && itemGetType(sourceItem) == ITEM_TYPE_AMMO) { return; } - if (a3 != nullptr && (a3 != &gInventoryArmor || itemGetType(*a2) == ITEM_TYPE_ARMOR)) { - if (a3 == &gInventoryArmor) { - _adjust_ac(_stack[0], gInventoryArmor, *a2); + if (sourceSlot != nullptr && (sourceSlot != &gInventoryArmor || itemGetType(*targetSlot) == ITEM_TYPE_ARMOR)) { + if (sourceSlot == &gInventoryArmor) { + _adjust_ac(_stack[0], gInventoryArmor, *targetSlot); } - *a3 = *a2; + *sourceSlot = *targetSlot; } else { - if (a4 != -1) { - itemRemove(_inven_dude, a1, 1); + if (itemIndex != -1) { + itemRemove(_inven_dude, sourceItem, 1); } - Object* itemToAdd = *a2; - *a2 = nullptr; - if (itemAdd(_inven_dude, itemToAdd, 1) != 0) { - itemAdd(_inven_dude, a1, 1); + Object* existingItem = *targetSlot; + *targetSlot = nullptr; + if (itemAdd(_inven_dude, existingItem, 1) != 0) { + itemAdd(_inven_dude, sourceItem, 1); return; } - a4 = -1; + itemIndex = -1; - if (a3 != nullptr) { - if (a3 == &gInventoryArmor) { + if (sourceSlot != nullptr) { + if (sourceSlot == &gInventoryArmor) { _adjust_ac(_stack[0], gInventoryArmor, nullptr); } - *a3 = nullptr; + *sourceSlot = nullptr; } } } else { - if (a3 != nullptr) { - if (a3 == &gInventoryArmor) { + if (sourceSlot != nullptr) { + if (sourceSlot == &gInventoryArmor) { _adjust_ac(_stack[0], gInventoryArmor, nullptr); } - *a3 = nullptr; + *sourceSlot = nullptr; } } - *a2 = a1; + *targetSlot = sourceItem; - if (a4 != -1) { - itemRemove(_inven_dude, a1, 1); + if (itemIndex != -1) { + itemRemove(_inven_dude, sourceItem, 1); } } @@ -2622,7 +2630,7 @@ static void _adjust_fid() } // 0x4717E4 -void inventoryOpenUseItemOn(Object* a1) +void inventoryOpenUseItemOn(Object* targetObj) { ScopedGameMode gm(GameMode::kUseOn); @@ -2706,7 +2714,7 @@ void inventoryOpenUseItemOn(Object* a1) InventoryItem* inventoryItem = &(_pud->items[inventoryItemIndex]); if (isInCombat()) { if (gDude->data.critter.combat.ap >= 2) { - if (_action_use_an_item_on_object(gDude, a1, inventoryItem->item) != -1) { + if (_action_use_an_item_on_object(gDude, targetObj, inventoryItem->item) != -1) { int actionPoints = gDude->data.critter.combat.ap; if (actionPoints < 2) { gDude->data.critter.combat.ap = 0; @@ -2717,7 +2725,7 @@ void inventoryOpenUseItemOn(Object* a1) } } } else { - _action_use_an_item_on_object(gDude, a1, inventoryItem->item); + _action_use_an_item_on_object(gDude, targetObj, inventoryItem->item); } keyCode = KEY_ESCAPE; } else { @@ -2869,11 +2877,11 @@ int objectGetCarriedQuantityByPid(Object* object, int pid) // 0x471D5C static void inventoryRenderSummary() { - int v56[7]; - memcpy(v56, dword_46E6D0, sizeof(v56)); + int summaryStats[7]; + memcpy(summaryStats, gSummaryStats, sizeof(summaryStats)); - int v57[7]; - memcpy(v57, dword_46E6EC, sizeof(v57)); + int summaryStats2[7]; + memcpy(summaryStats2, gSummaryStats2, sizeof(summaryStats2)); char formattedText[80]; @@ -2908,7 +2916,7 @@ static void inventoryRenderSummary() MessageListItem messageListItem; int offset = INVENTORY_WINDOW_WIDTH * 2 * fontGetLineHeight() + INVENTORY_WINDOW_WIDTH * INVENTORY_SUMMARY_Y + INVENTORY_SUMMARY_X; - for (int stat = 0; stat < 7; stat++) { + for (int stat = 0; stat < PRIMARY_STAT_COUNT; stat++) { messageListItem.num = stat; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { fontDrawText(windowBuffer + offset, messageListItem.text, 80, INVENTORY_WINDOW_WIDTH, _colorTable[992]); @@ -2929,12 +2937,12 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset + 40, messageListItem.text, 80, INVENTORY_WINDOW_WIDTH, _colorTable[992]); } - if (v57[index] == -1) { - int value = critterGetStat(_stack[0], v56[index]); + if (summaryStats2[index] == -1) { + int value = critterGetStat(_stack[0], summaryStats[index]); snprintf(formattedText, sizeof(formattedText), " %d", value); } else { - int value1 = critterGetStat(_stack[0], v56[index]); - int value2 = critterGetStat(_stack[0], v57[index]); + int value1 = critterGetStat(_stack[0], summaryStats[index]); + int value2 = critterGetStat(_stack[0], summaryStats2[index]); const char* format = index != 0 ? "%d/%d%%" : "%d/%d"; snprintf(formattedText, sizeof(formattedText), format, value1, value2); } @@ -3206,6 +3214,8 @@ Object* _inven_find_type(Object* obj, int itemType, int* indexPtr) return inventory->items[*indexPtr].item; } +// Searches for an item with a given id inside given obj's inventory. +// // 0x4726EC Object* _inven_find_id(Object* obj, int id) { @@ -3232,31 +3242,33 @@ Object* _inven_find_id(Object* obj, int id) return nullptr; } +// Returns inventory item at a given index. +// // 0x472740 -Object* _inven_index_ptr(Object* obj, int a2) +Object* _inven_index_ptr(Object* obj, int index) { Inventory* inventory; inventory = &(obj->data.inventory); - if (a2 < 0 || a2 >= inventory->length) { + if (index < 0 || index >= inventory->length) { return nullptr; } - return inventory->items[a2].item; + return inventory->items[index].item; } // inven_wield // 0x472758 -int _inven_wield(Object* a1, Object* a2, int a3) +int _inven_wield(Object* critter, Object* item, int hand) { - return _invenWieldFunc(a1, a2, a3, true); + return _invenWieldFunc(critter, item, hand, true); } // 0x472768 -int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) +int _invenWieldFunc(Object* critter, Object* item, int handIndex, bool animate) { - if (a4) { + if (animate) { if (!isoIsDisabled()) { reg_anim_begin(ANIMATION_REQUEST_RESERVED); } @@ -3307,7 +3319,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) } Object* v17; - if (a3) { + if (handIndex) { v17 = critterGetItem2(critter); item->flags |= OBJECT_IN_RIGHT_HAND; } else { @@ -3360,9 +3372,9 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) weaponAnimationCode = 0; } - if (hand == a3) { + if (hand == handIndex) { if ((critter->fid & 0xF000) >> 12 != 0) { - if (a4) { + if (animate) { if (!isoIsDisabled()) { const char* soundEffectName = sfxBuildCharName(critter, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED); animationRegisterPlaySoundEffect(critter, soundEffectName, 0); @@ -3371,7 +3383,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) } } - if (a4 && !isoIsDisabled()) { + if (animate && !isoIsDisabled()) { if (weaponAnimationCode != 0) { animationRegisterTakeOutWeapon(critter, weaponAnimationCode, -1); } else { @@ -3385,7 +3397,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) } } - if (a4) { + if (animate) { if (!isoIsDisabled()) { return reg_anim_end(); } @@ -3396,84 +3408,84 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) // inven_unwield // 0x472A54 -int _inven_unwield(Object* critter_obj, int a2) +int _inven_unwield(Object* critter_obj, int hand) { - return _invenUnwieldFunc(critter_obj, a2, 1); + return _invenUnwieldFunc(critter_obj, hand, true); } // 0x472A64 -int _invenUnwieldFunc(Object* obj, int a2, int a3) +int _invenUnwieldFunc(Object* critter, int hand, bool animate) { - int v6; - Object* item_obj; + int activeHand; + Object* item; int fid; - if (obj == gDude) { - v6 = interfaceGetCurrentHand(); + if (critter == gDude) { + activeHand = interfaceGetCurrentHand(); } else { - v6 = 1; + activeHand = HAND_RIGHT; // NPC's only ever use right slot } - if (a2) { - item_obj = critterGetItem2(obj); + if (hand) { + item = critterGetItem2(critter); } else { - item_obj = critterGetItem1(obj); + item = critterGetItem1(critter); } - if (item_obj) { - item_obj->flags &= ~OBJECT_IN_ANY_HAND; + if (item) { + item->flags &= ~OBJECT_IN_ANY_HAND; } - if (v6 == a2 && ((obj->fid & 0xF000) >> 12) != 0) { - if (a3 && !isoIsDisabled()) { + if (activeHand == hand && ((critter->fid & 0xF000) >> 12) != 0) { + if (animate && !isoIsDisabled()) { reg_anim_begin(ANIMATION_REQUEST_RESERVED); - const char* sfx = sfxBuildCharName(obj, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED); - animationRegisterPlaySoundEffect(obj, sfx, 0); + const char* sfx = sfxBuildCharName(critter, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED); + animationRegisterPlaySoundEffect(critter, sfx, 0); - animationRegisterAnimate(obj, ANIM_PUT_AWAY, 0); + animationRegisterAnimate(critter, ANIM_PUT_AWAY, 0); - fid = buildFid(OBJ_TYPE_CRITTER, obj->fid & 0xFFF, 0, 0, obj->rotation + 1); - animationRegisterSetFid(obj, fid, -1); + fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, 0, 0, critter->rotation + 1); + animationRegisterSetFid(critter, fid, -1); return reg_anim_end(); } - fid = buildFid(OBJ_TYPE_CRITTER, obj->fid & 0xFFF, 0, 0, obj->rotation + 1); - _dude_stand(obj, obj->rotation, fid); + fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, 0, 0, critter->rotation + 1); + _dude_stand(critter, critter->rotation, fid); } return 0; } // 0x472B54 -static int _inven_from_button(int keyCode, Object** a2, Object*** a3, Object** a4) +static int _inven_from_button(int keyCode, Object** outItem, Object*** outItemSlot, Object** outOwner) { - Object** v6; - Object* v7; - Object* v8; + Object** itemSlot; + Object* owner; + Object* item; int quantity = 0; switch (keyCode) { case 1006: - v6 = &gInventoryRightHandItem; - v7 = _stack[0]; - v8 = gInventoryRightHandItem; + itemSlot = &gInventoryRightHandItem; + owner = _stack[0]; + item = gInventoryRightHandItem; break; case 1007: - v6 = &gInventoryLeftHandItem; - v7 = _stack[0]; - v8 = gInventoryLeftHandItem; + itemSlot = &gInventoryLeftHandItem; + owner = _stack[0]; + item = gInventoryLeftHandItem; break; case 1008: - v6 = &gInventoryArmor; - v7 = _stack[0]; - v8 = gInventoryArmor; + itemSlot = &gInventoryArmor; + owner = _stack[0]; + item = gInventoryArmor; break; default: - v6 = nullptr; - v7 = nullptr; - v8 = nullptr; + itemSlot = nullptr; + owner = nullptr; + item = nullptr; InventoryItem* inventoryItem; if (keyCode < 2000) { @@ -3483,8 +3495,8 @@ static int _inven_from_button(int keyCode, Object** a2, Object*** a3, Object** a } inventoryItem = &(_pud->items[_pud->length - (index + 1)]); - v8 = inventoryItem->item; - v7 = _stack[_curr_stack]; + item = inventoryItem->item; + owner = _stack[_curr_stack]; } else if (keyCode < 2300) { int index = _target_stack_offset[_target_curr_stack] + keyCode - 2000; if (index >= _target_pud->length) { @@ -3492,8 +3504,8 @@ static int _inven_from_button(int keyCode, Object** a2, Object*** a3, Object** a } inventoryItem = &(_target_pud->items[_target_pud->length - (index + 1)]); - v8 = inventoryItem->item; - v7 = _target_stack[_target_curr_stack]; + item = inventoryItem->item; + owner = _target_stack[_target_curr_stack]; } else if (keyCode < 2400) { int index = _ptable_offset + keyCode - 2300; if (index >= _ptable_pud->length) { @@ -3501,8 +3513,8 @@ static int _inven_from_button(int keyCode, Object** a2, Object*** a3, Object** a } inventoryItem = &(_ptable_pud->items[_ptable_pud->length - (index + 1)]); - v8 = inventoryItem->item; - v7 = _ptable; + item = inventoryItem->item; + owner = _ptable; } else { int index = _btable_offset + keyCode - 2400; if (index >= _btable_pud->length) { @@ -3510,26 +3522,26 @@ static int _inven_from_button(int keyCode, Object** a2, Object*** a3, Object** a } inventoryItem = &(_btable_pud->items[_btable_pud->length - (index + 1)]); - v8 = inventoryItem->item; - v7 = _btable; + item = inventoryItem->item; + owner = _btable; } quantity = inventoryItem->quantity; } - if (a3 != nullptr) { - *a3 = v6; + if (outItemSlot != nullptr) { + *outItemSlot = itemSlot; } - if (a2 != nullptr) { - *a2 = v8; + if (outItem != nullptr) { + *outItem = item; } - if (a4 != nullptr) { - *a4 = v7; + if (outOwner != nullptr) { + *outOwner = owner; } - if (quantity == 0 && v8 != nullptr) { + if (quantity == 0 && item != nullptr) { quantity = 1; } @@ -3700,11 +3712,11 @@ static void inventoryExamineItem(Object* critter, Object* item) static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) { Object* item; - Object** v43; - Object* v41; + Object** itemSlot; + Object* owner; - int v56 = _inven_from_button(keyCode, &item, &v43, &v41); - if (v56 == 0) { + int quantity = _inven_from_button(keyCode, &item, &itemSlot, &owner); + if (quantity == 0) { return; } @@ -3776,7 +3788,7 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) } } } else { - if (itemType == ITEM_TYPE_CONTAINER && v43 != nullptr) { + if (itemType == ITEM_TYPE_CONTAINER && itemSlot != nullptr) { actionMenuItemsLength = 3; actionMenuItems = _act_no_use; } else { @@ -3878,7 +3890,7 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) windowDescription->width); } else { FrmImage backgroundFrmImage; - int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0); + int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->frmId, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { blitBufferToBuffer(backgroundFrmImage.getData() + windowDescription->width * rect.top + rect.left, cursorData->width, @@ -3896,52 +3908,52 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) int actionMenuItem = actionMenuItems[menuItemIndex]; switch (actionMenuItem) { case GAME_MOUSE_ACTION_MENU_ITEM_DROP: - if (v43 != nullptr) { - if (v43 == &gInventoryArmor) { + if (itemSlot != nullptr) { + if (itemSlot == &gInventoryArmor) { _adjust_ac(_stack[0], item, nullptr); } - itemAdd(v41, item, 1); - v56 = 1; - *v43 = nullptr; + itemAdd(owner, item, 1); + quantity = 1; + *itemSlot = nullptr; } if (item->pid == PROTO_ID_MONEY) { - if (v56 > 1) { - v56 = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, v56); + if (quantity > 1) { + quantity = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity); } else { - v56 = 1; + quantity = 1; } - if (v56 > 0) { - if (v56 == 1) { + if (quantity > 0) { + if (quantity == 1) { itemSetMoney(item, 1); - _obj_drop(v41, item); + _obj_drop(owner, item); } else { - if (itemRemove(v41, item, v56 - 1) == 0) { - Object* a2; - if (_inven_from_button(keyCode, &a2, &v43, &v41) != 0) { - itemSetMoney(a2, v56); - _obj_drop(v41, a2); + if (itemRemove(owner, item, quantity - 1) == 0) { + Object* item2; + if (_inven_from_button(keyCode, &item2, &itemSlot, &owner) != 0) { + itemSetMoney(item2, quantity); + _obj_drop(owner, item2); } else { - itemAdd(v41, item, v56 - 1); + itemAdd(owner, item, quantity - 1); } } } } } else if (explosiveIsActiveExplosive(item->pid)) { _dropped_explosive = 1; - _obj_drop(v41, item); + _obj_drop(owner, item); } else { - if (v56 > 1) { - v56 = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, v56); + if (quantity > 1) { + quantity = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity); - for (int index = 0; index < v56; index++) { - if (_inven_from_button(keyCode, &item, &v43, &v41) != 0) { - _obj_drop(v41, item); + for (int index = 0; index < quantity; index++) { + if (_inven_from_button(keyCode, &item, &itemSlot, &owner) != 0) { + _obj_drop(owner, item); } } } else { - _obj_drop(v41, item); + _obj_drop(owner, item); } } break; @@ -3959,10 +3971,10 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) break; case ITEM_TYPE_DRUG: if (_item_d_take_drug(_stack[0], item)) { - if (v43 != nullptr) { - *v43 = nullptr; + if (itemSlot != nullptr) { + *itemSlot = nullptr; } else { - itemRemove(v41, item, 1); + itemRemove(owner, item, 1); } _obj_connect(item, gDude->tile, gDude->elevation, nullptr); @@ -3972,34 +3984,34 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) break; case ITEM_TYPE_WEAPON: case ITEM_TYPE_MISC: - if (v43 == nullptr) { - itemRemove(v41, item, 1); + if (itemSlot == nullptr) { + itemRemove(owner, item, 1); } - int v21; + int useResult; if (_obj_action_can_use(item)) { - v21 = _protinst_use_item(_stack[0], item); + useResult = _protinst_use_item(_stack[0], item); } else { - v21 = _protinst_use_item_on(_stack[0], _stack[0], item); + useResult = _protinst_use_item_on(_stack[0], _stack[0], item); } - if (v21 == 1) { - if (v43 != nullptr) { - *v43 = nullptr; + if (useResult == 1) { + if (itemSlot != nullptr) { + *itemSlot = nullptr; } _obj_connect(item, gDude->tile, gDude->elevation, nullptr); _obj_destroy(item); } else { - if (v43 == nullptr) { - itemAdd(v41, item, 1); + if (itemSlot == nullptr) { + itemAdd(owner, item, 1); } } } break; case GAME_MOUSE_ACTION_MENU_ITEM_UNLOAD: - if (v43 == nullptr) { - itemRemove(v41, item, 1); + if (itemSlot == nullptr) { + itemRemove(owner, item, 1); } for (;;) { @@ -4010,11 +4022,11 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType) Rect rect; _obj_disconnect(ammo, &rect); - itemAdd(v41, ammo, 1); + itemAdd(owner, ammo, 1); } - if (v43 == nullptr) { - itemAdd(v41, item, 1); + if (itemSlot == nullptr) { + itemAdd(owner, item, 1); } break; default: @@ -4658,7 +4670,7 @@ static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* } // 0x474B2C -static int _barter_compute_value(Object* a1, Object* a2) +static int _barter_compute_value(Object* dude, Object* npc) { if (gGameDialogSpeakerIsPartyMember) { return objectGetInventoryWeight(_btable); @@ -4666,37 +4678,37 @@ static int _barter_compute_value(Object* a1, Object* a2) int cost = objectGetCost(_btable); int caps = itemGetTotalCaps(_btable); - int v14 = cost - caps; + int costWithoutCaps = cost - caps; - double bonus = 0.0; - if (a1 == gDude) { + double perkBonus = 0.0; + if (dude == gDude) { if (perkHasRank(gDude, PERK_MASTER_TRADER)) { - bonus = 25.0; + perkBonus = 25.0; } } int partyBarter = partyGetBestSkillValue(SKILL_BARTER); - int npcBarter = skillGetValue(a2, SKILL_BARTER); + int npcBarter = skillGetValue(npc, SKILL_BARTER); // TODO: Check in debugger, complex math, probably uses floats, not doubles. - double v1 = (_barter_mod + 100.0 - bonus) * 0.01; - double v2 = (160.0 + npcBarter) / (160.0 + partyBarter) * (v14 * 2.0); - if (v1 < 0) { + double barterModMult = (_barter_mod + 100.0 - perkBonus) * 0.01; + double balancedCost = (160.0 + npcBarter) / (160.0 + partyBarter) * (costWithoutCaps * 2.0); + if (barterModMult < 0) { // TODO: Probably 0.01 as float. - v1 = 0.0099999998; + barterModMult = 0.0099999998; } - int rounded = (int)(v1 * v2 + caps); + int rounded = (int)(barterModMult * balancedCost + caps); return rounded; } // 0x474C50 -static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Object* a4) +static int _barter_attempt_transaction(Object* dude, Object* offerTable, Object* npc, Object* barterTable) { MessageListItem messageListItem; - int v8 = critterGetStat(a1, STAT_CARRY_WEIGHT) - objectGetInventoryWeight(a1); - if (objectGetInventoryWeight(a4) > v8) { + int weightAvailable = critterGetStat(dude, STAT_CARRY_WEIGHT) - objectGetInventoryWeight(dude); + if (objectGetInventoryWeight(barterTable) > weightAvailable) { // Sorry, you cannot carry that much. messageListItem.num = 31; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4706,8 +4718,8 @@ static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Objec } if (gGameDialogSpeakerIsPartyMember) { - int v10 = critterGetStat(a3, STAT_CARRY_WEIGHT) - objectGetInventoryWeight(a3); - if (objectGetInventoryWeight(a2) > v10) { + int npcWeightAvailable = critterGetStat(npc, STAT_CARRY_WEIGHT) - objectGetInventoryWeight(npc); + if (objectGetInventoryWeight(offerTable) > npcWeightAvailable) { // Sorry, that's too much to carry. messageListItem.num = 32; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4716,25 +4728,25 @@ static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Objec return -1; } } else { - bool v11 = false; - if (a2->data.inventory.length == 0) { - v11 = true; + bool badOffer = false; + if (offerTable->data.inventory.length == 0) { + badOffer = true; } else { - if (itemIsQueued(a2)) { - if (a2->pid != PROTO_ID_GEIGER_COUNTER_I || miscItemTurnOff(a2) == -1) { - v11 = true; + if (itemIsQueued(offerTable)) { + if (offerTable->pid != PROTO_ID_GEIGER_COUNTER_I || miscItemTurnOff(offerTable) == -1) { + badOffer = true; } } } - if (!v11) { - int cost = objectGetCost(a2); - if (_barter_compute_value(a1, a3) > cost) { - v11 = true; + if (!badOffer) { + int cost = objectGetCost(offerTable); + if (_barter_compute_value(dude, npc) > cost) { + badOffer = true; } } - if (v11) { + if (badOffer) { // No, your offer is not good enough. messageListItem.num = 28; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4744,28 +4756,28 @@ static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Objec } } - itemMoveAll(a4, a1); - itemMoveAll(a2, a3); + itemMoveAll(barterTable, dude); + itemMoveAll(offerTable, npc); return 0; } // 0x474DAC -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* item, int quantity, int slotIndex, int indexOffset, Object* npc, Object* sourceTable, bool fromDude) { Rect rect; - if (a7) { + if (fromDude) { rect.left = 23; - rect.top = INVENTORY_SLOT_HEIGHT * a3 + 34; + rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + 34; } else { rect.left = 395; - rect.top = INVENTORY_SLOT_HEIGHT * a3 + 31; + rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + 31; } if (quantity > 1) { - if (a7) { - _display_inventory(a4, a3, INVENTORY_WINDOW_TYPE_TRADE); + if (fromDude) { + _display_inventory(indexOffset, slotIndex, INVENTORY_WINDOW_TYPE_TRADE); } else { - _display_target_inventory(a4, a3, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); + _display_target_inventory(indexOffset, slotIndex, _target_pud, INVENTORY_WINDOW_TYPE_TRADE); } } else { unsigned char* dest = windowGetBuffer(gInventoryWindow); @@ -4780,7 +4792,7 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj } FrmImage itemInventoryFrmImage; - int itemInventoryFid = itemGetInventoryFid(a1); + int itemInventoryFid = itemGetInventoryFid(item); if (itemInventoryFrmImage.lock(itemInventoryFid)) { int width = itemInventoryFrmImage.getWidth(); int height = itemInventoryFrmImage.getHeight(); @@ -4805,11 +4817,11 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj MessageListItem messageListItem; - if (a7) { + if (fromDude) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity) : 1; if (quantityToMove != -1) { - if (itemMoveForce(_inven_dude, a6, a1, quantityToMove) == -1) { + if (itemMoveForce(_inven_dude, sourceTable, item, quantityToMove) == -1) { // There is no space left for that item. messageListItem.num = 26; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4820,9 +4832,9 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj } } else { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity) : 1; if (quantityToMove != -1) { - if (itemMoveForce(a5, a6, a1, quantityToMove) == -1) { + if (itemMoveForce(npc, sourceTable, item, quantityToMove) == -1) { // You cannot pick that up. You are at your maximum weight capacity. messageListItem.num = 25; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4837,22 +4849,22 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj } // 0x475070 -static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, Object* a4, Object* a5, bool a6) +static void _barter_move_from_table_inventory(Object* item, int quantity, int slotIndex, Object* npc, Object* sourceTable, bool fromDude) { Rect rect; - if (a6) { + if (fromDude) { rect.left = INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD; - rect.top = INVENTORY_SLOT_HEIGHT * a3 + INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y_PAD; + rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y_PAD; } else { rect.left = INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD; - rect.top = INVENTORY_SLOT_HEIGHT * a3 + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y_PAD; + rect.top = INVENTORY_SLOT_HEIGHT * slotIndex + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y_PAD; } if (quantity > 1) { - if (a6) { - inventoryWindowRenderInnerInventories(_barter_back_win, a5, nullptr, a3); + if (fromDude) { + inventoryWindowRenderInnerInventories(_barter_back_win, sourceTable, nullptr, slotIndex); } else { - inventoryWindowRenderInnerInventories(_barter_back_win, nullptr, a5, a3); + inventoryWindowRenderInnerInventories(_barter_back_win, nullptr, sourceTable, slotIndex); } } else { unsigned char* dest = windowGetBuffer(gInventoryWindow); @@ -4867,7 +4879,7 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, } FrmImage itemInventoryFrmImage; - int itemInventoryFid = itemGetInventoryFid(a1); + int itemInventoryFid = itemGetInventoryFid(item); if (itemInventoryFrmImage.lock(itemInventoryFid)) { int width = itemInventoryFrmImage.getWidth(); int height = itemInventoryFrmImage.getHeight(); @@ -4892,11 +4904,11 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, MessageListItem messageListItem; - if (a6) { + if (fromDude) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_X, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity) : 1; if (quantityToMove != -1) { - if (itemMoveForce(a5, _inven_dude, a1, quantityToMove) == -1) { + if (itemMoveForce(sourceTable, _inven_dude, item, quantityToMove) == -1) { // There is no space left for that item. messageListItem.num = 26; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4907,9 +4919,9 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, } } 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)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity) : 1; if (quantityToMove != -1) { - if (itemMoveForce(a5, a4, a1, quantityToMove) == -1) { + if (itemMoveForce(sourceTable, npc, item, quantityToMove) == -1) { // You cannot pick that up. You are at your maximum weight capacity. messageListItem.num = 25; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -4924,7 +4936,7 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, } // 0x475334 -static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a3, int a4) +static void inventoryWindowRenderInnerInventories(int win, Object* leftTable, Object* rightTable, int draggedSlotIndex) { unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow); @@ -4932,19 +4944,19 @@ static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a fontSetCurrent(101); char formattedText[80]; - int v45 = fontGetLineHeight() + INVENTORY_SLOT_HEIGHT * gInventorySlotsCount; + int rectHeight = fontGetLineHeight() + INVENTORY_SLOT_HEIGHT * gInventorySlotsCount; - if (a2 != nullptr) { + if (leftTable != nullptr) { unsigned char* src = windowGetBuffer(win); - blitBufferToBuffer(src + INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH * INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y + INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD + INVENTORY_TRADE_WINDOW_OFFSET, INVENTORY_SLOT_WIDTH, v45 + 1, INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH, windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y + INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD, INVENTORY_TRADE_WINDOW_WIDTH); + blitBufferToBuffer(src + INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH * INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y + INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD + INVENTORY_TRADE_WINDOW_OFFSET, INVENTORY_SLOT_WIDTH, rectHeight + 1, INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH, windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y + INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD, INVENTORY_TRADE_WINDOW_WIDTH); unsigned char* dest = windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y_PAD + INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD; - Inventory* inventory = &(a2->data.inventory); + Inventory* inventory = &(leftTable->data.inventory); for (int index = 0; index < gInventorySlotsCount && index + _ptable_offset < inventory->length; index++) { InventoryItem* inventoryItem = &(inventory->items[inventory->length - (index + _ptable_offset + 1)]); int inventoryFid = itemGetInventoryFid(inventoryItem->item); artRender(inventoryFid, dest, INVENTORY_SLOT_WIDTH_PAD, INVENTORY_SLOT_HEIGHT_PAD, INVENTORY_TRADE_WINDOW_WIDTH); - _display_inventory_info(inventoryItem->item, inventoryItem->quantity, dest, INVENTORY_TRADE_WINDOW_WIDTH, index == a4); + _display_inventory_info(inventoryItem->item, inventoryItem->quantity, dest, INVENTORY_TRADE_WINDOW_WIDTH, index == draggedSlotIndex); dest += INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_SLOT_HEIGHT; } @@ -4954,11 +4966,11 @@ static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a messageListItem.num = 30; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { - int weight = objectGetInventoryWeight(a2); + int weight = objectGetInventoryWeight(leftTable); snprintf(formattedText, sizeof(formattedText), "%s %d", messageListItem.text, weight); } } else { - int cost = objectGetCost(a2); + int cost = objectGetCost(leftTable); snprintf(formattedText, sizeof(formattedText), "$%d", cost); } @@ -4969,21 +4981,21 @@ static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a rect.top = INVENTORY_TRADE_INNER_LEFT_SCROLLER_Y_PAD; // NOTE: Odd math, the only way to get 223 is to subtract 2. rect.right = INVENTORY_TRADE_INNER_LEFT_SCROLLER_X_PAD + INVENTORY_SLOT_WIDTH_PAD - 2; - rect.bottom = rect.top + v45; + rect.bottom = rect.top + rectHeight; windowRefreshRect(gInventoryWindow, &rect); } - if (a3 != nullptr) { + if (rightTable != nullptr) { unsigned char* src = windowGetBuffer(win); - blitBufferToBuffer(src + INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH * INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD + INVENTORY_TRADE_WINDOW_OFFSET, INVENTORY_SLOT_WIDTH, v45 + 1, INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH, windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD, INVENTORY_TRADE_WINDOW_WIDTH); + blitBufferToBuffer(src + INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH * INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD + INVENTORY_TRADE_WINDOW_OFFSET, INVENTORY_SLOT_WIDTH, rectHeight + 1, INVENTORY_TRADE_BACKGROUND_WINDOW_WIDTH, windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD, INVENTORY_TRADE_WINDOW_WIDTH); unsigned char* dest = windowBuffer + INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y_PAD + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD; - Inventory* inventory = &(a3->data.inventory); + Inventory* inventory = &(rightTable->data.inventory); for (int index = 0; index < gInventorySlotsCount && index + _btable_offset < inventory->length; index++) { InventoryItem* inventoryItem = &(inventory->items[inventory->length - (index + _btable_offset + 1)]); int inventoryFid = itemGetInventoryFid(inventoryItem->item); artRender(inventoryFid, dest, INVENTORY_SLOT_WIDTH_PAD, INVENTORY_SLOT_HEIGHT_PAD, INVENTORY_TRADE_WINDOW_WIDTH); - _display_inventory_info(inventoryItem->item, inventoryItem->quantity, dest, INVENTORY_TRADE_WINDOW_WIDTH, index == a4); + _display_inventory_info(inventoryItem->item, inventoryItem->quantity, dest, INVENTORY_TRADE_WINDOW_WIDTH, index == draggedSlotIndex); dest += INVENTORY_TRADE_WINDOW_WIDTH * INVENTORY_SLOT_HEIGHT; } @@ -5008,7 +5020,7 @@ static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a rect.top = INVENTORY_TRADE_INNER_RIGHT_SCROLLER_Y_PAD; // NOTE: Odd math, likely should be `INVENTORY_SLOT_WIDTH_PAD`. rect.right = INVENTORY_TRADE_INNER_RIGHT_SCROLLER_X_PAD + INVENTORY_SLOT_WIDTH; - rect.bottom = rect.top + v45; + rect.bottom = rect.top + rectHeight; windowRefreshRect(gInventoryWindow, &rect); } @@ -5192,9 +5204,9 @@ void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* } else { int slotIndex = keyCode - 1000; if (slotIndex + _stack_offset[_curr_stack] < _pud->length) { - int stackOffset = _stack_offset[_curr_stack]; - InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + stackOffset + 1)]); - _barter_move_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, stackOffset, barterer, playerTable, true); + int offset = _stack_offset[_curr_stack]; + InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + offset + 1)]); + _barter_move_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, offset, barterer, playerTable, true); _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); inventoryWindowRenderInnerInventories(win, playerTable, nullptr, -1); @@ -5224,10 +5236,10 @@ void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowRenderInnerInventories(win, playerTable, nullptr, -1); } else { - int itemIndex = keyCode - 2300; - if (itemIndex < _ptable_pud->length) { - InventoryItem* inventoryItem = &(_ptable_pud->items[_ptable_pud->length - (itemIndex + _ptable_offset + 1)]); - _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, itemIndex, barterer, playerTable, true); + int slotIndex = keyCode - 2300; + if (slotIndex < _ptable_pud->length) { + InventoryItem* inventoryItem = &(_ptable_pud->items[_ptable_pud->length - (slotIndex + _ptable_offset + 1)]); + _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, barterer, playerTable, true); _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); inventoryWindowRenderInnerInventories(win, playerTable, nullptr, -1); @@ -5240,10 +5252,10 @@ void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* inventoryWindowOpenContextMenu(keyCode, INVENTORY_WINDOW_TYPE_TRADE); inventoryWindowRenderInnerInventories(win, nullptr, bartererTable, -1); } else { - int v45 = keyCode - 2400; - if (v45 < _btable_pud->length) { - InventoryItem* inventoryItem = &(_btable_pud->items[_btable_pud->length - (v45 + _btable_offset + 1)]); - _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, v45, barterer, bartererTable, false); + int slotIndex = keyCode - 2400; + if (slotIndex < _btable_pud->length) { + InventoryItem* inventoryItem = &(_btable_pud->items[_btable_pud->length - (slotIndex + _btable_offset + 1)]); + _barter_move_from_table_inventory(inventoryItem->item, inventoryItem->quantity, slotIndex, barterer, bartererTable, false); _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); inventoryWindowRenderInnerInventories(win, nullptr, bartererTable, -1); @@ -5412,12 +5424,13 @@ static void _container_exit(int keyCode, int inventoryWindowType) } } +// Drop item inside a container item (bag, backpack, etc.). // 0x476464 -static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int quantity) +static int _drop_into_container(Object* container, Object* item, int sourceIndex, Object** itemSlot, int quantity) { int quantityToMove; if (quantity > 1) { - quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a2, quantity); + quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, quantity); } else { quantityToMove = 1; } @@ -5426,26 +5439,26 @@ static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int return -1; } - if (a3 != -1) { - if (itemRemove(_inven_dude, a2, quantityToMove) == -1) { + if (sourceIndex != -1) { + if (itemRemove(_inven_dude, item, quantityToMove) == -1) { return -1; } } - int rc = itemAttemptAdd(a1, a2, quantityToMove); + int rc = itemAttemptAdd(container, item, quantityToMove); if (rc != 0) { - if (a3 != -1) { + if (sourceIndex != -1) { // SFALL: Fix for items disappearing from inventory when you try to // drag them to bag/backpack in the inventory list and are // overloaded. - itemAdd(_inven_dude, a2, quantityToMove); + itemAdd(_inven_dude, item, quantityToMove); } } else { - if (a4 != nullptr) { - if (a4 == &gInventoryArmor) { + if (itemSlot != nullptr) { + if (itemSlot == &gInventoryArmor) { _adjust_ac(_stack[0], gInventoryArmor, nullptr); } - *a4 = nullptr; + *itemSlot = nullptr; } } @@ -5453,7 +5466,7 @@ static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int } // 0x47650C -static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int quantity, int keyCode) +static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** ammoItemSlot, int quantity, int keyCode) { if (itemGetType(weapon) != ITEM_TYPE_WEAPON) { return -1; @@ -5478,27 +5491,27 @@ static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int return -1; } - Object* v14 = ammo; - bool v17 = false; + Object* sourceItem = ammo; + bool isReloaded = false; int rc = itemRemove(_inven_dude, weapon, 1); for (int index = 0; index < quantityToMove; index++) { - int v11 = weaponReload(weapon, v14); - if (v11 == 0) { - if (a3 != nullptr) { - *a3 = nullptr; + int rcReload = weaponReload(weapon, sourceItem); + if (rcReload == 0) { + if (ammoItemSlot != nullptr) { + *ammoItemSlot = nullptr; } - _obj_destroy(v14); + _obj_destroy(sourceItem); - v17 = true; - if (_inven_from_button(keyCode, &v14, nullptr, nullptr) == 0) { + isReloaded = true; + if (_inven_from_button(keyCode, &sourceItem, nullptr, nullptr) == 0) { break; } } - if (v11 != -1) { - v17 = true; + if (rcReload != -1) { + isReloaded = true; } - if (v11 != 0) { + if (rcReload != 0) { break; } } @@ -5507,7 +5520,7 @@ static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int itemAdd(_inven_dude, weapon, 1); } - if (!v17) { + if (!isReloaded) { return -1; } @@ -5589,7 +5602,7 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma _draw_amount(value, inventoryWindowType); - bool v5 = false; + bool isTyping = false; for (;;) { sharedFpsLimiter.mark(); @@ -5609,11 +5622,11 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma soundPlayFile("iisxxxx1"); } else if (keyCode == 5000) { - v5 = false; + isTyping = false; value = max; _draw_amount(value, inventoryWindowType); } else if (keyCode == 6000) { - v5 = false; + isTyping = false; if (value < max) { if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) { if ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT) != 0) { @@ -5651,7 +5664,7 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma continue; } } else if (keyCode == 7000) { - v5 = false; + isTyping = false; if (value > min) { if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) { if ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT) != 0) { @@ -5693,22 +5706,22 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) { if (keyCode >= KEY_0 && keyCode <= KEY_9) { int number = keyCode - KEY_0; - if (!v5) { + if (!isTyping) { value = 0; } value = 10 * value % 100000 + number; - v5 = true; + isTyping = true; _draw_amount(value, inventoryWindowType); continue; } else if (keyCode == KEY_BACKSPACE) { - if (!v5) { + if (!isTyping) { value = 0; } value /= 10; - v5 = true; + isTyping = true; _draw_amount(value, inventoryWindowType); continue; @@ -5745,7 +5758,7 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item) unsigned char* windowBuffer = windowGetBuffer(_mt_wid); FrmImage backgroundFrmImage; - int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0); + int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->frmId, 0, 0, 0); if (backgroundFrmImage.lock(backgroundFid)) { blitBufferToBuffer(backgroundFrmImage.getData(), windowDescription->width, @@ -5955,19 +5968,19 @@ static int inventoryQuantityWindowFree(int inventoryWindowType) } // 0x477074 -int _inven_set_timer(Object* a1) +int _inven_set_timer(Object* item) { - bool v1 = _inven_is_initialized; + bool isInitialized = _inven_is_initialized; - if (!v1) { + if (!isInitialized) { if (inventoryCommonInit() == -1) { return -1; } } - int seconds = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_SET_TIMER, a1, 180); + int seconds = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_SET_TIMER, item, 180); - if (!v1) { + if (!isInitialized) { // NOTE: Uninline. inventoryCommonFree(); } diff --git a/src/inventory.h b/src/inventory.h index bb5a8ea..f1c033c 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -5,28 +5,41 @@ namespace fallout { +typedef enum Hand { + // Item1 (Punch) + HAND_LEFT, + // Item2 (Kick) + HAND_RIGHT, + HAND_COUNT, +} Hand; + typedef void InventoryPrintItemDescriptionHandler(char* string); void _inven_reset_dude(); void inventoryOpen(); void _adjust_ac(Object* critter, Object* oldArmor, Object* newArmor); -void inventoryOpenUseItemOn(Object* a1); -Object* critterGetItem2(Object* obj); -Object* critterGetItem1(Object* obj); -Object* critterGetArmor(Object* obj); +void inventoryOpenUseItemOn(Object* targetObj); +Object* critterGetItem2(Object* critter); +Object* critterGetItem1(Object* critter); +Object* critterGetArmor(Object* critter); Object* objectGetCarriedObjectByPid(Object* obj, int pid); int objectGetCarriedQuantityByPid(Object* obj, int pid); -Object* _inven_find_type(Object* obj, int a2, int* inout_a3); -Object* _inven_find_id(Object* obj, int a2); -Object* _inven_index_ptr(Object* obj, int a2); -int _inven_wield(Object* a1, Object* a2, int a3); -int _invenWieldFunc(Object* a1, Object* a2, int a3, bool a4); -int _inven_unwield(Object* critter_obj, int a2); -int _invenUnwieldFunc(Object* obj, int a2, int a3); +Object* _inven_find_type(Object* obj, int itemType, int* indexPtr); +Object* _inven_find_id(Object* obj, int id); +Object* _inven_index_ptr(Object* obj, int index); +// Makes critter equip a given item in a given hand slot with an animation. +// 0 - left hand, 1 - right hand. If item is armor, hand value is ignored. +int _inven_wield(Object* critter, Object* item, int hand); +// Same as inven_wield but allows to wield item without animation. +int _invenWieldFunc(Object* critter, Object* item, int hand, bool animate); +// Makes critter unequip an item in a given hand slot with an animation. +int _inven_unwield(Object* critter, int hand); +// Same as inven_unwield but allows to unwield item without animation. +int _invenUnwieldFunc(Object* critter, int hand, bool animate); int inventoryOpenLooting(Object* looter, Object* target); int inventoryOpenStealing(Object* thief, Object* target); void inventoryOpenTrade(int win, Object* barterer, Object* playerTable, Object* bartererTable, int barterMod); -int _inven_set_timer(Object* a1); +int _inven_set_timer(Object* item); Object* inven_get_current_target_obj(); } // namespace fallout diff --git a/src/item.cc b/src/item.cc index 5952825..c86e543 100644 --- a/src/item.cc +++ b/src/item.cc @@ -47,8 +47,8 @@ static int _item_move_func(Object* source, Object* target, Object* item, int qua static bool _item_identical(Object* item1, Object* item2); static int stealthBoyTurnOn(Object* object); 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 void _perform_drug_effect(Object* critter_obj, int* stats, int* mods, bool is_immediate); +static int _insert_drug_effect(Object* critter, Object* item, int duration, int* stats, int* mods); +static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool isImmediate); static bool _drug_effect_allowed(Object* critter, int pid); static int _insert_withdrawal(Object* obj, int a2, int a3, int a4, int a5); static int _item_wd_clear_all(Object* a1, void* data); @@ -319,7 +319,7 @@ int itemAttemptAdd(Object* owner, Object* itemToAdd, int quantity) return itemAdd(owner, itemToAdd, quantity); } -// item_add +// item_add_force // 0x4772B8 int itemAdd(Object* owner, Object* itemToAdd, int quantity) { @@ -675,14 +675,15 @@ static bool _item_identical(Object* item1, Object* item2) return false; } - int v1; + int item2Quantity; if (proto->item.type == ITEM_TYPE_AMMO || item1->pid == PROTO_ID_MONEY) { - v1 = item2->data.item.ammo.quantity; + item2Quantity = item2->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 - // bytes. + // NOTE: Likely there was a comparison of ItemObjectData structs via inlined memcmp + // ItemObjectData are 24 bytes, but compared 32 bytes due to struct alignment or such. + // Another explanation is the presence of 8 more bytes of unknown data that was never used. int i; for (i = 0; i < 8; i++) { if (item1->field_2C_array[i] != item2->field_2C_array[i]) { @@ -691,7 +692,7 @@ static bool _item_identical(Object* item1, Object* item2) } if (proto->item.type == ITEM_TYPE_AMMO || item1->pid == PROTO_ID_MONEY) { - item2->data.item.ammo.quantity = v1; + item2->data.item.ammo.quantity = item2Quantity; } return i == 8; @@ -2593,8 +2594,11 @@ int ammoGetDamageDivisor(Object* armor) return proto->item.data.ammo.damageDivisor; } +// Adds Drug event to event queue. +// [duration] is in minutes +// // 0x479B44 -static int _insert_drug_effect(Object* critter, Object* item, int a3, int* stats, int* mods) +static int _insert_drug_effect(Object* critter, Object* item, int duration, int* stats, int* mods) { int index; for (index = 0; index < 3; index++) { @@ -2619,7 +2623,7 @@ static int _insert_drug_effect(Object* critter, Object* item, int a3, int* stats drugEffectEvent->modifiers[index] = mods[index]; } - int delay = 600 * a3; + int delay = 600 * duration; if (critter == gDude) { if (traitIsSelected(TRAIT_CHEM_RESISTANT)) { delay /= 2; @@ -2637,25 +2641,23 @@ static int _insert_drug_effect(Object* critter, Object* item, int a3, int* stats // 0x479C20 static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool isImmediate) { - int v10; - int v11; - int v12; MessageListItem messageListItem; const char* name; const char* text; - char v24[92]; // TODO: Size is probably wrong. - char str[92]; // TODO: Size is probably wrong. + char msgBuf[92]; // TODO: Size is probably wrong. bool statsChanged = false; - int v5 = 0; - bool v32 = false; + int startIndex = 0; + bool firstStatIsMinimum = false; if (stats[0] == -2) { - v5 = 1; - v32 = true; + startIndex = 1; + firstStatIsMinimum = true; } - for (int index = v5; index < 3; index++) { + for (int index = startIndex; index < 3; index++) { + int oldStatBonus; + int statBonus; int stat = stats[index]; if (stat == -1) { continue; @@ -2665,32 +2667,31 @@ static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool is critter->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING; } - v10 = critterGetBonusStat(critter, stat); + oldStatBonus = critterGetBonusStat(critter, stat); - int before; - if (critter == gDude) { - before = critterGetStat(gDude, stat); - } + int before = (critter == gDude) + ? critterGetStat(gDude, stat) + : 0; - if (v32) { - v11 = randomBetween(mods[index - 1], mods[index]) + v10; - v32 = false; + if (firstStatIsMinimum) { + statBonus = randomBetween(mods[index - 1], mods[index]) + oldStatBonus; + firstStatIsMinimum = false; } else { - v11 = mods[index] + v10; + statBonus = mods[index] + oldStatBonus; } if (stat == STAT_CURRENT_HIT_POINTS) { - v12 = critterGetBaseStatWithTraitModifier(critter, STAT_CURRENT_HIT_POINTS); - if (v11 + v12 <= 0 && critter != gDude) { + int currentHp = critterGetBaseStatWithTraitModifier(critter, STAT_CURRENT_HIT_POINTS); + if (statBonus + currentHp <= 0 && critter != gDude) { name = critterGetName(critter); // %s succumbs to the adverse effects of chems. text = getmsg(&gItemsMessageList, &messageListItem, 600); - snprintf(v24, sizeof(v24), text, name); - _combatKillCritterOutsideCombat(critter, v24); + snprintf(msgBuf, sizeof(msgBuf), text, name); + _combatKillCritterOutsideCombat(critter, msgBuf); } } - critterSetBonusStat(critter, stat, v11); + critterSetBonusStat(critter, stat, statBonus); if (critter == gDude) { if (stat == STAT_CURRENT_HIT_POINTS) { @@ -2704,8 +2705,8 @@ static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool is messageListItem.num = after < before ? 2 : 1; if (messageListGetItem(&gItemsMessageList, &messageListItem)) { char* statName = statGetName(stat); - snprintf(str, sizeof(str), messageListItem.text, after < before ? before - after : after - before, statName); - displayMonitorAddMessage(str); + snprintf(msgBuf, sizeof(msgBuf), messageListItem.text, after < before ? before - after : after - before, statName); + displayMonitorAddMessage(msgBuf); statsChanged = true; } } @@ -2725,14 +2726,14 @@ static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool is // You suffer a fatal heart attack from chem overdose. messageListItem.num = 4; if (messageListGetItem(&gItemsMessageList, &messageListItem)) { - strcpy(v24, messageListItem.text); + strcpy(msgBuf, messageListItem.text); // TODO: Why message is ignored? } } else { name = critterGetName(critter); // %s succumbs to the adverse effects of chems. text = getmsg(&gItemsMessageList, &messageListItem, 600); - snprintf(v24, sizeof(v24), text, name); + snprintf(msgBuf, sizeof(msgBuf), text, name); // TODO: Why message is ignored? } } diff --git a/src/map.cc b/src/map.cc index 6368501..e73109f 100644 --- a/src/map.cc +++ b/src/map.cc @@ -373,7 +373,7 @@ int mapSetElevation(int elevation) } if (elevation != gElevation) { - wmMapMarkMapEntranceState(gMapHeader.field_34, elevation, 1); + wmMapMarkMapEntranceState(gMapHeader.index, elevation, 1); } gElevation = elevation; @@ -596,7 +596,7 @@ char* _map_get_description_idx_(int map) // 0x4826B8 int mapGetCurrentMap() { - return gMapHeader.field_34; + return gMapHeader.index; } // 0x4826C0 @@ -927,7 +927,7 @@ static int mapLoad(File* stream) lightSetAmbientIntensity(LIGHT_INTENSITY_MAX, false); objectSetLocation(gDude, gCenterTile, gElevation, nullptr); objectSetRotation(gDude, gEnteringRotation, nullptr); - gMapHeader.field_34 = wmMapMatchNameToIdx(gMapHeader.name); + gMapHeader.index = wmMapMatchNameToIdx(gMapHeader.name); if ((gMapHeader.flags & 1) == 0) { char path[COMPAT_MAX_PATH]; @@ -965,10 +965,10 @@ static int mapLoad(File* stream) Script* script; scriptGetScript(gMapSid, &script); - script->field_14 = gMapHeader.scriptIndex - 1; + script->index = gMapHeader.scriptIndex - 1; script->flags |= SCRIPT_FLAG_0x08; object->id = scriptsNewObjectId(); - script->field_1C = object->id; + script->ownerId = object->id; script->owner = object; _scr_spatials_disable(); scriptExecProc(gMapSid, SCRIPT_PROC_MAP_ENTER); @@ -1025,8 +1025,8 @@ err: rc = -1; } - wmMapMarkVisited(gMapHeader.field_34); - wmMapMarkMapEntranceState(gMapHeader.field_34, gElevation, 1); + wmMapMarkVisited(gMapHeader.index); + wmMapMarkMapEntranceState(gMapHeader.index, gElevation, 1); if (wmCheckGameAreaEvents() != 0) { rc = -1; @@ -1203,7 +1203,7 @@ static int _map_age_dead_critters() int _map_target_load_area() { int city = -1; - if (wmMatchAreaContainingMapIdx(gMapHeader.field_34, &city) == -1) { + if (wmMatchAreaContainingMapIdx(gMapHeader.index, &city) == -1) { city = -1; } return city; @@ -1254,7 +1254,7 @@ int mapHandleTransition() } } else { if (!isInCombat()) { - if (gMapTransition.map != gMapHeader.field_34 || gElevation == gMapTransition.elevation) { + if (gMapTransition.map != gMapHeader.index || gElevation == gMapTransition.elevation) { // SFALL: Remove text floaters after moving to another map. textObjectsReset(); @@ -1262,7 +1262,7 @@ int mapHandleTransition() } if (gMapTransition.tile != -1 && gMapTransition.tile != 0 - && gMapHeader.field_34 != MAP_MODOC_BEDNBREAKFAST && gMapHeader.field_34 != MAP_THE_SQUAT_A + && gMapHeader.index != MAP_MODOC_BEDNBREAKFAST && gMapHeader.index != MAP_THE_SQUAT_A && elevationIsValid(gMapTransition.elevation)) { objectSetLocation(gDude, gMapTransition.tile, gMapTransition.elevation, nullptr); mapSetElevation(gMapTransition.elevation); @@ -1276,7 +1276,7 @@ int mapHandleTransition() memset(&gMapTransition, 0, sizeof(gMapTransition)); int city; - wmMatchAreaContainingMapIdx(gMapHeader.field_34, &city); + wmMatchAreaContainingMapIdx(gMapHeader.index, &city); if (wmTeleportToArea(city) == -1) { debugPrint("\nError: couldn't make jump on worldmap for map jump!"); } @@ -1748,7 +1748,7 @@ static int mapHeaderWrite(MapHeader* ptr, File* stream) if (fileWriteInt32(stream, ptr->flags) == -1) return -1; if (fileWriteInt32(stream, ptr->darkness) == -1) return -1; if (fileWriteInt32(stream, ptr->globalVariablesCount) == -1) return -1; - if (fileWriteInt32(stream, ptr->field_34) == -1) return -1; + if (fileWriteInt32(stream, ptr->index) == -1) return -1; if (fileWriteUInt32(stream, ptr->lastVisitTime) == -1) return -1; if (fileWriteInt32List(stream, ptr->field_3C, 44) == -1) return -1; @@ -1768,7 +1768,7 @@ static int mapHeaderRead(MapHeader* ptr, File* stream) if (fileReadInt32(stream, &(ptr->flags)) == -1) return -1; if (fileReadInt32(stream, &(ptr->darkness)) == -1) return -1; if (fileReadInt32(stream, &(ptr->globalVariablesCount)) == -1) return -1; - if (fileReadInt32(stream, &(ptr->field_34)) == -1) return -1; + if (fileReadInt32(stream, &(ptr->index)) == -1) return -1; if (fileReadUInt32(stream, &(ptr->lastVisitTime)) == -1) return -1; if (fileReadInt32List(stream, ptr->field_3C, 44) == -1) return -1; diff --git a/src/map.h b/src/map.h index 70e8d7f..f4f8adc 100644 --- a/src/map.h +++ b/src/map.h @@ -51,7 +51,7 @@ typedef struct MapHeader { int globalVariablesCount; // map_number - int field_34; + int index; // Time in game ticks when PC last visited this map. unsigned int lastVisitTime; diff --git a/src/mouse.cc b/src/mouse.cc index ab91d63..9b27ba9 100644 --- a/src/mouse.cc +++ b/src/mouse.cc @@ -632,12 +632,12 @@ void mouseGetPosition(int* xPtr, int* yPtr) } // 0x4CAA04 -void _mouse_set_position(int a1, int a2) +void _mouse_set_position(int x, int y) { - gMouseCursorX = a1 - _mouse_hotx; - gMouseCursorY = a2 - _mouse_hoty; - _raw_y = a2 - _mouse_hoty; - _raw_x = a1 - _mouse_hotx; + gMouseCursorX = x - _mouse_hotx; + gMouseCursorY = y - _mouse_hoty; + _raw_y = y - _mouse_hoty; + _raw_x = x - _mouse_hotx; _mouse_clip(); } diff --git a/src/mouse.h b/src/mouse.h index 667250f..e166f0a 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -42,7 +42,7 @@ bool _mouse_in(int left, int top, int right, int bottom); bool _mouse_click_in(int left, int top, int right, int bottom); void mouseGetRect(Rect* rect); void mouseGetPosition(int* out_x, int* out_y); -void _mouse_set_position(int a1, int a2); +void _mouse_set_position(int x, int y); int mouseGetEvent(); bool cursorIsHidden(); void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons); diff --git a/src/obj_types.h b/src/obj_types.h index c1d1867..a4fd039 100644 --- a/src/obj_types.h +++ b/src/obj_types.h @@ -248,6 +248,7 @@ typedef struct MiscObjectData { int rotation; } MiscObjectData; +// TODO: use C-style inheritance for different ObjectData variants instead of unions within unions. typedef struct ObjectData { Inventory inventory; union { @@ -276,6 +277,7 @@ typedef struct Object { int flags; // obj_flags int elevation; // obj_elev union { + // TODO: union of different ObjectData sub-structs int field_2C_array[14]; ObjectData data; }; @@ -286,7 +288,7 @@ typedef struct Object { int outline; // obj_outline int sid; // obj_sid Object* owner; - int field_80; + int scriptIndex; } Object; typedef struct ObjectListNode { diff --git a/src/object.cc b/src/object.cc index e02f660..20b7aef 100644 --- a/src/object.cc +++ b/src/object.cc @@ -430,7 +430,7 @@ int objectRead(Object* obj, File* stream) if (fileReadInt32(stream, &(obj->lightIntensity)) == -1) return -1; if (fileReadInt32(stream, &field_74) == -1) return -1; if (fileReadInt32(stream, &(obj->sid)) == -1) return -1; - if (fileReadInt32(stream, &(obj->field_80)) == -1) return -1; + if (fileReadInt32(stream, &(obj->scriptIndex)) == -1) return -1; obj->outline = 0; obj->owner = nullptr; @@ -539,7 +539,7 @@ static int objectLoadAllInternal(File* stream) debugPrint("\nError connecting object to script!"); } else { script->owner = objectListNode->obj; - objectListNode->obj->field_80 = script->field_14; + objectListNode->obj->scriptIndex = script->index; } } @@ -661,7 +661,7 @@ static int objectWrite(Object* obj, File* stream) if (fileWriteInt32(stream, obj->lightIntensity) == -1) return -1; if (fileWriteInt32(stream, obj->outline) == -1) return -1; if (fileWriteInt32(stream, obj->sid) == -1) return -1; - if (fileWriteInt32(stream, obj->field_80) == -1) return -1; + if (fileWriteInt32(stream, obj->scriptIndex) == -1) return -1; if (objectDataWrite(obj, stream) == -1) return -1; return 0; @@ -3719,7 +3719,7 @@ static int objectAllocate(Object** objectPtr) object->pid = -1; object->sid = -1; object->owner = nullptr; - object->field_80 = -1; + object->scriptIndex = -1; return 0; } diff --git a/src/object.h b/src/object.h index f9ccfb5..3fd3775 100644 --- a/src/object.h +++ b/src/object.h @@ -55,7 +55,7 @@ int objectHide(Object* obj, Rect* rect); int objectEnableOutline(Object* obj, Rect* rect); int objectDisableOutline(Object* obj, Rect* rect); int _obj_toggle_flat(Object* obj, Rect* rect); -int objectDestroy(Object* a1, Rect* a2); +int objectDestroy(Object* object, Rect* rect); int _obj_inven_free(Inventory* inventory); bool _obj_action_can_use(Object* obj); bool _obj_action_can_talk_to(Object* obj); diff --git a/src/party_member.cc b/src/party_member.cc index dab17ab..c09a82d 100644 --- a/src/party_member.cc +++ b/src/party_member.cc @@ -58,10 +58,10 @@ typedef struct PartyMemberDescription { int level_pids[PARTY_MEMBER_MAX_LEVEL]; } PartyMemberDescription; -typedef struct STRU_519DBC { - int field_0; - int field_4; // party member level - int field_8; // early what? +typedef struct PartyMemberLevelUpInfo { + int level; // party member level + int numLevelUps; // number of PC level ups with this member in party + int isEarly; // last level up was "early" due to successful roll } STRU_519DBC; typedef struct PartyMemberListItem { @@ -113,7 +113,7 @@ static int _partyStatePrepped = 0; static PartyMemberDescription* gPartyMemberDescriptions = nullptr; // 0x519DBC -static STRU_519DBC* _partyMemberLevelUpInfoList = nullptr; +static PartyMemberLevelUpInfo* _partyMemberLevelUpInfoList = nullptr; // 0x519DC0 static int _curID = 20000; @@ -164,7 +164,7 @@ int partyMembersInit() memset(gPartyMemberDescriptions, 0, sizeof(*gPartyMemberDescriptions) * gPartyMemberDescriptionsLength); - _partyMemberLevelUpInfoList = (STRU_519DBC*)internal_malloc(sizeof(*_partyMemberLevelUpInfoList) * gPartyMemberDescriptionsLength); + _partyMemberLevelUpInfoList = (PartyMemberLevelUpInfo*)internal_malloc(sizeof(*_partyMemberLevelUpInfoList) * gPartyMemberDescriptionsLength); if (_partyMemberLevelUpInfoList == nullptr) goto err; memset(_partyMemberLevelUpInfoList, 0, sizeof(*_partyMemberLevelUpInfoList) * gPartyMemberDescriptionsLength); @@ -275,9 +275,9 @@ err: void partyMembersReset() { for (int index = 0; index < gPartyMemberDescriptionsLength; index++) { - _partyMemberLevelUpInfoList[index].field_0 = 0; - _partyMemberLevelUpInfoList[index].field_4 = 0; - _partyMemberLevelUpInfoList[index].field_8 = 0; + _partyMemberLevelUpInfoList[index].level = 0; + _partyMemberLevelUpInfoList[index].numLevelUps = 0; + _partyMemberLevelUpInfoList[index].isEarly = 0; } } @@ -285,9 +285,9 @@ void partyMembersReset() void partyMembersExit() { for (int index = 0; index < gPartyMemberDescriptionsLength; index++) { - _partyMemberLevelUpInfoList[index].field_0 = 0; - _partyMemberLevelUpInfoList[index].field_4 = 0; - _partyMemberLevelUpInfoList[index].field_8 = 0; + _partyMemberLevelUpInfoList[index].level = 0; + _partyMemberLevelUpInfoList[index].numLevelUps = 0; + _partyMemberLevelUpInfoList[index].isEarly = 0; } gPartyMemberDescriptionsLength = 0; @@ -364,9 +364,9 @@ static void partyMemberDescriptionInit(PartyMemberDescription* partyMemberDescri partyMemberDescription->level_pids[0] = -1; for (int index = 0; index < gPartyMemberDescriptionsLength; index++) { - _partyMemberLevelUpInfoList[index].field_0 = 0; - _partyMemberLevelUpInfoList[index].field_4 = 0; - _partyMemberLevelUpInfoList[index].field_8 = 0; + _partyMemberLevelUpInfoList[index].level = 0; + _partyMemberLevelUpInfoList[index].numLevelUps = 0; + _partyMemberLevelUpInfoList[index].isEarly = 0; } } @@ -403,7 +403,7 @@ int partyMemberAdd(Object* object) Script* script; if (scriptGetScript(object->sid, &script) != -1) { script->flags |= (SCRIPT_FLAG_0x08 | SCRIPT_FLAG_0x10); - script->field_1C = object->id; + script->ownerId = object->id; object->sid = ((object->pid & 0xFFFFFF) + 18000) | (object->sid & 0xFF000000); script->sid = object->sid; @@ -528,10 +528,10 @@ int partyMembersSave(File* stream) } for (int index = 1; index < gPartyMemberDescriptionsLength; index++) { - STRU_519DBC* ptr = &(_partyMemberLevelUpInfoList[index]); - if (fileWriteInt32(stream, ptr->field_0) == -1) return -1; - if (fileWriteInt32(stream, ptr->field_4) == -1) return -1; - if (fileWriteInt32(stream, ptr->field_8) == -1) return -1; + PartyMemberLevelUpInfo* ptr = &(_partyMemberLevelUpInfoList[index]); + if (fileWriteInt32(stream, ptr->level) == -1) return -1; + if (fileWriteInt32(stream, ptr->numLevelUps) == -1) return -1; + if (fileWriteInt32(stream, ptr->isEarly) == -1) return -1; } return 0; @@ -763,11 +763,11 @@ int partyMembersLoad(File* stream) partyFixMultipleMembers(); for (int index = 1; index < gPartyMemberDescriptionsLength; index++) { - STRU_519DBC* ptr_519DBC = &(_partyMemberLevelUpInfoList[index]); + PartyMemberLevelUpInfo* levelUpInfo = &(_partyMemberLevelUpInfoList[index]); - if (fileReadInt32(stream, &(ptr_519DBC->field_0)) == -1) return -1; - if (fileReadInt32(stream, &(ptr_519DBC->field_4)) == -1) return -1; - if (fileReadInt32(stream, &(ptr_519DBC->field_8)) == -1) return -1; + if (fileReadInt32(stream, &(levelUpInfo->level)) == -1) return -1; + if (fileReadInt32(stream, &(levelUpInfo->numLevelUps)) == -1) return -1; + if (fileReadInt32(stream, &(levelUpInfo->isEarly)) == -1) return -1; } return 0; @@ -1021,8 +1021,8 @@ static int _partyMemberItemSave(Object* object) } if (object->id < 20000) { - script->field_1C = _partyMemberNewObjID(); - object->id = script->field_1C; + script->ownerId = _partyMemberNewObjID(); + object->id = script->ownerId; } PartyMemberListItem* node = (PartyMemberListItem*)internal_malloc(sizeof(*node)); @@ -1454,25 +1454,25 @@ bool partyMemberSupportsChemUse(Object* object, int chemUse) int _partyMemberIncLevels() { int i; - PartyMemberListItem* ptr; + PartyMemberListItem* listItem; Object* obj; - PartyMemberDescription* party_member; + PartyMemberDescription* memberDescription; const char* name; int j; - int v0; - STRU_519DBC* ptr_519DBC; - int v24; + int memberIndex; + PartyMemberLevelUpInfo* levelUpInfo; + int levelMod; char* text; MessageListItem msg; char str[260]; - Rect v19; + Rect levelUpMessageRect; - v0 = -1; + memberIndex = -1; for (i = 1; i < gPartyMembersLength; i++) { - ptr = &(gPartyMembers[i]); - obj = ptr->object; + listItem = &(gPartyMembers[i]); + obj = listItem->object; - if (partyMemberGetDescription(obj, &party_member) == -1) { + if (partyMemberGetDescription(obj, &memberDescription) == -1) { // SFALL: NPC level fix. continue; } @@ -1484,67 +1484,75 @@ int _partyMemberIncLevels() name = critterGetName(obj); debugPrint("\npartyMemberIncLevels: %s", name); - if (party_member->level_up_every == 0) { + if (memberDescription->level_up_every == 0) { continue; } for (j = 1; j < gPartyMemberDescriptionsLength; j++) { if (gPartyMemberPids[j] == obj->pid) { - v0 = j; + memberIndex = j; } } - if (v0 == -1) { + if (memberIndex == -1) { continue; } - if (pcGetStat(PC_STAT_LEVEL) < party_member->level_minimum) { + if (pcGetStat(PC_STAT_LEVEL) < memberDescription->level_minimum) { continue; } - ptr_519DBC = &(_partyMemberLevelUpInfoList[v0]); + levelUpInfo = &(_partyMemberLevelUpInfoList[memberIndex]); - if (ptr_519DBC->field_0 >= party_member->level_pids_num) { + if (levelUpInfo->level >= memberDescription->level_pids_num) { continue; } - ptr_519DBC->field_4++; + levelUpInfo->numLevelUps++; - v24 = ptr_519DBC->field_4 % party_member->level_pids_num; - debugPrint("pm: levelMod: %d, Lvl: %d, Early: %d, Every: %d", v24, ptr_519DBC->field_4, ptr_519DBC->field_8, party_member->level_up_every); + levelMod = levelUpInfo->numLevelUps % memberDescription->level_up_every; + debugPrint("pm: levelMod: %d, Lvl: %d, Early: %d, Every: %d", levelMod, levelUpInfo->numLevelUps, levelUpInfo->isEarly, memberDescription->level_up_every); - if (v24 != 0 || ptr_519DBC->field_8 == 0) { - if (ptr_519DBC->field_8 == 0) { - if (v24 == 0 || randomBetween(0, 100) <= 100 * v24 / party_member->level_up_every) { - ptr_519DBC->field_0++; - if (v24 != 0) { - ptr_519DBC->field_8 = 1; - } + // Party member level up with a probability that depends on how "far" we are in the current "level_up_every" progression. + // For example, if level_up_every is 5 and NPC observed 7 level ups with the player, 5 % 7 = 2, 2 * 100 / 5 = 40 (40% probability). + // If levelMod is 0 (so we got 5, 10, etc. levels in the example above), probability is 100% (no roll). + // If previous level up occured "early" (due to probability roll), then we skip until we get to levelMod = 0, to begin the next cycle. - if (_partyMemberCopyLevelInfo(obj, party_member->level_pids[ptr_519DBC->field_0]) == -1) { - return -1; - } - - name = critterGetName(obj); - // %s has gained in some abilities. - text = getmsg(&gMiscMessageList, &msg, 9000); - snprintf(str, sizeof(str), text, name); - displayMonitorAddMessage(str); - - debugPrint(str); - - // Individual message - msg.num = 9000 + 10 * v0 + ptr_519DBC->field_0 - 1; - if (messageListGetItem(&gMiscMessageList, &msg)) { - name = critterGetName(obj); - snprintf(str, sizeof(str), msg.text, name); - textObjectAdd(obj, str, 101, _colorTable[0x7FFF], _colorTable[0], &v19); - tileWindowRefreshRect(&v19, obj->elevation); - } - } + if (levelUpInfo->isEarly != 0) { + if (levelMod == 0) { + levelUpInfo->isEarly = 0; } - } else { - ptr_519DBC->field_8 = 0; + continue; + } + + if (levelMod != 0 && randomBetween(0, 100) > 100 * levelMod / memberDescription->level_up_every) { + continue; + } + + levelUpInfo->level++; + if (levelMod != 0) { + levelUpInfo->isEarly = 1; + } + + if (_partyMemberCopyLevelInfo(obj, memberDescription->level_pids[levelUpInfo->level]) == -1) { + return -1; + } + + name = critterGetName(obj); + // %s has gained in some abilities. + text = getmsg(&gMiscMessageList, &msg, 9000); + snprintf(str, sizeof(str), text, name); + displayMonitorAddMessage(str); + + debugPrint(str); + + // Individual message + msg.num = 9000 + 10 * memberIndex + levelUpInfo->level - 1; + if (messageListGetItem(&gMiscMessageList, &msg)) { + name = critterGetName(obj); + snprintf(str, sizeof(str), msg.text, name); + textObjectAdd(obj, str, 101, _colorTable[0x7FFF], _colorTable[0], &levelUpMessageRect); + tileWindowRefreshRect(&levelUpMessageRect, obj->elevation); } } @@ -1552,23 +1560,23 @@ int _partyMemberIncLevels() } // 0x495EA8 -static int _partyMemberCopyLevelInfo(Object* critter, int a2) +static int _partyMemberCopyLevelInfo(Object* critter, int stagePid) { if (critter == nullptr) { return -1; } - if (a2 == -1) { + if (stagePid == -1) { return -1; } - Proto* proto1; - if (protoGetProto(critter->pid, &proto1) == -1) { + Proto* proto; + if (protoGetProto(critter->pid, &proto) == -1) { return -1; } - Proto* proto2; - if (protoGetProto(a2, &proto2) == -1) { + Proto* stageProto; + if (protoGetProto(stagePid, &stageProto) == -1) { return -1; } @@ -1583,15 +1591,15 @@ static int _partyMemberCopyLevelInfo(Object* critter, int a2) critterAdjustHitPoints(critter, maxHp); for (int stat = 0; stat < SPECIAL_STAT_COUNT; stat++) { - proto1->critter.data.baseStats[stat] = proto2->critter.data.baseStats[stat]; + proto->critter.data.baseStats[stat] = stageProto->critter.data.baseStats[stat]; } for (int stat = 0; stat < SPECIAL_STAT_COUNT; stat++) { - proto1->critter.data.bonusStats[stat] = proto2->critter.data.bonusStats[stat]; + proto->critter.data.bonusStats[stat] = stageProto->critter.data.bonusStats[stat]; } for (int skill = 0; skill < SKILL_COUNT; skill++) { - proto1->critter.data.skills[skill] = proto2->critter.data.skills[skill]; + proto->critter.data.skills[skill] = stageProto->critter.data.skills[skill]; } critter->data.critter.hp = critterGetStat(critter, STAT_MAXIMUM_HIT_POINTS); @@ -1604,7 +1612,7 @@ static int _partyMemberCopyLevelInfo(Object* critter, int a2) if (item2 != nullptr) { // SFALL: Fix for party member's equipped weapon being placed in the // incorrect item slot after leveling up. - _invenWieldFunc(critter, item2, 1, false); + _invenWieldFunc(critter, item2, HAND_RIGHT, false); } return 0; diff --git a/src/perk.cc b/src/perk.cc index 88be41a..80d53a5 100644 --- a/src/perk.cc +++ b/src/perk.cc @@ -14,19 +14,33 @@ namespace fallout { +enum PerkParamMode { + PERK_PARAM_MODE_FIRST_ONLY, + PERK_PARAM_MODE_OR, + PERK_PARAM_MODE_AND, +}; + typedef struct PerkDescription { char* name; char* description; int frmId; int maxRank; int minLevel; + // Critter stat to modify for every perk rank. int stat; + // Stat modifier for every perk rank. int statModifier; + // Skill number, normally. If bit 0x4000000 is set, will be treated as global var number instead. int param1; + // Required value of a skill or global var. int value1; - int field_24; + // Specifies wether to require both params, either one or just use the first one. + int paramMode; + // Skill or gvar number, see param1. int param2; + // Required value of a skill or global var. int value2; + // Required minimum value for every primary stat. int stats[PRIMARY_STAT_COUNT]; } PerkDescription; @@ -308,7 +322,7 @@ static bool perkCanAdd(Object* critter, int perk) } } - bool v1 = true; + bool req1Fulfilled = true; int param1 = perkDescription->param1; if (param1 != -1) { @@ -322,32 +336,32 @@ static bool perkCanAdd(Object* critter, int perk) if (value1 < 0) { if (isVariable) { if (gameGetGlobalVar(param1) >= value1) { - v1 = false; + req1Fulfilled = false; } } else { if (skillGetValue(critter, param1) >= -value1) { - v1 = false; + req1Fulfilled = false; } } } else { if (isVariable) { if (gameGetGlobalVar(param1) < value1) { - v1 = false; + req1Fulfilled = false; } } else { if (skillGetValue(critter, param1) < value1) { - v1 = false; + req1Fulfilled = false; } } } } - if (!v1 || perkDescription->field_24 == 2) { - if (perkDescription->field_24 == 0) { + if (!req1Fulfilled || perkDescription->paramMode == PERK_PARAM_MODE_AND) { + if (perkDescription->paramMode == PERK_PARAM_MODE_FIRST_ONLY) { return false; } - if (!v1 && perkDescription->field_24 == 2) { + if (!req1Fulfilled && perkDescription->paramMode == PERK_PARAM_MODE_AND) { return false; } diff --git a/src/pipboy.cc b/src/pipboy.cc index 62b5b0c..e847404 100644 --- a/src/pipboy.cc +++ b/src/pipboy.cc @@ -211,13 +211,13 @@ static int _PrintAMelevList(int a1); static int _PrintAMList(int a1); static void pipboyHandleVideoArchive(int a1); static int pipboyRenderVideoArchive(int a1); -static void pipboyHandleAlarmClock(int a1); +static void pipboyHandleAlarmClock(int eventCode); static void pipboyWindowRenderRestOptions(int a1); static void pipboyDrawHitPoints(); static void pipboyWindowCreateButtons(int a1, int a2, bool a3); static void pipboyWindowDestroyButtons(); static bool pipboyRest(int hours, int minutes, int kind); -static bool _Check4Health(int a1); +static bool _Check4Health(int minutes); static bool _AddHealth(); static void _ClacTime(int* hours, int* minutes, int wakeUpHour); static int pipboyRenderScreensaver(); @@ -1751,9 +1751,9 @@ static int pipboyRenderVideoArchive(int a1) } // 0x499518 -static void pipboyHandleAlarmClock(int a1) +static void pipboyHandleAlarmClock(int eventCode) { - if (a1 == 1024) { + if (eventCode == 1024) { if (_critter_can_obj_dude_rest()) { pipboyWindowDestroyButtons(); pipboyWindowRenderRestOptions(0); @@ -1769,15 +1769,14 @@ static void pipboyHandleAlarmClock(int a1) // appropriate handler (not the alarm clock). gPipboyTab = gPipboyPrevTab; } - } else if (a1 >= 4 && a1 <= 17) { + } else if (eventCode >= 4 && eventCode <= 17) { soundPlayFile("ib1p1xx1"); - pipboyWindowRenderRestOptions(a1 - 3); + pipboyWindowRenderRestOptions(eventCode - 3); - int duration = a1 - 4; + int duration = eventCode - 4; int minutes = 0; int hours = 0; - int v10 = 0; switch (duration) { case PIPBOY_REST_DURATION_TEN_MINUTES: @@ -2160,9 +2159,9 @@ static bool pipboyRest(int hours, int minutes, int duration) } // 0x499FCC -static bool _Check4Health(int a1) +static bool _Check4Health(int minutes) { - _rest_time += a1; + _rest_time += minutes; if (_rest_time < 180) { return false; diff --git a/src/proto_instance.cc b/src/proto_instance.cc index 9aecded..02bb39d 100644 --- a/src/proto_instance.cc +++ b/src/proto_instance.cc @@ -35,27 +35,29 @@ namespace fallout { static int _obj_remove_from_inven(Object* critter, Object* item); -static int _obj_use_book(Object* item_obj); -static int _obj_use_flare(Object* critter_obj, Object* item_obj); -static int _obj_use_radio(Object* item_obj); +static int _obj_use_book(Object* item); +static int _obj_use_flare(Object* critter, Object* item); +static int _obj_use_radio(Object* item); static int _obj_use_explosive(Object* explosive); static int _obj_use_power_on_car(Object* ammo); -static int _obj_use_misc_item(Object* item_obj); -static int _protinstTestDroppedExplosive(Object* a1); -static int _protinst_default_use_item(Object* a1, Object* a2, Object* item); -static int useLadderDown(Object* a1, Object* ladder, int a3); -static int useLadderUp(Object* a1, Object* ladder, int a3); -static int useStairs(Object* a1, Object* stairs, int a3); -static int _set_door_state_open(Object* a1, Object* a2); -static int _set_door_state_closed(Object* a1, Object* a2); -static int _check_door_state(Object* a1, Object* a2); +static int _obj_use_misc_item(Object* item); +static int _protinstTestDroppedExplosive(Object* explosiveItem); +static int _protinst_default_use_item(Object* user, Object* targetObj, Object* item); +static int useLadderDown(Object* user, Object* ladder); +static int useLadderUp(Object* user, Object* ladder); +static int useStairs(Object* user, Object* stairs); +static int _set_door_state_open(Object* door, Object* obj2); +static int _set_door_state_closed(Object* door, Object* obj2); +static int _check_door_state(Object* door, Object* obj2); static bool _obj_is_portal(Object* obj); static bool _obj_is_lockable(Object* obj); static bool _obj_is_openable(Object* obj); static int objectOpenClose(Object* obj); static bool objectIsJammed(Object* obj); -// 0x49A990 +// Accessed but not really used +// +// 0x49A990 static MessageListItem stru_49A990; // 0x49A9A0 @@ -105,10 +107,10 @@ int _obj_new_sid(Object* object, int* sidPtr) return -1; } - script->field_14 = sid & 0xFFFFFF; + script->index = sid & 0xFFFFFF; if (objectType == OBJ_TYPE_CRITTER) { - object->field_80 = script->field_14; + object->scriptIndex = script->index; } if (scriptType == SCRIPT_TYPE_SPATIAL) { @@ -120,7 +122,7 @@ int _obj_new_sid(Object* object, int* sidPtr) object->id = scriptsNewObjectId(); } - script->field_1C = object->id; + script->ownerId = object->id; script->owner = object; _scr_find_str_run_info(sid & 0xFFFFFF, &(script->field_50), *sidPtr); @@ -129,9 +131,9 @@ int _obj_new_sid(Object* object, int* sidPtr) } // 0x49AAC0 -int _obj_new_sid_inst(Object* obj, int scriptType, int a3) +int _obj_new_sid_inst(Object* obj, int scriptType, int scriptIndex) { - if (a3 == -1) { + if (scriptIndex == -1) { return -1; } @@ -145,7 +147,7 @@ int _obj_new_sid_inst(Object* obj, int scriptType, int a3) return -1; } - script->field_14 = a3; + script->index = scriptIndex; if (scriptType == SCRIPT_TYPE_SPATIAL) { script->sp.built_tile = builtTileCreate(obj->tile, obj->elevation); script->sp.radius = 3; @@ -154,14 +156,14 @@ int _obj_new_sid_inst(Object* obj, int scriptType, int a3) obj->sid = sid; obj->id = scriptsNewObjectId(); - script->field_1C = obj->id; + script->ownerId = obj->id; script->owner = obj; - _scr_find_str_run_info(a3 & 0xFFFFFF, &(script->field_50), sid); + _scr_find_str_run_info(scriptIndex & 0xFFFFFF, &(script->field_50), sid); if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) { - obj->field_80 = script->field_14; + obj->scriptIndex = script->index; } return 0; @@ -810,7 +812,7 @@ static int _obj_use_book(Object* book) // Light a flare. // // 0x49BBA8 -static int _obj_use_flare(Object* critter_obj, Object* flare) +static int _obj_use_flare(Object* critter, Object* flare) { MessageListItem messageListItem; @@ -819,7 +821,7 @@ static int _obj_use_flare(Object* critter_obj, Object* flare) } if ((flare->flags & OBJECT_QUEUED) != 0) { - if (critter_obj == gDude) { + if (critter == gDude) { // The flare is already lit. messageListItem.num = 588; if (messageListGetItem(&gProtoMessageList, &messageListItem)) { @@ -827,7 +829,7 @@ static int _obj_use_flare(Object* critter_obj, Object* flare) } } } else { - if (critter_obj == gDude) { + if (critter == gDude) { // You light the flare. messageListItem.num = 588; if (messageListGetItem(&gProtoMessageList, &messageListItem)) { @@ -1072,10 +1074,10 @@ int _protinst_use_item(Object* critter, Object* item) } // 0x49BFE8 -static int _protinstTestDroppedExplosive(Object* a1) +static int _protinstTestDroppedExplosive(Object* explosiveItem) { // SFALL - if (explosiveIsActiveExplosive(a1->pid)) { + if (explosiveIsActiveExplosive(explosiveItem->pid)) { Attack attack; attackInit(&attack, gDude, nullptr, HIT_MODE_PUNCH, HIT_LOCATION_TORSO); attack.attackerFlags = DAM_HIT; @@ -1157,7 +1159,7 @@ int _obj_use_item(Object* a1, Object* a2) } // 0x49C240 -static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) +static int _protinst_default_use_item(Object* user, Object* targetObj, Object* item) { char formattedText[90]; MessageListItem messageListItem; @@ -1165,8 +1167,8 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) int rc; switch (itemGetType(item)) { case ITEM_TYPE_DRUG: - if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) { - if (a1 == gDude) { + if (PID_TYPE(targetObj->pid) != OBJ_TYPE_CRITTER) { + if (user == gDude) { // That does nothing messageListItem.num = 582; if (messageListGetItem(&gProtoMessageList, &messageListItem)) { @@ -1176,7 +1178,7 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) return -1; } - if (critterIsDead(a2)) { + if (critterIsDead(targetObj)) { // 583: To your dismay, you realize that it is already dead. // 584: As you reach down, you realize that it is already dead. // 585: Alas, you are too late. @@ -1188,24 +1190,24 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) return -1; } - rc = _item_d_take_drug(a2, item); + rc = _item_d_take_drug(targetObj, item); - if (a1 == gDude && a2 != gDude) { + if (user == gDude && targetObj != gDude) { // TODO: Looks like there is bug in this branch, message 580 will never be shown, // as we can only be here when target is not dude. // 580: You use the %s. // 581: You use the %s on %s. - messageListItem.num = 580 + (a2 != gDude); + messageListItem.num = 580 + (targetObj != gDude); if (!messageListGetItem(&gProtoMessageList, &messageListItem)) { return -1; } - snprintf(formattedText, sizeof(formattedText), messageListItem.text, objectGetName(item), objectGetName(a2)); + snprintf(formattedText, sizeof(formattedText), messageListItem.text, objectGetName(item), objectGetName(targetObj)); displayMonitorAddMessage(formattedText); } - if (a2 == gDude) { + if (targetObj == gDude) { interfaceRenderHitPoints(true); } @@ -1213,7 +1215,7 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) case ITEM_TYPE_AMMO: // SFALL: Fix for being able to charge the car by using cells on other // scenery/critters. - if (a2->pid == PROTO_ID_CAR || a2->pid == PROTO_ID_CAR_TRUNK) { + if (targetObj->pid == PROTO_ID_CAR || targetObj->pid == PROTO_ID_CAR_TRUNK) { rc = _obj_use_power_on_car(item); if (rc == 1) { return 1; @@ -1224,7 +1226,7 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) break; case ITEM_TYPE_WEAPON: case ITEM_TYPE_MISC: - rc = _obj_use_flare(a1, item); + rc = _obj_use_flare(user, item); if (rc == 0) { return 0; } @@ -1240,7 +1242,7 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item) } // 0x49C3CC -int _protinst_use_item_on(Object* a1, Object* a2, Object* item) +int _protinst_use_item_on(Object* critter, Object* targetObj, Object* item) { int messageId = -1; int criticalChanceModifier = 0; @@ -1277,55 +1279,55 @@ int _protinst_use_item_on(Object* a1, Object* a2, Object* item) Script* script; if (item->sid == -1) { - if (a2->sid == -1) { - return _protinst_default_use_item(a1, a2, item); + if (targetObj->sid == -1) { + return _protinst_default_use_item(critter, targetObj, item); } - scriptSetObjects(a2->sid, a1, item); - scriptExecProc(a2->sid, SCRIPT_PROC_USE_OBJ_ON); + scriptSetObjects(targetObj->sid, critter, item); + scriptExecProc(targetObj->sid, SCRIPT_PROC_USE_OBJ_ON); - if (scriptGetScript(a2->sid, &script) == -1) { + if (scriptGetScript(targetObj->sid, &script) == -1) { return -1; } if (!script->scriptOverrides) { - return _protinst_default_use_item(a1, a2, item); + return _protinst_default_use_item(critter, targetObj, item); } } else { - scriptSetObjects(item->sid, a1, a2); + scriptSetObjects(item->sid, critter, targetObj); scriptExecProc(item->sid, SCRIPT_PROC_USE_OBJ_ON); if (scriptGetScript(item->sid, &script) == -1) { return -1; } - if (script->field_28 == 0) { - if (a2->sid == -1) { - return _protinst_default_use_item(a1, a2, item); + if (script->returnValue == 0) { + if (targetObj->sid == -1) { + return _protinst_default_use_item(critter, targetObj, item); } - scriptSetObjects(a2->sid, a1, item); - scriptExecProc(a2->sid, SCRIPT_PROC_USE_OBJ_ON); + scriptSetObjects(targetObj->sid, critter, item); + scriptExecProc(targetObj->sid, SCRIPT_PROC_USE_OBJ_ON); Script* script; - if (scriptGetScript(a2->sid, &script) == -1) { + if (scriptGetScript(targetObj->sid, &script) == -1) { return -1; } if (!script->scriptOverrides) { - return _protinst_default_use_item(a1, a2, item); + return _protinst_default_use_item(critter, targetObj, item); } } } - return script->field_28; + return script->returnValue; } if (isInCombat()) { MessageListItem messageListItem; // You cannot do that in combat. messageListItem.num = 902; - if (a1 == gDude) { + if (critter == gDude) { if (messageListGetItem(&gProtoMessageList, &messageListItem)) { displayMonitorAddMessage(messageListItem.text); } @@ -1333,7 +1335,7 @@ int _protinst_use_item_on(Object* a1, Object* a2, Object* item) return -1; } - if (skillUse(a1, a2, skill, criticalChanceModifier) != 0) { + if (skillUse(critter, targetObj, skill, criticalChanceModifier) != 0) { return 0; } @@ -1343,7 +1345,7 @@ int _protinst_use_item_on(Object* a1, Object* a2, Object* item) MessageListItem messageListItem; messageListItem.num = messageId; - if (a1 == gDude) { + if (critter == gDude) { if (messageListGetItem(&gProtoMessageList, &messageListItem)) { displayMonitorAddMessage(messageListItem.text); } @@ -1353,21 +1355,21 @@ int _protinst_use_item_on(Object* a1, Object* a2, Object* item) } // 0x49C5FC -int _obj_use_item_on(Object* a1, Object* a2, Object* a3) +int _obj_use_item_on(Object* user, Object* targetObj, Object* item) { - int rc = _protinst_use_item_on(a1, a2, a3); + int rc = _protinst_use_item_on(user, targetObj, item); if (rc == 1) { - if (a1 != nullptr) { - int flags = a3->flags & OBJECT_IN_ANY_HAND; - itemRemove(a1, a3, 1); + if (user != nullptr) { + int flags = item->flags & OBJECT_IN_ANY_HAND; + itemRemove(user, item, 1); - Object* replacedItem = itemReplace(a1, a3, flags); + Object* replacedItem = itemReplace(user, item, flags); // CE: Fix rare crash when using uninitialized action variables. The // following code is on par with |_obj_use_item| which does not // crash. - if (a1 == gDude) { + if (user == gDude) { int leftItemAction; int rightItemAction; interfaceGetItemActions(&leftItemAction, &rightItemAction); @@ -1387,7 +1389,7 @@ int _obj_use_item_on(Object* a1, Object* a2, Object* a3) } } - _obj_destroy(a3); + _obj_destroy(item); rc = 0; } @@ -1429,10 +1431,10 @@ int _check_scenery_ap_cost(Object* obj, Object* a2) } // 0x49C740 -int _obj_use(Object* a1, Object* a2) +int _obj_use(Object* user, Object* targetObj) { - int type = FID_TYPE(a2->fid); - if (a1 == gDude) { + int type = FID_TYPE(targetObj->fid); + if (user == gDude) { if (type != OBJ_TYPE_SCENERY) { return -1; } @@ -1443,22 +1445,22 @@ int _obj_use(Object* a1, Object* a2) } Proto* sceneryProto; - if (protoGetProto(a2->pid, &sceneryProto) == -1) { + if (protoGetProto(targetObj->pid, &sceneryProto) == -1) { return -1; } - if (PID_TYPE(a2->pid) == OBJ_TYPE_SCENERY && sceneryProto->scenery.type == SCENERY_TYPE_DOOR) { - return _obj_use_door(a1, a2, 0); + if (PID_TYPE(targetObj->pid) == OBJ_TYPE_SCENERY && sceneryProto->scenery.type == SCENERY_TYPE_DOOR) { + return _obj_use_door(user, targetObj); } bool scriptOverrides = false; - if (a2->sid != -1) { - scriptSetObjects(a2->sid, a1, a2); - scriptExecProc(a2->sid, SCRIPT_PROC_USE); + if (targetObj->sid != -1) { + scriptSetObjects(targetObj->sid, user, targetObj); + scriptExecProc(targetObj->sid, SCRIPT_PROC_USE); Script* script; - if (scriptGetScript(a2->sid, &script) == -1) { + if (scriptGetScript(targetObj->sid, &script) == -1) { return -1; } @@ -1466,17 +1468,17 @@ int _obj_use(Object* a1, Object* a2) } if (!scriptOverrides) { - if (PID_TYPE(a2->pid) == OBJ_TYPE_SCENERY) { + if (PID_TYPE(targetObj->pid) == OBJ_TYPE_SCENERY) { if (sceneryProto->scenery.type == SCENERY_TYPE_LADDER_DOWN) { - if (useLadderDown(a1, a2, 0) == 0) { + if (useLadderDown(user, targetObj) == 0) { scriptOverrides = true; } } else if (sceneryProto->scenery.type == SCENERY_TYPE_LADDER_UP) { - if (useLadderUp(a1, a2, 0) == 0) { + if (useLadderUp(user, targetObj) == 0) { scriptOverrides = true; } } else if (sceneryProto->scenery.type == SCENERY_TYPE_STAIRS) { - if (useStairs(a1, a2, 0) == 0) { + if (useStairs(user, targetObj) == 0) { scriptOverrides = true; } } @@ -1484,7 +1486,7 @@ int _obj_use(Object* a1, Object* a2) } if (!scriptOverrides) { - if (a1 == gDude) { + if (user == gDude) { // You see: %s MessageListItem messageListItem; messageListItem.num = 480; @@ -1493,7 +1495,7 @@ int _obj_use(Object* a1, Object* a2) } char formattedText[260]; - const char* name = objectGetName(a2); + const char* name = objectGetName(targetObj); snprintf(formattedText, sizeof(formattedText), messageListItem.text, name); displayMonitorAddMessage(formattedText); } @@ -1505,7 +1507,7 @@ int _obj_use(Object* a1, Object* a2) } // 0x49C900 -static int useLadderDown(Object* a1, Object* ladder, int a3) +static int useLadderDown(Object* user, Object* ladder) { int builtTile = ladder->data.scenery.ladder.destinationBuiltTile; if (builtTile == -1) { @@ -1528,7 +1530,7 @@ static int useLadderDown(Object* a1, Object* ladder, int a3) wmMapMarkMapEntranceState(transition.map, elevation, 1); } else { Rect updatedRect; - if (objectSetLocation(a1, tile, elevation, &updatedRect) == -1) { + if (objectSetLocation(user, tile, elevation, &updatedRect) == -1) { return -1; } @@ -1539,7 +1541,7 @@ static int useLadderDown(Object* a1, Object* ladder, int a3) } // 0x49C9A4 -static int useLadderUp(Object* a1, Object* ladder, int a3) +static int useLadderUp(Object* user, Object* ladder) { int builtTile = ladder->data.scenery.ladder.destinationBuiltTile; if (builtTile == -1) { @@ -1562,7 +1564,7 @@ static int useLadderUp(Object* a1, Object* ladder, int a3) wmMapMarkMapEntranceState(transition.map, elevation, 1); } else { Rect updatedRect; - if (objectSetLocation(a1, tile, elevation, &updatedRect) == -1) { + if (objectSetLocation(user, tile, elevation, &updatedRect) == -1) { return -1; } @@ -1573,7 +1575,7 @@ static int useLadderUp(Object* a1, Object* ladder, int a3) } // 0x49CA48 -static int useStairs(Object* a1, Object* stairs, int a3) +static int useStairs(Object* user, Object* stairs) { int builtTile = stairs->data.scenery.stairs.destinationBuiltTile; if (builtTile == -1) { @@ -1596,7 +1598,7 @@ static int useStairs(Object* a1, Object* stairs, int a3) wmMapMarkMapEntranceState(transition.map, elevation, 1); } else { Rect updatedRect; - if (objectSetLocation(a1, tile, elevation, &updatedRect) == -1) { + if (objectSetLocation(user, tile, elevation, &updatedRect) == -1) { return -1; } @@ -1607,37 +1609,37 @@ static int useStairs(Object* a1, Object* stairs, int a3) } // 0x49CAF4 -static int _set_door_state_open(Object* a1, Object* a2) +static int _set_door_state_open(Object* door, Object* obj2) { - a1->data.scenery.door.openFlags |= 0x01; + door->data.scenery.door.openFlags |= 0x01; return 0; } // 0x49CB04 -static int _set_door_state_closed(Object* a1, Object* a2) +static int _set_door_state_closed(Object* door, Object* obj2) { - a1->data.scenery.door.openFlags &= ~0x01; + door->data.scenery.door.openFlags &= ~0x01; return 0; } // 0x49CB14 -static int _check_door_state(Object* a1, Object* a2) +static int _check_door_state(Object* door, Object* obj2) { - if ((a1->data.scenery.door.openFlags & 0x01) == 0) { + if ((door->data.scenery.door.openFlags & 0x01) == 0) { // SFALL: Fix flags on non-door objects. - if (_obj_is_portal(a1)) { - a1->flags &= ~OBJECT_OPEN_DOOR; + if (_obj_is_portal(door)) { + door->flags &= ~OBJECT_OPEN_DOOR; } _obj_rebuild_all_light(); tileWindowRefresh(); - if (a1->frame == 0) { + if (door->frame == 0) { return 0; } CacheEntry* artHandle; - Art* art = artLock(a1->fid, &artHandle); + Art* art = artLock(door->fid, &artHandle); if (art == nullptr) { return -1; } @@ -1645,16 +1647,16 @@ static int _check_door_state(Object* a1, Object* a2) Rect dirty; Rect temp; - objectGetRect(a1, &dirty); + objectGetRect(door, &dirty); - for (int frame = a1->frame - 1; frame >= 0; frame--) { + for (int frame = door->frame - 1; frame >= 0; frame--) { int x; int y; - artGetFrameOffsets(art, frame, a1->rotation, &x, &y); - _obj_offset(a1, -x, -y, &temp); + artGetFrameOffsets(art, frame, door->rotation, &x, &y); + _obj_offset(door, -x, -y, &temp); } - objectSetFrame(a1, 0, &temp); + objectSetFrame(door, 0, &temp); rectUnion(&dirty, &temp, &dirty); tileWindowRefreshRect(&dirty, gElevation); @@ -1663,21 +1665,21 @@ static int _check_door_state(Object* a1, Object* a2) return 0; } else { // SFALL: Fix flags on non-door objects. - if (_obj_is_portal(a1)) { - a1->flags |= OBJECT_OPEN_DOOR; + if (_obj_is_portal(door)) { + door->flags |= OBJECT_OPEN_DOOR; } _obj_rebuild_all_light(); tileWindowRefresh(); CacheEntry* artHandle; - Art* art = artLock(a1->fid, &artHandle); + Art* art = artLock(door->fid, &artHandle); if (art == nullptr) { return -1; } int frameCount = artGetFrameCount(art); - if (a1->frame == frameCount - 1) { + if (door->frame == frameCount - 1) { artUnlock(artHandle); return 0; } @@ -1685,16 +1687,16 @@ static int _check_door_state(Object* a1, Object* a2) Rect dirty; Rect temp; - objectGetRect(a1, &dirty); + objectGetRect(door, &dirty); - for (int frame = a1->frame + 1; frame < frameCount; frame++) { + for (int frame = door->frame + 1; frame < frameCount; frame++) { int x; int y; - artGetFrameOffsets(art, frame, a1->rotation, &x, &y); - _obj_offset(a1, x, y, &temp); + artGetFrameOffsets(art, frame, door->rotation, &x, &y); + _obj_offset(door, x, y, &temp); } - objectSetFrame(a1, frameCount - 1, &temp); + objectSetFrame(door, frameCount - 1, &temp); rectUnion(&dirty, &temp, &dirty); tileWindowRefreshRect(&dirty, gElevation); @@ -1705,20 +1707,20 @@ static int _check_door_state(Object* a1, Object* a2) } // 0x49CCB8 -int _obj_use_door(Object* a1, Object* a2, int a3) +int _obj_use_door(Object* user, Object* door, bool animateOnly) { - if (objectIsLocked(a2)) { - const char* sfx = sfxBuildOpenName(a2, SCENERY_SOUND_EFFECT_LOCKED); + if (objectIsLocked(door)) { + const char* sfx = sfxBuildOpenName(door, SCENERY_SOUND_EFFECT_LOCKED); soundPlayFile(sfx); } bool scriptOverrides = false; - if (a2->sid != -1) { - scriptSetObjects(a2->sid, a1, a2); - scriptExecProc(a2->sid, SCRIPT_PROC_USE); + if (door->sid != -1) { + scriptSetObjects(door->sid, user, door); + scriptExecProc(door->sid, SCRIPT_PROC_USE); Script* script; - if (scriptGetScript(a2->sid, &script) == -1) { + if (scriptGetScript(door->sid, &script) == -1) { return -1; } @@ -1729,23 +1731,25 @@ int _obj_use_door(Object* a1, Object* a2, int a3) int start; int end; int step; - if (a2->frame != 0) { - if (_obj_blocking_at(nullptr, a2->tile, a2->elevation) != nullptr) { + if (door->frame != 0) { + if (_obj_blocking_at(nullptr, door->tile, door->elevation) != nullptr) { MessageListItem messageListItem; char* text = getmsg(&gProtoMessageList, &messageListItem, 597); displayMonitorAddMessage(text); return -1; } start = 1; - end = (a3 == 0) - 1; + // TODO: strange logic, check if correct + end = animateOnly ? -1 : 0; step = -1; } else { - if (a2->data.scenery.door.openFlags & 0x01) { + if (door->data.scenery.door.openFlags & 0x01) { return -1; } start = 0; - end = (a3 != 0) + 1; + // TODO: strange logic, check if correct + end = animateOnly ? 2 : 1; step = 1; } @@ -1753,27 +1757,27 @@ int _obj_use_door(Object* a1, Object* a2, int a3) for (int i = start; i != end; i += step) { if (i != 0) { - if (a3 == 0) { - animationRegisterCallback(a2, a2, (AnimationCallback*)_set_door_state_closed, -1); + if (!animateOnly) { + animationRegisterCallback(door, door, (AnimationCallback*)_set_door_state_closed, -1); } - const char* sfx = sfxBuildOpenName(a2, SCENERY_SOUND_EFFECT_CLOSED); - animationRegisterPlaySoundEffect(a2, sfx, -1); + const char* sfx = sfxBuildOpenName(door, SCENERY_SOUND_EFFECT_CLOSED); + animationRegisterPlaySoundEffect(door, sfx, -1); - animationRegisterAnimateReversed(a2, ANIM_STAND, 0); + animationRegisterAnimateReversed(door, ANIM_STAND, 0); } else { - if (a3 == 0) { - animationRegisterCallback(a2, a2, (AnimationCallback*)_set_door_state_open, -1); + if (!animateOnly) { + animationRegisterCallback(door, door, (AnimationCallback*)_set_door_state_open, -1); } - const char* sfx = sfxBuildOpenName(a2, SCENERY_SOUND_EFFECT_OPEN); - animationRegisterPlaySoundEffect(a2, sfx, -1); + const char* sfx = sfxBuildOpenName(door, SCENERY_SOUND_EFFECT_OPEN); + animationRegisterPlaySoundEffect(door, sfx, -1); - animationRegisterAnimate(a2, ANIM_STAND, 0); + animationRegisterAnimate(door, ANIM_STAND, 0); } } - animationRegisterCallbackForced(a2, a2, (AnimationCallback*)_check_door_state, -1); + animationRegisterCallbackForced(door, door, (AnimationCallback*)_check_door_state, -1); reg_anim_end(); } @@ -2177,37 +2181,40 @@ int objectUnjamAll() // critter_attempt_placement // 0x49D4D4 -int _obj_attempt_placement(Object* obj, int tile, int elevation, int a4) +int _obj_attempt_placement(Object* obj, int tile, int elevation, int radius) { + constexpr int maxDist = 7; + constexpr int maxAttempts = 100; + if (tile == -1) { return -1; } int newTile = tile; if (_obj_blocking_at(nullptr, tile, elevation) != nullptr) { - int v6 = a4; - if (a4 < 1) { - v6 = 1; - } - + // Find a suitable alternative tile where the dude can get to. + int dist = radius >= 1 ? radius : 1; int attempts = 0; - while (v6 < 7) { + while (dist < maxDist) { attempts++; - if (attempts >= 100) { + if (attempts >= maxAttempts) { break; } for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) { - newTile = tileGetTileInDirection(tile, rotation, v6); - if (_obj_blocking_at(nullptr, newTile, elevation) == nullptr && v6 > 1 && _make_path(gDude, gDude->tile, newTile, nullptr, 0) != 0) { + newTile = tileGetTileInDirection(tile, rotation, dist); + if (_obj_blocking_at(nullptr, newTile, elevation) == nullptr + && dist > 1 + && _make_path(gDude, gDude->tile, newTile, nullptr, 0) != 0) { break; } } - v6++; + dist++; } - if (a4 != 1 && v6 > a4 + 2) { + // If location is too far (or not found at all), find any free adjacent tile, regardless if it's reachable or not. + if (radius != 1 && dist > radius + 2) { for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) { int candidate = tileGetTileInDirection(tile, rotation, 1); if (_obj_blocking_at(nullptr, candidate, elevation) == nullptr) { diff --git a/src/proto_instance.h b/src/proto_instance.h index 8ef23b1..67c2a9f 100644 --- a/src/proto_instance.h +++ b/src/proto_instance.h @@ -17,11 +17,11 @@ int _obj_drop(Object* a1, Object* a2); int _obj_destroy(Object* obj); int _protinst_use_item(Object* a1, Object* a2); int _obj_use_item(Object* a1, Object* a2); -int _protinst_use_item_on(Object* a1, Object* a2, Object* item); -int _obj_use_item_on(Object* a1, Object* a2, Object* a3); +int _protinst_use_item_on(Object* critter, Object* targetObj, Object* item); +int _obj_use_item_on(Object* user, Object* targetObj, Object* item); int _check_scenery_ap_cost(Object* obj, Object* a2); -int _obj_use(Object* a1, Object* a2); -int _obj_use_door(Object* a1, Object* a2, int a3); +int _obj_use(Object* user, Object* targetObj); +int _obj_use_door(Object* user, Object* doorObj, bool animateOnly = false); int _obj_use_container(Object* critter, Object* item); int _obj_use_skill_on(Object* a1, Object* a2, int skill); bool objectIsLocked(Object* obj); @@ -33,7 +33,7 @@ int objectClose(Object* obj); int objectJamLock(Object* obj); int objectUnjamLock(Object* obj); int objectUnjamAll(); -int _obj_attempt_placement(Object* obj, int tile, int elevation, int a4); +int _obj_attempt_placement(Object* obj, int tile, int elevation, int radius); int _objPMAttemptPlacement(Object* obj, int tile, int elevation); } // namespace fallout diff --git a/src/scripts.cc b/src/scripts.cc index 5a459d7..573b3f5 100644 --- a/src/scripts.cc +++ b/src/scripts.cc @@ -603,7 +603,7 @@ Object* scriptGetSelf(Program* program) } object->id = scriptsNewObjectId(); - v1->field_1C = object->id; + v1->ownerId = object->id; v1->owner = object; for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) { @@ -924,7 +924,7 @@ int scriptsHandleRequests() } if ((gScriptsRequests & SCRIPT_REQUEST_ELEVATOR) != 0) { - int map = gMapHeader.field_34; + int map = gMapHeader.index; int elevation = gScriptsRequestedElevatorLevel; int tile = -1; @@ -933,7 +933,7 @@ int scriptsHandleRequests() if (elevatorSelectLevel(gScriptsRequestedElevatorType, &map, &elevation, &tile) != -1) { automapSaveCurrent(); - if (map == gMapHeader.field_34) { + if (map == gMapHeader.index) { if (elevation == gElevation) { reg_anim_clear(gDude); objectSetRotation(gDude, ROTATION_SE, nullptr); @@ -1034,14 +1034,14 @@ int scriptsHandleRequests() int _scripts_check_state_in_combat() { if ((gScriptsRequests & SCRIPT_REQUEST_ELEVATOR) != 0) { - int map = gMapHeader.field_34; + int map = gMapHeader.index; int elevation = gScriptsRequestedElevatorLevel; int tile = -1; if (elevatorSelectLevel(gScriptsRequestedElevatorType, &map, &elevation, &tile) != -1) { automapSaveCurrent(); - if (map == gMapHeader.field_34) { + if (map == gMapHeader.index) { if (elevation == gElevation) { reg_anim_clear(gDude); objectSetRotation(gDude, ROTATION_SE, nullptr); @@ -1276,7 +1276,7 @@ int scriptExecProc(int sid, int proc) clock(); char name[16]; - if (scriptsGetFileName(script->field_14 & 0xFFFFFF, name, sizeof(name)) == -1) { + if (scriptsGetFileName(script->index & 0xFFFFFF, name, sizeof(name)) == -1) { return -1; } @@ -1817,13 +1817,13 @@ static int scriptWrite(Script* scr, File* stream) } if (fileWriteInt32(stream, scr->flags) == -1) return -1; - if (fileWriteInt32(stream, scr->field_14) == -1) return -1; + if (fileWriteInt32(stream, scr->index) == -1) return -1; // NOTE: Original code writes `scr->program` pointer which is meaningless. if (fileWriteInt32(stream, 0) == -1) return -1; - if (fileWriteInt32(stream, scr->field_1C) == -1) return -1; + if (fileWriteInt32(stream, scr->ownerId) == -1) return -1; if (fileWriteInt32(stream, scr->localVarsOffset) == -1) return -1; if (fileWriteInt32(stream, scr->localVarsCount) == -1) return -1; - if (fileWriteInt32(stream, scr->field_28) == -1) return -1; + if (fileWriteInt32(stream, scr->returnValue) == -1) return -1; if (fileWriteInt32(stream, scr->action) == -1) return -1; if (fileWriteInt32(stream, scr->fixedParam) == -1) return -1; if (fileWriteInt32(stream, scr->actionBeingUsed) == -1) return -1; @@ -1971,12 +1971,12 @@ static int scriptRead(Script* scr, File* stream) } if (fileReadInt32(stream, &(scr->flags)) == -1) return -1; - if (fileReadInt32(stream, &(scr->field_14)) == -1) return -1; + if (fileReadInt32(stream, &(scr->index)) == -1) return -1; if (fileReadInt32(stream, &(prg)) == -1) return -1; - if (fileReadInt32(stream, &(scr->field_1C)) == -1) return -1; + if (fileReadInt32(stream, &(scr->ownerId)) == -1) return -1; if (fileReadInt32(stream, &(scr->localVarsOffset)) == -1) return -1; if (fileReadInt32(stream, &(scr->localVarsCount)) == -1) return -1; - if (fileReadInt32(stream, &(scr->field_28)) == -1) return -1; + if (fileReadInt32(stream, &(scr->returnValue)) == -1) return -1; if (fileReadInt32(stream, &(scr->action)) == -1) return -1; if (fileReadInt32(stream, &(scr->fixedParam)) == -1) return -1; if (fileReadInt32(stream, &(scr->actionBeingUsed)) == -1) return -1; @@ -2196,11 +2196,11 @@ int scriptAdd(int* sidPtr, int scriptType) scr->sp.built_tile = -1; scr->sp.radius = -1; scr->flags = 0; - scr->field_14 = -1; + scr->index = -1; scr->program = nullptr; scr->localVarsOffset = -1; scr->localVarsCount = 0; - scr->field_28 = 0; + scr->returnValue = 0; scr->action = 0; scr->fixedParam = 0; scr->owner = nullptr; @@ -2797,7 +2797,7 @@ int scriptGetLocalVar(int sid, int variable, ProgramValue& value) if (script->localVarsCount == 0) { // NOTE: Uninline. - _scr_find_str_run_info(script->field_14, &(script->field_50), sid); + _scr_find_str_run_info(script->index, &(script->field_50), sid); } if (script->localVarsCount > 0) { @@ -2825,7 +2825,7 @@ int scriptSetLocalVar(int sid, int variable, ProgramValue& value) if (script->localVarsCount == 0) { // NOTE: Uninline. - _scr_find_str_run_info(script->field_14, &(script->field_50), sid); + _scr_find_str_run_info(script->index, &(script->field_50), sid); } if (script->localVarsCount <= 0) { diff --git a/src/scripts.h b/src/scripts.h index ae2d696..f8437b0 100644 --- a/src/scripts.h +++ b/src/scripts.h @@ -102,12 +102,12 @@ typedef struct Script { int flags; // scr_script_idx - int field_14; + int index; Program* program; // scr_oid - int field_1C; + int ownerId; // scr_local_var_offset int localVarsOffset; @@ -115,8 +115,8 @@ typedef struct Script { // scr_num_local_vars int localVarsCount; - // return value? - int field_28; + // set by scr_return opcode + int returnValue; // Currently executed action. // diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 65ae23d..af0122d 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -292,7 +292,7 @@ static void op_abs(Program* program) static void op_get_script(Program* program) { Object* obj = static_cast(programStackPopPointer(program)); - programStackPushInteger(program, obj->field_80 + 1); + programStackPushInteger(program, obj->scriptIndex + 1); } // get_proto_data diff --git a/src/skill.h b/src/skill.h index cdaa31e..44d5b7b 100644 --- a/src/skill.h +++ b/src/skill.h @@ -29,7 +29,7 @@ int skillAddForce(Object* critter, int skill); int skillsGetCost(int a1); int skillSub(Object* critter, int skill); int skillSubForce(Object* critter, int skill); -int skillRoll(Object* critter, int skill, int a3, int* a4); +int skillRoll(Object* critter, int skill, int modifier, int* howMuch); char* skillGetName(int skill); char* skillGetDescription(int skill); char* skillGetAttributes(int skill); diff --git a/src/worldmap.cc b/src/worldmap.cc index 909d545..2929cc0 100644 --- a/src/worldmap.cc +++ b/src/worldmap.cc @@ -167,6 +167,11 @@ typedef enum EncounterConditionalOperator { ENCOUNTER_CONDITIONAL_OPERATOR_COUNT, } EncounterConditionalOperator; +typedef enum EncounterRatioMode { + ENCOUNTER_RATIO_MODE_USE_RATIO, + ENCOUNTER_RATIO_MODE_SINGLE, +} EncounterRatioMode; + typedef enum Daytime { DAY_PART_MORNING, DAY_PART_AFTERNOON, @@ -326,7 +331,7 @@ typedef struct EncounterItem { typedef struct EncounterEntry { char field_0[40]; int field_28; - int field_2C; + int ratioMode; int ratio; int pid; int flags; @@ -1689,7 +1694,7 @@ static int wmParseEncBaseSubTypeStr(EncounterEntry* encounterEntry, char** strin } if (strParseIntWithKey(&string, "ratio", &(encounterEntry->ratio), ":") == 0) { - encounterEntry->field_2C = 0; + encounterEntry->ratioMode = ENCOUNTER_RATIO_MODE_USE_RATIO; } if (strstr(string, "dead,") == string) { @@ -1739,7 +1744,7 @@ static int wmEncBaseTypeSlotInit(Encounter* encounter) static int wmEncBaseSubTypeSlotInit(EncounterEntry* encounterEntry) { encounterEntry->field_28 = -1; - encounterEntry->field_2C = 1; + encounterEntry->ratioMode = ENCOUNTER_RATIO_MODE_SINGLE; encounterEntry->ratio = 100; encounterEntry->pid = -1; encounterEntry->flags = 0; @@ -2822,13 +2827,13 @@ bool wmMapIdxIsSaveable(int mapIdx) // 0x4BFA64 bool wmMapIsSaveable() { - return (wmMapInfoList[gMapHeader.field_34].flags & MAP_SAVED) != 0; + return (wmMapInfoList[gMapHeader.index].flags & MAP_SAVED) != 0; } // 0x4BFA90 bool wmMapDeadBodiesAge() { - return (wmMapInfoList[gMapHeader.field_34].flags & MAP_DEAD_BODIES_AGE) != 0; + return (wmMapInfoList[gMapHeader.index].flags & MAP_DEAD_BODIES_AGE) != 0; } // 0x4BFABC @@ -2839,7 +2844,7 @@ bool wmMapCanRestHere(int elevation) // NOTE: I'm not sure why they're copied. memcpy(flags, _can_rest_here, sizeof(flags)); - MapInfo* map = &(wmMapInfoList[gMapHeader.field_34]); + MapInfo* map = &(wmMapInfoList[gMapHeader.index]); return (map->flags & flags[elevation]) != 0; } @@ -3791,11 +3796,11 @@ static int wmSetupCritterObjs(int encounterIndex, Object** critterPtr, int critt } int encounterEntryCritterCount; - switch (encounterEntry->field_2C) { - case 0: + switch (encounterEntry->ratioMode) { + case ENCOUNTER_RATIO_MODE_USE_RATIO: encounterEntryCritterCount = encounterEntry->ratio * critterCount / 100; break; - case 1: + case ENCOUNTER_RATIO_MODE_SINGLE: encounterEntryCritterCount = 1; break; default: @@ -3884,7 +3889,7 @@ static int wmSetupCritterObjs(int encounterIndex, Object** critterPtr, int critt _obj_disconnect(item, nullptr); if (encounterItem->isEquipped) { - if (_inven_wield(object, item, 1) == -1) { + if (_inven_wield(object, item, HAND_RIGHT) == -1) { debugPrint("\nERROR: wmSetupCritterObjs: Inven Wield Failed: %d on %s: Critter Fid: %d", item->pid, critterGetName(object), object->fid); } } @@ -3924,33 +3929,32 @@ static int wmSetupRndNextTileNumInit(Encounter* encounter) case ENCOUNTER_FORMATION_TYPE_DOUBLE_LINE: case ENCOUNTER_FORMATION_TYPE_WEDGE: case ENCOUNTER_FORMATION_TYPE_CONE: - case ENCOUNTER_FORMATION_TYPE_HUDDLE: - if (1) { - MapInfo* map = &(wmMapInfoList[gMapHeader.field_34]); - if (map->startPointsLength != 0) { - int rspIndex = randomBetween(0, map->startPointsLength - 1); - MapStartPointInfo* rsp = &(map->startPoints[rspIndex]); + case ENCOUNTER_FORMATION_TYPE_HUDDLE: { + MapInfo* map = &(wmMapInfoList[gMapHeader.index]); + if (map->startPointsLength != 0) { + int rspIndex = randomBetween(0, map->startPointsLength - 1); + MapStartPointInfo* rsp = &(map->startPoints[rspIndex]); - wmRndCenterTiles[0] = rsp->tile; - wmRndCenterTiles[1] = wmRndCenterTiles[0]; + wmRndCenterTiles[0] = rsp->tile; + wmRndCenterTiles[1] = wmRndCenterTiles[0]; - wmRndCenterRotations[0] = rsp->rotation; - wmRndCenterRotations[1] = wmRndCenterRotations[0]; - } else { - wmRndCenterRotations[0] = 0; - wmRndCenterRotations[1] = 0; + wmRndCenterRotations[0] = rsp->rotation; + wmRndCenterRotations[1] = wmRndCenterRotations[0]; + } else { + wmRndCenterRotations[0] = 0; + wmRndCenterRotations[1] = 0; - wmRndCenterTiles[0] = gDude->tile; - wmRndCenterTiles[1] = gDude->tile; - } - - wmRndTileDirs[0] = tileGetRotationTo(wmRndCenterTiles[0], gDude->tile); - wmRndTileDirs[1] = tileGetRotationTo(wmRndCenterTiles[1], gDude->tile); - - wmRndOriginalCenterTile = wmRndCenterTiles[0]; - - return 0; + wmRndCenterTiles[0] = gDude->tile; + wmRndCenterTiles[1] = gDude->tile; } + + wmRndTileDirs[0] = tileGetRotationTo(wmRndCenterTiles[0], gDude->tile); + wmRndTileDirs[1] = tileGetRotationTo(wmRndCenterTiles[1], gDude->tile); + + wmRndOriginalCenterTile = wmRndCenterTiles[0]; + + return 0; + } default: debugPrint("\nERROR: wmSetupCritterObjs: invalid Formation Type!"); @@ -3958,6 +3962,8 @@ static int wmSetupRndNextTileNumInit(Encounter* encounter) } } +// Determines tile to place the next object in the EncounterEntry at. +// // wmSetupRndNextTileNum // 0x4C16F0 static int wmSetupRndNextTileNum(Encounter* encounter, EncounterEntry* encounterEntry, int* tilePtr) @@ -3965,41 +3971,40 @@ static int wmSetupRndNextTileNum(Encounter* encounter, EncounterEntry* encounter int tile; int attempt = 0; - while (1) { + while (true) { switch (encounter->position) { - case ENCOUNTER_FORMATION_TYPE_SURROUNDING: - if (1) { - int distance; - if (encounterEntry->distance != 0) { - distance = encounterEntry->distance; - } else { - distance = randomBetween(-2, 2); + case ENCOUNTER_FORMATION_TYPE_SURROUNDING: { + int distance; + if (encounterEntry->distance != 0) { + distance = encounterEntry->distance; + } else { + distance = randomBetween(-2, 2); - distance += critterGetStat(gDude, STAT_PERCEPTION); + distance += critterGetStat(gDude, STAT_PERCEPTION); - if (perkHasRank(gDude, PERK_CAUTIOUS_NATURE)) { - distance += 3; - } + if (perkHasRank(gDude, PERK_CAUTIOUS_NATURE)) { + distance += 3; } - - if (distance < 0) { - distance = 0; - } - - int origin = encounterEntry->tile; - if (origin == -1) { - origin = tileGetTileInDirection(gDude->tile, wmRndTileDirs[0], distance); - } - - if (++wmRndTileDirs[0] >= ROTATION_COUNT) { - wmRndTileDirs[0] = 0; - } - - int randomizedDistance = randomBetween(0, distance / 2); - int randomizedRotation = randomBetween(0, ROTATION_COUNT - 1); - tile = tileGetTileInDirection(origin, (randomizedRotation + wmRndTileDirs[0]) % ROTATION_COUNT, randomizedDistance); } + + if (distance < 0) { + distance = 0; + } + + int origin = encounterEntry->tile; + if (origin == -1) { + origin = tileGetTileInDirection(gDude->tile, wmRndTileDirs[0], distance); + } + + if (++wmRndTileDirs[0] >= ROTATION_COUNT) { + wmRndTileDirs[0] = 0; + } + + int randomizedDistance = randomBetween(0, distance / 2); + int randomizedRotation = randomBetween(0, ROTATION_COUNT - 1); + tile = tileGetTileInDirection(origin, (randomizedRotation + wmRndTileDirs[0]) % ROTATION_COUNT, randomizedDistance); break; + } case ENCOUNTER_FORMATION_TYPE_STRAIGHT_LINE: tile = wmRndCenterTiles[wmRndIndex]; if (wmRndCallCount != 0) {