Remove Pickup, Re-Create Pickup

Started by Mötley, Oct 31, 2016, 01:31 AM

Previous topic - Next topic

Mötley

I have uploaded an example script of how to operate pickups due to weapon pickup issues, Not being able to remove and re-spawn etc.
"The original methods for pickups are nasty, This method is better ;)"

In this script you will also notice an example of running other time intervals off of one 'NewTimer'.

You Do NOT need many timers for loops only one. This loop example is highly expandable when modifying the time intervals.

Disclaimer: I can not be held accountable for you running bad coding in these timed loops

Quote from: KAKAN on Jul 17, 2016, 01:58 PMDon't use many pickups at a place, it will turn your server into shit.

The pickups in the server were only used as an example, They wont give you armour etc, There only examples.

You will need to convert your weapons from xml to CreateWeaponPickups(model, x, y, z)
Don't forget to remove the time prints "Added for noobs"

Enjoy the first ever pickup removal script ;)

/* Weapon Script */

#Motley
#10/30/16
#Note-pad++

max_weapons <- 2000;

weapon_pos_x <- array(max_weapons, 0);
weapon_pos_y <- array(max_weapons, 0);
weapon_pos_z <- array(max_weapons, 0);

weapon_picked <- array(max_weapons, false);

pickuped_weapon <- array(max_weapons, 0);
weapon_time <- array(max_weapons, 0);

Minutes <- 0;
Seconds <- 0;
Hours <- 0;

function onScriptLoad()
{
    CreateWeaponPickups( 274, 368.053, 1050.34, 19.213) // PISTOL
    CreateWeaponPickups( 283, 365.96, 1050.13, 19.213) // UZI
    CreateWeaponPickups( 277, 363.171, 1050.22, 19.213) // SHOTGUN
    CreateWeaponPickups( 366, 385.615, 1210.76, 19.4767) // HEALTH
    CreateWeaponPickups( 366, 468.686, 695.558, 12.1433) // HEALTH
    CreateWeaponPickups( 262, 407.347, -487.586, 12.3432) // BASEBALL BAT
    CreateWeaponPickups( 368, 385.499, -469.809, 12.3432) // ARMOUR
   
    NewTimer("Loop_Seconds", 1000, 0);
}

// Our server loop
function Loop_Seconds()
{
  //pickup-system
  for (local i=0;i<max_weapons;i++)
  {
    //pickup-time
    if (weapon_picked[i] == true)
    {
      if (weapon_time[i] > 0)
      {
         weapon_time[i]--;
         if (weapon_time[i] == 0)
         {
            // Create the pickup
            CreateWeaponPickups(pickuped_weapon[i], weapon_pos_x[i], weapon_pos_y[i], weapon_pos_z[i]);

            // Clear the arrays
            pickuped_weapon[i] = 0;
            weapon_pos_x[i] = 0;
            weapon_pos_y[i] = 0;
            weapon_pos_z[i] = 0;
            weapon_time[i] = 0;
            // Clear the arrays
         }
      }           
    }
    //pickup-time
  }
  //pickup-system
   
   //time durrations
   if ( Seconds == 60 )
   {
           Seconds = 0;
           Minutes++;

           Loop_Minutes();
   }

   if ( Minutes == 60 )
   {

           Minutes = 0;
           Hours++;

           Loop_Hours();
   }

   Seconds++;
   print("Seconds " +  Seconds);
   //time durrations
}

// Our seconds loop
function Loop_Minutes()
{
     print("Minutes " +  Minutes);
}

// Our minute loop
function Loop_Hours()
{
     print("Hours " +  Hours);
}


function CreateWeaponPickups(model, x, y, z) {
  local g_pickup = CreatePickup(model, Vector(x, y, z));
 
  weapon_picked[g_pickup.ID] = false;
   
  return g_pickup; 
}

function onPickupPickedUp(player, pickup) {
 
  local model = pickup.Model;
   
  switch (model)
  {

   /* PISTOL */
case 274:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      print(pickuped_weapon[pickup.ID]);
      break;
   /* UZI */
case 283:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      break;
   /* SHOTGUN */
case 277:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      break;
   /* HEALTH */
case 366:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      break;
   /* BASEBALL BAT */
case 262:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      break;
   /* ARMOUR */
   case 368:
      pickup.Remove();
      pickuped_weapon[pickup.ID] = model;
      weapon_pos_x[pickup.ID] = pickup.Pos.x;
      weapon_pos_y[pickup.ID] = pickup.Pos.y;
      weapon_pos_z[pickup.ID] = pickup.Pos.z;
      weapon_time[pickup.ID] = 30;
      break;
  }
 
  weapon_picked[pickup.ID] = true;
   
  return true;
}

.

#1
Do I even want to comment on this one?

local g_pickup = CreatePickup(model, Vector(x, y, z));
You clearly misunderstood the role of the 'g_' prefix in variable names.

weapon_pos_x <- array(max_weapons, 0);
weapon_pos_y <- array(max_weapons, 0);
weapon_pos_z <- array(max_weapons, 0);

