[ZScript] DropItem Amount Changed To ReadOnly?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!
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.

[ZScript] DropItem Amount Changed To ReadOnly?

Postby Lycanite » Tue Dec 12, 2017 6:00 pm

I currently use this class to map cvars to random monster spawners so that I can pick and choose what groups of monsters spawner via cvars.
Code: Select allExpand view
class CVARRandomSpawner : RandomSpawner
{
   override void BeginPlay()
   {
      int cvarAmountMin = 15;
      int cvarAmountMax = 19;
      string cvarAmountMap[20];
      cvarAmountMap[15] = 'spawners_nephrite';
      cvarAmountMap[16] = 'spawners_doom';
      cvarAmountMap[17] = 'spawners_heretic';
      cvarAmountMap[18] = 'spawners_hexen';
      cvarAmountMap[19] = 'spawners_blood';
      
      DropItem dropIter = GetDropItems();
      string lastNonCvarDrop = "";
      while (dropIter != null)
      {
         if (dropIter.Amount >= cvarAmountMin && dropIter.Amount <= cvarAmountMax)
         {
            CVar amountCvar = CVar.FindCVar(cvarAmountMap[dropIter.Amount]);
            int amount = amountCvar.GetInt();
            dropIter.Amount = amount;
         }
         else
         {
            lastNonCvarDrop = dropIter.Name;
         }
         dropIter = dropIter.Next;
      }
      
      Super.BeginPlay ();
   }
}


But it seems that Amount is now read only in the latest builds so I can no longer change it on this line
Code: Select allExpand view
dropIter.Amount = amount;


What's the workaround for this or is there a better way to do this in general?
User avatar
Lycanite
 
Joined: 13 Apr 2017
Discord: 3409

Re: [ZScript] DropItem Amount Changed To ReadOnly?

Postby Lycanite » Sat Dec 16, 2017 7:18 am

So in the end I decided just to copy the BeginPlay from the RandomSpawner class and just modify it from there, seems to work well again.

Code: Select allExpand view
class CVARRandomSpawner : RandomSpawner
{
   override void BeginPlay()
   {
      DropItem di;   // di will be our drop item list iterator
      DropItem drop; // while drop stays as the reference point.
      int n = 0;
      bool nomonsters = sv_nomonsters || level.nomonsters;

      //Super.BeginPlay();
      drop = di = GetDropItems();
      if (di != null)
      {
         while (di != null)
         {
            if (di.Name != 'None')
            {
               if (!nomonsters || !IsMonster(di))
               {
                  int amt = getCVARAmount (di.Amount);
                  if (amt < 0) amt = 1; // default value is -1, we need a positive value.
                  n += amt; // this is how we can weight the list.
               }
               di = di.Next;
            }
         }
         if (n == 0)
         { // Nothing left to spawn. They must have all been monsters, and monsters are disabled.
            Destroy();
            return;
         }
         
         // Then we reset the iterator to the start position...
         di = drop;
         
         // Take a random number...
         n = random[randomspawn](0, n-1);
         
         // And iterate in the array up to the random number chosen.
         while (n > -1 && di != null)
         {
            if (di.Name != 'None' &&
               (!nomonsters || !IsMonster(di)))
            {
               int amt = getCVARAmount (di.Amount);
               if (amt < 0) amt = 1;
               n -= amt;
               if ((di.Next != null) && (n > -1))
                  di = di.Next;
               else
                  n = -1;
            }
            else
            {
               di = di.Next;
            }
         }
         
         // So now we can spawn the dropped item.
         if (di == null || bouncecount >= MAX_RANDOMSPAWNERS_RECURSION)   // Prevents infinite recursions
         {
            Spawn("Unknown", Pos, NO_REPLACE);      // Show that there's a problem.
            Destroy();
            return;
         }
         else if (random[randomspawn]() <= di.Probability)   // prob 255 = always spawn, prob 0 = almost never spawn.
         {
            // Handle replacement here so as to get the proper speed and flags for missiles
            Class<Actor> cls = di.Name;
            if (cls != null)
            {
               Class<Actor> rep = GetReplacement(cls);
               if (rep != null)
               {
                  cls = rep;
               }
            }
            if (cls != null)
            {
               Species = Name(cls);
               readonly<Actor> defmobj = GetDefaultByType(cls);
               Speed = defmobj.Speed;
               bMissile |= defmobj.bMissile;
               bSeekerMissile |= defmobj.bSeekerMissile;
               bSpectral |= defmobj.bSpectral;
            }
            else
            {
               A_Log(TEXTCOLOR_RED .. "Unknown item class ".. di.Name .." to drop from a cvar random spawner\n");
               Species = 'None';
            }
         }
      }
   }
   
   int getCVARAmount (int amt)
   {
      int cvarAmountMin = 15;
      int cvarAmountMax = 19;
      string cvarAmountMap[20];
      cvarAmountMap[15] = 'spawners_nephrite';
      cvarAmountMap[16] = 'spawners_doom';
      cvarAmountMap[17] = 'spawners_heretic';
      cvarAmountMap[18] = 'spawners_hexen';
      cvarAmountMap[19] = 'spawners_blood';
      
      if (amt >= cvarAmountMin && amt <= cvarAmountMax)
      {
         CVar amountCvar = CVar.FindCVar(cvarAmountMap[amt]);
         amt = amountCvar.GetInt();
      }
      
      return amt;
   }
}


I suppose I should look into adding my own struct or something which can hold more information rather than using the amount as a hack, but this works for now!
User avatar
Lycanite
 
Joined: 13 Apr 2017
Discord: 3409


Return to Scripting

Who is online

Users browsing this forum: No registered users and 2 guests