Persistent minimaps problem

Hello! We are using this script for the Events “Area OnEnter/OnExit” and “Module OnPlayerRest”:

[code] const string MINIMAP_DB = “minimap_db”;
#include “x0_i0_stringlib”
void PersistentMinimap()
{
object oArea = OBJECT_SELF;
object oPC = GetEnteringObject();

if(oPC == OBJECT_INVALID)
    oPC = GetExitingObject();

if(oPC == OBJECT_INVALID)
{
    oPC = GetLastPCRested();
    oArea = GetArea(oPC);
}

if(!GetIsPC(oPC))
    return;

int iAreaHeight = GetAreaSize(AREA_HEIGHT, oArea);
int iAreaWidth = GetAreaSize(AREA_WIDTH, oArea);
string sAreaResRef = GetResRef(oArea);
string sMap = GetCampaignString(MINIMAP_DB, sAreaResRef, oPC);
string sX;
string sY;
struct sStringTokenizer stTok = GetStringTokenizer(sMap, ",");
WriteTimestampedLogEntry(GetName(oArea));
WriteTimestampedLogEntry("Loading: " +sMap);
while(HasMoreTokens(stTok))
{
    stTok = AdvanceToNextToken(stTok);
    sX = GetNextToken(stTok);
    stTok = AdvanceToNextToken(stTok);
    sY = GetNextToken(stTok);
    SetTileExplored(oPC, oArea, StringToInt(sX), StringToInt(sY), 1);

    //SendMessageToPC(oPC, "explored sX: " + sX + " / sY: " + sY);
}

sMap = "";

int x;
int y;

for(x = 0; x < iAreaWidth; x++)
    for (y = 0; y < iAreaHeight; y++)
        if(GetTileExplored(oPC, oArea, x, y))
            sMap += IntToString(x) + "," + IntToString(y) + ",";

WriteTimestampedLogEntry(GetName(oArea));
WriteTimestampedLogEntry("Saving: " +sMap);
SetCampaignString(MINIMAP_DB, sAreaResRef, sMap, oPC);

} [/code]

When the server crash or is closed and we restart it, only some explored tiles are loaded, while others look unexplored (black). Any idea?
Thanks a lot!

Any idea? :frowning:

I’d probably have the oPC call to a valid object be determined by the currently running event if you do intend to use the same script for 3 different events. You can get this with GetCurrentlyRunningEvent.

Once that’s solved if the issue doesn’t work the other issue is Get/SetCampaignString might not work with all PCs due to the limitation of oPC. Possibly migrating to something like sqlocals would work better, an example on a PC BIC: https://github.com/Finaldeath/nwscript_utility_scripts/blob/master/sql/utl_i_sqlplayer.nss or on a given campaign DB but using UUID (so it works even if the client crashes/leaves): https://github.com/Finaldeath/nwscript_utility_scripts/blob/master/sql/utl_i_sqluuid.nss

The other thing is what does your debug say if it is sometimes working and sometimes not? What is the string sMap showing for the non-working areas versus the working ones? Is the client losing data because they are leaving the module or some other reason?

If you make it to the vault discord it might be easier to do a bit of back and forth testing and debugging there because other than the issues above I can’t see much wrong.

1 Like
object oArea = OBJECT_SELF;
object oPC = GetEnteringObject();

if(oPC == OBJECT_INVALID)
    oPC = GetExitingObject();

if(oPC == OBJECT_INVALID)
{
    oPC = GetLastPCRested();
    oArea = GetArea(oPC);
}

This is the issue. It’ll always run for whatever object was last set for GetEnteringObject() It’ll never* be OBJECT_INVALID.

Either use GetCurrentlyRunningEvent() as @Jasperre suggested or give each event its own script.

*99,99999999% of the time

2 Likes

Thanks a lot guys! We will make some test and be back with a feedback :slight_smile:

Hello!

I’m Noler and I work with MillaJ in this project, first of all share my gratitute too for your help in this issue.

I have been testing the GetCurrentlyRunningEvent function today. I used it and split the script according the event called since the script saves the string on the events OnExit and OnPlayerRest events, and loads it on the OnEnter Event. In the original design it was calling the loading and saving both at the same time, what ever the event was, and I though that could cause troubles too.

Looks like this:

