Can an actor obtain the sector index it is inside?

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!)
Post Reply
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Can an actor obtain the sector index it is inside?

Post by crowbars82 »

Good evening everyone!

I am attempting to find a method to get an actor to retrieve the sector index it is inside, not the sector tag.

For example if I type the console command "currentpos" just after entering Doom 2 MAP02 it shows me the following information:

Code: Select all

Current player position: (1104.000,1984.000,-0.000), angle: 270.000, floorheight: -0.000, sector:7, lightlevel: 144
Sector 7 is the starting sector's sector index, however it's tag is 13 as it is linked to a teleported somewhere else in the map.

Doom 2 MAP02 example image loaded in Slade:
https://image.ibb.co/cMvtio/Untitled.png


A reason for this would be so that an actor can change the behaviour of the sector that it is inside, such as setting sector damage or something without the sector needing a tag, as the map is randomly generated.

Does anyone know if this is possible?

Much thanks!
User avatar
krokots
Posts: 296
Joined: Tue Jan 19, 2010 5:07 pm

Re: Can an actor obtain the sector index it is inside?

Post by krokots »

You can access actor current sector in ZScript. Use

Code: Select all

Sector sec = myActor.CurSector;
Then you get index

Code: Select all

int index = sec.Index();
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by crowbars82 »

Awesome, thanks Krokots! This is absolutely brilliant. I will have a bash at playing around with this when I get home... on-the-fly exploding walls here we come! :lol:
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by crowbars82 »

krokots wrote:You can access actor current sector in ZScript. Use

Code: Select all

Sector sec = myActor.CurSector;
Then you get index

Code: Select all

int index = sec.Index();
Hi Krokots,

I've had a dabble, however I have realised I have no idea what I am doing with this.

I am good at defining DECORATE actors and have many ACS scripts controlling lots of stuff, however I am having difficulty implementing the syntax that you have suggested.

Ideally what I have envisioned is to have these explosion actors generate into my maps, and then if they explode they are then able to alter the sector that they are inside.

I would need to tell the actor to:
  • obtain the sector index that it is inside of (what I am stuck on)
  • then be able to set a unique tag number to the sector (I can do this I think using "UniqueTID();")
  • and then lower the floor value of the sector giving the effect of explosion damage to the map (probably using something like "FloorAndCeiling_LowerRaise")

Here is my random explosion actor so far:

Code: Select all

Actor RandomExplosion 9681
{
	Radius 16
	Height 16
	Scale 0.8
	RenderStyle Translucent
	Alpha 0.8
	+LOOKALLAROUND
	+AMBUSH
	+QUICKTORETALIATE
	States
	{
	Spawn:
		TNT1 A 0
		TNT1 AA 6 A_LookEx    //keeps a loot out for the player passing by
		Loop
	See:
		TNT1 AA 6 A_JumpIfInTargetLOS("DecideToExplodeOrNot", 180, 0, 256)    //if this actor is within 180° of player fov goto state 
		Stop
	DecideToExplodeOrNot:
		TNT1 A 0
		TNT1 A 0 A_Jump(256, "ExplosionDeath", "NoExplosionDeath")    //to explode or not explode, that is the question
		Stop
	ExplosionDeath:
		TNT1 A 0
		TNT1 A 0 A_Quake (2, 35, 128, 512, 0)    //rumble the screen with damage if close
		CRXP ABCDEFGHIJKLMNOP 1 Bright Light("FIRELIGHT") A_SpawnProjectile("CrowSplosion01", random(90.0, 110.0), 0, random(0, 360), 2, random(90, -90), 0)    //chuck out some other projectiles, they work fine
		CRXP QRSTUVWXYZ 1 Bright Light("FIRELIGHT")
		CRXQ ABCDEFGHI 1 Bright Light("FIRELIGHT")
		Stop
	NoExplosionDeath:
		TNT1 A 0
		TNT1 A -1    //no explosion state
		Stop
	}
}
and here is a link to my efforts at making a functional geiger counter for an example of my ACS use: viewtopic.php?f=39&t=59064


As I understand it, we can put ZScript inside the actor itself, but I'm getting a bit confused on the syntax. Please can you point me in the right direction?

Much appreciated!
-crow
User avatar
krokots
Posts: 296
Joined: Tue Jan 19, 2010 5:07 pm

Re: Can an actor obtain the sector index it is inside?

Post by krokots »

I only know about ZScript, not much on Decorate, but I think that for this to work you need to convert this Actor from decorate to ZScript. It is pretty simple.

Code: Select all

