#How to replace SQF CfgFunctions in reforger?
1 messages Β· Page 1 of 1 (latest)
Pretty much
But mostly the entry points of CfgFunctions specialized modes
I have limited experience modding in arma 3 but from the wiki it looks like a library of functions - you can have your own library (or libraries) of functions and distribute them as a mod to be used as a dependency in other projects
however it looks like cfgfunctions is loading them from files (dynamically?), which I don't think is possible in script
The former is correct but not really what is the key point I try to replicate
It is the preInit, preStart, postInit which interests me
ah I get you, preInit = mission start before initialization, postInit = after initialization, preStart = after load but before mission start?
Check https://community.bistudio.com/wiki/Arma_3:_Functions_Library the attributes table
Probably explains it better than I ever could
Want to find replacement for documenting it
I think that this exact model is not present in the game, instead you'd have to rely on things like having init happen in a component of your game mode, for example
or inside your own entity if it is present in the world being loaded
additionally, nothing in addons can be executed before the game is loading into a world - mod scripts are compiled at that stage, not before (ie. cannot make a mod that does anything before you join a server/start game)
If you could send a specific example i could try to replicate something identical in reforger to point out similarities/differences. That may be helpful
Will do once I am back home from my parents
So a very basic sample for postInit/preInit (those two are pretty much just would be the following (using sqf functions to ease the sample, just imagine the functions would be implemented):
private _roads = [] call X39_fnc_getRoads;
{
if ([] call X39_fnc_iedChance) then {
[_x] call X39_fnc_createIed;
};
} forEach _roads;
Or one that probably better explains why adding this to every game mode is a chore:
("X39_HudLayer" call BIS_fnc_rscLayer) cutRsc ["X39Hud", "PLAIN"];
[] spawn {
while {true} do {
sleep 1; // Update every second only
[] call X39_fnc_updateHud;
};
};
There is even more things in desperate need of proper "how to entry-point" explaination, but for now the most basic once will do (see https://community.bistudio.com/wiki/Event_Scripts for more entry points about sqf mission eg.)
bumping for relevance
ooo my bad, i've gotten busy with the end of the semester. I'll try to get these soon
π
@meager hollow see this π
I do not think I really get what you want here
can you explain it in a verbose way without SQF samples?
Basically explain what, when and how you want to do things in an abstract way at least
@spare field
There are ways for scripters to introduce similar features that you have in SQF to Enscript, like in here for example
Read the thread for context
it started here
#enfusion_scripting message
Willco in 20 Minutes
Basic goal to me is to allow transitioning from sqf to enscript by finding ways to archive the same.
But as said, will write something proper down later
So, do you want to find direct replacement even if they are extremely wrong (Like the hacky stuff I did in that linked reply) or be guided through the proper ways of doing them but differently of course?
I am fine with both as long as you know the wrong ones are wrong, but tbh these hacky things are nice as they help you understand what can be done as well
But i would advise against using those
For starters, the whole thread actually started here: #enfusion_scripting message
Basically, there is 2 questions left in limbo to me right now:
- How can i make classes/... recognized by the game without having to add them to every game mode explicitly
- How can i make a function run at the start of eg. game mode being loaded (again: without adding it to the game mode explicitly)
For both, a relevant sample of Arma 3 would be eg. https://steamcommunity.com/sharedfiles/filedetails/?id=1638341685
Simply said:
I want to write a biki article on how to transform a modification which applies to the game as a whole (aka: No setup required besides loading the mod) from arma 3 to reforger.
The beauty of CfgFunctions was that it offered an easy way to run scripts from the very moment the main menu was shown, having an "entry point" essentially
Generally speaking, the lack of documented entry points for scripts is kinda an issue to me, personally, right now (eg. Arma 3 has https://community.bistudio.com/wiki/Event_Scripts and https://community.bistudio.com/wiki/Initialization_Order)
All of these are legit questions and totally doable, without any sort of downside and we do it ourselves in certain cases.
I will provide you some samples in a bit with explanations
Just a note
preStart behavior is just not possible, and if it happens to be through some hack then it should be patched
?
Hey sorry, I fell sick so I have not got around to do this yet
Sorry, hope you get well soon

Essentially, the way you can externally access events of entities and components is through ScriptInvoker getters and then insert your function there.
But tbf. your examples could be easily done for any game mode by modding the base game mode entity and adding custom components with the said functionalities, respective modding the relevant HUD functions.
Examples mostly serve the purpose of providing an idea of what might be done for this posting and are not relevant for my long term goals.
First thing to tackle is to provide arma 3 modders (including myself) a way to cope around the new stuff, allowing to have a grounded idea of how to do things when coming from arma 3
Yeah, lack of documentation makes it difficult to switch, but after some time I have the feeling that I got the hang of it and I miss SQF, CfgFunctions not one bit π
So far I mostly add my functionalities by adding components to the game mode. It offers me two entry points: OnPostInit and EOnInit. Sometimes I don't even need these, since the SCR_BaseGameModeComponentClass is really versatile and offers several events I can hook to like when player dies or disconnects and so on.
For instance, this component checks whether a player is far away from the initial respawn point and then deletes it:
https://github.com/Kexanone/EscapeGameMode_AR/blob/main/scripts/Game/GameMode/Components/EM_InitialSpawnPointDeleterComponent.c
And another example that doesn't need EOnInit that makes sure there's only one corpse per player:
https://github.com/Kexanone/EscapeGameMode_AR/blob/main/scripts/Game/GameMode/Components/EM_PlayerCorpseComponent.c
Escape game mode for Arma Reforger inspired by "Escape from Malden" from Arma 3. - EscapeGameMode_AR/EM_InitialSpawnPointDeleterComponent.c at main Β· Kexanone/EscapeGameMode_AR
So you simply add these components to the game mode entity, configure the attributes and that's it.
Neat
Will check that stuff tomorrow in depth
Np, feel free to ask if you need more explanations for some parts π
Those two files are requiring components to be placed if i am seeing this correct
however, i am looking for a way to have something apply to every game mode automatically without having to alter the world itself
You can apply it to every game mode by overriding the game mode prefab
no need to modify the world
Oh wait that's the wrong one π
You have to mod GameMode_Base.et
Then when you place your prefab in the world, you can modify the prefab rather than the instance in the world by changing the object you edit
Given i understood you correctly here, this still requires placement in the world in some way
The goal i have however is to archive the same by just having a mod loaded, no interaction required
The only reason you have to place it in the world editor is to be able to edit the prefab. You can just create some dummy world for that. By editing the prefab rather than the instance, it will be applied to all worlds.
Will toy around with that on the weekend (hopefully ... work is killing me right now) and probably ask a few more questions π
The escape game mode was a bad example on hindsight, since I created a new prefab for that, but I got an example for modding a prefab too: https://github.com/Kexanone/SkipNighttime
In this case I override TimeAndWeatherManager.et in order to add my SCR_SkipNighttimeComponent component to it.
This was one of my first mods, so it doesn't follow the proper tag convention yet. You should use your own prefix instead of SCR
The prefab is placed inside the world (Every world that has a game mode, which is basically every)
So if you mod the prefab by adding a component to it.
The component is also added to all prefabs that inherit from it (other game modes), so now its in all game mode prefabs.
And because every world has some game mode placed, you'll end up with your component in every world
@warm flare @spare field You should stop doing a component every time you want to add a script, a component per every time you want to introduce scripted behavior is not optimal and is not the intended usage of components.
If everyone does this then we end up with entities with hundred or more componennts on them, further slowing FindComponent methods and such. Not to mention huge increases of memory usage if used in certain prefabs.
Use component when it makes sense and when using modded classes is not an option
@spare field In your case, you want to mod a specific class. In this case it is ArmaReforgerScripted
so that you can do the following
modded class ArmaReforgerScripted
{
override event bool OnGameStart()
{
bool returnVal = super.OnGameStart();
// Your logic equivalent to postInit here!.
return returnVal;
}
}
That will add that logic to that game event from the Game (ArmaReforgerScripted imp) class directly from scripts
No need to mess with world editor, no need to create useless components for this case, no messing with entities, etc
In this case, you essentially updated the impl of the OnGameStart() of ArmaReforgerScripted so this will be available everywhere as it's now part of the class itself
Thats super clean actually. I can use this approach in a few places
I think this is not explained in the BIKI if I recall
I will make some tutorials on this
Thanks for the recommendation. I wasn't aware of the severe impact of components. It's a bummer. I really liked the modular nature they offered.
When does OnGameStart get called, when the game is launched? Or when a world has all entities loaded? Something else?
Is this where the gamemode is found and initialized?
Equivalent to post init would mean when the entity and its components have been initialized
So if you mod this script it mods all entities?
yes, all entities that are based on this class and classes that inherit from it
Gotcha
In hopes that this yields a way to emplace CfgFunctions, I am happy to try out whatever is available
Sorry, I completely misinterpreted ArmaReforgerScripted. I thought it was a placeholder, but it's an actual class π
No entity gets modded
Tbh. I'm not entirely happy with this approach. I hardly think it can be the idea to put all the nicely grouped features I had in components in one huge modded ArmaReforgerScripted. I also entirely lose the ability to have configurable attributes.
You don't need to put it into one huge modded class
you can still have many classes, that one there is just the initialization start point
You can put configuration into config file if you want a moddable config
Good call on config files. Might be the solution to regain the modularity π
Well, I'll give it a try and we'll see what MarioE has to complain about it again π
Which is the whole point of this question pretty much.
Finding Init points to replace CfgFunctions
You're asking a bad question
you say "replace CfgFunctions"
which doesn't really make sense.
There are no functions like that in Enforce Script
You meant how to get a init/preInit handler
It does make a lot of sense from the point I try to reason from.
My goal is to provide proper and qualified ways to utilize enscript, replacing sqf.
This means that I do not have any goal but the one which BI should provide in the biki, but does not (yet).
That is where I want to apply my spare time to solve an issue at. However, this includes to naively ask questions in relation to solving problems, from a sqf perspective
Plus, the whole thread only attempts to deal with the question to literally replace CfgFunctions
Wiki has a guide for sqf to enscript, but it doesn't show eventhandler probably
Because I attempt to go the naive way
It's a very relevant question you posed, which I tried to solve with components, but that's apparently not a good apporach. So discussing the best practice is very important.
@spare field That is not convenient or proper in my opinion, they are two different engines and what was good in RV is not good in enfusion
That literally is useless crap, covering (for the most part) object oriented programming
It's better to do things in enfusion the enfusion way instead of the RV way
I would say that it's better to spend the time understanding the new concepts, architecture, etc instead of trying to patch RV's in here
OnGameStart here is the same as postInit
It does not matter what the proper way is as of now. People start with preemptive knowledge, trying to apply sqf to reforger. If that step is not catched, a majority of people is left behind
The part I try to figure out here is not even a complex part
it should be catched and told to not do that
lIke how i am doing with you right now π
You should start a new journey for understanding this engine properly
trying to do RV to Enfusion will just make you do so many wrong assumptions
In particular, it is about transforming information from A to B
If you have questions, then just ask and we will answer
Do not worry about taking it upon yourself
We are working on improving the information i nwiki
Transforming CfgFunctions doesn't really make sense, because nothing of it applies anymore
The transform is rather "forget everything you knew and start from scratch"
Provide how tos, tutorials, etc
This.
Which is why I try to archive the naive knowledge of solving CfgFunctions in reforger for the pleb
So that people can get started on enfusion nicely at some point
We plan on properly introducing proper concepts and workflows, do not worry about that π
Your life would be easier if you just start from scratch here
The entry learning curve for enfusion is so much easier than RV
So do not worry about it and if you have any questions then just ask in the channels or ask me directly
I get your point that you shouldn't try to translate SQF to Enscript directly, but on a fundamental level CfgFunctions contains concepts that are in Enfusion too, like how to define and override functions and entry points.
As said, I attempt to be naive on purpose for that
Which is why the depth I get into enscript involves "does it work out of the box or not"
So I can dive in depth once that question is answered
My personal goal is writing a medical mod for the game
Prior, it is to write guides
They are not 1:1 and the behavior is not the same, we do not have CfgFunctions or similar in enfusion
So it's misleading to do CfgFunctions to Enfusion enscript
fair enough
The question was answered.
"There is no such thing as CfgFunctions, the clostest you get is getting a init event by modding the ArmaReforgerScripted class as shown above"
The qeustion now is, now that you know that, what is your next question
Cool
So enscript and reforger is a failed project
(obviously provoking)
There is a way to Archive the same
If not, that is an issue to be raised
What is your definition of "the same"
If there is a way, that is to be revealed here
You keep saying CfgFunctions, but CfgFunctions is alot of things.
One thing (init event) you have been shown.
if that is not what you were looking for, what other feature is it?
You can do everything you did with CfgFunctions in Enfusion too I would argue, except there's no entry point yet when the game starts π
there is
Pretty sure there is, you just can't load mods in main menu (or not officially-ish)
The same, in this case, as told many times in the lifetime of this thread, is an alternative way to archive the same (that is: a way to intercept regardless of placement akin to CfgFunctions preInit and postinit)
What, the fuck, is "the same" to you
But as modder you have no access to it because of the lock on main menubefore mods are loaded
a way to intercept regardless of placement akin to CfgFunctions preInit and postinit
You want a postInit handler that you can put anywhere, instead of having to put it into a specific place.
That doesn't exist. Ok, next question?
As said, I am in a (on purpose) extremely naive position. Because many modders with brief knowledge are in that position
The whole discussion is a philosophical by now btw. Because I did not try the ways offered yet (due to personal time constraints, right now at a local circus eg. But I ain't being paid or anything... So that is pretty much fine from my personal perspective)
Once I did, I will come back with additional questions
The main point of this thread tho, is to solve the features CfgFunctions offers
So the naive question is:
How to replace CfgFunctions
And yes, this is frustrating... But that is on purpose. Because people coming from sqf are asking those questions
Simply by tossing it away, forgetting about it and learning from scratch
Trying to do connections is not healthy for your learning process for this
"Question"
"Answer"
"No I refuse, I don't accept that answer"
"Question"
Do you really want to keep repeating that circle, I don't get the reasoning.
People from SQF will ask the same question indeed, but they will accept the answer they've been given
as you have seen, you have been stuck on this
while new modders are experienced already
and other arma modders that did not do this have progressed a lot
That is not how learning goes tho. The relation to arma 3 for functions is CfgFunctions
So I need to offer, for my biki article, alternate ways
I know it's hard to get rid of old ways and there is rejection on that but once you get past that, it's just easier and you realize how bad it was before
That is why I am so reluctant on this issue
That is exactly how learning works though.
"Hey I used to open that door with this key, but now it doesn't work anymore and I've been given this plastic card"
"You don't use the key anymore, just hold the plastic card up to this box"
"But no, I want to know how to use my key"
That's what you're doing right now
I have no issue to find replacements
Thought of replacing the rulings with nodded xlasses
But want an naive approach to write the proper article
As said, I did not try those ways as of now
If you have better ways to replace the features, go ahead.
Otherwise, I will try them and continue asking questions then
To write the article.
I would say "CfgFunctions doesn't exist anymore, but there are different ways to do the things that CfgFunctions used to do"
- Adding a postInit eventhandler is now done like so:
- X ...
Now if you have a specific question about a specific part of CfgFunctions that you want to know the new way to, you can ask that, and people can help you with that.
But you keep "no I want it all" "but that doesn't make sense" "but I want it all" then we won't get far
Feel free to write "transitioning from sqf to enscript" articles yourself tho
Will gladly take those solution over spending my own time for obvious reasons
No, as said multiple times by now, not yet tried those ways presented here. But am asking those questions because people usually are neither getting dev time, nor people's time modding for those reasons.
Ok so we are actually done here then for now.
It seemed as if you didn't get an answer yet and still wanted one
And again, would gladly take any tutorial provided by BI, writing eg. Dui squad radar any point in time over my own
Let's first experiment with the solutions that were proposed by MarioE and Dedmen before dragging this out over nothing^^
So with the modding ArmaReforgerScripted approach, what would be the appropriate way to ensure you only execute the code on the server?
My first approach would have been to get the RplComponent of the game mode entity and check whether the machine is the authority
Nvm, there's Replication.IsServer()
IsServer is another question on its own π€ͺ
Funny how modded over component almost sounds like the opposite of composition over inheritance
You can do composition in scripts alone, with modded as well
and you can break composition with components as well
What happens is up to the developer, nothing makes it safe for one or the other
I guess the closest thing is when the game mode starts
but not the game itself
So I came up with an approach to introduce modular scripts to SCR_BaseGameMode without the need of components:
modded class SCR_BaseGameMode : BaseGameMode
{
[Attribute("", UIWidgets.Auto, "", category: "Game Mode")]
protected ref array<ref KEX_GameModeScript> m_KEX_GameModeScripts;
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
foreach (KEX_GameModeScript script : m_KEX_GameModeScripts)
{
script.OnInit(this);
};
};
};
[BaseContainerProps()]
class KEX_GameModeScript
{
void OnInit(SCR_BaseGameMode owner) {};
};
[BaseContainerProps()]
class KEX_MySpecificScript : KEX_GameModeScript
{
[Attribute("0", UIWidgets.EditBox)]
protected float m_fMyVariable;
override void OnInit(SCR_BaseGameMode owner)
{
owner.GetOnPlayerDisconnected().Insert(OnPlayerDisconnected);
// Do stuff
};
void OnPlayerDisconnected(int playerID)
{
// Do stuff
};
};
There is no need for this, the class can be modded multiple times by multiple mods
For example:
// mod A
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
Print("Hello!, I have been called because of mod A.");
};
};
// mod B
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
Print("Hello!, I have been called because of mod B.");
};
};
// mod C
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
Print("Hello!, I have been called because of mod C.");
};
};
When SCR_BaseGameMode::EOnInit gets called it would do all of them so you would get this in the script log
Hello!, I have been called because of mod A.
Hello!, I have been called because of mod B.
Hello!, I have been called because of mod C.
You can add new things to the class with modded
like in this case
// mod A
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
Print("Hello!, I have been called because of mod A.");
};
};
// mod B
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
Print("Hello!, I have been called because of mod B.");
CustomPrint("Hello!, I have been called because of mod B.");
};
void CustomPrint(string content)
{
Print("CustomPrint: " + content);
}
};
// mod C
modded class SCR_BaseGameMode
{
override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
CustomPrint("Hello!, I have been called because of mod C.");
};
};
When SCR_BaseGameMode::EOnInit gets called it would do all of them so you would get this in the script log
Hello!, I have been called because of mod A.
Hello!, I have been called because of mod B.
CustomPrint: Hello!, I have been called because of mod B.
CustomPrint: Hello!, I have been called because of mod C.
same for defining new member variables
and changing constants or static values
Thanks, doing it this way is a good approach when a mod has a singular purpose and hard-coding the changes makes sense, like SkipNighttime. However, what about a case where you might not want that? Let's say you have an utility mod that provides a collection of features you can use to build scenarios like an initial spawn deleter, AI stalking players script and so on. Depending on the type of scenario, you might only need some of them. I don't see how what you suggested offers that flexibility, unless I break the utility mod into a bunch of separate mods for every tiny optional feature.
I just noticed that what I suggested essentially is an inferior version of components. If I introduced a FindScript method, I would be back at square one π
I see your point that doing components in every case introduces an unnecessary overhead, but isn't it the right tool when I want some optionality and if it isn't what would it be instead?
You can separate this modded class and other special behavior in separate classes, idk, perhaps use aspect-oriented programming or composition
Not everything has to be mashed together in the modded class and you can take away features added by other mods as well
It does not work exactly like inheritance
idk exactly what you want to create so I can't really give you hints/tips
If you explain further what you want (As result, not how you want it to work behind the scenes) then I will happily help to possibly find the best route
There is not a single true methodology to make something moddable, it highly depends on your system, feature, etc
It's almost the same as making some system scalable, the way to go depends on many things
So currently I have a bunch of game mode components for the various features for an escape game mode: https://github.com/Kexanone/EscapeGameMode_AR/tree/main/scripts/Game/GameMode/Components
Now I want to create a PvE CTI game mode instead as a new mod. I would like to reuse some of the features I implemented in the escape game mode, for instance, EM_RespawnTimerComponent (Allows modifying respawn timer in mission header) and EM_StalkerComponent (Handles AI that stalk players), but ofc there are some features I don't want in CTI like VictoryBorderComponent (ends game in victory when leaving a polygon area) and EM_SpawnTicketsComponent (introduces global spawn tickets and disables all spawns when no tickets are left).
So my original plan was to create an utility mod that contains all the components I have and I can add the ones that I need to each game mode.
Ofc I'm open to alternative suggestions how to structure my code if components aren't the right choice for what I'm trying to achieve
π, I will check it after work