A bit of help please

hello again

In my module i have certain placeables at the end of my pve zones that summon bosses when used. I set an int on the placeable after use then delete it after x amount of time.

How can i send a message back to players telling exactly when the placeable can be used again (the time before the int gets deleted)?

I can post the code im using on the placeable object if that’d help.

Use the function SendMessageToPC perhaps?

yeah i do that, but i need the ‘exact’ time before the int gets deleted and placeable can be used/boss can be summoned again.

Ok. Maybe we need to see your script about how you set the time for deleting the placeable then.

here is what i have…

void CommandMonster(object oMonster, object oPC)
{
    AssignCommand(oMonster, ActionDoCommand(PlayVoiceChat(VOICE_CHAT_BATTLECRY1, OBJECT_SELF)));
    AssignCommand(oMonster, ActionDoCommand(ActionPlayAnimation(ANIMATION_FIREFORGET_TAUNT)));
}
 
void DestroyMonster(object oMonster)
{
    DestroyObject(oMonster, 0.01f);
}

////////////////////////////////////////////////////////////
// The Main script
////////////////////////////////////////////////////////////
void main()
{
    object oPC = GetLastUsedBy();
    object oBOSS1 = GetObjectByTag("Ettin_Boss");
 if (GetIsObjectValid(oBOSS1) == TRUE )
    {
    FloatingTextStringOnCreature("The boss has already been summoned. Prepare for battle!!!", oPC, FALSE);
    return;
    }
    if (GetLocalInt(OBJECT_SELF, "ZONE1BOSS"))
    {
    FloatingTextStringOnCreature("This object cannot be used right now, please try again later!", oPC, FALSE);
    return;
    }
    if(GetIsPC(GetLastUsedBy()))
        {
            object oSumPoint = GetWaypointByTag("BOSS1_WP");
            location lSumPoint = GetLocation(oSumPoint);
            object oMonster = CreateObject(OBJECT_TYPE_CREATURE, "creatureresref",lSumPoint);
            //PlaySound("");
            ActionSpeakString("The boss has been summoned!!!", TALKVOLUME_TALK);
            CommandMonster(oMonster, oPC);
            SetLocalInt(OBJECT_SELF, "ZONE1BOSS", 1);
            DelayCommand(1800.0f, SetLocalInt(OBJECT_SELF, "ZONE1BOSS", 0));
            DelayCommand(900.0f, DestroyMonster(oMonster));
        }
      }

This section of the main script needs to send message telling the exact time before boss can be summoned again…

if (GetLocalInt(OBJECT_SELF, "ZONE1BOSS"))
    {
    FloatingTextStringOnCreature("This object cannot be used right now, please try again later!", oPC, FALSE);
    return;
    }

Maybe I’m stupid now but…eh…“please try again in 1800 seconds (or 30 minutes))” ? I mean, since you have a delaycommand of 1800 seconds it seems? I’m probably misunderstanding this whole thing. :flushed:

nah it’s probably me not explaining things properly haha

i just need the exact time, i can send a message saying 30 minutes till boss can be summoned yada yada, but that isnt accurate depending on when players try to summon the boss.

So you need like the hour and minute of the day when the players can summon the boss?
I’m sorry, but I don’t know how to script that, but I’m sure someone else can help you…

Maybe if you use (at least this function is available in NWN2) GetTimeMinute, and then add 30 min to that, and the result you then send like a message to the players?

look for an nwn1 library that does something like this (or roll yer own)

void SetIntervalStart(string sVariable, object oPlaceable = OBJECT_SELF)
{
    SetLocalInt(oPlaceable, sVariable, GetCurrent());
}

int GetSecondsElapsed(string sVariable, object oPlaceable = OBJECT_SELF)
{
    return GetCurrent() - GetLocalInt(oPlaceable, sVariable);
}

// gets current gametime in seconds
int GetCurrent()
{
    int iYear   = GetCalendarYear();
    int iMonth  = GetCalendarMonth();
    int iDay    = GetCalendarDay();
    int iHour   = GetTimeHour();
    int iMinute = GetTimeMinute();
    int iSecond = GetTimeSecond();

    return     iYear    * 12 * 28 * 24 * 60 * 60
            + (iMonth - 1)   * 28 * 24 * 60 * 60
            + (iDay   - 1)        * 24 * 60 * 60
            +  iHour                   * 60 * 60
            +  iMinute                      * 60
            +  iSecond;
    // the problem is this is Gametime, not realtime
    // a bit more work needs to be done here, i believe.
}

So to get the time remaining:

int iCooldown = 1800; // <- get this off the object, if it varies
int iTimeRemaining = iCooldown - GetSecondsElapsed(sVar);

and convert seconds to whatever format if you want, before displaying it to Player

be careful of clock/calender wraparound,

 
/just an idea, to get ya started, i suppose

thank you, ill mess around with that and see if i can get this working.

1 Like

It will wrap at around year 68, so it’s best to subtract the starting year or set it to 0 in the toolset. The latter has the benefit of showing the player how much time he spent playing.

Referencing the calendar may also bring other issues when the date is forced forward.

However in this case, the easiest approach (when only real time matters) is in my opinion to start a 1-second pseudo-heartbeat that will reduce ZONE1BOSS var from 1800 to 0.

Then it is a matter of just parsing the current value in OnUsed to minutes and seconds to display them to the placeable’s user.

yep. My routine will overflow the int-type @ very roughly year 2000

That’s probably best/easiest in this case. My lib is/was designed for more general usage …

yep, Shacker convinced me.

Either subtract the start year, or go with a 1-sec pHB that decrements time remaining …

 
[edit]

// Returns current Gametime in seconds.
// - note overflows/wraps after ~68 yr from game start
int CalcCurrent(int iStartYear)
{
	int iYear   = GetCalendarYear() - iStartYear;
	int iMonth  = GetCalendarMonth();
	int iDay    = GetCalendarDay();
	int iHour   = GetTimeHour();
	int iMinute = GetTimeMinute();
	int iSecond = GetTimeSecond();

	return     iYear    * 12 * 28 * 24 * 60 * 60
			+ (iMonth - 1)   * 28 * 24 * 60 * 60
			+ (iDay   - 1)        * 24 * 60 * 60
			+  iHour                   * 60 * 60
			+  iMinute                      * 60
			+  iSecond;
}

Got it working!

I use a script that gets total time in minutes, took it from my on player rest event… does the trick, not in seconds but it’s better this way i think.


int GetTotalTimeMinutes()
{
int nTimeMinutes;// Declaring a variable
int nMinutes = GetTimeMinute();// get number of minutes
int nHours = GetTimeHour();// get hours
int nDays = GetCalendarDay();// Get days
int nMonths = GetCalendarMonth();// Get months
int nYears = GetCalendarYear();// Get years
float fMinutesPerHour = HoursToSeconds(1);// Get number of seconds in 1 hour
int nMinutesPerHour = FloatToInt(fMinutesPerHour);// Change to int
nMinutesPerHour /= 60;// Divide by 60 to get minutes in an hour
// If you don't do this, any variance in the module hours/minutes can mess it up
nHours *= nMinutesPerHour;// Convert hours into minutes
nDays *= (nMinutesPerHour * 24);// Convert days into minutes
nMonths *= (nMinutesPerHour * 672);// Convert months into minutes
nYears *= (nMinutesPerHour * 8064);// Convert years into minutes
nTimeMinutes = (nMinutes + nHours + nDays + nMonths + nYears);// Add all together
return nTimeMinutes;// The return of the function is the total number of minutes
}

Ty for the help!

2 Likes