mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce19262283 | ||
|
|
e43762b45f | ||
|
|
ceb9c41e3d | ||
|
|
0aee36f77d | ||
|
|
9c41ddd243 | ||
|
|
f38d87e0ee | ||
|
|
5fa418ae08 | ||
|
|
c6c66a4b58 | ||
|
|
feeae8c750 | ||
|
|
58a67d58cb | ||
|
|
96881c19a3 | ||
|
|
c18828b61b | ||
|
|
b1e78bb61c | ||
|
|
bcb0228ed3 | ||
|
|
a75e634c96 | ||
|
|
c4f6c762c4 | ||
|
|
5ccd1534f4 | ||
|
|
8e0190939e | ||
|
|
0f7a8592a9 | ||
|
|
e9f3fd5039 | ||
|
|
6cc988aef5 | ||
|
|
e50369c18d | ||
|
|
f1ef55d22d | ||
|
|
d1fe920cf7 |
Generated
+3
-2
@@ -158,12 +158,13 @@
|
||||
//
|
||||
this.bCrittersLvar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.bCrittersLvar.Enabled = false;
|
||||
this.bCrittersLvar.Location = new System.Drawing.Point(119, 401);
|
||||
this.bCrittersLvar.Location = new System.Drawing.Point(118, 401);
|
||||
this.bCrittersLvar.Name = "bCrittersLvar";
|
||||
this.bCrittersLvar.Size = new System.Drawing.Size(99, 23);
|
||||
this.bCrittersLvar.Size = new System.Drawing.Size(100, 23);
|
||||
this.bCrittersLvar.TabIndex = 7;
|
||||
this.bCrittersLvar.Text = "Local variables";
|
||||
this.bCrittersLvar.UseVisualStyleBackColor = true;
|
||||
this.bCrittersLvar.Click += new System.EventHandler(this.bCrittersLvar_Click);
|
||||
//
|
||||
// DebugEditor
|
||||
//
|
||||
|
||||
+42
-1
@@ -38,7 +38,7 @@ namespace FalloutClient {
|
||||
|
||||
private static ByteConverter converter = new ByteConverter();
|
||||
|
||||
private enum Mode { Globals, MapVars, SGlobals, Arrays, Critters }
|
||||
private enum Mode { Globals, MapVars, SGlobals, Arrays, Critters, LocalVars }
|
||||
|
||||
private readonly EditorConnection connection;
|
||||
private Mode mode;
|
||||
@@ -47,6 +47,7 @@ namespace FalloutClient {
|
||||
private readonly Dictionary<uint, string> CritNames = new Dictionary<uint, string>();
|
||||
|
||||
private void Redraw() {
|
||||
bCrittersLvar.Enabled = false;
|
||||
bEdit.Enabled = false;
|
||||
Column2.ReadOnly = false;
|
||||
Column3.ReadOnly = false;
|
||||
@@ -96,6 +97,7 @@ namespace FalloutClient {
|
||||
Column2.HeaderText = "PID";
|
||||
Column3.HeaderText = "Pointer";
|
||||
bEdit.Enabled = true;
|
||||
bCrittersLvar.Enabled = true;
|
||||
for (int i = 0; i < connection.Critters.Length / 2; i++) {
|
||||
uint modcrit = (connection.Critters[i, 0] & 0xfffff);
|
||||
string name = CritNames.ContainsKey(modcrit) ? CritNames[modcrit] : "";
|
||||
@@ -333,6 +335,45 @@ namespace FalloutClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void bCrittersLvar_Click(object sender, EventArgs e) {
|
||||
if (dataGridView1.SelectedRows.Count == 0) return;
|
||||
int i = (int)dataGridView1.SelectedRows[0].Tag;
|
||||
|
||||
connection.WriteDataType(DataTypeSend.RetrieveCritter);
|
||||
connection.WriteInt(i);
|
||||
BinaryReader br = new BinaryReader(new System.IO.MemoryStream(connection.ReadBytes(33 * 4)));
|
||||
br.BaseStream.Position = 30 * 4;
|
||||
int sid = br.ReadInt32();
|
||||
br.Close();
|
||||
if (sid != -1) {
|
||||
connection.WriteDataType(DataTypeSend.GetLocal);
|
||||
connection.WriteInt(sid);
|
||||
int totalVar = connection.ReadInt();
|
||||
string[] values = new string[totalVar];
|
||||
if (totalVar > 0) {
|
||||
br = new BinaryReader(new System.IO.MemoryStream(connection.ReadBytes(totalVar * 4)));
|
||||
for (int j = 0; j < totalVar; j++) {
|
||||
values[j] = br.ReadInt32().ToString();
|
||||
}
|
||||
br.Close();
|
||||
}
|
||||
values = EditorWindow.ShowEditor(this, values);
|
||||
if (values != null) {
|
||||
int countVar = values.Length;
|
||||
MemoryStream ms = new MemoryStream(countVar * 4);
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
for (int j = 0; j < countVar; j++) bw.Write(int.Parse(values[j]));
|
||||
connection.WriteDataType(DataTypeSend.SetLocal);
|
||||
connection.WriteInt(sid);
|
||||
connection.WriteInt(countVar);
|
||||
connection.WriteBytes(ms.GetBuffer(), 0, countVar * 4);
|
||||
bw.Close();
|
||||
}
|
||||
} else {
|
||||
MessageBox.Show("This critter has no script attached.");
|
||||
}
|
||||
}
|
||||
|
||||
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e) {
|
||||
bEdit.PerformClick();
|
||||
}
|
||||
|
||||
Generated
+16
@@ -29,6 +29,7 @@
|
||||
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Column3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.checkBox = new System.Windows.Forms.CheckBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
@@ -100,11 +101,24 @@
|
||||
this.Column3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.Column3.Width = 150;
|
||||
//
|
||||
// checkBox
|
||||
//
|
||||
this.checkBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.checkBox.AutoSize = true;
|
||||
this.checkBox.Location = new System.Drawing.Point(103, 341);
|
||||
this.checkBox.Name = "checkBox";
|
||||
this.checkBox.Size = new System.Drawing.Size(91, 17);
|
||||
this.checkBox.TabIndex = 3;
|
||||
this.checkBox.Text = "Values in Hex";
|
||||
this.checkBox.UseVisualStyleBackColor = true;
|
||||
this.checkBox.Click += new System.EventHandler(this.checkBox_Click);
|
||||
//
|
||||
// EditorWindow
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(458, 371);
|
||||
this.Controls.Add(this.checkBox);
|
||||
this.Controls.Add(this.dataGridView1);
|
||||
this.Controls.Add(this.bCancel);
|
||||
this.Controls.Add(this.bSave);
|
||||
@@ -115,6 +129,7 @@
|
||||
this.Text = "Edit Values";
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
@@ -126,5 +141,6 @@
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Column3;
|
||||
private System.Windows.Forms.CheckBox checkBox;
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,34 @@ namespace FalloutClient {
|
||||
|
||||
public partial class EditorWindow : Form
|
||||
{
|
||||
private readonly DataType[] types;
|
||||
private readonly string[] values;
|
||||
private readonly DataType[] types = null;
|
||||
private string[] values;
|
||||
private bool save;
|
||||
private static bool valueInHex = false;
|
||||
|
||||
private void ConvertValues(bool toHex) {
|
||||
for (int i = 0; i < values.Length; i++) {
|
||||
if (toHex) {
|
||||
if (types == null || types[i] == DataType.Int) {
|
||||
int val = int.Parse(values[i]);
|
||||
values[i] = "0x" + val.ToString("x").ToUpper();
|
||||
}
|
||||
} else {
|
||||
if (types == null || types[i] == DataType.Int) {
|
||||
values[i] = Convert.ToInt32(values[i], 16).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EditorWindow(string[] names, DataType[] types, string[] values, bool isMap) {
|
||||
this.types = types;
|
||||
this.values = values;
|
||||
|
||||
InitializeComponent();
|
||||
checkBox.Checked = EditorWindow.valueInHex;
|
||||
dataGridView1.SuspendLayout();
|
||||
if (valueInHex) ConvertValues(true);
|
||||
if (names == null)
|
||||
for (int i = 0; i < types.Length; i++) {
|
||||
string element = i.ToString();
|
||||
@@ -31,15 +50,46 @@ namespace FalloutClient {
|
||||
public static string[] ShowEditor(DebugEditor form, string[] names, DataType[] types, string[] values, bool isMap = false) {
|
||||
EditorWindow editor = new EditorWindow(names, types, values, isMap);
|
||||
editor.ShowDialog();
|
||||
if (editor.save)
|
||||
if (editor.save) {
|
||||
if (valueInHex) editor.ConvertValues(false);
|
||||
return editor.values;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private EditorWindow(string[] values) {
|
||||
this.values = values;
|
||||
InitializeComponent();
|
||||
checkBox.Checked = EditorWindow.valueInHex;
|
||||
dataGridView1.SuspendLayout();
|
||||
if (valueInHex) ConvertValues(true);
|
||||
for (int i = 0; i < values.Length; i++) {
|
||||
dataGridView1.Rows.Add(i.ToString(), "Int", values[i]);
|
||||
}
|
||||
dataGridView1.ResumeLayout();
|
||||
}
|
||||
|
||||
public static string[] ShowEditor(DebugEditor form, string[] lvalues) {
|
||||
EditorWindow editor = new EditorWindow(lvalues);
|
||||
editor.ShowDialog();
|
||||
if (editor.save) {
|
||||
if (valueInHex) editor.ConvertValues(false);
|
||||
return editor.values;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool CheckInput(DataType type, string str) {
|
||||
switch (type) {
|
||||
case DataType.Int:
|
||||
if (valueInHex) {
|
||||
try {
|
||||
Convert.ToInt32(str, 16);
|
||||
return true;
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
return int.TryParse(str, out i);
|
||||
case DataType.Float:
|
||||
@@ -51,7 +101,7 @@ namespace FalloutClient {
|
||||
|
||||
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
|
||||
string str = (string)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
|
||||
if (str != null && CheckInput(types[e.RowIndex], str))
|
||||
if (str != null && CheckInput(((types != null) ? types[e.RowIndex] : DataType.Int), str))
|
||||
values[e.RowIndex] = str;
|
||||
else
|
||||
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = values[e.RowIndex];
|
||||
@@ -65,5 +115,13 @@ namespace FalloutClient {
|
||||
save = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void checkBox_Click(object sender, EventArgs e) {
|
||||
valueInHex = checkBox.Checked;
|
||||
ConvertValues(valueInHex);
|
||||
for (int i = 0; i < values.Length; i++) {
|
||||
dataGridView1.Rows[i].Cells[2].Value = values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace FalloutClient {
|
||||
SetSGlobal = 4,
|
||||
GetArray = 9,
|
||||
SetArray = 10,
|
||||
GetLocal = 11,
|
||||
SetLocal = 12,
|
||||
Exit = 254
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("4.1.7.0")]
|
||||
[assembly: AssemblyFileVersion("4.1.7.0")]
|
||||
[assembly: AssemblyVersion("4.1.9.0")]
|
||||
[assembly: AssemblyFileVersion("4.1.9.0")]
|
||||
|
||||
+9
-4
@@ -1,5 +1,5 @@
|
||||
;sfall configuration settings
|
||||
;v3.8.18
|
||||
;v3.8.19
|
||||
|
||||
[Main]
|
||||
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
|
||||
@@ -225,7 +225,7 @@ UseFileSystemOverride=0
|
||||
;Set to 1 to use the modified data load order for the engine to find game data
|
||||
;Original: patchXXX.dat > critter_patches > critter_dat > f2_res_patches > f2_res_dat > master_patches > master_dat
|
||||
;Modified: master_patches > critter_patches > patchXXX.dat > critter_dat > f2_res_patches > f2_res_dat > master_dat
|
||||
DataLoadOrderPatch=0
|
||||
DataLoadOrderPatch=1
|
||||
|
||||
;To change the default and starting player models, uncomment the next four lines.
|
||||
;The default models can also be changed ingame via script
|
||||
@@ -376,6 +376,7 @@ ProcessorIdle=-1
|
||||
EnableHeroAppearanceMod=0
|
||||
|
||||
;Set to 1 to skip the 3 opening movies
|
||||
;Set to 2 to also skip the splash screen
|
||||
SkipOpeningMovies=0
|
||||
|
||||
;Causes NPCs who complete their combat turn with AP left over will try and find other ways to spend it.
|
||||
@@ -390,7 +391,7 @@ AIBestWeaponFix=0
|
||||
;Set to 1 to fix NPCs not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory
|
||||
AIDrugUsePerfFix=0
|
||||
|
||||
;Allows the use of tiles over 80*36 in size. sfall will just split and resave them at startup
|
||||
;Allows the use of tiles over 80x36 in size. sfall will just split and resave them at startup
|
||||
;Set to 1 to check all tiles on started (slow)
|
||||
;Set to 2 if you provide a XLtiles.lst file in art\tiles\ containing a list of the tile ids that need checking
|
||||
AllowLargeTiles=0
|
||||
@@ -611,7 +612,7 @@ StackEmptyWeapons=0
|
||||
;If the amount of ammo boxes in the inventory is less than or equal to the reserve, only one box will be used
|
||||
ReloadReserve=-1
|
||||
|
||||
;Set to 1 to change the counter in the 'Move Items' window to start at the maximum number of items
|
||||
;Set to 1 to change the counter in the 'Move Items' window to start with maximum number except in the barter screen
|
||||
ItemCounterDefaultMax=0
|
||||
|
||||
;Set to 1 to leave the music playing in dialogue with talking heads
|
||||
@@ -664,6 +665,10 @@ SpecialDeathGVAR=491
|
||||
;Note that enabling this option can break the map changes in Modoc and Vault 15
|
||||
DisableSpecialMapIDs=0
|
||||
|
||||
;Changes the base value of the duration of the knockout effect (valid range: 35..100)
|
||||
;The formula for the duration in ticks is: 10 * (value - 3 * EN)
|
||||
KnockoutTime=35
|
||||
|
||||
;Set to 1 to display sfall built-in credits at the bottom of credits.txt contents instead of at the top
|
||||
CreditsAtBottom=0
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@
|
||||
#define get_cursor_mode sfall_func0("get_cursor_mode")
|
||||
#define get_flags(obj) sfall_func1("get_flags", obj)
|
||||
#define get_map_enter_position sfall_func0("get_map_enter_position")
|
||||
#define get_metarule_table sfall_func0("get_metarule_table")
|
||||
#define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset)
|
||||
#define get_outline(obj) sfall_func1("get_outline", obj)
|
||||
#define intface_hide sfall_func0("intface_hide")
|
||||
@@ -242,6 +243,7 @@
|
||||
#define item_weight(obj) sfall_func1("item_weight", obj)
|
||||
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
||||
#define loot_obj sfall_func0("loot_obj")
|
||||
#define metarule_exist(metarule) sfall_func1("metarule_exist", metarule)
|
||||
#define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle)
|
||||
#define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude)
|
||||
#define outlined_object sfall_func0("outlined_object")
|
||||
|
||||
@@ -305,7 +305,7 @@ Some utility/math functions are available:
|
||||
> string message_str_game(int fileId, int messageId)
|
||||
- works exactly the same as message_str, except you get messages from files in "text\<language>\game\" directory
|
||||
- use GAME_MSG_* defines or mstr_* macros from sfall.h to use specific msg file
|
||||
- Additional game msg files added by ExtraGameMsgFileList setting will have consecutive fileIds assigned beginning from 0x2000. (e.g. if you set ExtraGameMsgFileList=foo,bar in ddraw.ini, foo.msg will be associated with 0x2000 and bar.msg with 0x2001.)
|
||||
- Additional game msg files added by ExtraGameMsgFileList setting will have consecutive fileIds assigned beginning from 0x2000 to 0x2FFF. (e.g. if you set ExtraGameMsgFileList=foo,bar in ddraw.ini, foo.msg will be associated with 0x2000 and bar.msg with 0x2001.)
|
||||
|
||||
> int sneak_success
|
||||
- returns 1 if the player is currently sneaking, and last sneak attempt (roll against skill) was successful; 0 otherwise
|
||||
@@ -359,8 +359,11 @@ Some utility/math functions are available:
|
||||
> array sfall_func0("get_metarule_table")
|
||||
- returns names of all currently available scripting functions (via sfall_funcX)
|
||||
|
||||
> bool sfall_func1("metarule_exist", string metaruleName)
|
||||
- returns True if the specified name of metarule (sfall_funcX) function exists in the current version of sfall
|
||||
|
||||
> int sfall_func1("spatial_radius", object object)
|
||||
- return radius of spatial script, associated with given dummy-object (returned by create_spatial)
|
||||
- returns radius of spatial script, associated with given dummy-object (returned by create_spatial)
|
||||
|
||||
> object sfall_func2("critter_inven_obj2", object invenObj, int type)
|
||||
- works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot
|
||||
|
||||
+244
-57
@@ -862,8 +862,7 @@ static void __declspec(naked) action_melee_hack() {
|
||||
mov edx, 0x4113DC
|
||||
mov ebx, [eax + 0x20] // objStruct->FID
|
||||
and ebx, 0x0F000000
|
||||
sar ebx, 0x18
|
||||
cmp ebx, OBJ_TYPE_CRITTER // check if object FID type flag is set to critter
|
||||
cmp ebx, OBJ_TYPE_CRITTER << 24 // check if object FID type flag is set to critter
|
||||
jne end // if object not a critter leave jump condition flags
|
||||
// set to skip dodge animation
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_OUT or DAM_KNOCKED_DOWN // (original code)
|
||||
@@ -879,8 +878,7 @@ static void __declspec(naked) action_ranged_hack() {
|
||||
mov edx, 0x411B6D
|
||||
mov ebx, [eax + 0x20] // objStruct->FID
|
||||
and ebx, 0x0F000000
|
||||
sar ebx, 0x18
|
||||
cmp ebx, OBJ_TYPE_CRITTER // check if object FID type flag is set to critter
|
||||
cmp ebx, OBJ_TYPE_CRITTER << 24 // check if object FID type flag is set to critter
|
||||
jne end // if object not a critter leave jump condition flags
|
||||
// set to skip dodge animation
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_OUT or DAM_KNOCKED_DOWN // (original code)
|
||||
@@ -891,75 +889,98 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD SetNewResults_Ret = 0x424FC6;
|
||||
static void __declspec(naked) set_new_results_hack() {
|
||||
__asm {
|
||||
test ah, DAM_KNOCKED_OUT // DAM_KNOCKED_OUT?
|
||||
jz end // No
|
||||
mov eax, esi
|
||||
xor edx, edx
|
||||
inc edx // type = knockout
|
||||
jmp queue_remove_this_ // Remove knockout from queue (if there is one)
|
||||
end:
|
||||
add esp, 4 // Destroy the return address
|
||||
jmp SetNewResults_Ret
|
||||
call stat_level_;
|
||||
push eax;
|
||||
mov eax, esi;
|
||||
xor edx, edx;
|
||||
inc edx; // type = knockout
|
||||
call queue_remove_this_; // Remove knockout from queue (if there is one)
|
||||
pop eax;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) critter_wake_clear_hack() {
|
||||
__asm {
|
||||
jne end // This is not a critter
|
||||
mov dl, [esi + 0x44]
|
||||
test dl, DAM_DEAD // DAM_DEAD?
|
||||
jnz end // This is a corpse
|
||||
and dl, ~DAM_KNOCKED_OUT // 0xFE Unset DAM_KNOCKED_OUT
|
||||
or dl, DAM_KNOCKED_DOWN // Set DAM_KNOCKED_DOWN
|
||||
mov [esi + 0x44], dl
|
||||
jne end; // This is not a critter
|
||||
mov dl, [esi + 0x44];
|
||||
test dl, DAM_DEAD; // DAM_DEAD?
|
||||
jnz end; // This is a corpse
|
||||
and dl, ~DAM_KNOCKED_OUT; // Unset DAM_KNOCKED_OUT
|
||||
or dl, DAM_KNOCKED_DOWN; // Set DAM_KNOCKED_DOWN
|
||||
mov [esi + 0x44], dl;
|
||||
end:
|
||||
xor eax, eax
|
||||
inc eax
|
||||
pop esi
|
||||
pop ecx
|
||||
pop ebx
|
||||
retn
|
||||
xor eax, eax;
|
||||
inc eax;
|
||||
pop esi;
|
||||
pop ecx;
|
||||
pop ebx;
|
||||
retn; // exit from func
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD obj_load_func_Ret = 0x488F14;
|
||||
static void __declspec(naked) obj_load_func_hack() {
|
||||
__asm {
|
||||
test byte ptr [eax+0x25], 0x4 // Temp_
|
||||
jnz end
|
||||
mov edi, [eax + 0x64]
|
||||
shr edi, 0x18
|
||||
cmp edi, OBJ_TYPE_CRITTER
|
||||
jne skip
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_DOWN
|
||||
jz clear // No
|
||||
pushadc
|
||||
push ebx
|
||||
xor ecx, ecx
|
||||
mov edx, eax // object
|
||||
mov ebx, ecx // extramem null
|
||||
mov eax, ecx // time = 0
|
||||
inc ecx // type = 1
|
||||
call queue_add_
|
||||
pop ebx
|
||||
popadc
|
||||
test byte ptr [eax + 0x25], 0x4; // Temp_
|
||||
jz fix;
|
||||
retn;
|
||||
fix:
|
||||
mov edi, [eax + 0x64];
|
||||
and edi, 0x0F000000;
|
||||
cmp edi, OBJ_TYPE_CRITTER << 24;
|
||||
jne skip;
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_OUT;
|
||||
jnz clear; // Yes
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_DOWN;
|
||||
jz clear; // No
|
||||
push eax;
|
||||
xor ecx, ecx;
|
||||
mov edx, eax; // object
|
||||
mov ebx, ecx; // extramem null
|
||||
mov eax, ecx; // time = 0
|
||||
inc ecx; // type = 1
|
||||
call queue_add_; // run stand up anim
|
||||
pop eax;
|
||||
clear:
|
||||
and word ptr [eax + 0x44], ~(DAM_LOSE_TURN or DAM_KNOCKED_DOWN) // 0x7FFD
|
||||
and word ptr [eax + 0x44], ~(DAM_LOSE_TURN or DAM_KNOCKED_DOWN);
|
||||
skip:
|
||||
push 0x488F14
|
||||
retn
|
||||
end:
|
||||
push 0x488EF9
|
||||
retn
|
||||
add esp, 4;
|
||||
jmp obj_load_func_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) partyMemberPrepLoadInstance_hook() {
|
||||
__asm {
|
||||
and word ptr [eax + 0x44], ~(DAM_LOSE_TURN or DAM_KNOCKED_DOWN) // 0x7FFD
|
||||
jmp dude_stand_
|
||||
and word ptr [eax + 0x44], ~(DAM_LOSE_TURN or DAM_KNOCKED_DOWN);
|
||||
jmp dude_stand_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) combat_over_hack() {
|
||||
__asm {
|
||||
mov [eax + 0x3C], edx;
|
||||
and word ptr [eax + 0x44], ~DAM_LOSE_TURN;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) combat_over_hook() {
|
||||
__asm {
|
||||
test byte ptr [eax + 0x44], DAM_DEAD;
|
||||
jz fix;
|
||||
retn; // the dead cannot reload their weapons
|
||||
fix:
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_DOWN;
|
||||
jz skip;
|
||||
push eax;
|
||||
call dude_standup_;
|
||||
pop eax;
|
||||
xor edx, edx;
|
||||
skip:
|
||||
jmp cai_attempt_w_reload_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1719,7 +1740,7 @@ static void __declspec(naked) process_rads_hook() {
|
||||
__asm {
|
||||
push eax; // death message for DialogOut
|
||||
call display_print_;
|
||||
call GetCurrentLoops;
|
||||
call GetLoopFlags;
|
||||
test eax, PIPBOY;
|
||||
jz skip;
|
||||
mov eax, 1;
|
||||
@@ -2062,10 +2083,148 @@ dude:
|
||||
}
|
||||
}
|
||||
|
||||
static long blockingTileObj = 0;
|
||||
static const DWORD anim_move_to_tile_jmp = 0x416D91;
|
||||
static void __declspec(naked) anim_move_to_tile_hook() {
|
||||
__asm {
|
||||
call obj_blocking_at_;
|
||||
mov blockingTileObj, eax;
|
||||
cmp edi, ds:[_obj_dude];
|
||||
je isDude;
|
||||
retn;
|
||||
isDude:
|
||||
test eax, eax;
|
||||
jnz skip; // tile is blocked
|
||||
mov ebx, dword ptr [esp + 0x18 - 0x10 + 4]; // distance
|
||||
test ebx, ebx;
|
||||
jl skip; // dist < 0
|
||||
sub ebx, ds:[_combat_free_move];
|
||||
cmp ebx, [edi + 0x40];
|
||||
jge skip; // dist >= source.curr_mp
|
||||
test eax, eax;
|
||||
jnz skip;
|
||||
add esp, 4;
|
||||
jmp anim_move_to_tile_jmp;
|
||||
skip:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) anim_move_to_tile_hook_tile() {
|
||||
__asm {
|
||||
cmp blockingTileObj, 0;
|
||||
jne getTile;
|
||||
retn;
|
||||
getTile:
|
||||
jmp tile_num_in_direction_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) action_use_an_item_on_object_hack() {
|
||||
__asm {
|
||||
add ebx, ds:[_combat_free_move];
|
||||
mov eax, 2; // RB_RESERVED
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) action_climb_ladder_hack() {
|
||||
__asm {
|
||||
add ecx, ds:[_combat_free_move];
|
||||
mov eax, 2; // RB_RESERVED
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
//static const DWORD wmAreaMarkVisitedState_Error = 0x4C4698;
|
||||
static const DWORD wmAreaMarkVisitedState_Ret = 0x4C46A2;
|
||||
static void __declspec(naked) wmAreaMarkVisitedState_hack() {
|
||||
__asm {
|
||||
mov [ecx + 0x40], esi; // wmAreaInfoList.visited
|
||||
test esi, esi; // mark "unknown" state
|
||||
jz skip;
|
||||
mov eax, [ecx + 0x2C]; // wmAreaInfoList.world_posx
|
||||
mov edx, [ecx + 0x30]; // wmAreaInfoList.world_posy
|
||||
// fix loc coordinates
|
||||
cmp [ecx + 0x34], 1; // wmAreaInfoList.size
|
||||
jg largeLoc;
|
||||
je mediumLoc;
|
||||
//smallLoc:
|
||||
sub eax, 5;
|
||||
lea edx, [edx - 5];
|
||||
mediumLoc:
|
||||
sub eax, 10;
|
||||
lea edx, [edx - 10];
|
||||
largeLoc:
|
||||
mov ebx, esp; // ppSubTile out
|
||||
push edx;
|
||||
push eax;
|
||||
call wmFindCurSubTileFromPos_;
|
||||
// cmp eax, -1; // always return 0
|
||||
// jz error;
|
||||
pop eax;
|
||||
pop edx;
|
||||
mov ebx, [esp];
|
||||
mov ebx, [ebx + 0x18]; // sub-tile state
|
||||
test ebx, ebx;
|
||||
jnz skip;
|
||||
inc ebx; // 1
|
||||
skip:
|
||||
cmp [ecx + 0x38], 1; // wmAreaInfoList.start_state
|
||||
jne hideLoc;
|
||||
cmp esi, 2; // mark visited state
|
||||
jne fix;
|
||||
call wmMarkSubTileRadiusVisited_;
|
||||
hideLoc:
|
||||
jmp wmAreaMarkVisitedState_Ret;
|
||||
fix:
|
||||
push ebx;
|
||||
mov ebx, 1; // radius (fix w/o PERK_scout)
|
||||
call wmSubTileMarkRadiusVisited_;
|
||||
pop ebx;
|
||||
jmp wmAreaMarkVisitedState_Ret;
|
||||
//error:
|
||||
// add esp, 8;
|
||||
// jmp wmAreaMarkVisitedState_Error;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmWorldMap_hack() {
|
||||
__asm {
|
||||
mov ebx, [ebx + 0x34]; // wmAreaInfoList.size
|
||||
cmp ebx, 1;
|
||||
jg largeLoc;
|
||||
je mediumLoc;
|
||||
//smallLoc:
|
||||
sub eax, 5;
|
||||
lea edx, [edx - 5];
|
||||
mediumLoc:
|
||||
sub eax, 10;
|
||||
lea edx, [edx - 10];
|
||||
largeLoc:
|
||||
xor ebx, ebx;
|
||||
jmp wmPartyInitWalking_;
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD combat_should_end_break = 0x422D00;
|
||||
static void __declspec(naked) combat_should_end_hack() {
|
||||
__asm { // ecx = dude.team_num
|
||||
cmp ecx, [ebp + 0x50]; // npc who_hit_me.team_num
|
||||
je break;
|
||||
test byte ptr [edx], 1; // npc combat_data.combat_state
|
||||
jnz break;
|
||||
retn; // check next critter
|
||||
break:
|
||||
add esp, 4;
|
||||
jmp combat_should_end_break;
|
||||
}
|
||||
}
|
||||
|
||||
void BugFixesInit()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (IsDebug && (GetPrivateProfileIntA("Debugging", "BugFixes", 1, ".\\ddraw.ini")) == 0)) return;
|
||||
if (isDebug && (GetPrivateProfileIntA("Debugging", "BugFixes", 1, ".\\ddraw.ini")) == 0)) return;
|
||||
#endif
|
||||
|
||||
// fix vanilla negate operator on float values
|
||||
@@ -2254,6 +2413,8 @@ void BugFixesInit()
|
||||
SafeWrite8(0x4415CC, 0x00); // Prevent crashes when re-exporting
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
// Fix for op_lookup_string_proc_ engine function not searching the last procedure in a script
|
||||
SafeWrite8(0x46C7AC, 0x76); // jb > jbe
|
||||
|
||||
//if (GetPrivateProfileIntA("Misc", "WieldObjCritterFix", 1, ini)) {
|
||||
dlog("Applying wield_obj_critter fix.", DL_INIT);
|
||||
@@ -2282,12 +2443,17 @@ void BugFixesInit()
|
||||
// Fix for "NPC turns into a container" bug
|
||||
//if (GetPrivateProfileIntA("Misc", "NPCTurnsIntoContainerFix", 1, ini)) {
|
||||
dlog("Applying fix for \"NPC turns into a container\" bug.", DL_INIT);
|
||||
MakeCall(0x424F8E, set_new_results_hack);
|
||||
MakeJump(0x42E46E, critter_wake_clear_hack);
|
||||
MakeJump(0x488EF3, obj_load_func_hack);
|
||||
MakeCall(0x488EF3, obj_load_func_hack, 1);
|
||||
HookCall(0x4949B2, partyMemberPrepLoadInstance_hook);
|
||||
MakeCall(0x421F64, combat_over_hack, 1);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
// Fix for multiple knockout events being added to the queue
|
||||
HookCall(0x424F9A, set_new_results_hack);
|
||||
// Fix for knocked down critters not playing stand up animation when the combat ends
|
||||
// and prevent dead NPCs from reloading their weapons
|
||||
HookCall(0x421F30, combat_over_hook);
|
||||
|
||||
dlog("Applying fix for explosives bugs.", DL_INIT);
|
||||
// Fix crashes when killing critters with explosives
|
||||
@@ -2610,4 +2776,25 @@ void BugFixesInit()
|
||||
// up an item due to not enough space in the inventory
|
||||
HookCall(0x49B6E7, obj_pickup_hook);
|
||||
HookCall(0x49B71C, obj_pickup_hook_message);
|
||||
|
||||
// Fix for anim_move_to_tile_ engine function ignoring the distance argument for the player
|
||||
HookCall(0x416D44, anim_move_to_tile_hook);
|
||||
HookCall(0x416DD2, anim_move_to_tile_hook_tile);
|
||||
|
||||
// Fix for the player's movement in combat being interrupted when trying to use objects with Bonus Move APs available
|
||||
MakeCall(0x411FD6, action_use_an_item_on_object_hack);
|
||||
MakeCall(0x411DF7, action_climb_ladder_hack); // bug caused by anim_move_to_tile_ fix
|
||||
|
||||
// Fix for Scout perk being taken into account when setting the visibility of locations with mark_area_known function
|
||||
// also fix the incorrect coordinates for small/medium location circles that the engine uses to highlight their sub-tiles
|
||||
// and fix visited tiles on the world map being darkened again when a location is added next to them
|
||||
MakeJump(0x4C466F, wmAreaMarkVisitedState_hack);
|
||||
SafeWrite8(0x4C46AB, 0x58); // esi > ebx
|
||||
|
||||
// Fix the position of the target marker for small/medium location circles
|
||||
MakeCall(0x4C03AA, wmWorldMap_hack, 2);
|
||||
|
||||
// Fix for combat not ending automatically when there are no hostile critters
|
||||
MakeCall(0x422CF3, combat_should_end_hack);
|
||||
SafeWrite16(0x422CEA, 0x0C74); // jz 0x422CF8 (skip party members)
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ void CritLoad() {
|
||||
int slot2 = crit + part * 6 + ((critter == 19) ? 38 : critter) * 9 * 6;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
baseCritTable[slot2].values[i] = GetPrivateProfileIntA(section, CritNames[i], defaultTable[slot1].values[i], CritTableFile);
|
||||
if (IsDebug) {
|
||||
if (isDebug) {
|
||||
char logmsg[256];
|
||||
if (baseCritTable[slot2].values[i] != defaultTable[slot1].values[i]) {
|
||||
sprintf_s(logmsg, "Entry %s value %d changed from %d to %d", section, i, defaultTable[slot1].values[i], baseCritTable[slot2].values[i]);
|
||||
|
||||
+44
-13
@@ -25,18 +25,22 @@
|
||||
#include "FalloutEngine.h"
|
||||
#include "ScriptExtender.h"
|
||||
|
||||
#define CODE_EXIT (254)
|
||||
#define CODE_SET_GLOBAL (0)
|
||||
#define CODE_SET_MAPVAR (1)
|
||||
#define CODE_GET_CRITTER (2)
|
||||
#define CODE_SET_CRITTER (3)
|
||||
#define CODE_SET_SGLOBAL (4)
|
||||
#define CODE_GET_PROTO (5)
|
||||
#define CODE_SET_PROTO (6)
|
||||
#define CODE_GET_PLAYER (7)
|
||||
#define CODE_SET_PLAYER (8)
|
||||
#define CODE_GET_ARRAY (9)
|
||||
#define CODE_SET_ARRAY (10)
|
||||
enum DECode {
|
||||
CODE_SET_GLOBAL = 0,
|
||||
CODE_SET_MAPVAR = 1,
|
||||
CODE_GET_CRITTER = 2,
|
||||
CODE_SET_CRITTER = 3,
|
||||
CODE_SET_SGLOBAL = 4,
|
||||
CODE_GET_PROTO = 5,
|
||||
CODE_SET_PROTO = 6,
|
||||
CODE_GET_PLAYER = 7,
|
||||
CODE_SET_PLAYER = 8,
|
||||
CODE_GET_ARRAY = 9,
|
||||
CODE_SET_ARRAY = 10,
|
||||
CODE_GET_LOCVARS = 11,
|
||||
CODE_SET_LOCVARS = 12,
|
||||
CODE_EXIT = 254
|
||||
};
|
||||
|
||||
static const char* debugLog = "LOG";
|
||||
static const char* debugGnw = "GNW";
|
||||
@@ -194,6 +198,33 @@ static void RunEditorInternal(SOCKET &s) {
|
||||
delete[] data;
|
||||
}
|
||||
break;
|
||||
case CODE_GET_LOCVARS:
|
||||
{
|
||||
InternalRecv(s, &id, 4); // sid
|
||||
val = GetScriptLocalVars(id);
|
||||
InternalSend(s, &val, 4);
|
||||
if (val) {
|
||||
std::vector<int> values(val);
|
||||
long varVal;
|
||||
for (int i = 0; i < val; i++) {
|
||||
ScrGetLocalVar(id, i, &varVal);
|
||||
values[i] = varVal;
|
||||
}
|
||||
InternalSend(s, values.data(), val * 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_SET_LOCVARS:
|
||||
{
|
||||
InternalRecv(s, &id, 4); // sid
|
||||
InternalRecv(s, &val, 4); // len data
|
||||
std::vector<int> values(val);
|
||||
InternalRecv(s, values.data(), val * 4);
|
||||
for (int i = 0; i < val; i++) {
|
||||
ScrSetLocalVar(id, i, values[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
DEGameWinRedraw();
|
||||
}
|
||||
@@ -328,7 +359,7 @@ void DontDeleteProtosPatch() {
|
||||
}
|
||||
|
||||
void DebugEditorInit() {
|
||||
if (!IsDebug) return;
|
||||
if (!isDebug) return;
|
||||
DebugModePatch();
|
||||
DontDeleteProtosPatch();
|
||||
}
|
||||
|
||||
@@ -365,3 +365,21 @@ enum RollResult
|
||||
ROLL_SUCCESS = 0x2,
|
||||
ROLL_CRITICAL_SUCCESS = 0x3,
|
||||
};
|
||||
|
||||
enum QueueType : long
|
||||
{
|
||||
drug_effect_event = 0, // critter use drug
|
||||
knockout_event = 1, // critter
|
||||
addict_event = 2, // critter
|
||||
script_timer_event = 3, // any object
|
||||
game_time_event = 4, // no object
|
||||
poison_event = 5, // dude
|
||||
radiation_event = 6, // dude
|
||||
flare_time_event = 7, // item
|
||||
explode_event = 8, // item
|
||||
item_trickle_event = 9,
|
||||
sneak_event = 10, // dude
|
||||
explode_fail_event = 11, // item
|
||||
map_update_event = 12,
|
||||
gsound_sfx_event = 13 // no object
|
||||
};
|
||||
|
||||
+58
-6
@@ -265,6 +265,7 @@ const DWORD automap_ = 0x41B8BC;
|
||||
const DWORD barter_compute_value_ = 0x474B2C;
|
||||
const DWORD barter_inventory_ = 0x4757F0;
|
||||
const DWORD buf_to_buf_ = 0x4D36D4;
|
||||
const DWORD cai_attempt_w_reload_ = 0x42AECC;
|
||||
const DWORD check_death_ = 0x410814;
|
||||
const DWORD Check4Keys_ = 0x43F73C;
|
||||
const DWORD combat_ = 0x422D2C;
|
||||
@@ -339,6 +340,7 @@ const DWORD DrawFolder_ = 0x43410C;
|
||||
const DWORD DrawInfoWin_ = 0x4365AC;
|
||||
const DWORD drop_into_container_ = 0x476464;
|
||||
const DWORD dude_stand_ = 0x418378;
|
||||
const DWORD dude_standup_ = 0x418574;
|
||||
const DWORD editor_design_ = 0x431DF8;
|
||||
const DWORD elapsed_time_ = 0x4C93E0;
|
||||
const DWORD elevator_end_ = 0x43F6D0;
|
||||
@@ -509,8 +511,10 @@ const DWORD obj_dist_ = 0x48BBD4;
|
||||
const DWORD obj_dist_with_tile_ = 0x48BC08;
|
||||
const DWORD obj_drop_ = 0x49B8B0;
|
||||
const DWORD obj_erase_object_ = 0x48B0FC;
|
||||
const DWORD obj_find_first_ = 0x48B3A8;
|
||||
const DWORD obj_find_first_at_ = 0x48B48C;
|
||||
const DWORD obj_find_first_at_tile_ = 0x48B5A8;
|
||||
const DWORD obj_find_next_ = 0x48B41C;
|
||||
const DWORD obj_find_next_at_ = 0x48B510;
|
||||
const DWORD obj_find_next_at_tile_ = 0x48B608;
|
||||
const DWORD obj_lock_is_jammed_ = 0x49D410;
|
||||
@@ -529,6 +533,7 @@ const DWORD obj_use_book_ = 0x49B9F0;
|
||||
const DWORD obj_use_power_on_car_ = 0x49BDE8;
|
||||
const DWORD object_under_mouse_ = 0x44CEC4;
|
||||
const DWORD OptionWindow_ = 0x437C08;
|
||||
const DWORD palette_init_ = 0x493A00;
|
||||
const DWORD palette_set_to_ = 0x493B48;
|
||||
const DWORD partyMemberCopyLevelInfo_ = 0x495EA8;
|
||||
const DWORD partyMemberGetAIOptions_ = 0x4941F0;
|
||||
@@ -591,15 +596,18 @@ const DWORD roll_random_ = 0x4A30C0;
|
||||
const DWORD runProgram_ = 0x46E154;
|
||||
const DWORD SaveGame_ = 0x47B88C;
|
||||
const DWORD SavePlayer_ = 0x43A7DC;
|
||||
const DWORD scr_exec_map_exit_scripts_ = 0x4A69A0;
|
||||
const DWORD scr_exec_map_update_scripts_ = 0x4A67E4;
|
||||
const DWORD scr_find_first_at_ = 0x4A6524;
|
||||
const DWORD scr_find_next_at_ = 0x4A6564;
|
||||
const DWORD scr_find_obj_from_program_ = 0x4A39AC;
|
||||
const DWORD scr_find_sid_from_program_ = 0x4A390C;
|
||||
const DWORD scr_get_local_var_ = 0x4A6D64;
|
||||
const DWORD scr_new_ = 0x4A5F28;
|
||||
const DWORD scr_ptr_ = 0x4A5E34;
|
||||
const DWORD scr_remove_ = 0x4A61D4;
|
||||
const DWORD scr_set_ext_param_ = 0x4A3B34;
|
||||
const DWORD scr_set_local_var_ = 0x4A6E58;
|
||||
const DWORD scr_set_objs_ = 0x4A3B0C;
|
||||
const DWORD scr_write_ScriptNode_ = 0x4A5704;
|
||||
const DWORD set_game_time_ = 0x4A347C;
|
||||
@@ -636,6 +644,7 @@ const DWORD text_font_ = 0x4D58DC;
|
||||
const DWORD text_object_create_ = 0x4B036C;
|
||||
const DWORD tile_coord_ = 0x4B1674;
|
||||
const DWORD tile_num_ = 0x4B1754;
|
||||
const DWORD tile_num_in_direction_ = 0x4B1A6C;
|
||||
const DWORD tile_refresh_display_ = 0x4B12D8;
|
||||
const DWORD tile_refresh_rect_ = 0x4B12C0;
|
||||
const DWORD tile_scroll_to_ = 0x4B3924;
|
||||
@@ -659,8 +668,13 @@ const DWORD win_register_button_ = 0x4D8260;
|
||||
const DWORD win_register_button_disable_ = 0x4D8674;
|
||||
const DWORD win_register_button_sound_func_ = 0x4D87F8;
|
||||
const DWORD win_show_ = 0x4D6DAC;
|
||||
const DWORD wmFindCurSubTileFromPos_ = 0x4C0C00;
|
||||
const DWORD wmInterfaceScrollTabsStart_ = 0x4C219C;
|
||||
const DWORD wmMapIsSaveable_ = 0x4BFA64;
|
||||
const DWORD wmMarkSubTileRadiusVisited_ = 0x4C3550;
|
||||
const DWORD wmPartyInitWalking_ = 0x4C1E54;
|
||||
const DWORD wmPartyWalkingStep_ = 0x4C1F90;
|
||||
const DWORD wmSubTileMarkRadiusVisited_ = 0x4C35A8;
|
||||
const DWORD wmWorldMapFunc_ = 0x4BFE10;
|
||||
const DWORD wmWorldMapLoadTempData_ = 0x4BD6B4;
|
||||
const DWORD xfclose_ = 0x4DED6C;
|
||||
@@ -713,21 +727,26 @@ long __stdcall PartyMemberGetCurrentLevel(TGameObj* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
char* GetProtoPtr(DWORD pid) {
|
||||
char* GetProtoPtr(long pid) {
|
||||
char* proto;
|
||||
long result;
|
||||
__asm {
|
||||
mov eax, pid;
|
||||
lea edx, proto;
|
||||
call proto_ptr_;
|
||||
mov result, eax;
|
||||
}
|
||||
return proto;
|
||||
if (result != -1) {
|
||||
return proto;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char AnimCodeByWeapon(TGameObj* weapon) {
|
||||
if (weapon != NULL) {
|
||||
if (weapon != nullptr) {
|
||||
char* proto = GetProtoPtr(weapon->pid);
|
||||
if (proto && *(int*)(proto + 32) == item_type_weapon) {
|
||||
return (char)(*(int*)(proto + 36));
|
||||
if (proto != nullptr && *(int*)(proto + 32) == item_type_weapon) {
|
||||
return (char)(*(int*)(proto + 36));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -741,7 +760,7 @@ void DisplayConsoleMessage(const char* msg) {
|
||||
}
|
||||
|
||||
static DWORD mesg_buf[4] = {0, 0, 0, 0};
|
||||
const char* _stdcall GetMessageStr(DWORD fileAddr, DWORD messageId) {
|
||||
const char* __stdcall GetMessageStr(DWORD fileAddr, DWORD messageId) {
|
||||
DWORD buf = (DWORD)mesg_buf;
|
||||
const char* result;
|
||||
__asm {
|
||||
@@ -792,6 +811,8 @@ void SkillSetTags(int* tags, DWORD num) {
|
||||
}
|
||||
}
|
||||
|
||||
// Saves pointer to script object into scriptPtr using scriptID.
|
||||
// Returns 0 on success, -1 on failure.
|
||||
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr) {
|
||||
__asm {
|
||||
mov eax, scriptId;
|
||||
@@ -800,6 +821,29 @@ long __stdcall ScrPtr(long scriptId, TScript** scriptPtr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the number of local variables of the object script
|
||||
long GetScriptLocalVars(long sid) {
|
||||
TScript* script = nullptr;
|
||||
ScrPtr(sid, &script);
|
||||
return (script) ? script->num_local_vars : 0;
|
||||
}
|
||||
|
||||
long __fastcall ScrGetLocalVar(long sid, long varId, long* value) {
|
||||
__asm {
|
||||
mov ebx, value;
|
||||
mov eax, ecx;
|
||||
call scr_get_local_var_;
|
||||
}
|
||||
}
|
||||
|
||||
long __fastcall ScrSetLocalVar(long sid, long varId, long value) {
|
||||
__asm {
|
||||
mov ebx, value;
|
||||
mov eax, ecx;
|
||||
call scr_set_local_var_;
|
||||
}
|
||||
}
|
||||
|
||||
// redraws the main game interface windows (useful after changing some data like active hand, etc.)
|
||||
void InterfaceRedraw() {
|
||||
__asm call intface_redraw_;
|
||||
@@ -1028,6 +1072,14 @@ long __stdcall QueueFindFirst(TGameObj* object, long qType) {
|
||||
}
|
||||
}
|
||||
|
||||
TGameObj* __stdcall ObjFindFirst() {
|
||||
__asm call obj_find_first_;
|
||||
}
|
||||
|
||||
TGameObj* __stdcall ObjFindNext() {
|
||||
__asm call obj_find_next_;
|
||||
}
|
||||
|
||||
long __stdcall NewObjId() {
|
||||
__asm call new_obj_id_;
|
||||
}
|
||||
|
||||
+33
-9
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* FALLOUT2.EXE structs, function offsets and wrappers should be placed here
|
||||
*
|
||||
/*
|
||||
* FALLOUT2.EXE structs, function offsets and wrappers should be placed here
|
||||
*
|
||||
* only place functions and variables here which are likely to be used in more than one module
|
||||
*
|
||||
*/
|
||||
@@ -488,6 +488,7 @@ extern const DWORD automap_;
|
||||
extern const DWORD barter_compute_value_;
|
||||
extern const DWORD barter_inventory_;
|
||||
extern const DWORD buf_to_buf_;
|
||||
extern const DWORD cai_attempt_w_reload_;
|
||||
extern const DWORD check_death_;
|
||||
extern const DWORD Check4Keys_;
|
||||
extern const DWORD combat_;
|
||||
@@ -562,6 +563,7 @@ extern const DWORD DrawFolder_;
|
||||
extern const DWORD DrawInfoWin_;
|
||||
extern const DWORD drop_into_container_;
|
||||
extern const DWORD dude_stand_;
|
||||
extern const DWORD dude_standup_;
|
||||
extern const DWORD editor_design_;
|
||||
extern const DWORD elapsed_time_;
|
||||
extern const DWORD elevator_end_;
|
||||
@@ -618,7 +620,7 @@ extern const DWORD interpretPopLong_;
|
||||
extern const DWORD interpretPopShort_;
|
||||
extern const DWORD interpretPushLong_;
|
||||
extern const DWORD interpretPushShort_;
|
||||
extern const DWORD interpretError_;
|
||||
extern const DWORD interpretError_;
|
||||
extern const DWORD intface_get_attack_;
|
||||
extern const DWORD intface_hide_;
|
||||
extern const DWORD intface_is_hidden_;
|
||||
@@ -698,7 +700,7 @@ extern const DWORD main_game_loop_;
|
||||
extern const DWORD main_init_system_;
|
||||
extern const DWORD main_menu_hide_;
|
||||
extern const DWORD main_menu_loop_;
|
||||
// (int aObjFrom<eax>, int aTileFrom<edx>, char* aPathPtr<ecx>, int aTileTo<ebx>, int a5, int (__fastcall *a6)(_DWORD, _DWORD))
|
||||
// (int aObjFrom<eax>, int aTileFrom<edx>, char* aPathPtr<ecx>, int aTileTo<ebx>, int a5, int (__fastcall *a6)(_DWORD, _DWORD))
|
||||
// - path is saved in ecx as a sequence of tile directions (0..5) to move on each step,
|
||||
// - returns path length
|
||||
extern const DWORD make_path_func_;
|
||||
@@ -737,8 +739,10 @@ extern const DWORD obj_dist_;
|
||||
extern const DWORD obj_dist_with_tile_;
|
||||
extern const DWORD obj_drop_;
|
||||
extern const DWORD obj_erase_object_;
|
||||
extern const DWORD obj_find_first_;
|
||||
extern const DWORD obj_find_first_at_;
|
||||
extern const DWORD obj_find_first_at_tile_; // <eax>(int elevation<eax>, int tile<edx>)
|
||||
extern const DWORD obj_find_next_;
|
||||
extern const DWORD obj_find_next_at_;
|
||||
extern const DWORD obj_find_next_at_tile_; // no args
|
||||
extern const DWORD obj_lock_is_jammed_;
|
||||
@@ -760,6 +764,7 @@ extern const DWORD obj_use_book_;
|
||||
extern const DWORD obj_use_power_on_car_;
|
||||
extern const DWORD object_under_mouse_;
|
||||
extern const DWORD OptionWindow_;
|
||||
extern const DWORD palette_init_;
|
||||
extern const DWORD palette_set_to_;
|
||||
extern const DWORD partyMemberCopyLevelInfo_;
|
||||
extern const DWORD partyMemberGetAIOptions_;
|
||||
@@ -822,15 +827,18 @@ extern const DWORD roll_random_;
|
||||
extern const DWORD runProgram_; // eax - programPtr, called once for each program after first loaded - hooks program to game and UI events
|
||||
extern const DWORD SaveGame_;
|
||||
extern const DWORD SavePlayer_;
|
||||
extern const DWORD scr_exec_map_exit_scripts_;
|
||||
extern const DWORD scr_exec_map_update_scripts_;
|
||||
extern const DWORD scr_find_first_at_; // eax - elevation, returns spatial scriptID
|
||||
extern const DWORD scr_find_next_at_; // no args, returns spatial scriptID
|
||||
extern const DWORD scr_find_obj_from_program_; // eax - *program - finds self_obj by program pointer (has nice additional effect - creates fake object for a spatial script)
|
||||
extern const DWORD scr_find_sid_from_program_;
|
||||
extern const DWORD scr_get_local_var_;
|
||||
extern const DWORD scr_new_; // eax - script index from scripts lst, edx - type (0 - system, 1 - spatials, 2 - time, 3 - items, 4 - critters)
|
||||
extern const DWORD scr_ptr_; // eax - scriptId, edx - **TScript (where to store script pointer)
|
||||
extern const DWORD scr_remove_;
|
||||
extern const DWORD scr_set_ext_param_;
|
||||
extern const DWORD scr_set_local_var_;
|
||||
extern const DWORD scr_set_objs_;
|
||||
extern const DWORD scr_write_ScriptNode_;
|
||||
extern const DWORD set_game_time_;
|
||||
@@ -867,6 +875,7 @@ extern const DWORD text_font_;
|
||||
extern const DWORD text_object_create_;
|
||||
extern const DWORD tile_coord_; // eax - tilenum, edx (int*) - x, ebx (int*) - y
|
||||
extern const DWORD tile_num_;
|
||||
extern const DWORD tile_num_in_direction_;
|
||||
extern const DWORD tile_refresh_display_;
|
||||
extern const DWORD tile_refresh_rect_; // (int elevation<edx>, unkown<ecx>)
|
||||
extern const DWORD tile_scroll_to_;
|
||||
@@ -890,8 +899,13 @@ extern const DWORD win_register_button_;
|
||||
extern const DWORD win_register_button_disable_;
|
||||
extern const DWORD win_register_button_sound_func_;
|
||||
extern const DWORD win_show_;
|
||||
extern const DWORD wmFindCurSubTileFromPos_;
|
||||
extern const DWORD wmInterfaceScrollTabsStart_;
|
||||
extern const DWORD wmMapIsSaveable_;
|
||||
extern const DWORD wmMarkSubTileRadiusVisited_;
|
||||
extern const DWORD wmPartyInitWalking_;
|
||||
extern const DWORD wmPartyWalkingStep_;
|
||||
extern const DWORD wmSubTileMarkRadiusVisited_;
|
||||
extern const DWORD wmWorldMapFunc_;
|
||||
extern const DWORD wmWorldMapLoadTempData_;
|
||||
extern const DWORD xfclose_;
|
||||
@@ -918,7 +932,7 @@ extern const DWORD xvfprintf_;
|
||||
* in ASM code, call offsets directly, don't call wrappers as they might not be _stdcall
|
||||
* in C++ code, use wrappers (add new ones if the don't exist yet)
|
||||
*
|
||||
* Note: USE C++!
|
||||
* Note: USE C++!
|
||||
* 1) Place thin __declspec(naked) hooks, only use minimum ASM to pass values to/from C++
|
||||
* 2) Call _stdcall functions from (1), write those entirely in C++ (with little ASM blocks only to call engine functions, when you are too lazy to add wrapper)
|
||||
*/
|
||||
@@ -948,11 +962,11 @@ extern const DWORD xvfprintf_;
|
||||
// TODO: move these to different namespace
|
||||
long __stdcall IsPartyMember(TGameObj* obj);
|
||||
long __stdcall PartyMemberGetCurrentLevel(TGameObj* obj);
|
||||
char* GetProtoPtr(DWORD pid);
|
||||
char* GetProtoPtr(long pid);
|
||||
char AnimCodeByWeapon(TGameObj* weapon);
|
||||
// Displays message in main UI console window
|
||||
void DisplayConsoleMessage(const char* msg);
|
||||
const char* _stdcall GetMessageStr(DWORD fileAddr, DWORD messageId);
|
||||
const char* __stdcall GetMessageStr(DWORD fileAddr, DWORD messageId);
|
||||
long __stdcall ItemGetType(TGameObj* item);
|
||||
long __stdcall ItemSize(TGameObj* item);
|
||||
|
||||
@@ -962,10 +976,16 @@ void CritterPcSetName(const char* newName);
|
||||
// Returns the name of the critter
|
||||
const char* __stdcall CritterName(TGameObj* critter);
|
||||
|
||||
// Saves pointer to script object into scriptPtr using scriptID.
|
||||
// Saves pointer to script object into scriptPtr using scriptID.
|
||||
// Returns 0 on success, -1 on failure.
|
||||
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr);
|
||||
|
||||
// Returns the number of local variables of the object script
|
||||
long GetScriptLocalVars(long sid);
|
||||
|
||||
long __fastcall ScrGetLocalVar(long sid, long varId, long* value);
|
||||
long __fastcall ScrSetLocalVar(long sid, long varId, long value);
|
||||
|
||||
void SkillGetTags(int* result, DWORD num);
|
||||
void SkillSetTags(int* tags, DWORD num);
|
||||
|
||||
@@ -1035,6 +1055,10 @@ long __stdcall TraitLevel(long traitID);
|
||||
|
||||
long __stdcall QueueFindFirst(TGameObj* object, long qType);
|
||||
|
||||
TGameObj* __stdcall ObjFindFirst();
|
||||
|
||||
TGameObj* __stdcall ObjFindNext();
|
||||
|
||||
long __stdcall NewObjId();
|
||||
|
||||
FrmFrameData* __fastcall FramePtr(FrmHeaderData* frm, long frame, long direction);
|
||||
|
||||
+24
-13
@@ -62,11 +62,13 @@ static DDSURFACEDESC surfaceDesc;
|
||||
static DDSURFACEDESC movieDesc;
|
||||
|
||||
static DWORD palette[256];
|
||||
//static bool paletteInit = false;
|
||||
|
||||
static DWORD gWidth;
|
||||
static DWORD gHeight;
|
||||
|
||||
static int ScrollWindowKey;
|
||||
static bool windowInit = false;
|
||||
static DWORD windowLeft = 0;
|
||||
static DWORD windowTop = 0;
|
||||
|
||||
@@ -124,8 +126,7 @@ static const char* gpuEffect=
|
||||
"technique T0"
|
||||
"{"
|
||||
"pass p0 { PixelShader = compile ps_2_0 P0(); }"
|
||||
"}"
|
||||
;
|
||||
"}";
|
||||
|
||||
static D3DXHANDLE gpuBltBuf;
|
||||
static D3DXHANDLE gpuBltPalette;
|
||||
@@ -169,11 +170,11 @@ void GetFalloutWindowInfo(DWORD* width, DWORD* height, HWND* wnd) {
|
||||
}
|
||||
|
||||
long Gfx_GetGameWidthRes() {
|
||||
return ptr_scr_size->offx - (ptr_scr_size->x + 1);
|
||||
return (ptr_scr_size->offx - ptr_scr_size->x) + 1;
|
||||
}
|
||||
|
||||
long Gfx_GetGameHeightRes() {
|
||||
return ptr_scr_size->offy - (ptr_scr_size->y + 1);
|
||||
return (ptr_scr_size->offy - ptr_scr_size->y) + 1;
|
||||
}
|
||||
|
||||
int _stdcall GetShaderVersion() {
|
||||
@@ -388,7 +389,8 @@ static void Present() {
|
||||
if (ScrollWindowKey != 0 && ((ScrollWindowKey > 0 && KeyDown((BYTE)ScrollWindowKey))
|
||||
|| (ScrollWindowKey == -1 && (KeyDown(DIK_LCONTROL) || KeyDown(DIK_RCONTROL)))
|
||||
|| (ScrollWindowKey == -2 && (KeyDown(DIK_LMENU) || KeyDown(DIK_RMENU)))
|
||||
|| (ScrollWindowKey == -3 && (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT))))) {
|
||||
|| (ScrollWindowKey == -3 && (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT)))))
|
||||
{
|
||||
int winx, winy;
|
||||
GetMouse(&winx, &winy);
|
||||
windowLeft += winx;
|
||||
@@ -474,8 +476,8 @@ void RefreshGraphics() {
|
||||
}
|
||||
for (int d = shadersSize - 1; d >= 0; d--) {
|
||||
if (!shaders[d].Effect || !shaders[d].Active) continue;
|
||||
if (shaders[d].mode2 && !(shaders[d].mode2 & GetCurrentLoops())) continue;
|
||||
if (shaders[d].mode & GetCurrentLoops()) continue;
|
||||
if (shaders[d].mode2 && !(shaders[d].mode2 & GetLoopFlags())) continue;
|
||||
if (shaders[d].mode & GetLoopFlags()) continue;
|
||||
|
||||
if (shaders[d].ehTicks) shaders[d].Effect->SetInt(shaders[d].ehTicks, GetTickCount());
|
||||
UINT passes;
|
||||
@@ -499,7 +501,7 @@ void RefreshGraphics() {
|
||||
gpuBltEffect->BeginPass(0);
|
||||
}
|
||||
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
if (GPUBlt) {
|
||||
if (GPUBlt && !shadersSize) {
|
||||
gpuBltEffect->EndPass();
|
||||
gpuBltEffect->End();
|
||||
}
|
||||
@@ -623,10 +625,10 @@ public:
|
||||
HRESULT _stdcall GetEntries(DWORD, DWORD, DWORD, LPPALETTEENTRY) { UNUSEDFUNCTION; }
|
||||
HRESULT _stdcall Initialize(LPDIRECTDRAW, DWORD, LPPALETTEENTRY) { UNUSEDFUNCTION; }
|
||||
|
||||
HRESULT _stdcall SetEntries(DWORD, DWORD b, DWORD c, LPPALETTEENTRY d) {
|
||||
if (c == 0 || b + c > 256) return DDERR_INVALIDPARAMS;
|
||||
HRESULT _stdcall SetEntries(DWORD, DWORD b, DWORD c, LPPALETTEENTRY destPal) {
|
||||
if (!windowInit || c == 0 || b + c > 256) return DDERR_INVALIDPARAMS;
|
||||
|
||||
CopyMemory(&palette[b], d, c * 4);
|
||||
CopyMemory(&palette[b], destPal, c * 4);
|
||||
if (GPUBlt) {
|
||||
if (gpuPalette) {
|
||||
D3DLOCKED_RECT rect;
|
||||
@@ -638,11 +640,12 @@ public:
|
||||
} else {
|
||||
for (DWORD i = b; i < b + c; i++) { // swap color R <> B
|
||||
//palette[i]&=0x00ffffff;
|
||||
BYTE clr = *(BYTE*)((DWORD)&palette[i]);
|
||||
*(BYTE*)((DWORD)&palette[i]) = *(BYTE*)((DWORD)&palette[i] + 2);
|
||||
BYTE clr = *(BYTE*)((DWORD)&palette[i]); // B
|
||||
*(BYTE*)((DWORD)&palette[i]) = *(BYTE*)((DWORD)&palette[i] + 2); // R
|
||||
*(BYTE*)((DWORD)&palette[i] + 2) = clr;
|
||||
}
|
||||
}
|
||||
RefreshGraphics();
|
||||
return DD_OK;
|
||||
}
|
||||
};
|
||||
@@ -1058,6 +1061,13 @@ HRESULT _stdcall FakeDirectDrawCreate2(void*, IDirectDraw** b, void*) {
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
static __declspec(naked) void game_init_hook() {
|
||||
__asm {
|
||||
mov windowInit, 1;
|
||||
jmp palette_init_;
|
||||
}
|
||||
}
|
||||
|
||||
static double fadeMulti;
|
||||
static __declspec(naked) void palette_fade_to_hook() {
|
||||
__asm {
|
||||
@@ -1091,6 +1101,7 @@ void GraphicsInit() {
|
||||
}
|
||||
#undef _DLL_NAME
|
||||
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
|
||||
HookCall(0x44260C, game_init_hook);
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -82,7 +82,7 @@ typedef class UNLSTDframe {
|
||||
}
|
||||
~UNLSTDframe() {
|
||||
if (indexBuff != nullptr)
|
||||
delete[] indexBuff;
|
||||
delete[] indexBuff;
|
||||
}
|
||||
} UNLSTDframe;
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef class UNLSTDfrm {
|
||||
}
|
||||
~UNLSTDfrm() {
|
||||
if (frames != nullptr)
|
||||
delete[] frames;
|
||||
delete[] frames;
|
||||
}
|
||||
} UNLSTDfrm;
|
||||
|
||||
@@ -769,8 +769,8 @@ void _stdcall RefreshHeroBaseArt() {
|
||||
}
|
||||
|
||||
/*
|
||||
// Check fallout paths for file
|
||||
long __stdcall db_file_exist(const char *fileName, DWORD *sizeOut) {
|
||||
// Check fallout file and get file size (result 0 - file exists)
|
||||
long __stdcall db_dir_entry(const char *fileName, DWORD *sizeOut) {
|
||||
__asm {
|
||||
mov edx, sizeOut;
|
||||
mov eax, fileName;
|
||||
@@ -864,19 +864,16 @@ setPath:
|
||||
|
||||
static void __declspec(naked) CheckHeroExist() {
|
||||
__asm {
|
||||
cmp esi, critterArraySize; // check if loading hero art
|
||||
cmp esi, critterArraySize; // check if loading hero art
|
||||
jle endFunc;
|
||||
sub esp, 4;
|
||||
lea edx, [esp]; // size out
|
||||
mov eax, _art_name; // critter art file name address
|
||||
call db_dir_entry_; // check art file exists
|
||||
add esp, 4;
|
||||
cmp eax, -1;
|
||||
jne endFunc;
|
||||
mov eax, _art_name; // critter art file name address (file name)
|
||||
call db_access_; // check art file exists
|
||||
test eax, eax;
|
||||
jnz endFunc;
|
||||
|
||||
// if file not found load regular critter art instead
|
||||
sub esi, critterArraySize;
|
||||
add esp, 4; // drop func ret address
|
||||
add esp, 4; // drop func ret address
|
||||
mov eax, 0x4194E2;
|
||||
jmp eax;
|
||||
endFunc:
|
||||
|
||||
@@ -1422,7 +1422,7 @@ static void LoadHookScript(const char* name, int id) {
|
||||
|
||||
if (fileExist) {
|
||||
sScriptProgram prog;
|
||||
dlog(">", DL_HOOK);
|
||||
dlog("> ", DL_HOOK);
|
||||
dlog(name, DL_HOOK);
|
||||
LoadScriptProgram(prog, name);
|
||||
if (prog.ptr) {
|
||||
@@ -1440,7 +1440,7 @@ static void LoadHookScript(const char* name, int id) {
|
||||
}
|
||||
|
||||
static void HookScriptInit2() {
|
||||
dlogr("Loading hook scripts", DL_HOOK|DL_INIT);
|
||||
dlogr("Loading hook scripts:", DL_HOOK|DL_INIT);
|
||||
|
||||
char* mask = "scripts\\hs_*.int";
|
||||
DWORD *filenames;
|
||||
|
||||
+49
-6
@@ -34,12 +34,12 @@ static DWORD itemFastMoveKey = 0;
|
||||
static DWORD skipFromContainer = 0;
|
||||
|
||||
struct sMessage {
|
||||
DWORD number;
|
||||
DWORD flags;
|
||||
long number;
|
||||
long flags;
|
||||
char* audio;
|
||||
char* message;
|
||||
};
|
||||
static const char* MsgSearch(int msgno, DWORD file) {
|
||||
static const char* MsgSearch(long msgno, DWORD file) {
|
||||
if(!file) return 0;
|
||||
sMessage msg = { msgno, 0, 0, 0 };
|
||||
__asm {
|
||||
@@ -59,7 +59,7 @@ TGameObj* GetActiveItem() {
|
||||
}
|
||||
|
||||
void InventoryKeyPressedHook(DWORD dxKey, bool pressed, DWORD vKey) {
|
||||
if (pressed && reloadWeaponKey && dxKey == reloadWeaponKey && IsMapLoaded() && (GetCurrentLoops() & ~(COMBAT | PCOMBAT)) == 0) {
|
||||
if (pressed && reloadWeaponKey && dxKey == reloadWeaponKey && IsMapLoaded() && (GetLoopFlags() & ~(COMBAT | PCOMBAT)) == 0) {
|
||||
DWORD maxAmmo, curAmmo;
|
||||
TGameObj* item = GetActiveItem();
|
||||
__asm {
|
||||
@@ -651,6 +651,34 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_inven_unwield_hook() {
|
||||
__asm {
|
||||
mov ecx, [eax + 0x64];
|
||||
and ecx, 0x0F000000;
|
||||
cmp ecx, OBJ_TYPE_CRITTER << 24;
|
||||
jne skip;
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_OUT;
|
||||
jz skip;
|
||||
push 0x505AFC; // "But is already Inactive (Dead/Stunned/Invisible)"
|
||||
call debug_printf_;
|
||||
add esp, 4;
|
||||
retn;
|
||||
skip:
|
||||
jmp inven_unwield_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_wield_obj_critter_hook() {
|
||||
__asm {
|
||||
test byte ptr [eax + 0x44], DAM_KNOCKED_OUT;
|
||||
jz skip;
|
||||
mov eax, -1;
|
||||
retn;
|
||||
skip:
|
||||
jmp inven_wield_;
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD DoMoveTimer_Ret = 0x476920;
|
||||
static void __declspec(naked) do_move_timer_hook() {
|
||||
__asm {
|
||||
@@ -679,6 +707,16 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) do_move_timer_hack() {
|
||||
__asm {
|
||||
mov ebx, 1;
|
||||
call GetLoopFlags;
|
||||
test eax, BARTER;
|
||||
cmovz ebx, ebp; // set max when not in barter
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static int invenApCost, invenApCostDef;
|
||||
static char invenApQPReduction;
|
||||
static const DWORD inven_ap_cost_Ret = 0x46E812;
|
||||
@@ -804,7 +842,7 @@ void InventoryInit() {
|
||||
}
|
||||
|
||||
if (GetPrivateProfileIntA("Misc", "ItemCounterDefaultMax", 0, ini)) {
|
||||
BlockCall(0x4768A3); // mov ebx, 1
|
||||
MakeCall(0x4768A3, do_move_timer_hack);
|
||||
}
|
||||
|
||||
// Move items from bag/backpack to the main inventory list by dragging them on the character portrait (similar to Fallout 1 behavior)
|
||||
@@ -817,6 +855,11 @@ void InventoryInit() {
|
||||
if (UseScrollWheel) {
|
||||
MakeCall(0x473E66, loot_container_hack_scroll);
|
||||
MakeCall(0x4759F1, barter_inventory_hack_scroll);
|
||||
*((DWORD*)_max) = 100;
|
||||
*ptr_max = 100;
|
||||
};
|
||||
|
||||
// Check the DAM_KNOCKED_OUT flag for wield_obj_critter/inven_unwield script functions
|
||||
// Note: the flag is not checked for the metarule(METARULE_INVEN_UNWIELD_WHO, x) function
|
||||
HookCall(0x45B0CE, op_inven_unwield_hook);
|
||||
HookCall(0x45693C, op_wield_obj_critter_hook);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ DWORD InDialog() {
|
||||
return (InLoop & DIALOG) ? 1 : 0;
|
||||
}
|
||||
|
||||
DWORD GetCurrentLoops() {
|
||||
DWORD GetLoopFlags() {
|
||||
return InLoop;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ static bool _stdcall LoadGame2_Before() {
|
||||
errorLoad:
|
||||
CloseHandle(h);
|
||||
dlog_f("ERROR reading data: %s\n", DL_MAIN, buf);
|
||||
return (true & !IsDebug);
|
||||
return (true & !isDebug);
|
||||
}
|
||||
|
||||
static void _stdcall LoadGame2_After() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user