logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
NEGATIVE nwnx time?

 
Post new topic   Reply to topic    nwnx.org Forum Index -> Development
View previous topic :: View next topic  
Author Message
Dracos



Joined: 16 Oct 2006
Posts: 21

PostPosted: Fri Jan 26, 2007 11:40    Post subject: NEGATIVE nwnx time? Reply with quote

I don't know why but this happens randmoly on my server:

1. On module load I make nwnx-time start a timer on the object MODULE.
2. When my pc rests to check if he's allowed (meaning has passed the least amount of time to rest again) it's all okay for a while but then sometimes something strange happens, and when this "something" occurs, if I look the Query timer log in the nwnx4 dir it displays a NEGATIVE (like -2467893) number. What can be the cause?
Back to top
View user's profile Send private message MSN Messenger
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Fri Jan 26, 2007 17:55    Post subject: Reply with quote

sounds like an int overflow -- how long was the timer running?
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
Dracos



Joined: 16 Oct 2006
Posts: 21

PostPosted: Fri Jan 26, 2007 18:38    Post subject: Reply with quote

Here it is:

Code:

NWNX Timer Plugin V.0.0.1
(c) 2006 by Ingmar Stieger (Papillon)
visit us at http://www.nwnx.org

* Plugin initialized.
o Starting timer REST_MODULE_TIMER0
o Elapsed timer REST_MODULE_TIMER0: 1621947360 µs / 1621947.360 msec / 1621.947 sec

o Elapsed timer REST_MODULE_TIMER0: 1626947909 µs / 1626947.909 msec / 1626.948 sec

o Elapsed timer REST_MODULE_TIMER0: -2803305909 µs / -2803305.909 msec / -2803.306 sec

o Elapsed timer REST_MODULE_TIMER0: -2803305596 µs / -2803305.596 msec / -2803.306 sec

o Elapsed timer REST_MODULE_TIMER0: -2794309949 µs / -2794309.949 msec / -2794.310 sec

o Elapsed timer REST_MODULE_TIMER0: -2794309644 µs / -2794309.644 msec / -2794.310 sec

o Elapsed timer REST_MODULE_TIMER0: 931219131 µs / 931219.131 msec / 931.219 sec

o Elapsed timer REST_MODULE_TIMER0: 1062935714 µs / 1062935.714 msec / 1062.936 sec

o Elapsed timer REST_MODULE_TIMER0: 1062936015 µs / 1062936.015 msec / 1062.936 sec

o Elapsed timer REST_MODULE_TIMER0: 1231478927 µs / 1231478.927 msec / 1231.479 sec

o Elapsed timer REST_MODULE_TIMER0: 1231479349 µs / 1231479.349 msec / 1231.479 sec

o Elapsed timer REST_MODULE_TIMER0: -741526170 µs / -741526.170 msec / -741.526 sec

o Elapsed timer REST_MODULE_TIMER0: -512444517 µs / -512444.517 msec / -512.445 sec

o Elapsed timer REST_MODULE_TIMER0: -507443420 µs / -507443.420 msec / -507.443 sec

o Elapsed timer REST_MODULE_TIMER0: -46693062 µs / -46693.062 msec / -46.693 sec

o Elapsed timer REST_MODULE_TIMER0: -41692963 µs / -41692.963 msec / -41.693 sec

o Elapsed timer REST_MODULE_TIMER0: -37033502 µs / -37033.502 msec / -37.034 sec

o Elapsed timer REST_MODULE_TIMER0: -32033592 µs / -32033.592 msec / -32.034 sec

o Elapsed timer REST_MODULE_TIMER0: 975493789 µs / 975493.789 msec / 975.494 sec

o Elapsed timer REST_MODULE_TIMER0: 975494062 µs / 975494.062 msec / 975.494 sec

o Elapsed timer REST_MODULE_TIMER0: 1064979557 µs / 1064979.557 msec / 1064.980 sec

o Elapsed timer REST_MODULE_TIMER0: 1069981435 µs / 1069981.435 msec / 1069.981 sec
[/code]
Back to top
View user's profile Send private message MSN Messenger
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Fri Jan 26, 2007 19:12    Post subject: Reply with quote

Hmm - it does look like it's cycling back and forth within the int datatype limits. Even if this were correctable within the timer plugin, NWN itself limits ints to 32 bit - that means the max number it can support is 2147483648.

Looks like you'll have to find another way to check rest time; or maybe Papillon could add an additional function to get elapsed time in whole seconds?
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Sat Jan 27, 2007 22:28    Post subject: Reply with quote

Well, I could, but that is a bit out of the scope of the timer plugin (which really is for measuring very short, but accurate timings).

I used the following code for testing rest timeouts back in the days.... have a look at the example to see how it can be used.

