"How do I ZScript?"

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.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
Nash
 
 
Posts: 17456
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: ZScript-only "How do I..." thread

Post by Nash »

Courtesy quote:
ZZYZX wrote:
Vaecrius wrote:Thanks!
(I assume "&&(players.mo)" would do the trick? Or do I need to add a !=null after the mo?)

Objects implicitly cast to bool like in C, yes.

Vaecrius wrote:What's the difference between the AddInventory and GiveInventory (and GiveAmmo) functions? Does Add bypass pickup states? Do the first two ignore skill-based ammo doubling?

AddInventory takes an Inventory object (possibly created using Spawn()).
GiveInventory takes a class name.


////////////////////////////////////////////////

ZZYZX wrote:Ok, minus two scripted calls and minus four native calls http://pastebin.com/pmfTPmAq, because 30x slower function call here means noticeably smaller FPS with large usage counts.


And here's ZZYZX's optimized version, tweaked to be blood-splat-friendly. For educational purposes and for anyone else reading this!

[ EDIT: Latest version is here -> viewtopic.php?f=3&t=55073&p=973732#p973732 ]

////////////////////////////////////////////////

NOW! I have an actual, new question.

I'm trying to make SetToSlope() a generic function that any actor can use, so that I don't have to copy/paste that code ten billion times. And no, I can't make a base class because not everything that will use SetToSlope is the same kind of thing - some of them are vehicles, some of them are blood splats/floor grunge, some of them are even monsters. They're all different kinds of things with a lot of different base classes.

I tried this:

Code: Select all

class SetToSlope
{
    static void SetToSlope(void)
    {
        // code
    }
}

// trying it on a monster...
class Z_TestMonster : Z_MonsterBase
{
    override void Tick(void)
    {
        Super.Tick();
        SetToSlope.SetToSlope();
    }
}

// trying it on a blood splat...
class Z_BloodSplat : Z_BloodBase
{
    override void Tick(void)
    {
        Super.Tick();
        SetToSlope.SetToSlope();
    }
}
 
but it doesn't work!!!
Last edited by Nash on Sat Jan 28, 2017 12:06 am, edited 1 time in total.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine

Re: ZScript-only "How do I..." thread

Post by ZZYZX »

How exactly it doesn't work?
You will have to provide a self pointer, like such:

Code: Select all

class Lib
{
  static void SetToSlope(Actor self) { ... }
}
Oh, and replace CurSector with self.CurSector.

And then call it like

Code: Select all

Lib.SetToSlope(self);
in the actor.
Although if you make this a unified function, I'd give it arguments dAng and pitchOffset externally. And call pitchOffset dPitch for readability. 'd' by itself meant diff, while 'f' means floor.
User avatar
Nash
 
 
Posts: 17456
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: ZScript-only "How do I..." thread

Post by Nash »

ZZYZX wrote:Solution
Works perfectly now, thanks! And I took your advice about the name of the variable, and also parameterizing them. Thanks a bunch!!!

Code: Select all

//===========================================================================
//
// GENERIC PHYSICS CLASS
//
//===========================================================================

class Physics
{
    static void AlignToSlope(Actor self, double dAng, double dPitch)
    {
        vector3 fNormal = self.CurSector.FloorPlane.Normal;
        vector2 fNormalP1 = (fNormal.X != 0 || fNormal.Y != 0) ? (fNormal.X, fNormal.Y).Unit() : (0, 0);
        vector2 fNormalP2 = ((fNormal.X, fNormal.Y).Length(), fNormal.Z);
        double fAng = atan2(fNormalP1.Y, fNormalP1.X); // floor angle (not pitch!)
        double fPitch = -atan2(fNormalP2.X, fNormalP2.Y); // floor pitch
        double dDiff1 = sin(fAng - (dAng + dPitch));
        double dDiff2 = cos(fAng - dAng);
        self.Pitch = fPitch * dDiff2 + dPitch;
        self.Roll = fPitch * dDiff1;
        self.Angle = dAng;
    }
}

class Z_BloodSpot : Z_BloodBase
{
    bool bSloped;

    override void Tick()
    {
        if (!bSloped)
        {
            Physics.AlignToSlope(self, self.Angle, 0.f);
            bSloped = true;
        }
        Super.Tick();
    }
}

 
Last edited by Nash on Sat Jan 28, 2017 12:07 am, edited 2 times in total.
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia

Re: ZScript-only "How do I..." thread

Post by Matt »

So how do you... do that? I still don't understand what goes where and why and what "static" means and what can or cannot go into a thing that's "static".

Like, can you post a full example?
User avatar
The Zombie Killer
Posts: 1528
Joined: Thu Jul 14, 2011 12:06 am
Location: Gold Coast, Queensland, Australia

Re: ZScript-only "How do I..." thread

Post by The Zombie Killer »

A static function is a function without a hidden "self" argument, that's pretty much it, in simple terms.
As a result, if you want a static function to perform actions on the caller, you must explicitly pass the caller to the function.
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia

Re: ZScript-only "How do I..." thread

Post by Matt »

So why doesn't this work?

Code: Select all

class Lib{
	static void ShootMissile(actor self,class<Actor> ms="DoomImpBall",double ht=-1){
		if(ht<0) ht=self.height-12; //the real default
		actor prj=Spawn(ms,(pos.x,pos.y,pos.z+ht),ALLOW_REPLACE);
		prj.vel=vel;prj.angle=angle;prj.pitch=pitch;
		prj.target=self;prj.master=self;
		prj.vel+=(prj.speed*cos(pitch)*cos(angle),prj.speed*cos(pitch)*sin(angle),
			prj.speed*sin(-pitch));
	}
}
It gives "Call to unknown function 'Spawn'" and then an error message for all subsequent references to "prj".
User avatar
Ed the Bat
Posts: 3060
Joined: Thu May 03, 2012 1:18 pm
Graphics Processor: nVidia with Vulkan support
Location: Maryland, US

Re: ZScript-only "How do I..." thread

Post by Ed the Bat »

Spawn is a function of the Actor class. Your class, Lib, is not a descendant of Actor, so it has no direct access to Spawn. However, since Spawn is Static, you may call it as Actor.Spawn()
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia

Re: ZScript-only "How do I..." thread

Post by Matt »

Got it working, thanks!

EDIT: So like half the stuff I'm trying gets me "Cannot call non-static function Actor::_____ from here". How do I know whether a function is static?
User avatar
The Zombie Killer
Posts: 1528
Joined: Thu Jul 14, 2011 12:06 am
Location: Gold Coast, Queensland, Australia

Re: ZScript-only "How do I..." thread

Post by The Zombie Killer »

Generally you can check the contents of gzdoom.pk3/zscript/actor.txt and see if the function you're trying to use has the 'static' modifier.
User avatar
Nash
 
 
Posts: 17456
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: ZScript-only "How do I..." thread

Post by Nash »

Very specific question: How do I make a bullet puff of a hitscan's weapon do something different depending on whether it hit a wall, or a ceiling/floor? Is there any mechanics built-in that can detect these situations?
User avatar
The Zombie Killer
Posts: 1528
Joined: Thu Jul 14, 2011 12:06 am
Location: Gold Coast, Queensland, Australia

Re: ZScript-only "How do I..." thread

Post by The Zombie Killer »

Nash wrote:Very specific question: How do I make a bullet puff of a hitscan's weapon do something different depending on whether it hit a wall, or a ceiling/floor? Is there any mechanics built-in that can detect these situations?
There's probably better ways to do it, but I'd use [wiki]GetZAt[/wiki] or [wiki]A_CheckSolidFooting[/wiki] on puff spawn to check if it's on the floor or ceiling.
User avatar
Nash
 
 
Posts: 17456
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: ZScript-only "How do I..." thread

Post by Nash »

The Zombie Killer wrote: There's probably better ways to do it, but I'd use [wiki]GetZAt[/wiki] or [wiki]A_CheckSolidFooting[/wiki] on puff spawn to check if it's on the floor or ceiling.
Okay, this solves the condition filtering... now is there any way to get any information about the LINEDEF that the bullet attack hit? I'm hoping to retrieve the angle of the wall that the bullet just hit.
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia

Re: ZScript-only "How do I..." thread

Post by Matt »

Is it possible to use "target=" to set an actor's target? If not, what should I be using?

I'm trying to get this to work:

Code: Select all

movetarget=spawn("idledummy",pos);

...[in between the movetarget is placed in a position flanking the target]...

//call A_Chase using the movetarget
targbak=target; target=movetarget;
A_Chase(null,null,CHF_NODIRECTIONTURN);
target=targbak;
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49143
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript-only "How do I..." thread

Post by Graf Zahl »

Post more code. That fragment does not tell us enough. A_Chase has some delay counters so doing this just once won't produce much of a result.
User avatar
kodi
 
 
Posts: 1355
Joined: Mon May 06, 2013 8:02 am

Re: ZScript-only "How do I..." thread

Post by kodi »

Nash wrote: Okay, this solves the condition filtering... now is there any way to get any information about the LINEDEF that the bullet attack hit? I'm hoping to retrieve the angle of the wall that the bullet just hit.
Not yet AFAIK.
I guess you could fire a few hitscans in a "+" pattern from right behind the puff (with super tiny offsets) and calculate the angle between those to account for both slopes and wall angles.

Can't wait for it to be possible though, especially the possibility of retrieving the texture of the wall. I'll go into a frenzy of making F.E.A.R style particle effects if/when that becomes possible.

Return to “Scripting”