Go Back   EQEmulator Home > EQEmulator Forums > Support > Support::Windows Servers

Support::Windows Servers Support forum for Windows EQEMu users.

Reply
 
Thread Tools Display Modes
  #1  
Old 11-20-2017, 05:07 PM
Raghnar
Fire Beetle
 
Join Date: Feb 2010
Location: San Diego
Posts: 16
Thumbs up Ships in dynamic zones

I searched and searched and found people who say they have figured this out but I never could find their actual solution. So I have been working on one. I am almost there. I think I have cracked most of the nuts but wanted to get some input from smarter folks.

So my solution to not making zones static, is to simply spawn ships based on $zonetime. If players are in that zone, great ships spawn and move around. If zone is empty, nothing happens until a player comes in, then the script checks to see where a ship should be and puts it there. If all players leave and the ships are up and now stop moving, no problem we check for that the next time a player comes in zone and we move the ship and restart its new grid.

The work I have done so far seems to work fine. If anyone sees any obvious holes in the scripts that would make this fail, feel free to post a fix. Please go easy on my, my grasp of perl is about as tenuous as my grasp on logic and reality. I wrote some of this under the influence of Modelo as well. But please don't tell me this is just garbage and not offer a solution.

Some basics first:
Server - Akkadius PEQ via installer
Client - Titanium
Expansions - Classic, Kunark, Velious (for now)

Siren's Bane has some issues. Falling through it was the big one right? So in Ocean of Tears we set race = 72, texture = 1, gender =0. This gives us a ship you can walk on (you can still walk through walls and fall through poop deck). But the ship is also gigantic and difficult to maneuver without colliding with the docks and rocks in Butcherblock and East Freeport.

There are a couple solutions. The difficult one is to bring the later expansion ship models into your client everquest directory, add them to your global load and use those models. The easier solution is to use launches to take your players out to the zone line and move them to the waiting ship on the other side.

The easier solution just requires that you globally load the _chr files that have the launch model in them. I was not sure so I added butcher, erudnext, erudxing, firiona, halas, overthere, and timorous. It doesn't eat too much resource, but it would be best to find exactly which one has the launch. I will look later, pretty sure it is erudnext_chr.

So that means modifying your client's Everquest\Resources\GlobalLoad.txt file. For now just append this to the end. Or if it does exist in erudnext_chr like I think, just add that one and forget the others so your player's client doesn't have to load the extras.

1,0,TFFF,butcher_chr,Loading Characters
1,0,TFFF,erudnext_chr,Loading Characters
1,0,TFFF,erudsxing_chr,Loading Characters
1,0,TFFF,firiona_chr,Loading Characters
1,0,TFFF,halas_chr,Loading Characters
1,0,TFFF,overthere_chr,Loading Characters
1,0,TFFF,timorous_chr,Loading Characters

So now that I can use the launch models in East Freeport we simply set up a schedule. I am an old retired Operations Specialist, so I like it when my ship sails on time, so on my server the ship has a schedule and they stick to it. The shuttle from East Freeport leaves the pier at 3:00am (I will use standard time for you sand crabs even though the server uses a 24 hour clock), and 3:00pm. The Sirens Bane receives passengers in Ocean of Tears and sails east at precisely 3:30am and 3:30pm daily. It zones passengers into Butcherblock at around 7:57am and 7:57pm and drops the players onto the launch to the pier which drops them at the dock, waits until precisely 9:00am or pm before transiting back to the zone line to deliver them to the waiting Sirens Bane in Ocean of tears. Sirens Bane will then transit back to East Freeport.

After you modify your GlobalLoad.txt you are ready to set up your boats.

1. Create your zone line controllers
/zone freporte
#goto -2090 -38 -76
#spawn fpecontroller
/targ fpecontroller
#npcspawn create

/zone oot
#goto 10239 1272 -42
#spawn ootfpecontroller
/targ ootfpecontroller
#npcspawn create

