Final inventory actor pointer

Moderator: GZDoom Developers

User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Final inventory actor pointer

Post by FDARI »

Preferred patch: http://forum.zdoom.org/viewtopic.php?f=34&t=29364

I keep older versions of this post for reference, since the description gets major rewrites whenever I discover new quirks. We're well beyond bugfixing, and into fine tuning the submission. In this version of the post, I'll simply list the affected functions, related functions and their previous and current behaviour. The most recent change is based on discoveries regarding how player targets are handled in most code other than A_JumpIfInTargetInventory, A_GiveToTarget and A_TakeFromTarget.

Players generally don't use stored pointers. Several existing action functions, and some that I recently added, will get NULL as target when used in a player class.

A_RearrangePointers
No difference since its introduction. The discoveries made do not apply very well to this function. As players don't use stored pointers (much/at all), it would be a best practice not to use this in player classes.

A_GiveInventory, A_TakeInventory, A_TransferPointer
None of these functions were able to get a player's linetarget. A new AAPTR-flag has been added. AAPTR_PLAYER_GETTARGET. This flag can be or'ed with any standard selector (target,master,tracer,default,null) and will override the standard selector if used on a player. (If this flag is used, and a player is not looking at a target, the result will be NULL.)

AAPTR_PLAYER_GETTARGET is the same as AAPTR_PLAYER_GETTARGET|AAPTR_DEFAULT
It will get a player's target, and a regular actor's "self".

AAPTR_PLAYER_GETTARGET|AAPTR_NULL will get a player's target, or null.

AAPTR_PLAYER_GETTARGET|AAPTR_TARGET will get a player's target, or the stored target pointer.
And of course it can be used with AAPTR_MASTER and AAPTR_TRACER as well.

Note: AAPTR_DEFAULT|MASTER|TRACER|SELF and NULL can not be combined; any two of these in a single command would be ambiguous.

Note: Obviously AAPTR_PLAYER_GETTARGET can not be used to indicate a storage location for an actor pointer (relevant to A_TransferPointer and A_RearrangePointers). "GET" has been used in the name to help make this point.

A_GiveToTarget, A_TakeFromTarget, A_JumpIfInTargetInventory - before any changes I made
Do these even work when used in a player class? My reading of the code says they do not, and tests have so far agreed with me. These functions are not changed in that regard, however.

A_GiveToTarget, A_TakeFromTarget
In a previous patch, I wrongfully assumed that the length of a parameter list in zdoom.pk3 would limit the length of a parameter list submitted to an action function. Non-existent parameters would have returned 0, which is the desired value. These functions share code with A_GiveInventory and A_TakeInventory, and this code expects three parameters. If the third parameter is 0, the functions behave normally.

As this is not the case, a default parameter of 0 has been appended to these functions in the pk3.

As a side effect, it is possible to specify a third parameter in these two functions. If used, these parameters will forward the effect from the caller's target to the indicated pointer held by the caller's target. Some might find a use for this, but the parameter should probably not be put to regular use. As A_GiveInventory and A_TakeInventory duplicate and extend this behaviour, it might be time to deprecate the target-specific codepointers.

A_JumpIfInventory, A_JumpIfInTargetInventory
Added the ability to select a pointer for the test, exactly like A_GiveInventory and A_TakeInventory. A_JumpIfInventory was skipped in the code submission that has been added, and thus the A_JumpIfInTargetInventory extra-parameter-bug has not been introduced. Here, A_JumpIfInventory is extended with an extra parameter, which means that A_JumpIfInTargetInventory has received the exact same extension. As is the case for A_GiveToTarget and A_TakeFromTarget, I suggest deprecation of the more limited function.
Spoiler: Version two
Spoiler: Original post
Example of A_JumpIfInventory() with AAPTR_TRACER in use: Strife dagger with backstabbing. Sorry about publishing a resource that's not functional in any acknowledged version of the engine; I didn't notice at first.

EDIT: Attachments removed; they have served their purpose.
Last edited by FDARI on Thu Oct 27, 2011 10:01 am, edited 18 times in total.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

While I'm definitely for this, unfortunately this breaks the Stone of Temperance in AEoD whose main function is to stop seeking. I don't know what's the cause of it for certain, but I've flipped back and forth between this patch and the first one.

I'm making a rather uneducated guess but it might be the part where you put res=true instead of false...
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

Silence, noone must ever know I did that!
Uploading fixed patch now. Too much copy paste in the first one. (How did I ever expect to get away with copy-paste?)
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

I just saw you post this so I'm giving it a shot now.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

Okay, for some reason, it still likes to break the Stone of Temperance in AEoD and I don't know why. However, thinking about it, I can't help but think that we could do a better job of redesigning how it acts ourselves... Hmm...
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

If my code changes the behaviour of something, then my code is not correct. It should be 100% compatible with previous releases. Is the stone of temperance sufficiently independent that decorate + description would allow me to examine the effect? I would like to find out how on earth I broke it.

