Splitting the Globalscript...

Started by Technocrat, Wed 08/04/2015 11:50:21

Previous topic - Next topic

Technocrat

Hello! Lately I've been having issues compiling the game (dialog table overflow, but that's for another topic), and one of the proposed solutions is to split the globalscript up across other modules. This aspect of it is what I'd like some help with, if that's alright!

So, if I decide to move all of the functions relating to the inventory to their own module (lookats, interacts, etc). I have:
- Created a new module, InvFuncs
- Find function iHand_LookAt
- Cut function from Globalscript, paste it into InvFuncs


Aaaaannnd, that's where I'm stuck. My knowledge of the way modules interact with each other is limited, and based mostly on cargo-cult copying of what others have done before!
From what I understand, the item now no longer knows how/where to find this function anymore. So, if I try to "Look at" the hand, nothing will happen in-game. How can I get the module to communicate with the things that would normally happen in globalscript?

Monsieur OUXX

Well you still need to keep the function in the global script. But from that function, call your module's function.

There would be a way of getting rid of the global script's interaction functions altogether by intercepting the clicks in your module's repeatedly_execute, but that's overkill if you're currently just working around a compiler limitation.
 

Technocrat

Quote from: Monsieur OUXX on Wed 08/04/2015 12:07:05
Well you still need to keep the function in the global script. But from that function, call your module's function.

There would be a way of getting rid of the global script's interaction functions altogether by intercepting the clicks in your module's repeatedly_execute, but that's overkill if you're currently just working around a compiler limitation.


It is a most frustrating limitation. Adding one more sound effect will stop the game working!

Based on what you've said, it might be more sensible for me to take the functions that are particularly silly-complicated, and move them into another module, rather than just saying, blanket, "all inventory functions".

Gurok

#3
For reference, I keep only the essential "stubs" in my global script and have moved everything to separate scripts. Here's what it ends up looking like:

Spoiler

GlobalScript.ash (empty)
Code: ags


GlobalScript.asc
Code: ags
#region GUI Stubs