Class RandomExplosion : Actor
{
	Default
	{
		Radius 16;
		Height 16;
		Scale 0.8;
		RenderStyle "Translucent";
		Alpha 0.8;
		+LOOKALLAROUND;
		+AMBUSH;
		+QUICKTORETALIATE;
	}
	States
	{
		Spawn:
			TNT1 A 0;
			TNT1 AA 6 A_LookEx;    //keeps a loot out for the player passing by
			Loop;
		See:
			TNT1 AA 6 A_JumpIfInTargetLOS("DecideToExplodeOrNot", 180, 0, 256);    //if this actor is within 180° of player fov goto state
			Stop;
		DecideToExplodeOrNot:
			TNT1 A 0;
			TNT1 A 0 A_Jump(256, "ExplosionDeath", "NoExplosionDeath");    //to explode or not explode, that is the question
			Stop;
		ExplosionDeath:
			TNT1 A 0;
			TNT1 A 0 A_Quake (2, 35, 128, 512, 0);    //rumble the screen with damage if close
			CRXP ABCDEFGHIJKLMNOP 1 Bright Light("FIRELIGHT") A_SpawnProjectile("CrowSplosion01", random(90.0, 110.0), 0, random(0, 360), 2, random(90, -90), 0);    //chuck out some other projectiles, they work fine
			CRXP QRSTUVWXYZ 1 Bright Light("FIRELIGHT");
			CRXQ ABCDEFGHI 1 Bright Light("FIRELIGHT");
			Stop;
		NoExplosionDeath:
			TNT1 A 0;
			TNT1 A -1;   //no explosion state
			Stop;
	}
}
Then you can modify ExplosionDeath state, add something like this:

Code: Select all

		ExplosionDeath:
			TNT1 A 0;
			TNT1 A 0 A_Quake (2, 35, 128, 512, 0);    //rumble the screen with damage if close
			CRXP ABCDEFGHIJKLMNOP 1 Bright Light("FIRELIGHT") A_SpawnProjectile("CrowSplosion01", random(90.0, 110.0), 0, random(0, 360), 2, random(90, -90), 0);    //chuck out some other projectiles, they work fine
			CRXP QRSTUVWXYZ 1 Bright Light("FIRELIGHT");
			CRXQ ABCDEFGHI 1 Bright Light("FIRELIGHT");
			TNT1 A 0 ChangeSector(-32.0);
			Stop;
And add function

Code: Select all

void ChangeSector(double dh)
{
	Sector sec = CurSector;
	SecPlane floor = sec.floorplane;
	floor.ChangeHeight(dh);
}
But I don't know if it works, can't test it right now. You can check all the functions and stuff you can do with sectors in ZScript, in gzdoom.pk3, look for mapdata.txt inf ZScript folder.

BTW I remember that ZSCript classes don't show up on DoomBuilder properly, you needed to do something for that, but I can't remember what it was :roll:
Also you must create ZSCRIPT lump in your mod file and include your file with this new class.
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by crowbars82 »

krokots wrote:You can check all the functions and stuff you can do with sectors in ZScript, in gzdoom.pk3, look for mapdata.txt inf ZScript folder.
Dude, we did it! I had to make some changes, but after you suggested looking into to gzdoom.pk3, an entire new world of scripting was open before me!

I changed the actor to use inheritance:

Code: Select all

Actor RandomExplosion : RandomExplosionBase 9681
and within the ZSCRIPT.TXT I have:

Code: Select all

Class RandomExplosionBase : Actor
{
	void ChangeSector(double dh)
	{
		Sector sec = CurSector;
		double newfloor = sec.floorplane.D + 8;
		sec.MoveFloor(1.0, newfloor, 0, 1, false);
		TextureId textlight = TexMan.CheckForTexture ("CRTEKC06", TexMan.Type_Any);
		sec.SetTexture(0, textlight);
	}
}
Took me all evening to work this out, but it works! The Actor "RandomExplosion" inherits the Class "RandomExplosionBase" because I couldn't use a SpawnID (which I need) as "Game, DoomEdNum, SpawnID and ConversationID cannot be used in ZScript. Use MAPINFO for these instead." Then I couldn't get the SpawnNums to work within the MAPINFO file, but eventually worked this method out.

The code you suggested did do something, however it only lowered the walls of the sector (I found this out by making it go up instead of down), so after some Googling I found JPL's post where he dabbles with turning the original levels upside-down and I found various syntaxes in his zscript that helped determine how to do the rest.

Thanks again for this, I now have much more dangerous generated maps for my project! :twisted:

Link to images of result!
User avatar
krokots
Posts: 296
Joined: Tue Jan 19, 2010 5:07 pm

