Using DECORATE to change player class

Archive of the old editing forum
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
Locked
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Using DECORATE to change player class

Post by InsaneFury »

I want people to choose out of many player classes. Since the initial "New Game" playerclass submenu only supports a limited number of player classes, I'm trying to employ Strife dialog to get this done.

I'm already identifying player classes based on custom inventory items, which when I give them to the player via Strife Script, work just as intended. So, as far as my DECORATE scripts are concerned, the player acts like the playerclass I intended, since all checks are based on those class-specific CustomItems.

The problem however is getting the player morphed (permanently, as the 'choice' needs to transfer over levels). I created the following DECORATE code:

Code: Select all

ACTOR ClearPlayerClass : CustomInventory // helper actor
{
  States
  {
    Pickup: //remove all player classes
	  TNT1 A 0 A_TakeInventory ("AllowRott", 1) 
	  // TNT1 A 0 A_TakeInventory ("RottMorph", 1) 
	  // TNT1 A 0 A_TakeInventory ("DoomMorph", 1) 
	  TNT1 A 0 A_TakeInventory ("AllowDoom", 1) 
    Stop
  }
}

actor DoomMorph: PowerMorph
{
 PowerMorph.PlayerClass "PL_Doom"
 PowerMorph.MorphStyle (MRF_FULLHEALTH|MRF_ADDSTAMINA|MRF_LOSEACTUALWEAPON)
}

actor RottMorph: PowerMorph
{
 PowerMorph.PlayerClass "PL_Rott"
 PowerMorph.MorphStyle (MRF_FULLHEALTH|MRF_ADDSTAMINA|MRF_LOSEACTUALWEAPON)
}

actor AllowDoomClass : CustomInventory
{
  ConversationID 312
  States
  {
  	Pickup:
	  TNT1 A 0 A_GiveInventory ("ClearPlayerClass", 1)
	  TNT1 A 0 A_GiveInventory ("AllowDoom", 1) 
	  TNT1 A 0 A_GiveInventory ("DoomMorph", 1) 
	  TNT1 A 0 A_GiveInventory ("Pistol", 1)
	  TNT1 A 0 A_GiveInventory ("Fist", 1)
    Stop
  }
}

actor AllowRottClass : CustomInventory
{
  ConversationID 313
  States
  {
  	Pickup:
	  TNT1 A 0 A_GiveInventory ("ClearPlayerClass", 1)
	  TNT1 A 0 A_GiveInventory ("AllowRott", 1) 
	  TNT1 A 0 A_GiveInventory ("RottMorph", 1) 
	  TNT1 A 0 A_GiveInventory ("RottKnife", 1) 
	  TNT1 A 0 A_GiveInventory ("RottDualPistol", 1) 
    Stop
  }
}
As-is, the code is fairly obvious: AllowDoomClass and AllowRottClass are items given by the Strife dialog, which would transform the player to those respected classes. In doing so, they first remove any items identifying the current class (either DoomClass or RottClass), then morph the player and add the corresponding items.

Note that I don't want to use ACS code at all, as I believe that ACS function numbers could conflict with other WADs loaded, possibly crippling their code. So unless someone can tell me that the ACS function numbers should be unique per WAD as opposed to over all loaded WADs, so that's why I want to have it in DECORATE instead.

Also, I believe morphing players permanently, transitioning over levels isn't possible. But I hope to be corrected on this.

*edit*
Just read that it's not possible to behave as a normal player when morphed (picking up items/weapons and such), so I need to go about this a different approach. Unfortunately, that'd probably mean using ACS? :(
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Re: Using DECORATE to change player class

Post by InsaneFury »

Right, as I've no clue where to start, I'm bumping this one. :)

In the meantime, I've been looking into ACS, hoping that:
1) ACS code can be applied, regardless of it being tied to specific MAPs
2) Script numbers only have to be unique on a per-wad/per-lump basis.

I found the MorphActor function, which changes the player class, just like a MorphProjectile would do.

Problem with this is the fact that I don't want to morph the player, I want to change the class, permanently, with no limitation concerning the use of weapons and picking up items, etc.

Furthermore, my player classes have their own skins, and when using the MorphActor the actor seems to morph to said class (chasecam reveals the skin changed), but when moving the skin reverts back to the previous one. I'm not sure why this happens. The Duration specified is 1048576, so it shouldn't snap out of it quite that fast.

ACS code:

Code: Select all

#library "ACS" // Name of the library
#include "zcommon.acs"

Script 1 (void)
{
    print (s:"Rott Player!");
	//Thing_ChangeTID(0,1000+PlayerNumber());//This assigns the TID
	int morphed = MorphActor(0, "PL_Rott", "", 1048576, 0, "", "");
}

