need help with first Zscript weapon

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!)
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

need help with first Zscript weapon

Post by vAethor »

This was actually in a previous topic, but I must've replied too late because it seems to be dead.

Anyways, I took a look at Caligari87's tranquility.pk3 to see how he made a weapon with multiple moving parts as overlays, now I'm trying something like that. My custom weapon's a basic assault rifle with an added ammo counter like in Halo or Aliens that counts down to zero as you shoot bullets. I already made crappy placeholder graphics for the gun, the counter and the spent casings and started a new PK3, but I'm sorta at a loss as to where to go next.

Here's what I got so far:
https://drive.google.com/file/d/1tW2GYV ... sp=sharing

I currently have my zscript lump with the following code so far:

Code: Select all

// Crappy gun test with ammo counter (Halo-style)
// Created:  02/14/2018
// Modified: 02/14/2018

// - THE GUN -------------------------------------------------------------------
class CounterGun : pistol
{
	Default {
	Weapon.SlotNumber 2;
	}
	
	States {
	Spawn:
		CGUN A -1;
		Loop;
	}
}
Currently it doesn't do much - pressing the slot for it just causes the player pull out another instance of the regular pistol. But this is as far as I've gotten so far, as I am a complete beginner at Zscript and had trouble making sense of Caligari's code.

I wish there were more Zscript tutorials so I could learn more on my own without asking these dumb questions.
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
Contact:

Re: need help with first Zscript weapon

Post by Matt »

It wasn't intended to be a general ZScript weapon tutorial, but this reloading pistol might be a start.
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Matt wrote:It wasn't intended to be a general ZScript weapon tutorial, but this reloading pistol might be a start.
Hmm, I'm studying your code and doing research on the wiki along the way. I tried executing what I've got so far but I got the cryptic error "Unexpected integer constant, Expecting '-' or '+' or ';' or identifier or '}' for line 32 of my code

Code: Select all

		// More actor flags
		+weapon.ammo_optional	+weapon.alt_ammo_optional
		+weapon.ammouse1 0;		+weapon.ammouse2 0;
This was copied directly from yours. I checked all the curly brackets to make sure nothing's unclosed, everything checks out as far as I know.

What exactly am I doing wrong here? I need to fix this before I can go on. Forgive me for being such a newcomer, but again if Zscript were as widely used as DECORATE and ACS this would be a lot easier for me.

Here's my complete code if you want to see it:

Code: Select all

// Crappy gun test with ammo counter (Halo-style)
// Created:  02/14/2018
// Modified: 02/15/2018

/* Code loosely based on Matt's reloading pistol script and Caligari's multi-
   overlay gun thing. */


const GUN_MAXAMMO = 35; // The maximum number of bullets the gun can carry


// THE GUN
class CounterGun : pistol replaces pistol
{
	Default 
	{ 
		Weapon.SlotNumber 2;
		+rollsprite +rollcenter /* NOTE TO MYSELF: Looking up these actor
								   flags on the Zdoom Wiki to see what they
								   mean (for future reference.)
							   
								   +rollsprite rotates the sprite (GL only?)
								   +rollcenter centers the point at which the
							        sprite rotates */
								
		+weapon.noalert /* Just copying from Matt's code here...he says this
						   is for firing the gun empty, making sure it doesn't
						   alert enemies when fired with no ammo. */
					   
		// More actor flags
		+weapon.ammo_optional	+weapon.alt_ammo_optional
		+weapon.ammouse1 0;		+weapon.ammouse2 0;
		/* */
	
	}
	
	States
	{
		nope: // Generic state (no ammo, not loaded, etc.)
		---- A 1 A_WeaponReady(WRF_NOFIRE);
		goto ready;
		
		ready:
		CGUN A 1 A_WeaponReady(WRF_ALLOWRELOAD | WRF_ALLOWZOOM);
		wait;
		
		fire:
		CGUN A 4
		{
			if (invoker.loaded < 1) {
				player.setpsprite (PSP_WEAPON, invoker.findstate("nope"));
			}
		}
	}
	
}
The answer is probably something extremely obvious, but in the meantime maybe I should dust off my old C++ book and refresh my memory on actual coding, not just scripting.
Blue Shadow
Posts: 4949
Joined: Sun Nov 14, 2010 12:59 am

Re: need help with first Zscript weapon

Post by Blue Shadow »

vAethor wrote:

Code: Select all

		// More actor flags
		+weapon.ammo_optional	+weapon.alt_ammo_optional
		+weapon.ammouse1 0;		+weapon.ammouse2 0;