Re: Can an actor obtain the sector index it is inside?

Post by krokots »

Neat! I didn't know what that "D" was, so it is current floor plane height? And yes, you can do really cool stuff with ZScript. Changing textures, heights, using line specials from script, etc, enjoy :D

BTW you don't need that "dh" now if you just add 8 to that "D" thing, or you can change 8 to dh, and pass 8 as a parameter in the function, and change this for other actors, so they will have various effects without having to add new functions.
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by crowbars82 »

I too don't know why the ".D" does the thing we want either. I've been Googling and Googling but I can't seem to find any decent reference listing or some kind of "ZScript for absolute beginners but with tutorials on ALL the possible parameters".

The best I've been doing so far is to extract all of GZDoom.PK3 into a folder, then use Notepad++ to search all files for bits of code I've found online and get a list such as this:

Code: Select all

Search "cursector" (47 hits in 17 files)
  C:\EXTRACTED GZDOOM PK3\zscript\actor.txt (2 hits)
	Line 8: 	native Sector		cursector;
	Line 104: 	native Sector CurSector;
  C:\EXTRACTED GZDOOM PK3\zscript\doom\bossbrain.txt (1 hit)
	Line 388: 				newmobj.LastHeard = newmobj.CurSector.SoundTarget;
  C:\EXTRACTED GZDOOM PK3\zscript\heretic\weaponskullrod.txt (1 hit)
	Line 338: 		double newz = mo.CurSector.NextHighestCeilingAt(mo.pos.x, mo.pos.y, mo.pos.z, mo.pos.z, FFCF_NOPORTALS) - mo.height;
  C:\EXTRACTED GZDOOM PK3\zscript\hexen\blastradius.txt (2 hits)
	Line 146: 			if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo))
	Line 146: 			if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo))
  C:\EXTRACTED GZDOOM PK3\zscript\hexen\flies.txt (1 hit)
	Line 89: 		Actor other = FindCorpse(CurSector, 5);
  C:\EXTRACTED GZDOOM PK3\zscript\hexen\spike.txt (2 hits)
	Line 189: 				if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
	Line 189: 				if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
  C:\EXTRACTED GZDOOM PK3\zscript\shared\dynlights.txt (2 hits)
	Line 380: 		if (CurSector) AddZ(-CurSector.floorplane.ZatPoint(pos.XY), false); // z is absolute for Vavoom lights
	Line 380: 		if (CurSector) AddZ(-CurSector.floorplane.ZatPoint(pos.XY), false); // z is absolute for Vavoom lights
  C:\EXTRACTED GZDOOM PK3\zscript\shared\sectoraction.txt (16 hits)
	Line 30: 		if (CurSector != null)
	Line 32: 			// Remove ourself from self CurSector's list of actions
	Line 33: 			if (CurSector.SecActTarget == self)
	Line 35: 				CurSector.SecActTarget = SectorAction(tracer);
	Line 39: 				Actor probe = CurSector.SecActTarget;
	Line 60: 		// Add ourself to self CurSector's list of actions
	Line 61: 		tracer = CurSector.SecActTarget;
	Line 62: 		CurSector.SecActTarget = self;
	Line 93: // Triggered when entering CurSector -------------------------------------------
	Line 103: // Triggered when leaving CurSector --------------------------------------------
	Line 113: // Triggered when hitting CurSector's floor ------------------------------------
	Line 123: // Triggered when hitting CurSector's ceiling ----------------------------------
	Line 133: // Triggered when using inside CurSector ---------------------------------------
	Line 143: // Triggered when using a CurSector's wall -------------------------------------
	Line 231: 			if (playeringame[i] && players[i].mo && players[i].mo.CurSector == self.CurSector)
	Line 231: 			if (playeringame[i] && players[i].mo && players[i].mo.CurSector == self.CurSector)
  C:\EXTRACTED GZDOOM PK3\zscript\shared\setcolor.txt (2 hits)
	Line 14: 		CurSector.SetColor(color(args[0], args[1], args[2]), args[3]);
	Line 34: 		CurSector.SetFade(color(args[0], args[1], args[2]));
  C:\EXTRACTED GZDOOM PK3\zscript\shared\sharedmisc.txt (1 hit)
	Line 222: 		CurSector.Flags |= args[0];
  C:\EXTRACTED GZDOOM PK3\zscript\shared\skies.txt (9 hits)
	Line 57: 			level.sectorPortals[0].mDestination = CurSector;
	Line 118: 			A_Log(String.Format("Can't find SkyViewpoint %d for sector %d\n", args[0], CurSector.Index()));
	Line 126: 				if (CurSector.GetPortalType(sector.ceiling) == SectorPortal.TYPE_SKYVIEWPOINT)
	Line 127: 					CurSector.Portals[sector.ceiling] = boxindex;
	Line 131: 				if (CurSector.GetPortalType(sector.floor) == SectorPortal.TYPE_SKYVIEWPOINT)
	Line 132: 					CurSector.Portals[sector.floor] = boxindex;
	Line 179: 		CurSector.Flags |= Sector.SECF_SILENT;
	Line 184: 		if (CurSector != null)
	Line 186: 			CurSector.Flags &= ~Sector.SECF_SILENT;
  C:\EXTRACTED GZDOOM PK3\zscript\shared\soundenvironment.txt (1 hit)
	Line 23: 		CurSector.SetEnvironmentID((args[0]<<8) | (args[1]));
  C:\EXTRACTED GZDOOM PK3\zscript\shared\waterzone.txt (1 hit)
	Line 14: 		CurSector.MoreFlags |= Sector.SECMF_UNDERWATER;
  C:\EXTRACTED GZDOOM PK3\zscript\strife\oracle.txt (1 hit)
	Line 44: 			spectre.CurSector.SoundTarget = spectre.LastHeard = self.LastHeard;
  C:\EXTRACTED GZDOOM PK3\zscript\strife\strifefunctions.txt (3 hits)
	Line 44: 		CurSector.SoundTarget = null;
	Line 45: 		for (Actor mo = CurSector.thinglist; mo != null; mo = mo.snext)
	Line 152: 		CurSector.RemoveForceField();
  C:\EXTRACTED GZDOOM PK3\zscript\strife\strifeitems.txt (1 hit)
	Line 620: 			spectre.CurSector.SoundTarget = spectre.LastHeard = toucher;
  C:\EXTRACTED GZDOOM PK3\zscript\strife\thingstoblowup.txt (1 hit)
	Line 211: 		sector sec = CurSector;