Code:

// Name     : Date and time functions (aps persistence version)
// Author   : Ingmar Stieger / Papillon
// Created  : August 27, 2002
// Modified : April 21, 2003
// Modified : August 30, 2003 (removed call to SpeakString)

// Implemented datatype
//  * DateTime

// Implemented functions
//  * addDateTime()           : Add two DateTimes
//  * subDateTime()           : Substract two DateTimes
//  * compareDateTime()       : Compare two DateTimes
//  * getCurrentDateTime()    : Return current DateTime
//  * newDateTime()           : Create new DateTime with given values
//  * SetLocalDateTime()      : Set oObject's local DateTime variable to date
//  * GetLocalDateTime()      : Get oObject's local DateTime variable
//  * SetPersistentDateTime() : Set oObject's persistent DateTime variable to date
//  * GetPersistentDateTime() : Set oObject's persistent DateTime variable to date
//  * debugPrintDateTime()    : Print DateTime for debugging purposes
//  * DateTimeToString)       : Convert DateTime to string

// See function headers for details
//
// Example:
/*  object oPC = GetPCSpeaker();

    struct DateTime date1 = getCurrentDateTime();
    struct DateTime date2 = newDateTime(0,0,0,8); // 8 hours later
    struct DateTime finished = addDateTime(date1, date2);

    SetLocalDateTime(oPC, "forge_shortsword_blade_finished", finished);
*/

// Date datatype
struct DateTime
{
    int year;
    int month;
    int day;
    int hour;
    int minute;
    int second;
    int millisecond;
};

//
// Add two DateTimes
//
struct DateTime addDateTime(struct DateTime date1, struct DateTime date2)
{
    int overflow;

    // add milliseconds
    if (date1.millisecond + date2.millisecond > 999)
    {
        date1.second++;
        overflow = 1000;
    }
    date1.millisecond = date1.millisecond + date2.millisecond - overflow;
    overflow = 0;

    // add seconds
    if (date1.second + date2.second > 59)
    {
        date1.minute++;
        overflow = 60;
    }
    date1.second = date1.second + date2.second - overflow;
    overflow = 0;

    // add minutes
    if (date1.minute + date2.minute > 59)
    {
        date1.hour++;
        overflow = 60;
    }
    date1.minute = date1.minute + date2.minute - overflow;
    overflow = 0;

    // add hours
    if (date1.hour + date2.hour > 23)
    {
        date1.day++;
        overflow = 24;
    }
    date1.hour = date1.hour + date2.hour - overflow;
    overflow = 0;

    // add days
    if (date1.day + date2.day > 28)
    {
        date1.month++;
        overflow = 28;
    }
    date1.day = date1.day + date2.day - overflow;
    overflow = 0;

    // add months
    if (date1.month + date2.month > 12)
    {
        date1.year++;
        overflow = 12;
    }
    date1.month = date1.month + date2.month - overflow;
    overflow = 0;

    // add years
    date1.year = date1.year + date2.year;

    return date1;
}

//
// Substract two DateTimes
//
// returns date1 - date2
//
struct DateTime subDateTime(struct DateTime date1, struct DateTime date2)
{
    int underflow;

    // sub milliseconds
    if (date1.millisecond - date2.millisecond < 0)
    {
        date1.second--;
        underflow = 1000;
    }
    date1.millisecond = date1.millisecond - date2.millisecond + underflow;
    underflow = 0;

    // sub seconds
    if (date1.second - date2.second < 0)
    {
        date1.minute--;
        underflow = 60;
    }
    date1.second = date1.second - date2.second + underflow;
    underflow = 0;

    // sub minutes
    if (date1.minute - date2.minute < 0)
    {
        date1.hour--;
        underflow = 60;
    }
    date1.minute = date1.minute - date2.minute + underflow;
    underflow = 0;

    // sub hours
    if (date1.hour - date2.hour < 0)
    {
        date1.day--;
        underflow = 24;
    }
    date1.hour = date1.hour - date2.hour + underflow;
    underflow = 0;

    // sub days
    if (date1.day - date2.day < 0)
    {
        date1.month--;
        underflow = 28;
    }
    date1.day = date1.day - date2.day + underflow;
    underflow = 0;

    // sub months
    if (date1.month - date2.month < 0)
    {
        date1.year--;
        underflow = 12;
    }
    date1.month = date1.month - date2.month + underflow;
    underflow = 0;

    // sub years
    date1.year = date1.year - date2.year;

    return date1;
}

