Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Knox on Tue 06/07/2010 16:32:20

Title: Dividing the Global Script...guidelines **SOLVED**
Post by: Knox on Tue 06/07/2010 16:32:20
Hi,

In the manual, I found an entry "Multiple Scripts" which explains that you can break up your Global script into pieces if it starts to get large. Right now mine is about 6000 lines, but this includes many "custom scripts" to manage inventory items, various gameplay elements, etc...

Here is all I could find in that entry that explains what to keep in the GS:
Quote
The main global script still has to contain all the event functions (Look At Character scripts, Interact With Inventory scripts and so forth) and all the GUI handlers (btnSave_Click, etc).

The thing is, Im still not too sure what needs to be in the GS, it just says "and so forth"...for those who have done this already, is it a "trial and error" kind of deal?

"All the event" functions Im not to sure what it means, exactly...GUI handlers, its ok though, I understand that...
Title: Re: Dividing the Global Script...guidelines
Post by: GarageGothic on Tue 06/07/2010 16:48:45
Basically anything that is linked directly from editor (the stuff that is auto-named/generated from the interaction or GUI editor). All the purely scripted stuff such as on_event, rep_exec and of course custom functions that you call from within other functions can be moved to modules. (Of course if you need to call a custom function in a module from the global script, you must first import the function in the module header).
Title: Re: Dividing the Global Script...guidelines
Post by: Knox on Tue 06/07/2010 19:18:08
Ok so whenever something is clicked from the editor that creates a line in the Global Script...should stay there, right?

Is it safe to say pretty much any function with "_onclick" should stay in the GS?

Also, I was thinking of doing this and was wondering if its "a good idea":

Instead of having hundreds of cThisCharacter_Look,  cThisCharacter_Talk, etc...I was thinking of processing everything for hotposts, characters and objects in my "on_mouse_click", something like this:


function on_mouse_click(MouseButton button)
{
    LocationType loctype = GetLocationType(mouse.x, mouse.y);
    if (loctype== eLocationCharacter) doGameResponses(eLocationCharacter);
    else if (loctype== eLocationHotspot) doGameResponses(eLocationHotspot);
    else if (loctype== eLocationObject) doGameResponses(eLocationObject);

}


Then, I would have this in a module:

function doGameResponses(LocationType *loctype)
{
   Character *overCharacter = Character.GetAtScreenXY(mouse.x, mouse.y);
  Object *overObject = Object.GetAtScreenXY(mouse.x, mouse.y);
  Hotspot* overHotspot = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
   if (loctype == eLocationCharacter)
  {
     if (mouse.Mode == emodeLook)
    {
       if (cChar == cEgo) Display ("This is the main character");
       else doUnhandledInv_Character(overCharacter);
     }
     else if (mouse.Mode == emodeTalk)
    {
        //etc...
     }
  }
   else if (loctype == eLocationHotspot)
  {
     //etc...
  }
   else if (loctype == eLocationObject)
  {
     //etc...
  }
}


Then, another module would handle the unhandled "generic" responses like so:

function doUnhandledInv_Character(Character *cChar)
{
  unhandledResponse_Inv = Random(5);
  if (unhandledResponse_Inv == 0) cChar.GSay(String.Format("Hmmm, nope, that %s doesn't look familiar.", sActiveItem));
  else if (unhandledResponse_Inv == 0)
   //...etc....     
}



Is this a "good" way of handling all the possible responses to left clicks for hotspots, objects and characters? I feel I can manage it better in a module so I wont make my GS even bigger than it already is...
Title: Re: Dividing the Global Script...guidelines
Post by: GarageGothic on Tue 06/07/2010 19:51:38
Yeah, only skimmed the code, but it sounds very sensible. I'd probably want to keep room events (hotspots, objects etc.) in the individual room scripts, not just to decrease the number of if-statements but also to be able to refer to them by name rather than number only. You could of course have a similar piece of code in the room script to still avoid the autogenerated scripts but keeping the aforementioned benefits.

