Added setting array values for the debug editor.

This commit is contained in:
NovaRain
2019-04-05 12:03:25 +08:00
parent 06bbe3ceb5
commit 563fdddc7e
11 changed files with 126 additions and 72 deletions
+15
View File
@@ -23,6 +23,7 @@
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.Column0 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
@@ -34,6 +35,7 @@
this.bSGlobals = new System.Windows.Forms.Button();
this.bArrays = new System.Windows.Forms.Button();
this.bEdit = new System.Windows.Forms.Button();
this.bCrittersLvar = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
@@ -153,11 +155,23 @@
this.bEdit.UseVisualStyleBackColor = true;
this.bEdit.Click += new System.EventHandler(this.bEdit_Click);
//
// bCrittersLvar
//
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.Name = "bCrittersLvar";
this.bCrittersLvar.Size = new System.Drawing.Size(99, 23);
this.bCrittersLvar.TabIndex = 7;
this.bCrittersLvar.Text = "Local variables";
this.bCrittersLvar.UseVisualStyleBackColor = true;
//
// DebugEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(585, 436);
this.Controls.Add(this.bCrittersLvar);
this.Controls.Add(this.bEdit);
this.Controls.Add(this.bArrays);
this.Controls.Add(this.bSGlobals);
@@ -187,6 +201,7 @@
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
private System.Windows.Forms.DataGridViewTextBoxColumn Column3;
private System.Windows.Forms.Button bCrittersLvar;
}
}
+22 -19
View File
@@ -187,8 +187,9 @@ namespace FalloutClient {
return;
}
if (e.ColumnIndex == 2) {
string str = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
int val;
if (!int.TryParse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), out val)) {
if (str == null || !int.TryParse(str, out val)) {
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = array[e.RowIndex];
} else {
array[e.RowIndex] = val;
@@ -197,8 +198,9 @@ namespace FalloutClient {
connection.WriteInt(val);
}
} else {
string str = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
float val;
if (!float.TryParse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), out val)) {
if (str == null || !float.TryParse(str, out val)) {
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = array[e.RowIndex];
} else {
array[e.RowIndex] = converter.GetAsInt(val);
@@ -226,9 +228,7 @@ namespace FalloutClient {
lenData += lenType[j];
}
byte[] buf = connection.ReadBytes(lenData); // read data
MemoryStream ms=new MemoryStream(buf);
BinaryReader br=new BinaryReader(ms);
ms.Position = 0;
BinaryReader br = new BinaryReader(new MemoryStream(buf));
for (int j = 0; j < strings.Length; j++) {
switch (types[j]) {
case DataType.Int:
@@ -239,19 +239,16 @@ namespace FalloutClient {
break;
case DataType.String:
byte[] bytes = br.ReadBytes(lenType[j]);
strings[j] = System.Text.Encoding.ASCII.GetString(bytes, 0, lenType[j] - 1); //Array.IndexOf<byte>(bytes, 0)
strings[j] = System.Text.Encoding.ASCII.GetString(bytes, 0, Array.IndexOf<byte>(bytes, 0));
break;
}
}
br.Close();
strings = EditorWindow.ShowEditor(null, types, strings, true);
strings = EditorWindow.ShowEditor(this, null, types, strings, connection.ArrayIsMap[i]);
if (strings != null) { // save
/*connection.WriteDataType(DataTypeSend.SetArray);
connection.WriteInt(i);
ms = new MemoryStream(connection.ArrayLengths[i] * connection.ArrayFlag[i]);
BinaryWriter bw=new BinaryWriter(ms);
MemoryStream ms = new MemoryStream(lenData);
BinaryWriter bw = new BinaryWriter(ms);
for (int j = 0; j < strings.Length; j++) {
ms.Position = j * connection.ArrayFlag[i];
switch (types[j]) {
case DataType.Int:
bw.Write(int.Parse(strings[j]));
@@ -260,15 +257,21 @@ namespace FalloutClient {
bw.Write(float.Parse(strings[j]));
break;
case DataType.String:
byte[] bytes=System.Text.Encoding.ASCII.GetBytes(strings[j]);
if (bytes.Length < connection.ArrayFlag[i]) bw.Write(bytes);
else bw.Write(bytes, 0, connection.ArrayFlag[i] - 1);
bw.Write(0);
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(strings[j]);
if (bytes.Length < lenType[j])
bw.Write(bytes);
else
bw.Write(bytes, 0, lenType[j] - 1);
bw.Write((byte)0);
break;
}
}
connection.WriteBytes(ms.GetBuffer(), 0, connection.ArrayLengths[i] * connection.ArrayFlag[i]);
bw.Close();*/
// send data to sfall
connection.WriteDataType(DataTypeSend.SetArray);
connection.WriteInt(i); // index
connection.WriteInt(lenData);
connection.WriteBytes(ms.GetBuffer(), 0, lenData);
bw.Close();
}
}
break;
@@ -309,7 +312,7 @@ namespace FalloutClient {
names[29] = " Outline flags";
names[30] = " Script ID";
names[32] = " Script index";
strings = EditorWindow.ShowEditor(names, types, strings);
strings = EditorWindow.ShowEditor(this, names, types, strings);
if (strings != null) {
MemoryStream ms = new MemoryStream(33 * 4);
BinaryWriter bw = new BinaryWriter(ms);
+1
View File
@@ -109,6 +109,7 @@
this.Controls.Add(this.bCancel);
this.Controls.Add(this.bSave);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.MinimumSize = new System.Drawing.Size(300, 200);
this.Name = "EditorWindow";
this.Text = "Editor Values";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
+2 -2
View File
@@ -28,7 +28,7 @@ namespace FalloutClient {
dataGridView1.ResumeLayout();
}
public static string[] ShowEditor(string[] names, DataType[] types, string[] values, bool isMap = false) {
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)
@@ -51,7 +51,7 @@ namespace FalloutClient {
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
string str = (string)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (CheckInput(types[e.RowIndex], str))
if (str != null && CheckInput(types[e.RowIndex], str))
values[e.RowIndex] = str;
else
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = values[e.RowIndex];
+9
View File
@@ -126,4 +126,13 @@
<metadata name="Column3.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column3.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>
+2 -1
View File
@@ -15,7 +15,8 @@ namespace FalloutClient {
if (args.Length == 1 && args[0] == "-debugedit") {
Application.Run(new DebugEditor(new EditorConnection()));
} else {
throw new Exception("Multiplayer is no longer supported");
MessageBox.Show("The debug editor can only be run from the game.",
"sfall Debug Editor", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
}
+1
View File
@@ -92,6 +92,7 @@ WRAP_WATCOM_FUNC2(void, perk_add_effect, GameObject*, critter, long, perkId)
WRAP_WATCOM_FUNC2(long, perk_can_add, GameObject*, critter, long, perkId)
//WRAP_WATCOM_FUNC2(void, perk_remove_effect, GameObject*, critter, long, perkId)
WRAP_WATCOM_FUNC6(long, pick_death, GameObject*, attacker, GameObject*, target, GameObject*, weapon, long, amount, long, anim, long, hitFromBack)
WRAP_WATCOM_FUNC0(void, process_bk)
WRAP_WATCOM_FUNC0(void, proto_dude_update_gender)
WRAP_WATCOM_FUNC2(long*, queue_find_first, GameObject*, object, long, qType)
WRAP_WATCOM_FUNC2(long*, queue_find_next, GameObject*, object, long, qType)
+2 -1
View File
@@ -180,8 +180,9 @@
#define FO_VAR_retvals 0x43EA7C
#define FO_VAR_rotation 0x631D34
#define FO_VAR_sad 0x530014
#define FO_VAR_script_path_base 0x51C710
#define FO_VAR_scr_size 0x6AC9F0
#define FO_VAR_script_engine_running 0x51C714
#define FO_VAR_script_path_base 0x51C710
#define FO_VAR_scriptListInfo 0x51C7C8
#define FO_VAR_skill_data 0x51D118
#define FO_VAR_slot_cursor 0x5193B8
+53 -44
View File
@@ -30,18 +30,20 @@
namespace sfall
{
#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_EXIT = 254
};
static const char* debugLog = "LOG";
static const char* debugGnw = "GNW";
@@ -55,6 +57,10 @@ struct sArray {
long flag;
};
static void DEGameWinRedraw() {
fo::func::process_bk();
}
static bool SetBlocking(SOCKET s, bool block) {
DWORD d = !block;
ioctlsocket(s, FIONBIO, &d);
@@ -63,13 +69,12 @@ static bool SetBlocking(SOCKET s, bool block) {
static bool InternalSend(SOCKET s, const void* _data, int size) {
const char* data = (const char*)_data;
int upto = 0;
int tmp;
DWORD d;
while (upto < size) {
tmp = send(s, &data[upto], size - upto, 0);
if (tmp > 0) upto += tmp;
else {
d = WSAGetLastError();
int tmp = send(s, &data[upto], size - upto, 0);
if (tmp > 0) {
upto += tmp;
} else {
DWORD d = WSAGetLastError();
if (d != WSAEWOULDBLOCK && d != WSAENOBUFS) return true;
}
}
@@ -79,13 +84,12 @@ static bool InternalSend(SOCKET s, const void* _data, int size) {
static bool InternalRecv(SOCKET s, void* _data, int size) {
char* data = (char*)_data;
int upto = 0;
int tmp;
DWORD d;
while (upto < size) {
tmp = recv(s, &data[upto], size - upto, 0);
if (tmp > 0) upto += tmp;
else {
d = WSAGetLastError();
int tmp = recv(s, &data[upto], size - upto, 0);
if (tmp > 0) {
upto += tmp;
} else {
DWORD d = WSAGetLastError();
if (d != WSAEWOULDBLOCK && d != WSAENOBUFS) return true;
}
}
@@ -93,6 +97,8 @@ static bool InternalRecv(SOCKET s, void* _data, int size) {
}
static void RunEditorInternal(SOCKET &s) {
*(DWORD*)FO_VAR_script_engine_running = 0;
std::vector<DWORD*> vec = std::vector<DWORD*>();
for (int elv = 0; elv < 3; elv++) {
for (int tile = 0; tile < 40000; tile++) {
@@ -105,13 +111,12 @@ static void RunEditorInternal(SOCKET &s) {
}
}
}
int numCritters = vec.size();
int numGlobals = fo::var::num_game_global_vars;
int numMapVars = fo::var::num_map_global_vars;
int numSGlobals = GetNumGlobals();
int numArrays = script::GetNumArrays();
InternalSend(s, &numGlobals, 4);
InternalSend(s, &numMapVars, 4);
InternalSend(s, &numSGlobals, 4);
@@ -120,6 +125,7 @@ static void RunEditorInternal(SOCKET &s) {
GlobalVar* sglobals = new GlobalVar[numSGlobals];
GetGlobals(sglobals);
sArray* arrays = new sArray[numArrays];
script::GetArrays((int*)arrays);
@@ -138,30 +144,30 @@ static void RunEditorInternal(SOCKET &s) {
if (code == CODE_EXIT) break;
int id, val;
switch (code) {
case 0:
case CODE_SET_GLOBAL:
InternalRecv(s, &id, 4);
InternalRecv(s, &val, 4);
fo::var::game_global_vars[id] = val;
break;
case 1:
case CODE_SET_MAPVAR:
InternalRecv(s, &id, 4);
InternalRecv(s, &val, 4);
fo::var::map_global_vars[id] = val;
break;
case 2: // Retrieve Critter
case CODE_GET_CRITTER:
InternalRecv(s, &id, 4);
InternalSend(s, vec[id], 0x84);
break;
case 3: // Set Critter
case CODE_SET_CRITTER:
InternalRecv(s, &id, 4);
InternalRecv(s, vec[id], 0x84);
break;
case 4:
case CODE_SET_SGLOBAL:
InternalRecv(s, &id, 4);
InternalRecv(s, &val, 4);
sglobals[id].val = val;
break;
case 9: // get array values
case CODE_GET_ARRAY: // get array values
{
InternalRecv(s, &id, 4);
DWORD *types = new DWORD[arrays[id].size * 2]; // type, len
@@ -178,22 +184,25 @@ static void RunEditorInternal(SOCKET &s) {
delete[] types;
}
break;
case 10: // set array values
case CODE_SET_ARRAY: // set array values
{
//InternalRecv(s, &id, 4);
//InternalRecv(s, &val, 4);
//char *data = new char[arrays[id].size * arrays[id * 3 + 2]];
//InternalRecv(s, data, arrays[id].size * arrays[id * 3 + 2]);
//script::DESetArray(arrays[id].id, 0, data);
//delete[] data;
InternalRecv(s, &id, 4);
InternalRecv(s, &val, 4); // len data
char *data = new char[val];
InternalRecv(s, data, val);
script::DESetArray(arrays[id].id, nullptr, data);
delete[] data;
}
break;
}
DEGameWinRedraw();
}
SetGlobals(sglobals);
delete[] sglobals;
delete[] arrays;
*(DWORD*)FO_VAR_script_engine_running = 1;
}
void RunDebugEditor() {
@@ -201,13 +210,13 @@ void RunDebugEditor() {
SOCKET sock, client;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) return;
//create the socket
// create the socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
WSACleanup();
return;
}
//bind the socket
// bind the socket
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
@@ -224,7 +233,7 @@ void RunDebugEditor() {
return;
}
//Start up the editor
// Start up the editor
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -242,7 +251,7 @@ void RunDebugEditor() {
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
//Connect to the editor
// Connect to the editor
client = accept(sock, 0, 0);
if (client == SOCKET_ERROR) {
closesocket(sock);
@@ -284,7 +293,7 @@ void DebugModePatch() {
DWORD dbgMode = GetPrivateProfileIntA("Debugging", "DebugMode", 0, ::sfall::ddrawIni);
if (dbgMode) {
dlog("Applying debugmode patch.", DL_INIT);
//If the player is using an exe with the debug patch already applied, just skip this block without erroring
// If the player is using an exe with the debug patch already applied, just skip this block without erroring
if (*((DWORD*)0x444A64) != 0x082327E8) {
SafeWrite32(0x444A64, 0x082327E8); // call debug_register_env_
SafeWrite32(0x444A68, 0x0120E900); // jmp 0x444B8E
+18 -4
View File
@@ -340,10 +340,24 @@ void DEGetArray(int id, DWORD* types, char* data) {
}
}
// those too are not really used yet in FalloutClient (AFAIK) -- phobos2077
void DESetArray(int id, const DWORD* types, const void* data) {
//if (types) memcpy(arrays[id].types, types, arrays[id].len * 4);
//memcpy(arrays[id].data, data, arrays[id].len*arrays[id].datalen);
void DESetArray(int id, const DWORD* types, const char* data) {
int pos = 0;
for (size_t i = 0; i < arrays[id].val.size(); i++) {
auto& arVal = arrays[id].val[i];
switch (arVal.type) {
case DataType::INT:
arVal.intVal = *(long*)(data + pos);
pos += 4;
break;
case DataType::FLOAT:
arVal.floatVal = *(float*)(data + pos);
pos += 4;
break;
case DataType::STR:
strcpy(arVal.strVal, data + pos);
pos += arVal.len;
}
}
}
/*
+1 -1
View File
@@ -161,7 +161,7 @@ int GetNumArrays();
void GetArrays(int* arrays);
void DEGetArray(int id, DWORD* types, char* data);
void DESetArray(int id, const DWORD* types, const void* data);
void DESetArray(int id, const DWORD* types, const char* data);
// creates new normal (persistent) array. len == -1 specifies associative array (map)
DWORD _stdcall CreateArray(int len, DWORD flags);