Implementing: Discovery/POIs

EQ2Emulator Development forum.

Moderator: Team Members

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Implementing: Discovery/POIs

Post by John Adams » Wed Oct 19, 2011 1:07 pm

Scat (or anyone who knows C++),

I've got the basics wired up for hitting a location that awards "Discovery" XP, whistles and bells. Now, I need a place to store already discovered locations. Before I get into the DB side (cuz I can manage that), I'd like to ask you of the best way to handle it in code.

I was thinking this... When world starts, it reads from `locations` any loc that has discovery = 1, since not all locations will award discovery pts. This will keep the list smaller, perhaps. I would need a struct to hold that data:

Code: Select all

struct DiscoPOIs {
  int32 location_id;
}
Then, at login, a players info loads, including details about their POI discoveries. For examples sake, let's make it a table "character_discovery", with an id, char_id, and location_id values.

Code: Select all

struct PlayerPOIs {
  int32 char_id;
  map<int32, bool>;
}
(I know that last struct is wrong, that's why I am posting this message)


Should I use a map<char_id, map<location_id, bool> > so we can quickly iterate through a specific players list when they enter a new location?

If they haven't discovered it, then discover it, add it to the map<>, flag it for player data update, and boom, done.

If they have discovered it, simply show the location popup msg like normal.

I'd like some help getting the >best way possible< to implement this, regardless of what decision i make on the DB side how to store locs.

My two options are a character_history (or something) table with the discovery location ID in it. Or, a blob value in the character_details record that holds each discovery ID in an array fashion (1|2|265|2030) etc


Thoughts?

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Wed Oct 19, 2011 9:57 pm

Can't we just have an xref table for charcacter_id and location_id? If it exists then obviously they've visited it; if not then they haven't.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Thu Oct 20, 2011 10:52 am

John Adams wrote:For examples sake, let's make it a table "character_discovery", with an id, char_id, and location_id values.
my question isn't about storage. it's about how to best handle checks for already-discovered POIs in code.

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Thu Oct 20, 2011 8:57 pm

You could create a global list that you have to manage like you mentioned, or have a list that each player carries around. Maybe having a list of locations for each player in player.cpp would be best.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Fri Oct 21, 2011 7:54 am

Yes, that is precisely what I wanted to do. So again, if it's best, how? I have never added this kinda thing to emu, so I am not sure where to begin. I'll work on it this weekend just to finish this system up. Figure with what i learn here, I can finally finish LoginEquipUpdates, too. map<of a<map>> thingy.

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Fri Oct 21, 2011 4:12 pm

Well if you do it inside of players.cpp I think the best bet would be to create a map of vectors. So:

map<zone_id, vector<Location*> >. (The space between the >> is important since >> is an operator in C++) Where the main key is a zone id, and each zone id has a list of locations you can run through. Encapsulate that all in a class (this is a C++ afterall!) called"PlayerLocations" or something, where each player has its own instance.

The reason why groups, IRC, and such systems are global maps of character IDs are because they client and player object get destroyed and re-loaded every time a client zones. So for locations, quests, etc, this is fine.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Fri Oct 21, 2011 4:15 pm

Hmm, if it is zone_id <Location>, do you mean <Location> is an array of <char_id, location_id>? I am not seeing how to link a player's discovered location to a new one he just found in a zone. Sorry, you know maps, lists, and vectors are one of my weaker points ;)

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Fri Oct 21, 2011 4:30 pm

Nah. Each character will have an instance of class (because you're inside of player.cpp), so there's no reason to store a char_id with it. If you access the character, you already know the character ID.

Each character will have a map of zone IDs. Each zone ID will reference a list of Locations that are in that zone.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Sat Oct 22, 2011 3:09 pm

k, either we're talking about two entirely different things, or I am completely missing the point (likely).
  • I am a character.
    I enter a location w/Disco = 1.
    I get XP and a dingy thing.
    World records that location_id in a record in my character tables.
    I wander off elsewhere.
    Eventually, I wander back through the same location.
    But this time I do not get a dingy thing nor XP, just a normal location popup
    because the world now knows that char_id has already discovered location_id.
I do not see how making each character carry around a list of all zones (800), all location_id's (1,000's) is going to accomplish this. Wouldn't it be simpler for World to just check the current character's known location_id *only*, because there will only be 1 id (PK) per location.

Or are you trying to limit the iteration to only the "Players <current zone <discovered Locations> >"? So it's only looking at, say, ZoneID 470's locations...

What am I missing? Confused.

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Sun Oct 23, 2011 12:45 am

Are all location_ids unique (outside of their zone)? If so then we can definitely do it purely off location_id. I was thinking that only the locations you discovered would get added to the map<zone_id, List of locations>. So you wouldn't store all of them right away...only the ones you found. They are 4 byte and 8 byte integers so it's not so much memory it'd be taking up. Or maybe I'm not thinking of it the right way?

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Sun Oct 23, 2011 9:04 am

Yes. `locations`.`id` is the unique id, globally.

In my mind, I see this no different than `quests` -> `character_quests`. How does the world currently know you (the player) have already done QuestID 1, and knows to not offer it again? Realizing this, maybe I should inspect the quest code...

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Sun Oct 23, 2011 11:19 am

It simply looks through a Quest list that the player has. If it has the Quest ID, and it's marked as completed, then it's completed. I think locations should work the same way. If the player has a location ID in it's list of locations, then they've discovered it.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Sun Oct 23, 2011 2:30 pm

Allow me to welcome you to what I've been saying since the start of this conversation. Glad to see we agree, as usual.

Now.

How the hell do I do it just like this? Which was the original question ;) Copy how Quests are done, tweaked slightly? I'd rather not tap the DB each loc, if that's how Quests does it. Time to modernize. Go iter. Very sexy.

User avatar
Scatman
Retired
Posts: 1688
Joined: Wed Apr 16, 2008 5:44 am
EQ2Emu Server: Scatman's Word
Characters: Scatman
Location: New Jersey

Re: Implementing: Discovery/POIs

Post by Scatman » Sun Oct 23, 2011 2:58 pm

I understand we agree, so maybe I am not explaining myself thoroughly enough. First of all, I wouldn't copy how quests are done because it is a much bigger and complex system. The only thing we need to store here is simply whether or not a character has visited a location_id, right? So you could do this one of two ways.

1) Each character will contain a map, where each key in the map is a zone_id, which references a list of location_ids, as I mentioned earlier.
So it's look like this: map<zone_id, vector<location_id> >. This would allow you to have a quicker look up of locations since you're only looking within a certain zone. So let's say I'm in Queen's Colony (zone_id=253). I enter location_id 6, so now we need to check if I've been there. Well now I can check the map to see if the key for zone_id=253. If there is no key yet, then we are done right there, since I have not discovered any locations in this zone yet. So now we create a vector<location_id>, add 6 to the vector, add the vector to the map at key 253, and save the location_id to the database.

If the map does contain a key of 253, then we iterate through the vector of location_ids at key=253 of the map. If the location_id is found, then we're done. If not, then we add it to the list and save it to the database.

2) Simply just create a vector<location_id> that each player has. Since location_id is unique, you can just iterate through one list.

I'm not sure how many locations there are in EQ2. And since it can be customized, there potentially could be lots. That's why #1 might be best, since we do less processing on the server side. But this will use a little bit more memory. So it's a performance vs. memory size + a bit more complexity trade off.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Implementing: Discovery/POIs

Post by John Adams » Sun Oct 23, 2011 9:47 pm

Perfect :)

Why didn't you just say so in the first place? :mrgreen:

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests