I have a line with a switch texture and a repeatable, player-activatible special. When I flip the switch, a sound plays, the line texture changes and the special fires.
After a few seconds, the sound plays again and the texture changes back. I don't want this to happen; is there any way to set it up so the texture only changes when I activate the line, and doesn't change back after a few seconds?
Right now I'm changing the texture and playing the sound in ACS, but I'd like to get it working with animdefs.
switch OFF_TEXTURE on pic ON_TEXTURE tics 0 off pic ON_TEXTURE tics 0
That'll get the switch to stay flipped, but when you activate it again, it the texture won't change back, and the sound plays when the automatic flipping back happens. I tried adding another line, defining the same animation going in the other direction (switch ON_TEXTURE...), but it just seems to override the first line. Messing with tic count doesn't seem helpful either.
I'm sure it's something simple... how can I get the switch to stay put when I flip it?
EDIT: Discovered I could make it non-repeatable, and then set the line special up again in an ACS script. This isn't ideal, because now the line needs to have a tag for SetLineSpecial (as far as I know there's no way to get SetLineSpecial to affect the activating line, like ClearLineSpecial... tried passing 0 as first argument, didn't work).
Controlling repeatable switch state?
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.
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.
Re: Controlling repeatable switch state?
A hacky way to do this is to set your ACS to replicate the switch on/off action, NOT by using the switch special, but by using texture change & sound effect specials. In this way, you'll have absolute control of the texture changes, and can set the "end" texture any way you want. As this is a repeatable action, you'll also need to set the logic up so that the texture change does not occur beyond the first time the switch is used.
Give your switch linedef a LINE_ID, set it to repeatable, yada yada. Then, use the suggested scripting:
If you have more than one switch for which you wish to do the same sequence, simply increment the integer value (e,g, "switchon2"), give your new switch a new LINE_ID, copy & paste & change the relevant parts of the scripts above.
Give your switch linedef a LINE_ID, set it to repeatable, yada yada. Then, use the suggested scripting:
Code: Select all
#include "zcommon.acs"
script 1 OPEN
{
SetLineSpecial(LINE_ID,80,15,0,0,0,0); //Light switch:Script 15
}
int switchon1;
script 15 (void)
{
If (!switchon1)
{
Setlinetexture (LINE_ID, SIDE_FRONT, TEXTURE_MIDDLE, "TEXTURE NAME FOR ON POSITION");
ActivatorSound("NAME OF SWITCH SOUND",127);
switchon = 1;
delay(const:35*XX); //XX is the number of seconds you want between texture changes
Setlinetexture (LINE_ID, SIDE_FRONT, TEXTURE_MIDDLE, "TEXTURE NAME FOR OFF POSITION");
[Perform your desired action, e.g., lowering a lift];
}
else
{ If (switchon1) //This line is optional and is included mainly for clarity. If you remove it you'll need to remove the appropriate number of curly brackets.
{ ActivatorSound("NAME OF SWITCH SOUND",127);
[Perform your desired action, e.g., lowering a lift];
}
}
}
Re: Controlling repeatable switch state?
Hmm, thanks, that looks a lot like one of my earlier attempts (except I think I went with SectorSound).
Hard-coding all this stuff seems inflexible, but some of that can be mitigated with script args...
What I've done for now is stick a bunch of data in custom UDMF fields, on the line with the switch. So the UDMF looks like this:
Then I wrote a little script that'll iterate over UDMF user fields named like foo_1, foo_2, foo_3, calling a named script and passing each value to it (we don't have first-class functions, right?).
Then the rest of my code looks like this:
The huge glaring problem here is "lights on" has some warmup time -- a flicker and then a fade -- so "lights off" needs to terminate it. That's enough to pretty much kill any chance of reuse (I can't have "lights off" kill the "lights on" happening in another room).
I guess I'm mainly trying to figure out how to achieve some level of encapsulation/reuse at this point (although it would still be great if there were some kind of "switches stay put" line flag).
Hard-coding all this stuff seems inflexible, but some of that can be mitigated with script args...
What I've done for now is stick a bunch of data in custom UDMF fields, on the line with the switch. So the UDMF looks like this:
Code: Select all
linedef {
v1=...; v2=...; sidefront=...;
blocking=true; playeruse=true;
special=80; // ACS_Execute
id=1;
arg0str="lights on";
user_light_things=2;
user_dark_things=1;
user_light_sector_1=1;
user_light_sector_2=3;
user_volumetric_sector_1=3;
}
Code: Select all
function void IterateLineUDMFInt(int tag, str field, str scriptname, int a, int b) {
int i = 0;
int sid = GetLineUDMFInt(tag, strparam(s:"user_", s:field, s:"_", i:++i));
while (sid > 0) {
ACS_NamedExecuteAlways(scriptname, 0, sid, a, b);
sid = GetLineUDMFInt(tag, strparam(s:"user_", s:field, s:"_", i:++i));
}
}
Code: Select all
script "flicker" (int sid) {
Light_Stop(sid);
Light_Strobe(sid, 96, 80, 1, 3);
}
script "fade" (int sid) {
Light_Stop(sid);
Light_ChangeToValue(sid, 96);
Light_Fade(sid, 128, 30);
}
script "haze" (int sid, int value) {
Sector_SetFade(sid, value, value, value);
}
script "dim" (int sid) {
Light_Stop(sid);
Light_ChangeToValue(sid, 64);
}
script "lights on" (void) {
ACS_NamedTerminate("lights off", 0);
SetLineSpecial(1, ACS_NamedExecute, "lights off");
Thing_Activate(GetLineUDMFInt(1, "user_light_things"));
Thing_Deactivate(GetLineUDMFInt(1, "user_dark_things"));
IterateLineUDMFInt(1, "light_sector", "flicker", 0, 0);
delay(30);
IterateLineUDMFInt(1, "light_sector", "fade", 0, 0);
IterateLineUDMFInt(1, "volumetric_sector", "haze", 255, 0);
}
script "lights off" (void) {
ACS_NamedTerminate("lights on", 0);
SetLineSpecial(1, ACS_NamedExecute, "lights on");
Thing_Activate(GetLineUDMFInt(1, "user_dark_things"));
Thing_Deactivate(GetLineUDMFInt(1, "user_light_things"));
IterateLineUDMFInt(1, "volumetric_sector", "haze", 0, 0);
IterateLineUDMFInt(1, "light_sector", "dim", 0, 0);
}
I guess I'm mainly trying to figure out how to achieve some level of encapsulation/reuse at this point (although it would still be great if there were some kind of "switches stay put" line flag).