Page 1 of 1

Making a weapon/monster with an outdoors only attack

Posted: Mon Nov 08, 2021 9:27 am
by mrspeaker
What it says in the title. I want to make a monster with an attack that calls down lightning for example, but can only be used if the target is outdoors. Is that possible?
There are ways to check if the target is underwater by checking waterlevel, but is there a way to check if a monster is outdoors or indoors, as in, under a ceiling or exposed to the sky?

Re: Making a weapon/monster that with an outdoors only attac

Posted: Mon Nov 08, 2021 9:37 am
by nova++
Are you willing to use ZScript? You can grab the target's current sector and check its ceiling texture, I believe. I'm not in a good spot to try it myself right now (I actually need to do something similar for my project at some point), but I am fairly sure it's possible.

Re: Making a weapon/monster that with an outdoors only attac

Posted: Mon Nov 08, 2021 10:26 am
by Virathas
Just a quick note, if Zandronum compatibilty is required ACS can be used for that (I did that in my project, both an air strike and thunderstorm). The base gist is the same, to check an actor's ceiling texture.

Re: Making a weapon/monster that with an outdoors only attac

Posted: Tue Nov 09, 2021 12:36 pm
by mrspeaker
nova++ wrote:Are you willing to use ZScript? You can grab the target's current sector and check its ceiling texture, I believe. I'm not in a good spot to try it myself right now (I actually need to do something similar for my project at some point), but I am fairly sure it's possible.
Unfortunately I only know how to use decorate. I have zero scripting/coding experience.
Virathas wrote:Just a quick note, if Zandronum compatibilty is required ACS can be used for that (I did that in my project, both an air strike and thunderstorm). The base gist is the same, to check an actor's ceiling texture.
How did you manage to do it, if you don't mind me asking? I'm very interested especially in the airstrike since my idea was for a monster that could call an artillery strike on bosses.

Re: Making a weapon/monster with an outdoors only attack

Posted: Fri Nov 12, 2021 2:13 am
by Virathas
Well, copying straight from my mod the scripts:
DECORATE

Code: Select all

Actor AirStrikeBeacon
{
Radius 16
Height 16
Mass 10
Speed 4
BounceFactor 0.0
-SHOOTABLE
-CANBLAST
States
{
Spawn:
	MINE A 0 A_Gravity
	BEAC ABABA 35
	BEAC A 0 ACS_NamedExecuteAlways("AirStrikeTest",0)
	goto idle
Idle:
	BEAC AB 10
	Loop
Death:
	BEAC A 1 A_FadeOut(0.015)
	Loop
}
}
ACS

Code: Select all

script "AirStrikeTest" (void)
{
	int CenterTID = ActivatorTID();
	int MissileID = UniqueTID();		
	
int timepast = 0;
int failcount = 0	;

	while ( timepast < 400 )
	{
		if  (failcount >= 100)
		{
			failcount = 0;
			delay(5);
			timepast++;
		}

     int x = GetActorX(CenterTID) + random(-768.0, 768.0);
     int y = GetActorY(CenterTID) + random(-768.0, 768.0);
     int z = GetActorCeilingZ(CenterTID);
	if (!(Spawn("Airstrikemissile", x, y, z, MissileID)))
	{
		failcount++;
		continue;
	}
	else
	{
		if ((CheckActorCeilingTexture(MissileID,"F_SKY1")) || (CheckActorCeilingTexture(MissileID,"F_SKY2")) || (CheckActorCeilingTexture(MissileID,"F_SKY3")) || (CheckActorCeilingTexture(MissileID,"F_SKY4")) || (CheckActorCeilingTexture(MissileID,"SKY1")) || (CheckActorCeilingTexture(MissileID,"SKY2")) || (CheckActorCeilingTexture(MissileID,"SKY3")) || (CheckActorCeilingTexture(MissileID,"SKY2A")) || (CheckActorCeilingTexture(MissileID,"SKYFOG")) || (CheckActorCeilingTexture(MissileID,"SKYFOG2")) || (CheckActorCeilingTexture(MissileID,"SKY")) || (CheckActorCeilingTexture(MissileID,"F_SKY")))
		{
			if 	((GetActorCeilingZ (MissileID) - GetActorFloorZ (MissileID)) < 16)
			{
				Thing_Remove(MissileID);
				failcount++;
				Continue;
			}
			else
			{
				SetActorPosition(MissileID, x,y,GetActorCeilingZ(MissileID) - 4.0, 0);
			}
		}
		else
		{
			Thing_Remove(MissileID);
			failcount++;
			Continue;
		}
		Thing_ChangeTID(MissileID, 0);
		delay(5);
		timepast++;
	}
	}
		Thing_Remove(CenterTID);
}
What it does in short: A beacon after a short while summons a few hundred missiles from sky in a significant radius.

What it does in long: The script is called from the decorate actor once, and only once.
The script first sets a TID to the actor, to be able to reference it easily.
The timepast variable is used to count how many missiles have been already spawned
The failcount is a safety variable, in case there are no valid places to spawn a missile, it will eventually terminate the script.
"if (!(Spawn("Airstrikemissile", x, y, z, MissileID)))" <- this both spawns a missile as well as checks for success. It adds a TID to the missile to reference it later.
The latter large "if" block is the thing you want the most - this tests if the location where missile spawns has the sky. If not, the missile is removed.

In your case the "beacon" should be spawned at the player's location, and then a similar script should be ran.

Hope it isn't too confusing :P

Re: Making a weapon/monster with an outdoors only attack

Posted: Tue Nov 16, 2021 6:12 pm
by Matt
If you want to avoid both ACS and Zscript, one more option is to shoot an invisible, zero-damage, no-blood ripper projectile straight up really fast. If it explodes, it's hit a ceiling and should give the shooter an item marking the shooter as being under a ceiling; if it hits sky, it just disappears without doing anything further.

The weapon can then be set to, upon any shot:
1. Delete the item from the user's inventory
2. Shoot the invisible projectile
3. Wait a moment
4. Jump to an abort state if the item is found


That said, if you're willing to convert the weapon code to ZScript (basically just add a bunch of semicolons, add a version number, change a few formatting things for damage and put the properties/flags in a "default" block), you can basically skip to step 4 with something like

Code: Select all

MJOG A 0 A_JumpIf(CurSector.GetTexture(CurSector.ceiling)==SkyFlatNum,"summonlightning");
goto fail;

Re: Making a weapon/monster with an outdoors only attack

Posted: Wed Apr 06, 2022 1:46 pm
by mrspeaker
Thanks for the help! Your posts gave me an idea and I think I found an easy way to do this.

Monster shoots an invisible non-damaging missile on another valid monster (A_CheckLOF is called before to ensure he doesn't shoot something else). Upon hitting the target, it spawns another missile that has the +SKYEXPLODE flag, is also invisible and non-damaning, ripping, goes straight up and has both a Death and a Death.Sky states. So if it hits a ceiling, nothing happens and if it hits the sky, it works normally. What do you think? Will it work?

EDIT: It works. Now I just need to fine-tune it and I'll have a spotter marine that calls in artillery strikes on bosses.