Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
  • 0
LukeGaming

How does Lost Soul attack work? How to replicate it without a_skullattack?

Question

Recently I have been trying to make some changes to lost soul in zscript (things like making it do homing attack, or stop its charge after certain distance - all of it was giving me unexpected results) and I ran into a major problem - I have no idea how this thing really works. Zdoom wiki wasn't much help https://zdoom.org/wiki/A_SkullAttack

Why does it loop with goto Missile+2? Is there is some way to replicate this type of pseudo-projectile attack without using a_skullattack?

Share this post


Link to post

3 answers to this question

Recommended Posts

  • 0

A_SkullAttack does following things:

  • Checks if has valid target
  • Sets up +SKULLFLY flag (this flag handles what happens when the actor later crashes into something)
  • Plays attack sound
  • Turns to face target (player)
  • Sets its velocity to charge speed (given by function parameter) in that facing direction
  • Adjusts Z velocity so it can hit target that is on different Z position

Lost soul attack has goto Missile+2 so it loops frames C and D, so it does not call A_SkullAttack again (this loop breaks when actor with +SKULLFLY crashes into something.)

 

  • To make homing attack, you may need to call A_SkullAttack (or something with similar behavior) in loop.
  • To stop charging, you should stop the moving (A_Stop) and clear the +SKULLFLY flag, and probably jump to some normal state (like See).

 

A_SkullAttack is defined like this (from gzdoom.pk3):

void A_SkullAttack(double skullspeed = DEFSKULLSPEED)
{
	if (target == null) return;

	if (skullspeed <= 0) skullspeed = DEFSKULLSPEED;

	bSkullfly = true;
	A_StartSound(AttackSound, CHAN_VOICE);
	A_FaceTarget();
	VelFromAngle(skullspeed);
	Vel.Z = (target.pos.Z + target.Height/2 - pos.Z) / DistanceBySpeed(target, skullspeed);
}

 

Share this post


Link to post
  • 0

I mildly hate A_SkullAttack too, so I get your question.

Using that function is basically a shortcut to make your monsters behave like projectiles until they miss or hit, but unfortunately there's more behind it (jaeden did a great job showing everything the function does).

 

So if you want to get rid of some of nasty stuff that can happen with the function or avoid some limitations, you can either rewrite the function giving it a new name and adding/removing whatever you like or go for different maybe more hacky ways.

 

For example, you can use SEEKERMISSILE with A_SeekerMissile() on monsters too if you want straight up homing actors, or you could just use ThrustThing and calling A_FaceTarget.

To get the impact damage you could use a proximity check like A_JumpIfTargetInLOS and if it returns true call a melee attack function, or shoot a flash invisible projectile.

 

You can play with tons of other options to make your custom lost soul behavior without being forced to limit yourself with A_SkullAttack if it doesn't suit your needs

Share this post


Link to post
  • 0
15 hours ago, jaeden said:

A_SkullAttack does following things:

  • Checks if has valid target
  • Sets up +SKULLFLY flag (this flag handles what happens when the actor later crashes into something)
  • Plays attack sound
  • Turns to face target (player)
  • Sets its velocity to charge speed (given by function parameter) in that facing direction
  • Adjusts Z velocity so it can hit target that is on different Z position

Lost soul attack has goto Missile+2 so it loops frames C and D, so it does not call A_SkullAttack again (this loop breaks when actor with +SKULLFLY crashes into something.)

 

  • To make homing attack, you may need to call A_SkullAttack (or something with similar behavior) in loop.
  • To stop charging, you should stop the moving (A_Stop) and clear the +SKULLFLY flag, and probably jump to some normal state (like See).

 

A_SkullAttack is defined like this (from gzdoom.pk3):


void A_SkullAttack(double skullspeed = DEFSKULLSPEED)
{
	if (target == null) return;

	if (skullspeed <= 0) skullspeed = DEFSKULLSPEED;

	bSkullfly = true;
	A_StartSound(AttackSound, CHAN_VOICE);
	A_FaceTarget();
	VelFromAngle(skullspeed);
	Vel.Z = (target.pos.Z + target.Height/2 - pos.Z) / DistanceBySpeed(target, skullspeed);
}

 

 

14 hours ago, Kan3 said:

I mildly hate A_SkullAttack too, so I get your question.

Using that function is basically a shortcut to make your monsters behave like projectiles until they miss or hit, but unfortunately there's more behind it (jaeden did a great job showing everything the function does).

 

So if you want to get rid of some of nasty stuff that can happen with the function or avoid some limitations, you can either rewrite the function giving it a new name and adding/removing whatever you like or go for different maybe more hacky ways.

 

For example, you can use SEEKERMISSILE with A_SeekerMissile() on monsters too if you want straight up homing actors, or you could just use ThrustThing and calling A_FaceTarget.

To get the impact damage you could use a proximity check like A_JumpIfTargetInLOS and if it returns true call a melee attack function, or shoot a flash invisible projectile.

 

You can play with tons of other options to make your custom lost soul behavior without being forced to limit yourself with A_SkullAttack if it doesn't suit your needs

Thank you both very much, I now have general idea on how it works and what to do with it.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×