Edit: Do you know what code pointers are broken? I keep thinking it must be one of the old targetinventory-related functions (Give, Take, JumpIf). What else is there? I considered the possibility that I'd have broken it by not adding a 3. parameter to these functions, as they share parameter interpretation code with the functions I extended. However, I am rather confident that missing parameters return 0, which is the only value I want from them anyway.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

Well, here's the stone of temperance to kinda give you an idea...

Code: Select all

ACTOR StoneOfTemperance : CustomInventory
{
    +FLOATBOB
    +COUNTITEM
    +INVENTORY.FANCYPICKUPSOUND
    +INVENTORY.INVBAR
    Scale 0.25
    Inventory.Amount 1
    Inventory.MaxAmount 10
    Inventory.PickupMessage "You found the Stone of Temperance!"
    Inventory.PickupSound "powerup/voidstone"
    Inventory.UseSound "powerup/stone/use"
    Inventory.Icon "HARTVOST"
    States
    {
    Spawn:
	VOST ABCDEFGHIJKLMNOPQRSTUVWX 2
	Loop
    Use:
	TNT1 A 0 A_JumpIfInventory("NoSeekTimer",1,4)
	TNT1 A 0 A_GiveInventory("NoSeekTimer",1)
	TNT1 A 0 A_GiveInventory("NoSeekPalette",1)
	TNT1 A 0 A_SpawnItemEx("NoSeek1",0,0,0,0,0,0,0,32,0)
	Stop
	TNT1 A 0
	Stop
    }
}

ACTOR PowerNoSeek : PowerProtection
{
    DamageFactor "Normal", 0.666
    Inventory.Icon "ARTVOIDA"
}

ACTOR NoSeekPalette : PowerupGiver
{
    -INVENTORY.INVBAR
    +INVENTORY.INTERHUBSTRIP
    Inventory.MaxAmount 1
    Powerup.Type "NoSeek"
    Powerup.Color Magenta4 0.2
    Powerup.Duration 1575
    +AUTOACTIVATE
}

ACTOR NoSeekTimer : CustomInventory
{
   +NOTIMEFREEZE
   +INVENTORY.INTERHUBSTRIP
   States
   {
   Use:
       TNT1 A 0
       Stop
   }
}

ACTOR NoSeekTimer2 : Inventory
{
    +NOTIMEFREEZE
    Inventory.Amount 1
    Inventory.MaxAmount 1575
    States
    {
    Spawn:
        TNT1 A 0
        Stop
    }
}

ACTOR NoSeek1
{
    Radius 0
    Height 0
    +NOTIMEFREEZE
    +NOFEAR
    States
    {
    Spawn:
        TNT1 A 0
        TNT1 A 0 A_SpawnItemEx("NoSeekGiver",0,0,0,0,0,0,0,32,0)
        Stop
    }
}

ACTOR NoSeek2 : CustomInventory
{
    +AUTOACTIVATE
    +NOTIMEFREEZE
    States
    {
    Pickup:
        TNT1 A 0 A_ChangeFlag("CANTSEEK",1)
	TNT1 A 0 A_ChangeFlag("NORADIUSDMG",1)
	TNT1 A 0 A_ChangeFlag("DONTRIP",1)
        Stop
    }
}

ACTOR NoSeek3 : CustomInventory
{
    +AUTOACTIVATE
    +NOTIMEFREEZE
    States
    {
    Pickup:
        TNT1 A 0 A_ChangeFlag("CANTSEEK",0)
	TNT1 A 0 A_ChangeFlag("NORADIUSDMG",0)
	TNT1 A 0 A_ChangeFlag("DONTRIP",0)
        Stop
    }
}

ACTOR NoSeekGiver
{
    Health 1000000000
    Radius 0
    Height 0
    Speed 0
    +NONSHOOTABLE
    +MISSILEMORE
    +MISSILEEVENMORE
    +NOTIMEFREEZE
    +NOFEAR
    MinMissileChance 0
    States
    {
    Spawn:
        TNT1 A 1 A_Look
        Loop
    See:
        TNT1 A 1 A_Chase
        Loop
    Missile:
	TNT1 A 0 A_JumpIfInTargetInventory("NoSeekTimer",1,2)
	TNT1 A 0 A_Jump(256,"Death")
	TNT1 A 0 A_GiveToTarget("NoSeek2",1)
	TNT1 A 0 A_JumpIfInventory("NoSeekTimer2",1575,"Death")
	TNT1 A 1 A_GiveInventory("NoSeekTimer2",1)
	Goto Missile+3
    Death:
        TNT1 A 0 A_GiveToTarget("NoSeek3",1)
	TNT1 A 0 A_TakeFromTarget("NoSeekTimer",1)
        Stop
    }
}
It's supposed to do 3 things:
-Make the user unseekable
-Make the user unrippable
-Make the user immune to explosion damage without the +FORCERADIUSDMG flag.
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

