Compare commits

...
15 Commits
Author SHA1 Message Date
phobos2077 39b369f7df Fix build after last merge 2024-06-07 17:53:37 +02:00
phobos2077 76ac71bc08 Merge remote-tracking branch 'y0lo/feature/y0lo/fast-barter-auto-calc-change-money' into sfall-port
# Conflicts:
#	src/inventory.cc
2024-06-04 15:03:52 +02:00
phobos2077 323cc6165c Decyphering inventory.cc + a few other places 2024-06-02 14:11:26 +02:00
phobos2077 dfcf61b184 Misc decyphering 2024-05-31 13:23:45 +02:00
phobos2077 20d55423f7 Decypher Party level 2024-05-31 13:22:07 +02:00
phobos2077 8714d418ac Clang format fixes 2024-05-18 20:08:02 +02:00
phobos2077 6efbe795dc Decyphering in and around proto_instance + fix build 2024-05-18 20:02:03 +02:00
phobos2077 ebb6a6b9d8 Decyphering: perform_drug_effect, MapHeader, perk params
- Remove a few constant conditions in worldmap.cc
2024-05-18 19:07:24 +02:00
phobos2077 26c04ae803 obj_attempt_placement + WM encounter ratioMode naming 2024-05-16 23:30:58 +02:00
phobos2077 da72bc9501 Inventory symbol naming (WIP) 2024-05-16 23:29:46 +02:00
phobos2077 91a502d704 gdialog_scroll_subwin() readability 2024-05-08 23:01:40 +02:00
phobos2077 71f84cbe44 Decypher buildFid (art_id) function 2024-05-03 16:22:18 +02:00
Ivan Sokolov 0e31ac4753 Simplyfy logic to calc suggested amount of barter money 2023-06-22 00:38:18 +08:00
Ivan Sokolov a949178e30 Set recomended ammount of money to be moved for barter
The feature works in any direction to move from/to player/npc and from/to inventory/table
2023-06-21 21:13:06 +08:00
Ivan Sokolov 0e806d9be3 Add feature for automatic calculation of barter money 2023-06-20 17:21:10 +08:00
31 changed files with 1103 additions and 1038 deletions
+56 -56
View File
@@ -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();
}
+4 -4
View File
@@ -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();
+9 -8
View File
@@ -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;
}
}
+19 -36
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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;
}
+51 -50
View File
@@ -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;
+74 -74
View File
@@ -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);
}
}
-8
View File
@@ -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
+3 -3
View File
@@ -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);
};
+417 -378
View File
File diff suppressed because it is too large Load Diff
+25 -12
View File
@@ -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
+39 -38
View File
@@ -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?
}
}
+13 -13
View File
@@ -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,12 +1254,12 @@ int mapHandleTransition()
}
} else {
if (!isInCombat()) {
if (gMapTransition.map != gMapHeader.field_34 || gElevation == gMapTransition.elevation) {
if (gMapTransition.map != gMapHeader.index || gElevation == gMapTransition.elevation) {
mapLoadById(gMapTransition.map);
}
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);
@@ -1273,7 +1273,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!");
}
@@ -1745,7 +1745,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;
@@ -1765,7 +1765,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;
+1 -1
View File
@@ -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;
+5 -5
View File
@@ -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();
}
+1 -1
View File
@@ -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);
+3 -1
View File
@@ -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 {
+4 -4
View File
@@ -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;
@@ -533,7 +533,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;
}
}
@@ -655,7 +655,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;
@@ -3710,7 +3710,7 @@ static int objectAllocate(Object** objectPtr)
object->pid = -1;
object->sid = -1;
object->owner = nullptr;
object->field_80 = -1;
object->scriptIndex = -1;
return 0;
}

Some files were not shown because too many files have changed in this diff Show More