Globally accessible functions

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Globally accessible functions

Postby Kzer-Za » Sat May 23, 2020 1:38 pm

Can I set a function that can be accessed by all actors, not just the ones inheriting from the actor in which it was defined? I mean, I know how to create a function for a class:

Code: Select allExpand view
Class ClassName : Actor
{
   void SchismHeightClip
   {
      if (prevFloorclip != Floorclip)
         Height = Height - (Floorclip - prevFloorclip);
      prevFloorclip = Floorclip;
   }
...
}


But then this or any other such function can be accessed only by classes that inherit from ClassName. Where can I define functions that need global access, for classes that I can't all inherit from one class?
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby Blue Shadow » Sat May 23, 2020 6:32 pm

Make it a static function. Example:

Code: Select allExpand view
class Blah // Inheriting from Actor isn't necessary.
{
    static void LogActorHealth (Actor other)
    {
        if (other != null)
        {
            Console.Printf("%d", other.health);
        }
    }
}

class DemonY : Demon
{
    States
    
{
    Death:
        // Logs its killer's health.
        SARG A 0 { Blah.LogActorHealth(target); }
        Goto Super::Death;
    }
}

One thing to note is that static functions don't have an implicit caller. That's why you need to pass the actor on which the function is to be executed.
User avatar
Blue Shadow
 
 
 
Joined: 14 Nov 2010
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: ATI/AMD (Modern GZDoom)

Re: Globally accessible functions

Postby 3saster » Sat May 23, 2020 8:54 pm

More specifically, static functions are can be though of as functions that "exist by themselves", and don't rely a particular instance of a class to be used. Thus, you can call them anywhere you like, but because they "exist by themselves", you have to explicitly pass them any variables you want it to use (or they have to be global). Static functions are not unique to ZScript btw; many other programming languages have the concept of static functions or variables.
User avatar
3saster
 
Joined: 11 May 2018
Location: Canada

Re: Globally accessible functions

Postby SanyaWaffles » Sat May 23, 2020 11:01 pm

Static functions are useful to put into a utilities class that you can call from any class. I have one in DD2 that's slowly being built for stuff I use across multiple classes.
User avatar
SanyaWaffles
Navy Did Nothing Wrong
 
Joined: 25 Apr 2013
Location: Eastern Ohio
Discord: SanyaWaffles#5095
Twitch ID: sanyawaffles
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Globally accessible functions

Postby Kzer-Za » Sat May 23, 2020 11:31 pm

Thanks!

But I'm having difficulties with accessing user variables from a static function. Using the same function as in my first post, that adjusts the actor's height when it is clipped into the floor: I need to access a variable "prevFloorclip" in actor "other", so I need to define a variable other2 with the class of this actor. Since I don't know the class (the whole point of creating a global function, to acces it from any class), I try to get the class name. But something is not working. Here is the code:

Code: Select allExpand view
Class SchLib : Actor
{
   int prevFloorclip;
   
   static void SchismHeightClip(Actor other)
   {
      if (other != null)
      {
         name OtherClassName = other.GetClassName();
         
         let other2 = OtherClassName(other);
         
         if (other2.prevFloorclip != other2.Floorclip)
            other2.Height = other2.Height - (other2.Floorclip - other2.prevFloorclip);
         other2.prevFloorclip = other2.Floorclip;
      }
   }
}


And I get an error

Code: Select allExpand view
Call to unknown function 'OtherClassName'
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby SanyaWaffles » Sun May 24, 2020 1:06 am

I don't think this will work either but did you try this?

Code: Select allExpand view
         Class<Actor> OtherClassName = other.GetClassName();
         
         let other2 = OtherClassName(other);
         
         if (other2.prevFloorclip != other2.Floorclip)
            other2.Height = other2.Height - (other2.Floorclip - other2.prevFloorclip);
         other2.prevFloorclip = other2.Floorclip;


I dunno if there's a way to cast stuff dynamically like this.
User avatar
SanyaWaffles
Navy Did Nothing Wrong
 
Joined: 25 Apr 2013
Location: Eastern Ohio
Discord: SanyaWaffles#5095
Twitch ID: sanyawaffles
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Globally accessible functions

Postby Kzer-Za » Sun May 24, 2020 1:26 am

