Well after doing some work in PowerBuilder (I know a lot of IDE's have that kind of functionality as well), I got to use the debugger and breakpoints and found them quite useful.
So I created a debugger class that you can attach to any of your scripts.
PHP Code:
/*
Core Debugger Functions:
Avoid overwriting these functions in your scripts.
- onInitializeDebugger()
- onCreateDebuggerGUI(title)
- onChangeDebuggerScope(obj)
- onDebuggerCall(obj)
- onResumeDebuggingCode(obj)
- onResumingCode()
Debugging Functions:
Call these in your scripts to use the debugger.
- debug_breakPoint(temp.time)
- debug_updateVariables(temp.scope)
*/
//#CLIENTSIDE
function onCreated() {
// Control Debug Access
temp.debuggers = {
"fowlplay4"
};
if (player.account in temp.debuggers) {
onInitializeDebugger();
}
}
function onInitializeDebugger() {
// Initialize Debugger GUI
onCreateDebuggerGUI(this.name);
}
function onCreateDebuggerGUI(title) {
// Creates Simple Debugger GUI
new GuiWindowCtrl("Debugger_" @ title) {
profile = GuiBlueWindowProfile;
clientrelative = true;
clientextent = "173,262";
canmove = true;
canresize = false;
closequery = false;
canminimize = canmaximize = false;
destroyonhide = true;
visible = true;
text = "Debugging:" SPC title;
x = screenwidth - 200;
y = 7;
new GuiTextCtrl("Debugger_" @ title @ "Text1") {
profile = GuiBlueTextProfile;
height = 20;
text = "Variables";
width = 46;
x = 11;
}
new GuiScrollCtrl("Debugger_" @ title @ "_Scroll") {
profile = GuiBlueScrollProfile;
height = 192;
hscrollbar = "alwaysOff";
vscrollbar = "dynamic";
width = 163;
x = 5;
y = 19;
new GuiTextListCtrl("Debugger_" @ title @ "_List") {
profile = GuiBlueTextListProfile;
height = 32;
horizsizing = "width";
width = 159;
temp.varlist = this;
}
}
new GuiTextEditCtrl("Debugger_" @ title @ "_Scope") {
profile = GuiBlueTextEditProfile;
height = 20;
width = 126;
x = 42;
y = 214;
text = "this.";
this.varslist = temp.varlist;
thiso.catchevent(name, "onAction", "onChangeDebuggerScope");
hint = "Press enter to change debugger's variable scope.";
}
new GuiTextCtrl("Debugger_" @ title @ "_Text2") {
profile = GuiBlueTextProfile;
height = 20;
text = "Scope";
width = 31;
x = 7;
y = 213;
}
new GuiTextCtrl("Debugger_" @ title @ "_Text3") {
profile = GuiBlueTextProfile;
height = 20;
text = "Call";
width = 17;
x = 11;
y = 238;
}
new GuiTextEditCtrl("Debugger_" @ title @ "_Call") {
profile = GuiBlueTextEditProfile;
height = 20;
width = 126;
x = 42;
y = 239;
thiso.catchevent(name, "onAction", "onDebuggerCall");
hint = "Press enter to call a certain function in the script.";
}
}
// Populate Variable List
debug_updateVariables();
}
function onChangeDebuggerScope(obj) {
// Clear List
temp.list = obj.varslist;
temp.list.clearrows();
// Determine Scope
temp.scope = obj.text;
temp.scope = temp.scope.ends(".") ? temp.scope : (temp.scope @ ".");
// Locate Variables
temp.variablez = getstringkeys(temp.scope);
// Determine Functions
temp.functionz = this.getfunctions();
// List Variables
for (temp.var: variablez) {
// Filter out Functions
if (temp.var in temp.functionz) continue;
// Get Value of Variable
temp.value = makevar(temp.scope @ temp.var);
// Add Row to Variable List
temp.data = temp.scope @ temp.var @ ": " @ temp.value;
temp.row = list.addrow(0, temp.data);
temp.row.hint = temp.value;
}
}
function onDebuggerCall(obj) {
// Determine Call
temp.call = obj.text;
// Call Object
if (call.starts("on")) this.trigger(call.substring(2), "");
else this.(@call)();
}
function onResumeDebuggingCode(obj) {
// Decrease Window Size
with (makevar("Debugger_" @ thiso.name)) {
height -= 32;
}
// Destroy Button
obj.destroy();
// Resume Code
this.trigger("onResumingCode", "");
}
/*
Halts the script and places the resume button on the
debugger.
temp.time - The length in seconds to halt script for.
If unspecified, defaults to 24 hours.
*/
function debug_breakPoint(temp.time) {
// Check for Debugger Window
if (!isObject("Debugger_" @ this.name)) return;
// Create Resume Button
with (makevar("Debugger_" @ this.name)) {
if (!isObject("Debugger_" @ thiso.name @ "_Resume")) {
height += 32;
new GuiButtonCtrl("Debugger_" @ thiso.name @ "_Resume") {
x = 4;
y = 239 + 22;
width = 164;
text = "Resume Code";
profile = "GuiBlueButtonProfile";
thiso.catchevent(name, "onAction", "onResumeDebuggingCode");
}
}
}
// Update Variable List based on Scope
debug_updateVariables();
// Begin Wait
waitfor(this, "onResumingCode", (temp.time ? temp.time : 3600 * 24));
}
/*
Updates the variable list.
temp.scope - If specified it overwrites the scope in
the text box, and updates accordingly.
*/
function debug_updateVariables(temp.scope) {
// Determine Scope Object
temp.obj_scope = makevar("Debugger_" @ this.name @ "_Scope");
// Update Scope Text if neccesary
temp.obj_scope.text = temp.scope ? temp.scope : temp.obj_scope.text;
// Update Variable List
onChangeDebuggerScope(temp.obj_scope);
}
It's very simple to use, adjust the account access array in the created event of the debugger class so you have access then add the following to the top of your script:
PHP Code:
function onCreated() {
// Assuming you named the class debugger
join("debugger");
}
You can join it on the client-side as well but depending on the method that you use you'll have to update the script twice or reconnect to get the debugger to appear.
If you joined it on the server-side you have to use the following code to remove it:
PHP Code:
function onCreated() {
join("debugger");
leave("debugger");
}
Here's some example usage of what the debugger can do so far:
PHP Code:
function onCreated() {
// Assuming you named the class debugger
join("debugger");
}
//#CLIENTSIDE
function onCreated() {
// Call Example Function
someCrazyScript();
}
function someCrazyScript() {
// Example Code
this.something = 1;
this.lolol = true;
// Pause Script for Debugger
debug_breakPoint();
// Example Code Continued
this.something = 2;
// Update Variable List for Debugger
debug_updateVariables("this.");
}
At the moment it's quite simple but I may look into adding/improving features like:
- Serverside Functionality
- Editing Values in Debugger
- Improved GUI
- External Windows (when the v6 Beta comes)
Here's an image of it in action, I inserted a break point in the script when the player reaches the peak of the jump in my gravity script.