Ripper with fixed damage per actor?

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
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Ripper with fixed damage per actor?

Post by Kzer-Za »

I want to create a projectile that goes through enemies but hurts each of them only once. Is it posssible to accomplish with rippers? Do they do damage every tic? Maybe I should give it a zero damage but give it PosionDamage with a duration of a second (because in that time the projectile would definitely leave the body), but then if two such projectiles hit one actor within a second, the damage from the second one will be ignored, if I don't set the flag ADDITIVEPOISONDAMAGE. But if I add it, wouldn't the ripper add the poison as much times as it would do normal damage?
User avatar
comet1337
Posts: 876
Joined: Fri Sep 25, 2015 3:48 am
Location: elsewhere

Re: Ripper with fixed damage per actor?

Post by comet1337 »

rippers don't do damage once per tic
they do damage based on distance travelled through an actor
if you're using zscript, you'll want to take a look at SpecialMissileHit
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

Unfortunately, this is the extent of my knoledge of zscript: https://zdoom.org/wiki/Converting_DECOR ... to_ZScript, and I don't even understand everything in there. Are there any tutorials? The pages in the category "ZScript guides" are more like reference cards for those who already know their way around. Where can I learn the basics? Like its structure, what goes where, etc.
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

As far as I can tell, making SpecialMissileHit return 1 just turns it into a ripper. Of course, my knoledge of zscript is very limited, so maybe I'm just doing something wrong. My code is this:

Code: Select all

Class HLCrossbowBolt : FastProjectile
{
	override int SpecialMissileHit (Actor victim)
	{
		victim.DamageMobj (self, target, 10, 'Melee');
		return 1;
	}
Default
{
//	Speed 90;
	Speed 10;
	DamageFunction 0;
	DamageType "Ether";
	SeeSound "";
	Radius 2;
	Height 2;
	Projectile;
	+DONTSPLASH;
	+WINDTHRUST;
	RenderStyle "Add";
	DeathSound "BOWHIT1";
	Obituary "$OB_MPCROSSBOW";
	MissileHeight 8;
	Decal "CrossbowScorch";
}
	States
	{
	Spawn:
		HLAR A 1 Bright A_SpawnItem("EtherealFlare1");
		Loop;
	Death:
		FX03 CDE 2 Bright A_SpawnItem("EtherealFlare2");
		Stop;
	}
}
It definitely does damage multiple times.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Ripper with fixed damage per actor?

Post by Arctangent »

I mean, you're telling the missile to, each time it collides with a damageable actor, deal 10 damage and then pass through without exploding. So, it'll pass through once, deal its damage, pass through again, deal its damage, etc.. Basically, you're not telling the game to do anything but what ripping missiles already do - there's nothing there saying "pass through this actor, but don't deal damage."

So, you're going to want to do that, and the most straightforward way to do that is to keep track of what actors the missile has already hit, so it can know not to damage them. [wiki]Dynamic arrays[/wiki] are perfect for this - they can store any number of actor pointers and have the Find() function to grab the index of an item - so you could, say,

Code: Select all

	Array<Actor> hitList;

	override int SpecialMissileHit (Actor victim)
	{
		if (hitList.Find (victim) == hitList.Size())
		{
			victim.DamageMobj (self, target, 10, 'Melee');
			hitlist.Push (victim)
		}
		return 1;
	}
to add a dynamic array to your missle, then use the info in there to see if the missile's hit anything or not.

Note the if statement: if Find() can't find the item, then it'll instead return the array's size. So we can compare Find() and Size() to see if the victim's not in there, and thus, hasn't already been hit.
User avatar
Apeirogon
Posts: 1605
Joined: Mon Jun 12, 2017 12:57 am

Re: Ripper with fixed damage per actor?

Post by Apeirogon »

Here more elegant solution

Code: Select all

   actor last_hit;

   override int SpecialMissileHit (Actor victim)
   {
      if (last_hit == victim) {return 1;}

      victim.damagemobj(arguments);
      last_hit = victim;
      return 1;
   }
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Ripper with fixed damage per actor?

Post by Arctangent »

Apeirogon wrote:Here more elegant solution

Code: Select all

   actor last_hit;

   override int SpecialMissileHit (Actor victim)
   {
      if (last_hit == victim) {return 1;}

      victim.damagemobj(arguments);
      last_hit = victim;
      return 1;
   }