#goto -10258 302 -42
#spawn ootbutcontroller
/targ ootbutcontroller
#npcspawn create

/zone butcher
#goto 3683 1611.7 -13
#spawn butcontroller
/targ butcontroller
#npcspawn create

You will need to edit each spawn point that you just created to have them face the direction the ship or shuttle will face when it spawns.

You will need to edit each npc you created to enable Quest Globals. Eventually you will want to change their race to Invisible Man (127) and body type to No Target (11). But while testing it is best to leave them as is.


2. Set up your ships and launches


Butcher - Find the Butcher Block SirensBane in your db. In my install it is 68228. Make sure it is race 73 (launch), Texture 1, and Gender 0. This will set it to look like the Captain's Skiff that takes players out to Maiden's Voyage.

Find the spawngroup for SirensBane and delete any spawn points. Keep the spawn group, just delete the spawn point.

Change run speed to 3.5

Freeport - Zone to East Freeport (freporte) and do the same for SirensBane there (10183). Delete any spawnpoints.

Change run speed to 3.5

Ocean of Tears - In OOT you will want to modify SirensBane (69134) to race 72 (ship), texture 1, gender 0. Again find the spawn group and delete any spawn points.

Change run speed to 3.856. Run speeds will vary depending on your grid length. You can experiment using the information I posted below if you want to lengthen or shorten your round trip times.

Make sure to enable Quest Globals for all of your ships.

3. Create your scripts.

You are going to need a few perl scripts. One for each controller, one for each ship, and one for each harbor master. You can name them after the npcname or after the npcid. I will list them here with npc name to avoid confusion.

Freeport Zone Controller

fpecontroller.pl
Code:
# Zone to Ocean of Tears
# Zone: freporte
# Raghnar

sub EVENT_SPAWN {
$x = $npc->GetX();
$y = $npc->GetY();
#Set proximity
quest::set_proximity($x - 40,$x + 40,$y - 40,$y + 40);
quest::settimer(1,1);
quest::settimer(3,30);
  
}

sub EVENT_ENTER {
	
	if ($qglobals{"fozoneopen"} == 1 ) {
	quest::setglobal("ooteast",1,7,"F"); #let oot side zone know to change race
	quest::setglobal("boatrider",1,5,"S60"); #let oot player enter event know to lev player
	quest::movepc(69,10239,1272,10,0);
	}
	elsif ($qglobals{"ootwest"} == 1) { #boat illusion so players are not hovering over water
		quest::npcrace(73);
		quest::npctexture(1);
		quest::npcgender(0);
		
	}
	else {
	quest::shout("Zone is not open");
	}
}

sub EVENT_TIMER {
	if ($timer == 1 && $zonetime == 210) { 
		quest::stoptimer($timer); 
		quest::settimer(2,3); 
		quest::spawn(10183,23,0,-2090,-38,-76); 
		quest::npcrace(127);
		quest::setglobal("ofzoneopen",2,7,"F"); #close zone to any players still in oot
		quest::setglobal("ootwest",2,7,"F"); #keep extra shuttles from spawning
		quest::signalwith(10192,1); #tell harbor master to let folks know where boat is
		}
	if ($timer == 1 && $zonetime == 1410) { 
		quest::stoptimer($timer);
		quest::settimer(2,3);
		quest::spawn(10183,23,0,-2090,-38,-76);
		quest::npcrace(127);
		quest::setglobal("ofzoneopen",2,7,"F"); #close oot to fpe zone line just in case
		quest::setglobal("ootwest",2,7,"F"); #keeps extra shuttles from spawning
		quest::signalwith(10192,2); #tell harbor master to let folks know where boat is
		}
	if ($timer == 1 && $zonetime == 300) { #boat leaves dock at this time
		quest::stoptimer($timer);
		quest::settimer(2,3);
		quest::setglobal("fozoneopen",1,7,"F"); #open zone so players can zone to oot
		}
	if ($timer == 1 && $zonetime == 1500) { #boat leaves dock at this time
		quest::stoptimer($timer);
		quest::settimer(2,3);
		quest::setglobal("fozoneopen",1,7,"F"); #open zone so players can zone to oot
		}
		
	if ($timer == 1 && $zonetime == 330) { #boat has spawned in oot
		quest::stoptimer($timer);
		quest::settimer(2,3);
		quest::setglobal("fozoneopen",2,7,"F"); #close zone to players remaining in fpe
		}
	if ($timer == 1 && $zonetime == 1530) { #boat has spawned in oot
		quest::stoptimer($timer);
		quest::settimer(2,3);
		quest::setglobal("fozoneopen",2,7,"F"); #close zone to players remaining in fpe
		}
	
	if ($timer == 2) {
		quest::stoptimer($timer);
		quest::settimer(1,1);
		}
}
Ocean of Tears to Freeport Zone Controller

