Ok, this IS thread resurrection, but Shigs finally forced me to kick start my lazy brain and Just quickHack It(tm)
DS 2.9a13. If i'd call it "thoroughly tested" i'd be lying, but it seems to be working on my testmud.
Add to your /secure/include/config.h:
#define MUDTIME_IS_REALTIME 1
/* /daemon/seasons.c
* from the Dead Souls LPC Library
* handles game-based time
* created by Descartes of Borg 950508
* Version: @(#) seasons.c 1.7@(#)
* Last modified: 96/10/27
*/
/* Has been modified numerous times since then, but nobody bothered
* to update the headers.
*
* realtime stuff first hacked in by Raudhrskal, 2009-01-19
*/
#include <lib.h>
#include <cfg.h>
#include <config.h>
#include <function.h>
#include <localtime.h>
#include "include/seasons.h"
inherit LIB_DAEMON;
private static int CurrentDay, CurrentYear;
private static int Dawn, Morning, Noon, Twilight, Night;
private static int ticktock, MidnightOffset;
private static string CurrentSeason, TimeOfDay;
private static mapping Moons;
private static class month CurrentMonth;
private static string *Days;
private static function *DawnCalls, *MorningCalls, *NoonCalls;
private static function *TwilightCalls, *NightCalls, *MidnightCalls;
private static class month *Months;
int eventTickTock(int tick){
#if MUDTIME_IS_REALTIME
tick = 0;
#else
if(!tick) tick = 0;
#endif
ticktock = tick;
eventConfigure();
return GetCurrentTime()/1200;
}
int GetTickTock(){ return ticktock; }
int *GetMudTime(){
//return ({ GetHour(GetCurrentTime()), GetMinutes(GetCurrentTime()) });
return ({ GetHour(time()), GetMinutes(time()) });
}
#if MUDTIME_IS_REALTIME
# define REALTIME_CFG ".realtime"
#else
# define REALTIME_CFG ""
#endif
static void create() {
string *lines;
int i, maxi;
daemon::create();
DawnCalls = ({});
MorningCalls = ({});
NoonCalls = ({});
TwilightCalls = ({});
NightCalls = ({});
MidnightCalls = ({});
ticktock = 0;
MidnightOffset = 0;
maxi = sizeof(lines = filter(explode(read_file(CFG_MONTHS + REALTIME_CFG), "\n"),
(: $1 && $1 != "" && $1[0] != '#' :)));
Months = allocate(maxi);
for(i=0; i<maxi; i++) {
Months[i] = new(class month);
sscanf(lines[i], "%s:%s:%d:%d",((class month)Months[i])->Name,
((class month)Months[i])->Season,
((class month)Months[i])->Days,
((class month)Months[i])->DaylightHours);
}
#if MUDTIME_IS_REALTIME
//Leap year?
i=localtime(time())[LT_YEAR];
if( (!(i % 400)) || ( (i % 100) && (!(i % 4)) ) ) {
((class month)Months[1])->Days = 29;
}
#endif
Days = filter(explode(read_file(CFG_DAYS + REALTIME_CFG), "\n"),
(: $1 && $1 != "" && $1[0] != '#' :));
maxi = sizeof(lines = filter(explode(read_file(CFG_MOONS), "\n"),
(: $1 && $1 != "" && $1[0] != '#' :)));
Moons = allocate_mapping(maxi);
for(i=0; i<maxi; i++) {
string nom, id, desc, lnom;
int phase;
sscanf(lines[i], "%s:%d:%s:%s", nom, phase, id, desc);
lnom = convert_name(nom);
Moons[lnom] = new(class moon);
((class moon)Moons[lnom])->Name = nom;
((class moon)Moons[lnom])->Phase = phase;
((class moon)Moons[lnom])->Id = id;
((class moon)Moons[lnom])->Description = desc;
}
eventConfigure();
}
static void eventConfigure() {
int i, x, days, tot, maxi;
#if MUDTIME_IS_REALTIME
mixed *lct;
lct = localtime(GetTime(time()));
CurrentYear = lct[LT_YEAR];
CurrentMonth = (class month)Months[lct[LT_MON]];
CurrentSeason = CurrentMonth->Season;
CurrentDay = lct[LT_MDAY];
MidnightOffset = lct[LT_GMTOFF];
#else
days = GetTime(time()) / (DAY_LENGTH * HOUR_LENGTH);
for(tot=0, i=0, maxi = sizeof(Months); i<maxi; i++)
tot += ((class month)Months[i])->Days;
CurrentYear = days / tot + 1;
days = (days % tot) + 1;
for(i=0, maxi = sizeof(Months); i<maxi; i++) {
if( days <= ((class month)Months[i])->Days ) {
CurrentMonth = (class month)Months[i];
CurrentSeason = ((class month)Months[i])->Season;
CurrentDay = days;
break;
}
else days -= ((class month)Months[i])->Days;
}
#endif
x = CurrentMonth->DaylightHours * HOUR_LENGTH;
Morning = ((DAY_LENGTH * HOUR_LENGTH) - x) / 2;
Twilight = Morning + x;
Noon = (DAY_LENGTH * HOUR_LENGTH) / 2;
if( Morning < HOUR_LENGTH ) {
Dawn = Morning/2;
Night = Twilight + Morning/2;
}
else {
Dawn = Morning - HOUR_LENGTH;
Night = Twilight + HOUR_LENGTH;
}
x = GetCurrentTime();
if( x < Dawn ) {
TimeOfDay = "night";
call_out( (: eventDawn :), Dawn - x);
}
else if( x < Morning ) {
TimeOfDay = "dawn";
call_out( (: eventMorning :), Morning - x);
}
else if( x < Noon ) {
TimeOfDay = "day";
call_out( (: eventNoon :), Noon - x);
}
else if( x < Twilight ) {
TimeOfDay = "day";
call_out( (: eventTwilight :), Twilight - x);
}
else if( x < Night ) {
TimeOfDay = "twilight";
call_out( (: eventNight :), Night - x );
}
else {
TimeOfDay = "night";
call_out( (: eventMidnight :), (DAY_LENGTH * HOUR_LENGTH) - x);
}
}
static void eventDawn() {
object *obs;
int i;
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventMorning :), Morning - GetCurrentTime() );
#endif
TimeOfDay = "dawn";
obs = filter(users(), (: environment($1) &&
environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!((int)environment($1)->GetProperty("no time")) :));
message("environment",
"%^YELLOW%^The sun appears just over the horizon.%^RESET%^",
obs );
i = sizeof(DawnCalls);
while(i--) catch(evaluate(DawnCalls[i]));
}
static void eventMorning() {
object *obs;
int i;
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventNoon :), Noon - GetCurrentTime());
#endif
TimeOfDay = "day";
obs = filter(users(), (: environment($1) &&
(string)environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!((int)environment($1)->GetProperty("no time")) :));
message("environment", "%^BOLD%^YELLOW%^The sun now shines completely "
"on a new day.%^RESET%^", obs);
i = sizeof(MorningCalls);
while(i--) catch(evaluate(MorningCalls[i]));
}
static void eventNoon() {
int i;
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventTwilight :), Twilight - GetCurrentTime());
#endif
TimeOfDay = "day";
/* debug("Noon Time!"); */
i = sizeof(NoonCalls);
while(i--) catch(evaluate(NoonCalls[i]));
}
static void eventTwilight() {
object *obs;
int i;
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventNight :), Night - GetCurrentTime() );
#endif
TimeOfDay = "twilight";
obs = filter(users(), (: environment($1) &&
(string)environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!((int)environment($1)->GetProperty("no time")) :));
message("environment", "%^CYAN%^The sun begins to fall away into "
"twilight.%^RESET%^", obs);
i = sizeof(TwilightCalls);
while(i--) catch(evaluate(TwilightCalls[i]));
}
static void eventNight() {
object *obs;
int i,x;
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventMidnight :),
(DAY_LENGTH * HOUR_LENGTH) - GetCurrentTime() );
#endif
TimeOfDay = "night";
obs = filter(users(), (: environment($1) &&
(string)environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!((int)environment($1)->GetProperty("no time")) :));
message("environment",
"%^BOLD%^BLUE%^Night darkens all that is real.%^RESET%^", obs);
i = sizeof(NightCalls);
while(i--){
mixed f = NightCalls[i];
if((x = functionp(f)) && !(x & FP_OWNER_DESTED)){
catch(evaluate(f));
}
}
}
static void eventMidnight() {
int i;
CurrentDay++;
i = CurrentMonth->Days;
if( CurrentDay > i ) {
int y;
y = CurrentYear;
eventConfigure();
if( y != CurrentYear )
message("shout", "Happy New Year!!!\nIt is now the year " +
GetYearString(CurrentYear) + "!!!!!", users());
return;
}
#if MUDTIME_IS_REALTIME
eventConfigure();
#else
call_out( (: eventDawn :), Dawn);
#endif
TimeOfDay = "night";
/* debug("midnight!"); */
i = sizeof(MidnightCalls);
while(i--) catch(evaluate(MidnightCalls[i]));
}
int GetCurrentDay() { return CurrentDay; }
string GetCurrentDayName() { return GetDayName(time()); }
string GetCurrentMonth() { return CurrentMonth->Name; }
string GetCurrentSeason() { return CurrentSeason; }
// get seconds from the start of the day.
int GetCurrentTime() { return (GetTime(time()) - MidnightOffset) % (DAY_LENGTH * HOUR_LENGTH) + ticktock; }
int GetCurrentYear() { return CurrentYear; }
varargs int GetDay(int x) {
int tot, days, i, maxi;
if(!x) x = time();
#if MUDTIME_IS_REALTIME
return localtime(x)[LT_MDAY];
#else
days = absolute_value(GetTime(x) / (DAY_LENGTH * HOUR_LENGTH));
for(tot=0, i=0, maxi = sizeof(Months); i<maxi; i++)
tot += ((class month)Months[i])->Days;
days = (days % tot) + ( (x < DAY_ONE) ? 0 : 1 );
if( x < DAY_ONE ) {
i = sizeof(Months);
while(i--) {
if( days < ((class month)Months[i])->Days )
return ((class month)Months[i])->Days - days;
else days -= ((class month)Months[i])->Days;
}
return 0;
}
for(i=0, maxi = sizeof(Months); i<maxi; i++) {
if( days <= ((class month)Months[i])->Days ) return days;
else days -= ((class month)Months[i])->Days;
}
return 0;
#endif
}
varargs string GetDayName(int x) {
int days;
if(!x) x = time();
#if MUDTIME_IS_REALTIME
return Days[localtime(x)[LT_WDAY]];
#else
days = absolute_value(GetTime(x) / (DAY_LENGTH * HOUR_LENGTH));
return Days[days % sizeof(Days)];
#endif
}
string *GetDays() { return Days + ({}); }
int GetDaylightHours(string mon) {
int i;
i = sizeof(Months);
while(i--) {
if( ((class month)Months[i])->Name == mon )
return ((class month)Months[i])->DaylightHours;
}
return 0;
}
varargs int GetHour(int x) {
int y;
if(!x)
x = time();
#if MUDTIME_IS_REALTIME
return localtime(x)[LT_HOUR];
#else
y = absolute_value(GetTime(x));
y = y % (DAY_LENGTH * HOUR_LENGTH);
if( x < DAY_ONE ) y = (DAY_LENGTH * HOUR_LENGTH) - y;
return (y / HOUR_LENGTH);
#endif
}
varargs int GetMinutes(int x) {
int y;
if(!x)
x = time();
#if MUDTIME_IS_REALTIME
return localtime(x)[LT_MIN];
#else
y = absolute_value(GetTime(x));
y = y % (DAY_LENGTH * HOUR_LENGTH);
if( x < DAY_ONE ) y = (DAY_LENGTH * HOUR_LENGTH) - y;
return (y % HOUR_LENGTH) / (HOUR_LENGTH/60);
#endif
}
string GetMonth(int x) {
int monthIndex;
monthIndex = GetMonthIndex(x);
return Months[monthIndex]->Name;
}
private varargs int GetMonthIndex(int x) {
int tot, days, i, maxi;
if(!x) x = time();
#if MUDTIME_IS_REALTIME
return localtime(x)[LT_MON];
#else
if( x < DAY_ONE ) days = (DAY_ONE - x) / (DAY_LENGTH * HOUR_LENGTH);
else days = GetTime(x) / (DAY_LENGTH * HOUR_LENGTH);
for(tot=0, i=0, maxi = sizeof(Months); i<maxi; i++)
tot += ((class month)Months[i])->Days;
days = (days % tot) + ((x >= DAY_ONE) ? 1 : 0);
if( x < DAY_ONE ) {
i = sizeof(Months);
while(i--) {
if( days < ((class month)Months[i])->Days )
return i;
else days -= ((class month)Months[i])->Days;
}
return 0;
}
for(i=0, maxi = sizeof(Months); i<maxi; i++) {
if( days <= ((class month)Months[i])->Days )
return i;
else days -= ((class month)Months[i])->Days;
}
return 0;
#endif
}
string *GetMonths() {
string *ret = ({});
int i, maxi;
for(i=0, maxi = sizeof(Months); i<maxi; i++)
ret += ({ ((class month)Months[i])->Name });
return ret;
}
string GetSeason(int x) {
int monthIndex;
monthIndex = GetMonthIndex(x);
return Months[monthIndex]->Season;
}
varargs int GetTime(int x) { if(!x) x = time(); return (x - DAY_ONE); }
string GetTimeOfDay() { return TimeOfDay; }
function AddTimeEvent(string tod, function f) {
switch(tod) {
case "dawn": DawnCalls += ({ f }); break;
case "morning": MorningCalls += ({ f }); break;
case "noon": NoonCalls += ({ f }); break;
case "twilight": TwilightCalls += ({ f }); break;
case "night": NightCalls += ({ f }); break;
case "midnight": MidnightCalls += ({ f }); break;
default: return 0;
}
return f;
}
mapping GetTimeEvents() {
return ([ "dawn" : DawnCalls + ({}), "morning" : MorningCalls + ({}),
"noon" : NoonCalls + ({}), "twilight" : TwilightCalls + ({}),
"night" : NightCalls + ({}), "midnight" : MidnightCalls + ({}) ]);
}
varargs int GetYear(int x) {
int i, tot;
if(!x) x = time();
#if MUDTIME_IS_REALTIME
return localtime(x)[LT_YEAR];
#else
i = sizeof(Months);
while(i--) tot += ((class month)Months[i])->Days;
i = (GetTime(x) / (DAY_LENGTH * HOUR_LENGTH)) / tot;
if( x < DAY_ONE ) return i;
else return i + 1;
#endif
}
string GetYearString(int x) {
#if MUDTIME_IS_REALTIME
if( x < 0 ) return (x * (-1)) + " BC";
else return x + "";
#else
if( x < 0 ) return (x * (-1)) + " BN";
else return x + " NM";
#endif
}
/*
* Moon functions
*/
string array GetMoons() {
return map(keys(Moons), (: ((class moon)Moons[$1])->Name :));
}
string GetPhaseName(mixed val) {
if( stringp(val) ) {
val = GetPhase(val);
}
switch(val) {
case 0: return "new";
case 1: return "waxing";
case 2: return "waning";
case 3: return "full";
default: return "error";
}
}
int GetPhase(string m) {
int x, y, z;
m = convert_name(m);
x = ((class moon)Moons[m])->Phase;
y = GetTime(time()) % x;
z = x / 4;
return y / z;
}
int GetRadiantLight() {
switch( TimeOfDay ) {
case "night": return (GetMoonLight() * 2);
case "day": return 60;
default: return 30;
}
}
int GetMoonLight() {
string *moons;
int i, y = 0;
i = sizeof(moons = keys(Moons));
while(i--) {
int z;
z = GetPhase(moons[i]);
if( z == 4) z = 2;
y += z;
}
return y;
}
string GetLong(string arg) {
string array arr, mn;
object env;
string tmp;
int i;
if( !(env = environment(this_player())) )
return "You are in serious trouble.";
switch(arg) {
case "sun":
switch(GetTimeOfDay()) {
case "dawn":
return "The sun is hanging low in the eastern sky.";
case "day":
return "The sun is shining brightly in the daytime sky.";
case "twilight":
return "The sun is sinking into the western sky.";
case "night":
return "There is no sun to be seen.";
}
case "moon": case "moons":
if( GetTimeOfDay() != "night" ) return "During the day?";
else {
string *moons;
int x = 0;
i = sizeof(moons = keys(Moons));
while(i--) {
int y;
if( (y = GetPhase(moons[i])) == 0 ) continue;
else if( tmp )
tmp += (((class moon)Moons[moons[i]])->Name) +
" is " + GetPhaseName(y) + ".\n";
else tmp = "\n" +
"You gaze up at the sky, and see the moons...\n"+
(((class moon)Moons[moons[i]])->Name) +
" is " +
GetPhaseName(y) + ".\n";
x = 1;
}
if( !x ) return 0;
else return tmp;
}
case "sky":
if( GetTimeOfDay() == "night" ) {
tmp = GetLong("moon");
if( !tmp ) {
return "The sky is filled only with the glitter of stars.";
}
else {
return tmp;
}
}
else {
string sky;
tmp = GetLong("sun");
if( this_player() ) {
env = environment(this_player());
}
if( sky = env->GetSky() ) {
env = find_object(sky);
if( env ) {
object array obs = filter(all_inventory(env),
(: living($1) &&
!$1->GetInvis(this_player()) :));
/* function(object ob) { */
/* if( ob->GetInvis(this_player()) ) { */
/* return 0; */
/* } */
/* if( living(ob) ) { */
/* return 1; */
/* } */
/* return 0; */
/* }); */
if( sizeof(obs) ) {
int maxi = sizeof(obs);
sky = obs[i]->GetName();
if( maxi == 1 ) {
sky += " is flying in the sky.";
}
else {
for(i=1; i<maxi; i++) {
if( i == maxi-1 ) {
if( maxi == 2 ) {
sky += " and ";
}
else {
sky += ", and ";
}
}
else {
sky += ", ";
}
sky += obs[i]->GetName();
}
sky += " are flying in the sky.";
}
tmp = sky + "\n" + tmp;
}
}
}
return tmp;
}
default:
if( Moons[arg] ) return ((class moon)Moons[arg])->Description;
arr = map(mn = keys(Moons), (: ((class moon)Moons[$1])->Id :));
if( (i = member_array(arg, arr)) != -1 )
return ((class moon)Moons[mn[i]])->Description;
else return 0;
}
}
int eventShow(object who, string args) {
string str;
if( !who || !sizeof(args) ) return 0;
if( !str = GetLong(args) ) return 0;
if( !(string)environment(who)->GetClimateExposed() ) {
who->eventPrint("You can't see that from here!");
return 1;
}
who->eventPrint(str);
environment(who)->eventPrint((string)who->GetName() + " gazes toward the sky.", who);
return 1;
}
#ifndef __GLOBAL_H
#define __GLOBAL_H
#include <config.h>
#include <lib.h>
#if COMPAT_MODE
#include <compat.h>
#endif
#if MUDTIME_IS_REALTIME
# define DAY_ONE 0
# define HOUR_LENGTH 3600
# define DAY_LENGTH 24
#else
# define DAY_ONE 720550800
#endif
#define SEFUN "/secure/sefun/sefun"
#define DEBUG
#ifdef debug
#undef debug
#endif /* debug */
//#ifdef DEBUG
//#define debug(x, y) (find_player(x) || master())->eventPrint(x)
//#endif /* DEBUG */
#endif /* GLOBAL_H */
# /cfg/days.cfg.realtime
# from the Dead Souls 3 LPC Library
# days configuration file
# DO NOT EDIT!
# This file is used in the "realtime" mode,
# when mud time is same as Earth time.
# See days.cfg for customization.
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
NOTE! This one (months.cfg.realtime) should be verified and adjusted by someone competent.
Last number is amout of daylight hours per day, so setting it to '24' as somebody else did is WRONG.
# /cfg/months.cfg.realtime
# from the Dead Souls 3 LPC Library
# months configuration file
# DO NOT EDIT!
# This file is used in the "realtime" mode,
# when mud time is same as Earth time.
# See months.cfg for customization.
January:winter:31:8
February:winter:28:10
March:spring:31:11
April:spring:30:12
May:spring:31:14
June:summer:30:16
July:summer:31:14
August:summer:31:12
September:autumn:30:11
October:autumn:31:10
November:autumn:30:8
December:winter:31:6
Share & Enjoy. Feedback is welcome.
//'Skal