A_SkullAttack seems to be a bit of a weird one. I have an enemy (it's a fish!) that uses A_SkullAttack to swim at the player and damage him. I've placed the fish in a map in fairly large swarms... er schools? Problem is, they can damage and kill each other so all the player has to do is step back and wait until most of the fish have gone and then mop up the remainder. They're not actually infighting, just bumping in to each other (infighting is switched off in the MAPINFO).
I want them to not hurt each other but, otherwise, be perfectly normal. There is nothing fancy about my use of A_SkullAttack. It's just there in the missile state, just like a lost soul.
I've tried:
+NOINFIGHTSPECIES
+DONTHARMCLASS
+DONTHARMSPECIES
I gave them
DamageType "Fishy"
DamageFactor "Fishy", 0.0
And none of the above worked.
So, is it even possible?
Enemy with A_SkullAttack not hurt each other - how?
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!)
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!)
-
-
- Posts: 26880
- Joined: Tue Jul 15, 2003 4:58 pm
- Location: Scotland
-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Enemy with A_SkullAttack not hurt each other - how?
A_SkullAttack sets the MF_SKULLFLY (in ZScript bSkullFly) flag on the actor. When that flag is set, collision with any other actor calls an internal 'Slam' function that causes damage to the hit actor, disregarding any DONTHARM* flags.
I don't know of a way to get around this other than to use ZScript to override your enemy's Slam function (or maybe the DamageMobj function) and add an IsFriend(victim) check so that the slams don't damage other enemies (or something similar).
EDIT: The internal default Slam function damages the hit actor with a damagetype of 'Melee' (see here) You *could* try just making your fish immune to melee damage, but that might have other unwanted side effects (like not being able to punch or chainsaw fish...).
I don't know of a way to get around this other than to use ZScript to override your enemy's Slam function (or maybe the DamageMobj function) and add an IsFriend(victim) check so that the slams don't damage other enemies (or something similar).
EDIT: The internal default Slam function damages the hit actor with a damagetype of 'Melee' (see here) You *could* try just making your fish immune to melee damage, but that might have other unwanted side effects (like not being able to punch or chainsaw fish...).
-
-
- Posts: 26880
- Joined: Tue Jul 15, 2003 4:58 pm
- Location: Scotland
Re: Enemy with A_SkullAttack not hurt each other - how?
Thanks for that information.
I just took a look at the ZScript definition for the Lost Soul and I certainly don't see anything in there that I can easily tamper with to address this. I may have to look at a different approach for the enemy. Shame because the SkullAttack was exactly what I wanted and it works well other than the killing each other issue.
[edit] Just seen your edit. I'll see if that works simply for the sake of investigation but I do still want to be able to melee-kill the fish (I was even toying with making the firing weapons not work underwater) so, unfortunately, I don't think it's a solution. [/edit]
[edit2] Well, making the fish immune to the melee damage type does indeed stop them killing each other by bumping into one another but it does also prevent the player using melee weapons to kill them. I did try giving a melee weapon a new damage type but the fish still seemed to be immune to it for some reason. [/edit2]
[edit3] Doh! Guess who forgot melee weapon damagetype goes on the puff, not the weapon? I can indeed make the fish immune to melee and then make melee weapons use a different damage type to get the effect I want. Now I just have to think things through to see if altering the melee weapons like that will have an unwanted side effect elsewhere. Thanks for the help.
[/edit3]
I just took a look at the ZScript definition for the Lost Soul and I certainly don't see anything in there that I can easily tamper with to address this. I may have to look at a different approach for the enemy. Shame because the SkullAttack was exactly what I wanted and it works well other than the killing each other issue.

[edit] Just seen your edit. I'll see if that works simply for the sake of investigation but I do still want to be able to melee-kill the fish (I was even toying with making the firing weapons not work underwater) so, unfortunately, I don't think it's a solution. [/edit]
[edit2] Well, making the fish immune to the melee damage type does indeed stop them killing each other by bumping into one another but it does also prevent the player using melee weapons to kill them. I did try giving a melee weapon a new damage type but the fish still seemed to be immune to it for some reason. [/edit2]
[edit3] Doh! Guess who forgot melee weapon damagetype goes on the puff, not the weapon? I can indeed make the fish immune to melee and then make melee weapons use a different damage type to get the effect I want. Now I just have to think things through to see if altering the melee weapons like that will have an unwanted side effect elsewhere. Thanks for the help.