Well. What I find is that I made an incorrect assumption: The argument list submitted to my action function will not necessarily be limited to the number of arguments specified in ZDOOM.PK3; it may contain unpredictable data beyond this point. That means that the old and true "target" variants of functions will need a slight touch-up to be compatible.

On the other hand: Convoluted and complex code, man! I think it could already have been done in simpler ways, and now you might have more ways to do it. I'll just have to fix us another patch.
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

There are two approaches:
1 - Adding logic to the 3 inventory-related functions that checks if the third parameter should be used
2 - Adding the extra parameter in the ZDOOM.PK3 definition, for all the "target" functions. This has the side effect of allowing a two-step jump, while preserving default behaviour. (A_JumpIfInTargetInventory("Item",1,2 AAPTR_MASTER) will only jump if you have a target with a master that has the required amount of the specified item)

Solution 2 is technically most satsifying. But the "target"-functions gain a feature as a side-effect (which we must then decide if should be used or advised against/undocumented). The ability to forward a request to any of the target's pointers like this is slightly inappropriate for the function name, and also inappropriate because the more generic functions I made are meant to overlap completely with target-specific functions.

Solution 1 looks like slightly more engine-work, but may make more sense in some regard. I'm looking for advice / ideas here, before posting a patch.

EDIT: Patch lines for PK3 are added to the first post. It is too easy not to at least put forth the solution.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

FDARI wrote:On the other hand: Convoluted and complex code, man! I think it could already have been done in simpler ways, and now you might have more ways to do it. I'll just have to fix us another patch.
Don't blame me! I didn't make it. I'm just posting it here for convenience. Anyway I'm reading the rest of your posts now...
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

This patch happened to fix more crashes. Thanks man! Still doesn't fix the issues with the likes of Stone of Temperance though.

Question, how would you go about re-writing the stone of temperance?
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

I only used the radiusdamage to test the condition of the stone of temperance, but on my computer the official release and my latest patch worked out the same (as if there was 100% compatibility, which is what I'm aiming for). What remaining differences do you find? Also; if my patch were 100% backward compatible, it should probably not fix any crashes that occured in previous versions. Thus, I'm still wondering what I might be doing wrong. If I can find out how my code affects your crashes, I can probably also find out how to fix them in the first place (without engine update). And I can find any weaknesses in my work.

I don't know exactly how I'd rewrite the stone of temperance, but after reading the source-code I have the impression that: Any/most non-monster actors spawned without SXF_TRANSFERPOINTERS will target their creator like missiles do. This appears to apply to your helper actors (NoSeek1, NoSeekGiver). This probably means that NoSeek1 is immediately set with the necessary target pointer and requires no further preparation; it can give inventory to the target, and perform the work of "NoSeekGiver"; and it does not have to look or chase at all. (Target is correct from the get-go.)

If this is not automatically the case, you can use A_CustomMissile instead, and make it target that way. There might be even simpler solutions, but I don't know the reasoning behind every line of decorate.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

Yeah, I was asking for your opinion about it first before jumping onto changing it off the bat.
User avatar
Major Cooke
Posts: 8206
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town

Re: Final inventory actor pointer

Post by Major Cooke »

After some more testing... CustomInventory is no longer performing A_ChangeFlag on the user and I have no idea why. I tested it with A_SetInvulnerable and that worked just fine, but A_ChangeFlag is being absolutely stubborn! That is, using your patch.

Here, try this code:

Code: Select all

Actor TestInv : CustomInventory
{
	States
	{
	Pickup:
		TNT1 A 0 A_SetInvulnerable
		TNT1 A 0 A_ChangeFlag("CANTSEEK",1)
		TNT1 A 0 A_ChangeFlag("NORADIUSDMG",1)
		TNT1 A 0 A_ChangeFlag("DONTRIP",1)
		Stop
	}
}
"Give testinv" in the console and watch. You're invulnerable but you still dont have the flag settings.
User avatar
FDARI
Posts: 1097
Joined: Tue Nov 03, 2009 9:19 am

Re: Final inventory actor pointer

Post by FDARI »

There must be a difference between our versions at this point. I tested that actor. All code pointers were executed with "DoomPlayer" as "self", and all flag changes were made to the DoomPlayer. I also replaced A_SetInvulnerable with A_ChangeFlag("NODAMAGE",1), and it made the player properly invulnerable.

Perhaps I have again failed to post a valid diff after all; my grasp of the svn-tool is far more tenuous than my grasp of C++ and the ZDoom engine (and even that isn't outright amazing yet).

I don't see anything wrong about my patch. I uploaded my thingdef_codeptr - source, which contains all modifications for this patch. Can you test with this code, or use this code to create your own diff-patch and compare with mine? If you get a different patch, then I might have done something wrong when generating mine.

EDIT: PS - Preserve your current version! (I'm sure you will, but then again, is anything certain?)

Return to “Closed Feature Suggestions [GZDoom]”