ZScript "Standard Library" - Brainstorming

Post your example zscripts/ACS scripts/etc here.
Forum rules
The Projects forums are only for projects. If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.

Got a cool project idea but nothing else? Put it in the project ideas thread instead!

Projects for any Doom-based engine (especially 3DGE) are perfectly acceptable here too.

Please read the full rules for more details.
User avatar
Xaser
 
 
Posts: 10773
Joined: Sun Jul 20, 2003 12:15 pm

ZScript "Standard Library" - Brainstorming

Post by Xaser »

The idea's been vaguely mentioned before, but it's probably worth opening up a separate discussion channel, so...

Now that ZScript is a thing, there's way less burden on the developers to implement certain types of new features since a vast amount of things that previously required engine development can now be DIY'd in scripting. 'Course, that also means that the burden is now on us as a community to implement these things, and there's liable to be many common problems that folks will wish to solve in script-land.

The Idea: a quasi-official ZScript "Standard Library" would be a cool community project to undertake at some point, and I'm interested to hear what ideas folks may have for such a thing, just to get the ball rolling. I've got a few ideas I'll jot down myself at some point (standardized reloading and synthfire, for instance), but mostly I wanted to open the door for brainstorming.

As a quick word of warning, I'd advise folks interested in actually writing such a library to exercise caution before jumping headlong into things. Doing this correctly is a non-trivial undertaking -- there needs to be a clean, well-documented API and sane versioning/release scheduling, else folks will try and axe-murder you when you publish a version that breaks everything. :P

Anyhow, discuss. Or don't -- I'm a Xaser, not a cop.
Gez
 
 
Posts: 17924
Joined: Fri Jul 06, 2007 3:22 pm

Re: ZScript "Standard Library" - Brainstorming

Post by Gez »

How about a modified item grab function replicating stuff like Smart Scavenger? E.g., you have 47 shells, you move over a shellbox, you know have 50 shells -- but the shellbox is still there and will give up to a full 17 shells the next time. Having such an override function ready to be plugged in would be useful. Same for medikits and why not armors.
User avatar
Nash
 
 
Posts: 17456
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Post by Nash »

I've been preparing a set of minimal ZScript demo WAD set. :D Here's what I have so far:
ZScript examples

Position object to player smoothly
How to iterate through objects
Draw something on the screen
User avatar
kodi
 
 
Posts: 1355
Joined: Mon May 06, 2013 8:02 am

Re: ZScript "Standard Library" - Brainstorming

Post by kodi »

A radial "hitscan" function would be incredibly useful, something that automatically spawns a single puff on any shootable actor within the radius (sight check optional).
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: ZScript "Standard Library" - Brainstorming

Post by Major Cooke »

Xaser wrote:As a quick word of warning, I'd advise folks interested in actually writing such a library to exercise caution before jumping headlong into things. Doing this correctly is a non-trivial undertaking -- there needs to be a clean, well-documented API and sane versioning/release scheduling, else folks will try and axe-murder you when you publish a version that breaks everything. :P
Structs and/or classes with static functions aught to be fine. For example I use the struct TIterator to ease creation of ThinkerIterator so I can stop looking it up so much.

Note this is moreso tailed towards what I need it for so a lot of stuff can be left out.

Code: Select all

// Contains the iterator flags and instructions.
Struct TIteratorProperties
{
    enum EItFlags
    {
        ITF_EXACT =         1,        // Disregard inheritance.
        ITF_NOTID =            1 << 1,    // Ignore actors with a TID.
        ITF_NOSPECIAL =        1 << 2, // Ignore actors with a special.
        
        ITF_SAFE =            ITF_NOTID|ITF_NOSPECIAL,
    };
    
    enum EItInstructions
    {
        ITN_DESTROY =        1,        // Destroy all actors found.
        ITN_LOGCOUNT =        2,        // Displays how many of the actors were found.
    };
}

//------------------------------------------------------------------------------
// TIterator
//
// -- Properties --
// * p             - Contains a copy of accessible flags.
// * caller        - The actor doing the distance check.
//
// -- Functions --
// * (!)ErrorMessage (count)
//        Logs a problem message to console.
//        
// * (!)FindActors (ActorType, instructions, flags, maxcount, dist);
//        Looks for ActorType based on flags and distance, then executes the given
//        instruction.
//
// * Setup (mo)
//        Inserts the caller into the struct so it may run properly.
// 
// * DoFindActors
//        A wrapper function which sets up the iterator itself, and calls 
//        FindActors inside the TIterator struct.
//
// (!) - Private function. Must be called on by another.
//------------------------------------------------------------------------------

