[ZS] Very conditional pickup (solved!)

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
NeoTerraNova
Posts: 153
Joined: Tue Mar 14, 2017 5:18 pm
Location: Western North Southlandia (East Side)

[ZS] Very conditional pickup (solved!)

Post by NeoTerraNova »

Hey, everyone. I hope you're all doing well. Once more, I need assistance, as I just can't figure out what I'm doing wrong.

I have four distinct weapons, but a total of ten "actors" (the extra six being special conditional clones of the four base weapons) that use the same type of ammo, but for specific coding reasons, don't share the same ammo pool (Weapon A and its inherited clones A1 and A2 use the same pool, Weapon B and its clone B1 use the same pool, etc., but are both the same caliber and would pick up and use the same bullets).

I want to have loose bullets drop/findable that can "top off" the active magazines in these weapons (this is in addition to complete magazines, but that has no bearing on this problem).

On pickup, I want a chunk of code that does the following:

1) Checks to see if the Player even has one of the weapons in their inventory

2) Checks to make sure that by picking up the lone bullet, the magazine isn't filled up too far/over max capacity.

3) I'm not too worried about "fill priority" (which weapons get the loose bullets first if more than one weapon is held), but I would like to understand how this is achieved so I can set this priority myself.


I have been working on my own to make code that works, and I've come up with this:

Code: Select all

Class Loose9mm1Z : CustomInventory
{
Default
{
	Scale 0.2;
	inventory.pickupsound "pickup/9mm";
	inventory.pickupmessage "Loose Ammunition: 9mm round";
	-COUNTITEM
    }
    states
	{
Pickup:
  TNT1 A 0
  {
    let Z21M = FindInventory("Z21AM");
    let Z211 = FindInventory("Z21");
    let Z212 = FindInventory("Z21SH");
    let Z213 = FindInventory("Z21HH");
    if(Z21M.Amount + 1 <= Z21M.MaxAmount)
     {
       if(Z211 != null)
       {
        A_GiveInventory("Z21AM",1);
       } 
       else if(Z212 != null)
       {
         A_GiveInventory("Z21AM",1);
       }
       else if(Z213 != null)
       {
         A_GiveInventory("Z21AM",1);
       } 
       else
       { 
        return invoker.FindState("Nothing");
      }
  return invoker.FindState(null); 
     }
  return invoker.FindState(null); 
  }
  TNT1 A 0 A_RailWait; 
  Stop;
  
    Nothing:
        TNT1 A 0 A_PRINT("I can't take this.");
    Fail;
	Spawn:
       9MMB A -1 Bright;
	Stop;
	}
}


While this code is functional, it only works for one weapon (the "Z21" pistol). I tried to expand it, and through several iterations, ended up with failure. My final attempt so far is this:

Code: Select all

Class Loose9mm1Z : CustomInventory
{
Default
{
	Scale 0.2;
	inventory.pickupsound "pickup/9mm";
	inventory.pickupmessage "Loose Ammunition: 9mm round";
	-COUNTITEM
    }
    states
	{
Pickup:
  TNT1 A 0
  {
    let Z21M = FindInventory("Z21AM");
    let LEMM = FindInventory("Mk27AM");
    let G44M = FindInventory("G44AM");
    let MP4M = FindInventory("MP4AM");
    let Z211 = FindInventory("Z21");
    let Z212 = FindInventory("Z21SH");
    let Z213 = FindInventory("Z21HH");
    let LEM1 = FindInventory("Mk27");
    let LEM2 = FindInventory("Mk27SH");
    let LEM3 = FindInventory("Mk27HH");
    let G441 = FindInventory("G44");
    let G442 = FindInventory("G44SH");
    let MP41 = FindInventory("MP4");
    let MP42 = FindInventory("MP4SD");
    if(Z21M.Amount + 1 <= Z21M.MaxAmount)
     {
       if(Z211 != null && Z212 != null && Z213 != null)
       {
        A_GiveInventory("Z21AM",1);
       }
    else if(LEMM.Amount + 1 <= LEMM.MaxAmount)
     {
       if(LEM1 != null && LEM2 != null && LEM3 != null)
       {
        A_GiveInventory("Mk27AM",1);
       } 
    else
       { 
        return invoker.FindState("Nothing");
       }
  return invoker.FindState(null); 
     }
  return invoker.FindState(null); 
     }
  return invoker.FindState(null); 
     }
  TNT1 A 0 A_RailWait; 
  Stop;
  
    Nothing:
        TNT1 A 0 A_PRINT("I can't take this.");
    Fail;
	Spawn:
       9MMB A -1 Bright;
	Stop;
	}
}
The base weapons ("Z-21" and "G44" and "LEM" and "MP4") each have clones for specific reasons, but the clones share the ammo pool of the base weapons since you can't carry more than one of each weapon type (so, you can't have, for example, a basic Z-21 and a Z-21SH). I tried to condense the checks into one grouping here and test it, but it crashes when I try to pick up the ammo. If I swap the checks (checking if the weapons are in inventory first, then checking MaxAmount) then I pick up the item, but do not gain the bullet into the weapon, it just vanishes.

