Author Topic: Database question: Getting oPlayer?  (Read 740 times)

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Database question: Getting oPlayer?
« on: June 26, 2015, 02:10:50 am »


               

Most of the Bioware database functions like SetCampaignInt() allow an object oPlayer parameter to be passed. That's handy, as storing information specific to a player is otherwise difficult (a player name can be up to 255 characters long and the variable names for DB variables are limited to 32 characters).


 


But, the lexicon has the following warning



Not a bug, but a caveat: The database uses information about the player to store PC specific information. Thus, you can't use the PC as the oPlayer parameter in the database functions. This one is a little harder to work around. One thing you could perhaps do is ignore the oPlayer parameter, and then construct a variable name based on some of the info stored about the player OnClientEnter (see the workaround).



And here is the mentioned workaround



//Workaround for the caveat above

void main()
{
    object oPC=GetEnteringObject();
    string sPlayerName=GetPCPlayerName(oPC);
    string sIP=GetPCIPAddress(oPC);
    string sKey=GetPCPublicCDKey(oPC);
    SetLocalString(oPC, "player_name", sPlayerName);
    SetLocalString(oPC, "player_ip", sIP);
    SetLocalString(oPC, "player_cdkey", sKey);
}

So, the player name and some other strings are saved on the PC object and would be available during the OnClientLeave event. But, of course, the player name is not the same as the player object and I don't know how to get the player object to use at that time. So, I am not sure how to pass the player object to functions during the OnClientExit event. And, in fact, I don't even really know how to get the actual player object (as opposed to the PC object) at any point; all I can get is the player name using GetPCPlayerName().


 


Now, the obvious thing I looked at was how does Bioware use the oPlayer parameter. But, despite the "Thus, you can't use the PC as the oPlayer parameter in the database functions." warning above, it seems they are happily just passing in the PC object for that. (For example, look at how SetCampaignDBInt() is implemented in x0_i0_campaign.)  I assume that all the calls to those functions that specify oPlayer are actually just passing the PC object. Or, at least my quick search didn't find any calls that didn't do that. The actual player name is stored in the DB files, so the game is presumably grabbing the player info from the PC object if the DB write is made while the player is still logged.


 


So, what happens when this is tried during OnClientLeave? As best I can tell, no player information is stored, the same as if one had not supplied anything for that parameter.


 


Is there a nice way to save player-specific information to the Bioware DB during OnClientLeave? (Keeping in mind that the player name can be very long, so just adding it to the variable name is a non-starter.) Right now I am contemplating a hash to deal with this, but that is a mess and slows down an already slow operation.



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Database question: Getting oPlayer?
« Reply #1 on: June 26, 2015, 01:32:07 pm »


               

I don't believe there is a "player" object. There is just the PC object and some information about the player that you showed examples of.  If you want to use it on client leave you will need to ignore the oPlayer argument (probably in all your calls) and make up a naming scheme since the getPLayerXX routines don't work there.


 


As an aside, have you considered NWNX and MySQL instead of the bioware DB routines?



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Database question: Getting oPlayer?
« Reply #2 on: June 26, 2015, 01:39:38 pm »


               

Btw, after re-reading the lexicon page, it looks like that caveat is poorly worded and incomplete. From the context it seems to be trying to say "you can't use the PC as the oPlayer argument in the onClientLeave handler".  That's really what the illustrated workaround is addressing.



               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Database question: Getting oPlayer?
« Reply #3 on: June 26, 2015, 04:28:42 pm »


               


Btw, after re-reading the lexicon page, it looks like that caveat is poorly worded and incomplete. From the context it seems to be trying to say "you can't use the PC as the oPlayer argument in the onClientLeave handler".  That's really what the illustrated workaround is addressing.




I know that's what the workaround was addressing. (It really doesn't serve any other purpose.) I agree that the wording isn't clear, particularly since it implies that there is decent workaround to the issue mentioned of not using oPC as oPlayer during onClientLeave. Since player names can be way, way longer than the DB variable names, using CD keys is complicated when players can have more than one attached to the same player name, and IPs are too transient to be useful, there isn't an especially elegant workaround that I am seeing.


 


Unfortunately, I was hoping that my little project would work for a PW that hasn't shown much inclination to adding MySQL or NWNX. In all probability, I will end up using some marginal scheme to map player names to shorter strings and use those in the calls to the SetCampaign*() functions without supplying oPlayer.



               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Database question: Getting oPlayer?
« Reply #4 on: June 26, 2015, 08:11:07 pm »


               

Im using skin as an PC ID. Each new player gets different ID, last used ID is stored it database (in nwnx, but you can use bioware db for this simple task of course), incrementing by 1 each time.


 


Of course, skin is unsafe, you would need the fixes from my patch or to run without ELC and ILR to make it work otherwise player gonna lose skin when logging in.


 


Alternatively you can use any undroppable item in inventory, miscelanious small is perfect for that.


It can be done even without database if you make tag to be 8-16 random characters from alphabet, the chance two players had ever same id is basically a zero anyway.



               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Database question: Getting oPlayer?
« Reply #5 on: June 27, 2015, 04:57:53 am »


               

Shadooow, that's pretty much what I am planning on at the moment. I will work out the mapping system and then include a STORE_DB_INDEX_ON_PERSISTENT_ITEM switch and then a STORE_DB_INDEX_ITEM_TAG string that can be set to the tag of the player token or whatever. A short addition to onClientEnter will do the bookkeeping.


 


The map should cover the case where no persistent item is present and hopefully be rarely used, as it will be slower.