Bug with mpat in a greet prog
< Newer Topic
:: Older Topic >
Pages:<< prev 1 next >>
#1 Oct 12, 2009 5:17 pm
Apprentice
GroupMembers
Posts60
JoinedJul 25, 2005
When you use an mpat in a mprog's greet, it'll end up firing twice.
Example:
The above will make the NPC fire the say twice. Probably has something to do with the mpat making the NPC leave the room and come back.
Example:
mpedit X add greet 100 ' Hello, $n! mpat 10 look
The above will make the NPC fire the say twice. Probably has something to do with the mpat making the NPC leave the room and come back.
#2 Oct 12, 2009 5:18 pm
Sorcerer
GroupMembers
Posts723
JoinedMar 5, 2005
I was able to reproduce this with BIYG and stock Smaug that SBI has.
#3 Oct 12, 2009 7:10 pm
Geomancer
GroupAdministrators
Posts1,917
JoinedJul 26, 2005
Also in LoP, now interestingly enough if you add more mpats it still only does it twice. So wonder why it limits it to twice yet it will cause it to do it twice.
#4 Oct 12, 2009 7:34 pm
Black Hand
GroupAdministrators
Posts3,685
JoinedJan 1, 2002
That's an odd little bug, wonder why nobody noticed it before.
#5 Oct 12, 2009 8:02 pm
Geomancer
GroupAdministrators
Posts1,917
JoinedJul 26, 2005
Well the problem is that mprog_greet_trigger never takes into consideration that if they leave the room and come back in while its executing there position in the list changes to the end. So it will allow it to fire twice (maybe more under the right circumstances like if it minvoked/transed someone and then did another mpat) Im open for suggestions on best way to go about doing this though lol.
#6 Oct 12, 2009 8:14 pm
Geomancer
GroupAdministrators
Posts1,917
JoinedJul 26, 2005
The best I can guess is that you need to make a list of all the characters in the room at the start and use that list instead of the chars in the room list as it goes since it can change.
#7 Oct 13, 2009 12:00 am
Black Hand
GroupAdministrators
Posts3,685
JoinedJan 1, 2002
Heh. Would figure this is one of those weird list things. They do seem to love to pop up everywhere.
#8 Oct 13, 2009 2:45 am
Off the Edge of the Map
GroupAdministrators
Posts1,200
JoinedMar 21, 2006
The commands at/atobj/mpat/whatever else, should just be modified to not remove the person from the list. I never understood why they were handled that way to begin with.
#9 Oct 13, 2009 4:08 am
Black Hand
GroupAdministrators
Posts3,685
JoinedJan 1, 2002
If that can be done safely without some kind of odd pointer issues coming up, then I don't see why not. Right now it's because they make use of char_from_room() and char_to_room() to do what they do.
#10 Dec 4, 2009 4:10 pm
Apprentice
GroupMembers
Posts86
JoinedAug 25, 2003
Hello, in my opinion we have two problems at same time,
1) xxxx_prog_trigger like GREET_PROG (but probably much other) loop CHAR_DATA in room to check if the prog is present or not. But, if the list of CHAR_DATA in room change for some reason (mpat command is one possibile situation), a mud prog could re-fire more than one time.
2) MPAT (and other commands) can invoke a char_from_room / char_to_room so the list of CHAR_DATA in room change [up at point (1)].
...so I suppose we can change xxxx_prog_trigger loop system with something like a queded list... otherwise we need to change command like MPAT to prevent the change list of CHAR_DATA in a room.
I think, another way, could be simply do something like this via building:
>greet_prog 100
if wasinroom($i) == 214
break
endif
' Hello, $n!
mpat 214 mpechoall TRIG TEST
I don't know if this really "FIX" all cases.
Bye
mat
1) xxxx_prog_trigger like GREET_PROG (but probably much other) loop CHAR_DATA in room to check if the prog is present or not. But, if the list of CHAR_DATA in room change for some reason (mpat command is one possibile situation), a mud prog could re-fire more than one time.
2) MPAT (and other commands) can invoke a char_from_room / char_to_room so the list of CHAR_DATA in room change [up at point (1)].
...so I suppose we can change xxxx_prog_trigger loop system with something like a queded list... otherwise we need to change command like MPAT to prevent the change list of CHAR_DATA in a room.
I think, another way, could be simply do something like this via building:
>greet_prog 100
if wasinroom($i) == 214
break
endif
' Hello, $n!
mpat 214 mpechoall TRIG TEST
I don't know if this really "FIX" all cases.
Bye
mat
#11 Jan 31, 2010 10:35 am
Geomancer
GroupAdministrators
Posts1,917
JoinedJul 26, 2005
So did anyone every do anything on this?
#12 Jan 31, 2010 11:24 am
Off the Edge of the Map
GroupAdministrators
Posts1,200
JoinedMar 21, 2006
I haven't. I got distracted with Mass Effect 2, Dragon Age: Origins, Halo 3: ODST, and Fallout 3. It was a good Holiday season for games. >.> lol
#13 Jan 31, 2010 11:42 am
Geomancer
GroupAdministrators
Posts1,917
JoinedJul 26, 2005
Sounds like fun, I had went through once and fixed it in mine then didn't like how i fixed it so took it out. Plus was waiting to see if anyone else had a better idea. Earlier today I got to wondering if I had took it out or not so got to looking and noticed I had so got to wondering if anyone had come up with something when I seen no one has I did another temporary list inside the function itself. It is always a pain though when dealing with programs since they can cause things to die, move, etc.... When I do the next release of LoP (eventually going to be done sooner or later) It will have the fix in it unless someone comes up with something better etc... I'm going to go ahead and put in what I have here for people to look at and decide if there is a better way etc... Who knows maybe it will help us all get it solved or at least get some people working on coming up with something better or something.
Here it is:
So lets see what we can all come up with on this lol.
Here it is:
void mprog_greet_trigger( CHAR_DATA *ch ) { /* We need a temporary list of the chars to keep it only firing ones it needs to, probably needed in other locations too */ typedef struct tmp_char TMP_CHAR; struct tmp_char { TMP_CHAR *next, *prev; CHAR_DATA *who; /* Who are we checking now? */ }; TMP_CHAR *tmp_first = NULL, *tmp_last = NULL, *tmpmob, *tmpmob_next; CHAR_DATA *vmob, *vmob_next; int rvnum; if( !ch || !ch->in_room ) return; rvnum = ch->in_room->vnum; /* Ok link them in the tmp list */ for( vmob = ch->in_room->first_person; vmob; vmob = vmob_next ) { vmob_next = vmob->next_in_room; if( !vmob || !vmob->in_room || vmob->in_room->vnum != rvnum || !is_npc( vmob ) || !can_see( vmob, ch ) || vmob->fighting || !is_awake( vmob ) || char_died( vmob ) || char_died( ch ) || ( is_npc( ch ) && ch->pIndexData == vmob->pIndexData ) ) continue; CREATE( tmpmob, TMP_CHAR, 1 ); tmpmob->who = vmob; LINK( tmpmob, tmp_first, tmp_last, next, prev ); } /* Ok now toss through the tmp list and remove them as we go */ for( tmpmob = tmp_first; tmpmob; tmpmob = tmpmob_next ) { tmpmob_next = tmpmob->next; vmob = tmpmob->who; if( !vmob || !vmob->in_room || vmob->in_room->vnum != rvnum || !is_npc( vmob ) || !can_see( vmob, ch ) || vmob->fighting || !is_awake( vmob ) || char_died( vmob ) || char_died( ch ) || ( is_npc( ch ) && ch->pIndexData == vmob->pIndexData ) ) { UNLINK( tmpmob, tmp_first, tmp_last, next, prev ); tmpmob->who = NULL; DISPOSE( tmpmob ); continue; } if( HAS_PROG( vmob->pIndexData, GREET_PROG ) ) mprog_percent_check( vmob, ch, NULL, NULL, GREET_PROG ); else if( HAS_PROG( vmob->pIndexData, ALL_GREET_PROG ) ) mprog_percent_check( vmob, ch, NULL, NULL, ALL_GREET_PROG ); UNLINK( tmpmob, tmp_first, tmp_last, next, prev ); tmpmob->who = NULL; DISPOSE( tmpmob ); } /* Just incase for some reason something is still in need to remove it now */ for( tmpmob = tmp_first; tmpmob; tmpmob = tmpmob_next ) { tmpmob_next = tmpmob->next; UNLINK( tmpmob, tmp_first, tmp_last, next, prev ); tmpmob->who = NULL; DISPOSE( tmpmob ); } }
So lets see what we can all come up with on this lol.
Pages:<< prev 1 next >>