Log in

View Full Version : switches & levers controlling doors


blackdragonsdg
04-29-2011, 04:03 AM
So I got the bright idea to try to make some various lifts function correctly. I thought this would be fairly simple but I was wrong.

I was testing the following in Vergalid Mines

door 41 = lever at zone in
door 40 = main lift
doors 38 & 39 = ropes for main lift

Initially the main lift and the ropes are in a closed state. Both the lift and the ropes are at the bottom of the shaft.

player.pl
my $doorstate = quest::isdooropen(40);

sub EVENT_CLICKDOOR
{
if($doorid == 41 && !$doorstate)
{
quest::forcedooropen(38);
quest::forcedooropen(39);
quest::forcedooropen(40);
}
if($doorid == 41 && $doorstate)
{
quest::forcedoorclose(38);
quest::forcedoorclose(39);
quest::forcedoorclose(40);
}
}


When the lever is triggered both the lift and the ropes go into an open state and rise to the top of the shaft. Triggering the lever a second time should cause the lift and ropes to enter a closed state and lower back to the bottom of the shaft.
The problem is quest::forcedoorclose() doesn't seem to be working. Don't know if I used it wrong or if it is actually broken. Any input would be appreciated.

trevius
04-29-2011, 04:41 AM
First, don't use "my" when defining variables outside of a sub event. Second, if you define your variable outside of the sub like you did for checking door state, it won't update ever again after the script is initially loaded. This means it won't know if the door state has changed. If you use the script below, that will at least resolve those 2 issues:


sub EVENT_CLICKDOOR
{

my $doorstate = quest::isdooropen(40);

if($doorid == 41 && !$doorstate)
{
quest::forcedooropen(38);
quest::forcedooropen(39);
quest::forcedooropen(40);
}
if($doorid == 41 && $doorstate)
{
quest::forcedoorclose(38);
quest::forcedoorclose(39);
quest::forcedoorclose(40);
}
}

blackdragonsdg
04-29-2011, 05:53 PM
Ok I moved the variable declaration. It corrected my bad usage but didn't alter the end result of the script.

blackdragonsdg
05-02-2011, 04:53 AM
Well I figured out how to make the lever, ropes and platform work all at once. There appears to be an error in doors.cpp.

default doors.cpp
void Doors::ForceOpen(Mob *sender)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
md->doorid = door_id;
md->action = OPEN_DOOR;
entity_list.QueueClients(sender,outapp,false);
safe_delete(outapp);

if(!isopen) {
close_timer.Start();
isopen=true;
}
else {
close_timer.Disable();
isopen=false;
}
}

void Doors::ForceClose(Mob *sender)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
md->doorid = door_id;
md->action = OPEN_DOOR;
entity_list.QueueClients(sender,outapp,false);
safe_delete(outapp);

if(!isopen) {
close_timer.Start();
isopen=true;
}
else {
close_timer.Disable();
isopen=false;
}
}


The above sections are identical which is why Doors::ForceClose() doesn't work properly.
Now changing md->action = OPEN_DOOR; to md->action = CLOSE_DOOR; as it is below allows Doors::ForceClose() to work a little better

changed doors.cpp
void Doors::ForceOpen(Mob *sender)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
md->doorid = door_id;
md->action = OPEN_DOOR;
entity_list.QueueClients(sender,outapp,false);
safe_delete(outapp);

if(!isopen) {
close_timer.Start();
isopen=true;
}
else {
close_timer.Disable();
isopen=false;
}
}

void Doors::ForceClose(Mob *sender)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
md->doorid = door_id;
md->action = CLOSE_DOOR;
entity_list.QueueClients(sender,outapp,false);
safe_delete(outapp);

if(!isopen) {
close_timer.Start();
isopen=true;
}
else {
close_timer.Disable();
isopen=false;
}
}


That single change didn't completely fix the problem. I think the isopen() and the associated timers are causing a weird bounce effect when used with opentype 40. I changed the database to use opentype 58 so that a click is required to open and close the lever and then the lift and ropes worked as they should have but obviously the lever is frozen in place.
If anyone can see a better way to fix the odd bounce effect besides changing opentype I am all for it otherwise I will keep looking for a better solution.