void PersistentMinimap()
{
    object oArea = OBJECT_SELF;
    int iEvent = GetCurrentlyRunningEvent();
    int iAreaHeight = GetAreaSize(AREA_HEIGHT, oArea);
    int iAreaWidth = GetAreaSize(AREA_WIDTH, oArea);
    string sAreaResRef = GetResRef(oArea);

    string sMap;
    object oPC;

    if(iEvent == EVENT_SCRIPT_AREA_ON_ENTER)
    {
        oPC = GetEnteringObject();
        if(!GetIsPC(oPC)) return;
        WriteTimestampedLogEntry("Entering an Area.");
        WriteTimestampedLogEntry("The current event is: " +IntToString(iEvent));

        sMap = GetCampaignString(MINIMAP_DB, sAreaResRef, oPC);
        string sX;
        string sY;
        struct sStringTokenizer stTok = GetStringTokenizer(sMap, ",");
        WriteTimestampedLogEntry(GetName(oArea));
        WriteTimestampedLogEntry("Loading: " +sMap);
        while(HasMoreTokens(stTok))
        {
            stTok = AdvanceToNextToken(stTok);
            sX = GetNextToken(stTok);
            stTok = AdvanceToNextToken(stTok);
            sY = GetNextToken(stTok);
            SetTileExplored(oPC, oArea, StringToInt(sX), StringToInt(sY), 1);

            //SendMessageToPC(oPC, "explored sX: " + sX + " / sY: " + sY);
        }
    }
    else if( iEvent == EVENT_SCRIPT_AREA_ON_EXIT)
    {
        WriteTimestampedLogEntry("The current event is: " +IntToString(iEvent));
        oPC = GetExitingObject();
        if(!GetIsPC(oPC)) return;
        WriteTimestampedLogEntry("Leaving an Area.");
        sMap = "";
        int x;
        int y;

        for(x = 0; x < iAreaWidth; x++)
            for (y = 0; y < iAreaHeight; y++)
                if(GetTileExplored(oPC, oArea, x, y))
                    sMap += IntToString(x) + "," + IntToString(y) + ",";

        WriteTimestampedLogEntry(GetName(oArea));
        WriteTimestampedLogEntry("Saving: " +sMap);
        SetCampaignString(MINIMAP_DB, sAreaResRef, sMap, oPC);
    }
    else if(iEvent == EVENT_SCRIPT_MODULE_ON_PLAYER_REST)
    {
        WriteTimestampedLogEntry("The current event is: " +IntToString(iEvent));
        oPC = GetLastPCRested();
        if(!GetIsPC(oPC)) return;
        oArea = GetArea(oPC);
        WriteTimestampedLogEntry("Resting");
        sMap = "";
        int x;
        int y;

        for(x = 0; x < iAreaWidth; x++)
            for (y = 0; y < iAreaHeight; y++)
                if(GetTileExplored(oPC, oArea, x, y))
                    sMap += IntToString(x) + "," + IntToString(y) + ",";

        WriteTimestampedLogEntry(GetName(oArea));
        WriteTimestampedLogEntry("Saving: " +sMap);
        SetCampaignString(MINIMAP_DB, sAreaResRef, sMap, oPC);
    }

}

With that, I did many test and the OnExit and OnEnter events seems to load and save the minimap perfectly. Tried many times to explore areas and restart the server, got minimap explored according it was before the restart. Seems to be an issue in the OnPlayerRest event tho. The script recognises the player resting event, but then saves the string variable “sMap” empty. On the rest event it gets the area ok too.

These are the messages of the logs, in case they help in anything:

OnEnter Event:

[Thu Nov 11 23:32:04] Entering an Area.
[Thu Nov 11 23:32:04] The current event is: 4002
[Thu Nov 11 23:32:04] Dive - North Woods Of The Golden City
[Thu Nov 11 23:32:04] Loading: 2,0,2,1,2,2,2,3,2,4,2,5,2,8,2,9,2,10,2,11,3,0,3,1,3,2,3,3,3,4,3,5,3,8,3,9,3,10,3,11,4,0,4,1,4,2,4,3,4,4,4,5,4,8,4,9,4,10,4,11,5,2,5,3,5,4,5,5,6,2,6,3,6,4,6,5,7,3,7,4,7,5,8,3,8,4,8,5,9,3,9,4,9,5,

OnExit Event:

[Thu Nov 11 23:31:57] The current event is: 4003
[Thu Nov 11 23:31:57] Leaving an Area.
[Thu Nov 11 23:31:57] Dive - North Woods Of The Golden City
[Thu Nov 11 23:31:57] Saving: 2,0,2,1,2,2,2,3,2,4,2,5,2,8,2,9,2,10,2,11,3,0,3,1,3,2,3,3,3,4,3,5,3,8,3,9,3,10,3,11,4,0,4,1,4,2,4,3,4,4,4,5,4,8,4,9,4,10,4,11,5,2,5,3,5,4,5,5,6,2,6,3,6,4,6,5,7,3,7,4,7,5,8,3,8,4,8,5,9,3,9,4,9,5,

OnPlayerRest Event:

[Thu Nov 11 23:31:13] The current event is: 3012
[Thu Nov 11 23:31:13] Resting
[Thu Nov 11 23:31:13] Dive - North Woods Of The Golden City
[Thu Nov 11 23:31:13] Saving: 
[Thu Nov 11 23:31:42] The current event is: 3012
[Thu Nov 11 23:31:42] Resting
[Thu Nov 11 23:31:42] Dive - North Woods Of The Golden City
[Thu Nov 11 23:31:42] Saving: 

Note that the rest event called it twice, at the begining and at the end, but both saved an empty string. Any thoughts on why the Rest event doesn’t work? Am I missing something?

Thanks ^^

Edit: Ok after posting this I realised that on the rest event the object oArea is the module, so it can’t check the width and height of the area… I need to update those values in that part of the script >.< gona test.

Edit 2: Yes that was the issue, rest event not saving the string properly:

[Thu Nov 11 23:53:52] The current event is: 3012
[Thu Nov 11 23:53:52] Resting
[Thu Nov 11 23:53:52] Dive - North Woods Of The Golden City
[Thu Nov 11 23:53:52] Saving: 0,3,0,4,0,5,1,3,1,4,1,5,1,6,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,11,3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,3,10,3,11,4,0,4,1,4,2,4,3,4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11,5,2,5,3,5,4,5,5,6,2,6,3,6,4,6,5,7,3,7,4,7,5,8,3,8,4,8,5,9,3,9,4,9,5,

Need further test with multple players, atm I only tested alone. I think I got some black tiles while loading but wasnt sure… Will continue testing tomorrow.

Thanks everyone!