Zone instancing
(Sorry, I would have put this in the old thread but I did not want to confuse anyone on how the code worked)
This code basically enables zone instancing Select a zone you want to instance Set that zone's insttype to 1 Select a character you want to access that zone Set that character's instZflagNum to a number greater than 1000 instZOrgID to the zoneID of the zone you picked rinse and repeat with second character changing the instZflagNum (if you want them to go to a different zone) Zone characters into the zone you picked. K, here is my example I want to instance blackburrow (has a zoneid of 17 I set blackburrow's insttype to 1 in the zone table I want my toon MonkGod to access an instance of blackburrow I set MonkGod's instZflagNum to 1001 instZOrgID to 17 I then set the instZflagnum and insZordID on Aries, my other character. changing the instZflagNum to 1002 Setting instZOrgID to 17 All that would be required to get this fully functional is a quest command that sets a character’s InstZflagNum and instZOrgID. I have a method for doing this but don’t know where to put the code. Anyone willing to help write it please let me know. Anyhow here are the required changes. This was done against 1129 using PEQ database. Please let me know what bugs you notice. Required SQL Code:
ALTER TABLE `zone` ADD column `insttype` tinyint (1) zerofill unsigned NOT NULL default '0'; Line 498 insert Code:
ztz->requested_zone_id = database.GetInstZoneID(ztz->requested_zone_id, ztz->name); Code:
int server_id; Code:
zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name); World\Client.cpp Line 644 insert Code:
zoneID = database.GetInstZoneID(zoneID, GetCharName()); Line 122 Code:
//Checks if the zone can be instanced, character has a instance flag, and Line 201 insert Code:
int32 GetCharInstFlagNum(int32 charID); Line 1173 Code:
const char* Database::GetZoneName(int32 zoneID, bool ErrorUnknown) { Code:
int32 Database::GetDfltInstZFlag(){ Append to the end Code:
int32 ZoneDatabase::GetInstType(int32 zoneid) { Code:
#include <string> Zone\zonedb.h line 194 change const char* zone_name to int32 zoneid Code:
bool PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay = 0); At the end of Zone Related around line 181 Code:
int32 GetInstType(int32 zoneid); Zone.cpp Line 1146 change short_name to zoneid Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list, delay)) Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list)) Zone.cpp Line 772 change short_name to zoneid Code:
else if (tmp == 0) { Code:
zone->ResetAuth(); Zone\spawn2.cpp line 226 Code:
bool ZoneDatabase::PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay) { |
Definitely some interesting stuff! I will have to check this out more when I get a bit more time. I think this code could definitely be useful at some point. I don't want you to feel like your submissions are getting ignored though. If this can be finalized and get the quest commands added, this could actually be some really useful code. With limited resources for creating content, some of the more popular custom servers may have bottlenecks in some zones that are very popular. Maybe adding 1 instance during peak times, or when needed, would help balance out players and content. So, a small server with limited content could still be enjoyed by many.
Anyway, it is definitely something worth looking into more. I was wondering why you named the setting "instZOrgID" instead of something like "instZoneID". I am all for anything that is clear and as simple as possible. So, naming settings after what they are used to set is IMO the best way. |
Thank you for the reply Trevius.
If I get some time this weekend, after work and college, I will knock out some of the quest code to use for setting the instance flags and such. After looking at the questmgr.cpp it does not look like it would be too bad especially since a kind soul put instructions at the top. The instZOrgID actually stands for Instance Zone’s Original Zone ID. It is used in the code to track what zone the instZflagNum (later used as the instance zone’s ID) belongs too. I couldn’t think of a better name for instZOrgID so I went with it but if we can come up with something a little more intuitive adjusting the code would not be difficult. |
Please note this code is not tested, I have no experience writing quests so I am hoping someone with quest writing experience will test it for me.
This code adds a quest function that will set a character's instance flag. Sending that character to an instance the next time they zone into the zone of your choice. It requires two bits of information. The character's ID and the zoneID of the zone you want instanced. If there are any questions please let me know. Anyhow here is the code. Zone\perlparser.cpp Near Line 1759 insert Code:
XS(XS__setindinstflag); Around Line 1899 insert Code:
newXS(strcpy(buf, "setindinstflag"), XS__setindinstflag, file); Around line 150 insert Code:
void setindinstflag(int32 charID, int32 orgZoneID); At the end insert Code:
void QuestManager::setindinstflag(int32 charID, int32 orgZoneID) At the end insert Code:
void Database::setOneCharInstFlag(int32 charID, int32 orgZoneID) At the end insert Code:
void setOneCharInstFlag(int32 charID, int32 orgZoneID); |
Here is the code for setting a group’s instance flags through quests. This will allow the whole group to zone into the same instance.
Please note, I have no experience writing quests so this is untested. I appreciate any feedback. zone\perlparser.cpp Insert at the end around line 1914 Code:
newXS(strcpy(buf, "setgroupinstflag"), XS__setgroupinstflag, file); insert around line 1758 Code:
XS(XS__setgroupinstflag); Insert around line 151 Code:
void setgroupinstflag(int32 charID, int32 orgZoneID); Insert at the end Code:
void QuestManager::setgroupinstflag(int32 charID, int32 orgZoneID) Insert at the end Code:
void Database::setGroupInstFlagNum(int32 charID, int32 orgZoneID) Insert at the end Code:
void setGroupInstFlagNum(int32 charID, int32 orgZoneID); |
Some changes to the quest code plus a way to manually set a characters instflag.
Syntax for quest functions setinstflag(charID, originalZoneID, type) charID = character ID of the character requesting flag originalZoneID = zoneID of the zone you want instanced (blackburrow would be 17) type = 0 will flag only the requesting character type = 1 will flag the requesting character’s group including that character type = 2 will flag the requesting character’s raid including that character setinstflagmanually(charID, originalZoneID, instFlag) charID = character ID of the character requesting flag originalZoneID = zoneID of the zone you want instanced (blackburrow would be 17) instFlag = the instance flag you want to give the requesting character. Pick a number between 1000 and 1999. Try not to use the same one for different quests. The setinstflagmanually will allow you to send characters to the same instance zone even if they are not in the same group or raid. SQL changes Code:
INSERT INTO variables VALUES ('curInstFlagNum', 2000, 'Determines what instance flag will be handed out next', '2008-09-05 04:46:47'); Code changes Get rid of my previous quest code. I combined the single, group, and raid flags into one quest function and added a way to manually set a character’s instance flag. perparser.cpp insert around line 1758 Code:
XS(XS__setinstflag); Perlparser.cpp Insert at the end around line 1916 (becomes line 1916 after previous insert of code into perparser.cpp) Code:
newXS(strcpy(buf, "setinstflag"), XS__setinstflag, file); questmgr.h Insert around line 151 Code:
void setinstflag(int32 charID, int32 orgZoneID, int type); Insert at the end Code:
void QuestManager::setinstflag(int32 charID, int32 orgZoneID, int type) Insert at the end Code:
void Database::setOneCharInstFlag(int32 charID, int32 orgZoneID) database.h Insert at the end Code:
void setOneCharInstFlag(int32 charID, int32 orgZoneID); |
I haven't had a lot of time to play with this, but it looks like the group and raid types crash the zone when used. This happens whether you are in a group/raid or not. Here is the output:
Code:
#0 0x08155ec3 in Database::setGroupInstFlagNum (this=0x836ac24, charID=22, in my source. The raid dump is the same, just with the raid code. If you want that, just let me know. Another small problem, /goto doesn't seem to work in instances. The red text pops telling you who you're going to, but you don't actually move. This may be unrelated to your code, but /goto does indeed work in normal zones. The single player function works perfectly, and the instances themselves from what I can tell work great as well. I had a couple of toons in two instances of the same zone, and the spawns and quests worked great in each instance. No overlapping at all. Very impressive. Now some suggestions, since your system forces instances to be dynamic (static versions of the zone are ignored, and can only be accessed by players without an instance flag) is there anyway that you can add a rule that will allow server ops to keep the instances open for a certain amount of time after the last player left it? If the op sets the rule to 10 minutes, then the zone stays open for 10 minutes after it became empty of players. Also, could raid type 2 be changed to flag group members as well? The idea behind this is so we could just set everything to type 2. If a group comes along that aren't in a raid, they can get flagged with this single function instead of having an extra elsif in the script to check for non-raid groups. Can a variable be added to enable Perl to check if a player is already flagged for an instance? Also, can a new Perl function be added that will delete the flags from a player/group/raid (set both columns to 0?) Finally, I'm not sure how your system handles this, but what happens to players that join a raid/group after they've been flagged? Can it be made so that they inherit those flags? |
I think I figured out where I messed up the group and raid instance flags. Database::setGroupInstFlagNum and Database::setRaidInstFlagNum will need replaced with the ones below.
Can you post, or send me, the quest script you are using to set these? I suck at quest writing so using yours would help me test them. I like the idea of holding the zone open for a set amount of time. Also, I agree there needs to be ways to check if someone is already flagged, remove the flag, and inherit the flag of the group/raid leader. I also want to add a way to shutdown the zone after a certain amount of time (like ldons). The only issue I could see with making the type 2 flag raids or groups is some server admins may want to limit how many people can be in the instance. Though I could make a type 3 that flags both. It might take me a while to figure out why goto is not working in instances. But I will see. Code:
void Database::setGroupInstFlagNum(int32 charID, int32 orgZoneID) Code:
void Database::setRaidInstFlagNum(int32 charID, int32 orgZoneID) |
Actually, why not just make an option to keep all dynamic zones up for X amount of time after the last player leaves? I wouldn't mind having that for my dynamic zones as well :)
|
I'm not going to sticky this one yet, I am still getting a zone crash with the newest code regarding the raid and group types. Could you post a diff to make sure I am not merging incorrectly?
|
I am fairly certainly you are merging it correctly. I just screwed up the code. Here are two I found this afternoon that need changed. Basically I had ‘%i’ when it should be %i
It is kinda hard to see but the %i is surrounded by two ‘ I will try to post a full diff by this weekend. I would do it sooner but work is killing me this week. line 31 inside Database::setGroupInstFlagNum Code:
// Select the character IDs of the characters in the group line 33 inside Database::setRaidInstFlagNum Code:
// Select the character IDs of the characters in the raid One side question though. Please don’t laugh to hard (this is my first time writing a quest) below is what I wrote for a quest to set these instance flags. It does not work. I know the quest::setinstflag($charid,18,0); is causing the problem since the says work. It never sets the flags in the database and just hangs at the setinstflag. I figured out it hangs there by swapping the quest::say and quest::setinstflag places. Any idea where I messed up the script? or is my code that wrong? Code:
sub EVENT_SAY { |
Your quest script is fine. It's your code that you use to call setinstflag that's messed up. I'd put some debug statements in there and try to figure out where it's giving you grief. I've REALLY been wanting to mess around with this but I'm so limited on time right now....
|
Just out of curiosity, why are they int32 variables instead of just int? Could that make a difference when compiling between the different machines? Does it make a difference compiling on the different machines when typecasting an int -> int32?
|
Well I got it working. I will try to post a diff tonight or tomorrow. The quest functions got an overhaul.
Quote:
I think most programming languages view int and int32 as the same thing. However, I took your suggestion and changed most of the int32 to int. Looks better and is easier to read even if it has little to no effect on the code. |
Quote:
Code:
typedef unsigned char int8; Quote:
|
Thanks AndMetal, I honestly didn’t know which method was preferred. Sorry, I don’t have the energy at the moment to switch the int and int32s around. Though I did learn something and now know in the future.
Here is a diff of all the required code. Hopefully I got it all. With this the only required manual database entry is setting the zone insttype to 1. Required SQL Code:
ALTER TABLE `zone` ADD column `insttype` tinyint (1) zerofill unsigned NOT NULL default '0'; Line 498 insert Code:
ztz->requested_zone_id = database.GetInstZoneID(ztz->requested_zone_id, ztz->name); Code:
int server_id; Line 533 insert Code:
zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name); World\Client.cpp Line 644 insert Code:
zoneID = database.GetInstZoneID(zoneID, GetCharName()); Line 122 Code:
//Checks if the zone can be instanced, character has a instance flag, and Line 201 insert Code:
int32 GetCharInstFlagNum(int32 charID); Around Line 1173 Code:
const char* Database::GetZoneName(int32 zoneID, bool ErrorUnknown) { Code:
int32 Database::GetDfltInstZFlag(){ Append to the end Code:
int32 ZoneDatabase::GetInstType(int32 zoneid) { Code:
#include <string> Zone\zonedb.h line 194 change const char* zone_name to int32 zoneid Code:
bool PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay = 0); At the end of Zone Related around line 181 Code:
int32 GetInstType(int32 zoneid); Zone.cpp Line 1146 change short_name to zoneid Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list, delay)) Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list)) Zone.cpp Line 772 change short_name to zoneid Code:
else if (tmp == 0) { Code:
zone->ResetAuth(); Zone\spawn2.cpp line 226 Code:
bool ZoneDatabase::PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay) { Insert at the end around line 1884 Code:
newXS(strcpy(buf, "setinstflag"), XS__setinstflag, file); Zone\perparser.cpp insert around line 1758 Code:
XS(XS__setinstflag); Zone\questmgr.h Insert around line 151 Code:
void setinstflag(int charID, int orgZoneID, int type); Insert at the end Code:
void QuestManager::setinstflag(int charID, int orgZoneID, int type) Code:
sub EVENT_SAY { |
In your questmgr.cpp you might have some leftover debug code.
Code:
say("Got to start of setinstflagmanually"); |
Oops, your right. Good catch.
Zone\questmgr.cpp at the end QuestManager::setinstflagmanually should be Code:
void QuestManager::setinstflagmanually(int charID, int orgZoneID, int instFlag) |
Anyone have a chance over the weekend to test this out? I would like to get this portion tested before I add some other features.
One thing I noticed while testing it on my minilogin server: Using two characters from the same account in an instance causes one to get disconnected when the other zones out of the instance. I think this is related to how the client/emu interact and likely cannot be fixed since Sony intended only one character to be logged in on the same account at a time. Though, I do not know if this problem would occur on a public server. Below are some things I want to implement once this code is tested. Quest function to delete instance flags (reset them to zero) Fix goto command so it works in instances Quest function to get the average level of a group and raid Hold dynamic and instance zones open for a set period of time. There is probably already a short timer in the code that is triggered when a zone becomes empty so I will just need to find it and allow the time to be set from a database entry. I had more but cannot remember them at the moment. |
I didn't actually test the instances (though they worked for me earlier) However, I can confirm all the types flag me properly and don't cause a crash anymore. Nice work!
|
Yep more changes.
This is a fix for setinstflagmanually to allow manual flagging of raids, groups, and individuals. This also offers a way to delete instance flags by sending a orgZoneID of -1 and a instFlag of -1 to the function. Please note if you have already setup quests to use the setinstflagmanually you will need to add a fourth parameter to it. Format for quests - setinstflagmanually(charID, orginalZoneID, instFlag, type) types 0 = individual 1 = group 2 = raid 3 = individual, group, and raid Zone\perlparser.cpp Find XS(XS__setinstflagmanually) replace with below code (line is 1774 on mine but..) Code:
XS(XS__setinstflagmanually); Find void QuestManager::setinstflagmanually and replace with below code (line 1420 on mine) Code:
void QuestManager::setinstflagmanually(int charID, int orgZoneID, int instFlag, int type) Find void setinstflagmanually and replace with below code (line 151 on mine) Code:
void setinstflagmanually(int charID, int orgZoneID, int instFlag, int type); |
Some thoughts…
Code:
//Copies original zones information into a new zone entry replacing the old zoneidnumber with the instflagnum (The shutdowndelay column needs added, I will add it tonight or tomorrow) Also, I am reluctant to enable inheriting of instance flags in groups and raids because it may allow players to circumvent zone limitations. For example, Group zones into an LDoN 1 member drops out of the group but stays in the LDoN The group then invites another character. He/she zones into the LDoN (because he/she now has the flag) Now 7 characters are in the zone when the content was built for 6. To keep players from doing this we would either have to boot them from the instance when they disband or have a hidden NPC check the zone every few minutes for players without the correct instance flag. Any thoughts? Another side note, I may have a fix for the goto command but I need to test it. |
tecnicly speaking on LIVE after you zoned into LDON and someone Lds, camps, crashes etc- you CANNOT invite someone else from outside- the zone should remain LOCKED until adventure expires or forfeit, even if group inside got smaller
|
Fix to include shutdowndelay column in zone copy
zone\zonedb.cpp Find ZoneDatabase::LoadInstZone(int32 target_zone_ID, int32 instFlagNum) Replace Line 17 inside the function (line 1542 for whole file (Rev98 )) Code:
if (RunQuery(query, MakeAnyLenString(&query, "INSERT INTO zone (short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, zoneidnumber, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer) SELECT '%s', file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, %i, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer FROM zone WHERE zoneidnumber =%i", temp2,instFlagNum,target_zone_ID), errbuf, 0, &affected_rows)){ Code:
if (RunQuery(query, MakeAnyLenString(&query, "INSERT INTO zone (short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, zoneidnumber, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer, shutdowndelay) SELECT '%s', file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, %i, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer, shutdowndelay FROM zone WHERE zoneidnumber =%i", temp2,instFlagNum,target_zone_ID), errbuf, 0, &affected_rows)){ ChaosSlayer, I think you are right about the LDoNs. Everyone had to be in the group before the LDoN task was accepted or they could not get into the zone. Though, I think GoD and OoW instances flags could be shared via the share task button. |
Thought I'd add... With the instancing ability we need to add a new check to the /goto <playername> command so it will check the characters_ table and replicate any instance flags on the GM before zoning. That way if someone is stuck in the geometry or bugged death or whatever a GM can zone into that instance and check.
|
Quote:
|
All times are GMT -4. The time now is 09:01 PM. |
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.