Struct TIterator
{
    TIteratorProperties p;
    private Actor caller;
//------------------------------------------------------------------------------
    private void ErrorMessage (int count)
    {
        if (!caller)    return;
        String msg = "";
        Switch (count)
        {
            Case -1:
            {
                msg = "Iterator error: No ActorType specified";
                break;
            }
            Case -3:
            {
                msg = "Iterator error: No instructions passed";
                break;
            }
            Default:    break;
        }
        caller.A_Log(msg);
    }
    
//------------------------------------------------------------------------------
    void Setup(Actor mo)
    {
        if (mo)    caller = mo;
    }
//------------------------------------------------------------------------------
    void DoFindActors (Class<Actor> ActorType, int instructions, int flags = 0, int maxcount = 0, double dist = 0.0)
    {
        if (caller)
        {
            int count = FindActors(ActorType, instructions, flags, maxcount, dist);
            
            if (count < 0)
            {
                ErrorMessage (count);
                return;
            }
            
            if (flags & p.ITN_LOGCOUNT)
                caller.A_LogInt(count);
        }
    }
//------------------------------------------------------------------------------
    private int FindActors (Class<Actor> ActorType, int instructions, int flags = 0, int maxcount = 0, double dist = 0.0)
    {
        // Indicate something went wrong or its not set up properly.            
        if (!ActorType)        return -1;    // Actor type doesn't exist
        if (!caller)        return -2;    // No caller was passed
        if (!instructions)    return -3;    // No instructions were passed
        
        ThinkerIterator it = ThinkerIterator.Create(ActorType);
        Actor mo;
        int count = 0;
        while (mo = Actor(it.Next(flags & p.ITF_EXACT)))
        {
            if (((flags & p.ITF_EXACT) && mo.GetClass() != ActorType) || !(mo is ActorType))
                continue;
                
            // Ignore actors with special and/or tids unless specified.
            if ((flags & p.ITF_NOTID) && mo.tid)
                continue;
            if ((flags & p.ITF_NOSPECIAL) && mo.special)
                continue;
            
            // Don't take owned items.
            if (mo is "Inventory")
            {
                let inv = Inventory(mo);
                if (inv.Owner != null)
                    continue;
            }
            
            // Make sure it's in range.
            if (dist <= 0.0 || caller.Distance3D(mo) <= dist)
            {
                count++;
                
                // Now perform the instructions.
                if (instructions & p.ITN_DESTROY)
                {
                    mo.Destroy();
                    continue;
                }
            }
        }
        return count;
    }
}

//------------------------------------------------------------------------------
// IteratorBase
//
// Houses all the setup materials for inheriting from. 
// Don't spawn it directly -- Inherit from it and replace
// PostBeginPlay instead.
//------------------------------------------------------------------------------

Class IteratorBase : Actor
{
    TIterator finder;
    TIteratorProperties p;

    override void PostBeginPlay()
    {
        Destroy();
        return;
    }
    
    Default
    {
        +NOSECTOR
        +NOINTERACTION
        +THRUACTORS
        +NOBLOCKMAP
    }
}

//==============================================================================
//==============================================================================
//    Examples
//==============================================================================
//==============================================================================

// Removes ammo on the map and prints the number of actors removed, but only if
// they have no tid or special.
Class AmmoRemover : IteratorBase
{
    override void PostBeginPlay()
    {   
        int instructions = p.ITN_DESTROY|p.ITN_LOGCOUNT;
        int flags = p.ITF_SAFE;
        int maxcount = 0;
        double dist = 0.0;
        
        finder.Setup(self);
        finder.DoFindActors("Ammo",instructions, flags, maxcount, dist);
        Destroy();
        return;
    }
}
ZzZombo
Posts: 317
Joined: Mon Jul 16, 2012 2:02 am

Re: ZScript "Standard Library" - Brainstorming

Post by ZzZombo »

Attach an object to another at certain offset, and angle, relative or absolute.
Copy properties from one actor to another, provided one is subclass of another, that's it, they are assignment-compatible. Create a copy of an actor.
Provide an alternative actor flag system where multiple sources of a flag would work with each other independently. So if two things make an actor invulnerable, removing one doesn't cancel the other.
User avatar
Enjay
 
 
Posts: 26540
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland

