Speed

Post your example zscripts/ACS scripts/etc here.

Speed

Postby Hey Doomer » Fri Nov 19, 2021 3:30 pm

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:
You do not have the required permissions to view the files attached to this post.
Hey Doomer
 
Joined: 25 Sep 2021
Operating System: Windows 11
OS Test Version: No (Using Stable Public Version)
Graphics Processor: ATI/AMD with Vulkan Support

Return to Script Library

Who is online

Users browsing this forum: bjork and 1 guest