... which will proceed to use normal ripping behavior if the projectile is in the position to hit multiple actors at the same time ( y'know, like in the very rare situation where monsters are standing next to each other ), which is what I'd call the exact opposite of "elegant."
User avatar
Apeirogon
Posts: 1605
Joined: Mon Jun 12, 2017 12:57 am

Re: Ripper with fixed damage per actor?

Post by Apeirogon »

hit multiple actors at the same time
This is most likely an artificial situation. Because I used it, like always, and dont faced with such situation.
Only cases when this really can happens is when projectile have enormous height and/or radius.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Ripper with fixed damage per actor?

Post by Arctangent »

Apeirogon wrote:
hit multiple actors at the same time
This is most likely an artificial situation. Because I used it, like always, and dont faced with such situation.
Only cases when this really can happens is when projectile have enormous height and/or radius.
If it was an artificial situation, then the vanilla rocket launcher would be pretty useless.

Unless by "enormous height and radius" you mean ... y'know, the size of vanilla projectiles, considering they're more than capable of colliding with multiple monsters at once, especially in the narrow spaces of Doom 1 maps.
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

Arctangent wrote:

Code: Select all

	Array<Actor> hitList;

	override int SpecialMissileHit (Actor victim)
	{
		if (hitList.Find (victim) == hitList.Size())
		{
			victim.DamageMobj (self, target, 10, 'Melee');
			hitlist.Push (victim)
		}
		return 1;
	}
Thanks! That works beautifuly :)

There's one hitch though, such a projectile hits myself the moment it is spawned :) I suppose, projectiles are spawned by default inside the players "box" (or what is it called). So I suppose the simplest way of avoiding hurting the launcher of the projectile (it can be not only the player since I'm planning on giving a similar attack to a monster) would be to place it in the array. Something like this?

Code: Select all

	Array<Actor> hitList;

	hitlist.Push (something) // <- the designation of the actor that launches the projectile
	override int SpecialMissileHit (Actor victim)
	{
		if (hitList.Find (victim) == hitList.Size())
		{
			victim.DamageMobj (self, target, 10, 'Melee');
			hitlist.Push (victim)
		}
		return 1;
	}
Only I don't know how I should designate the said actor.
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

Also, I tested such a projectile with monsters. They do indeed hurt themselves when launching such projectiles, and besides, if a member of their species is hit with it, they get into infights within the species. Can it be prevented without setting the damagefactor to zero?
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Ripper with fixed damage per actor?

Post by Arctangent »

Something as simple as this:

Code: Select all

if (victim == target) return 1;
before the rest of the code in SpecialMissileHit should handle all of that perfectly fine.

All standard projectile-spawning functions will set the projectile's target to its owner, so you can always use that as a reference to them. As for why it's stored as the projectile's target? That's because in vanilla Doom 1, the only pointer actors had to other actors was their target, so id just reused it for projectiles since there weren't any that needed to keep track of an actual target.

Which, of course, changed as soon as Doom 2 rolled around, and that's why there's a target and a tracer pointer for all actors.
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

Thanks, that fixes the problem with damaging self, but the monsters still get into infights within one species. I mean, normally, if a monster is hit by a projectile launched by a member of its species, it is unharmed and does not turn on the launcher, but with these projectiles they do get hurt and turn on each other.

I scrambled something that I thought would fix it (additional condition), but it does not work:
Edit: It was my lack of attention, I forgot to insert this into one of the two projectiles. Actually this does work.

Code: Select all

		if (victim.GetSpecies() == target.GetSpecies())
			return 1;
But this doesn't: I tried to put "PrintBold(s:"The script works");" the line above "return 1", but then the game wouldn't launch with this error:

Code: Select all

Script error, ":zscript.proj_mon_beast" line 68:
Call to unknown function 'PrintBold'
Trying to PlaySound prior to "return 1" also returns "unknown function" (I wanted to make the projectiles play the hit sound, because now they go silently through everyone).
Blue Shadow
Posts: 4949
Joined: Sun Nov 14, 2010 12:59 am

Re: Ripper with fixed damage per actor?

Post by Blue Shadow »

They should be [wiki]A_PrintBold[/wiki] and [wiki]A_PlaySound[/wiki]. What you're trying to use there are their ACS equivalent.
Kzer-Za
Posts: 509
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Ripper with fixed damage per actor?

Post by Kzer-Za »

Thanks!
Post Reply

Return to “Scripting”