ootfpecontroller.pl

Code:
# Zone to East Freeport
# Zone: oot
# Raghnar

sub EVENT_SPAWN {
$x = $npc->GetX();
$y = $npc->GetY();
#Set proximity
quest::set_proximity($x - 150,$x + 150,$y - 150,$y + 150);
quest::settimer(4,1);
quest::settimer(6,1);
}


sub EVENT_ENTER {
	if ($qglobals{"ofzoneopen"} == 1) {  
	quest::setglobal("ootwest",1,7,"F");
	quest::setglobal("boatrider",1,5,"S60");
	quest::movepc(10,-2090,-38,-55);
	}
	
	elsif ($qglobals{"ooteast"} == 1) {
		quest::npcrace(72);
		quest::npctexture(1);
		quest::npcgender(0);
		
	}
	else {
		quest::shout("Zone is not open");
	}	
		
} 

sub EVENT_TIMER {   

	if ($timer == 4 && $zonetime == 330) {
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::spawn2(69134,60,0,10239,1272,-42,128);
		quest::npcrace(127);
		quest::setglobal("fozoneopen",2,7,"F"); #close zone in fpe if players still exist there
		quest::setglobal("ooteast",2,7,"F"); #no more race changes for controller
		}
		
	if ($timer == 4 && $zonetime == 1530) {
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::spawn2(69134,60,0,10239,1272,-42,128);
		quest::npcrace(127);
		quest::setglobal("fozoneopen",2,7,"F"); #close zone in fpe if players still exist there
		quest::setglobal("ooteast",2,7,"F");#no more race changes for controller
		}
	
	if ($timer == 4 && $zonetime == 125) { #open zone so players can zone to fpe on boat 
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::setglobal("ofzoneopen",1,7,"F");
		}
		
	if ($timer == 4 && $zonetime == 1325) { #open zone so players can zone to fpe on boat
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::setglobal("ofzoneopen",1,7,"F");
		}
	
	if ($timer == 4 && $zonetime == 210) { #close the zone to fpe if no players zoned
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::setglobal("ofzoneopen",2,7,"F");
		}
		
	if ($timer == 4 && $zonetime == 1410) { #close the zone to fpe if no players zoned
		quest::stoptimer($timer);
		quest::settimer(5,3);
		quest::setglobal("ofzoneopen",2,7,"F");
		}
		
	if ($timer == 5) {
			quest::stoptimer($timer);
			quest::settimer(4,1);
			}
	
}
Ocean of Tears to Butcher Zone Controller

ootbutcontroller.pl

Code:
# Zone to Butcherblock Mountains
# Zone: oot
# Raghnar

sub EVENT_SPAWN {
$x = $npc->GetX();
$y = $npc->GetY();
#Set proximity
quest::set_proximity($x - 150,$x + 150,$y - 150,$y + 150);
quest::settimer(7,1);
}