Re: ZScript "Standard Library" - Brainstorming

Post by Enjay »

I don't think that I am talented enough to write anything meaningful, but I fully support the idea of this script library. It makes a lot of sense and, if it takes off, I'm sure it will be very useful to a lot of people (myself included). I also suspect that the best/most useful/most frequently used might find their way into official support as part of a library within gzdoom.pk3.
User avatar
Rachael
Posts: 13738
Joined: Tue Jan 13, 2004 1:31 pm
Preferred Pronouns: She/Her

Re: ZScript "Standard Library" - Brainstorming

Post by Rachael »

Enjay wrote:I also suspect that the best/most useful/most frequently used might find their way into official support as part of a library within gzdoom.pk3.
That is unlikely. Remember the problem you had compiling Stronghold after official sqrt support was added?

Unless Graf can find a way to create exceptions for said library (where GZDoom overrides the library's internal functions instead of erroring out) I don't think it's likely anything will be added in. Unless - of course - said library was careful to prefix its function names, i.e. "ZComLib_FunctionName" etc - whereas GZDoom could opt to omit those prefixes.
User avatar
Enjay
 
 
Posts: 26540
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland

Re: ZScript "Standard Library" - Brainstorming

Post by Enjay »

Fair enough. That makes sense. I hadn't really considered the technical/conflict implications of such a thing. I was just sort of thinking out loud that if someone created a particular code-pointer-like function that was clearly pretty universally useful, that such a thing might be a possible candidate for official inclusion.
User avatar
Rachael
Posts: 13738
Joined: Tue Jan 13, 2004 1:31 pm
Preferred Pronouns: She/Her

Re: ZScript "Standard Library" - Brainstorming

Post by Rachael »

If someone wants to have that happen, then using prefixes would be a very good idea. Among other things, that would also prevent name clashes when someone actually does, later on, implement a function on their own in their own mod that also uses this library, but would later break because this library picked up on that function and the modder updated it.
User avatar
Xaser
 
 
Posts: 10773
Joined: Sun Jul 20, 2003 12:15 pm

Re: ZScript "Standard Library" - Brainstorming

Post by Xaser »

Yeah, I'd absolutely advocate using a prefix -- or a namespace if that indeed becomes a proper thing following Graf's type system overhaul.

Speaking of, even though this is the bikesheddiest sub-topic, I'm thinking of what to name such a thing. I'd originally imagined calling the library "XT" (for XTended or some shiz) just to give all the functions a nice "XT_" prefix, but something like ZTL (reference to C++'s STL) or SZL (Standard ZScript Library) are obvious-maybes as well.

Either way, a ton of cool ideas thus far! That radial hitscan bit reminds me I've always wanted to make something like "A_ArcAttack" which melees all enemies within a cone, for better sword-y weapons and such. So that's on the mental tally as well.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm

Re: ZScript "Standard Library" - Brainstorming

Post by Arctangent »

Xaser wrote:"A_ArcAttack"
hey don't let everyone just use my signature move like it was nothing
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: ZScript "Standard Library" - Brainstorming

Post by Major Cooke »

I'll see if I can supply a smooth transitioning from-one-spot-to-another using a sine wave, going from position A to B. Gonna be a little tricky...

Also, I say make it absolutely mandatory that authors of code exhaust themselves at documenting their functions and features. To this day I still look at all the undocumented zscript code and ask myself "What the hell does this even do?"
User avatar
Rachael
Posts: 13738
Joined: Tue Jan 13, 2004 1:31 pm
Preferred Pronouns: She/Her

Re: ZScript "Standard Library" - Brainstorming

Post by Rachael »

Major Cooke wrote:Also, I say make it absolutely mandatory that authors of code exhaust themselves at documenting their functions and features. To this day I still look at all the undocumented zscript code and ask myself "What the hell does this even do?"
Time to get researching! The world is counting on you! You are our second most knowledgeable person on the subject!

Kidding, of course...

Except about that last part... :twisted:
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: ZScript "Standard Library" - Brainstorming

Post by Major Cooke »

I tried escaping that responsibility with my trusty steed.
Image

But he got into the horse nip. I'm going nowhere except a hospital if I even try to get on him.

Return to “Script Library”