Custom Monsters Switching GUI

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.

Custom Monsters Switching GUI

Postby RastaManGames » Mon Aug 09, 2021 9:51 am

Is there any modern method to create an "Modification Options GUI", that can contain switches to turn on (enabled) or turn off (disabled) specific enemies in the mod?
As example: I have mod, that replaces almost all enemies with zombie, dog and ghost. So... In the special menu i just able to turn off dog or ghost (if i don't like them) or even turn off all custom enemies and have default ones.
I need this to my mod, where player wanna be able to turn off those enemies that he don't like at all due to their big variety.
User avatar
RastaManGames
Syberian Doom Fan
 
Joined: 13 Mar 2014
Location: Russian Federation, Krasnoyarsk
Discord: ℝ𝕒𝕀π•₯π•’π•„π•’π•Ÿπ”Ύπ•’π•žπ•–π•€#4168
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Custom Monsters Switching GUI

Postby Player701 » Tue Aug 10, 2021 7:51 am

The simplest way would probably be to introduce custom CVARs to control your replacements and create a custom mod menu via MENUDEF that would allow you to change those CVARs. Then, instead of having your replacements hard-coded via the replaces keyword, handle the CheckReplacement event and decide whether you want to replace a certain monster type by checking for the value of the appropriate CVAR. For example:

Code: Select allExpand view
class TestHandler : EventHandler
{
    override void CheckReplacement(ReplaceEvent e)
    {
        if (e.Replacee == 'ZombieMan' && replace_zombieman)
        {
            e.Replacement = 'MyMonster';
        }
    }
}

Define your CVAR in CVARINFO like this:
Code: Select allExpand view
server bool replace_zombieman = true;


If you want to control replacements by the replaced type instead of the type being replaced, the mechanism is the same, just name your CVARs accordingly and add appropriate conditions to your CheckReplacement code. You can reference CVARs directly from ZScript by their name, there is no need to use GetCVar etc. unless in certain special cases.

Your MENUDEF code could look somewhat like this:
Code: Select allExpand view
AddOptionMenu "OptionsMenu"
{
    submenu "My Mod Options", "MyModOptionMenu"
}

OptionMenu "MyModOptionMenu"
{
    Option "Replace ZombieMan", "replace_zombieman ", "YesNo"
}

Note that an alternate, simplified options menu has been introduced in newer GZDoom versions, so you may probably want to add a link to your custom menu to OptionsMenuSimple as well. Or you can extend or replace the main menu directly to include a link to your custom menu instead.
User avatar
Player701
Β 
Β 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Custom Monsters Switching GUI

Postby RastaManGames » Tue Aug 10, 2021 4:01 pm

Well, i totally understand parts about CVARINFO and MENUDEF. But... I guess, that i need to rewrite spawner function from the blank page right now. Thing is, that my mod has aggressive approach, where i have 57 custom enemies, that are 100% sure is gonna replace every monster on the map with predefined probability. I just need (somehow) to define an list of those 57 classes and disable specific enemies from this list using CVARs changes from mod options menu (that was created via MENUDEF). Your method is good and solid, but this approaching is pure soft, where user is defining, which of vanilla Doom monster is gonna be replaced. I need more harsh and painful method, where user only can decide, which enemies from roster he wanna see in his playthroughs and which ones he just wanna "ban" from spawning.

Something like this:
Spoiler: "Big Image"


I have very poor skills of programming and for now my code like this:
1) ZScript, where is defined roster of all enemies and exist poor rough spawner.
Code: Select allExpand view
Class ActiveRoster : RandomSpawner
{
   Default
   {
      DropItem "NPC_STEcolog",255,150;
      DropItem "NPC_STMilitary",255,300;
      DropItem "NPC_STBandit",255,300;
      DropItem "NPC_STFreedom",255,100;
      DropItem "NPC_STLoner",255,100;
      DropItem "NPC_STNewbie",255,100;   
      DropItem "NPC_STBlindDog",255,200;
      DropItem "NPC_STPseudoDog",255,200;
      DropItem "NPC_STMonolith",255,75;
      DropItem "NPC_STMercenary",255,75;
      DropItem "NPC_STZombie",255,25;
      DropItem "NPC_STClearSky",255,50;
      DropItem "NPC_STDuty",255,50;
      DropItem "NPC_Bear1",255,150;
      DropItem "NPC_Bear2",255,300;
      DropItem "NPC_Bear3",255,300;
      DropItem "NPC_Scav1",255,150;
      DropItem "NPC_Scav2",255,300;
      DropItem "NPC_Scav3",255,300;
      DropItem "NPC_Scav4",255,100;
      DropItem "NPC_Scav5",255,100;
      DropItem "NPC_Scav6",255,100;
      DropItem "NPC_Psycho",255,100;
      DropItem "NPC_KPDude1",255,150;
      DropItem "NPC_KPDude2",255,300;
      DropItem "NPC_KPDude3",255,300;
      DropItem "NPC_KPGirl1",255,150;
      DropItem "NPC_KPGirl2",255,300;
      DropItem "NPC_KPGirl3",255,300;
      DropItem "NPC_UTMale1",255,150;
      DropItem "NPC_UTMale2",255,150;
      DropItem "NPC_UTFemale1",255,75;
      DropItem "NPC_UTFemale2",255,75;
      DropItem "NPC_BFUnit1",255,300;
      DropItem "NPC_BFUnit2",255,100;
      DropItem "NPC_BFUnit3",255,75;
      DropItem "NPC_BFUnit4",255,50;
      DropItem "NPC_P2Dude1",255,300;
      DropItem "NPC_P2Girl1",255,150;
      DropItem "NPC_P2Main1",255,300;
      DropItem "NPC_P2Dude2",255,300;
      DropItem "NPC_P2Girl2",255,150;
      DropItem "NPC_P2Main2",255,300;
      DropItem "NPC_Fear1",255,150;
      DropItem "NPC_Fear2",255,300;
      DropItem "NPC_Fear3",255,300;
      DropItem "NPC_MW1A",255,150;
      DropItem "NPC_MW1B",255,300;
      DropItem "NPC_MW1C",255,300;
      DropItem "NPC_MW2A",255,150;
      DropItem "NPC_MW2B",255,300;
      DropItem "NPC_MW2C",255,300;
      DropItem "NPC_MW2D",255,75;
      DropItem "NPC_MW2E",255,50;
      DropItem "NPC_Akan1",255,150;
      DropItem "NPC_Akan2",255,300;
      DropItem "NPC_Akan3",255,300;
   }
}

