desire help with monster that can drop and retrieve object

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!)
Post Reply
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

desire help with monster that can drop and retrieve object

Post by bimshwel »

I have had success using ints before to control this sort of thing, and think I could make this work by incorporating those and custom pain frames, but it seems like inventory commands would make more sense, yet I evidently do not understand how they work. It is not CRUCIAL that this work, but I got it into my mind that it COULD work after observing the various documented child/sibling/master and inventory A_s, and so assembled this mess

Code: Select all

actor fyop2 : fyip 10007
{
health 70
translation "fyip3"
	  Speed 7
		    xScale 0.078
			    yScale 0.072
		states
		{
		    Spawn:
					fepd i 1 A_RadiusGive("hat2", 16, RGF_GIVESELF,  1) //A_GiveInventory ("hat2") didn't seem to work
			idle:
          fepd im 10 A_Look
        loop
     See:
          fepd abcdefgh 3 A_Chase     
          Loop

		  nohatsee:
		   fepf abcdefgh 3 
		   {
	A_wander;
	 A_JumpIfInventory("hat2", 1, "gethat");
	 }
		 	fepf abcdefgh 3 
			{
	A_chase;
	 A_JumpIfInventory("hat2", 1, "gethat");
	 }
		  loop
		       Missile:
			   fefp a 0 A_JumpIfInventory("hat2", 0, "nohatmissile")
	  fepd i 10 A_FaceTarget
	       fepd j 3 a_startsound ("fyip/zupe")
           fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
           fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
          fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
           fepd l 3 a_SpawnProjectile ("casingthing", 24, 12, -192)
           fepd m 8 A_FaceTarget
		      fepd j 3 a_startsound ("fyip/zupe")
           fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
          fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
          fepd k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
           fepd l 3 a_SpawnProjectile("casingthing", 24, 12, -192)
           fepd mjn 3
          GoTo See
		  nohatmissile:
		  	  fepf i 10 
			  {
			  A_FaceTarget;
			   A_JumpIfInventory("hat2", 1, "gethat");
	      }
	       fepf j 3 a_startsound ("fyip/zupe")
           fepf k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
           fepf k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
          fepf k 1 bright a_SpawnProjectile ("zipzupezip", 26, 0, 0)
           fepf l 3 a_SpawnProjectile ("casingthing", 24, 12, -192)
           fepf mjn 3
		   goto nohatsee
		  pain.slap:
		  fefp a 0
		  fefp a 0 A_JumpIfInventory("hat2", 0, "nohatpain")
		  fedp a 2 A_spawnitemex ("hatthing2", random (0, -1), random (-2, 2), random (32, 48), random (0, -4), random (-2, 2), random (1, 4),  0, SXF_TRANSFERTRANSLATION)	
		  fefp a 2 {
		  A_TakeInventory("hat2", 1);
		  a_setuservar ("user_fyop2hatloss", 1);
		  }
		   fefp b 2 
          fefp b 2 A_Pain
		  fefp aabb 2 
		  goto nohatsee
		  nohatpain:
		  fefp a 0 a_changevelocity (0,0,2, CVF_RELATIVE)
		  fefp a 0 A_Jump (128, "nohatpain2")
          fefp aab 2 
          fefp b 2 A_Pain
		  fefp aabb 2 
          GoTo nohatSee
		  nohatPain2:
		  fefp ccd 2 
          fefp d 2 A_Pain
		  fefp ccdd 2 
          GoTo nohatSee
		  	       Pain:
				   fedp a 0 A_JumpIfInventory("hat2", 0, "nohatpain")
	    fedp a 0 A_Jump (128, "pain2")
          fedp aab 2 
          fedp b 2 A_Pain
          GoTo See
		  Pain2:
		  fedp ccd 2 
          fedp d 2 A_Pain
          GoTo See
		  gethat:
		  fedg a 4 a_removechildren
		  fedg bcdef 4
		  goto see
//an a_facechild or equivalent code would be nice but for the time being I have only drawn it picking up a hat from the front anyway.
		  death:

   fynv a 0 A_JumpIfInventory("hat2", 0, "nohatflop")
FYNV ab 4 
FYnv c 4 A_Scream
fynv d 0 A_TakeInventory("hat2", 1) 
dropgun:
		  FYnv d 0 A_spawnitemex ("gunthing2", random (1, 3), random (-1, -3), random (16, 32), random (.5, 2), random (.5, 1), random (3, 6), 0, SXF_TRANSFERTRANSLATION)
		  FYnv c 0 A_spawnitemex ("hatthing2", random (0, -1), random (-2, 2), random (32, 48), random (0, -4), random (-2, 2), random (1, 4),  0, SXF_TRANSFERTRANSLATION)	
		  fynv e 0 a_changevelocity (0,0,random (.5, 2),0,0)
		    fypf b 0 ThrustThing(angle * 256 / 360 + 128, random (0.5, 2), 0, 0)		
		  
          FYnv e 4  		
          FYnv f 0 A_Fall 
          Fynv ghi 4
	  FYnv j -1
          Stop
		  nohatflop:
		  FYNV kl 4 
FYnv m 4 A_Scream
goto dropgun
}
}
this fool consistently fails to respond as if its inventory has changed. it drops a hat when slapped, but ignores the "jumpifinventory" commands and so reverts to the hat-wearing sprites and can be made to drop additional hats. Which is funny but not beneficial.

