View previous topic :: View next topic |
Author |
Message |
Zunath
Joined: 06 Jul 2006 Posts: 183
|
Posted: Thu Jun 07, 2007 1:49 Post subject: Real World Time |
|
|
Is it possible to get the real world time and base things within NWN off of it? Through the use of an external program of some such?
I'd like to be able to spawn certain monsters depending on what time it might be or what day of the week it is.
Anyone have any idea on how to accomplish this? |
|
Back to top |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Thu Jun 07, 2007 8:34 Post subject: |
|
|
In mod heartbeat:
Code: | void main () {
int nUptime = GetLocalInt(OBJECT_SELF, "uptime");
SQLExecDirect("SELECT UNIX_TIMESTAMP() - " + IntToString(GetLocalInt(OBJECT_SELF, "boottime")));
if (SQLFetch() == SQL_SUCCESS) {
nUptime = StringToInt(SQLGetData(1));
SetLocalInt(OBJECT_SELF, "uptime", nUptime);
}
} |
"boottime" is set onmodload:
Code: | // load boot time into the boottime variable
SQLExecDirect("SELECT UNIX_TIMESTAMP()");
if (SQLFetch() == SQL_SUCCESS)
SetLocalInt(GetModule(), "boottime", StringToInt(SQLGetData(1)));
SetLocalInt(GetModule(), "uptime", 0); |
This link should help:
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
HTH,
Funky |
|
Back to top |
|
|
nosfe
Joined: 25 Apr 2007 Posts: 22
|
Posted: Thu Jun 07, 2007 14:25 Post subject: |
|
|
mhh,
I am not convinced to make a select in the heartbeat, every 6 seconds that made a little much;
especially if you use a trigger which suits him to make Select and to see what time it is really then lance or not the spawn;
very more light |
|
Back to top |
|
|
TroveLord
Joined: 22 Nov 2006 Posts: 136 Location: Italy
|
Posted: Thu Jun 07, 2007 16:13 Post subject: |
|
|
Assuming that you use a database can't you it for the purpose?
Here's what you need
Code: |
SELECT CURRENT_TIME
SELECT CURRENT_DATE
SELECT CURRENT_TIMESTAMP
|
|
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Thu Jun 07, 2007 16:19 Post subject: |
|
|
There is a NWNX Clock plugin by kungfoowiz which gets the date as well. It will have to be updated for the upcoming NWNX4 1.08, though (read: it will only work up to NWNX 1.07).
http://nwnx.org/index.php?id=65 _________________ Papillon |
|
Back to top |
|
|
Zunath
Joined: 06 Jul 2006 Posts: 183
|
Posted: Thu Jun 07, 2007 20:13 Post subject: |
|
|
Thanks guys, I use NWNX2 for NWN1 though so some of your suggestions I won't be able to use.
Trovelord, that does seem pretty easy to do. Where in the script would I place those constants? Would I use the SQLExecDirect function?
Sorry, I've only gotten used to using the Get and Set PersistentObjects.
Funky, thanks for the suggestion but I think a heartbeat script will be a bit too much for the PW I am making.
Thanks again all!
EDIT: Also, I am using SQLite for my database. I couldn't figure out regular MySQL |
|
Back to top |
|
|
TroveLord
Joined: 22 Nov 2006 Posts: 136 Location: Italy
|
Posted: Thu Jun 07, 2007 22:33 Post subject: |
|
|
Zunath wrote: | that does seem pretty easy to do. Where in the script would I place those constants? |
Wherever you need, you might want to check the local time as if statement before creating a monster.
Zunath wrote: | Would I use the SQLExecDirect function? |
Yes like this
Code: | string GetSQLTime()
{
string sSQL = "SELECT CURRENT_TIME";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
}
string GetSQLDate()
{
string sSQL = "SELECT CURRENT_DATE";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
}
string GetSQLTimeStamp()
{
string sSQL = "SELECT CURRENT_TIMESTAMP";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
} |
|
|
Back to top |
|
|
Zunath
Joined: 06 Jul 2006 Posts: 183
|
Posted: Fri Jun 08, 2007 4:50 Post subject: |
|
|
I included what you wrote into another file. It looks like this:
Code: | #include "aps_include"
// Gets the current REAL WORLD time, uses NWNX2
string GetSQLTime();
string GetSQLTime()
{
string sSQL = "SELECT CURRENT_TIME";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
}
// Gets the current REAL WORLD date, uses NWNX2
string GetSQLDate();
string GetSQLDate()
{
string sSQL = "SELECT CURRENT_DATE";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
}
// Gets the current REAL WORLD time stamp, uses NWNX2
string GetSQLTimeStamp();
string GetSQLTimeStamp()
{
string sSQL = "SELECT CURRENT_TIMESTAMP";
SQLExecDirect(sSQL);
if(SQLFetch() == SQL_SUCCESS)
{
return SQLGetData(1);
}
else
{
return "Database error";
}
}
//void main(){}
|
I placed this test script on the OnUsed of a placeable to test everything.
Code: |
#include "aps_include"
#include "rwt_include"
void main()
{
object oSelf = OBJECT_SELF;
object oPC = GetLastUsedBy();
string sTime = GetSQLTime();
string sDate = GetSQLDate();
string sTimeStamp = GetSQLTimeStamp();
SendMessageToPC(oPC, sTime);
SendMessageToPC(oPC, sDate);
SendMessageToPC(oPC, sTimeStamp);
}
|
It returned "database error" in game. What did I do wrong? Is this not compatible with a SQLite database?
Thanks again, sorry to cause problems.[/code] |
|
Back to top |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Fri Jun 08, 2007 5:27 Post subject: |
|
|
Zunath wrote: | Thanks guys, I use NWNX2 for NWN1 though so some of your suggestions I won't be able to use.
Funky, thanks for the suggestion but I think a heartbeat script will be a bit too much for the PW I am making.
|
Lol, didn't expect to find myself advocating this position, but the hearbeat is probably the most efficient solution here. I'm a nut when it comes to script efficiency, just take a look at the bioboards if you doubt it. I have used and abused the profiler to no end. And, I can assure you, the impact of that heatbeat on your mod will be about null. Not quite, but so close to it as to be insubstantial. HG is a huge mod, 110M at last count, with about 470 areas chock full of content, and runs smoothly, with a more substantial heartbeat than that. And please, don't mistake me for a heartbeat apologist, it's the only one in my mod (other than the ones on a few creatures) becuase I use psuedos for everything else. Psuedos take roughly 5x as long to run, so I only use them for scripts that run less than 20% of the time - but that's nothing in my mod. Just food for thought. Oh, a SELECT every 6 seconds is nothing in terms of machine time.
Here's our full mod heartbeat, which, again, has almost no overhead and no noticeable impact on the mod:
Code: | #include "aps_include"
object GetMessenger()
{
return GetLocalObject(GetModule(), "FKY_CHT_MESSENGER");
}
void SendChatLogMessage(object oRecipient, string sMessage, object oSender = OBJECT_INVALID, int nChannel = 4)
{
if (!GetIsObjectValid(oSender)) return;
if (FindSubString(sMessage, "¬")!=-1) return;
if (nChannel == 4 && !GetIsObjectValid(oRecipient)) return;
SetLocalString(oSender, "NWNX!CHAT!SPEAK", ObjectToString(oSender)+"¬"+ObjectToString(oRecipient)+"¬"+IntToString(nChannel)+"¬"+sMessage);
}
object FindAddressee(string sPlayername)
{
string sCheck;
object oPC = GetFirstPC();
while (GetIsObjectValid(oPC))
{
sCheck = GetPCPlayerName(oPC);
if (sCheck == sPlayername) return oPC;
oPC = GetNextPC();
}
return OBJECT_INVALID;
}
void main () {
int nUptime = GetLocalInt(OBJECT_SELF, "uptime");
SQLExecDirect("SELECT UNIX_TIMESTAMP() - " + IntToString(GetLocalInt(OBJECT_SELF, "boottime")));
if (SQLFetch() == SQL_SUCCESS) {
nUptime = StringToInt(SQLGetData(1));
SetLocalInt(OBJECT_SELF, "uptime", nUptime);
}
int nLastMinute = GetLocalInt(OBJECT_SELF, "lastminute");
if (nUptime >= nLastMinute + 60) {
string sServer = GetLocalString(OBJECT_SELF, "ServerNumber");
string sSQL = "SELECT name, sender, message FROM messages WHERE server = '" + sServer + "'";
string sMessage, sName, sLocalString;
object oAddressee, oPC;
string sSender;
int nCount = 1;
int nX;
object oMod = GetModule();
SQLExecDirect(sSQL);
while(SQLFetch() != SQL_ERROR)
{
sMessage = SQLDecodeSpecialChars(SQLGetData(3));
sName = SQLDecodeSpecialChars(SQLGetData(1));
sSender = SQLDecodeSpecialChars(SQLGetData(2));
PrintString(sMessage+sName+sSender);
if (sName == "None") AssignCommand(oMod, SpeakString(sMessage, TALKVOLUME_SHOUT));
else
{
oAddressee = FindAddressee(sName);
if (GetIsObjectValid(oAddressee))
{
FloatingTextStringOnCreature("<c þ >Interserver message received from " + sSender + "!</c>", oAddressee, FALSE);
//SendMessageToPC(oAddressee, "<c þ >" + sMessage + "</c>");
SendChatLogMessage(oAddressee, "<c þ >" + sMessage + "</c>", GetMessenger());
}
}
}
sSQL = "DELETE FROM messages WHERE server = '" + sServer + "'";
SQLExecDirect(sSQL);
SetLocalInt(OBJECT_SELF, "lastminute", nUptime);
}
} |
As you can see there's a much heftier select than the one I suggested. And with accurate time you can do all kinds of cool timestamping. We use it for temporary casterlevel increases, for example.
Funky |
|
Back to top |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Fri Jun 08, 2007 8:49 Post subject: |
|
|
Zunath wrote: |
It returned "database error" in game. What did I do wrong? Is this not compatible with a SQLite database?
Thanks again, sorry to cause problems. |
Yes, as far as I know those are MySQL functions only. If you'd like help setting it up just let us know.
Funky |
|
Back to top |
|
|
TroveLord
Joined: 22 Nov 2006 Posts: 136 Location: Italy
|
Posted: Fri Jun 08, 2007 9:33 Post subject: |
|
|
FunkySwerve wrote: | Zunath wrote: |
It returned "database error" in game. What did I do wrong? Is this not compatible with a SQLite database?
Thanks again, sorry to cause problems. |
Yes, as far as I know those are MySQL functions only. If you'd like help setting it up just let us know.
Funky |
I've actually tested them with SQLite and they work. What won't work is SELECT VERSION() because SQLite has its own function for that: SELECT sqlite_version() |
|
Back to top |
|
|
Gryphyn
Joined: 20 Jan 2005 Posts: 431
|
Posted: Fri Jun 08, 2007 10:53 Post subject: |
|
|
How would these work?
Strings
Code: | if (function == wxT("REALTIME"))
{
wxDateTime CallTime = wxDateTime::Now();
wxTimeSpan SpanTime = CallTime.Subtract(LoadTime);
if (timerName == wxT("DATE"))
{
wxLogMessage(wxT("o Date is %s"), CallTime.FormatISODate());
sprintf_s(returnBuffer, MAX_BUFFER, "%s", CallTime.FormatISODate());
}
if (timerName == wxT("TIME"))
{
wxLogMessage(wxT("o Time is %s"), CallTime.FormatISODate());
sprintf_s(returnBuffer, MAX_BUFFER, "%s", CallTime.FormatISOTime());
}
if (timerName == wxT("UPTIME"))
{
wxLogMessage(wxT("o Uptime is %s"), SpanTime.Format());
sprintf_s(returnBuffer, MAX_BUFFER, "%s", SpanTime.Format());
}
else
{
wxLogMessage(wxT("* Unknown RealTime option '%s' called"));
return NULL;
}
} |
ISODate = YYYY-MM-DD
ISOTime = HH:MM:SS
Integers
Code: | if (function == wxT("REALTIME"))
{
wxDateTime CallTime = wxDateTime::Now();
wxTimeSpan SpanTime = CallTime.Subtract(LoadTime);
if (timerName == wxT("YEAR")) return CallTime.GetYear();
else if (timerName == wxT("MONTH")) return CallTime.GetMonth();
else if (timerName == wxT("MON")) return CallTime.GetMonth();
else if (timerName == wxT("DAY")) return CallTime.GetDay();
else if (timerName == wxT("HOUR")) return CallTime.GetHour();
else if (timerName == wxT("HR")) return CallTime.GetHour();
else if (timerName == wxT("MINUTE")) return CallTime.GetMinute();
else if (timerName == wxT("MIN")) return CallTime.GetMinute();
else if (timerName == wxT("MILLI")) return CallTime.GetMillisecond();
else if (timerName == wxT("MILLISECOND")) return CallTime.GetMillisecond();
else if (timerName == wxT("UPDAYS")) return SpanTime.GetDays();
else if (timerName == wxT("UPHOURS")) return SpanTime.GetHours();
else if (timerName == wxT("UPMINUTES")) return SpanTime.GetMinutes();
else
{
wxLogMessage(wxT("* Unknown RealTime option '%s' called"));
}
} |
OK, there's a bit more that what's shown, and some liberties taken (an assumption that when the plug-in is loaded is when the server starts)
Your post got me thinking about extending functionality of the Timer plug-in. So far this stuff is working with the 1.08 build.
Want more?
Cheers
Gryphyn |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Fri Jun 08, 2007 12:27 Post subject: |
|
|
Gryphyn, this seems to be a fine addition to the time plugin. Do you want to add your code to the "offical" version ? _________________ Papillon |
|
Back to top |
|
|
Gryphyn
Joined: 20 Jan 2005 Posts: 431
|
Posted: Fri Jun 08, 2007 13:02 Post subject: |
|
|
Papillon wrote: | Gryphyn, this seems to be a fine addition to the time plugin. Do you want to add your code to the "offical" version ? |
It was a 10 min 'knock-up', but works fine.
Sure, if you want it for the real - Timer plug-in - the source is yours.
I'll send an e-mail.
I'm not sure what other functions may be requested (hence the post) but they are dead simple to add in.
PS. In the aether...
I've also done some re-naming but the essence is there...
Cheers
Gryphyn |
|
Back to top |
|
|
Zunath
Joined: 06 Jul 2006 Posts: 183
|
Posted: Tue Jul 03, 2007 1:42 Post subject: |
|
|
I've decided it would be better to go with MySQL instead of SQLite since it seems there's a lot more functionality with MySQL.
However, I'm not too sure how to set it up. I've downloaded the SQL server 5.0 and the GUI tools, but as far as actually getting it functional I'm at a loss. And the OBDC documentation didn't help much either.
Thanks guys, can't wait to use real world time. |
|
Back to top |
|
|
|
|
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
|