trevius
05-02-2011, 06:30 AM
Nice catch. I think the issue may be again with those commands being copies of each other. This section here probably needs to be adjusted for the ForceClose:

if(!isopen) {
close_timer.Start();
isopen=true;
}
else {
close_timer.Disable();
isopen=false;
}

It probably needs to be set something like this (untested):

if(isopen) {
close_timer.Disable();
isopen=false;
}

blackdragonsdg
05-02-2011, 05:20 PM
I tried the suggested change and got mixed results. It will work fine one minute and then it goes back to its random behavior. It seems like it is getting confused.

sorvani
05-02-2011, 11:56 PM
i stuck all the above changes in my build and the Kelethin lifts still do not work every click. Yes I'm making sure they finished traversing up or down before clicking again.

trevius
05-03-2011, 05:27 AM
I think those lifts are a whole different issue all together. Those things have never worked properly, and I don't think they use scripts anyway so it is not relevant to this thread.

Uleat
06-10-2012, 10:39 PM
I'm looking at this in my spare time. I'm sure blackdragon's fix for ForceClose is correct and I will add my inverted door fix as
well..and submit sometime after the next revision. I just need to double-check the logic table to make sure it won't be
buggy the way it's coded atm.

In regards to the mines' lift issue (and other multi-part doors), something similar to his fix for player.pl is probably correct as
well. you would just need to add each door with its corresponding ones to the check (i.e., clickdoor(1)->forceopen(2,3,4),
clickdoor(2)->forceopen(1,3,4), etc...) Lever activated versus direct click would need some attention though. (Is there a
way to add player.pl-type script to a zone's quest directory?)

Door type 40 is a whole other beast. I'm getting click events as late as 10 minutes after I've activated it. Is it possible that
this door type is sending a 'click' event of some type after it resets, and flipping the server door state in a 'bounce' effect?
If it is sending a 'toggle' event, the server code shouldn't be setting a close_timer for this type of door. It should be
waiting for the return event to set the current state of the door. (Still thinking through the possibilities..client LD's might
be a problem and require some attention.)

I'm not packet savvy, but I'd like to know if there are client events being sent during this 'bounce' period.


U

blackdragonsdg
06-10-2012, 11:28 PM
The lifts and such in Vergalid mines behave in an erratic manor and I am sorry to say I never found a good fix for them. I did hold onto some of the work I did before.

All the following applies to the very first lift you encounter in the zone. Assuming the door id's haven't changed this should still work.

player.pl
sub EVENT_CLICKDOOR
{
my $doorstate = quest::isdooropen(38);

if($doorid == 41 && !$doorstate)
{
quest::forcedooropen(38);
quest::forcedooropen(39);
quest::forcedooropen(40);
}
if($doorid == 41 && $doorstate)
{
quest::forcedoorclose(38);
quest::forcedoorclose(39);
quest::forcedoorclose(40);
}
if($doorid == 42 && !$doorstate)
{
quest::forcedooropen(38);
quest::forcedooropen(39);
quest::forcedooropen(40);
}
if($doorid == 42 && $doorstate)
{
quest::forcedoorclose(38);
quest::forcedoorclose(39);
quest::forcedoorclose(40);
}
}

required changes for player.pl to work
update doors set triggerdoor = 0 where doorid = 38 and name = 'OBJ_ELEVPLAT';
update doors set triggerdoor = 0 where doorid = 39 and name = 'OBJ_ELEVROPE';
update doors set triggerdoor = 0, opentype = 58 where doorid = 41 and name = 'OBJ_ELEVSWLEVER';
update doors set triggerdoor = 0, opentype = 58 where doorid = 42 and name = 'OBJ_ELEVSWLEVER';


The above changes should cause the lift, ropes and levers to work with each other.
If I remember correctly it was also possible to control the lifts, ropes and levers without the need for a script which is what I believe the following changes will do.

update doors set triggerdoor = 39 where doorid = 38 and name = 'OBJ_ELEVPLAT';
update doors set triggerdoor = 40 where doorid = 39 and name = 'OBJ_ELEVROPE';
update doors set triggerdoor = 38 where doorid = 41 and name = 'OBJ_ELEVSWLEVER';
update doors set triggerdoor = 0 where doorid = 42 and name = 'OBJ_ELEVSWLEVER';

The suggested change to Doors::ForceClose() is probably correct and it did improve function a bit but I think some of the lifts and such may require additional code support to make them function correctly.

The bounce effect as you put it is the same erratic behavior I saw when messing with the lifts. If that bounce effect can be removed then the rest should be pretty easy to figure out.

Uleat
06-11-2012, 12:31 AM
(This is an afterthought to the 'bounce' effect.)

Since my 'sender->message()' debug code was stricly inside of 'HandleClick', does the fact that I'm getting those messages during
these events indicate that a client-side action is being performed when the 'bounce' occurs?

(And thanks for posting your full code. You already had what I was contemplating!) :)