/* Shared */
function Command_HideModal(GUIControl *a, MouseButton b) { GUI.Command_HideModal(a, b); }
/* gDisambiguate */
function btnDisambiguateOptionA_OnClick(GUIControl *a, MouseButton b) { GDisambiguate.btnDisambiguateOptionA_OnClick(a, b); }
function btnDisambiguateOptionB_OnClick(GUIControl *a, MouseButton b) { GDisambiguate.btnDisambiguateOptionB_OnClick(a, b); }
/* gInventory */
function gInventory_OnClick(GUI *a, MouseButton b) { GInventory.OnClick(a, b); }
function btnInventoryDown_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventoryDown_OnClick(a, b); }
function btnInventoryUp_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventoryUp_OnClick(a, b); }
function btnInventoryOptions_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventoryOptions_OnClick(a, b); }
function btnInventoryProgress_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventoryProgress_OnClick(a, b); }
function btnSwitchToShelly_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventorySwitchToShelly_OnClick(a, b); }
function btnSwitchToSpook_OnClick(GUIControl *a, MouseButton b) { GInventory.btnInventorySwitchToSpook_OnClick(a, b); }
/* gExitToTitle */
function btnExitToTitleYes_OnClick(GUIControl *a, MouseButton b) { GExitToTitle.btnExitToTitleYes_OnClick(a, b); }
function gExitToTitle_OnKeyPress(eKeyCode a) { GExitToTitle.OnKeyPress(a); }
/* Exit to Desktop */
function btnExitToDesktopYes_OnClick(GUIControl *a, MouseButton b) { GExitToDesktop.btnExitToDesktopYes_OnClick(a, b); }
function gExitToDesktop_OnKeyPress(eKeyCode a) { GExitToDesktop.OnKeyPress(a); }
/* gSaveGame */
function btnSaveGameSave_OnClick(GUIControl *control, MouseButton button) { GSaveGame.btnSaveGameSave_OnClick(control, button); }
function lstSaveGame_OnSelectionChanged(GUIControl *control) { GSaveGame.lstSaveGame_OnSelectionChanged(control); }
function btnSaveGameDelete_OnClick(GUIControl *control, MouseButton button) { GSaveGame.btnSaveGameDelete_OnClick(control, button); }
function txtSaveGameName_OnActivate(GUIControl *control) { GSaveGame.txtSaveGameName_OnActivate(control); }
function btnSaveGameListUp_OnClick(GUIControl *control, MouseButton button) { GSaveGame.btnSaveGameListUp_OnClick(control, button); }
function btnSaveGameListDown_OnClick(GUIControl *control, MouseButton button) { GSaveGame.btnSaveGameListDown_OnClick(control, button); }
function gSaveGame_OnKeyPress(eKeyCode keycode) { GSaveGame.OnKeyPress(keycode); }
/* gLoadGame */
function lstLoadGame_OnSelectionChanged(GUIControl *a) { GLoadGame.lstLoadGame_OnSelectionChanged(a); }
function btnLoadGameDelete_OnClick(GUIControl *a, MouseButton b) { GLoadGame.btnLoadGameDelete_OnClick(a, b); }
function btnLoadGameLoad_OnClick(GUIControl *a, MouseButton b) { GLoadGame.btnLoadGameLoad_OnClick(a, b); }
function btnLoadGameListUp_OnClick(GUIControl *a, MouseButton b) { GLoadGame.btnLoadGameListUp_OnClick(a, b); }
function btnLoadGameListDown_OnClick(GUIControl *a, MouseButton b) { GLoadGame.btnLoadGameListDown_OnClick(a, b); }
function gLoadGame_OnKeyPress(eKeyCode a) { GLoadGame.OnKeyPress(a); }
/* gDelete */
function btnDeleteYes_OnClick(GUIControl *a, MouseButton b) { GDelete.btnDeleteYes_OnClick(a, b); }
function gDelete_OnKeyPress(eKeyCode a) { GDelete.OnKeyPress(a); }
/* gOptions */
function btnOptionsCaptions_OnClick(GUIControl *a, MouseButton b) { GOptions.btnOptionsCaptions_OnClick(a, b); }
function sldOptionsSpeech_OnChange(GUIControl *a) { GOptions.sldOptionsSpeech_OnChange(a); }
function sldOptionsMusic_OnChange(GUIControl *a) { GOptions.sldOptionsMusic_OnChange(a); }
function sldOptionsSpeed_OnChange(GUIControl *a) { GOptions.sldOptionsSpeed_OnChange(a); }
function btnOptionsExitToTitle_OnClick(GUIControl *a, MouseButton b) { GOptions.btnOptionsExitToTitle_OnClick(a, b); }
function btnOptionsExitToDesktp_OnClick(GUIControl *a, MouseButton b) { GOptions.btnOptionsExitToDesktop_OnClick(a, b); }
function btnOptionsSaveGame_OnClick(GUIControl *control, MouseButton button) { GOptions.btnOptionsSaveGame_OnClick(control, button); }
function btnOptionsLoadGame_OnClick(GUIControl *a, MouseButton b) { GOptions.btnOptionsLoadGame_OnClick(a, b); }
/* gProgress */
function gProgress_OnKeyPress(eKeyCode a) { GProgress.OnKeyPress(a); }
function btnProgress_OnClick(GUIControl *a, MouseButton b) { GProgress.btnProgress_OnClick(a, b); }
/* gHelp */
function gHelp_OnClick(GUI *a, MouseButton b) { GHelp.OnClick(a, b); }

#endregion

#region Character Stubs

/* cShelly */
function cShelly_Talk() { CShelly.Talk(); }
function cShelly_Auxiliary() { CShelly.Auxiliary(); }
function cShelly_Look() { CShelly.Look(); }
function cShelly_Interact() { CShelly.Interact(); }
function cShelly_UseInv() { CShelly.UseInv(); }
/* cSpook */
function cSpook_Talk() { CSpook.Talk(); }
function cSpook_Auxiliary() { CSpook.Auxiliary(); }
function cSpook_Look() { CSpook.Look(); }
function cSpook_Interact() { CSpook.Interact(); }
function cSpook_UseInv() { CSpook.UseInv(); }
/* cJeanette */
function cJeanette_UseInv() { CJeanette.UseInv(); }
function cJeanette_Talk() { CJeanette.Talk(); }
/* cAubrey */
function cAubrey_Talk() { CAubrey.Talk(); }

#endregion

#region Inventory Stubs