Still the same error :(
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby Cherno » Sun May 24, 2020 5:34 am

Code: Select allExpand view
 name OtherClassName = other.GetClassName();
         
         let other2 = OtherClassName(other);


This means that a new variable of type "name" called "OtherClassName" is initialized.
Then another variable called "other2" is initialized and assigned the return value of the function "OtherClassName" with the parameter of other passed.

See why this doesn't work? the compiler tells you the right thing; OtherClassName is not a function, but you try to use it as one. You want to cast other as other's class, but it won't work like this (by the way, GetClassName does not return a class). Actually, IO am not sure why you would want to do this anyway, since you are only accessing base actor variables like prevFloorclip, so you can just do away with other2 and access otehr directly.
User avatar
Cherno
 
Joined: 06 Dec 2016

Re: Globally accessible functions

Postby Kzer-Za » Sun May 24, 2020 6:57 am

Cherno wrote:so you can just do away with other2 and access otehr directly.


But how? From this topic viewtopic.php?f=122&t=68669 I got the impression that I can't. And indeed, if I try this:

Code: Select allExpand view
Class SchLib : Actor
{
   static void SchismHeightClip(Actor other)
   {
      if (other)
      {
         if (other.prevFloorclip != other.Floorclip)
            other.Height = other.Height - (other.Floorclip - other.prevFloorclip);
         other.prevFloorclip = other.Floorclip;
      }
   }
}


then I get the error

Code: Select allExpand view
Unknown identifier 'prevFloorclip'


like in the aforementioned topic.
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby _mental_ » Sun May 24, 2020 7:47 am

Either cast other to your base actor class (where prevFloorclip is defined), or change argument type to that class.
_mental_
 
 
 
Joined: 07 Aug 2011

Re: Globally accessible functions

Postby Kzer-Za » Sun May 24, 2020 7:56 am

_mental_ wrote:Either cast other to your base actor class (where prevFloorclip is defined), or change argument type to that class.


Then the whole idea loses its point. If I could inherit all the actors that need this function from one class, I would simply define this function in that class. One variable I can add to actors that inherit from different classes, but the code of the function I want to keep in one place, not in two or three different classes from which it is inherited by the actors that need it. Otherwise, if/when I decide to expand/change that function code I may change it in one class and forget about the other(s). It seems like a bad design to keep one code in more than one place.
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby _mental_ » Sun May 24, 2020 10:14 am

Your approach cannot work by definition because ZScript is a statically-typed language. To access a member, the type of its class must be known at compile time.
_mental_
 
 
 
Joined: 07 Aug 2011

Re: Globally accessible functions

Postby Kzer-Za » Sun May 24, 2020 2:52 pm

So, for now I decided to use PainChance to store the value of the Floorclip during the previous tic, since PainChance is not gonna be used in my mod anyway and it is one of the values that can be accessed directly in any class via other.PainChance.
Kzer-Za
 
Joined: 20 Aug 2017

Re: Globally accessible functions

Postby KeksDose » Mon May 25, 2020 12:55 am

You could wrap your var in a struct or class to get the function with it. Since you allow editing actors, this'll reduce work to just a few easy lines and reuses the same function for all cases. There's also mixins that kinda have the same result, but a potentially great benefit is being able to set default values for your vars.

Code: Select allExpand view
struct HeightClip { // or "mixin class HeightClip"
   double prevFloorclip;
   
   void Tick 
(Actor mo) {
      if(mo && mo.floorclip != prevFloorclip) {
         // ...
      }
   }
}

class Whatever : Actor {
   HeightClip height_clip; // or "mixin HeightClip"
   
   
// You can then set height_clip.prevFloorclip = floorclip and call height_clip.Tick(self) to use your function.
   // If you use a mixin, you can skip writing height_clip. Rename Tick back to SchismHeightClip then haha.
}
User avatar
KeksDose
Praise Mima and the Moon
 
 
 
Joined: 06 Jul 2007

Re: Globally accessible functions

Postby Apeirogon » Mon May 25, 2020 1:26 am

Did you try to use virtual functions? Something like
Code: Select allExpand view
struct struct_data {int i;}

class monsta : actor
{
struct_data data_name;
//set data name somewhere
virtual void get_all_data(in out struct_data var)
{
if(data_name && var) {var.i = var.i;}
}

}

class player : playerpawn
{same as for monsta}

Then just call actors virtual function from static. IIRC you can call virtual functions without explicitly defining class type.
User avatar
Apeirogon
I have a strange sense of humour
 
Joined: 12 Jun 2017

Next

Return to Scripting

Who is online

Users browsing this forum: No registered users and 1 guest