Log in

View Full Version : Limiting players in a room


chrsschb
05-26-2009, 08:12 PM
I want to set up a boss encounter within a dungeon that will only be attemptable by a set number of people/bots. If the boss is aggroed and the number of players/bots is above this limit I want to have the boss kick these people outside of the room.

Is this possible? Something similar to what Nagafen/Vox do, but for quantity of players, instead of level of players.

Here's the quest for reference:

sub EVENT_SPAWN {
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 100, $x + 100, $y - 100, $y + 100);
}

sub EVENT_ENTER {
if (($ulevel >= 53) && ($status == 0)) {
quest::echo("I will not fight you, but I will banish you!");
quest::movepc(30,-7024,2020,-60.7);
}
}

sub EVENT_AGGRO {
quest::settimer("getloc",15); #mob will get position every 15 seconds if pulled away from spawn point
}

sub EVENT_TIMER {
quest::clear_proximity();
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 100, $x + 100, $y - 100, $y + 100);
}

sub EVENT_DEATH {
quest::stoptimer("getloc");
quest::clear_proximity();
}

trevius
05-26-2009, 08:58 PM
Depending on exactly how you wanted the event to play out and how to deal with resetting the event and such, it probably wouldn't be to hard to do what you are wanting.



sub EVENT_SPAWN {
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 100, $x + 100, $y - 100, $y + 100);

$enter_count = 0; #Keep track of how many characters enter the proximity.
}

sub EVENT_ENTER {

$enter_count = $enter_count + 1;

if ($enter_count >= 6) {
quest::echo("No more than 6 at a time may do this encounter.");
quest::movepc(152, 0, 0, -30);
}
}

If you wanted to get more advanced, you could use sub EVENT_COMBAT to handle resetting the enter count variable if people fail the event so it could be restarted. You could also use temporary quest globals to assign to people as they enter and do a check for that temporary qglobal before upping the enter count again. This way, the first 6 chars to get inside the proximity can then leave and come back and still get in, but it won't allow others to come in.

I don't know anything at all about bots, so I don't know if they would be counted properly, or if proximities even take them into account at all.

ChaosSlayerZ
05-26-2009, 09:24 PM
I have a related quetsion.

Trev - would it be posible to write a perl script which woudl identify a player by some sort of parameter (level above X or class X etc) and somehow mark that player UNABLE to damage the mob?

BTW I was thinking, basing of Nagafen script can we try to emulate Trivial Encounter restriction like on FV server has or eq2:

Could we use perhaps use EVENT_AGGRO to determien player level and ONLY banish him if he actualy agroes the mob (gets on it hate list) rather than just enter its proximity?

trevius
05-26-2009, 10:24 PM
I have tried using EVENT_AGGRO for that, but it didn't work. I think it only runs the check when the mob changes aggro, not for anyone who gets on the hate list. Though, it would be nice to have that as an event type (among the list of quite a few other event types I wouldn't mind seeing).

The only way I can think of to keep particular levels or classes or whatever from damaging a mob would be to cast DA on them repeatedly for the length of the fight. That would be possible, but would require using the client search script code that a few scripts in the custom quest section use.

chrsschb
05-26-2009, 10:58 PM
Thanks for the reply Trev. Think this would work?

sub EVENT_SPAWN {
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 100, $x + 100, $y - 100, $y + 100);

$enter_count = 0; #Keep track of how many characters enter the proximity.
}

