mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added viewing and modifying local vars for critters to the debug editor.
This commit is contained in:
Generated
+1
@@ -164,6 +164,7 @@
|
||||
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")]
|
||||
|
||||
+43
-12
@@ -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();
|
||||
}
|
||||
|
||||
+29
-2
@@ -596,10 +596,12 @@ 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;
|
||||
@@ -728,7 +730,7 @@ char AnimCodeByWeapon(TGameObj* weapon) {
|
||||
if (weapon != NULL) {
|
||||
char* proto = GetProtoPtr(weapon->pid);
|
||||
if (proto && *(int*)(proto + 32) == item_type_weapon) {
|
||||
return (char)(*(int*)(proto + 36));
|
||||
return (char)(*(int*)(proto + 36));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -742,7 +744,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 {
|
||||
@@ -793,6 +795,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;
|
||||
@@ -801,6 +805,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_;
|
||||
|
||||
+16
-8
@@ -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
|
||||
*
|
||||
*/
|
||||
@@ -618,7 +618,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 +698,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_;
|
||||
@@ -827,10 +827,12 @@ extern const DWORD scr_find_first_at_; // eax - elevation, returns spatial scrip
|
||||
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_;
|
||||
@@ -919,7 +921,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)
|
||||
*/
|
||||
@@ -953,7 +955,7 @@ char* GetProtoPtr(DWORD 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);
|
||||
|
||||
@@ -963,10 +965,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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user