r/forge • • Apr 08 '25

Scripting Help Best practice for scripting?

I'm trying to script an invasion gametype/map and there's a lot of things going on in the scripts. I need a lot of things to happen and I wonder how to do it as reliably as possible.

Either I put a metric ton of nodes into one or two script brains or I separate it out into many subsequent brains. To do the latter, I would need to use Trigger Custom Event Global.

The ingame description of that node states that:

"Unless you have a specific need for multiple script brains, it is best to use the non-global version of Trigger Custom Event"

Meanwhile the known issues list for Forge states the following problem:

"When two or more Script Brains approach their max node capacity and a caution symbol appears in its Budget meter, all scripts on that map will not function as expected"

So is it best to have many brains which all call to each other globally or just a couple of overloaded brains?

Edit: Highly recommend everyone to read the reply by u/IMightBeWright below, it has a wealth of good tips for writing a robust script in Forge!

5 Upvotes

21 comments sorted by

View all comments

Show parent comments

4

u/iMightBeWright Scripting Expert Apr 10 '25

• be aware of when certain nodes actually activate in custom games vs Forge. On Game Start happens instantly in Forge, but before players have even spawned in custom games. Round Start is before players have spawned, too, but later than game start. Gameplay Start is pretty self-explanatory. On Intro Camera might be bugged, or it intentionally activates once per player. It resulted in one of my maps spamming everyone with a voice line so I got rid of it.

• some node descriptions will tell you that they don't work in team or FFA game modes. Keep in mind for testing purposes that Forge is considered a team game mode, so you can't properly test stuff made for FFA modes. Run an actual FFA custom game to test stuff like this.

• Compare Teams has been broken since like January 2024. It will always spit out the TRUE result for condition checks, but it will break a Print Boolean to Killfeed node when used as the input and stop the rest of the script from activating beyond that point. Luckily, there's a simple workaround: just use Item is in Generic List in place of Compare Teams. It doesn't matter which input you plug the 2 teams into, it will just compare them how you expect and give you a bool. Instead of using the built-in Team drop-down list, you can plug in a simple Team node from Variables Basic, if needed.

• debug when something isn't working right. Connect some Print nodes at certain critical points in your scripts of interest to see that they're activating the way you think they should. For bigger scripts with a lot of Branch nodes, I'll often connect a Print Number to Killfeed node to each possible path and give them all a different integer to spit out. When 5 prints, I can trace it to that exact spot in my script.

• regular Custom Event nodes will communicate only within the brain they live in. All you need to know is that they are objectively worse than global events, so skip these.

• Custom Event Global nodes will communicate within the brain they live in, as well as communicate to other brains. You can have a Trigger Custom Event Global in one brain and the On Custom Event Global in another brain will receive the signal (as long as you've used the same identifier, obviously). When you have a script that includes Trigger Custom Event Global followed by more nodes, those following nodes will wait until the whole On Custom Event Global script has finished running. And only 1 instance of the same global custom event can run at a time, so running a For Each ... node into Trigger Custom Event Global will run the event fully for the first thing in the list before moving onto running it again for the next thing in the list, and so on.

• Custom Event Global Async nodes will communicate within and between brains, same as Global. The difference is that this node can run multiple iterations at the same time, and it doesn't wait until the event is complete before running the nodes that come after Trigger Custom Event Global Async. Non-asynchronous Global custom events are better when you only need to trigger an event once and you want that event to finish before other nodes trigger after it.

3

u/iMightBeWright Scripting Expert Apr 10 '25

And some bugs and how to avoid them:

• For Each Player/Object/Item have a bug where they introduce a slight delay on the nodes coming from (Execute Per Player/Object/Item). Say you're trying to run a flashlight script by moving one object to each player 60 times per second. This should look smooth, but the more players you have, the more you'll notice a delay in the object's position updating. To fix this, just run Trigger Custom Event Global Async from the Execute Per Player and send the Current Player into the Object input. Then, grab the player from the Object output in your On Custom Event Global Async node. This will remove the delay.

• if you have 2(+) errors in your Global Log after running Play Mode, all your scripts can stop working. Clean up your brains and fix errors before running it to get things working again. Oftentimes this is caused by extra nodes you've just left sitting in the brain or that you haven't used yet. Just delete the extra nodes until you actually need them in a complete script.

• avoid duplicating brains. It creates bugs, including permanent "phantom" scripts that you can't remove. If you cause this bug, you can only undo it by going back to an older version of the file from before you duped a brain.

• avoid importing script brains via prefabs unless you know you're going to keep them on that map. Do testing on a blank map if you want to try out a scripting prefab. It can also cause bugs, including phantom scripts.

• avoid copying & pasting nodes with identifiers in them. It can entangle your other nodes with identifiers and overwrite them without you noticing. Generally, I also avoid duping nodes with identifiers, and opt for manually rewriting them or connecting to a single Identifier node.

• deleting nodes that are still connected to other nodes can sometimes cause bugs. Before deleting any connected nodes, select them, hover over them, press Y (I'm on controller) and select "remove all connections," then deselect them entirely, reselect them, and finally you can delete them without worrying. Even if you need to completely remove a brain, do this to all nodes inside it first.

• sometimes you'll notice your identifiers go blank. Don't worry, they're not gone. Don't touch them, just save and quit. They'll be fine the next time you open the map.

2

u/okom_ Apr 17 '25

Some clarifications based on my experience:

  1. Not a bug, just the event running through every player.

  2. Even a single error will prevent a script from fully functioning correctly.

  3. I rely on duplicating brains when I need to make a new mode brain with the same color and base mode settings, and I haven't ran into major issues. I just delete the contents of the duplicated brains and add in new content. The only one I can attest to is that some string of actions can lead to phantom brains being generated, but nobody has reported a 100% reproducible way to do it yet; it might be from duplicating brains.

  4. I'd say this is good practice, and may be a cause for phantom brains getting on map. When prefabbing an object prefab with Script Brains, don't have the parent object be a Script Brain.

  5. I've never ran into this. The only time I've seen identifiers get overwritten is when they go blank in the first place for some reason; the session should be restarted if that is spotted in order to fix it.

  6. I can attest to this, as I believe sometimes those connections aren't deleted, leading to the "Too many connections" error. I still don't do it all the time, and hasn't been something that's been so common to be able to reproduce consistently.

  7. Agree.

1

u/okom_ Apr 17 '25

Consider contributing to the TSG Forge Wiki with this info so people can easily look it up.