Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More weapon slots #56

Open
Y-Less opened this issue Aug 19, 2016 · 9 comments
Open

More weapon slots #56

Y-Less opened this issue Aug 19, 2016 · 9 comments

Comments

@Y-Less
Copy link
Contributor

Y-Less commented Aug 19, 2016

This is something I thought of and mostly wrote years ago, but never released and subsequently lost. I realised that it was quite simple to bypass the weapon slot limit in the same way as I do classes in y_classes - just have three.

Say player is holding a weapon in slot 7, you give them another weapon from (say) slots 6 and 8 (in reality, fists and camera, or other mostly non-deadly weapons will be best). When you detect that they switched to the weapon in slot 6, you know that they changed weapons down, and you can give and arm the correct weapon. If they switch to the weapon in slot 8, they changed up, and again you give them the new weapon accordingly. That next weapon could be a different slot 7 weapon, or any other weapon at all. Just make sure that the sentinel weapons are also updated if required (e.g. giving them an actual slot 6 weapon will prevent the use of slot 6 for detecting a change).

You could get very clever and make those sentinel weapons ones they actually own, or make it so that instead of cycling through all weapons in one slot before moving on to the next slot, you cycle through one of each entirely before moving on to the next ones - would be harder to code, but would lead to less flickering.

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 19, 2016

Slots 0, 9, 10, and 11 are good for sentinel checks (you need three, two for normal use, and a third for when they are actually holding a weapon from a sentinel slot).

@Crayder
Copy link
Contributor

Crayder commented Aug 19, 2016

So if I understand correctly, this could be used to easily add custom weapons or even change the order of a player's weapons?

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 19, 2016

Custom weapons would be harder (I think, not sure how to do that but I have heard of it being done). It would be for changing weapon order, yes, and for allowing more weapons to (appear to) be held. So instead of just having EITHER an AK47 OR an M4 (because they share a slot, and you can only have one weapon per slot), you could have both at once. You can't actually give a player both, but with this you detect when they change which weapon they are holding and switch that out for the correct one.

@Crayder
Copy link
Contributor

Crayder commented Aug 19, 2016

Yes, that's what I meant. And by custom weapons I mean like having two M4's but calling one something different and making it have different stats. This detection could make that pretty simple.

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 19, 2016

Given that this include already handles the alternate stats - yes.

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 19, 2016

Well, I assume so, I've not actually read the code, this was just a suggestion for all weapons, but I don't see any theoretical reason why it can't be used for more than all weapons.

@Crayder
Copy link
Contributor

Crayder commented Aug 19, 2016

From my understanding, the basic idea is a system as represented in GTA:V. But in theory it can be used for more explicit things as I suggested, custom weapons.

Ok, so we would need an array to store each player's weapons and a weapon change detector. For external use we could also add a callback to be called when a player changes weapons, it would send the player ID and the direction of the change (this could be used in other includes and such for custom weapons and such). By default when the weapon change is detected the array would be tested for valid weapons to the left or right respectively, if the weapon is valid change to it, if not loop to the first or last index, respectively. If there are no valid weapons simply give back the fist. GivePlayerWeapon would be hooked to start with, giving the player the weapon provided and inserting it into the array. The array would be sorted in the order the weapons are given (?) so the weapons could be ordered however the user wants. Or the array would be sorted by the weapon slot then the weapon ID, where the slots would be gone through as they are by default and each weapon in the slots would be gone through from least to greatest.

Right?

I might take the time out to do this myself... xD
🎯

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 19, 2016

I don't know about ordering. Going by order given doesn't make much sense, because that ends up quite random if they are getting weapons by various means through a play session. Ordering by slot/id is better, but becomes slightly non-deterministic when multiple variants of the same weapon are involved. I would think that the simplest order would be to use the order the developer defines the weapons in.

@Y-Less
Copy link
Contributor Author

Y-Less commented Aug 29, 2016

So purely by fluke, I was going through some really old folders, trying to clean up my hard disk a little bit, and came across this:

/*enum E_Y_WEAPONS_DATA
{
    E_Y_WEAPONS_DATA_NEXT
    E_Y_WEAPONS_DATA_LAST
    E_Y_WEAPONS_DATA_SLOT
    E_Y_WEAPONS_DATA_NEXT
}*/

static stock const
    YSI_g_scWeaponSlots[] =
        {
            0,  0,  1,  1,  1,  1,  1,  1,  1,  1,
            10, 10, 10, 10, 10, 10, 8,  8,  8,  2,
            2,  2,  3,  3,  3,  4,  4,  5,  5,  4,
            6,  6,  7,  7,  7,  7,  8,  12, 9,  9,
            9,  11, 11, 11
        };

// Store the ammo, -1 means does not have.
static stock
    YSI_g_sWeapons[MAX_PLAYERS][47 - 3],
    YSI_g_sSlots[MAX_PLAYERS],
    YSI_g_sCurrentSet[MAX_PLAYERS][13],
    PlayerArray:YSI_g_sHasConflict<MAX_PLAYERS>,
    PlayerArray:YSI_g_sHasExtras<MAX_PLAYERS>;

