Page 1 of 1

Speed

PostPosted: Fri Nov 19, 2021 3:30 pm
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 allExpand view
// 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 allExpand view
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:

Re: Speed

PostPosted: Thu Dec 02, 2021 8:43 pm
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 :)

Re: Speed

PostPosted: Fri Dec 03, 2021 5:03 am
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.