Speed

Post your example zscripts/ACS scripts/etc here.
Forum rules
The Projects forums are only for projects. If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.

Got a cool project idea but nothing else? Put it in the project ideas thread instead!

Projects for any Doom-based engine (especially 3DGE) are perfectly acceptable here too.

Please read the full rules for more details.
Hey Doomer
Posts: 283
Joined: Sat Sep 25, 2021 3:38 am

Speed

Post by Hey Doomer »

An annoyance (for me) of Doom has been having a health of 2 and being able to zoom around as though everything is OK. There should be consequences. A logical consequence is to slow down or speed up, deal more or less damage, feel more or less damage, and heal or regenerate armor slow or fast. I've called this Speed because the most noticeable consequence is changes in player speed.

The way this works is simple: everything that spawns is given a powerup that determines how a change in health affects the owner. Monster and player variables are controlled by different Cvars, so (for example) a negative "Speed" factor will make monsters move faster after they are hurt. Monsters can also regenerate health, as if you need motivation to kill them.

CVars:

Code: Select all

// monster speed abilities
user float mospeed_freq = 5;
user float mospeed_speed = 0;
user float mospeed_damagefactor = 0;
user float mospeed_damagemultiply = 0;
user float mospeed_health = 0;

// player speed abilities
user float plspeed_freq = 5;
user float plspeed_speed = 0;
user float plspeed_damagefactor = 0;
user float plspeed_damagemultiply = 0;
user float plspeed_health = 0;
user float plspeed_adrenaline = 1;
user float plspeed_armor = 0;

// debug
user bool speed_debug=false;
ZScript:

Code: Select all

class ArmorRegen : BasicArmorBonus
{
	Default
	{
		Armor.SaveAmount 1;
		Armor.MaxSaveAmount 0x7FFFFFFF;
	}
}

class Speed : Powerup
{
	Default
	{
		Powerup.Duration 0x7FFFFFFF;
		+Inventory.Autoactivate;
	}

	// baseHealth baselines
	int baseHealth;
	int baseSpeed;
	float baseDamageFactor;
	float baseDamageMultiply;
	
	// counters
	int lasthealth;
	int lastarmor;
	int tCount;

	// cvars
	float cvar_freq;
	float cvar_speed;
	float cvar_damagefactor;
	float cvar_damagemultiply;
	float cvar_health;
	float cvar_adrenaline;
	float cvar_armor;
	bool cvar_debug;

