Static variables

Discussions about Coding and Scripting
1337GameDev
Experienced
Posts: 85
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Static variables

Post by 1337GameDev » Fri Nov 06, 2020 10:38 pm

I'm curious in unrealscript supports static variables.

I have a hud Mutator I made, and want to have a static variable that's shared amongst all instances.

Do I instead have to manage this myself or create a Singleton?

I would prefer not to if there's a way around that.

User avatar
Barbie
Godlike
Posts: 2069
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Static variables

Post by Barbie » Fri Nov 06, 2020 10:46 pm

I see you run into the same issues as I did years ago... :confused2:
I have solved that with

Code: Select all

// Don't edit this file! 
// Automatically created by Version.cmd at 07.10.2020 13:04:53,08 
class BarbiesWorldVersion extends Object; 
static function int GetBarbiesWorldVersion() { 
	return 3542; 
}
This "variable" is set from outside UScript by a shell script.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett

1337GameDev
Experienced
Posts: 85
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Static variables

Post by 1337GameDev » Fri Nov 06, 2020 10:58 pm

Hmm, how can i set a static variable from another script? And how is that variable set in a cmd script? Wouldn't you want to use an INI value instead?

User avatar
Barbie
Godlike
Posts: 2069
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Static variables

Post by Barbie » Fri Nov 06, 2020 11:38 pm

I've written a batch script to compile and copy the files. It also creates above mentioned file "BarbiesWorldVersion.uc", which contains the build count.
But in essence it should show you how to use a "variable" (more a constant, eh) within multiple other classes. There it is accessed via

Code: Select all

class'BarbiesWorldVersion'.static.GetBarbiesWorldVersion()
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett

1337GameDev
Experienced
Posts: 85
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Static variables

Post by 1337GameDev » Sat Nov 07, 2020 1:08 am

Barbie wrote:
Fri Nov 06, 2020 11:38 pm
I've written a batch script to compile and copy the files. It also creates above mentioned file "BarbiesWorldVersion.uc", which contains the build count.
But in essence it should show you how to use a "variable" (more a constant, eh) within multiple other classes. There it is accessed via

Code: Select all

class'BarbiesWorldVersion'.static.GetBarbiesWorldVersion()
But this is no different than any other constant.

I can already do this with a static object and method.

How do I make a static variable that I can assign to via another script in game?

User avatar
Feralidragon
Godlike
Posts: 5300
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Static variables

Post by Feralidragon » Sat Nov 07, 2020 1:43 am

@Barbie: He's asking about static variables, those are static methods.

@1337GameDev: Answering your question: kind of.
UnrealScript doesn't have any real concept of static variables, at least in the way you probably know, that is to say that you have no way of declaring a variable as static.

It does however have a different kind of concept that you don't usually find in other languages (unless you use reflection on those to force it out, of course), in which every class variable has 2 types of values: the current value (per instance) and the default value (shared across all instances of the class).

You can access (read and write) the default value this way:

Code: Select all

var int SomeVar; //non-static variable, no different from any other

myVar = default.SomeVar; //read
default.SomeVar = 123; //write
and from another class:

Code: Select all

myVar = class'SomeClass'.default.SomeVar; //read
class'SomeClass'.default.SomeVar = 123; //write
and every instance of the same class will be able to see the same default value, meaning that changing the variable defaults is effectively a way of using these variables as static, thus achieving what you want.

There are a few catches, however:
  • if you set the variable as configurable, the defaults are affected by the configuration files (.ini), and if they're written to, even if you never run SaveConfig or StaticSaveConfig yourself, some other code may inadvertently save these new values back to the configuration file;
  • if you set the variable as localized, the defaults are affected by localization files (.int, as well as each locale variation of this extension);
  • if the package is not unloaded on map change for any reason, the default value won't reset to its actual package default;
  • if your variable is an Actor reference of any kind, there's a bug in the GC where it won't nullify the reference of the Actor object statically set in that variable default when the object is destroyed, eventually causing a crash over that default still referencing a destroyed Actor object (this bug was fixed this week actually, so patch 469b will have this fix already);
  • in a multiplayer environment, if you intend to replicate these values across the network, you cannot, since replication only happens for current values (per instance) and often by comparing with the default value to check if it changed (on the first replication), which may lead you to a different kind of problem if you use the same variable statically and non-statically (sometimes it will replicate, sometimes it might not, depending on the current default value of that variable).