Seriously though? Why not just an array of vectors:
weapon_pos <- array(max_weapons);
foreach (i, v in wepon_pos) weapon_pos[i] = Vector(0, 0, 0);

Or simpler:
weapon_pos = array(max_weapons);
weapon_pos.apply(@(v) Vector(0, 0, 0));

Actually, why not just a class for all the stuff and search in an array just once not 1000 times.

That switch statement can be collapsed to a single case:
switch (model)
{
    case 274:
    case 283:
    case 277:
    case 366:
    case 262:
    case 368:
    {
        pickup.Remove();
        pickuped_weapon[pickup.ID] = model;
        weapon_pos_x[pickup.ID] = pickup.Pos.x;
        weapon_pos_y[pickup.ID] = pickup.Pos.y;
        weapon_pos_z[pickup.ID] = pickup.Pos.z;
        weapon_time[pickup.ID] = 30;
        print(pickuped_weapon[pickup.ID]);
    } break;
}

Also, if you have more than one statement in your case then you're indicated to use braces {  } to group all the statements as one. Not sure if this is enforced on Squirrel, but some languages do. And it's something you should have in your habits.

But to be honest, I don't even have what to poke fun off. The entire thing is a nonsense and a total waste of processing power.

Did anyone here ever touched a manual on programming? Just for lolz, to see what's in there. Even the Squirrel manual is fine. As long as it's a manual.
.

Mötley

Interesting.
I honestly only picked up small time coding a year ago, Haven't been able to do better studies, Yet not for long periods of time.


This is the first pickup removal script, I am noob'ish I will be honest, But I really try obviously. Someday I plan to actually go to school.


I would love to see you release your own version, You could do yours way better, And I will remove mine :).

.

#3
Quote from: Mötley on Oct 31, 2016, 02:23 AMI would love to see you release your own version, You could do yours way better, And I will remove mine :).

I'm not really sure what the need for this thing is or what is it supposed to do. I didn't understood the first time and I don't understand now either. The code is just so nonsense to put it together and see a purpose.

But if I ever understand what's this supposed to do then yeah, I promise I'll do a proper version just to prove something.

EDIT: Actually, now I get it. This is supposed to destroy pickups and then re-create them later. Am I right?
.

Mötley

The objective is to be able to enter a pickup, Instead of setting the alpha remove it,
When you use .Remove the pickup will never re_create "It's officially gone", Thats why I used arrays to store the pickups data. I had to run a check so I used a bool for true/false upon the pickup being removed.

Once 30 seconds passes by the pickup will re-create just like on Scriptload, And the information in the arrays are cleared.

I am not that good but I seriously did what I could to make it happen.

Thijn

Quote from: . on Oct 31, 2016, 02:06 AMAlso, if you have more than one statement in your case then you're indicated to use braces {  } to group all the statements as one. Not sure if this is enforced on Squirrel, but some languages do. And it's something you should have in your habits.
I've never seen that before in my life, not online in other code either. What kind of languages enforce this?

.

Quote from: Thijn on Oct 31, 2016, 06:59 AMI've never seen that before in my life, not online in other code either. What kind of languages enforce this?

C++ for example. It's not required all the time. Mostly when you declare variables. But it's not a bad habit to have because you never know when you modify code and forget about them.
.

.

#7
Anyway, I've spent a couple minutes on making a snippet. The goal was to only process anything if you absolutely have to. Not iterate thousands of elements each second for no reason at all.

Here you go:
// ------------------------------------------------------------------------------------------------
g_ManagedPickups <- {};
g_DormantPickups <- [];
g_PendingPickups <- [];

// ------------------------------------------------------------------------------------------------
class PickupState
{
    // State properties
    mTimer = 0
    mPosition = null
    mWorld = -1
    mModel = -1
    mAutomatic = -1
    mQuantity = -1
    mDelay = 0
    mTag = ""
    // Base constructor
    function constructor(tag, delay, pickup)
    {
        // Take snapshot of the pickup properties
        mPosition = pickup.Pos;
        mWorld = pickup.World;
        mModel = pickup.Model;
        mAutomatic = pickup.Automatic;
        mQuantity = pickup.Quantity;
        // Store the additional pickup information
        mDelay = delay;
        mTag = tag;
    }
}

