Thread: Debugger
View Single Post
  #1  
Old 11-28-2009, 09:50 PM
fowlplay4 fowlplay4 is offline
team canada
fowlplay4's Avatar
Join Date: Jul 2004
Location: Canada
Posts: 5,200
fowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond repute
Debugger

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;
    
screenwidth 200;
    
7;

    new 
GuiTextCtrl("Debugger_" title "Text1") {
      
profile GuiBlueTextProfile;
      
height 20;
      
text "Variables";
      
width 46;
      
11;
    }
    new 
GuiScrollCtrl("Debugger_" title "_Scroll") {
      
profile GuiBlueScrollProfile;
      
height 192;
      
hscrollbar "alwaysOff";
      
vscrollbar "dynamic";
      
width 163;
      
5;
      
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;
      
42;
      
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;
      
7;
      
213;
    }
    new 
GuiTextCtrl("Debugger_" title "_Text3") {
      
profile GuiBlueTextProfile;
      
height 20;
      
text "Call";
      
width 17;
      
11;
      
238;
    }
    new 
GuiTextEditCtrl("Debugger_" title "_Call") {
      
profile GuiBlueTextEditProfile;
      
height 20;
      
width 126;
      
42;
      
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(0temp.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") {
        
4;
        
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.
Attached Thumbnails
Click image for larger version

Name:	graal_1259436924.png
Views:	979
Size:	24.2 KB
ID:	49929  
__________________
Quote:

Last edited by fowlplay4; 11-29-2009 at 01:00 AM..
Reply With Quote