Script Help, No Luck So Far - Custom Roleplay Hourly Reward

I would like help making a script that gives players experience and tokens every hour. I have asked before and have gotten “ask X they might be able to help” or some random code that does not apply. Could someone help me with this, it is driving me nuts!

Have a go at writing a script, post it here if it doesn’t work.

You could use the module heartbeat event, GetTimeHour (or a counter) stored in a module variable to tell when an hour has elapsed, GetFirstPC, GetLastPC, GiveXPToCreature and CreateItemOnObject.

More help in the Lexicon.

2 Likes

If you’re operating on 60 realtime minutes per game hour / are a-okay with dispensing rewards according to ingame hours rather than realtime ones, then yeah, you’ll want to store the current game hours as a timestamp, and check against that to see whether it’s time to dispense rewards again. Whenever the current game hour is not equal to the stored game hour, dispense reward, store current game hour.

:thinking: If you want to dispense rewards according to elapsed realtime, with game time running at a different speed, you could try setting up a pseudoheartbeat that functions as an independent realtime clock. If it’s just the one for the entire module, and it only cycles through the players once per hour, it ?shouldn’t? be too performance-intensive (said someone who is not a PW dev, blithely. Fingers crossed the local PW devs will intervene if this is nonsense).

Do you know which it is you want? Rewards according to passed ingame hours, or rewards according to passed realtime hours? Does the module’s game time go by 60 realtime minutes per ingame hour, or does it pass faster?

1 Like

The length of a game hour is set in the module properties under the advanced tab.

I will give some sugestions after I get home tonight.

2 Likes

Thank you all this is very helpful. The clock on the server goes 24 hours to one real life hour. So I tried hourly but heartbeat fires every 6 seconds, so it gives it 12 times on hr 5. So I figured I could set it to say hour 5 minute 59 second 59 but not sure how to edit beyond hour. I could set it to on roleplay or have each player have a custom hour so they dont get the bonus as soon as they login with nwnx, but that is after I can get the script to do the basic part first. Thank you for your great help!

1 Like

I haven’t tested it, but give this module heartbeat script a shot, the very first tick might come sooner or later than expected, but after that it should be normalized. It’s based on server time, not on real time.

void main()
{
    object oMODULE = GetModule();
    int nHOUR = GetTimeHour();
    int nTIME = GetLocalInt(oMODULE, "RP_HOUR");
    if ((nHOUR == 0) && (nTIME == 23)) nTIME = -1;
    if (nHOUR <= nTIME) return;
    SetLocalInt(oMODULE, "RP_HOUR", nHOUR);
    object oPC = GetFirstPC();
    while (oPC != OBJECT_INVALID)
    {
        GiveXPToCreature(oPC, 10);
        oPC = GetNextPC();
    }
}
2 Likes

Will try it. Thank you very much!

1 Like

I did this and it works but gives them every minute.

{
object oMODULE = GetModule();
int nHOUR = GetTimeHour();
int nTIME = GetLocalInt(oMODULE, “RP_HOUR”);
if ((nHOUR == 0) && (nTIME == 23)) nTIME = -1;
if (nHOUR <= nTIME) return;
SetLocalInt(oMODULE, “RP_HOUR”, nHOUR);
object oPC = GetFirstPC();
while (oPC != OBJECT_INVALID)
{
GiveXPToCreature(oPC, 1000);
GiveGoldToCreature(oPC, 5000);
CreateItemOnObject(“dmtoken”, oPC);
oPC = GetNextPC();

If I set the minute/hr to 60 would it fix it?

If you want to try the modulewide realtime clock route, I’ve just set one up, and it seems to work:

void RT_Clock(int nSeconds=0, int nMinutes=0, int nHours=0, int nDays=0)
{
    int nDoPCLoop, nHourlyRewards;

    // Advance the clock:
    if (nSeconds >= 60)
        {
        nSeconds -= 60;
        nMinutes += 1;
        }
    if (nMinutes >= 60)
        {
        nMinutes -= 60;
        nHours   += 1;
        }
    if (nHours >= 24)
        {
        nHours -= 24;
        nDays  += 1;
        }

    // Debug message:
    SendMessageToPC(GetFirstPC(), "RT Clock - "+IntToString(nDays)+"d, "
                                               +IntToString(nHours)+"h, "
                                               +IntToString(nMinutes)+"m, "
                                               +IntToString(nSeconds)+"s.");

    // ------------------------------------------------------------
    // Check whether stuff should be given to or done with the PCs:
    // ------------------------------------------------------------
    // Is it time to hand out hourly rewards?
    if (GetLocalInt(OBJECT_SELF, "LAST_REWARD_HOUR") != nHours)
        {
        nDoPCLoop      = TRUE;
        nHourlyRewards = TRUE;

        SetLocalInt(OBJECT_SELF, "LAST_REWARD_HOUR", nHours);
        }

    // --------------------------------------------------------
    // If there's a reason to do it, then loop through the PCs:
    // --------------------------------------------------------
    if (nDoPCLoop)
        {
        object oTarget = GetFirstPC();
        while (oTarget != OBJECT_INVALID)
            {
            // Dispense hourly rewards:
            if (nHourlyRewards)
                {
                GiveXPToCreature(oTarget, 50);
                CreateItemOnObject("cookie", oTarget);
                }

            oTarget = GetNextPC();
            }
        }

    DelayCommand(1.0, RT_Clock(nSeconds+1, nMinutes, nHours, nDays));
}

void main()
{
    RT_Clock();
}

Started off in OnModuleLoad, via

ExecuteScript("rt_clock", OBJECT_SELF);

I’m given to understand that DelayCommand calls are not very PW-friendly for performance reasons, though. Keeping a realtime-clock ticking in the background might make more sense if it’s made more extensive use of than just this one thing and nothing else. Maybe for storing the realtime clock seconds/minutes/hours/days on the module as local ints to use for other realtime-dependent timestamps.

1 Like

I used your script and took out the debug message. PERFECT! Thank you for all your hard work.

1 Like

That, or you could have just divided the rewards by 60 and multiplied the dm token prices by 60, would have had the same end result.

2 Likes