// ------------------------------------------------------------------------------------------------
function PickupPulse()
{
    // Don't even bother to enter a loop if there are no dormant pickups
    if (g_DormantPickups.len() > 0)
    {
        for (local i = 0, n = g_DormantPickups.len(); i < n;)
        {
            // Grab the pickup state
            local state = g_DormantPickups[i];
            // Update the remaining time
            if (--state.mTimer > 0)
            {
                ++i; // There's still some time left on this one
            }
            else
            {
                // Add it to the list of pickups pending to be created
                g_PendingPickups.push(state);
                // Remove it from the list of dormant pickups
                g_DormantPickups.remove(i);
                // The size of the dormant pickups list has changed
                --n;
            }
        }
    }
    // Don't even bother to enter a loop if there are no pending pickups
    if (g_PendingPickups.len() > 0)
    {
        foreach (state in g_PendingPickups)
        {
            // Create the pickup instance as accurate as the original
            local inst = CreatePickup(state.mModel, state.mWorld, state.mQuantity, state.mPosition, 0, state.mAutomatic);
            /*
             * If we fail to create it (out of slots) here then we can't throw an error like in the beginning
             * Therefore, your pickup state will be lost. Not that you would need it anymore now.
            */
            // Add it back to the list of managed pickups
            if (inst != null)
            {
                g_ManagedPickups.rawset(inst.ID, state);
            }
        }
        // We can clear the pending list now
        g_PendingPickups.clear();
    }
}

NewTimer("PickupPulse", 1000, 0);

// ------------------------------------------------------------------------------------------------
function CreateManagedPickup(tag, time, ...)
{
    // Add the `this` environment
    vargv.insert(0, this);
    // Create the pickup instance
    local inst = CreatePickup.acall(vargv);
    // Validate the instance
    if (!inst)
    {
        throw "Cannot create the pickup instance";
    }
    // Manage this pickup now
    g_ManagedPickups.rawset(inst.ID, PickupState(tag, time.tointeger(), inst));
}

// ------------------------------------------------------------------------------------------------
function RemoveManagedPickup(tag)
{
    // See the pickup is in the managed pickups list
    foreach (id, state in g_ManagedPickups)
    {
        if (state.mTag == tag)
        {
            // Find the pickup instance
            inst = FindPickup(id)
            // Remove it if it exist
            if (inst != null)
            {
                inst.Remove();
            }
            // Now remove the state as well
            g_ManagedPickups.rawdelete(id);
            // We removed a pickup
            return true;
        }
    }

    // Try in the dormant pickups list as well
    foreach (idx, state in g_DormantPickups)
    {
        if (state.mTag == tag)
        {
            g_DormantPickups.remove(idx);
            // We removed a pickup
            return true;
        }
    }

    // Finally, try in the pending pickups list
    foreach (idx, state in g_PendingPickups)
    {
        if (state.mTag == tag)
        {
            g_PendingPickups.remove(idx);
            // We removed a pickup
            return true;
        }
    }

    // At this point we couldn't find such pickup
    return false;
}

// ------------------------------------------------------------------------------------------------
function onManagedPickupPickedUp(player, pickup)
{
    print("managed pickup was collected " + pickup.ID);
    // ...
}

// ------------------------------------------------------------------------------------------------
function onPickupPickedUp(player, pickup)
{
    // Is this a managed pickup?
    if (pickup.ID in g_ManagedPickups)
    {
        // Grab the pickup instance
        local state = g_ManagedPickups.rawget(pickup.ID);
        // Remove it from the list of managed pickups
        g_ManagedPickups.rawdelete(pickup.ID);
        // Reset the timer to the original delay value
        state.mTimer = state.mDelay;
        // Insert it into the dormant pickups list
        g_DormantPickups.push(state);
        // All has been taken care of. Do something with it
        onManagedPickupPickedUp(player, pickup);
        // Finally, we can remove the pickup instance
        pickup.Remove();
    }
}

// ------------------------------------------------------------------------------------------------
function onPlayerSpawn(player)
{
    local x = player.Pos.x, y = player.Pos.y, z = player.Pos.z, ox = 1.0, oy = 1.0;
    // dummy names, dummy values, dummy w/e
    CreateManagedPickup("street.weapon.1",      7,  274, Vector(x - (ox++), y - (oy++), z));
    CreateManagedPickup("stunt.health.4",       16, 366, Vector(x - (ox++), y - (oy++), z));
    CreateManagedPickup("city.weapon.3",        10, 283, Vector(x - (ox++), y - (oy++), z));
    CreateManagedPickup("roof.home.weapon.7",   14, 277, Vector(x - (ox++), y - (oy++), z));
}

Now let's talk issues. I've only tested this briefly and my god, the crashes that you get. I have never seen a more broken server in my life. Simply creating a pickup and then closing the server produces a crash. What the actual f*?

After they're re-created their icons don't appear anymore. Not sure why and didn't bother to even figure out why.
The server is very sensitive to when you close it. 9 out of 10 times you're likely to get a crash.

I have a feeling that it's not the script fault but more likely from the server.



@Stormeus This is on you. I did offer to fix some of these bugs. To this day I still don't know why you guys still didn't allow me (especially now that you've lost interest in the project) because I never got an answer.
.

Mötley

@S.L.C

You want to know what is wrong with your script?

After finnaly getting the time to read it over, I noticed your usage for CreatePickup happens to be one of the most bugged ways to create pickups,

After changing your code over to

local inst = CreatePickup(state.mModel state.mPosition);
Your code works like magic. I really do not know WHY the other CreatePickup settings don't work right but that was your issue.

In general nice script. I will point anything else out when I get the time to understand your coding :P