"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.

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

Postby ZZYZX » Fri Jan 27, 2017 5:49 am

I can do this http://i.imgur.com/QjzNbfm.png
But not sure how to also apply random angle to that.
I know that to rotate it by 90 degrees, I need to swap smth with smth, I think roll with angle. But whatevs.
What order does Doom apply these angles in?

Code currently looks like this
Code: Select allExpand view
class SlopedThing : Candelabra
{
    Default
    {
        +FLATSPRITE;
        //+ROLLCENTER;
    }
   
    private void SetToSlope(double dang)
    {
        vector3 fnormal = CurSector.floorplane.normal;
        if (!CurSector.floorplane.isSlope())
            fnormal = (0, 0, 1);
        vector2 fnormalp1 = (fnormal.x != 0 || fnormal.y != 0) ? (fnormal.x, fnormal.y).Unit() : (0, 0);
        vector2 fnormalp2 = ((fnormal.x, fnormal.y).Length(), fnormal.z);

        self.roll = 0;
        self.angle = atan2(fnormalp1.y, fnormalp1.x);
        self.pitch = -90+atan2(fnormalp2.x, fnormalp2.y);
        //Console.Printf("angles = %.2f, %.2f, %.2f\n", angle, pitch, roll);
    }
   
    override void PostBeginPlay()
    {
        Super.PostBeginPlay();
    }
   
    override void Tick()
    {
        double dang = (level.time*3)%360;
        //dang = 45;
        SetToSlope(dang);
        Super.Tick();
    }
}
User avatar
ZZYZX
le chat du rabbin
 
 
 
Joined: 14 Oct 2012
Location: Ukraine
Discord: ZZYZX#1394
Github ID: jewalky

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

Postby Major Cooke » Fri Jan 27, 2017 9:02 am

For starters it should affect the roll, not the angle. Will experiment.

Graf, does that help?
User avatar
Major Cooke
QZDoom Maintenance Team
 
Joined: 28 Jan 2007

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

Postby Caligari87 » Fri Jan 27, 2017 9:44 am

viewtopic.php?f=3&t=50334

@ZZYZX: I made a little demo here of combining pitch and roll for the playercamera to (kind of) defeat gimbal-lock and make it appear as if the level were "tilted". It's likely very crude compared to what you're doing but perhaps there's a little bit of code in there that would help.

8-)
User avatar
Caligari87
I'm just here for the community
User Accounts Assistant
 
Joined: 26 Feb 2004
Location: Salt Lake City, Utah, USA
Discord: Caligari87#3089

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

Postby Major Cooke » Fri Jan 27, 2017 9:56 am

What we're trying to do is this with the green stickmen.

Image
User avatar
Major Cooke
QZDoom Maintenance Team
 
Joined: 28 Jan 2007

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

Postby Caligari87 » Fri Jan 27, 2017 10:02 am

I know. I'm just offering some math that worked for my use case, which seemed somewhat similar in the general purpose. If it's helpful, great. If not, disregard.

8-)
User avatar
Caligari87
I'm just here for the community
User Accounts Assistant
 
Joined: 26 Feb 2004
Location: Salt Lake City, Utah, USA
Discord: Caligari87#3089

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

Postby ZZYZX » Fri Jan 27, 2017 11:41 am

Ok so I got this horrible geometrical hack based on observing how it rotates :)
Has nothing to do with Caligari's solution though (in fact I didn't even understand what's going on there and why the /50).
http://pastebin.com/6qs9jviW (nevermind Sign, it's unused)

It's a little tiny bit off though (almost unnoticeable). I believe it needs to be upscaled/downscaled by 1.2 or smth.
Also, you probably can make it a shadow by giving it pitch of 90/-90. But it's a little tiny bit off too.
User avatar
ZZYZX
le chat du rabbin
 
 
 
Joined: 14 Oct 2012
Location: Ukraine
Discord: ZZYZX#1394
Github ID: jewalky

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

Postby Major Cooke » Fri Jan 27, 2017 11:48 am

I'm not worried about the shadows. In fact I probably might exclude them because that's going to be a bit costly -- I'd rather wait on GZDoom to support a real light/sun system for that.

Also it works, so I'm not complaining. :P
User avatar
Major Cooke
QZDoom Maintenance Team
 
Joined: 28 Jan 2007

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

Postby Nash » Fri Jan 27, 2017 12:59 pm

ZZYZX wrote:Ok so I got this horrible geometrical hack based on observing how it rotates :)
Has nothing to do with Caligari's solution though (in fact I didn't even understand what's going on there and why the /50).
http://pastebin.com/6qs9jviW (nevermind Sign, it's unused)