-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Enemy with A_SkullAttack not hurt each other - how?
If you want to avoid the pain of that route... Here's a 'Fish' actor with a modified Slam function (plus a property to allow setting the impact damage type).
I also included a 'Fish2' with some other little fish-related code bits I already had lying around that help keep fish in the water without needing blocking lines or actors.
EDIT: To incorporate change discussed below into example code...
I also included a 'Fish2' with some other little fish-related code bits I already had lying around that help keep fish in the water without needing blocking lines or actors.
Code: Select all
version "3.5"
class Fish : LostSoul
{
name ChargeDamageType;
Property ChargeDamageType:chargedamagetype;
Default
{
+DONTHARMCLASS
Fish.ChargeDamageType 'Fish'; // Allow setting the damage type of the impact
}
override bool Slam(Actor victim) // Modified from p_mobj.cpp
{
bSkullFly = false;
vel = (0, 0, 0);
if (!victim) { return false; }
// Compare the class and species if one of the DONTHARM* flags is set
bool isfriendly = (bDontHarmClass && victim.GetClass() == GetClass()) || (bDontHarmSpecies && victim.GetSpecies() == GetSpecies());
if (health > 0)
{
if (!bDormant)
{
if (!isfriendly)
{
int dam = GetMissileDamage(7, 1);
int newdam = victim.DamageMobj (self, self, dam, ChargeDamageType); // Don't default to 'Melee' any more
victim.TraceBleed (newdam > 0 ? newdam : dam, self);
}
if (health > 0)
{
if (SeeState != NULL) SetState (SeeState);
else SetIdle();
}
}
else
{
SetIdle();
tics = -1;
}
}
return false; // stop moving
}
}
class Fish2 : Fish // With some added code to keep fish in the water and not attacking things outside of the water
{
Default
{
MaxStepHeight 0;
}
States
{
Missile:
SKUL C 10 BRIGHT A_FaceTarget;
SKUL D 4 BRIGHT A_FishAttack;
SKUL CD 4 BRIGHT;
Goto Missile+2;
}
override void Tick()
{
if (!globalfreeze && !level.Frozen)
{
if (waterlevel < 3) { vel.z = min(vel.z, -FloatSpeed); } // If you're at or above the water's surface, push the actor back down into the water
if (target && target.waterlevel == 0) { target = null; } // Forget your target if they got out of the water
}
Super.Tick();
}
void A_FishAttack(double skullspeed = DEFSKULLSPEED)
{
if (target == null || target.waterlevel == 0) // Don't attack anything that's out of the water
{
target = null;
tics = 0;
SetIdle();
}
else
{
A_SkullAttack(skullspeed); // Otherwise use the normal skull attack function
}
}
}
Last edited by AFADoomer on Sat Sep 08, 2018 12:33 pm, edited 3 times in total.
-
-
- Posts: 26880
- Joined: Tue Jul 15, 2003 4:58 pm
- Location: Scotland
Re: Enemy with A_SkullAttack not hurt each other - how?
Hah! was in the process of adding the following post. It looks as if you have anticipated much of what I was about to ask. Changing the weapons wasn't much hassle BTW because I already had them all set up with custom puffs but I definitely going to investigate your code. Thank you once again.
Wrote, write, whats a vowel between friends.Enjay was about to wrote:
I may as well ask, just in case it's something hidden that I haven't spotted.
As far as I can tell, changing my melee weapons to use my new unique damage type ( Damagetype "HitMeBabyOneMoreTime" ) has no adverse effect on the game. So I just want to check is there anything important in the game that might explicitly expect a melee weapon to do damage of type Melee?
And while I'm asking questions - back to the fish.
I have restricted myself to using them in areas where it is impossible for them to rise up out the water (they are floating/no gravity enemies). e.g. keeping them inside a completely flooded tunnel by having monster blocking lines at either end of the tunnel. However, it would be nice to be able to put them into ponds and other bodies of water with completely open surfaces. The problem is, they can just fly up and out of the water.
I have tried giving them a waterlevel jump statement in their code that forces them downwards if they start to rise above the surface of deep water. That basically works unless my old friend A_SkullAttack is being used. If the fish is charging using A_SkullAttack they can find it quite easy to charge out of a pool of water. They move so fast that no matter how frequently I put the A_JumpIf statements in, they can start a charge and be out of the water before the next waterlevel check. At that point, they just lie helpless on the shore of the water (kind of appropriate I suppose) as the waterlevel check is now trying to force them below the water even though they are now lying on the land.
So, is there any way of forcing an enemy to not be able to rise above the surface of the water? Perhaps a mapping way - effectively a vertical version of a monster blocking line (like a 3D floor or some actor that can be placed above the water surface that the fish cant get through but the player and projectiles can)? Or some better way of coding it that I haven't thought of?
-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Enemy with A_SkullAttack not hurt each other - how?
Glad to help!
One thing you might have to tweak - in the code for pushing the enemy back down into the water, using -FloatSpeed instead of -1 in the velocity setting code gets far better results (I pulled the code from an enemy with a FloatSpeed of 1, so hadn't noticed a problem before).
One thing you might have to tweak - in the code for pushing the enemy back down into the water, using -FloatSpeed instead of -1 in the velocity setting code gets far better results (I pulled the code from an enemy with a FloatSpeed of 1, so hadn't noticed a problem before).
-
-
- Posts: 26880
- Joined: Tue Jul 15, 2003 4:58 pm
- Location: Scotland
Re: Enemy with A_SkullAttack not hurt each other - how?
I've given it a quick look and it's much better than what I had managed to do. During its attack charges, it hasn't risen out of the water once. However, it can do so when it;s just doing its normal swimming around.
I'm not very up to speed with ZScript yet, where would I apply your suggested floatspeed change?
Nevermind - I think I got it:
Right? It seems to work.
[edit] and with a bit of further minor tweaking to suit my own needs, it seems to be doing exactly what I want. Once again, thank you very much.
[/edit]
I'm not very up to speed with ZScript yet, where would I apply your suggested floatspeed change?
Nevermind - I think I got it:
Code: Select all
if (waterlevel < 3) { vel.z = min(vel.z, -FloatSpeed); }
[edit] and with a bit of further minor tweaking to suit my own needs, it seems to be doing exactly what I want. Once again, thank you very much.

-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Enemy with A_SkullAttack not hurt each other - how?
Correct. I think there are still some cases where they can be pushed up out of the water by another actor underneath them, but they don't seem to actually escape the water.
-
-
- Posts: 26880
- Joined: Tue Jul 15, 2003 4:58 pm
- Location: Scotland
Re: Enemy with A_SkullAttack not hurt each other - how?
I think that will be a rare enough situation in my setup that I won't have to worry about it and if it does happen, well, so be it. 
For what it's worth, one of my minor tweaks was to make it so the fish won't attack while you are above the water or only ankle deep (instead of only when you are above water). The fish is big enough that it would just look silly in ankle deep water anyway and I also had a pool where the player could stand ankle-deep at the edge but the floor of the pool sloped away to a deeper and the fish couldn't get into the shallow bit due to blocking lines. So he just sat there at the line thrashing away at it trying to get at the player simply because the players ankles were wet.
Also, in many cases the player can't see through the surface of many deep water setups, so having an unseen fish nibbling at you toes wasn't that good. So I've set it so that the player/target must be at least "waistdeep" (waterlevel 2) before the fish tries to swim at them in attack mode. That may not be a universal solution, but it suits my needs.

For what it's worth, one of my minor tweaks was to make it so the fish won't attack while you are above the water or only ankle deep (instead of only when you are above water). The fish is big enough that it would just look silly in ankle deep water anyway and I also had a pool where the player could stand ankle-deep at the edge but the floor of the pool sloped away to a deeper and the fish couldn't get into the shallow bit due to blocking lines. So he just sat there at the line thrashing away at it trying to get at the player simply because the players ankles were wet.