sub EVENT_ENTER {

$enter_count = $enter_count + 1;

if ($enter_count >= 6) {
quest::echo("No more than 6 at a time may do this encounter.");
quest::movepc(152, 0, 0, -30);
}

sub EVENT_EXIT (

$enter_count = $enter_count - 1;

}

sub EVENT_COMBAT (

if ($combat_state == 0) {
$enter_count = 0;
}
}

trevius
05-26-2009, 11:10 PM
That would work for most cases, but if I was writing something that I wanted to be positive people could not exploit in any way, it would probably take a considerable amount more coding to handle.

My main concern about that is 6 people could enter the proximity and then have 1 person engage and die, and then they would be able to bring 6 more players in. When making special encounters like that, you have to try to think of all possible angles people could use to exploit it. When you get a lot of people trying the same event over time, it is a sure thing that they will eventually find the loopholes if there are any. Trust me, I have had my fair share of them on Storm Haven lol.

chrsschb
05-26-2009, 11:21 PM
That would work for most cases, but if I was writing something that I wanted to be positive people could not exploit in any way, it would probably take a considerable amount more coding to handle.

My main concern about that is 6 people could enter the proximity and then have 1 person engage and die, and then they would be able to bring 6 more players in. When making special encounters like that, you have to try to think of all possible angles people could use to exploit it. When you get a lot of people trying the same event over time, it is a sure thing that they will eventually find the loopholes if there are any. Trust me, I have had my fair share of them on Storm Haven lol.

Hmm, nothing that can be written without a ton of work?

Is there a way to lower the count when someone dies?

chrsschb
05-26-2009, 11:39 PM
Just tested this script:

sub EVENT_SPAWN {
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 15, $x + 15, $y - 15, $y + 15);

$enter_count = 0; #Keep track of how many characters enter the proximity.
}

sub EVENT_ENTER {

$enter_count = $enter_count + 1;
quest::shout("1");

if ($enter_count > 1) {
quest::shout("No more than 1 at a time may do this encounter.");
quest::movepc(241, 0, 0, 20);
}

sub EVENT_EXIT {

$enter_count = $enter_count - 1;
quest::shout("2");

}

}

The NPC shouts 1 when PC 1 enters. When PC 2 enters he shouts 1, then kicks PC 2 out, then shouts the "No more blahblah."

I also had my PC run up to him and just die. When I died he shouted 2, which means he drops count when a player dies.

chrsschb
05-27-2009, 01:33 AM
Ok, now I'm trying to add a timed check because the script fires slowly. I expect if several people rush the proximity at the same time the boss would lose count. Using the following code he still keeps count and tells you he's over his limit, but the second MovePC won't fire. I'm guessing this is because he doesn't know which PC to move? Can I have him move a random PC if this is the case?


sub EVENT_SPAWN {
my $x = $npc->GetX();
my $y = $npc->GetY();
quest::set_proximity($x - 15, $x + 15, $y - 15, $y + 15);
quest::settimer("count",5);

$enter_count = 0;
}


sub EVENT_ENTER {

$enter_count = $enter_count + 1;
quest::shout("1");

if ($enter_count > 1) {
quest::shout("No more than 1 at a time may do this encounter.");
quest::movepc(241, 0, 0, 20);
}
}


sub EVENT_TIMER {
if (($timer eq "count") && ($enter_count > 1)) {
quest::shout("No more than 1 at a time may do this encounter. Part 2");
quest::movepc(241, 0, 0, 20);
quest::stoptimer("count");
quest::settimer("count",5);
}
}


sub EVENT_EXIT {

$enter_count = $enter_count - 1;
quest::shout("2");

}

trevius
05-27-2009, 03:30 AM
Well, part of the problem is that even though Proximities are useful, they are also very limited and don't handle certain things as well as they should. Really, IMO, the best way to do it would be to run the clientsearch check that you can get from the Rampage script that Kayen posted here:

http://www.eqemulator.net/forums/showthread.php?t=27850

You can do distance checks and even count in real time how many players are in range.

Then, probably what I would do would be to assign temporary qglobals to each person that enters the proximity. And, have it set an incrementing value for the qglobal so that it starts at 1 and goes up just like the enter_count variable does.

Then, you can use the client search code from the Rampage script to look for players and check their qglobals. If their value is greater than 6, it kicks them out.