sub EVENT_ENTER {
	
	if ($qglobals{"obzoneopen"} == 1) {
	quest::setglobal("buteast",1,7,"F"); #let oot zone know to change race
	quest::setglobal("boatrider",1,5,"S60"); #let oot player enter know to lev player
	quest::movepc(68,3683,1611.7,14,0);
	}
	
	elsif ($qglobals{"ootwest"} == 1) { #boat illusion
		quest::npcrace(72);
		quest::npctexture(1);
		quest::npcgender(0);
		
	}
	else {
		quest::shout("Zone is not open");
	}	
	
}

sub EVENT_TIMER {  

	if ($timer == 7 && $zonetime == 930) {  
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::spawn2(69134,61,0,-10258,302,-42,64);
		quest::npcrace(127);
		quest::setglobal("bozoneopen",2,7,"F"); #close zone in butcher if players still exist there
		quest::setglobal("ootwest",2,7,"F"); #no more race changes for controller
		}
		
	if ($timer == 7 && $zonetime == 2130){ 
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::spawn2(69134,61,0,-10258,302,-42,64);
		quest::npcrace(127);
		quest::setglobal("bozoneopen",2,7,"F"); #close zone in butcher if players still exist there
		quest::setglobal("ootwest",2,7,"F"); #no more race changes for controller
		}
	
	if ($timer == 7 && $zonetime == 715) { #open zone for players to zone to butcher
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::setglobal("obzoneopen",1,7,"F");
		}
		
	if ($timer == 7 && $zonetime == 1915) { #open zone for players to zone to butcher
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::setglobal("obzoneopen",1,7,"F");
		}	
	
	if ($timer == 7 && $zonetime == 810) { #close the zone to butcher if no players zoned
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::setglobal("obzoneopen",2,7,"F");
		}		
	
	if ($timer == 7 && $zonetime == 2010) { #close the zone to butcher if no players zoned
		quest::stoptimer($timer);
		quest::settimer(8,3);
		quest::setglobal("obzoneopen",2,7,"F");
		}		
	
	if ($timer == 8) {
			quest::stoptimer($timer);
			quest::settimer(7,1);
			}

}
Butcher to Ocean of Tears Zone Controller

butcontroller.pl

Code:
# Zone to Ocean of Tears
# Zone: butcher
# Raghnar

sub EVENT_SPAWN {
$x = $npc->GetX();
$y = $npc->GetY();
#Set proximity
quest::set_proximity($x - 40,$x + 40,$y - 40,$y + 40);
quest::settimer(9,1);
quest::settimer(11,1);
}

sub EVENT_ENTER {
	
	if ($qglobals{"bozoneopen"} == 1 ) {
	quest::setglobal("ootwest",1,7,"F");
	quest::setglobal("boatrider",1,5,"S60");
	quest::movepc(69,-10258.1,302,20,0);
	}
	elsif ($qglobals{"buteast"} == 1) { 
		quest::npcrace(73);
		quest::npctexture(1);
		quest::npcgender(0);
		}
	else {
	quest::shout("Zone is not open");
	}
}