hook OnPlayerConnect(playerid)
{
    // Always have fists.
    YSI_g_sSlots = 1;
    // Have no other weapons though.
    for (new i = 0; i != sizeof (YSI_g_sWeapons[]); ++i)
    {
        YSI_g_sWeapons[playerid][i] = -1;
    }
    for (new i = 0; i != sizeof (YSI_g_sCurrentSet[]); ++i)
    {
        YSI_g_sCurrentSet[playerid][i] = 0;
    }
}

static stock Weapon_CountSlots(playerid)
{
    new
        count = 0,
        slots = YSI_g_sSlots[playerid];
    for (new j = 1; j != (1 << 13); j <<= 1)
    {
        if (slots & j)
        {
            ++count;
        }
    }
    return count;
}

static stock Weapon_DoRemove(playerid, weaponid)
{
    new
        w[13],
        a[13];
    // Get existing weapons (minus one).
    for (new i = 0; i != 13; ++i)
    {
        GetPlayerWeaponData(playerid, i, w[i], a[i]);
        if (w[i] == weaponid)
        {
            w[i] = 0;
        }
    }
    // Get the current weapon and reset all.
    new
        s = GetPlayerWeapon(playerid);
    ResetPlayerWeapons(playerid);
    // Restore all weapons except the removed one.
    for (new i = 0; i != 13; ++i)
    {
        if (w[i])
        {
            GivePlayerWeapon(playerid,  w[i], a[i]);
        }
    }
    if (s != weaponid)
    {
        SetPlayerArmedWeapon(playerid, s);
    }
    return 1;
}

static stock Weapon_CheckExtra(playerid)
{
    // Check if we need (or no longer need) extra weapons to detect multiple
    // weapons in the same slot while not having enough weapons naturally to do
    // it cleanly.
    if (PA_Get(YSI_g_sHasExtras, playerid))
    {
        // Has extras already - do we still need them.
        new
            count = 0,
            slots = YSI_g_sSlots[playerid],
            w[13],
            a[13];
        // Get existing weapons (minus one).
        for (new i = 0, j = 1; i != 13; ++i, j <<= 1)
        {
            if (slots & j)
            {
                GetPlayerWeaponData(playerid, i, w[i], a[i]);
                ++count;
            }
        }
        if (count < 3)
        {
        }
        else
        {
            // No longer need extras.
            if (
        }
    }
    else
    {
    }
    return 1;
}

static stock Weapon_DoGive(playerid, weaponid, id, ammo)
{
    ammo = max(ammo, 0);
    if (weaponid == WEAPON_SATCHEL)
    {
        // VERY special case - give them two weapons, neither of which are in
        // shared slots.  This means that a) we never need to check for slot
        // conflicts and b) we don't need to check if we need extra hidden
        // weapons to detect changing slots because there will be at least 3
        // slots in use (so remove any extra weapons they may have).
        if (PA_Get(YSI_g_sHasConflict, playerid))
        {
            // Has a conflict.
            if (PA_Get(YSI_g_sHasExtras, playerid))
            {
                // Has extra weapons to make up the difference.
                PA_Vet(YSI_g_sHasExtras, playerid);
                if (YSI_g_sSlots[playerid] & (1 << 10))
                {
                    Weapon_DoRemove(playerid, WEAPON_FLOWER);
                }
                else
                {
                    Weapon_DoRemove(playerid, WEAPON_FLOWER);
                }
            }
        }
        return 1;
    }
    new
        slot = YSI_g_scWeaponSlots[id];
    if (YSI_g_sWeapons[playerid][id] == -1)
    {
        // Don't already have this weapon.
        YSI_g_sWeapons[playerid][id] = ammo;
        if (YSI_g_sSlots[playerid] & (1 << slot))
        {
            // Already have a different weapon in this slot.
            PA_Let(YSI_g_sHasConflict, playerid);
            // Now we need to work out if we need extra fake slots.
            if (Weapon_CountSlots(playerid) < 3)
            {
                // We need at least three slots for this to work to detect when
                // the player changes weapon in one direction or the other.  One
                // of these will always be slot 0, as that can never be empty.
                // The other COULD be slot 10 or 12, but never both.
                if (YSI_g_sSlots[playerid] & (1 << 10))
                {
                    // Give them the detonator (they will have no satchels).
                }
                else
                {
                    // 
                }
            }
        }
        else
        {
            // Don't already have a weapon in this slot - just give them it.
            GivePlayerWeapon(playerid, weaponid, ammo);
            YSI_g_sCurrentSet[playerid][slot] = weaponid;
        }
    }
    else
    {
        YSI_g_sWeapons[playerid][id] += ammo;
        if (YSI_g_sCurrentSet[playerid][slot] == weaponid)
        {
            // They are currently holding the weapon, give them more ammo.
            GivePlayerWeapon(playerid, weaponid, ammo);
        }
        // Now we need to work out if we no longer need extra fake slots.
    }
    // Make sure we know there is a weapon in this slot.
    YSI_g_scWeaponSlots[id] |= (1 << slot);
    return 1;
}

stock Weapon_Give(playerid, weaponid, ammo)
{
    if (0 <= weaponid <= 18)
    {
        Weapon_DoGive(playerid, weaponid, weaponid, ammo);
    }
    else if (22 <= weaponid <= 46)
    {
        Weapon_DoGive(playerid, weaponid, weaponid - 3, ammo);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants