Recreating Whirlwind without A_WhirlwindSeek

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!
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!)
Kzer-Za
Posts: 529
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Recreating Whirlwind without A_WhirlwindSeek

Post by Kzer-Za »

I'm trying to do the subject in order to give the Whirlwind a certain lifetime, so that it doesn't die when it hits an obstacle, but just waits until its lifetime runs out (and can continue pursuing when its aim shows itself again). I have run into a couple problems.

1. A_VileAttack (that I used for making my version of Whirlwind thrust the object of the attack in the air) takes place when the whirlwind is still pretty far from me, I'd say about 4 meters away. Also it doesn't thrust me up where I stood, but teleports me straight into the position of the Iron Lich and thrusts up there.

2. The whirlwind dies when it hits the ceiling (if I fly up and it follows me). Sure, the original Whirlwind did it too, but it was the second thing that I wanted to fix. But despite having BounceType "Hexen" and BounceFactor 0, it still dies when it hits the ceiling.

Can these two things be fixed?

Code: Select all

Class Tornado : Actor
{
	int TornadoLife;
	
	override void PostBeginPlay()
	{
		TornadoLife = 350;
		Super.PostBeginPlay();
	}
Default
{
	Radius 16;
	Height 74;
	Speed 10;
	DamageFunction 3;
	DamageType "Ether";
	Projectile;
	-ACTIVATEIMPACT
	-ACTIVATEMCROSS
	+SEEKERMISSILE
	+DONTSEEKINVISIBLE
//	+EXPLOCOUNT
	+STEPMISSILE
	+WINDTHRUST
	+NOWALLBOUNCESND
	+BOUNCEONACTORS
	+CANBOUNCEWATER
	-FLOORCLIP
	BounceType "Hexen";
//	BounceType "HexenCompat";
	BounceFactor 0;
	WallBounceFactor 0;
	RenderStyle "Translucent";
	Alpha 0.5;
	SeeSound "ironlich/attack3";
//	DefThreshold 60;
//	Threshold 50;
}
	States
	{
	Spawn:
		FX07 DDEEFFGG 3;
	Pursue:
		TNT1 A 0 A_JumpIf(TornadoLife < 0, "Death");
		FX07 ABC 3
		{
			TornadoLife = TornadoLife - 3; // minus frame length
			A_SeekerMissile(10, 30, 0);
		}
		TNT1 A 0 A_VileAttack("ironlich/attack3", 0, 0, 0, 1.0);
		Loop;
	Death:
		TNT1 A 0 A_Stop;
		FX07 GFED 4;
		Stop;
	}
}
Kzer-Za
Posts: 529
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Kzer-Za »

I just tried to replace A_VileAttack with "ThrustThingZ(1000, 38, 0, 1);" and again, it applies the vertical force to me when the whirlwind is pretty far from me, at about the same distance as when it applies A_VileAttack. The radius of the whirlwind is 16, and if I remove both A_VileAttack and ThrustThingZ then it starts dealing damage at the right distance (when its model seems to touch me). Why then does it apply A_VileAttack and ThrustThingZ at such a great distance?
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Arctangent »

I'm not really sure what you're expecting. Neither of those functions have any concept of range - and ThrustThingZ doesn't even have a concept of the actor's position - so of course they'd apply their effects fully if you didn't implement your own range check.

I mean, it's not like you're calling them when the projectile hits something, either. You're calling them while it's flying around idly, so it goes without saying that they'd just apply their effects while they're flying around.

Notice that the actual whirlwind actor doesn't even do its toss-up effects via an action function, but through an override of a virtual function that's called when dealing its damage. A_WhirlwindSeek is literally just that - a function the whirlwind uses to seek out its tracer - and has nothing to do with its special on-hit effects. Also worth noticing is that it doesn't make use of ThrustThingZ, but rather manipulates the target's vel vector directly - worth remembering that's one of the main powers of ZScript, the ability to modify an actor's variables without doing it through a middleman function.
Kzer-Za
Posts: 529
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Kzer-Za »

Ah, thanks!

About the code of the DoSpecialDamage by this link, could you, please, clarify what "if (level.time & 16)" means? For me it reads as "if level.time is true and 16 is true". I don't understand what it's supposed to mean.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Arctangent »

That's not the logical AND, which is &&, it's the binary one. That means it's taking binary form of level.time and zeroing out any bits that aren't shared by 00010000 ( which is 16 in binary ), then following through if the result is non-zero ( because zero implicitly equals false, and non-zero implicitly equals true - and if you zero out all the bits in a number, you end up with 0 ). Unless I'm mistaken, that means a whirlwind can start tossing its victims 16 tics after the level starts, continues to do so for a total of 16 tics ( including the tic it "activates" ), then "shuts off" for 16 more tics before the process repeats.

Likely the idea was to give a sense of randomness to whether or not a whirlwind will toss the player up, while also preventing it from permanently juggling them until they die.
Kzer-Za
Posts: 529
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Kzer-Za »

Thanks again!
Kzer-Za
Posts: 529
Joined: Sat Aug 19, 2017 11:52 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Recreating Whirlwind without A_WhirlwindSeek

Post by Kzer-Za »

Now thrusting works! :)

Concerning the problem with hitting the ceiling, I was mistaken. The WW does not actually die hitting it if it is spawned lower and raises to the ceiling. However, I gave the Iron Lich +FLOAT, so it pursues me and raises to just below the ceiling (or sometimes raises there even if I stay on the ground, pushed there by my shots). And if it tries "shooting" a WW there, the latter obviously tries to spawn inside the ceiling and dies. I didn't want to decrease the offset of A_SpawnProjectile because then the WW wouldn't seem like it's coming out of the Lich's mouth, and I didn't want to decrease the WW height because it would mess up collision detection (I think).

So I fixed that by setting its initial height to 34 instead of 74 and using this in the Spawn state:

Code: Select all

FX07 DDEEFFGG 3 {self.height = self.height + 5;}
It seems to work, but does it actually do what I suppose it should do? (I.e., gradually increasing the height to 74 with steps of 5).

Return to “Scripting”