It's a little tiny bit off though (almost unnoticeable). I believe it needs to be upscaled/downscaled by 1.2 or smth.
Also, you probably can make it a shadow by giving it pitch of 90/-90. But it's a little tiny bit off too.


Very cool! Can you make a version that would work for things like flat blood splats, etc? I tried messing around by compensating the angle, pitch and roll but can't seem to come up with anything that looks correct...

EDIT:

Code: Select allExpand view

class Z_BloodSpot 
: Z_BloodBase
{
    Default
    
{
        Radius 8;
        RenderStyle "Shaded";
    }

    private void SetToSlope(double dAng)
    {
        vector3 fNormal = CurSector.FloorPlane.Normal;
        if (!CurSector.FloorPlane.isSlope())
        fNormal = (0, 0, 1);
        vector2 fNormalP1 = (fNormal.!= 0 || fNormal.!= 0) ? (fNormal.X, fNormal.Y).Unit() : (0, 0);
        vector2 fNormalP2 = ((fNormal.X, fNormal.Y).Length(), fNormal.Z);
        vector2 angNormal1 = (cos(dAng - 90), sin(dAng - 90)).Unit();
        vector2 angNormal2 = (cos(dAng), sin(dAng)).Unit();
        double dDiff1 = (angNormal1.* fNormalP1.+ angNormal1.* fNormalP1.Y); // dot product
        double dDiff2 = (angNormal2.* fNormalP1.+ angNormal2.* fNormalP1.Y); // dot product
        Self.Pitch = -atan2(fNormalP2.X, fNormalP2.Y) * dDiff2;
        Self.Roll = atan2(fNormalP2.X, fNormalP2.Y);
        Self.Roll *= dDiff1;
        Self.Angle = dAng;
    }

    override void PostBeginPlay()
    {
        Super.PostBeginPlay();
    }

    override void Tick()
    {

        SetToSlope(Angle);
        Super.Tick();
    }

    States
    
{
    Spawn:
        TNT1 A 0 NoDelay A_SpawnItemEx("Z_BloodDrop", flags: BLOOD_FLAGS);
        TNT1 A 1 A_Jump(256, "BloodSpot1", "BloodSpot2", "BloodSpot3", "BloodSpot4");
        Stop;
    BloodSpot1:
        BSPT A 0 A_SetTics(BLOODSPOT_TICS);
        Goto FadeOut;
    BloodSpot2:
        BSPT B 0 A_SetTics(BLOODSPOT_TICS);
        Goto FadeOut;
    BloodSpot3:
        BSPT C 0 A_SetTics(BLOODSPOT_TICS);
        Goto FadeOut;
    BloodSpot4:
        BSPT D 0 A_SetTics(BLOODSPOT_TICS);
        Goto FadeOut;
    FadeOut:
        "####" "#" 2 A_FadeOut(BLOODSPOT_FADEOUTSPEED);
        Loop;
    }
}
 


Image

This works for 3D blood splats. The only difference is I flipped the atan signs for Self.Roll and Self.Pitch, and removed the -90 from the Self.Pitch. Very nice!! Thank you ZZYZX-senpai
User avatar
Nash
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Github ID: nashmuhandes

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

Postby ZZYZX » Fri Jan 27, 2017 1:38 pm

http://pastebin.com/hNGuPrQQ an optimized (?) version without dot product, replaced with AngDiffAs10. That function would compare two angles and return 1 for matching, and -1 for opposite.
User avatar
ZZYZX
le chat du rabbin
 
 
 
Joined: 14 Oct 2012
Location: Ukraine
Discord: ZZYZX#1394
Github ID: jewalky

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

Postby Graf Zahl » Fri Jan 27, 2017 1:49 pm

That's actually de-optimized. If you are out for speed, do not use scripted subfunctions - they are really costly - my profiling showed they take 30x as long to call as a native function call.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

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

Postby ZZYZX » Fri Jan 27, 2017 1:52 pm

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.
Anyway, why do scripted functions lag that much?
User avatar
ZZYZX
le chat du rabbin
 
 
 
Joined: 14 Oct 2012
Location: Ukraine
Discord: ZZYZX#1394
Github ID: jewalky

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

Postby Graf Zahl » Fri Jan 27, 2017 2:04 pm

Where's scripted function calls in there? All those math functions are actually intrinsics. Sure, the operation they perform costs time but they are single opcodes. That function actually has no 'call' opcode whatsoever.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

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

Postby ZZYZX » Fri Jan 27, 2017 2:10 pm

Nowhere, hence minus two :)
I was asking about the previous one, why does scripted vs native CALL (not execution even!) cost more?
User avatar
ZZYZX
le chat du rabbin
 
 
 