U

blackdragonsdg
06-11-2012, 12:50 AM
(This is an afterthought to the 'bounce' effect.)
Since my 'sender->message()' debug code was stricly inside of 'HandleClick', does the fact that I'm getting those messages during
these events indicate that a client-side action is being performed when the 'bounce' occurs?


Well I don't have a clue. Maybe someone with more expertise on the subject can answer that question.

Uleat
06-11-2012, 08:19 AM
(I went ahead and assumed that it is, since I'm getting sender-related messages that should only be generated if I click
something, and came up with this.)


I believe the 'bounce' effect is the result of the type 40 door model having an internal 'state_timer' expire without receiving a close
action from the server to indicate proper status. The door itself is then sending interval repeated (spamming) 'ClickDoor'
events, possibly using some of the OP_ClickDoor' unknown00x values, to request a close door action. The number of 'bounces'
that you receieve are probably proportional to lag and server load. (I'm hypothesizing all of this based on my observations.)

(It was Colonel Mustard in the Dining Room with the 'HandleClick' Code..err... Sorry..late night...)


I came to this conclusion by doing the following:

In addition to sending the 'md->action = OPEN_DOOR' during normal checks, I also initiated a new packet and sent a
'md->action = CLOSE_DOOR', during the same 'HandleClick' call, to the client. The bounce effect was negated, but no lever travel
occured. (I'm up to 45 minutes with no call-backs.)


If it were possible to send a close action back to the same client when 'close_timer' expires, this 'bounce' effect could
probably be absolutely negated and still allow proper lever travel.

This should be able to coded into Doors::Process(), but it might take a sender/timer storage array to handle multiple client
actions..or, even better, a general zone-wide broadcast, which I have no knowlegde (yet) of how to do.

I will look into the zone-wide broadcast aspect and see if I can come up with something. I know what to do in Doors::Process(),
I just need figure out how to send the entire zone a 'md->action = CLOSE_DOOR' action.


If I can get all of these fixes working, I'll bump this back to Code Submissions and roll off a diff patch of doors.cpp against the current
revision and see what dev to contact about having them tested and implemented.


I'll have to learn some more about the scripting aspect, but I think your fix for the lift is definitely the way to go. I'm still not sure
about putting it in players.pl since the muli-part doors in the Gyrospires would work the same way (and any custom content), but there
may be no other way around it.


U

Uleat
06-11-2012, 05:44 PM
Ok, I have a working fix for the opentype 40 door. Once I have tested it as much as I can, I'll look at multi-part doors in the
database and see if I can put those into player.pl using your (blackdragon) implementation.


U

blackdragonsdg
06-12-2012, 12:13 AM
The player.pl I posted was for testing on a specific lift in Vergalid. It may not work for any other door or lift. Take a look at the player.pl for gyrospireb in your quests directory...I think that might be a better way to deal with multi part doors.

Uleat
06-12-2012, 12:55 AM
I remembered seeing player.pl somewhere..I had thought it was a plugin, but my bad.

Yeah, I see what they're doing there. I'll muse over the different means and see what comes up (that Gyrospire code is
pretty tight though.) Unless someone finds a problem that I missed during testing, the remaining door issues should lie
between the player.pl and database values.


U

Uleat
06-13-2012, 08:09 AM
bd,
Try my posted 'multiple door fix' with your script to see if that helps. I'll be offline until later tonight, but I'm going
to throw your script in real quick and see how it works (I put in Trev's untested ForceClose fix too.)

I don't see an issue with the 4-part doors now. I was going into Gyro Z..which doesn't have a quest folder yet.
(although they appear to be twin zones.)


U

blackdragonsdg
06-13-2012, 06:40 PM
Well the Vergalid lift I was testing with before no longer bounces in an erratic manner so that is an improvement. My attempts to make the lift, ropes and levers work together with a script yields only 50% success which is not good enough. Gonna keep messing with it as my script or logic is probably off and I am just not seeing it yet. Still gotta try database control as well.

Uleat
06-13-2012, 09:40 PM
(You should try having two or more clients at the lift with the test code enabled, but the type 40 check disabled
in the Process() procedure..you think it has erratic behavior with one client..hah!)


If you're using only the lever actuator, I saw only one problem that required two clicks. I'm pretty sure your script
is right. The problem lies in ForceOpen and ForceClose.

I'm working on those, but I think this is the problem:

ForceOpen - we want to force a door open no matter what. The action for an open door case should be to
restart the timer, not to close the door. This creates dis-syncronous operation between the server and client
(we just sent an open door command to the client..why do we want the server to think it's shut now?)

ForceClose - your catch on the 'open door' action was correct. With that, and Trev's suggested fix, the only thing
that might need to be done is to add a zone 'close' broadcast to ensure a closed door really is closed.

I'm still looking at these, which is why they didn't make my patch. I don't want the changes to interefere with
any working scripts that have already accounted for a broken 'ForceClose.'

I didn't make the changes in the database that you suggested yet, which is probably why I can still click a rope and
have it activate alone.


U

Uleat
06-18-2012, 05:06 AM
I need a dev pow-wow on this one...


Some scripted doors that use ForceOpen (i.e., gyrospireb 4-part doors in ..\quests\gyrospireb\player.pl) are designed
to us it to toggle the door state and not necessarily force it open.

On the other side, I can't help blackdragon with the vergalid mines lift issue without knowing what the actual design of the
function calls are.


My questions are these:

What are the intended purposes of these two functions, and should they be changed even if it affects many scripted
actions? (Every script will need to be reviewed to determine if a ForceClose action is needed.)


U

sorvani
06-19-2012, 01:27 AM
Write a new export with the new functionality. Do not break every script in the SVN.

Uleat
06-19-2012, 02:00 AM
Understood.

trevius
06-19-2012, 02:57 AM
Can always use the existing function and just add an argument to it with a default set to how it currently works.


ForceOpen(leave_open=false)

sorvani
06-19-2012, 05:30 PM
or that :P

Uleat
06-19-2012, 10:32 PM
I'll keep that in mind, thanks!


Sidenote on GFay lifts though...

I'm wanting to test some scripting without hard-coding this since it only affects (currently) one zone.


Is there a default script file that loads/can be loaded when a zone is initiated?

I guess any npcs that I create could eventually be committed to peq, but a zoneload.pl type of file would be less intrusive. I could
have it 'spawn' the npcs and then just have script files ready for them.


Thanks!
U

sorvani
06-20-2012, 10:08 AM
I would suggest that you break down your issues to individual issues and fixes. the whole lift collision thing is something I can not replicate easily, and thus really do not care about. But the levers working the lifts on a single click are a nice little fix.

Uleat
06-20-2012, 02:55 PM
Sorvani, I think I just fully realized what you said last time about not seeing the error...

I misinterpreted that as you hadn't seen the bug before the fix. But, if you're still not seeing..I wonder if I'm the only one (or few) who can.


I thought, at one point, that I may have damaged my processor. (I've spent some serious time calculating primes and had many 10+ hour
sessions.)

I noticed that some of my fp calculations weren't accurate, so I switched from using SQR(n) to n^(1/2) and the error went away.

I know that P4's still used the original Pentium math co-processor, that had the fp error, up through P4 mobile.


If this is a hardware issue, which would explain the odd fp calculation behavior I've been observing, and it doesn't affect the majority
of players, then consider the GFay issue CLOSED. (I have an idea..oh god, there he goes again..on how to fix the the click->no movement
of activator issue, but that is LOW priority atm.)

(If any servers admins are having players complain about this 'missing the lift' bug, I'll accept pm requests to continue working on it and post
anything that I find in the 'custom code' forum. I will judge continuation based on the number of requests that I receive between today
(date of this posting) and the next 60 days.)


U