This configures an award that is given periodically with a long time interval, add the following to your login script, or create a new script containing the below and set your Instance.RunOnLogin to call this new script.
This script makes a few assumptions you can tweak where noted
// See if the character is eligible for the award
Integer eligible=gsGetKV(CALLER,"Characters.PeriodAward");
if (eligible==1) {
// They are allowed to earn this type of XP
// See when the award is next allowed
Integer nextAt=gsGetCharacterKV(CALLER,"Characters.PeriodTimer");
// if this number isn't zero (which means they just moved into the eligible state), and is in the future, award the XP
if (nextAt>0 && nextAt>gsGetUnixTime()) {
Response discardResponse=gsElevatedAPIX(CALLER,"Experience.Award",[CALLER,"Characters.Period",1,"Periodic XP award"]);
nextAt=0; // causes timer reset
}
if (nextAt==0) {
// if nextAt is zero, we either loaded a zero timer, meaning the character is newly eligible, or nextAt was set to zero after the award above.
// Set up timer for next award
Integer discard=gsSetCharacterKVs(CALLER,["Characters.PeriodTimer",""+(gsGetUnixTime()+60*60*24*90)]); // timer is 90 days
}
} else {
// They are not allowed to earn this type of XP, so we just blank the timer (in case they are moved from being eligible to not eligible)
Integer discard=gsSetCharacterKVs(CALLER,["Characters.PeriodTimer","0"]);
}