Script 2 (void)
{
    print (s:"Doom Player!");
	//Thing_ChangeTID(0,1000+PlayerNumber());//This assigns the TID
	int morphed = MorphActor(0, "PL_Doom", "", 1048576, 0, "", "");
}
I couldn't find any alternative function I could use, as SetActorProperty doesn't seem to be able to change the classname.
User avatar
NeuralStunner
 
 
Posts: 12328
Joined: Tue Jul 21, 2009 12:04 pm
Preferred Pronouns: No Preference
Operating System Version (Optional): Windows 11
Graphics Processor: nVidia with Vulkan support
Location: capital N, capital S, no space
Contact:

Re: Using DECORATE to change player class

Post by NeuralStunner »

InsaneFury wrote: 1) ACS code can be applied, regardless of it being tied to specific MAPs
2) Script numbers only have to be unique on a per-wad/per-lump basis.
A [wiki]LOADACS[/wiki] lump is your ally here.

Here's an idea what you could do... Instead of morphing, use only one class but give it massive Decorate. Use dummy [wiki]Inventory[/wiki] items, and [wiki]A_JumpIfInventory[/wiki] to jump to the states for the desired pseudo-class. [wiki]SetActorProperty[/wiki] will also help immensely, in fact it can do most of the work for you.

Based off the most common differences between player classes:

1 - Sprites. Check the dummy item at the beginning of each state, and jump to one that is identical except for the sprite names. (Player.CrouchSprite would give you trouble, so it's probably best you set that to "". Squished standing sprites look awful, but that's the price you pay.) Note that you might be able to reference the correct sprite name in Spawn, and use "----" in the rest, which means don't change the sprite series. I don't know for sure, and you'd have to make sure the player is in their Spawn state after their pseudo-class changes. ([wiki]SetActorState[/wiki] should do it.) A Player equivalent to [wiki]SetMarineSprite[/wiki] would be ideal, especially if it could set both the PLAY sprite and the CrouchSprite.
2 - Speed. SetActorProperty can modify this directly.
3 - Health. Health and SpawnHealth can be changed by SetActorProperty.
Start the base class with the max Health of the lowest class. Now give it a customized [wiki]UpgradeStamina[/wiki] for each class, to bring it up to what you want. This upgrade should be permanent.
4 - Jumping. JumpZ can be changed by SetActorProperty.
5 - Sounds. This is a tough one... Some can be changed by SetActorProperty, but on a case-by-case basis. Others, like "UseFail", can't. (I wonder if all these sounds could be exposed to change by ACS?)
6 - Status Bar. This one is easy, [wiki=SBARINFO]SBarInfo[/wiki] can check for the dummy item.

I wonder if some new ACS functions would be possible? SetPlayerDisplayName (TID, "Name"), SetPlayerSprite (TID, "Sprite"), "CrouchSprite"), SetPlayerSoundClass (TID, "Name")?

Anyways, hope that helps! (Heh, looking all this stuff up has helped give me some ideas.) :)
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Re: Using DECORATE to change player class

Post by InsaneFury »

Wow, are you serious? That's way too much icky hacky code to manage, considering I'm only using this to get around the 6 classes select screen limitation... :shock:

Implementing 19 classes this way would be a real PITA... :roll: Not to mention messing with the custom playersounds and defining weaponsets per 'class'. The way I see it, ZDooM has a whole playerclass system in place already, I just need a tool that allows me to switch between them when a level (play session) starts.

I noticed this thread from way back, requesting a way to change classes mid-game. As the copic continues, Graf Zahl hints at some code 'being in', but I doubt that refers to the class selection code as I've yet to come across a function that does that, without imposing all limitations of the morph.
User avatar
Xaser
 
 
Posts: 10774
Joined: Sun Jul 20, 2003 12:15 pm
Contact:

Re: Using DECORATE to change player class

Post by Xaser »

Unfortunately, you've stumbled upon what is possibly the most "why the deuce is this not in?" feature in the history of features. Most of us are still waiting on an answer. ;)
User avatar
NeuralStunner
 
 
Posts: 12328
Joined: Tue Jul 21, 2009 12:04 pm
Preferred Pronouns: No Preference
Operating System Version (Optional): Windows 11
Graphics Processor: nVidia with Vulkan support
Location: capital N, capital S, no space
Contact:

Re: Using DECORATE to change player class

Post by NeuralStunner »

InsaneFury wrote:Wow, are you serious? That's way too much icky hacky code to manage, considering I'm only using this to get around the 6 classes select screen limitation... :shock:
Quite serious. But as I said, most of it works through ACS with the same simple function. If you make a global ACS script, it should work nicely. Conflict with other wads would probably not be a big concern, as it's doubtful your class select area would be present, and therefore usable, anyway. But sometimes you need to use some "hackiy" methods to get results. That's what I do, and I've gotten some interesting lessons out of it.