class GlobalReplacer : EventHandler
{
    override void CheckReplacement(ReplaceEvent e)
    {
        if (e.Replacee == 'ZombieMan' || e.Replacee == 'ShotgunGuy' || e.Replacee == 'DoomImp' || e.Replacee == 'Demon' || e.Replacee == 'Spectre' || e.Replacee == 'ChaingunGuy' || e.Replacee == 'Cacodemon' || e.Replacee == 'LostSoul' || e.Replacee == 'PainElemental' || e.Replacee == 'BaronOfHell' || e.Replacee == 'HellKnight' || e.Replacee == 'Revenant' || e.Replacee == 'Fatso' || e.Replacee == 'Arachnotron' || e.Replacee == 'Archvile' || e.Replacee == 'SpiderMastermind' || e.Replacee == 'Cyberdemon' || e.Replacee == 'WolfensteinSS')
        {
            e.Replacement = 'ActiveRoster';
        }
    }
}

2) CVARINFO with each individual enemy for total control of roster.
Code: Select allExpand view
//NPCs from "S.T.A.L.K.E.R.":
server bool NPC_STEcolog_InRoster = true;
server bool NPC_STMilitary_InRoster = true;
server bool NPC_STBandit_InRoster = true;
server bool NPC_STFreedom_InRoster = true;
server bool NPC_STLoner_InRoster = true;
server bool NPC_STNewbie_InRoster = true;
server bool NPC_STBlindDog_InRoster = true;
server bool NPC_STPseudoDog_InRoster = true;
server bool NPC_STMonolith_InRoster = true;
server bool NPC_STMercenary_InRoster = true;
server bool NPC_STZombie_InRoster = true;
server bool NPC_STClearSky_InRoster = true;
server bool NPC_STDuty_InRoster = true;

//NPCs from "Escape From Tarkov":
server bool NPC_Bear1_InRoster = true;
server bool NPC_Bear2_InRoster = true;
server bool NPC_Bear3_InRoster = true;
server bool NPC_Scav1_InRoster = true;
server bool NPC_Scav2_InRoster = true;
server bool NPC_Scav3_InRoster = true;
server bool NPC_Scav4_InRoster = true;
server bool NPC_Scav5_InRoster = true;
server bool NPC_Scav6_InRoster = true;

//NPCs from "Kingpin: Life Of Crime":
server bool NPC_KPDude1_InRoster = true;
server bool NPC_KPDude2_InRoster = true;
server bool NPC_KPDude3_InRoster = true;
server bool NPC_KPGirl1_InRoster = true;
server bool NPC_KPGirl2_InRoster = true;
server bool NPC_KPGirl3_InRoster = true;

//NPCs from "Unreal Tournament":
server bool NPC_UTMale1_InRoster = true;
server bool NPC_UTMale2_InRoster = true;
server bool NPC_UTFemale1_InRoster = true;
server bool NPC_UTFemale2_InRoster = true;

//NPCs from "Battlefield 3":
server bool NPC_BFUnit1_InRoster = true;
server bool NPC_BFUnit2_InRoster = true;
server bool NPC_BFUnit3_InRoster = true;
server bool NPC_BFUnit4_InRoster = true;

//NPCs from "Postal 2":
server bool NPC_P2Dude1_InRoster = true;
server bool NPC_P2Dude2_InRoster = true;
server bool NPC_P2Girl1_InRoster = true;
server bool NPC_P2Girl2_InRoster = true;
server bool NPC_P2Main1_InRoster = true;
server bool NPC_P2Main2_InRoster = true;

//NPCs from "F.E.A.R.":
server bool NPC_Fear1_InRoster = true;
server bool NPC_Fear2_InRoster = true;
server bool NPC_Fear3_InRoster = true;

//NPCs from "Call Of Duty 4: Modern Warfare":
server bool NPC_MW1A_InRoster = true;
server bool NPC_MW1B_InRoster = true;
server bool NPC_MW1C_InRoster = true;

//NPCs from "Call Of Duty 4: Modern Warfare 2":
server bool NPC_MW2A_InRoster = true;
server bool NPC_MW2B_InRoster = true;
server bool NPC_MW2C_InRoster = true;
server bool NPC_MW2D_InRoster = true;
server bool NPC_MW2E_InRoster = true;

//NPCs from "Payday 2":
server bool NPC_Akan1_InRoster = true;
server bool NPC_Akan2_InRoster = true;
server bool NPC_Akan3_InRoster = true;

//NPCs from "???":
server bool NPC_Psycho_InRoster = true;

3) MENUDEF, where player is gonna be able to disable/enable each enemy class from global spawner.
Code: Select allExpand view
AddOptionMenu "OptionsMenu"
{
    submenu "Russian Mercenaries Roster", "RM_OptionMenu"
}

OptionMenu "RM_OptionMenu"
{
   Title "Russian Mercenaries Roster"
   StaticText ""
   StaticText "S.T.A.L.K.E.R."
   Option "Ecolog", "NPC_STEcolog_InRoster", "YesNo"
   Option "Military Member", "NPC_STEcolog_InRoster", "YesNo"
   Option "Bandit", "NPC_STEcolog_InRoster", "YesNo"
   Option "Freedom Member", "NPC_STEcolog_InRoster", "YesNo"
   Option "Loner", "NPC_STEcolog_InRoster", "YesNo"
   Option "Newbie", "NPC_STEcolog_InRoster", "YesNo"
   Option "Blind Dog", "NPC_STEcolog_InRoster", "YesNo"
   Option "Pseudo Dog", "NPC_STEcolog_InRoster", "YesNo"
   Option "Monolith Member", "NPC_STEcolog_InRoster", "YesNo"
   Option "Mercenary", "NPC_STEcolog_InRoster", "YesNo"
   Option "Zombie", "NPC_STEcolog_InRoster", "YesNo"
   Option "Clear Sky Member", "NPC_STEcolog_InRoster", "YesNo"
   Option "Duty Member", "NPC_STEcolog_InRoster", "YesNo"
   StaticText ""
   StaticText "Escape From Tarkov"
   Option "Bear Member β„–1 (Sergei)", "NPC_Bear1_InRoster", "YesNo"
   Option "Bear Member β„–2 (Sasha)", "NPC_Bear2_InRoster", "YesNo"
   Option "Bear Member β„–3 (Mikhail)", "NPC_Bear3_InRoster", "YesNo"
   Option "Scav Member β„–1", "NPC_Scav1_InRoster", "YesNo"
   Option "Scav Member β„–2", "NPC_Scav2_InRoster", "YesNo"
   Option "Scav Member β„–3", "NPC_Scav3_InRoster", "YesNo"
   Option "Scav Member β„–4", "NPC_Scav4_InRoster", "YesNo"
   Option "Scav Member β„–5", "NPC_Scav5_InRoster", "YesNo"
   Option "Scav Member β„–6", "NPC_Scav6_InRoster", "YesNo"
   StaticText ""
   StaticText "Kingpin: Life Of Crime"
   Option "Kingpin Dude β„–1", "NPC_KPDude1_InRoster", "YesNo"
   Option "Kingpin Dude β„–2", "NPC_KPDude2_InRoster", "YesNo"
   Option "Kingpin Dude β„–3", "NPC_KPDude3_InRoster", "YesNo"
   Option "Kingpin Girl β„–1", "NPC_KPGirl1_InRoster", "YesNo"
   Option "Kingpin Girl β„–2", "NPC_KPGirl2_InRoster", "YesNo"
   Option "Kingpin Girl β„–3", "NPC_KPGirl3_InRoster", "YesNo"
   StaticText ""
   StaticText "Unreal Tournament"
   Option "Unreal Tournament Male β„–1", "NPC_UTMale1_InRoster", "YesNo"
   Option "Unreal Tournament Male β„–2", "NPC_UTMale2_InRoster", "YesNo"
   Option "Unreal Tournament Female β„–1", "NPC_UTFemale1_InRoster", "YesNo"
   Option "Unreal Tournament Female β„–2", "NPC_UTFemale2_InRoster", "YesNo"
   StaticText ""
   StaticText "Battlefield 3"
   Option "BF Unit β„–1 (Assault)", "NPC_BFUnit1_InRoster", "YesNo"
   Option "BF Unit β„–2 (Support)", "NPC_BFUnit2_InRoster", "YesNo"
   Option "BF Unit β„–3 (Recon)", "NPC_BFUnit3_InRoster", "YesNo"
   Option "BF Unit β„–4 (Engineer)", "NPC_BFUnit4_InRoster", "YesNo"
   StaticText ""
   StaticText "Postal 2"
   Option "Going Postal Dude β„–1", "NPC_P2Dude1_InRoster", "YesNo"
   Option "Going Postal Dude β„–2", "NPC_P2Dude2_InRoster", "YesNo"
   Option "Going Postal Girl β„–1", "NPC_P2Girl1_InRoster", "YesNo"
   Option "Going Postal Girl β„–2", "NPC_P2Girl2_InRoster", "YesNo"
   Option "Going Postal Protagonist β„–1", "NPC_P2Main1_InRoster", "YesNo"
   Option "Going Postal Protagonist β„–2", "NPC_P2Main2_InRoster", "YesNo"
   StaticText ""
   StaticText "F.E.A.R."
   Option "F.E.A.R. Unit β„–1", "NPC_Fear1_InRoster", "YesNo"
   Option "F.E.A.R. Unit β„–2", "NPC_Fear2_InRoster", "YesNo"
   Option "F.E.A.R. Unit β„–3", "NPC_Fear3_InRoster", "YesNo"
   StaticText ""
   StaticText "Call Of Duty: Modern Warfare"
   Option "MW1 Specnaz β„–1", "NPC_MW1A_InRoster", "YesNo"
   Option "MW1 Specnaz β„–2", "NPC_MW1B_InRoster", "YesNo"
   Option "MW1 Specnaz β„–3", "NPC_MW1C_InRoster", "YesNo"
   StaticText ""
   StaticText "Call Of Duty: Modern Warfare 2"
   Option "MW2 Specnaz β„–1", "NPC_MW2A_InRoster", "YesNo"
   Option "MW2 Specnaz β„–2", "NPC_MW2B_InRoster", "YesNo"
   Option "MW2 Specnaz β„–3", "NPC_MW2C_InRoster", "YesNo"
   Option "MW2 Specnaz β„–4", "NPC_MW2D_InRoster", "YesNo"
   Option "MW2 Specnaz β„–5", "NPC_MW2E_InRoster", "YesNo"
   StaticText ""
   StaticText "Payday 2"
   Option "Akan's Mercenary β„–1", "NPC_Akan1_InRoster", "YesNo"
   Option "Akan's Mercenary β„–2", "NPC_Akan2_InRoster", "YesNo"
   Option "Akan's Mercenary β„–3", "NPC_Akan3_InRoster", "YesNo"
   StaticText ""
   StaticText "Original"
   Option "Psycho", "NPC_Psycho_InRoster", "YesNo"
}


