I’ve made a new (and slightly improved) version of the frame timer bundles…
Here’s the normal version:
{"data":{"behavior":{"v":"2","nodes":[{"inputCount":7,"outputCount":2,"name":"Frame Timer","behaviorType":"logic.NodeGroup","x":-180,"y":-32,"id":"cfd3efb195a58f40","notes":"Made by thebrickccentric\n\nIMPORTANT: You MUST connect an Always behavior to the Always input!","n_o":1,"isMenuItem":false},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":96,"group":"cfd3efb195a58f40","id":"cfd3efb1307d8f4e","notes":"Delay - This is measured in frames. 0 delay means that Out# will output on the same frame that Start is input, 1 delay means that Out# will output on the next frame after Start is input, 2 delay means that Out# will output on not the next frame but the one after that, etc.","portId":"cfd3efb195a58f40i0","tag":"Delay","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":160,"group":"cfd3efb195a58f40","id":"cfd3efb1de6e5847","notes":"Repeat - This is how many times you want the timer to output before it stops. 0 Repeat just disables the timer (nothing will output), 1 repeat means the timer will output once, 2 repeat means it will output twice, etc. You CAN input Infinity to the Repeat input if you want the timer to repeat forever.","n_o":0,"portId":"cfd3efb195a58f40i1","tag":"Repeat Count","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":224,"group":"cfd3efb195a58f40","id":"cfd3efb12c07f545","notes":"Pause - Pauses the timer, but does not reset anything.","portId":"cfd3efb195a58f40i2","tag":"Pause","dataType":2},{"expression":"B%(A+1)==0?1:0","default0":1,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":2,"version":2,"tag":"Frame Delay","inputCount":3,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":1080,"y":480,"group":"cfd3efb195a58f40","id":"cfd3efb3a045e34f","notes":"CHANGE THE DEFAULT DELAY HERE (by changing the value of \"A\")","n_o":1},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":1440,"y":448,"group":"cfd3efb195a58f40","id":"cfd3efb4f9a8874d","notes":"Count how many times the timer has output.","startVal":0,"tag":"Output Number","roundMode":1},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":360,"y":416,"group":"cfd3efb195a58f40","id":"cfd3efb4799c1445","notes":"Reset all internal values","startVal":0,"tag":"Reset","roundMode":1},{"inputCount":1,"outputCount":0,"name":"Bundle Output","behaviorType":"logic.NodeGroupOutput","x":1800,"y":256,"group":"cfd3efb195a58f40","id":"cfd3efb4b502df4a","notes":"Out# - This activates only after the same amount of game frames have passed as the value of the Delay input. It counts how many times it is activated and sends that value. The first output is 1, the second output is 2, the third output is 3, etc.","portId":"cfd3efb195a58f40o0","tag":"Out#","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":288,"group":"cfd3efb195a58f40","id":"cfd3efb4f4e41145","notes":"Resume - Starts the timer again right where you left off when Pause was input, and does not change or reset any of the timer's internal values.","portId":"cfd3efb195a58f40i3","tag":"Resume","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":352,"group":"cfd3efb195a58f40","id":"cfd3efb43ecb2b4e","notes":"Reset - Stops the timer from outputting any more, and resets all of the timer's internal values to their default state.","portId":"cfd3efb195a58f40i4","tag":"Reset","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":416,"group":"cfd3efb195a58f40","id":"cfd3efb4fe9b6346","notes":"Start - First, this resets all internal values in the timer. then it begins counting the amount of game frames that pass. Once the amount of frames passed is equal to the Delay input's value, the Out# output will activate.","portId":"cfd3efb195a58f40i5","tag":"Start","dataType":2},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":540,"y":576,"group":"cfd3efb195a58f40","id":"cfd3efb5461a024d","notes":"Pause / Resume Switch","_startVal":1,"dataType":2},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":360,"y":608,"group":"cfd3efb195a58f40","id":"cfd3efb588c7184a","notes":"Start / Reset Switch","_startVal":0,"dataType":2},{"inputCount":1,"outputCount":0,"name":"Bundle Output","behaviorType":"logic.NodeGroupOutput","x":2160,"y":704,"group":"cfd3efb195a58f40","id":"cfd3efb58ba07d44","notes":"Done - This outputs only after Out# has activated the same amount of times as the Repeat Count. It sends a value of 1.","portId":"cfd3efb195a58f40o1","tag":"Done","dataType":2},{"expression":"B==A?1:0","default0":1,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":2,"version":2,"tag":"==Repeat Count?","inputCount":3,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":1620,"y":416,"group":"cfd3efb195a58f40","id":"cfd3efb52fd83a43","notes":"CHANGE THE DEFAULT REPEAT COUNT HERE (by changing the value of \"A\", set to -1 to make the timer repeat forever)","n_o":1},{"expression":"Math.round(Math.max(A,0))","default0":0,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":1,"version":2,"tag":"Nearest Positive Integer","inputCount":2,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":360,"y":192,"group":"cfd3efb195a58f40","id":"cfd3efb52bc37a45","notes":"This ensures that the Repeat Count amount is always positive or 0 and is a whole number (not a decimal, we can't count decimal amount of outputs)"},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":900,"y":512,"group":"cfd3efb195a58f40","id":"cfd3efb567a78946","notes":"Count how many frames have passed","startVal":0,"tag":"Frame Number","roundMode":1},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":720,"y":544,"group":"cfd3efb195a58f40","id":"cfd3efb5aeab024d","notes":"0 Repeat Count Switch","_startVal":1,"dataType":2},{"expression":"Math.round(Math.max(A,0))","default0":0,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":1,"version":2,"tag":"Nearest Positive Integer Excluding 0","inputCount":2,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":360,"y":96,"group":"cfd3efb195a58f40","id":"cfd3efb63ce6c94e","notes":"This ensures that the Delay amount is always positive or 0 and is a whole number (not a decimal; we can't count a decimal amount of frames)"},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":664,"group":"cfd3efb195a58f40","id":"cfd3efb6eb4e5a4f","notes":"Always - REMEMBER TO CONNECT AN ALWAYS BEHAVOR TO THIS INPUT; IT IS HOW THE FRAME TIMER COUNTS FRAMES!","portId":"cfd3efb195a58f40i6","tag":"Always","dataType":2},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":1620,"y":224,"group":"cfd3efb195a58f40","id":"cfd3efb60c8d2d49","notes":"This is so that the final output always happens before \"Done\" outputs","_startVal":1,"dataType":2},{"gateVal":1,"mode":"equal to","inputCount":2,"outputCount":2,"name":"Filter","behaviorType":"logic.logic.Filter2","x":1260,"y":504,"group":"cfd3efb195a58f40","id":"cfd3efb6b6196347","notes":"If the amount of frames passed is equal to the set delay, then output"},{"gateVal":0,"mode":"greater than","inputCount":2,"outputCount":2,"name":"Filter","behaviorType":"logic.logic.Filter2","x":540,"y":200,"group":"cfd3efb195a58f40","id":"cfd3efb60d60ee4b","notes":"If the Repeat Count is 0, then the timer is deactivated"},{"gateVal":1,"mode":"equal to","inputCount":2,"outputCount":2,"name":"Filter","behaviorType":"logic.logic.Filter2","x":1800,"y":464,"group":"cfd3efb195a58f40","id":"cfd3efb6fda49145","notes":"Pass=Out# has been output the same amount fo times as the Repeat input value, so the timer is done"},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":1980,"y":688,"group":"cfd3efb195a58f40","id":"cfd3efb6b9bff642","notes":"This is so that \"Done\" always outputs very last","_startVal":1,"dataType":2},{"inputCount":0,"outputCount":1,"name":"Always","behaviorType":"logic.triggers.Always","x":-360,"y":96,"group":"","id":"cfe77207e879b546"}],"links":[{"input_id":"cfd3efb195a58f40i6","output_id":"cfe77207e879b546o0"},{"input_id":"cfd3efb195a58f40i6","output_id":"cfe77207e879b546o0"},{"input_id":"cfd3efb63ce6c94ei0","output_id":"cfd3efb1307d8f4eo0"},{"input_id":"cfd3efb63ce6c94ei1","output_id":"cfd3efb1307d8f4eo0"},{"input_id":"cfd3efb52bc37a45i0","output_id":"cfd3efb1de6e5847o0"},{"input_id":"cfd3efb52bc37a45i1","output_id":"cfd3efb1de6e5847o0"},{"input_id":"cfd3efb5461a024di0","output_id":"cfd3efb12c07f545o0"},{"input_id":"cfd3efb6b6196347i1","output_id":"cfd3efb3a045e34fo0"},{"input_id":"cfd3efb60c8d2d49i2","output_id":"cfd3efb4f9a8874do0"},{"input_id":"cfd3efb52fd83a43i1","output_id":"cfd3efb4f9a8874do0"},{"input_id":"cfd3efb52fd83a43i2","output_id":"cfd3efb4f9a8874do0"},{"input_id":"cfd3efb4f9a8874di0","output_id":"cfd3efb4799c1445o0"},{"input_id":"cfd3efb567a78946i0","output_id":"cfd3efb4799c1445o0"},{"input_id":"cfd3efb5461a024di1","output_id":"cfd3efb4799c1445o0"},{"input_id":"cfd3efb5461a024di1","output_id":"cfd3efb4f4e41145o0"},{"input_id":"cfd3efb4799c1445i1","output_id":"cfd3efb43ecb2b4eo0"},{"input_id":"cfd3efb588c7184ai0","output_id":"cfd3efb43ecb2b4eo0"},{"input_id":"cfd3efb4799c1445i1","output_id":"cfd3efb4fe9b6346o0"},{"input_id":"cfd3efb588c7184ai1","output_id":"cfd3efb4fe9b6346o0"},{"input_id":"cfd3efb5aeab024di2","output_id":"cfd3efb5461a024do0"},{"input_id":"cfd3efb5461a024di2","output_id":"cfd3efb588c7184ao0"},{"input_id":"cfd3efb6fda49145i1","output_id":"cfd3efb52fd83a43o0"},{"input_id":"cfd3efb60d60ee4bi1","output_id":"cfd3efb52bc37a45o0"},{"input_id":"cfd3efb3a045e34fi1","output_id":"cfd3efb567a78946o0"},{"input_id":"cfd3efb3a045e34fi2","output_id":"cfd3efb567a78946o0"},{"input_id":"cfd3efb567a78946i2","output_id":"cfd3efb5aeab024do0"},{"input_id":"cfd3efb3a045e34fi0","output_id":"cfd3efb63ce6c94eo0"},{"input_id":"cfd3efb588c7184ai2","output_id":"cfd3efb6eb4e5a4fo0"},{"input_id":"cfd3efb4b502df4ai0","output_id":"cfd3efb60c8d2d49o0"},{"input_id":"cfd3efb4f9a8874di2","output_id":"cfd3efb6b6196347o0"},{"input_id":"cfd3efb52fd83a43i0","output_id":"cfd3efb60d60ee4bo0"},{"input_id":"cfd3efb5aeab024di1","output_id":"cfd3efb60d60ee4bo0"},{"input_id":"cfd3efb5aeab024di0","output_id":"cfd3efb60d60ee4bo1"},{"input_id":"cfd3efb4799c1445i1","output_id":"cfd3efb6fda49145o0"},{"input_id":"cfd3efb588c7184ai0","output_id":"cfd3efb6fda49145o0"},{"input_id":"cfd3efb6b9bff642i2","output_id":"cfd3efb6fda49145o0"},{"input_id":"cfd3efb58ba07d44i0","output_id":"cfd3efb6b9bff642o0"}]}}}
Here’s the Repeat Forever version:
{"data":{"behavior":{"v":"2","nodes":[{"inputCount":6,"outputCount":1,"name":"FrameTimer RepeatForever","behaviorType":"logic.NodeGroup","x":-630,"y":-16,"id":"cfd57d4de4a70f42","notes":"Made by thebrickccentric\n\nIMPORTANT: You MUST connect an Always behavior to the Always input!","n_o":1,"isMenuItem":false},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":160,"group":"cfd57d4de4a70f42","id":"cfd57d4edbc8494f","notes":"Delay - This is measured in frames. 0 delay means that Out# will output on the same frame that Start is input, 1 delay means that Out# will output on the next frame after Start is input, 2 delay means that Out# will output on not the next frame but the one after that, etc.","n_o":0,"portId":"cfd57d4de4a70f42i0","tag":"Delay","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":224,"group":"cfd57d4de4a70f42","id":"cfd57d4e08392c4f","notes":"Pause - Pauses the timer, but does not reset anything.","portId":"cfd57d4de4a70f42i1","tag":"Pause","dataType":2},{"expression":"B%(A+1)==0?1:0","default0":30,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":2,"version":2,"tag":"Frame Delay","inputCount":3,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":900,"y":480,"group":"cfd57d4de4a70f42","id":"cfd57d4e1926944f","notes":"CHANGE THE DEFAULT DELAY HERE (by changing the value of \"A\")","n_o":1},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":1260,"y":448,"group":"cfd57d4de4a70f42","id":"cfd57d4e83a2f84a","notes":"Count how many times the timer has output.","startVal":0,"tag":"Output Number","roundMode":1},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":360,"y":416,"group":"cfd57d4de4a70f42","id":"cfd57d4e36820a43","notes":"Reset all internal values","startVal":0,"tag":"Reset","roundMode":1},{"inputCount":1,"outputCount":0,"name":"Bundle Output","behaviorType":"logic.NodeGroupOutput","x":1440,"y":464,"group":"cfd57d4de4a70f42","id":"cfd57d4e045cad40","notes":"Out# - This activates only after the same amount of game frames have passed as the value of the Delay input. It counts how many times it is activated and sends that value. The first output is 1, the second output is 2, the third output is 3, etc.","portId":"cfd57d4de4a70f42o0","tag":"Out#","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":288,"group":"cfd57d4de4a70f42","id":"cfd57d4e354e914a","notes":"Resume - Starts the timer again right where you left off when Pause was input, and does not change or reset any of the timer's internal values.","portId":"cfd57d4de4a70f42i2","tag":"Resume","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":352,"group":"cfd57d4de4a70f42","id":"cfd57d4e47f25544","notes":"Reset - Stops the timer from outputting any more, and resets all of the timer's internal values to their default state.","portId":"cfd57d4de4a70f42i3","tag":"Reset","dataType":2},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":416,"group":"cfd57d4de4a70f42","id":"cfd57d4e4ae0514c","notes":"Start - First, this resets all internal values in the timer. then it begins counting the amount of game frames that pass. Once the amount of frames passed is equal to the Delay input's value, the Out# output will activate.","portId":"cfd57d4de4a70f42i4","tag":"Start","dataType":2},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":540,"y":576,"group":"cfd57d4de4a70f42","id":"cfd57d4ec49d9b42","notes":"Pause / Resume Switch","_startVal":1,"dataType":2},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":360,"y":608,"group":"cfd57d4de4a70f42","id":"cfd57d4f9bff7941","notes":"Start / Reset Switch","_startVal":0,"dataType":2},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":720,"y":528,"group":"cfd57d4de4a70f42","id":"cfd57d4f3eac9e43","notes":"Count how many frames have passed","startVal":0,"tag":"Frame Number","roundMode":1},{"expression":"Math.round(Math.max(A,0))","default0":0,"default1":0,"default2":0,"default3":0,"default4":0,"default5":0,"params":1,"version":2,"tag":"Nearest Positive Integer Excluding 0","inputCount":2,"outputCount":1,"name":"Expression","behaviorType":"logic.logic.Expression","x":360,"y":176,"group":"cfd57d4de4a70f42","id":"cfd57d4fb2cdd648","notes":"This ensures that the Delay amount is always positive or 0 and is a whole number (not a decimal; we can't count a decimal amount of frames)"},{"inputCount":0,"outputCount":1,"name":"Bundle Input","behaviorType":"logic.NodeGroupInput","x":180,"y":664,"group":"cfd57d4de4a70f42","id":"cfd57d4fb0a69a49","notes":"Always - REMEMBER TO CONNECT AN ALWAYS BEHAVOR TO THIS INPUT; IT IS HOW THE FRAME TIMER COUNTS FRAMES!","portId":"cfd57d4de4a70f42i5","tag":"Always","dataType":2},{"gateVal":1,"mode":"equal to","inputCount":2,"outputCount":2,"name":"Filter","behaviorType":"logic.logic.Filter2","x":1080,"y":496,"group":"cfd57d4de4a70f42","id":"cfd57d4fc4da4a49","notes":"If the amount of frames passed is equal to the set delay, then output"},{"inputCount":0,"outputCount":1,"name":"Always","behaviorType":"logic.triggers.Always","x":-810,"y":112,"group":"","id":"cfe79d3672293148"}],"links":[{"input_id":"cfd57d4de4a70f42i5","output_id":"cfe79d3672293148o0"},{"input_id":"cfd57d4de4a70f42i5","output_id":"cfe79d3672293148o0"},{"input_id":"cfd57d4fb2cdd648i0","output_id":"cfd57d4edbc8494fo0"},{"input_id":"cfd57d4fb2cdd648i1","output_id":"cfd57d4edbc8494fo0"},{"input_id":"cfd57d4ec49d9b42i0","output_id":"cfd57d4e08392c4fo0"},{"input_id":"cfd57d4fc4da4a49i1","output_id":"cfd57d4e1926944fo0"},{"input_id":"cfd57d4e045cad40i0","output_id":"cfd57d4e83a2f84ao0"},{"input_id":"cfd57d4e83a2f84ai0","output_id":"cfd57d4e36820a43o0"},{"input_id":"cfd57d4f3eac9e43i0","output_id":"cfd57d4e36820a43o0"},{"input_id":"cfd57d4ec49d9b42i1","output_id":"cfd57d4e36820a43o0"},{"input_id":"cfd57d4ec49d9b42i1","output_id":"cfd57d4e354e914ao0"},{"input_id":"cfd57d4e36820a43i1","output_id":"cfd57d4e47f25544o0"},{"input_id":"cfd57d4f9bff7941i0","output_id":"cfd57d4e47f25544o0"},{"input_id":"cfd57d4e36820a43i1","output_id":"cfd57d4e4ae0514co0"},{"input_id":"cfd57d4f9bff7941i1","output_id":"cfd57d4e4ae0514co0"},{"input_id":"cfd57d4f3eac9e43i2","output_id":"cfd57d4ec49d9b42o0"},{"input_id":"cfd57d4ec49d9b42i2","output_id":"cfd57d4f9bff7941o0"},{"input_id":"cfd57d4e1926944fi1","output_id":"cfd57d4f3eac9e43o0"},{"input_id":"cfd57d4e1926944fi2","output_id":"cfd57d4f3eac9e43o0"},{"input_id":"cfd57d4e1926944fi0","output_id":"cfd57d4fb2cdd648o0"},{"input_id":"cfd57d4f9bff7941i2","output_id":"cfd57d4fb0a69a49o0"},{"input_id":"cfd57d4e83a2f84ai2","output_id":"cfd57d4fc4da4a49o0"}]}}}
Note: you can still make the normal version repeat forever by sending Infinity to the Repeat input, or setting the default value inside the bundle to -1. (The Repeat Forever version just cuts out some of the code that would be used to check if you’ve reached the repeat count)
Also, these and the FPS counter bundle now have their own game: