Preventing stock weapons being given in IDKFA cheat?

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!)
Post Reply
User avatar
MartinHowe
Posts: 2078
Joined: Mon Aug 11, 2003 1:50 pm
Preferred Pronouns: He/Him
Location: East Suffolk (UK)

Preventing stock weapons being given in IDKFA cheat?

Post by MartinHowe »

Is there any way to prevent stock weapons being given in IDKFA cheat?

I have a mod that defines several weapons; some are new, some replace the stock weapons with functional equivalents based on a flexible base class (so they are not derived from the originals). However, IDKFA gives the stock weapons as well. I have found a way to prevent them being given at all or otherwise spawned:

Code: Select all

// --- DISABLE STOCK WEAPONS ---------------------------------------------------

gameinfo
{
    AddEventHandlers = "DisableStockWeapons"
}

// -----------------------------------------------------------------------------

// --- DISABLE STOCK WEAPONS ---------------------------------------------------

version "4.5"

// --- DEFAULT -----------------------------------------------------------------

Class DisableStockWeapons : EventHandler
{
    // =========================================================================

    override void WorldThingSpawned(WorldEvent e)
    {
        actor thing = e.Thing;
        name cn = thing.GetClassName();
        switch (cn)
        {
            case 'Chainsaw':
            case 'Pistol':
            case 'Shotgun':
            case 'SuperShotgun':
            case 'Chaingun':
            case 'RocketLauncher':
            case 'PlasmaRifle':
            case 'BFG9000':
                thing.Destroy();
                break;
        }
    }

    // =========================================================================
}

// -----------------------------------------------------------------------------
But this is a bit clumsy and it runs for every item spawned; it also would happen even if a stock weapon is explicitly spawned in the console or by a script. Is there a less hacky way to do it and limited to cheat giving?
User avatar
phantombeta
Posts: 2175
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: Preventing stock weapons being given in IDKFA cheat?

Post by phantombeta »

Does your mod define its own PlayerPawn? If so, you can override the give cheat in it.
User avatar
MartinHowe
Posts: 2078
Joined: Mon Aug 11, 2003 1:50 pm
Preferred Pronouns: He/Him
Location: East Suffolk (UK)

Re: Preventing stock weapons being given in IDKFA cheat?

Post by MartinHowe »

phantombeta wrote: Sat Jul 06, 2024 4:12 pm Does your mod define its own PlayerPawn? If so, you can override the give cheat in it.
Thanks, didn't know about that. Sadly this is a generic mod that wants to be as non-intrusive as possible and overriding player classes is about as intrusive as it gets as there's no way to know what player classes will be in use by users. This is the kind of thing that event handlers were made for but GZDoom does not have a 'reason code' in any of its event handlers AFAICS; that would make event handlers much more useful.
yum13241
Posts: 874
Joined: Mon May 10, 2021 8:08 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): EndeavorOS (basically Arch)
Graphics Processor: Intel with Vulkan/Metal Support
Contact:

Re: Preventing stock weapons being given in IDKFA cheat?

Post by yum13241 »

Try this:

Code: Select all

class ReplacementHandler : EventHandler
{
	//===========================================================================
	//
	// Handle swapping out vanilla weapons
	//
	//===========================================================================

	override void PlayerEntered(PlayerEvent e)
	{
		PlayerPawn pmo = players[e.PlayerNumber].mo;
		if (!pmo) return;
		SwapWeapons(pmo);
	}

	override void PlayerRespawned(PlayerEvent e)
	{
		PlayerPawn pmo = players[e.PlayerNumber].mo;
		if (!pmo) return;
		SwapWeapons(pmo);
	}
	
	override void WorldTick(void)
	{
		// I can't think of a better way LOL
		for (int i = 0; i < MAXPLAYERS; i++)
		{
			if (playeringame[i])
			{
				let pmo = players[i].mo;
				if (pmo)
				{
					SwapWeapons(pmo);
				}
			}
		}
	}

	//===========================================================================
	//
	// Give smooth weapons to player
	//
	//===========================================================================