I am sure that done something very wrong and off. For now i need to understand how to implement CVARs into spawner to enable each enemy class if variable positive and disable if she are negative.
User avatar
RastaManGames
Syberian Doom Fan
 
Joined: 13 Mar 2014
Location: Russian Federation, Krasnoyarsk
Discord: ℝ𝕒𝕀π•₯π•’π•„π•’π•Ÿπ”Ύπ•’π•žπ•–π•€#4168
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Custom Monsters Switching GUI

Postby Player701 » Wed Aug 11, 2021 12:14 am

If you are utilizing RandomSpawners, then you will have to create a custom class inherited from RandomSpawner and override the ChooseSpawn() virtual method to pick the type of monster to spawn depending on the CVARs that are currently enabled. A RandomSpawner picks a type to spawn from the list of its DropItems, but I don't think you can remove items from this list dynamically, so you may need to re-implement the random pick logic from scratch, storing the types and weights in dynamic arrays. I may be able to provide a concrete example later this week if I have the time, for now you can also view this thread for an example of how one can apply extra spawning conditions to a RandomSpawner (the examples there may be a bit too complex for you though).
User avatar
Player701
Β 
Β 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Custom Monsters Switching GUI

Postby RastaManGames » Wed Sep 08, 2021 1:31 am

Since i am using more detailed monsters spawns, i have an new idea of realization in a way of this:
Code: Select allExpand view
if(spawner01==false&&spawner02==false&&...&&spawnerN==false)
{
    DropItem "NPC_BlankSpace",255,25;
}
else
{
    if(spawner01==true)
    {
        DropItem "NPC_Enemy01",255,25;
    }
    if(spawner02==true)
    {
        DropItem "NPC_Enemy02",255,25;
    }
    ...
    if(spawnerN==true)
    {
        DropItem "NPC_EnemyN",255,25;
    }
}

First, it checks, if player just disabled all replacements. If all of them are disabled, then there is no enemy. Just blank actor (i need this).
Then, if one or several enemies are enabled, it check every CVAR and, if it is true, it just adds that enemy to "DropItem" list.
But this idea still abusing RandomSpawner. Difference that is now every Doom monster have several potential replacements from the list.
User avatar
RastaManGames
Syberian Doom Fan
 
Joined: 13 Mar 2014
Location: Russian Federation, Krasnoyarsk
Discord: ℝ𝕒𝕀π•₯π•’π•„π•’π•Ÿπ”Ύπ•’π•žπ•–π•€#4168
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: No registered users and 1 guest