DECORATE Weapon Questions

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!)
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

DECORATE Weapon Questions

Post by Exosphere »

Need a little help with a few weapon conundrums.

1. I have seen weapons in other mods (most notably Russian Overkill's Powercube weapon at least from what I remember) where the ammo recharges over time. However, I have been sort of lost on how to put it in code. Are there any clear examples that I look at to get a better understanding how this recharging works? Pretty much solved

2. One of the weapons for my mods I am planning on adding is a rifle that has the ability to fire three different projectiles and also being able to cycle through them. However, I would ideally like to have it so that the weapon uses three different kinds of ammo, one for each respective projectile. I am completely stumpted as how to make this a reality, both the cycling AND WHILE using three different ammo types; I do have some ideas, but I would really like to see if anyone has done this before and can clearly explain how to acheive this OR there are any clear and fairly simple examples I can look at.

Any help is appreciated.
Last edited by Exosphere on Mon Dec 11, 2017 12:22 pm, edited 2 times in total.
User avatar
R4L
Global Moderator
Posts: 400
Joined: Fri Mar 03, 2017 9:53 am
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 11 Pro
Graphics Processor: nVidia (Modern GZDoom)
Contact:

Re: DECORATE Weapon Questions

Post by R4L »

The way I picture your first question working, is a constant reload loop that gives 1 to a custom ammo type every few seconds. Your fire state would allow a shot when you have a certain amount of ammo recharged. You could even have it so you can fire weaker shots at certain recharged levels. For a weapon that acts similar to that, I'd look at wildweasel's Diaz mod (I'm always referencing this, but for obvious reasons!) for the Psionic Amp weapon. It constantly charges up while it's equipped.

For your second question, you might want to check out Lithium. The rifle has a "modal" upgrade that allows you to switch from full auto to burst, and then have a third mode that fires grenades IIRC. Also, Russian Overkill's Rasputin weapon seems to have three custom inventory items defined, each one for each different ammo mode, so there's also that...
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

Minor Breakthrough:

I decided to go with ACS for the mode changer instead of only DECORATE, and have been able to successfully change to the shotgun mode. However, once it is in Shotgun mode, it can't be changed to Rocket mode, and I have no idea why that is. Included is the "Cycler" ACS code as well as the switching portion of the weapon.

Code: Select all

#library "cyclr"
#include "zcommon.acs"

script "Cycler" (int mode)
{
	int init = 1;
	mode = init;
	
	if (CheckWeapon("OICW") == 1)
	{
		mode++;
		
		if(mode == init)
		{
			TakeInventory("RocketMode", 1);
			GiveInventory("RifleMode", 1);
			Log(s:"9.5x25mm Caseless Rifle Mode: ACTIVE.");
		}
		if(mode == 2)
		{
			TakeInventory("RifleMode", 1); 
			GiveInventory("ShotgunMode", 1);
			Log(s:"10ga Shotgun Mode: ACTIVE.");
		}
		if(mode == 3)
		{
			TakeInventory("ShotgunMode", 1);
			GiveInventory("RocketMode", 1);
			Log(s:"20mm Smart Rocket Mode: ACTIVE.");
		}
		if(mode == 4)
		{ mode = init; }
	}
}

Code: Select all

Fire:
			TNT1 A 0 A_JumpIfInventory("RifleMode", 1, "RifleFire")
			TNT1 A 0 A_JumpIfInventory("ShotgunMode", 1, "ShotgunFire")
			TNT1 A 0 A_JumpIfInventory("RocketMode", 1, "RocketFire")
			Goto Ready

AltFire:
			PLSG A 1 ACS_NamedExecute("Cycler", 0, 1, 0, 0)
			OICW A 1 A_Log("Mode Switched")
			Goto Ready
Anyone have any ideas/solutions on why this is partially working?
User avatar
Apeirogon
Posts: 1605
Joined: Mon Jun 12, 2017 12:57 am

Re: DECORATE Weapon Questions

Post by Apeirogon »

Exosphere wrote:Need a little help with a few weapon conundrums.

1. I have seen weapons in other mods (most notably Russian Overkill's Powercube weapon at least from what I remember) where the ammo recharges over time. However, I have been sort of lost on how to put it in code. Are there any clear examples that I look at to get a better understanding how this recharging works?

Code: Select all

actor constantlu_reloading_weapon:weapon
{
   Weapon.SelectionOrder 7980
   Weapon.KickBack 60
   Weapon.AmmoUse 1
   Scale 0.95
   Weapon.AmmoType "charging_cell"   
   Inventory.PickupMessage "What a cheater weapon I discover..."
   Obituary "%o was beat by %k's ace in the sleeve"
   +WEAPON.NOALERT
   States
   {
   Ready:
	 DTRS ABCDE 1 a_weaponready
         tnt1 q 0 a_giveinventory("charging_cell",1)//give to you every tick that you hold it in hand and dont shoot one "charging_cell"
	 Loop

   Deselect:
     DTEK A 1 A_Lower
   loop

   Select:
	 TNT1 A 0 A_Raise
	 Wait

   Fire:
     DTKF A 2 Bright A_FireCustomMissile("cheat_projectile",0,1,0,0,0,0)
	 DTKF B 1 Bright A_Light2
     DTKF C 2 A_Light0
     TNT1 A 0 A_ReFire
     Goto Ready
  
   Spawn:
     DTEP A -1
     Stop
     }
}
Or look at russian overkill powercube. If you try look at it pillowbluster dont burst into your room, with madly rolling eyes and words "CLOSE SLADE, HANDS UP THAT I CAN SEE IT!!!"
Exosphere wrote:OR there are any clear and fairly simple examples I can look at.
TR_SturmmanM97 from the throoper.
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

Thanks for the input Apeirogon. You didn't need to a full example weapon, all I really needed was this:

Code: Select all

Ready:
    DTRS ABCDE 1 a_weaponready
         tnt1 q 0 a_giveinventory("charging_cell",1)//give to you every tick that you hold it in hand and dont shoot one "charging_cell"
    Loop
But still, thank you anyway.
Apeirogon wrote: Or look at russian overkill powercube. If you try look at it pillowbluster dont burst into your room, with madly rolling eyes and words "CLOSE SLADE, HANDS UP THAT I CAN SEE IT!!!"
Don't worry, I'm not making a weapon that is identical to the PowerCube, I just needed to know how it recharged ammo.

(Still looking for any input from anyone on the issues with the ACS and DECORATE code I posted)
User avatar
Apeirogon
Posts: 1605
Joined: Mon Jun 12, 2017 12:57 am

Re: DECORATE Weapon Questions

Post by Apeirogon »

You ACS code can be easy implement in decorate.

Code: Select all

altfire:
sprite letter number 
{
if (countinv("shotgun_mode")==1)
{
a_TakeInventory("shotgun_mode", 1);
a_GiveInventory("rocket_mode", 1);
A_Print(s:"20mm Smart Rocket Mode: ACTIVE.");
}

else if (countinv("rocket_mode")==1)
{
a_TakeInventory("rocket_mode", 1);
A_Print(s:"9.5x25mm Caseless Rifle Mode: ACTIVE.");
}

else if (countinv("shotgun_mode")==1 && countinv("rocket_mode")==1)
{
GiveInventory("ShotgunMode", 1);
A_Print(s:"10ga Shotgun Mode: ACTIVE.");
}
}
User avatar
Blitzky
Posts: 29
Joined: Tue Jan 25, 2011 6:02 pm
Location: Chicagoland, Illinois

Re: DECORATE Weapon Questions

Post by Blitzky »

I'll admit my knowledge of ACS is a bit limited, but...

Your variable 'mode' only exists within your script.

Every time you call this script, it checks to see if the player is holding the correct weapon, then increments mode by 1.
However, every time the script is called, it also sets 'mode' to be equal to 'init', which is 1.

Essentially, you're calling a script that assigns mode to 1, then increments it to 2 every time, meaning it's constantly trying to switch from rifle mode to shotgun mode.
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

Blitzky wrote:I'll admit my knowledge of ACS is a bit limited, but...

Your variable 'mode' only exists within your script.

Every time you call this script, it checks to see if the player is holding the correct weapon, then increments mode by 1.
However, every time the script is called, it also sets 'mode' to be equal to 'init', which is 1.

Essentially, you're calling a script that assigns mode to 1, then increments it to 2 every time, meaning it's constantly trying to switch from rifle mode to shotgun mode.
Interesting. I'm also not as knowledgable in ACS, but still willing to learn. Do you have any suggestions on fixes I could change to make it work?
User avatar
Blitzky
Posts: 29
Joined: Tue Jan 25, 2011 6:02 pm
Location: Chicagoland, Illinois

Re: DECORATE Weapon Questions

Post by Blitzky »

Here's my 'analysis':

Code: Select all

DECORATE
Fire:
         TNT1 A 0 A_JumpIfInventory("RifleMode", 1, "RifleFire")
         TNT1 A 0 A_JumpIfInventory("ShotgunMode", 1, "ShotgunFire")
         TNT1 A 0 A_JumpIfInventory("RocketMode", 1, "RocketFire")
         Goto Ready

AltFire:
         PLSG A 1 ACS_NamedExecute("Cycler", 0, 1, 0, 0)  //Call 'Cycler' with a value of 1 for the first argument
         OICW A 1 A_Log("Mode Switched")
         Goto Ready
=========================================================
ACS
#library "cyclr"
#include "zcommon.acs"

script "Cycler" (int mode)	//Value of 1 is passed to 'mode' by the altfire state
{
   int init = 1;	//'init' is created and given a value of 1
   mode = init;	//'mode' is given the value of 'init'(1)
   
   if (CheckWeapon("OICW") == 1)  //Make sure the player is using the OICW
   {
      mode++;	//'mode' is incremented, now a value of 2
      
      if(mode == init)	//'mode' is 2, skip this part
      {
         TakeInventory("RocketMode", 1);
         GiveInventory("RifleMode", 1);
         Log(s:"9.5x25mm Caseless Rifle Mode: ACTIVE.");
      }
      if(mode == 2)	//'mode' is 2, execute this
      {
         TakeInventory("RifleMode", 1); 
         GiveInventory("ShotgunMode", 1);
         Log(s:"10ga Shotgun Mode: ACTIVE.");
      }
      if(mode == 3)	//'mode' is 2, nothing beyond is executed
      {
         TakeInventory("ShotgunMode", 1);
         GiveInventory("RocketMode", 1);
         Log(s:"20mm Smart Rocket Mode: ACTIVE.");
      }
      if(mode == 4)
      { mode = init; }
   }
}
This is what I mentioned earlier. You defined 'mode' as an argument here, and pass it a value of 1 when altfire is used.
However, your script immediately gives it a value of 1 regardless by setting it equal to 'init'.
To remedy this without editing your script, you would need to write a few more lines in the altfire state that pass values of 1, 2, or 3, depending on which of the three dummy items the player is currently holding.
The 'init' value is redundant, as it is the same as giving mode a value of 1.

However, you can completely avoid the use of variables like this:

Code: Select all

#library "cyclr"
#include "zcommon.acs"
 
script "Cycler" (void)
{
   if (CheckWeapon("OICW") == 1) //Make sure the player is using the OICW
   {
      if(CheckInventory("RifleMode")) //Execute if the player has "RifleMode"
      {
         TakeInventory("RifleMode", 1); 
         GiveInventory("ShotgunMode", 1);
         Log(s:"10ga Shotgun Mode: ACTIVE.");
      }
	  
	  else if(CheckInventory("ShotgunMode")) //Execute if the player has "ShotgunMode"
      {
         TakeInventory("ShotgunMode", 1);
         GiveInventory("RocketMode", 1);
         Log(s:"20mm Smart Rocket Mode: ACTIVE.");
      }
	  
	  else if(CheckInventory("RocketMode"))	//Execute if the player has "RocketMode"
      {
         TakeInventory("RocketMode", 1);
         GiveInventory("RifleMode", 1);
         Log(s:"9.5x25mm Caseless Rifle Mode: ACTIVE.");
      }  
   }
}
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

SIgnificant Update:

After some tinkering, and with a little help from Blitzky, I was able to successfully have it so that the weapon can switch between the rifle, shotgun, and rocket launcher without fail. Now with that complete, the final aspect for the weapon that I would want to have is the ability to reload at will or once the ammo from the magazine is depleated. (The gun will use infinite ammo.) However, with the method that I had implemented, it doesnt function properly, in that it doesnt reload (with all weapons) and stalls on the rocket mode after firing one rocket. (I will include the code snippets for people to look at, along with the ACS of the improved cycler.) Let me know if anything needs to be clairified.

ACS

Code: Select all

if (CheckWeapon("OICW") == 1)
	{
		if(CheckInventory("RocketMode")==1 && CheckInventory("RifleMode")==0)
		//If Rocket Mode is ACTIVE and RifleMode is INACTIVE 
		{
			TakeInventory("RocketMode", 1);
			GiveInventory("RifleMode", 1);
			Print(s:"9.5x25mm Caseless Rifle Mode: ACTIVE.");
		}
		else if(CheckInventory("RifleMode")==1 && CheckInventory("ShotgunMode")==0)
		//If Rifle Mode is ACTIVE and Shotgun Mode is INACTIVE
		{
			TakeInventory("RifleMode", 1); 
			GiveInventory("ShotgunMode", 1);
			Print(s:"10ga Shotgun Mode: ACTIVE.");
		}
		else if(CheckInventory("ShotgunMode")==1 && CheckInventory("RocketMode")==0)
		//If Shotgun Mode is ACTIVE and RocketMode is INACTIVE
		{
			TakeInventory("ShotgunMode", 1);
			GiveInventory("RocketMode", 1);
			Print(s:"20mm Smart Rocket Mode: ACTIVE.");
		}
	}
DECORATE

Code: Select all

ACTOR RifleMag : Ammo
{
	Inventory.MaxAmount 99
	+INVENTORY.PERSISTENTPOWER
	+INVENTORY.INVBAR
	+IGNORESKILL
}
//Magazine Example

Reload:
			TNT1 A 0 A_JumpIfInventory("RifleMag", 0, "RifleReload")
			etc
			Goto Ready
RifleReload:
			OICW A 1 A_GiveInventory("RifleMag", 99)
			Goto Ready
ShotgunReload:
			~ (same syntax as above)
			Goto Ready
RocketReload:
			~ (same syntax as above)
			Goto Ready
User avatar
R4L
Global Moderator
Posts: 400
Joined: Fri Mar 03, 2017 9:53 am
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 11 Pro
Graphics Processor: nVidia (Modern GZDoom)
Contact:

Re: DECORATE Weapon Questions

Post by R4L »

For reloading, you will want to do two ammo types for each mode. One type is your magazine count, the other is your reserve. In your Reload state you create a new looping state that adds 1 to your magazine and takes 1 from reserve if the weapon magazine is not full. If it is full, you go to your second reload state where you finish up the reload. Do a check in your Fire state for when there is no ammo, and jump to the Reload state.
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

R4L wrote:For reloading, you will want to do two ammo types for each mode. One type is your magazine count, the other is your reserve. In your Reload state you create a new looping state that adds 1 to your magazine and takes 1 from reserve if the weapon magazine is not full. If it is full, you go to your second reload state where you finish up the reload. Do a check in your Fire state for when there is no ammo, and jump to the Reload state.
I gave it a shot, however I am pretty sure this isnt the method you are referring to. Here is the code.

Code: Select all

ACTOR RifleMagReserve : Ammo
{
	Inventory.MaxAmount 99
	+INVENTORY.PERSISTENTPOWER
	+INVENTORY.INVBAR
	+IGNORESKILL
}
ACTOR RifleMagCount : Ammo
{
	Inventory.Amount 99
	+IGNORESKILL
}

States
{
RifleFire:
			OICW A 2 A_FireCGun
			OICW A 1 A_TakeInventory("RifleMagCount", 1)
			OICW A 1 A_Refire
			OICW A 1 A_JumpIfNoAmmo("RifleReload")
			Goto Ready
RifleReload:
			OICW A 1 A_TakeInventory("RifleMagReserve", 1)
			OICW A 1 A_GiveInventory("RifleMagCount", 1)
			OICW A 1 A_JumpIfInventory("RifleMagCount", 99, "RifleReady")
			Loop
RifleReady:
			TNT1 A 0 A_PlaySound("weapons/shotgr", CHAN_AUTO, 50.0)
			OICW A 1 A_Print("Rifle Reloaded")
			Goto Ready
}
However, I am still encountering the problem of when the Rocket launcher is fired once, it can't be fired again and I cant switch to any other mode.

Anyone have any thoughts?
User avatar
R4L
Global Moderator
Posts: 400
Joined: Fri Mar 03, 2017 9:53 am
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 11 Pro
Graphics Processor: nVidia (Modern GZDoom)
Contact:

Re: DECORATE Weapon Questions

Post by R4L »

JumpIfNoAmmo should be the first thing in your fire state.

EDIT: Deleted most of my post because it was just plain incorrect. Looking at your new code for reloading, it seems that you have only defined how the rifle reloads, not the other two weapons.
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: DECORATE Weapon Questions

Post by Exosphere »

R4L wrote:JumpIfNoAmmo should be the first thing in your fire state.

EDIT: Deleted most of my post because it was just plain incorrect. Looking at your new code for reloading, it seems that you have only defined how the rifle reloads, not the other two weapons.
Its ok about deleting you post, dont worry about it. :) The other reloads are mostly the same, but I can the adding details on my own.

Anyway, another update. I was still experimenting with the decorate functions before trying out ACS again. Luckily, I was surprisingly able to make it work, to an extent. The weapon will still fires even if the ammo is empty in their corresponding magazines. The +AMMO_OPTIONAL flag isnt present in the weapon.

ACS

Code: Select all

script "Reloader" (void) 
{
	if (CheckWeapon("OICW") == 1)
	{
		if(CheckInventory("RifleMode")==1)
		{ GiveInventory("RifleMag", 25); Print(s:"Rifle Reloaded"); }
	}
}
DECORATE

Code: Select all

RifleFire:
			OICW A 1 A_JumpIfNoAmmo("Reload")
			OICW A 1 BRIGHT A_FireProjectile()
			OICW A 1 A_TakeInventory("RifleMag", 1)
			OICW A 1 A_Refire
			Goto Ready

Reload:
			OICW A 1 ACS_NamedExecute("Reloader", 0, 0, 0, 0)
			//play sound indicating weapon has been reloaded
			Goto Ready
Last edited by Exosphere on Mon Dec 11, 2017 3:12 pm, edited 1 time in total.
User avatar
R4L
Global Moderator
Posts: 400
Joined: Fri Mar 03, 2017 9:53 am
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 11 Pro
Graphics Processor: nVidia (Modern GZDoom)
Contact:

Re: DECORATE Weapon Questions

Post by R4L »

Wouldn't be because your script is named "reload" and your calling "reloader" in your Reload state, would it?
Post Reply

Return to “Scripting”