So yeah, technically you can use singletons, and use the defaults as static, but you might run into trouble depending on how you use them, so you might want to contact the patch devs for you to enter the beta testing team and test whatever you want to do using the snapshot with the fix I mentioned above (that kind of testing would also be very welcome, being a very recent fix).

1337GameDev
Experienced
Posts: 85
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Static variables

Post by 1337GameDev » Sat Nov 07, 2020 3:21 am

Feralidragon wrote:
Sat Nov 07, 2020 1:43 am
@Barbie: He's asking about static variables, those are static methods.

@1337GameDev: Answering your question: kind of.
UnrealScript doesn't have any real concept of static variables, at least in the way you probably know, that is to say that you have no way of declaring a variable as static.

It does however have a different kind of concept that you don't usually find in other languages (unless you use reflection on those to force it out, of course), in which every class variable has 2 types of values: the current value (per instance) and the default value (shared across all instances of the class).

You can access (read and write) the default value this way:

Code: Select all

var int SomeVar; //non-static variable, no different from any other

myVar = default.SomeVar; //read
default.SomeVar = 123; //write
and from another class:

Code: Select all

myVar = class'SomeClass'.default.SomeVar; //read
class'SomeClass'.default.SomeVar = 123; //write
and every instance of the same class will be able to see the same default value, meaning that changing the variable defaults is effectively a way of using these variables as static, thus achieving what you want.

There are a few catches, however:
  • if you set the variable as configurable, the defaults are affected by the configuration files (.ini), and if they're written to, even if you never run SaveConfig or StaticSaveConfig yourself, some other code may inadvertently save these new values back to the configuration file;
  • if you set the variable as localized, the defaults are affected by localization files (.int, as well as each locale variation of this extension);
  • if the package is not unloaded on map change for any reason, the default value won't reset to its actual package default;
  • if your variable is an Actor reference of any kind, there's a bug in the GC where it won't nullify the reference of the Actor object statically set in that variable default when the object is destroyed, eventually causing a crash over that default still referencing a destroyed Actor object (this bug was fixed this week actually, so patch 469b will have this fix already);
  • in a multiplayer environment, if you intend to replicate these values across the network, you cannot, since replication only happens for current values (per instance) and often by comparing with the default value to check if it changed (on the first replication), which may lead you to a different kind of problem if you use the same variable statically and non-statically (sometimes it will replicate, sometimes it might not, depending on the current default value of that variable).
So yeah, technically you can use singletons, and use the defaults as static, but you might run into trouble depending on how you use them, so you might want to contact the patch devs for you to enter the beta testing team and test whatever you want to do using the snapshot with the fix I mentioned above (that kind of testing would also be very welcome, being a very recent fix).
Ahhhh.

I've seen this when grepping the source files. I never understood why the defaults would be changed, not this is it.

And damn, I might need replication :/ I might need some kind of Singleton / value store in an Actor for replication.

But I like the idea of using the defaults. Great idea!

And thanks for mentioning the config considerations. I would have been confused when I got to that part.

Speaking of that...
Any easy way / example for making an easy options uwindow for the configurable options for a Mutator, gamemode, weapon, etc?

User avatar
Feralidragon
Godlike
Posts: 5300
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Static variables

Post by Feralidragon » Sat Nov 07, 2020 2:40 pm

Generally speaking, is almost always better to have a single static/default variable pointing to an object, and have that object perform everything you want non-statically (rather than having a full set of static variables in a single class), especially since handling things statically is generally considered an anti-pattern.

In that sense, when it comes to replication, you can do just that: implement a static getter method, and if the default reference is not set yet, then depending on the environment the code is running at (client or server -> NetMode), you can spawn it (server) or perform a foreach AllActors to look up the existing actor (client), that way both sides of the network can statically reference the same actor.

As for UMenu, let me warn you beforehand that the menu systems in UT99 are one of the messiest and most confusing things there, so if you get lost how something connects to what, it's normal. :lol2:

In that sense, the best I can offer you is the source for a mod where I implemented such a menu, so you can use as a reference:
http://www.mediafire.com/file/7iexip635 ... C.rar/file

If you want to see the menus in action, you can download the compiled mod here:
https://www.moddb.com/downloads/nw3-ultra-gore-sse

These menus are Mod menus (when you click the Mod tab at the top bar in the main game screen), which is probably also what you want.

I also have a source with just the menus (included the mod above mostly so you could see them in action in a practical scenario):
http://www.mediafire.com/file/rq72mjl8q ... C.rar/file

These are also very old sources of mine, so it's likely the code could be much better nowadays, but it should at least give you a good idea on how to work with them.