|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Quests::Plugins & Mods Completed plugins for public use as well as modifications. |
|
|
|
08-16-2011, 11:20 PM
|
|
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Spawn Tools Plugins
Here are some fun plugins I have been working on a bit lately. Most of these plugins could be used for other purposes, but they were created specifically for spawning an entire zone of NPCs randomly that looks fairly natural.
Here are the steps to add these plugins to your server:
1. Open notepad, or whatever text editor you prefer.
2. Copy and paste the following code into Notepad:
Code:
#Usage: my $LoSDistance = plugin::GetMaxLoSDistFromHeading(Heading, [DistIncrements, MaxDist, Mob]);
# This plugin attempts to get the max visible distance from the specified heading for the specified mob
# It returns the Max LoS that it can find for the settings provided
# Heading is the direction to get the max LoS for.
# DistIncrements is how much the distance check will increase each loop it does (default 20).
# Higher distance is more efficient but less precise.
# MaxDist is the maximum distance to check up to for LoS (default 200).
# Mob is an optional field to set the source NPC/Client (default is current NPC)
sub GetMaxLoSDistFromHeading {
my $npc = plugin::val('$npc');
my $client = plugin::val('$client');
my $Heading = $_[0];
my $DistIncrements = $_[1];
my $MaxDist = $_[2];
my $Mob = $_[3];
if (!$DistIncrements)
{
$DistIncrements = 20;
}
if (!$MaxDist)
{
$MaxDist = 200;
}
if (!$Mob)
{
$Mob = $npc;
}
my $LoSMobSize = 5;
my $MaxZDiff = 10;
my $MaxLoS = 0;
my $OrigX = $Mob->GetX();
my $OrigY = $Mob->GetY();
for ($LoSDistCheck = $DistIncrements; $LoSDistCheck <= $MaxDist; $LoSDistCheck += $DistIncrements)
{
my $Degrees = plugin::ConvertHeadingToDegrees($Heading);
#plugin::Debug("Current Distance Check: $LoSDistCheck || Degrees $Degrees");
my $PI = 3.141592653589793238;
my $Radian = $Degrees * ($PI / 180);
my $CircleX = $LoSDistCheck * cos($Radian);
my $CircleY = $LoSDistCheck * sin($Radian);
my $DestX = $CircleX + $OrigX;
my $DestY = $CircleY + $OrigY;
my $DestZ = $Mob->FindGroundZ($DestX, $DestY, $MaxZDiff);
my $LoS_Check = $Mob->CheckLoSToLoc($DestX, $DestY, $DestZ, $LoSMobSize);
if ($LoS_Check)
{
#plugin::Debug("LoS Success");
# If LoS is successful at this distance, continue the loop to check the next distance
$MaxLoS = $LoSDistCheck;
}
else
{
# Once LoS fails, end the loop
$LoSDistCheck = $MaxDist + 1;
}
}
return $MaxLoS;
}
#Usage: plugin::FaceBestHeading([MinLoSDist]);
# This plugin attempts to find a good heading that isn't facing a wall/structure that blocks LoS
# If the NPC is currently facing a wall, this will look for the clearest/longest view available and point that way
# It returns the best heading that it finds as well
# MinLoSDist is the minimum distance to start searching for better headings (default 20)
# If the NPC is already facing a heading that has further LoS than MinLoSDist, it will not change heading
sub FaceBestHeading {
my $npc = plugin::val('$npc');
my $MinLoSDist = $_[0];
if (!$MinLoSDist)
{
$MinLoSDist = 20;
}
# Build an array for the best matching headings
my @BestHeadings = ();
my $CurHeading = $npc->GetHeading();
my $LoSDistance = plugin::GetMaxLoSDistFromHeading($CurHeading);
my $MaxLoSDistance = $LoSDistance;
my $EqualHeadings = 0;
if ($LoSDistance < $MinLoSDist)
{
# Check headings in 16 directions for the best one(s)
for ($HeadingCheck = 0; $HeadingCheck < 256; $HeadingCheck += 16)
{
$LoSDistance = plugin::GetMaxLoSDistFromHeading($HeadingCheck, 5, 35);
if ($LoSDistance >= $MaxLoSDistance)
{
if ($LoSDistance == $MaxLoSDistance && $EqualHeadings > 0)
{
# If this headings max LoS is equal to the previous one, add it to the array of best headings
push(@BestHeadings, $HeadingCheck);
# For equal headings to be added to the array, they must all be consecutive
$EqualHeadings++;
}
else
{
@BestHeadings = ($HeadingCheck);
#plugin::Debug("Array Set to $HeadingCheck");
$MaxLoSDistance = $LoSDistance;
# Reset the equal headings count to 1 when a new max is found
$EqualHeadings = 1;
}
}
else
{
# Set equal headings to 0 if the current heading is less than the current Max LoS
# This ensures that equal headings will always be consecutive
$EqualHeadings = 0;
}
}
my $NewHeading = $CurHeading;
my $BestCount = @BestHeadings;
# If the Heading Array has entries, use the one in the middle of the array
if ($BestCount)
{
# Choose the best heading in the middle of the array to face the most open/clear angle
my $ArrayPick = int($BestCount / 2);
$NewHeading = $BestHeadings[$ArrayPick];
}
$npc->SetHeading($NewHeading);
$npc->SendPosition();
}
return $NewHeading;
}
#Usage: my $ShortestHeading = plugin::HeadingToShortestLoS([MaxDistToCheck=8]);
# MaxDistToCheck is the maximum distance to check for nearby LoS blocking
sub HeadingToShortestLoS {
my $npc = plugin::val('$npc');
my $MaxDistToCheck = $_[0];
if (!$MaxDistToCheck)
{
$MaxDistToCheck = 8;
}
my $OrigX = $npc->GetX();
my $OrigY = $npc->GetY();
my $OrigZ = $npc->GetZ();
my $ZeroLoSCheck = $npc->CheckLoSToLoc(($OrigX + 0.1), $OrigY, $OrigZ, 5);
if (!$ZeroLoSCheck)
{
# If this check fails, they are probably stuck in a wall
return -2;
}
my @BestHeadings = ();
my $CurHeading = $npc->GetHeading();
my $MinLoSDistance = 5000;
for ($HeadingCheck = 0; $HeadingCheck < 256; $HeadingCheck += 16)
{
$LoSDistance = plugin::GetMaxLoSDistFromHeading($HeadingCheck, 1, $MaxDistToCheck);
if ($LoSDistance <= $MinLoSDistance)
{
if ($LoSDistance == $MinLoSDistance)
{
push(@BestHeadings, $HeadingCheck);
}
else
{
@BestHeadings = ($HeadingCheck);
$MinLoSDistance = $LoSDistance;
}
}
}
my $NewHeading = $CurHeading;
my $BestCount = @BestHeadings;
# If the Heading Array has entries, use the one in the middle of the array
if ($BestCount && $BestCount < 15)
{
my $ArrayPick = int($BestCount / 2);
$NewHeading = $BestHeadings[$ArrayPick];
}
else
{
# Return -1 if no nearby objects found blocking LoS
return -1;
}
return $NewHeading;
}
#Usage: my $NPCMoved = plugin::MoveAwayFromWall([MinLoSDist=5]);
# MinLoSDist is the minimum distance to start searching for better headings (default 40)
# If the NPC is already facing a heading that has further LoS than MinLoSDist, it will not change heading
sub MoveAwayFromWall {
my $npc = plugin::val('$npc');
my $ShortestHeading = plugin::HeadingToShortestLoS();
if ($ShortestHeading == -2)
{
# Stuck in a wall
#$npc->Depop();
return -1;
}
elsif ($ShortestHeading == -1)
{
# Not too close to a wall
#plugin::FaceBestHeading(25);
return 0;
}
else
{
# Close to a wall
my @DestArray = plugin::CalcDestFromHeading($ShortestHeading, 5);
my $DestX = $DestArray[0];
my $DestY = $DestArray[1];
my $DestZ = $DestArray[2];
my $LoS_Check = $npc->CheckLoSToLoc($DestX, $DestY, $DestZ, 5);
# If this check fails, they are too close to the wall
if (!$LoS_Check)
{
# Face them toward the wall
$npc->SetHeading($ShortestHeading);
# Get the reverse heading from the wall
my $ReverseHeading = plugin::GetReverseHeading();
#my $LoSDistance = plugin::GetMaxLoSDistFromHeading($ReverseHeading, 1, 5);
@DestArray = plugin::CalcDestFromHeading($ReverseHeading, 10);
$DestX = $DestArray[0];
$DestY = $DestArray[1];
$DestZ = $DestArray[2];
$LoS_Check = $npc->CheckLoSToLoc($DestX, $DestY, $DestZ, 5);
# If there is enough room, move them the opposite direction from the nearest wall
if ($LoS_Check)
{
@DestArray = plugin::CalcDestFromHeading($ReverseHeading, 10);
$DestX = $DestArray[0];
$DestY = $DestArray[1];
$DestZ = $DestArray[2];
$npc->GMMove($DestX, $DestY, ($DestZ + 1), $ReverseHeading);
# Return true if moved
return 1;
}
else
{
# Not enough room to move toward or away from the wall
# Move toward the best heading
my $BestHeading = plugin::FaceBestHeading();
@DestArray = plugin::CalcDestFromHeading($BestHeading, 6);
$DestX = $DestArray[0];
$DestY = $DestArray[1];
$DestZ = $DestArray[2];
$npc->GMMove($DestX, $DestY, ($DestZ + 1), $BestHeading);
# Return true if moved
return 1;
}
}
}
# If no move, return false
return 0;
}
#Usage: plugin::MoveToFirstBestZ();
sub MoveToFirstBestZ {
my $npc = plugin::val('$npc');
my $x = plugin::val('$x');
my $y = plugin::val('$y');
my $h = plugin::val('$h');
$npc->GMMove($x, $y, 1000, $h);
my $GroundZ = $npc->FindGroundZ($x, $y, 3);
if($GroundZ > -5000)
{
$npc->GMMove($x, $y, ($GroundZ -10), $h);
$NextGroundZ = $npc->FindGroundZ($x, $y, 3);
if($NextGroundZ > -5000)
{
$npc->GMMove($x, $y, $NextGroundZ, $h);
}
else
{
$npc->GMMove($x, $y, $GroundZ, $h);
}
}
}
#Usage: plugin::SpawnZone(X, Y, Z, Distance, Variance, Columns, Rows);
# This is used to spawn a grid of NPCs and can be used to spawn an entire zone
# X/Y/Z are the coords of the first NPC to spawn that the others are spawned based on it's location
# Distance is the distance each member of the formation will be from each other on both axis
# Variance is the max distance of scatter effect you want on the grid positioning to make it look less like a grid
# Columns is the number of columns you want in the formation
# Rows is the number of rows you want in the formation
sub SpawnZone {
my $entity_list = plugin::val('$entity_list');
my $SpawnX = $_[0];
my $SpawnY = $_[1];
my $SpawnZ = $_[2];
my $Distance = $_[3];
my $Variance = $_[4];
my $Columns = $_[5];
my $Rows = $_[6];
$Heading = plugin::RandomRange(0, 254);
$MaxZDiff = 3;
# Create the array of NPCIDs to spawn in the grid
my @NPCIDList = ();
my $NPCNum = 7;
while ($_[$NPCNum])
{
push(@NPCIDList, $_[$NPCNum]);
$NPCNum++;
}
my $ListLength = (@NPCIDList) - 1;
my $FirstNPCID = $NPCIDList[0];
# Set the first NPC to spawn directly in the center of the grid
$SpawnX = $SpawnX - (($Rows - 1) * $Distance / 2);
$SpawnY = $SpawnY - (($Columns - 1) * $Distance / 2);
# Spawn the first NPC
quest::spawn2($FirstNPCID, 0, 0, $SpawnX, $SpawnY, $SpawnZ, $Heading);
# Get the first NPC
my $MainNPC = $entity_list->GetNPCByNPCTypeID($FirstNPCID);
my $NewX = $SpawnX;
my $NewY = $SpawnY;
$NewX = $NewX + $Distance;
if ($MainNPC)
{
for ($ColNum = 0; $ColNum < $Columns; $ColNum++)
{
for ($RowNum = 0; $RowNum < $Rows; $RowNum++)
{
# Prevent Respawn over the first NPC
if ($RowNum > 0 || $ColNum > 0)
{
my $RandXDiff = plugin::RandomRange(0, $Variance);
my $RandYDiff = plugin::RandomRange(0, $Variance);
# Set even numbers to negative
if ($RandXDiff && ($RandXDiff / 2) == int($RandXDiff / 2))
{
$RandXDiff *= -1;
}
if ($RandYDiff && ($RandYDiff / 2) == int($RandYDiff / 2))
{
$RandYDiff *= -1;
}
my $ModX = $NewX + $RandXDiff;
my $ModY = $NewY + $RandYDiff;
my $NewZ = $MainNPC->FindGroundZ($ModX, $ModY, $MaxZDiff);
if ($NewZ > -5000)
{
my $RandomNPCNum = plugin::RandomRange(0, $ListLength);
my $NPCID = $NPCIDList[$RandomNPCNum];
my $RandHeading = plugin::RandomRange(0, 254);
quest::spawn2($NPCID, 0, 0, $ModX, $ModY, $NewZ, $RandHeading);
}
$NewX = $NewX + $Distance;
}
}
$NewY = $NewY + $Distance;
$NewX = $SpawnX;
}
}
}
#Usage: my $ReverseHeading = plugin::GetReverseHeading([$mob]);
# Returns the heading of the opposite direction the mob is facing
sub GetReverseHeading {
my $npc = plugin::val('$npc');
my $Mob = $_[0];
if (!$Mob)
{
$Mob = $npc;
}
my $CurHeading = $Mob->GetHeading();
my $ReverseHeading = 128 + $CurHeading;
if ($ReverseHeading >= 256)
{
$ReverseHeading = $ReverseHeading - 256;
}
return $ReverseHeading;
}
#Usage: my $Degrees = plugin::ConvertHeadingToDegrees(Heading);
# Converts 0-256 headings into 0 to 360 degrees
sub ConvertHeadingToDegrees {
my $Heading = $_[0];
my $ReverseHeading = 256 - $Heading;
my $ConvertAngle = $ReverseHeading * 1.40625;
if ($ConvertAngle <= 270)
{
$ConvertAngle = $ConvertAngle + 90;
}
else
{
$ConvertAngle = $ConvertAngle - 270;
}
return $ConvertAngle;
}
return 1; #This line is required at the end of every plugin file in order to use it
3. Save that file to your server /plugins/ folder and name it "spawn_tools.pl".
4. Do a #questreload and the new plugin should be ready for use
Then, to make use of these plugins, you will need some extra scripts. Here is one you can put on any NPC. I currently use it on a GM tool pet I made, but you could add it to any NPC in the zone you are working on. This does the actual spawning of the zone. It is best to position the NPC in the center of the zone so your grid reaches all sides of the zone. Depending on the size if your zone, you may need to adjust the number of columns, rows or distance to fill the entire zone.
This example includes Guk LDoN NPC IDs, but you can just replace the NPC IDs with any other IDs you want that fit your zone. I used gukc as my test zone for this script, so you may want to try it there just to get an idea of how it works and to see the results.
Code:
sub EVENT_SAY {
my $SpawnZone = quest::saylink("Spawn Zone", 0, "Spawn the Zone");
if ($status > 20)
{
if ($text =~/Hail/i)
{
quest::say("Are you ready to [ $SpawnZone ]?");
}
if ($text =~/Spawn Zone/i)
{
quest::say("Starting Zone Spawn");
#Usage: plugin::SpawnZone(X, Y, Z, Distance, Variance, Columns, Rows);
plugin::SpawnZone($x, $y, $z, 50, 20, 40, 40,
264200, # A_Blighted_Jin_Master
264228, # A_Cursed_Guktan
264202, # A_Cursed_Korta_Researcher
264223, # A_Dazzling_Oculus
264220, # A_Decaying_Yunta_Witchdoctor
264221, # A_Doomed_Yunta_Witchdoctor
264217, # A_Ghoulish_Dar_Warrior
264212, # A_Ghoulish_Darta_Knight
264219, # A_Miserable_Jinta_Phantasm
264213, # A_Witness_of_Hate_Bonecollector
264216, # A_Witness_of_Hate_Seer
264226, # A_Witness_of_Hate_assassin
264214, # A_Witness_of_Hate_knave
264207, # a_cursed_burrower
264215, # a_forlorn_Darta_soldier
264218 # an_unsanctified_Korta_priest
);
quest::say("Zone Spawn complete");
}
}
else
{
quest::say("Sorry, I only speak with GMs");
}
}
That will get the zone spawned, but you will still have NPCs that are half stuck in walls or inside them completely and you will have lots of NPCs facing walls or headings that just don't look natural. To resolve that, you will want to create a default.pl file in zone folder you are working/testing in and add the following to it:
Code:
# default.pl - Moves away from walls and sets Best Heading
sub EVENT_SPAWN {
# Move away from walls and set the best heading
my $HeadingTimer = plugin::RandomRange(2,5);
quest::settimer("BestHeading", $HeadingTimer);
}
sub EVENT_TIMER {
if ($timer eq "BestHeading")
{
quest::stoptimer("BestHeading");
my $NPCMoved = plugin::MoveAwayFromWall();
if ($NPCMoved == -1)
{
# Stuck in a wall
plugin::Debug("Stuck in wall - Depopping");
$npc->Depop();
}
else
{
plugin::FaceBestHeading(25);
}
}
}
Note that some of these scripts are modified a bit from the ones I use to make them easier for the general public. Since I didn't actually test some of the ones posted here exactly as they are posted, there may be issues but I am pretty sure they should work fine. Also, some of these plugins require other plugins that you can find in the Akkadius Plugin Repository if you don't already have them. The scripts will fail if you don't have all of the required plugins.
These plugins are pretty resource intensive, so I wouldn't recommend over-using them. I mainly made them to assist in new zone development. I plan to spawn a zone with the plugin, then use another script that will save all of the spawns to the DB. These scripts could probably be used to create dynamic zones for players, but if you do that, I would keep it pretty limited and in smaller zones.
I hope you guys like these plugins. I know I am pretty impressed with their results so far. They aren't quite perfect, but they are good enough for getting a very nice head-start on spawning a zone from scratch. You could spawn a zone with this in seconds and clean it up with #spawnfix as needed and have a very nice looking zone in under an hour easily. You would still want to spawn named manually and such as needed, but this works well for random trash spawns.
I may continue this idea and add a plugin that checks around an NPC when it spawns and determines if it has enough room to use the RandomRoam plugin effectively and set it if so. This would get things close to being able to make a dynamically spawned and pathed zone.
Last edited by trevius; 08-17-2011 at 05:35 AM..
|
|
|
|
08-17-2011, 04:44 PM
|
Hill Giant
|
|
Join Date: Sep 2006
Posts: 112
|
|
Nice code. I am sure that will help a lot of us in creating zones in a matter of say 30m instead of a day (Depending on the zone).
Appreciate the post. Going to test this out soon.
|
08-18-2011, 02:06 PM
|
Hill Giant
|
|
Join Date: Mar 2010
Posts: 236
|
|
same, after i finish spawning my zone im gonna work on adding these.
|
08-18-2011, 02:26 PM
|
|
Administrator
|
|
Join Date: Feb 2009
Location: MN
Posts: 2,071
|
|
I will add these to the repository shortly.
Edit: Added to repository. Go ahead and source.
|
09-03-2011, 07:01 PM
|
Hill Giant
|
|
Join Date: Mar 2010
Posts: 236
|
|
hey trev, do you have the script you use to save em all to the database?
Also can the plug in be altered to spawn less mobs or more?
|
09-03-2011, 07:09 PM
|
|
Administrator
|
|
Join Date: Feb 2009
Location: MN
Posts: 2,071
|
|
Quote:
Originally Posted by Astal
hey trev, do you have the script you use to save em all to the database?
Also can the plug in be altered to spawn less mobs or more?
|
This really should be quite simple, I haven't tested this, but it should work.
Code:
my @npclist = $entity_list->GetNPCList();
foreach $ent (@npclist){
$ent->NPCSpawn($ent, "add", 1200);
}
|
|
|
|
09-04-2011, 09:20 PM
|
|
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Quote:
Originally Posted by Astal
Also can the plug in be altered to spawn less mobs or more?
|
You can spawn exactly the density of NPCs that you want. The distance field below will set how far apart they spawn from each other, which controls density. Then, rows and columns can control the total size of the area that the NPCs populate. The fields are all covered in the comments of the plugin:
#Usage: plugin::SpawnZone(X, Y, Z, Distance, Variance, Columns, Rows);
# This is used to spawn a grid of NPCs and can be used to spawn an entire zone
# X/Y/Z are the coords of the first NPC to spawn that the others are spawned based on it's location
# Distance is the distance each member of the formation will be from each other on both axis
# Variance is the max distance of scatter effect you want on the grid positioning to make it look less like a grid
# Columns is the number of columns you want in the formation
# Rows is the number of rows you want in the formation
|
|
|
|
09-04-2011, 11:13 PM
|
Hill Giant
|
|
Join Date: Mar 2010
Posts: 236
|
|
ok ill fiddle with it, thanks
ok that add script, i guess id add it to the same npc with a new text command or whatever right. Does that save them the same way spawning multiple instances in georges npc editor and spawn placing them manually would?
ok yeah that script dont work, trev u willing to post the one you use to save the spawns
oh btw if u get random roam working with this ill love u forever
|
09-05-2011, 12:42 AM
|
|
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Akka's script was really close. That function is a client function though, so it needs to be initiated from a client (since you should always have a client available to use that command anyway).
I haven't actually tried saving the NPCs after using these plugins yet, but it should be very simple. I didn't test this, but I think this script should work:
Code:
if ($text =~/Save Spawns/i)
{
my @npclist = $entity_list->GetNPCList();
foreach $ent (@npclist)
{
$client->NPCSpawn($ent, "add", 1200);
}
}
|
09-05-2011, 04:25 PM
|
Hill Giant
|
|
Join Date: Mar 2010
Posts: 236
|
|
Quote:
Originally Posted by trevius
Akka's script was really close. That function is a client function though, so it needs to be initiated from a client (since you should always have a client available to use that command anyway).
I haven't actually tried saving the NPCs after using these plugins yet, but it should be very simple. I didn't test this, but I think this script should work:
Code:
if ($text =~/Save Spawns/i)
{
my @npclist = $entity_list->GetNPCList();
foreach $ent (@npclist)
{
$client->NPCSpawn($ent, "add", 1200);
}
}
|
ok that works, is there anyway i can make it add all of the same npc type to 1 spawn group. Thats how i do my other spawns
|
09-17-2011, 12:55 PM
|
Hill Giant
|
|
Join Date: Jan 2010
Location: Baltimore Maryland
Posts: 152
|
|
I went to gukc and used the script you posted and it worked like a charm. I used the exact same script in a SoD zone and it wouldn't work. I did get it to work in a zone like crushbone, so I am very very confused. Is there something blocking SoD zones that anyone might know about?
__________________
Expletus / Volgar
|
09-17-2011, 01:58 PM
|
Dragon
|
|
Join Date: Dec 2008
Location: Tennessee
Posts: 654
|
|
Quote:
Originally Posted by Expletus
I went to gukc and used the script you posted and it worked like a charm. I used the exact same script in a SoD zone and it wouldn't work. I did get it to work in a zone like crushbone, so I am very very confused. Is there something blocking SoD zones that anyone might know about?
|
I used the tool in Citadel of the Worldslayer and it worked very well. Only quirk I found was a positive gain in zone height seemed to cause spawning issues. Easily overcome by placing the npc used for spawning at the heightest point in the zone. And that was probably just a setting that needed to be changed.
All around it is an excellant tool as it saves many, many hours on zone creation time.
|
09-17-2011, 02:12 PM
|
Hill Giant
|
|
Join Date: Jan 2010
Location: Baltimore Maryland
Posts: 152
|
|
I don't know why it won't work for me to be honest. If you wouldn't mind, try using it in Oceangreenvillage and see if it spawns anything but 1 mob. I will try some other SoD zones, maybe that zone is special
__________________
Expletus / Volgar
|
09-17-2011, 02:54 PM
|
Dragon
|
|
Join Date: Dec 2008
Location: Tennessee
Posts: 654
|
|
It worked for me in ocreangreenvillage.
|
09-17-2011, 02:58 PM
|
Hill Giant
|
|
Join Date: Jan 2010
Location: Baltimore Maryland
Posts: 152
|
|
Interesting... all of my SoD zones won't spawn but 1 npc (the first line). No matter how I change it, it's just 1 npc that spawns. If I go to any other zones outside of SoD it works flawlessly...
Any ideas?
__________________
Expletus / Volgar
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 11:39 AM.
|
|
|
|
|
|
|
|
|
|
|
|
|