	void setDefaults()
	{
		baseHealth = Owner.Health;
		baseSpeed = Owner.Speed;
		baseDamageFactor = Owner.DamageFactor;
		baseDamageMultiply = Owner.DamageMultiply;
		lasthealth = Owner.Health;
		lastarmor = CountInv("BasicArmor");
		tCount = 0;

		if (Owner.bIsMonster)
		{
			cvar_freq = Cvar.FindCvar("mospeed_freq").GetFloat();
			cvar_speed = Cvar.FindCvar("mospeed_speed").GetFloat();
			cvar_damagefactor = Cvar.FindCvar("mospeed_damagefactor").GetFloat();
			cvar_damagemultiply = Cvar.FindCvar("mospeed_damagemultiply").GetFloat();
			cvar_health = Cvar.FindCvar("mospeed_health").GetFloat();
		}
		else
		{
			cvar_freq = Cvar.FindCvar("plspeed_freq").GetFloat();
			cvar_speed = Cvar.FindCvar("plspeed_speed").GetFloat();
			cvar_damagefactor = Cvar.FindCvar("plspeed_damagefactor").GetFloat();
			cvar_damagemultiply = Cvar.FindCvar("plspeed_damagemultiply").GetFloat();
			cvar_health = Cvar.FindCvar("plspeed_health").GetFloat();
			cvar_adrenaline =  Cvar.FindCvar("plspeed_adrenaline").GetFloat();
			cvar_armor =  Cvar.FindCvar("plspeed_armor").GetFloat();
		}
		cvar_debug = Cvar.FindCvar("speed_debug").GetBool();
	}
	override void DoEffect()
	{
		if (!lasthealth)
		{
			setDefaults();
		}
		tCount++;
		if (tCount > 35 * cvar_freq)
		{
			tCount = 0;
			if (Owner.Health < baseHealth)
			{
				if (lasthealth != Owner.Health)
				{
					Owner.Speed += (Owner.Health - lasthealth) * 0.01 * cvar_speed;
					Owner.DamageFactor -= (Owner.Health - lasthealth) * 0.01 * cvar_damagefactor;
					Owner.DamageMultiply += (Owner.Health - lasthealth) * 0.01 * cvar_damagemultiply;
					Owner.Health += Random(0, baseHealth) + CountInv("BasicArmor") > lasthealth ? cvar_health : 0;
					lasthealth = Owner.Health;

					if (cvar_debug)
					{
						console.printf("%s: Speed: %f Dish: %f Take: %f Health: %d", Owner.GetSpecies(), Owner.Speed, Owner.DamageMultiply, Owner.DamageFactor, Owner.Health);
					}
				}
			}
			if (Owner.Health == baseHealth)
			{
				Owner.Speed = baseSpeed;
				Owner.DamageFactor = baseDamageFactor;
				Owner.DamageMultiply = baseDamageMultiply;
			}
			// these only apply to the player
			if (Owner.Health > baseHealth)
			{
				Owner.Speed *= cvar_adrenaline;
			}
			if (CountInv("BasicArmor") < lastarmor)
			{
				Owner.GiveInventory("ArmorRegen", Random(0, 1) * cvar_armor);
			}
		}
	}
}

class speed_EventHandler : EventHandler
{
	int tidCounter;

	override void WorldThingSpawned(WorldEvent e)
	{
		if (e.thing && e.thing.bIsMonster)
		{
			e.thing.GiveInventory("Speed", 1);

			// give the monster a unique tid
			if (tidCounter == 0)
			{
				tidCounter = 22000;
			}
			if (e.thing && e.thing.bIsMonster && !e.thing.tid)
			{
				e.thing.ChangeTid(tidCounter);
				tidCounter++;
			}
		}
	}
	override void PlayerSpawned(PlayerEvent e)
	{
		PlayerInfo player = players[e.PlayerNumber];
		if (player.mo.CountInv("Speed") == 0)
		{
			player.mo.GiveInventory("Speed", 1);
			player.mo.GiveInventory("ArmorRegen", 100);
		}
	}
}
To be fair, I also start the player with 100 armor. It seems dumb to start the game without any armor at all (my preference). The Speed powerup handles factors related to health that changes every cvar_freq seconds. I'm still playing around with this, but the idea is that player armor increases the chance of health regeneration. As you can see, if cvars are set to defaults nothing happens. Finally, if health is over baseline health, an adrenaline factor is applied to the player. That can be entertaining.

Small changes in the sliders greatly affect the game balance as you can imagine. Originally I put defaults that were minimal but thought better of it. This could be buggy, and I'm still testing it. But I think the basic idea works.

Update
Spoiler:
thugsta
Posts: 150
Joined: Mon Jan 21, 2019 10:10 am

Re: Speed

Post by thugsta »

Can you make an alt version of this but only for the monsters and without health regen (or make health regen be a toggle?) That will be fantastic. Loving your work i got to say, ideas hardly ever if ever seen :)
Hey Doomer
Posts: 283
Joined: Sat Sep 25, 2021 3:38 am

Re: Speed

Post by Hey Doomer »

Thanks for the comments!

The Settings menu controls amounts of speed, damage, damage multiplier, and regeneration. I see that I can't reset health and armor to zero for the player (no regeneration), but it does go down to .19 and .06, which is low enough.

So, for example, you can make monsters move slower and the player faster or vice versa depending on what happens. You can make monster regenerate health while the player steadily loses a little. Stuff like that, that's the idea.

Return to “Script Library”