..and then see how that code is being used and try to work it out from there based on that. Problem solving can be fun and "argh" at the same time!

None the less I will battle onwards! Thanks again for your insight, I'm sure that I will come up with other bizarre ways to use ZScript now! :)
User avatar
KeksDose
 
 
Posts: 596
Joined: Thu Jul 05, 2007 6:13 pm
Location: my laboratory
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by KeksDose »

About d: It appears gzd defines floors and ceilings using the plane equation ax + by + cz = d, so a field like height would be redundant. (a b c) is the plane's normal, but it doesn't have to be unit length. gzd should store them in unit length, though, since planes don't change their orientation.

d is a measure of distance from (0 0 0) to the plane. In your special case, the planes don't have a slope, so you can assume the normal will be (0 0 1) or (0 0 -1). The equation then simplifies to +-z = d, and there's your measure of floor and ceiling height.

And more more generally, (a b c) is orthogonal to the plane, so the distance vector from (0 0 0) to the plane is a multiple of that. If you set (x y z) = L * (a b c), then the above equation yields L * (a^2 + b^2 + c^2) = d. If (a b c) were unit length, then L = d, the signed distance as said.
User avatar
Nash
 
 
Posts: 17506
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by Nash »

You could just use ZatPoint to simplify getting the Z of a floor/ceiling plane, given an X & Y coordinate. It calculates everything for you, taking slope into account.

Code: Select all

double newfloor = sec.floorplane.ZatPoint(Pos.XY) + 8;
 
User avatar
crowbars82
Posts: 40
Joined: Sun Nov 05, 2017 6:22 pm
Contact:

Re: Can an actor obtain the sector index it is inside?

Post by crowbars82 »

This is all super-massively helpful, thanks guys! I will have a go at tinkering with various things methinks :)
User avatar
Gutawer
Posts: 469
Joined: Sat Apr 16, 2016 6:01 am
Preferred Pronouns: She/Her

Re: Can an actor obtain the sector index it is inside?

Post by Gutawer »

KeksDose wrote:About d: It appears gzd defines floors and ceilings using the plane equation ax + by + cz = d, so a field like height would be redundant. (a b c) is the plane's normal, but it doesn't have to be unit length. gzd should store them in unit length, though, since planes don't change their orientation.
Very small correction, it's ax + by + cz + d = 0 with GZDoom, this is noted in a comment in secplane_t:

Code: Select all

struct secplane_t
{
	// the plane is defined as a*x + b*y + c*z + d = 0
	// ic is 1/c, for faster Z calculations
Post Reply

Return to “Scripting”