Though, this would mean that once the limit of people are reached in the proximity, they would be the only chars that could do that event until their qglobal ran out.

You could also use a combination of that script along with the player.pl and have the player.pl do an EVENT_EXIT_ZONE or whatever the event for leaving a zone is called. And, when they leave the zone (die/gate/whatever), it deletes their temporary global and makes it available to the next person to enter.

There really are quite a few options depending on how creative you are about it and exactly what you are trying to accomplish.

If you wanted a simple way to handle it, you could just set the zone in the zones table to only allow a max of how many players you want to limit the encounter to. But, if you are only wanting to limit it for certain NPCs and not the whole zone, that wouldn't really work. Again, it depends on exactly what you are trying to do. I figured I would just give you a few ideas about things to consider. With enough creativity, a ton of stuff is possible that you wouldn't normally think would be possible.

Shendare
05-27-2009, 12:35 PM
Huh. So EntityList->GetClientByID() actually takes more of an Index as a parameter than an ID. Interesting.

chrsschb
05-27-2009, 12:48 PM
Trev, your idea sounds good, but way beyond my skill level.

The encounter is inside of a public zone. The boss is located in a room and I want only X number of people to be able to attempt him at once. If someone dies, or leaves, another person should be able to enter.

The way I have above is really simple, but slow and exploitable.

ChaosSlayerZ
05-27-2009, 02:02 PM
i could sugest a crude work around to create a sort of "mini-zone" inside a public zone

make the door leading to mobs room to be perma locked
put either a quest npc or an inviseable triger in front on the door which will allow only 6 peopel in by tagging them with a temp flag

this way NO one who doesnt have a flag can get in.
If person dies inside a room- he can be rezzed from inside i guess

in additon block casting of spells like COH


reset encounter after some min time has passed or if mob dies

THE only problem if zone itself doesn't have ANY doors actualy aviable - like Ruj or Guk LDONs.
BTW if anyone can sugest how to load ANy door into guk, mir or ruj LDON- i will be eternaly grateful =)

chrsschb
05-27-2009, 07:24 PM
i could sugest a crude work around to create a sort of "mini-zone" inside a public zone

make the door leading to mobs room to be perma locked
put either a quest npc or an inviseable triger in front on the door which will allow only 6 peopel in by tagging them with a temp flag

this way NO one who doesnt have a flag can get in.
If person dies inside a room- he can be rezzed from inside i guess

in additon block casting of spells like COH


reset encounter after some min time has passed or if mob dies

THE only problem if zone itself doesn't have ANY doors actualy aviable - like Ruj or Guk LDONs.
BTW if anyone can sugest how to load ANy door into guk, mir or ruj LDON- i will be eternaly grateful =)

This is a big and open room, a door really isn't an option (and it lacks the ability to drop the count).

Congdar
05-27-2009, 07:50 PM
EVENT_SLAY for when the npc kills a pc would be a good place to decrement the count.

nosfentora
05-28-2009, 09:04 AM
Is the room completely open or is there a 'doorway' that they need to pass through?

You could put an invisible npc @ the doorway and set it's proximity to be a line / ellipse rather than a circle.


quest::set_proximity($x, $x, $y - 100, $y + 100);


If the room is an open-air room, you could bound the area by 4 invisible npcs, setting their proximities to create a square/rectangle around the room.

What about a hailable npc to get in, flagging the hailer, and using the boundaries set by invisible npcs?

Dibalamin
05-28-2009, 12:11 PM
If there is a doorway you could also use a player.pl with the sub EVENT_CLICKDOOR.

Just have it increment a counter ++1 for each click with a quest::movepc and if counter > 6 it gives them a message saying the encounter is full? I haven't dove into global variables but you could have the counter tied to one of them and then use a sub EVENT_SLAY on the npc in the room to decrement the counter if he murders someone.

If no door I'd use the proximities & 2 different inaccessible areas of a zone....add a crate to a hall or something to block it off.