(And actually, it's seven classes max on the menu.)
InsaneFury wrote:Implementing 19 classes this way would be a real PITA...
Implementing 19 at all is going to be tough. :shock:

Swapping class was actually present in Vanilla Hexen, with the "Shadowcaster [0-2]" cheat. However, it did reset several things, such as AC, when used. I have to assume ZDoom's inventory code is much more complex, so that kind of thing would likely be prone to break if not done carefully, or be complained about if not done "well enough".
User avatar
Xaser
 
 
Posts: 10774
Joined: Sun Jul 20, 2003 12:15 pm
Contact:

Re: Using DECORATE to change player class

Post by Xaser »

That question is (from what I can recall) one of the main reasons why this feature was delayed for so long (and eventually fogotten about). Should the new class keep all the inventory from the old class, or should it reset to defaults? Or should the new class keep only the items that the new class is allowed to use (e.g. toss unselectable weapons)? Which method is best?

I think the answer is simple: all of them.

No, seriously. All it would take is a single "resetinventory" arg -- if 0, keep everything the way it is, and if 1, reset the inventory to the class's defaults. It could later be extended into a 'flags' variable in case an alternative method (as mentioned above) ever arises.

[Another concern is health/armor, I suppose, but again, that's why there args exist.]
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Re: Using DECORATE to change player class

Post by InsaneFury »

If you make a global ACS script, it should work nicely. Conflict with other wads would probably not be a big concern, as it's doubtful your class select area would be present, and therefore usable, anyway.
There will not be a class select area per se: On spawn, players will spawn an NPC that'll use Strife Dialogue to magically transform the player. By doing it this way, the feature should work, independent of loaded wads.

The ACS conflict I was asking about is what will happen if another wad is loaded that uses ACS function 1 to open a door, while my script has a second function 1: can only one function with a number be resident at all times during play? Or is this scoped to the lump it's declared in?
User avatar
NeuralStunner
 
 
Posts: 12328
Joined: Tue Jul 21, 2009 12:04 pm
Preferred Pronouns: No Preference
Operating System Version (Optional): Windows 11
Graphics Processor: nVidia with Vulkan support
Location: capital N, capital S, no space
Contact:

Re: Using DECORATE to change player class

Post by NeuralStunner »

InsaneFury wrote:The ACS conflict I was asking about is what will happen if another wad is loaded that uses ACS function 1 to open a door, while my script has a second function 1: can only one function with a number be resident at all times during play? Or is this scoped to the lump it's declared in?
Yes, there is the potential for conflict. Don't use Script 1 for a universal mod, that's way too common in maps. It would be better to use a high number. You can use any number up to 999, so you could try to pick something odd you doubt would be used much. (Like, say, 871.)
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Re: Using DECORATE to change player class

Post by InsaneFury »

NeuralStunner wrote:Yes, there is the potential for conflict. Don't use Script 1 for a universal mod, that's way too common in maps. It would be better to use a high number. You can use any number up to 999, so you could try to pick something odd you doubt would be used much. (Like, say, 871.)
Yeah, and if I 'so happen' to pick a number that someone else picked in their WAD I'm going to load, the end result will be unplayable. :(

Which is why I'm rather appalled by ACS, although I guess for some specific functionality, DECORATE is too limited. No wonder I see all those references to DoomScript as being the utopian DooM solution (never would have those two words would appear back to back in a sentence :D).

So, let's see. I've got a "Choose Player Class" which is limited to 9 classes, which I want to workaround by making Strife Dialogue to transform the player into another PlayerClass, but I don't want to do that in ACS as it might break third-party add-on WADs and all constructs in both DECORATE and ACS are limited to morphing the player, instead of permanently altering the playerclass.

Bottom line: either I go with the 'proper' way, class-wise and accept that the class can only be picked in the Player Setup menu, or I go the hacky way, implementing 19 classes all in one playerclass and relying on tonnes of scripting that might pose more trouble than it's worth.

Guess I'll stick with option #1 then. :P
User avatar
NeuralStunner
 
 
Posts: 12328
Joined: Tue Jul 21, 2009 12:04 pm
Preferred Pronouns: No Preference
Operating System Version (Optional): Windows 11
Graphics Processor: nVidia with Vulkan support
Location: capital N, capital S, no space
Contact:

Re: Using DECORATE to change player class

Post by NeuralStunner »

You can also force a class when starting a game via command line, with +PlayerClass. Note that this will be the display name. I.E. To play as the Hexen Cleric, you would use the option "+PlayerClass Cleric", while the actor itself is called ClericPlayer. (Of course, it could be called MysteryPlayer, and the display name could still be "Cleric".)

Now, PlayerClass is actually console command. Suppose you start a new game as a Fighter, then go to the console and put in the following commands:

Code: Select all

] PlayerClass Mage
] Map MAP01
This would effectively start a new game, but you'd be a Mage this time instead.
User avatar
InsaneFury
Posts: 105
Joined: Mon Nov 23, 2009 6:51 am

Re: Using DECORATE to change player class

Post by InsaneFury »

Yeah, I know. For me personally it isn't a big deal for now, but for other (new) players it would come across as rather cumbersome.

IMO a mod should be standalone within ZDoom, not depending on the player to parameterize the shortcut, or having to type console commands.
Locked

Return to “Editing (Archive)”