//
// Compare two DateTimes
//
// returns < 0 if date1 is earlier than date2
// returns = 0 if date1 and date2 are the same
// returns > 0 if date1 is later than date2
//
int compareDateTime(struct DateTime date1, struct DateTime date2)
{
    if (date1.year != date2.year)
        return (date1.year - date2.year);

    if (date1.month != date2.month)
        return (date1.month - date2.month);

    if (date1.day != date2.day)
        return (date1.day - date2.day);

    if (date1.hour != date2.hour)
        return (date1.hour - date2.hour);

    if (date1.minute != date2.minute)
        return (date1.minute - date2.minute);

    if (date1.second != date2.second)
        return (date1.second - date2.second);

    if (date1.millisecond != date2.millisecond)
        return (date1.millisecond - date2.millisecond);

    return 0;
}

//
// Return current DateTime
//
struct DateTime getCurrentDateTime()
{
    struct DateTime now;

    now.year = GetCalendarYear();
    now.month = GetCalendarMonth();
    now.day = GetCalendarDay();
    now.hour = GetTimeHour();
    now.minute = GetTimeMinute();
    now.second = GetTimeSecond();
    now.millisecond = GetTimeMillisecond();

    return now;
}

//
// Create new DateTime with given values;
//
struct DateTime newDateTime(int year = 0, int month = 0, int day = 0, int hour = 0,
                            int minute = 0, int second = 0, int millisecond = 0)
{
    struct DateTime newDate;

    newDate.year = year;
    newDate.month = month;
    newDate.day = day;
    newDate.hour = hour;
    newDate.minute = minute;
    newDate.second = second;
    newDate.millisecond = millisecond;

    return newDate;
}

//
// Set oObject's local DateTime variable to date
//
void SetLocalDateTime(object oObject, string sVarName, struct DateTime date)
{
    SetLocalInt(oObject, sVarName + "year", date.year);
    SetLocalInt(oObject, sVarName + "month", date.month);
    SetLocalInt(oObject, sVarName + "day", date.day);
    SetLocalInt(oObject, sVarName + "hour", date.hour);
    SetLocalInt(oObject, sVarName + "minute", date.minute);
    SetLocalInt(oObject, sVarName + "second", date.second);
    SetLocalInt(oObject, sVarName + "millisecond", date.millisecond);
}

//
// Get oObject's local DateTime variable
//
struct DateTime GetLocalDateTime(object oObject, string sVarName)
{
    struct DateTime date;

    date.year = GetLocalInt(oObject, sVarName + "year");
    date.month = GetLocalInt(oObject, sVarName + "month");
    date.day = GetLocalInt(oObject, sVarName + "day");
    date.hour = GetLocalInt(oObject, sVarName + "hour");
    date.minute = GetLocalInt(oObject, sVarName + "minute");
    date.second = GetLocalInt(oObject, sVarName + "second");
    date.millisecond = GetLocalInt(oObject, sVarName + "millisecond");

    return date;
}

//
// Set oObject's persistent DateTime variable to date
//
void SetPersistentDateTime(object oObject, string sVarName, struct DateTime date, int iExpiration =
                           0, string sScriptFile = "pwdata")
{
    string sDateTime;

    sDateTime = IntToString(date.year);
    sDateTime += ":" + IntToString(date.month);
    sDateTime += ":" + IntToString(date.day);
    sDateTime += ":" + IntToString(date.hour);
    sDateTime += ":" + IntToString(date.minute);
    sDateTime += ":" + IntToString(date.second);
    sDateTime += ":" + IntToString(date.millisecond);

    SetPersistentString(oObject, sVarName, sDateTime, iExpiration, sScriptFile);
}

//
// Decode encoded DateTime String
// note: function calls itself only if sDateTime contains a ':'
// so an endless recursion could only happen when given a endless
// string sDateTime ;)
//

struct DateTime DecodeDateTimeRecursive(struct DateTime date, string sDateTime, int depth = 0)
{
    int iDelimiterPos;
    int iChars;
    string subString;

    iDelimiterPos = FindSubString(sDateTime, ":");
    if (iDelimiterPos != -1)
    {
        iChars = GetStringLength(sDateTime) - iDelimiterPos - 1;
        subString = GetStringRight(sDateTime, iChars);
        date = DecodeDateTimeRecursive(date, subString, depth + 1);
        sDateTime = GetStringLeft(sDateTime, iDelimiterPos);
    }

    switch (depth)
    {
    case 6:
        date.millisecond = StringToInt(sDateTime);
        break;
    case 5:
        date.second = StringToInt(sDateTime);
        break;
    case 4:
        date.minute = StringToInt(sDateTime);
        break;
    case 3:
        date.hour = StringToInt(sDateTime);
        break;
    case 2:
        date.day = StringToInt(sDateTime);
        break;
    case 1:
        date.month = StringToInt(sDateTime);
        break;
    case 0:
        date.year = StringToInt(sDateTime);
        break;
    }