	void SwapWeapons(PlayerPawn pmo)
	{
		if (pmo.FindInventory("Pistol") && pmo.player.ReadyWeapon is "Pistol")
		{
			pmo.TakeInventory("Pistol", 0x7FFFFFFF);
			pmo.GiveInventory("ADDYOURPISTOLHERE", 1);
			pmo.TakeInventory("Clip", 20);
		}

		if (pmo.FindInventory("Fist") && pmo.player.ReadyWeapon is "Fist")
		{
			pmo.TakeInventory("Fist", 0x7FFFFFFF);
			pmo.GiveInventory("ADDYOURFISTHERE", 1);
		} // just do this for every weapon lol, so when a stock weapon is cheated, it immediately gets taken.
	}

	//===========================================================================
	//
	// Replace spawned weapons in the world
	//
	//===========================================================================

	override void CheckReplacement(ReplaceEvent e)
	{
		if (e.Replacee == "Fist") e.Replacement = "ADDYOURFIST";
		else if (e.Replacee == "Chainsaw") e.Replacement = "ADDYOURCSAW"
		else if (e.Replacee == "Pistol") e.Replacement = "ADDYOURPISTOL";
		else if (e.Replacee == "Shotgun") e.Replacement = "ADDYOURSHOTGUN";
		
		else if (e.Replacee == "Chaingun") e.Replacement = "ADDYOURCGUN";
		else if (e.Replacee == "BFG9000") e.Replacement = "ADDYOURBFG";
		
		else if (e.Replacee == "RocketLauncher") e.Replacement = "ADDYOURRLAUNCHER";
		else if (e.Replacee == "PlasmaRifle") e.Replacement = "ADDYOURPGUN";
		else if (e.Replacee == "BFG9000") e.Replacement = "ADDYOURBFG";
	}
}
That's originally Nash's code, not mine. I used it in an unreleased project of mine and then re-generalized it for you. That last part handles spawns in world, which also means summon weapname, due to how GZDoom works, while the SwapWeapons() function handles giving through cheats or any instance where a stock weapon would enter the inventory.
User avatar
MartinHowe
Posts: 2078
Joined: Mon Aug 11, 2003 1:50 pm
Preferred Pronouns: He/Him
Location: East Suffolk (UK)

Re: Preventing stock weapons being given in IDKFA cheat?

Post by MartinHowe »

yum13241 wrote: Thu Sep 05, 2024 9:13 am Try this:
Thanks very much :mrgreen: Sorry for the late reply, had to stop working on my project for a while; the following is the end result.

Unlike the game itself, it doesn't select the weapon immediately if given at the console; however, I personally prefer it not to and cheat codes are only meant for testing purposes anyway.

Note that for the purposes of starting the game, the pistol must be checked after the fist; otherwise, the fist gets selected. I can find no reason for this, but when one is coding this deep inside the engine, one must expect timing sequence dependencies under the hood to get in the way sometimes.

Code: Select all

// --- STOCK WEAPONS REPLACER --------------------------------------------------

// This event handler replaces the stock weapons in Doom with their enhanced
// replacements from the pack.

// To use it, cite it in the Gameinfo section of a Mapinfo script; for example:
//
// gameinfo
// {
//     AddEventHandlers = "M426_StockWeapons_Replacer"
// }

// Credit: Nash Muhandes (ZDoom forums) for the original
// Credit: yum13241 (ZDoom forums) for initial generalsisation work

class M426_StockWeapons_Replacer : EventHandler
{
    // Replace when spawned in the world
    override void CheckReplacement(ReplaceEvent e)
    {
        e.IsFinal = false;

        if (e.Replacee == "Fist"  )          { e.Replacement = "Fistt";           return; }
        if (e.Replacee == "Chainsaw")        { e.Replacement = "Chainsaww";       return; }
        if (e.Replacee == "Pistol"  )        { e.Replacement = "Pistoll";         return; }
        if (e.Replacee == "Shotgun" )        { e.Replacement = "Shotgunn";        return; }
        if (e.Replacee == "SuperShotgun" )   { e.Replacement = "Coachgun";        return; }
        if (e.Replacee == "Chaingun" )       { e.Replacement = "Chaingunn";       return; }
        if (e.Replacee == "RocketLauncher" ) { e.Replacement = "RocketLauncherr"; return; }
        if (e.Replacee == "PlasmaRifle" )    { e.Replacement = "PlasmaRiflle";    return; }
        if (e.Replacee == "BFG9000" )        { e.Replacement = "BFGG9000";        return; }
    }