Once you've "perfected" your doGameResponse function you could put a doRoomResponse in the default template room file so you don't have to cut-n-paste for every new room.
Title: Re: Dividing the Global Script...guidelines
Post by: Khris on Tue 06/07/2010 21:59:37
I'd probably use one function for each object, hotspot, character and inv item; then leave the former two in the room scripts and move the latter two to a separate script.
In the function, I'd check the mouse mode or used verb and handle it accordingly, then put an else at the end with a call to a custom unhandled function.
Everything is only linked to any_click, save inv items.
This is pretty much exactly how the 9-verb template works, btw.
Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: Knox on Tue 06/07/2010 22:47:36
Nice, thanks for the extra info guys...Im going to use your tips to see what I can do so its as good as possible :)



**EDIT**
Ok I found the solution
Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: Knox on Fri 09/07/2010 15:42:33
Hi,

I was wondering the main reason why you guys would NOT recommend having the hotspots + objects processed in a module rather than in the room scripts? If I dont personally mind using else if's and using
the hotpost/objects .ID or .Name, is it still "ok"?

I guess I personally rather having everything in one location instead of going through all the room scripts, etc...

Here is an example (at the debuggin stage anyways) of the unhandled script for objects (same template for hotspots)


function unhandled_GamePlayResponses_Obj(Object *oObj)
{
  unhandledResponse_Obj = Random(5);
  //LOOK AT OBJECT 1/5
  if (mouse.Mode == eModeLookat)
  {
    Display("Unhandled response...Object: %s", oObj.Name);
  }
  //INTERACT WITH OBJECT 2/5
  else if (mouse.Mode == eModeInteract)
  {
    Display("Unhandled response...Interact with %s", oObj.Name);
  }
  //QUESTION OBJECT 3/5
  else if (mouse.Mode == eModeQuestion)
  {
    Display("Unhandled response...Question %s", oObj.Name);
  }
  //COMMAND OBJECT 4/5
  else if (mouse.Mode == eModeCommand)
  {
    Display("Unhandled response...Command %s", oObj.Name);
  } 
  //USE INVENTORY ITEM/TACTICS ITEM ON OBJECT 5/5
  else if (mouse.Mode == eModeUseinv)
  {
    Display("Active Inventory: %d", player.ActiveInventory.ID);
      //INVENTORY ITEM
      if (unhandledResponse_Obj == 0) Display("rand00 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name);
      else if (unhandledResponse_Obj == 1) Display("Unhandled response...rand01 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name);
      else if (unhandledResponse_Obj == 2) Display("Unhandled response...rand02 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name);
      else if (unhandledResponse_Obj == 3) Display("Unhandled response...rand03 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name);
      else if (unhandledResponse_Obj == 4) Display("Unhandled response...rand04 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name);
      else if (unhandledResponse_Obj == 5) Display("Unhandled response...rand05 Inventory Item \"%s\" on object: %s", sActiveItem, oObj.Name); 
    }
  } 
}

Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: GarageGothic on Fri 09/07/2010 15:49:41
Nah, no problem as long as you're fine with referring to them by ID number rather than script name. That's the only real difference. Personally I like room scripts because then at least I don't break the whole game if I mess up the code, plus it's a shorter script to troubleshoot.
Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: Knox on Fri 09/07/2010 16:32:39
Yeah that IS true though, shorter to debug later...Im going to have to think about this then a bit to make sure...but again, thanks for the help :)
Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: Knox on Fri 09/07/2010 20:05:39
Sorry for the double-post, didnt want to create another topic:

Is a "void" faster or like more efficient than a function that doesnt return anything, but still named (wrongly), a function?

I heard somewhere that its better to rename your functions to "void" if it doesnt return anything because its "better"/faster...

If so, well Id like to pass through all my scripts and rename my returnless functions to voids...how do I know if those functions returns anything...is it safe to say that if I don't see "return blah;" somewhere in the function, I can rename the function to a void?
Title: Re: Dividing the Global Script...guidelines **SOLVED**
Post by: GarageGothic on Sat 10/07/2010 00:26:00
Possibly it's faster, but not to a degree you would notice. I think the main idea is that it's good coding practice to use "void" for functions that don't return a value. And as you said, if the function doesn't contain the word "return", it can safely be marked as void. And obviously don't check for any returned values from a void function (not that it would make any sense to have done so if it never returned anything in the first place) :).