    return date;
}

//
// Get oObject's persistent DateTime variable
//
struct DateTime GetPersistentDateTime(object oObject, string sVarName)
{
    struct DateTime date;
    string sDateTime;

    sDateTime = GetPersistentString(oObject, sVarName);

    date = DecodeDateTimeRecursive(date, sDateTime);
    return date;
}

//
// Hour to string
//
string HourToString(struct DateTime date)
{
    if (date.hour < 10)
        return "0" + IntToString(date.hour);
    else
        return IntToString(date.hour);
}

//
// Minute to string
//
string MinuteToString(struct DateTime date)
{
    if (date.minute < 10)
        return "0" + IntToString(date.minute);
    else
        return IntToString(date.minute);
}

//
// Second to string
//
string SecondToString(struct DateTime date)
{
    if (date.second < 10)
        return "0" + IntToString(date.second);
    else
        return IntToString(date.second);
}

//
// Print DateTime for debugging purposes
// format: mm/dd/yyyy, hh:mm:ss:ms
//
void debugPrintDateTime(struct DateTime date)
{
    SpeakString("DateTime: " + IntToString(date.month) + "/" +
                IntToString(date.day) + "/" +
                IntToString(date.year) + ", " +
                HourToString(date) + ":" +
                MinuteToString(date) + ":" +
                SecondToString(date) + "(:" + IntToString(date.millisecond) + ")");
}

//
// Convert DateTime to String
// format: year:month:day:hour:minute:second:millisecond
//
string DateTimeToString(struct DateTime date)
{
    string sDateTime;

    sDateTime = IntToString(date.year);
    sDateTime += ":" + IntToString(date.month);
    sDateTime += ":" + IntToString(date.day);
    sDateTime += ":" + IntToString(date.hour);
    sDateTime += ":" + IntToString(date.minute);
    sDateTime += ":" + IntToString(date.second);
    sDateTime += ":" + IntToString(date.millisecond);

    return sDateTime;
}


And then:

Code:

// Name     : avlis_onrest
// Purpose  : Restrict player resting
// Author   : Ingmar Stieger
// Modified : December 23, 2002

// Configuration START

int iUnrestrictedLevels = 2; // all levels up to 2 may rest as often as they like
int iRestMinHours = 4; // At least 4 hours must pass before resting is allowed again

// Configuration END

#include "datetime"

void main()
{
    object oPC = GetLastPCRested();
    if (!GetIsPC(oPC))
        return;

    // level restriction. Level 1+2 may rest as often as they want.
    if (GetHitDice(oPC) <= iUnrestrictedLevels)
        return;

    struct DateTime dNow = getCurrentDateTime();
    struct DateTime dLastRested = GetLocalDateTime(oPC, "last_rested_datetime");
    struct DateTime dDelay = newDateTime(0,0,0,iRestMinHours);
    struct DateTime dSoonest = addDateTime(dLastRested, dDelay);

    switch (GetLastRestEventType())
    {
        case REST_EVENTTYPE_REST_STARTED:
            if (compareDateTime(dNow, dSoonest) < 0)
            {
                SendMessageToPC(oPC, "You can rest only every "
                                + IntToString(iRestMinHours) + " hours.");
                SetLocalInt(oPC, "last_rest_allowed", FALSE);
                AssignCommand(oPC,ClearAllActions());
            }
            else
                SetLocalInt(oPC, "last_rest_allowed", TRUE);
        break;

        case REST_EVENTTYPE_REST_FINISHED:
                SetLocalDateTime(oPC, "last_rested_datetime", getCurrentDateTime());
        break;

        case REST_EVENTTYPE_REST_CANCELLED:
            if (GetLocalInt(oPC, "last_rest_allowed") == TRUE)
                SetLocalDateTime(oPC, "last_rested_datetime", getCurrentDateTime());
        break;
    }
}



Of course, this is NWN1 code, so it might have to be modified for NWN2.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Urlord



Joined: 17 Nov 2006
Posts: 122

PostPosted: Sun Jan 28, 2007 4:37    Post subject: Reply with quote

I think this is a good segway for me to plug our Time and Date function Library. You can finde it on the vault - HERE.

We also have a List Function Library Here.

Sorry for the plugs - One was relavent and the other I couldn't resist. They really are great functions though - Try them.
_________________
Jim (aka, Urlord)
Visit the Persistent World of Nymri
Back to top
View user's profile Send private message Send e-mail
Dracos



Joined: 16 Oct 2006
Posts: 21

PostPosted: Sun Jan 28, 2007 11:22    Post subject: Reply with quote

WELL What can I say...

THANKS A LOT GUYS! Smile
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Development All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group