Weapon.AmmoUse1 and Weapon.AmmoUse2 are properties, not flags, thus they shouldn't be prefixed with a '+'.
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Blue Shadow wrote:
vAethor wrote:

Code: Select all

		// More actor flags
		+weapon.ammo_optional	+weapon.alt_ammo_optional
		+weapon.ammouse1 0;		+weapon.ammouse2 0;
Weapon.AmmoUse1 and Weapon.AmmoUse2 are properties, not flags, thus they shouldn't be prefixed with a '+'.
Thanks man, that did something.

I got a couple more errors saying certain actor properties in the code I copied from weren't valid, and I had to comment out the code for the Fire state since it didn't recognize more things, but I did get my gun to show up in the game when I test-ran and hit IDKFA:

Image

I added the following code in the fire state:

Code: Select all

---- A 1 A_PlaySound ("GunShot");
		CGUN ABCD 1;
		goto ready;
and now it shoots too! But it doesn't kill anything yet.

I'm just still reverse-engineering others' code at this point. I take it ---- is Zscript's version of TNT1?
Blue Shadow
Posts: 4949
Joined: Sun Nov 14, 2010 12:59 am

Re: need help with first Zscript weapon

Post by Blue Shadow »

vAethor wrote:I got a couple more errors saying certain actor properties in the code I copied from weren't valid, and I had to comment out the code for the Fire state since it didn't recognize more things
I can't see in the code anything that would be considered an unknown or invalid actor property. For the Fire state, however, it's probably the 'loaded' variable that is causing the error, and that's because it's not declared in the weapon.
I take it ---- is Zscript's version of TNT1?
[wiki=Sprite#Special_names]Not really[/wiki].
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Blue Shadow wrote: I can't see in the code anything that would be considered an unknown or invalid actor property.
For the Fire state, however, it's probably the 'loaded' variable that is causing the error, and that's because it's not declared in the weapon.
Oh my bad. it was weapon.alt_ammo_optional that was commented out because GZdoom thought it was an actor property. I somehow didn't have the + next to it. I put it back since I remembered it's actually a flag, not a property. Now it runs just fine.

I just added Int loaded; at the very beginning of the class definition, now it runs perfectly. Well, except the gun doesn't animate and it still looks buggy since the equipping and putting away animations revert back to the vanilla Pistol, but it does play the firing sound as I have added a placeholder A_PlaySound() function at the beginning of the Fire state. It's a placeholder since I am guessing there is a more elegant way of doing this within Zscript, but this is what I know works from my experience with DECORATE.
I take it ---- is Zscript's version of TNT1?
Not really.
Oh yeah, I just looked it up, it means "keep previous sprite." Derp.

Anyways, I noticed something odd through trial and error. Commenting out the more complicated firing code that was in Matt's source I am still studying, and instead using simpler DECORATE-style placeholder code like this:

Code: Select all

fire:
		---- A 1 A_PlaySound ("GunShot"); /* Placeholder code for playing the
											 firing sound, probably a more
											 elegant way of doing this in
											 Zscript. */
		CGUN ABCD 1;
		goto ready;
		
		//CGUN A 1
		//{
			//if (invoker.loaded < 1)
			//{
				//player.setpsprite (PSP_WEAPON, invoker.findstate("nope"));
			//} // if statement end
		//} // loop end
The gun actually animates in addition to playing the sound, albeit somewhat slowly (it's about as fast as the vanilla Chaingun I'm guessing.)

But going with the original more advanced code has different results:

Code: Select all

fire:
		---- A 1 A_PlaySound ("GunShot"); /* Placeholder code for playing the
											 firing sound, probably a more
											 elegant way of doing this in
											 Zscript. */
		//CGUN ABCD 1;
		//goto ready;
		
		CGUN A 1
		{
			if (invoker.loaded < 1)
			{
				player.setpsprite (PSP_WEAPON, invoker.findstate("nope"));
			} // if statement end
		} // loop end
The gun doesn't animate (yet, because I haven't actually put in the code for animation...I'm planning on handling that in a function instead and just calling that function here) but it does play the firing sound, and by listening to it the rate of fire is almost twice as fast. I also notice the gun is stationary when firing standing still, but jitters about randomly while bobbing if shooting while moving around.

I'm guessing it's faster now since it cycles through the loop much faster now as it doesn't pause a tic to animate each frame on the CGUN ABCD 1 line. Am I right?
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
Contact:

Re: need help with first Zscript weapon

Post by Matt »

[wiki]A_PlaySound[/wiki] is indeed what you should be using to play the sound. Remember to specify the channel, though.

(Just as a side note: don't get too caught up in trying to find "more elegant" ZScript alternatives if you aren't specifically trying to avoid a specific thing that is assumed or ignored by a known "DECORATE" action function. Generally that function, calling more native code to do what it does, will be more optimized anyway - I've been going back to a lot of my earlier ZScript "xxx=spawn... xxx.angle=... xxx.master=..." etc. codeblocks lately and replacing them with A_SpawnItemEx.)

That said...
The gun doesn't animate (yet, because I haven't actually put in the code for animation...I'm planning on handling that in a function instead and just calling that function here) but it does play the firing sound, and by listening to it the rate of fire is almost twice as fast. I also notice the gun is stationary when firing standing still, but jitters about randomly while bobbing if shooting while moving around.

I'm guessing it's faster now since it cycles through the loop much faster now as it doesn't pause a tic to animate each frame on the CGUN ABCD 1 line. Am I right?
Yes to your last question.

Here's what your first block of code does:
1. Play sound "gunshot" on the default channel
2. Run through one frame of whatever was last used, taking 1 tic
3. Run through frames CGUNA0 through CGUND0, each taking 1 tic
4. Go back to the ready state
Total time: 5 tics per shot

Here's what your second block does:
1. Play sound "gunshot" on the default channel
2. Run through one frame of whatever was last used, taking 1 tic
3. Check to see if the weapon's "loaded" variable is below 1; if it is, go to the ready state; if not, continue to 4
4. Run through frame CGUNA0, taking 1 tic
5. Continue to whatever is below that quoted section
Total time: 2 tics per shot


My example in that post does not include the Select and Deselect states. They are found on the wiki's DECORATE version of the pistol actor - just add "();" after A_Raise/A_Lower, and put in a number inside those parentheses if you want the lower/raise to be faster or slower (bigger numbers are faster and the default is 6).

(It might be worthwhile to click on some of those links on that example code as well - everything you see there will work in ZScript, it's just a matter of formatting a few optional extras.)
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Matt wrote:[wiki]A_PlaySound[/wiki] is indeed what you should be using to play the sound. Remember to specify the channel, though.

(Just as a side note: don't get too caught up in trying to find "more elegant" ZScript alternatives if you aren't specifically trying to avoid a specific thing that is assumed or ignored by a known "DECORATE" action function. Generally that function, calling more native code to do what it does, will be more optimized anyway - I've been going back to a lot of my earlier ZScript "xxx=spawn... xxx.angle=... xxx.master=..." etc. codeblocks lately and replacing them with A_SpawnItemEx.)
Way ahead of ya :D . While I was waiting for new replies I did a little research on some of the flags, properties and functions you used as well as learning more about DECORATE ones I already know. I also was dissatisfied with my placeholder sprites so I went into Clip Studio, rendered what I have so far of my unfinished final version and added a muzzle flash, and now it looks much better:
ImageImage

Will eventually have to either switch it back to the placeholder or work on animating this version's ammo counter separately though, because the '35' is currently a completely static part of the sprite, no overlays yet.

Now I know Zdoom (GZdoom in my case) has eight channels, so I thought to assign the gunshot sound to CHAN_WEAPON.

Now I did try a little experiment that currently failed and made me have to comment out the code, but my thought was to layer in a motor sound under the automatic gun fire (because in my fictional universe this gun uses an electromechanical bolt and ejection assembly.) I added another A_PlaySound one tic before to loop the sound "cgun_motorloop") but it ended up cancelling all the sounds when I added A_StopSound to end the motor loop when it goes back to Ready.

Code: Select all

ready:
		// Now A_WeaponReady allows reload and zoom (self-explanitory I guess)
		CGN2 A 1 A_WeaponReady(WRF_ALLOWRELOAD | WRF_ALLOWZOOM);
		//---- A 1 A_StopSound (CHAN_5);
		wait;

		select:
		CGN2 A 1 A_Raise(9);
		Loop;
		
		deselect:
		CGN2 A 1 A_Lower(8);
		Loop;

		fire:
			  /* Placeholder code for playing the firing sound, probably a more
		         elegant way of doing this in Zscript. */
		//---- A 2 A_PlaySound ("cgun_motorloop", CHAN_5,      1, true) ;
		---- A 1 A_PlaySound ("cgun_shoot", 	CHAN_WEAPON, 1, false);
		CGN2 BDC 1;
		goto ready;
		
		//CGUN A 1
		//{
		/* 'invoker' is what we use to refer to the weapon. If we don't use
			it Zdoom assumes we're referring to the player instead. */
			//if (invoker.loaded < 1)
			//{
				// Go to the abort (nope) state if no ammo is loaded 
				//player.setpsprite (PSP_WEAPON, invoker.findstate("nope"));
				/* PSP_WEAPON is the sprite layer which refers to the actual
				   weapon. PSP_X refers to a set of internal layers used by the
				   engine (according to the Zdoom Wiki,) and is used with
				   A_OVERLAY.
				   
				   I need to ask someone what 'setpsprite' is and does...it's
				   not showing up in any search on the wiki. */
				   
			//} // if statement end
		//} // loop end
	} // states definition end
Also just for the record, I think I pretty much understand the gist of your code I currently have commented out, except for the 'setpsprite' function. I looked it up on the Wiki as it says in my comment and it turned up nothing.

And here is my PK3 so far:
Attachments
ammo-counter-gun.pk3
(253.58 KiB) Downloaded 47 times
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
Contact:

Re: need help with first Zscript weapon

Post by Matt »

SetPSprite sets a sprite state for an overlay - in more user-friendly terms, this is like setstate for your weapon and weaponflashes instead of your actor sprite (PLAYA1, etc.).
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Matt wrote:SetPSprite sets a sprite state for an overlay - in more user-friendly terms, this is like setstate for your weapon and weaponflashes instead of your actor sprite (PLAYA1, etc.).
Hmm okay, I think I get it. I notice your code points to the "nope" state as the second argument for setpsprite(), and that PSP_WEAPON is just the base gun sprite to apply the overlays to (I think.)

Hmm, now I got an idea. Since you say it sets the sprite state, I just got an idea for my ammo counter. Would it work if I get it to point to a function I write that animates and handles the ammo countdown and checks to see if there are still bullets in the clip? Either that or a state just for the counter, but I don't think that will work since as far as I know states apply to the whole weapon actor, not just a single overlay.

Here's some pseudocode for my idea:

Code: Select all

const GUN_MAXAMMO = 35;
int bullets;

states:
{
fire:
if (ammo loaded < 1)
{
player.setpsprite (PSP_WEAPON, go back to "nope" state);
}
else if
{
play sound (gunshot);
shoot a bullet;
countBullets(); // see below for my attempt to define this function

animation stuff;
more animation stuff;

goto ready;

// counter function
void countBullets()
{

// Not super-familiar with arrays, or even if Zscript can do them, but it's the only way I can think of to dynamically animate the counter
string frames [36] = {all the frames of the counter in here};

int currentBullets = GUN_MAXAMMO - bullets; // I think I did something wrong here

For (i = 0; i < currentBullets; i++)
{
CNT1 frames[something in here, not sure] 1;
bullets = bullets - 1;
}
}

Please current my logic if you can, I think I may be way off but I hope you get my idea.
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
Contact:

Re: need help with first Zscript weapon

Post by Matt »

Keep in mind that any single ZScript function has to execute everything all at once, so to spread something out over a bunch of tics you'll need to use states.
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Matt wrote:Keep in mind that any single ZScript function has to execute everything all at once, so to spread something out over a bunch of tics you'll need to use states.
Hmm, please explain. So maybe instead of using a function I create a state for the counter code instead?

Okay, what if I have the counter code execute in a state called counter, which as soon as it's done it checks to see if there are still bullets, and if there are it goes back to the firing state, but if there aren't it goes to the nope state?
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
Contact:

Re: need help with first Zscript weapon

Post by Matt »

That should work.

What you had in your previous post looked like you were trying to play a couple frames within the script itself.
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: need help with first Zscript weapon

Post by vAethor »

Hey, I confess I don't know as much about this as I first thought. I think my logic is good but my syntax isn't. I'm also extremely busy with work and other things and aren't replying until now.

I tried writing my char (ABCD-etc.) array in C++ for practice but even then I forgot the basic syntax as I hadn't even touched genuine non-game programming for almost five years and am quite rusty.

I am discouraged, and am hoping this thread isn't dead since I haven't replied in over three days.

I think the most I can do is get the most I can out of the Zscript code I'm already studying until you reply again, and maybe try and split both things that I want to do (ammo counting and making a gun with multiple overlays) into two separate projects until I have them both down.
Post Reply

Return to “Scripting”