Joined: 14 Oct 2012
Location: Ukraine
Discord: ZZYZX#1394
Github ID: jewalky

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

Postby Major Cooke » Fri Jan 27, 2017 2:50 pm

Graf, which would be healthier for speed?

One single function call all the time? (Calls ProcessCooldowns which only performs its stuff if the timer is %3, %2 or %10, all = 0)
Code: Select allExpand view
   override void Tick()
   {
      if (isVoodoo() || health <= 0)
      {
         Super.Tick();
         return;
      }
      
      if (PentaNoiseWait > 0)   PentaNoiseWait--;
      if (level.maptime <= 1)   InitPlayer();
      
      ProcessCooldowns();
      if (GetClass() == "Doom4Player")      UpdateHAM();
      Super.Tick();
   }
   
   void ProcessCooldowns()
   {
                // Use common denominator.
      int timer = level.maptime % 30;
      // No need to check for StaticChargeDrain since the upgrade alone
      // shuts this off.
      if (!(timer % 3))
      {
         if (!CountInv("StaticUpgrade4"))
         {
                if (CountInv("StaticUpgrade3"))
            {   A_TakeInventory("StaticRifleChargingToken",1);   }
            else if (CountInv("StaticUpgrade2"))
            {   A_TakeInventory("StaticRifleChargingToken",2);   }
            else
            {   A_TakeInventory("StaticRifleChargingToken",4);   }
         }
         A_TakeInventory("PlasmaStunBombCounter",1);
         user_lasthp = health + CountInv("BasicArmor");
      }
      
      if (!(timer % 2))
      {
         A_TakeInventory("SGTripleShotTimer",1);
         A_TakeInventory("SGGrenadeTimer",1);
      }
      if (!(timer % 10))
      {
         if (CountInv("GrenadeCooldown"))
         {
            A_TakeInventory("GrenadeCooldown",1);
            if (!CountInv("GrenadeCooldown"))
            {
               A_PlaySound("Doom4/Weapon/Grenade/GrenadeRegen");
            }
         }
      }
   }


Or multiple functions split up over time?

In this version, ProcessCooldown1, 2, and 3 are only called after 3, 2, and 10 tics passed respectively.

Code: Select allExpand view
   int CooldownTimer[3];
   override void Tick()
   {
      if (isVoodoo() || health <= 0)
      {
         Super.Tick();
         return;
      }
      
      if (PentaNoiseWait > 0)   PentaNoiseWait--;
      if (level.maptime <= 1)   InitPlayer();
      
      static const int CooldownCaps[] = { 3, 2, 10 };
      for (int i = 0; i < 3; i++)
      {
         CooldownTimer[i] = (CooldownTimer[i] + 1) % CooldownCaps[i];
      }
      
      if (!CooldownTimer[0])   ProcessCooldown1();
      if (!CooldownTimer[1])   ProcessCooldown2();
      if (!CooldownTimer[2])   ProcessCooldown3();   
      if (GetClass() == "Doom4Player")      UpdateHAM();
      Super.Tick();
   }
   
   void ProcessCooldown1()
   {
      // No need to check for StaticChargeDrain since the upgrade alone
      // shuts this off.
      if (!CountInv("StaticUpgrade4"))
      {
             if (CountInv("StaticUpgrade3"))
         {   A_TakeInventory("StaticRifleChargingToken",1);   }
         else if (CountInv("StaticUpgrade2"))
         {   A_TakeInventory("StaticRifleChargingToken",2);   }
         else
         {   A_TakeInventory("StaticRifleChargingToken",4);   }
      }
      A_TakeInventory("PlasmaStunBombCounter",1);
      user_lasthp = health + CountInv("BasicArmor");
   }
   
   void ProcessCooldown2()
   {
      A_TakeInventory("SGTripleShotTimer",1);
      A_TakeInventory("SGGrenadeTimer",1);
   }
   
   void ProcessCooldown3()
   {
      if (CountInv("GrenadeCooldown"))
      {
         A_TakeInventory("GrenadeCooldown",1);
         if (!CountInv("GrenadeCooldown"))
         {
            A_PlaySound("Doom4/Weapon/Grenade/GrenadeRegen");
         }
      }
   }
User avatar
Major Cooke
QZDoom Maintenance Team
 
Joined: 28 Jan 2007

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

Postby Graf Zahl » Fri Jan 27, 2017 3:23 pm

In that case it really doesn't matter because the native code being called by those subfunctions requires a lot more time than the VM function calls.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

PreviousNext

Return to Scripting

Who is online

Users browsing this forum: MFG38 and 0 guests