    // Replace after player enters the game
    override void PlayerEntered(PlayerEvent e)
    {
        PlayerPawn pmo = players[e.PlayerNumber].mo;
        if (!pmo) return;
        SwapWeapons(pmo);
    }

    // Replace after player respawns in the map
    override void PlayerRespawned(PlayerEvent e)
    {
        PlayerPawn pmo = players[e.PlayerNumber].mo;
        if (!pmo) return;
        SwapWeapons(pmo);
    }

    // Replace when given to the player
    override void WorldTick(void)
    {
        for (int i = 0; i < MAXPLAYERS; i++)
        {
            if (playeringame[i])
            {
                let pmo = players[i].mo;
                if (pmo && pmo.Health > 0)
                {
                    SwapWeapons(pmo);
                }
            }
        }
    }

    // ==========================================================================

    void SwapWeapon(
        PlayerPawn pmo,
        class<Weapon> replacee,
        class<Weapon> replacement,
        class<Ammo> ammoType = null,
        int ammoCount = 0)
    {
        // If not found then nothing to do
        if (!pmo.FindInventory(replacee))
            return;

        // Remember which weapon is
        // currently being wielded.
        let oldWeapon = pmo.player.ReadyWeapon;

        // Replace the weapon and any ammo it gives
        pmo.TakeInventory(replacee, MAX_INT);
        if (ammoType)
        {
            pmo.TakeInventory(ammoType, ammoCount);
        }
        pmo.GiveInventory(replacement, 1);

        // If no weapon was being wielded
        // then select the new weapon now.
        if (oldWeapon == null)
        {
            // We want the Weapon actor flags
            let defaults = GetDefaultByType(replacement);

            // If no auto switch then do nothing
            if (defaults.bNO_AUTO_SWITCH)
                return;

            // If out of ammo and no auto switch
            // on acquiring some then do nothing.
            let ammoCount = pmo.CountInv(defaults.AmmoType1) - defaults.AmmoGive1;
            if (ammoCount <= 0 && defaults.bNOAUTOSWITCHTO)
                return;

            // OK to proceed with selection
            pmo.A_SelectWeapon(replacement);
            return;
        }

        // If the old weapon was replaced
        // then select the new one instead;
        // otherwise, reselect the old one.
        if (oldWeapon == null || replacee == oldWeapon.GetClass())
        {
            pmo.A_SelectWeapon(replacement);
        }
        else // (replacee != oldWeapon.GetClass())
        {
           pmo.A_SelectWeapon(oldWeapon.GetClass());
        }
    }

    // =========================================================================

    void SwapWeapons(PlayerPawn pmo)
    {
        SwapWeapon(pmo, "Fist", "Fistt");
        SwapWeapon(pmo, "Chainsaw", "Chainsaww");
        SwapWeapon(pmo, "Pistol", "Pistoll", "Clip", 20);
        SwapWeapon(pmo, "SuperShotgun", "Coachgun", "Shell", 8);
        SwapWeapon(pmo, "Chaingun", "Chaingunn", "Clip", 20);
        SwapWeapon(pmo, "RocketLauncher", "RocketLauncherr", "RocketAmmo", 2);
        SwapWeapon(pmo, "PlasmaRifle", "PlasmaRiflle", "Cell", 40);
        SwapWeapon(pmo, "BFG9000", "BFGG9000", "Cell", 40);
    }

    // =========================================================================
}
yum13241
Posts: 874
Joined: Mon May 10, 2021 8:08 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): EndeavorOS (basically Arch)
Graphics Processor: Intel with Vulkan/Metal Support
Contact:

Re: Preventing stock weapons being given in IDKFA cheat?

Post by yum13241 »

You're welcome.
Post Reply

Return to “Scripting”