Code: Select all

actor hatthing2 : hatthing
{
     States
     {
     Spawn:
          fyoy ab 5
          fyoy c -1
          stop
		     death:
          fyoy d 1
		  fyoy d 3 A_Fall
		    fyoy efg 4
			hatgive:
			fyoy h 10 A_RadiusGive("hat2", 16, RGF_NOMASTER, RGF_EXFILTER, 1)
			//this hopefully will attempt to and potentially succeed returning itself to its "master"
	goto hatgive
		  }}

ACTOR hat2 : CustomInventory
{
 States
  {
  Spawn:
    fyoy h -1
    Stop
  //Pickup:
//goto gethat
  }
}
bits for the hat, which may not be directly relevant. I was not sure if it was wise to have the visible dropped object (which the player can grab) be the same as the imaginary inventory object that the monster is [meant to be] given
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by Player701 »

bimshwel wrote:and so assembled this mess
Sorry to say this, but it is indeed a mess: it's very hard to read your code due to inconsistent indentation. Next time you post code here, please make sure it is indented properly (see examples for DECORATE in the ZDoom Wiki, e.g. here), then it will be much easier to comprehend.

What I can say right now:

Code: Select all

Spawn:
    fepd i 1 A_RadiusGive("hat2", 16, RGF_GIVESELF,  1) //A_GiveInventory ("hat2") didn't seem to work
Neither A_RadiusGive nor A_GiveInventory will do anything here unless you add the NoDelay flag.

bimshwel wrote:

Code: Select all

A_JumpIfInventory("hat2", 0, "nohatmissile")
Note that [wiki]A_JumpIfInventory[/wiki] reserves a special meaning for the value 0 of its second argument:
ZDoom Wiki wrote:Note that if amount is 0, the jump is only performed if the actor is carrying the maximum number of that item. This is useful for checking whether the player has the maximum amount of ammo for a particular weapon, regardless of whether or not he's found a backpack.
Since you haven't defined a MaxAmount for your item class, it defaults to 1, so A_JumpIfInventory("hat2", 0, ...) is equivalent to A_JumpIfInventory("hat2", 1, ...). Therefore, your code probably doesn't work the same way you expect it to.


If you could address the above issues, you will likely be able to fix the problem yourself. If you still can't, please post the new version of your code here, and I'll investigate further when I have the time.
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

thank you for the input! Organizational consistency often eludes me but I will attempt to do as you have suggested. I wonder if doing more editing outside of slade and notepad might help me get the alignment more under control.
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

ah ha the game will not actually track whether the item is had or not without it having a "use" state, even though the creature cannot use an item apart from merely by having the thing. now i fear that my use of jumpifinventory inside of an anonymous function is causing failure, so i attempted to finally figure out how that is supposed to be done. I have been intimidated by it in the past and merely aimed to avoid needing it.

Code: Select all

	See:
			fepf a 1
					fepf a 1 nodelay A_JumpIfInventory("hat2", 1, "hatsee") 
					//this would be easier if I could have it check for 0 hats but evidently that makes it check for MAXIMUM hats
			
			nohatsee:
					fepf abcdefgh 3 
						{
							if (Checkinventory("hat2", 1))
								{ A_wander;
								}
							else
								{ return state ("gethat");
								}
							}
					fepf abcdefgh 3 
						{
							if (Checkinventory("hat2", 1))
								{ A_chase;
								}
							else
								{ return state ("gethat");
								}
							}
					loop
I tried to make sense of the description of what to do instead of jumping states, which led to me trying return, which generates a RED error message stating "Return type mismatch." looking up that phrase indicates I have gotten into something that is for the moment beyond my limited range of understanding. I am also not certain that the checkinventory syntax is correct since using it seems to result in a demand for more parameters than https://zdoom.org/wiki/CheckInventory 's example makes use of.
Gez
 
 
Posts: 17835
Joined: Fri Jul 06, 2007 3:22 pm

Re: desire help with monster that can drop and retrieve obje

Post by Gez »

Yes, the fact that A_JumpIfWhatever functions stop A_Jumping and merely behave as a sort of If instruction when placed in anonymous functions is a big gotcha.

The return type mismatch is also due to this being an anonymous function.

Basically, and to try to make things as simple as I can explain:

Code: Select all

{
    if (something)
    {
        return state("mystate")
    }
}
This function has actually two paths. One of them (if "something" evaluates to true) will return a state. The other path is if "somehing" evaluates to false. Then it doesn't return a state, instead it does nothing -- and returns nothing. That means the function can has two different types of a return, either a state or nothing. And that's a mismatch. It should either always return a state, or always return nothing.

The way to fix that is to get your function to return the null state where you don't want it to perform a jump. That would look like this:

Code: Select all

{
    if (something)
    {
        return state("mystate");
    }
    return state(0);
}
or like this, this works too:

Code: Select all

{
    if (something)
    {
        return state("mystate");
    }
    return state("");
}
Whichever way you prefer to represent the null state, it provides a safe way to prevent the anonymous function from ending with a jump when other conditions in the function would cause a jump.

In other words, if you do this:

Code: Select all

             nohatsee:
                   fepf abcdefgh 3
                      {
                         if (Checkinventory("hat2", 1))
                            { A_wander;
                              return state(0);
                            }
                         else
                            { return state ("gethat");
                            }
                         }
                   fepf abcdefgh 3
                      {
                         if (Checkinventory("hat2", 1))
                            { A_chase;
                              return state(0);
                            }
                         else
                            { return state ("gethat");
                            }
                         }
                   loop
That should work, I think.
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

Thank you! That works, but as soon as I realized it worked I saw that what I had presented is the opposite of what I intend; i want it to alternate wandering and chasing if it does NOT have a hat, UNTIL it finds a hat. Or is found by a hat, as the case may need to be.

Code: Select all

	 nohatsee:
                   fepf abcdefgh 3
                      {
                         if (Checkinventory("hat2", 1))
                            { return state ("gethat");
                              return state(0);
                            }
                         else
                            { A_wander;
                            }
                         }
                   fepf abcdefgh 3
                      {
                         if (Checkinventory("hat2", 1))
                            { return state ("gethat");
                              return state(0);
                            }
                         else
                            { A_chase;
                            }
                         }
                   loop
I tried turning it around and am back to the mismatch error I started with, since I still seem unable to check for zero of an inventory item or totally grasp the explanation of why it matches or does not match. and "if hat2 = 1 = false" seems absurd.

Code: Select all

actor hatthing2 : hatthing
{
     States
     {
     Spawn:
			fyoy ab 5
			fyoy c -1
			stop
	death:
			fyoy d 1
			fyoy d 3 A_Fall
			fyoy efg 4
	hatgive:
			fyoy h 4 A_RadiusGive("hat2", 32, RGF_MONSTERS, 1, fyop2 )
			//this hopefully will attempt to and potentially succeed returning itself to its "master"
	goto hatgive
	use: 
			fyoy h 1
		  }}
additionally I expect to have trouble with this hat transferer eventually since I am uncertain if it permits me to single out the master as a recipient. I can EXCLUDE the master and it looks like I can invert the settings, which I tried to have it do before, but at that time no transfer occurred. In a worst-case situation I can prevent putting more than one fyop2 in any single zone, since there are a few fyip and fyop variants.

an alternate method might be to have fyop GAIN a fake inventory item when losing its hat, but then would the child hat be able to revoke the fake inventory anti-hat and provoke a state jump in its master? Once again it only appears possible to have this go in the opposite direction.
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by Player701 »

bimshwel wrote:I still seem unable to check for zero of an inventory item
Since you can jump if you have 1 or more of an item with A_JumpIfInventory(..., 1, ...), the states following the call (which execute when you don't jump) represent the condition when you don't have the item.

Code: Select all

SomeState:
    TNT1 A 0 A_JumpIfInventory("MyItem", 1, "HaveItem")
DontHaveItem: // This label is for convenience's sake only, it doesn't affect the actual behavior
    // These states will execute if the actor does not have any of MyItem
    ...
    Goto SomeState // Repeat the check
HaveItem:
    // These states will execute if the actor has at least 1 of MyItem
    ...
    Goto SomeState // Repeat the check
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

Yes, I moved some stuff around after you pointed out the bit about not being able to check for zero, but when trying to do the same thing inside the anonymous function that Gez described based on my information that I had backwards, possibly on account of already having switched stuff around earlier, I no longer remember, I could not figure out the syntax.
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by Player701 »

IMO, using anonymous functions for simple inventory checking and jumping is overkill, since A_JumpIfInventory already exists to do exactly that.
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

It isn't NECESSARY, but doing it the other way, my code looks even uglier

Code: Select all

fepf a 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf a 3 a_wander
fepf b 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf b 3 a_wander
fepf c 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf c 3 a_wander
fepf d 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf d 3 a_wander
fepf e 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf e 3 a_wander
fepf f 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf f 3 a_wander
fepf g 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf g 3 a_wander
fepf h 0 A_JumpIfInventory("hat2", 1, "hatget") 
fepf h 3 a_wander
I end up having to do tedious, ugly, difficult to amend stuff when I can't figure out the proper way rather often, so as long as I am asking questions it seemed worth checking on a better way out of it this one time, that I might be able to apply to others as I encounter or re-encounter them.
Last edited by bimshwel on Fri Jun 17, 2022 12:13 am, edited 1 time in total.
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by Player701 »

Sorry, didn't see you wanted to do the check during every single state instead of just in the beginning of the state sequence. Then it is indeed better to simplify the code by using anonymous function blocks. Looking at your previous example, I can see you have some extraneous return statements there. Here's how the block should look like:

Code: Select all

{
    if (Checkinventory("hat2", 1))
    {
        return state("gethat");
    }
    
    A_Wander; // or A_Chase
}
It should be functionally identical to yours - the only question is whether it does what you actually want it to do.
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

thank you for looking at it again! so now it is laid out like

Code: Select all

	 nohatsee:
                   fepf abcdefgh 3
						{
						if (Checkinventory("hat2", 1))
							{
							return state("gethat");
							}
						A_Wander; 
						}
                   fepf abcdefgh 3
						{
							if (Checkinventory("hat2", 1))
							{
							return state("gethat");
							}   
						A_Chase;
						}
                   loop
		
but is still generating mismatch errors, specifically on the closing fancy brackets after wander and chase.
Gez
 
 
Posts: 17835
Joined: Fri Jul 06, 2007 3:22 pm

Re: desire help with monster that can drop and retrieve obje

Post by Gez »

Player701 wrote:Looking at your previous example, I can see you have some extraneous return statements there.
What did I just say? They're not extraneous.

Code: Select all

{
    if (Checkinventory("hat2", 1))
    {
        return state("gethat");
    }
    A_Wander; // or A_Chase
    return state(0);
}
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by Player701 »

There were two returns following each other in the same block, so the second one was definitely unnecessary. That's what I was talking about. And yeah, looks like it needs one in the end as well. Sure been a while since I coded in DECORATE... :?
User avatar
bimshwel
Posts: 704
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced
Contact:

Re: desire help with monster that can drop and retrieve obje

Post by bimshwel »

ehhhhh one step at a time! I don't mind porting it all to zscript eventually; I constructed a great many more messes than this over my years trying. But yes it all, or at least everything immediately relevant, functions now, thank you! This setup should no doubt help in future matters and if I see the code pieces enough eventually I will comprehend them better.

And it is greatly amusing to me to finally see the hat grasp in action. The beasts are so disorderly when bunched together i couldn't tell if the wrong one was trying to receive a hat it couldn't remove anyway so this should not attempt to become anyone else's problem again for a while.
ehhhhdit:

Code: Select all

	fyoy h 4 A_RadiusGive("hat2", 32, RGF_MONSTERS|RGF_NOMASTER|rgf_inclusive, 1, fyop2)
this seems to be behaving so the matter may indeed be concluded.
Post Reply

Return to “Scripting”