/* iBottleOfWater */
function iBottleOfWater_Interact() { IBottleOfWater.Interact(); }
/* iContract */
function iContract_UseInv() { Inventory.Combine(iContract, player.ActiveInventory); }
/* iManicureSet */
function iManicureSet_Look() { IManicureSet.Look(); }
/* iPoleWithNet */
function iPoleWithNet_Look() { IPoleWithNet.Look(); }
function iPoleWithNet_Interact() { IPoleWithNet.Interact(); }
function iPoleWithNet_OtherClick() { IPoleWithNet.Auxiliary(); }
/* iPole */
function iPole_UseInv() { Inventory.Combine(iPole, player.ActiveInventory); }
/* iNet */
function iNet_UseInv() { Inventory.Combine(iNet, player.ActiveInventory); }
/* iHiCal */
function iHiCal_UseInv() { Inventory.Combine(iHiCal, player.ActiveInventory); }

#endregion

#region Global Object Stubs

/* oManicureSet */
function oManicureSet_Look() { OManicureSet.Look(); }
function oManicureSet_Interact() { OManicureSet.Interact(); }
/* oRustyScissors */
function oRustyScissors_Look() { ORustyScissors.Look(); }
function oRustyScissors_Interact() { ORustyScissors.Interact(); }

#endregion

#region Automatic Stubs

function dialog_request(int a) { }

#endregion
[close]

This may or may not help you with your __DialogScripts.asc problem. If you reduce the number of entries in GlobalScripts.ash, that *might* help as the symbol table is part-populated by symbols in all preceding .ash files and __DialogScripts.asc is the last thing compiled. However, you'll be polluting those earlier .ash files with more entries for any moved functions and it's all a bit pointless. I still think it would be more fruitful for you to remove chunks of dialogue from your dialogue scripts and replace them with calls to functions located in separate modules. This will actually reduce the number of unique symbols in __DialogScripts.asc specifically. In particular, look for long conversations with complex interactions that you can convert, e.g.:

Code: ags
@1
E: Hey
B: Hey
E: Wassup?
B: Not much, you?
  cErnie.ShakeHandsWith(cBert);
  cErnie.WalkTo(99, 99);
  cErine.ChangeView(ERNIESITTING);
E: Wassup?
B: Not much, you?
E: Wassup?
B: Not much, you?
E: Wassup?
B: Not much, you?
E: Okay then, bye.


Becomes:

Response:
Code: ags
@1
  DoWassupDialogue();


ExtraDialogue.ash
Code: ags
import function DoWassupDialogue();


ExtraDialogue.asc
Code: ags
function DoWassupDialogue()
{
    cErnie.Say("Hey");
    cBert.say("Hey");
    ... etc.
}


Just a word of warning, this isn't without pitfalls either. I would recommend moving your largest dialogue response to a separate function and seeing if that alleviates the symbol table overflow. If it does, proceed and add sounds until you run into the symbol table overflow problem again and repeat the process. Each moved function will eliminate some symbol space used directly by __DialogScript.asc but add a small number of symbols to the symbol space inherited by all proceeding scripts.

I did a lot of investigation into this recently. Almost half of the symbol space is used by default symbols (e.g. +, *, -, =, function, while, ProcessClick, etc.) and trying to reorganise things around the limit can get tedious fast. I would really recommend upgrading to 3.4 which removes this limit, but I'm guessing you're too far along.
[img]http://7d4iqnx.gif;rWRLUuw.gi

Monsieur OUXX

#4
Quote from: Technocrat on Wed 08/04/2015 12:14:31
Based on what you've said, it might be more sensible for me to take the functions that are particularly silly-complicated, and move them into another module, rather than just saying, blanket, "all inventory functions".

As a reminder, the core issue is the number of symbols. Symbols include parameter names, function names, etc. So yes, focusing on the complicated functions is essential, but sometimes even moving simple functions reduces the number of symbols.

Also, Gurok is right about the dialogs. Id idn't know that dialogs were silently embedded into the global script.

 

Technocrat

Quote from: Gurok on Wed 08/04/2015 12:46:03
WassupDialogue

Wow, this solution has been extremely successful so far! I moved one topic from one dialogue (granted, a big one) into its own script, and the game's compiling properly!

If we didn't only have a month before release, I'd probably go for 3.4, but this is working brilliantly for the moment! Many thanks!

SMF spam blocked by CleanTalk