I tried to logically expand the first code into multiple entries (repeating the syntax of the Z-21 checks to the following weapons) but it didn't work, and I couldn't figure out how to make each check, look for both the existence of the weapon in inventory, AND make sure they weren't overfilling the weapons in question.

Any advice or guidance is greatly appreciated! Thanks to anyone that stops by to help.



EDIT

I managed to fix it on my own, though I have ZERO idea how I pulled this off. My problem lied in the fact that I was breaking the "order of checking" into the wrong parts of the code (I don't know the technical term for this). What I should have done, and ended up doing, was to combine the check for each separate weapon into the same line as the check for ammo overcapacity (again, sorry, I don't know the technical terms for this).

After tinkering around, this is the code that I got. I'm putting it up here in case anyone else wants to do something like this.

Code: Select all

Class Loose9mm1Z : CustomInventory
{
Default
{
	Scale 0.2;
	inventory.pickupsound "pickup/9mm";
	inventory.pickupmessage "Loose Ammunition: 9mm round";
	-COUNTITEM
    }
    states
	{
Pickup:
  TNT1 A 0
  {
    let Z21M = FindInventory("Z21AM");
    let LEMM = FindInventory("Mk27AM");
    let G44M = FindInventory("G44AM");
    let MP4M = FindInventory("MP4AM");
    let Z211 = FindInventory("Z21");
    let Z212 = FindInventory("Z21SH");
    let Z213 = FindInventory("Z21HH");
    let LEM1 = FindInventory("Mk27");
    let LEM2 = FindInventory("Mk27SH");
    let LEM3 = FindInventory("Mk27HH");
    let G441 = FindInventory("G44");
    let G442 = FindInventory("G44SH");
    let MP41 = FindInventory("MP4");
    let MP42 = FindInventory("MP4SD");
    if(Z211 != null || Z212 != null || Z213 != null && Z21M.Amount + 1 <= Z21M.MaxAmount)
     {
        A_GiveInventory("Z21AM",1);
       }
    else if(LEM1 != null || LEM2 != null || LEM3 != null && LEMM.Amount + 1 <= LEMM.MaxAmount)
       {
        A_GiveInventory("Mk27AM",1);
       } 
    else if(G441 != null || G442 != null && G44M.Amount + 1 <= G44M.MaxAmount)
       {
        A_GiveInventory("G44AM",1);
       } 
    else if(MP41 != null || MP42 != null && MP4M.Amount + 1 <= MP4M.MaxAmount)
       {
        A_GiveInventory("MP4AM",1);
       } 
    else
       { 
        return invoker.FindState("Nothing");
       }
  return invoker.FindState(null); 
     }
  TNT1 A 0 A_RailWait; 
  Stop;
  
    Nothing:
        TNT1 A 0 A_PRINT("All my 9mm weapons are full.");
    Fail;
	Spawn:
       9MMB A -1 Bright;
	Stop;
	}
}
The text bits "Z21" and "LEM" and "G44" and "MP4" are the weapons. "AM" stands for "Active Magazine" (part of a code chunk I got from someone else to redo the entire weapon system) and stands for the magazine in the gun. This code chunk will only fill the weapons in your current inventory, in this order of preference. While I would like to have some way in a menu option to allow the user to select what weapon gets filled first according to THEIR preference, that's far beyond my abilities.

Return to “Scripting”