PDA

View Full Version : Anti Train Code


eqwarrior
07-21-2009, 02:04 PM
Is there a way to know how many mobs have aggroed a player and then boot them from a zone or off the server for making too big of a train? Players love to make trains to power level. Maybe it would be customizeable that you could set how big the train could be, what zone would it be affected, and a time limit of being booted from the zone/server as a punishment or cool down? Would probably require some edit in source code + quest code. Any ideas to stop 300 mob trains besides giving all mobs summon?

gaeorn
07-21-2009, 03:59 PM
You could do something through quests. Have all the mobs send a signal to a controller on aggro and another signal on death. The controller will add to a count for each aggro and deduct for each death. If the counter goes above a certain number, have the controller take whatever action you desire (port the player, spawn a super tough mob on top of the player... whatever you can think of).

trevius
07-21-2009, 06:10 PM
I am sure that it could be done fairly easily with scripts, but I don't know if I would do it that way exactly. Mainly because monks might aggro many different NPCs without pulling and killing them, so their count might go too high and get them booted when they shouldn't be. You could probably do something simple like using EVENT_ATTACK and EVENT_KILLED_MERIT to add and remove points using a temp qglobal system.

You might also be able to use the IsOnHatelist(p) quest object for this, but I haven't ever used it, so I don't know how useful it would be in this situation.

To use the EVENT_ATTACK, you might be able to do something like this:

sub EVENT_ATTACK {

if (!defined($qglobals{train_stopper})){
quest::setglobal("train_stopper", 1, 5, "S30");
}
else
{
quest::setglobal("train_stopper", ($qglobals{train_stopper} + 1), 5, "S30");
if ($qglobals{train_stopper} > 30){
quest::movepc(152, 0, 0, -30); #Nexus port for offenders
}
}
}

sub EVENT_KILLED_MERIT {
if (defined($qglobals{train_stopper})){
if ($qglobals{train_stopper} > 1){
quest::setglobal("train_stopper", ($qglobals{train_stopper} - 1), 5, "S30");
}
}
}


Then just make sure that all of the NPCs in the zone have the global flag set for them in the npc_types table. You can always tweak this script to work smoother for your needs. I haven't tested it, but it should work. Might need minor adjustments incase I made a typo or something though.

eqwarrior
07-21-2009, 08:49 PM
I understand the quest code. Looks pretty good. Now if the user triggers EVENT_COMBAT less than every 30 seconds, then the 30 second global would never expire, thus eventually booting them for a train? As you said, I could probably tweek it a bit, but this is exactly what I was looking for. Was hoping there could be a source code to return a value of how many NPC's have that player on aggro, but perl quest seems to be a quick code/fix.

Thanks.

trevius
07-21-2009, 10:35 PM
Actually I don't think EVENT_COMBAT would quite work right in the first place, so I changed it to EVENT_ATTACK and EVENT_KILLED_MERIT. I think that should work just fine as it is posted.

The idea is that if they are aggroing 1 mob (or more) less than every 30 seconds, the global would keep counting up until it finally kicks them. But, if they are just pulling constantly and killing really fast 1 by 1, they will get the points removed by the EVENT_KILLED_MERIT, so it won't ever kick them. And, if a monk is aggroing a bunch of stuff and FDing, most likely they are going to clear that 30 second timer from time to time so they shouldn't exceed the cap to be kicked. Like I said though, you will probably want to test it and maybe play around with it to see how well it works. Probably putting it in a zone that people commonly AE in will get some quick feedback on the settings for it or if there are issues.

You should be able to add that to the default.pl for your server in the quests/templates folder so it works for all zones if you want. Or you could add it to the default.pl for individual zones that you want to stop trains in. Or, if the NPCs in question already have scripts associated with them, you would just need to add those pieces into the existing scripts for the NPCs.

Yeah, I agree that it would be nice to have a code check for it, and maybe even some sort of rule. It would also be really handy to be able to do hate count for players or NPCs to see how many things total are on their hate list. That would make it pretty simple to limit trains via scripts.

Maybe at some point a rule could be added for this. It would probably be something that would fit into the same category with leashing NPCs to their spawn point, which is another thing I would like to see added at some point. The NPC leashing could be set by adding a new field to the npc_types table named something like "leashdist" so you could set leashes on a per NPC basis. For max train size, that is something that would probably need to go in the zones table so you could set the max hate count from npcs on a per zone basis in a field named something like "maxhatecount". Both new fields defaulting to 0 of course, which would mean those features are disabled.

I don't really have time to work on either of these atm, but they are good ideas to keep note of in case someone else finds the time to write them.

eqwarrior
07-21-2009, 11:00 PM
Thanks Trev!

KingMort
07-22-2009, 01:20 PM
You could also Leash the mobs that you want to not be trained..

Here is the code for that ..

Forgot who originally wrote this for my server but it works great! Thank you to whoever that was (Striat I think).. And i apologize that I forgot who you were.

Alright so this would go at the TOP of the script

##This is npc's spawned x, y location and leash length
$leashlength = 100;


sub EVENT_COMBAT
{
if($combat_state == 1)
{
quest::settimer("checkleash",5);
}
}


NOTE: You can change that 5 to whatever number you like..

Then you can place this down near the bottom (actually doesn't matter but that is how I do it)

sub EVENT_TIMER
{
$currentx = $npc->GetX();
$currenty = $npc->GetY() ;
$currentz = $npc->GetZ();

if($timer eq "checkleash")
{
###This is just the equation for a sphere
###(x - x_0 )^2 + (y - y_0 )^2 + ( z - z_0 )^2 = r^2.
###

$leftside = ((($currentx - $startingx)*($currentx-$startingx)) + (($currenty - $startingy)*($currenty - $startingy)) + (($currentz - $startingz)*($currentz - $startingz)));
$rightside = ($leashlength * $leashlength);
if($leftside > $rightside)
{
$currentx = undef;
$currenty = undef;
$currentz = undef;
$npc->WipeHateList();
$npc->GMMove($startingx, $startingy, $startingz, $startingh);
quest::stoptimer("checkleash");
quest::settimer("checkleash",5);
}
}


Anyway hope it works for you

King
www.raidaddicts.org

trevius
07-22-2009, 09:38 PM
Just a guess, but does there also happen to be an EVENT_SPAWN section that sets the $startingx, $startingy, $startingz, and $startingh variables that you didn't post? And if so, does leashing work effectively with multiple of the same NPCs running the same script and being aggroed at the same time? I might have to test that script out :P

I know Kayen posted this leashing script a while back in this thread, but I think it leashes NPCs to other NPCs, not to their spawn point:

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

sub EVENT_AGGRO
{
quest::settimer("LeashCheck",5);
}

sub EVENT_TIMER {

if ($timer eq "LeashCheck") {
$LeashedID = $entity_list->GetMobByNpcTypeID(1247);
$distanceCHK = $LeashedID->CalculateDistance($x, $y, $z);
#quest::shout("$distanceCHK x $LeashedID");
if ($distanceCHK >= 30) {
$LeashedID->WipeHateList();
$LeashedID->GMMove($x, $y, $z, 1);
}
}
}