sub EVENT_TIMER {
	if ($timer == 9 && $zonetime == 810) { 
		quest::stoptimer($timer); 
		quest::settimer(10,3); 
		quest::spawn(68228,224,0,3683,1611.7,-13);
		quest::npcrace(127);
		quest::setglobal("obzoneopen",2,7,"F");
		quest::setglobal("buteast",2,7,"F"); #keep extra shuttles from spawning
		quest::signalwith(68233,1); 
		}
	if ($timer == 9 && $zonetime == 2010) { 
		quest::stoptimer($timer);
		quest::settimer(10,3);
		quest::spawn(68228,224,0,3683,1611.7,-13);
		quest::npcrace(127);
		quest::setglobal("obzoneopen",2,7,"F");
		quest::setglobal("buteast",2,7,"F"); #keeps extra shuttles from spawning
		quest::signalwith(68233,2);
		}
	if ($timer == 9 && $zonetime == 900) { #boat leaves dock at this time
		quest::stoptimer($timer);
		quest::settimer(10,3);
		quest::setglobal("bozoneopen",1,7,"F"); #open zone so players can zone to oot
		}
	if ($timer == 9 && $zonetime == 2100) { #boat leaves dock at this time
		quest::stoptimer($timer);
		quest::settimer(10,3);
		quest::setglobal("bozoneopen",1,7,"F"); #open zone so players can zone to oot
		}
	if ($timer == 9 && $zonetime == 0930) { #boat spawns in oot
		quest::stoptimer($timer);
		quest::settimer(10,3);
		quest::setglobal("bozoneopen",2,7,"F"); #close zone to players still in butcher
		}
	if ($timer == 9 && $zonetime == 2130) { #boat spawns in oot
		quest::stoptimer($timer);
		quest::settimer(10,3);
		quest::setglobal("bozoneopen",2,7,"F"); close zone to players still in butcher
		}
		
	if ($timer == 10) {
		quest::stoptimer($timer);
		quest::settimer(9,1);
		}
	
	
	
			
}

Sirens Bane


SirensBane.pl

Code:
sub EVENT_SPAWN {
$x = $npc->GetX();
$y = $npc->GetY();
#Set proximity
quest::set_proximity($x - 40,$x + 40,$y - 40,$y + 40);		
}

sub EVENT_EXIT {
	quest::delglobal("boatrider");
	quest::FlyMode(0);
}

sub EVENT_SIGNAL {
	if ($signal == 1) {
		quest::depop();
		}
}
Player

player.pl

Code:
sub EVENT_ENTERZONE {

	if ($qglobals{"boatrider"} == 1) {
	
		quest::FlyMode(2);
		}
	}
4. Set up your grids.

Create new grids with Wander Type of One Way and Pause Type of Full

Ocean of Tears West to East
x y z h pause
10239 1272 -42 129 0
10014 -636 -42 -1 0
7500 -1000 -42 -1 0
7450.82 -2090.26 -42 128 30
7357 -2644 -42 -1 0
2612.25 -1756.4 -42 -1 0
1152.41 -701.18 -42 -1 0
-6000 -200 -42 -1 0
-8179.47 204.64 -42 -1 0
-9196.82 183 -42 192 30
-9996.37 190.36 -42 -1 0
-10258.1 302.68 -42 -1 0

Ocean of Tears East to West

-10258.1 302.68 -42 64 0
-9996.37 190.36 -42 -1 0
-9196.82 183 -42 64 30
-8179.47 204.64 -42 -1 0
-6000 -200 -42 -1 0
1152.41 -701.18 -42 -1 0
2612.25 -1756.4 -42 -1 0
7357 -2644 -42 -1 0
7450.82 -2090.26 -42 255 30
7500 -1000 -42 -1 0
10014 -636 -42 -1 0
10239 1272 -42 -1 0

These grids will take a ship at speed 3.8566 approximately 4 hours and 25 game minutes to cross from zone in to zone out.

Butcher
1 3683 1611.7 -13 193 63
2 3275.9 1528.6 -13 -1 0
3 3279.6 1353.4 -13 0 63
4 3275.9 1528.6 -13 -1 0
5 3683 1611.7 -13 -1 0

Freeport
1 -2090 -38 -76 64 45
2 -1550 -38 -76 -1 0
3 -980 -38 -76 192 66
4 -1550 -38 -76 -1 0
5 -2098 -38 -76 -1 0


That will make your ships cycle. There are a few bugs yet to work out. When a ship is up in a zone and all players leave the zone, the ship seems to stop. If players return before the shutdown delay kills the zone, the ship will start moving again but it will not be on schedule. I need to write a script to recognize this and depop them. My pre-edit post had an attempt at this, but it was messed up and shut down spawns and zone lines in ways I had not predicted.

