Creating a Shrink Ray

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.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
metalx1000
Posts: 21
Joined: Tue Apr 23, 2024 5:56 pm
Operating System Version (Optional): Debian SID
Graphics Processor: Not Listed
Contact:

Creating a Shrink Ray

Post by metalx1000 »

I've created a shrink ray that shrinks monsters a little bit each time they are hit, until they are at half size.
It works, but I feel like there has to be a better way to do it.

Currently it replaces the Plasma Balls for the Plasma Gun.

The code is below or here:
https://gitlab.com/metalx1000/Doom-Zscr ... type=heads

Code: Select all

// replaces PlasmaBall with shrink ray ball 
// each hit will shrink monster by .01 until they are at have size
class ShrinkBall : PlasmaBall Replaces PlasmaBall
{
  Default
  {
    Translation "192:207=16:31"; //make the ball red
    Damage 0;
  }

  override void Tick()
  {
    super.Tick();

    double dist = 0;
    let bti = BlockThingsIterator.Create(self, dist);
    while (bti.Next())
    {
      let act = bti.thing;
      if(bti.thing.bIsMonster){
        if (self && Distance3D(bti.thing) < 64)
        {
          if(bti.thing.scale.y > .5){
            //Console.Printf(TEXTCOLOR_GREEN .. "%f", bti.thing.scale.y);
            bti.thing.Scale = (bti.thing.Scale.x*.99,bti.thing.Scale.x*.99);
            //bti.thing.Scale.x-=.01;
            //bti.thing.Scale.y-=.01;
          }
        }
      }
    }
  }
}

Any suggestions on improving this code or doing a different way would be appreciated.
Jarewill
 
 
Posts: 1853
Joined: Sun Jul 21, 2019 8:54 am

Re: Creating a Shrink Ray

Post by Jarewill »

It might be better to use a different virtual function like DoSpecialDamage.
That way you will get a direct pointer to the hit actor and you won't need to run an iterator every tick.
You could even use the +HITTRACER flag and alter the actor in the projectile's Death state.
User avatar
metalx1000
Posts: 21
Joined: Tue Apr 23, 2024 5:56 pm
Operating System Version (Optional): Debian SID
Graphics Processor: Not Listed
Contact:

Re: Creating a Shrink Ray

Post by metalx1000 »

Jarewill wrote: Thu May 09, 2024 9:51 am It might be better to use a different virtual function like DoSpecialDamage.
That way you will get a direct pointer to the hit actor and you won't need to run an iterator every tick.
You could even use the +HITTRACER flag and alter the actor in the projectile's Death state.
Thank you for your quick and useful answer.
DoSpecialDamage worked great!

I'll play around with +HITTRACER next.

My new code below or HERE

Code: Select all

// replaces PlasmaBall with shrink ray ball
// each hit will shrink monster by .01 until they are at have size
class ShrinkBall : PlasmaBall Replaces PlasmaBall
{
  float min_size; // this will be set to the smallest a monster can get
  float scale_rate; // the rate at which the monster shrinks
  Default
  {
    Translation "192:207=16:31"; //make the ball red
    Damage 1; // Need to do damge for DoSpecialDamage to run
  }


  // https://zdoom.org/wiki/DoSpecialDamage
  override int DoSpecialDamage (Actor victim, int damage, Name damagetype)
  {
    min_size = .5; // monster won't go smaller then half size
    scale_rate = .9; // smaller float the quicker they shrink
    if (victim != NULL && target != NULL && victim.Scale.x > min_size)
    {
      let s = victim.Scale.x*scale_rate;
      //Console.Printf(TEXTCOLOR_GREEN .. "%f", s);
      victim.Scale = (s,s);
    }
    return 0; // 0  damage so shrink ray doesn't hurt monster
  }
}

peewee_RotA
Posts: 407
Joined: Fri Feb 07, 2014 6:45 am

Re: Creating a Shrink Ray

Post by peewee_RotA »

For the actual shrinking, adding an inventory item to the target actor is one of the best ways to apply effects. That way the actor has something you can check for later to prove they are under the effect, and you can apply things to the actors using the inventory's virtual functions. It gives you access to things like when it is used, when it expires if it is timed, when the actor changes levels, etc.

Here's an example of adding an inventory item to decorations to convert them into monsters:
https://github.com/cabbruzzese/xrpg/blo ... ead.zs#L44

Code: Select all

class RaiseStatueItem : Inventory
{
	Default
	{
		+INVENTORY.UNDROPPABLE
		+INVENTORY.UNTOSSABLE
		+INVENTORY.AUTOACTIVATE
		+INVENTORY.PERSISTENTPOWER
		+INVENTORY.UNCLEARABLE
	}

    override bool Use(bool pickup)
    {
		if (!Owner)
			return false;
		
		let statueMo = StatueMonster(Owner);
		if (!statueMo)
			return false;
		
		if (!statueMo.IsSpawnFinished() && statueMo.StatueMonsterType)
		{
			statueMo.SetState(statueMo.FindState("StatueMonsterRise"));
		}

        return false;
    }
}
You basically just have to give the target the inventory item, and the inventory item can do all of these effects on its owner.
User avatar
metalx1000
Posts: 21
Joined: Tue Apr 23, 2024 5:56 pm
Operating System Version (Optional): Debian SID
Graphics Processor: Not Listed
Contact:

Re: Creating a Shrink Ray

Post by metalx1000 »

peewee_RotA ,
Thanks for the advise.
I have to play around with Inventory items more.
I get the basic idea, but haven't used them in any of my scripts yet.
Post Reply

Return to “Scripting”