I also need to write a script that will check to see if a boat should be up but never spawned because the zone was empty. This script will figure out where the boat should be and where the next logical spawn location is, wait for that time, spawn the boat on a different truncated grid.

I will post those when I get them tested.

Last edited by Raghnar; 11-20-2017 at 09:10 PM.. Reason: Timers were messed up, and I forgot to close some ifs properly.
Reply With Quote
  #2  
Old 11-20-2017, 05:35 PM
Raghnar
Fire Beetle
 
Join Date: Feb 2010
Location: San Diego
Posts: 16
Default

Run speed and grid length are important to know if you want your ships to arrive at the zone line at the right time.

It takes some experimentation to get it right, but knowing your grid length is helpful. My oot grids don't double back on themselves so the distance is easy to find by simple geometry of each leg. Lay out your grid from west to east (so if it is an east to west grid start with the last waypoint), don't worry about the z.

x1,y1
x2,y2
x3,y3
x4,y4

The total length of this grid would be the sum of the length of the hypotenuses of right triangles each pair of waypoints make:

((SQRT((x1-x2)^2 + (y1-y2)^2)) + (SQRT((x2-x3)^2 + (y2-y3)^2)) + (SQRT((x3-x4)^2 + (y3-y4)^2)))

If the grid doubles back on itself or has legs with no x offset (direct north or south track), then it becomes more difficult but not impossible. But if you made it this far you can figure out how to get those lengths on your own.

So in my grid I had a total length of 24231.42 units. I had two pauses of 30, one at each island stop. Using that data I wanted to figure out the exact run speed the ship needed to get from spawn in at 3:30 to zone out at NLT 7:55. So the total travel time of 265 game minutes (4 hours 25 minutes). I found that with the 60 ticks of pause the speed could be determined by applying a constant of 23.7098 in the time distance formula. So if I divided the total distance by my time constant, and then divided that by the desired number of minutes I got 3.856604. And indeed setting my ship run speed to 3.856 worked and my ship transit across oot took exactly 265 game minutes.

Changing you island wait times might cause that constant to shift, not sure. I derived it by dividing my grid length by the original run speed of 3.5 times the transit time of 292 game minutes at run speed 3.5.

Last edited by Raghnar; 11-20-2017 at 09:09 PM.. Reason: Island stops were only 30 seconds each.
Reply With Quote
  #3  
Old 11-20-2017, 08:06 PM
Raghnar
Fire Beetle
 
Join Date: Feb 2010
Location: San Diego
Posts: 16
Default

My timers were boogered up because of syntax. I will edit and correct after a bit more testing.
Reply With Quote
  #4  
Old 11-25-2017, 09:21 PM
Thalix
Sarnak
 
Join Date: Sep 2016
Posts: 70
Default

Great work! Really cool, thank you! Please post your updated code if you are done.
Reply With Quote
  #5  
Old 11-25-2017, 10:41 PM
Raghnar
Fire Beetle
 
Join Date: Feb 2010
Location: San Diego
Posts: 16
Default

Just working on the last two scripts.

1. Script that ship uses to check its own position vs. time in the case a player enters a previously empty zone that had a ship stuck in it. I have this script working, but am trying to decide if I want to add more than just 3 points on the grid to check just so a player does not log in, see ship, run out to it with lev on to ride only to have it depop under them and respawn half way across map. So I am currently sitting on islands to see how far away I can see the ships.

2. The second script, should be the easiest, and that checks to see if a ship is NOT up when it should be, and spawn it where it should be at. It will reuse some of the script from the reposition script that already works, just trying to figure out the most efficient way of checking for the ships existence.

Also there are a couple syntax errors still up in the scripts that I already posted, I will repost those at some point since I can no longer edit the original.
Reply With Quote
  #6  
Old 01-10-2021, 04:02 AM
Havas Nukes
Fire Beetle
 
Join Date: Jan 2021
Posts: 3
Default

Where you at with it ?
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:59 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3