/* /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 */ #include <lib.h> #include <cfg.h> #include <config.h> #include "include/seasons.h" inherit LIB_DAEMON; private static int CurrentDay, CurrentYear, Dawn, Morning, Twilight, Night; private static int ticktock; private static string CurrentSeason, TimeOfDay; private static mapping Moons; private static class month CurrentMonth; private static string *Days; private static function *DawnCalls, *MorningCalls, *TwilightCalls; private static function *NightCalls, *MidnightCalls; private static class month *Months; int eventTickTock(int tick){ if(!tick) tick = 0; ticktock = tick; eventConfigure(); return GetCurrentTime()/1200; } int GetTickTock(){ return ticktock; } int *GetMudTime(){ return ({ GetHour(GetCurrentTime()), GetMinutes(GetCurrentTime()) }); } static void create() { string *lines; int i, maxi; daemon::create(); MorningCalls = ({}); DawnCalls = ({}); TwilightCalls = ({}); NightCalls = ({}); MidnightCalls = ({}); ticktock = 0; maxi = sizeof(lines = filter(explode(read_file(CFG_MONTHS), "\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); } Days = filter(explode(read_file(CFG_DAYS), "\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; days = (time() - DAY_ONE) / (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; } x = CurrentMonth->DaylightHours * HOUR_LENGTH; Morning = ((DAY_LENGTH * HOUR_LENGTH) - x) / 2; Twilight = Morning + x; 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 < 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; call_out( (: eventMorning :), Morning - GetCurrentTime() ); TimeOfDay = "dawn"; obs = filter(users(), (: environment($1) && (string)environment($1)->GetClimate()!="indoors" && !((int)environment($1)->GetProperty("no time")) :)); message("environment", "%^YELLOW%^The sun appears just over the horizon.", obs ); i = sizeof(DawnCalls); while(i--) catch(evaluate(DawnCalls[i])); } static void eventMorning() { object *obs; int i; call_out( (: eventTwilight :), Twilight - GetCurrentTime()); TimeOfDay = "day"; obs = filter(users(), (: environment($1) && (string)environment($1)->GetClimate()!="indoors" && !((int)environment($1)->GetProperty("no time")) :)); message("environment", "%^BOLD%^YELLOW%^The sun now shines completely " "on a new day.", obs); i = sizeof(MorningCalls); while(i--) catch(evaluate(MorningCalls[i])); } static void eventTwilight() { object *obs; int i; call_out( (: eventNight :), Night - GetCurrentTime() ); TimeOfDay = "twilight"; obs = filter(users(), (: environment($1) && (string)environment($1)->GetClimate()!="indoors" && !((int)environment($1)->GetProperty("no time")) :)); message("environment", "%^CYAN%^The sun begins to fall away into " "twilight.", obs); i = sizeof(TwilightCalls); while(i--) catch(evaluate(TwilightCalls[i])); } static void eventNight() { object *obs; int i; call_out( (: eventMidnight :), DAY_LENGTH - GetCurrentTime() ); TimeOfDay = "night"; obs = filter(users(), (: environment($1) && (string)environment($1)->GetClimate()!="indoors" && !((int)environment($1)->GetProperty("no time")) :)); message("environment", "%^BOLD%^BLUE%^Night darkens all that is real.", obs); i = sizeof(NightCalls); while(i--) catch(evaluate(NightCalls[i])); } 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; } call_out( (: eventDawn :), Dawn); TimeOfDay = "night"; 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; } int GetCurrentTime() { return (time()- DAY_ONE) % (DAY_LENGTH * HOUR_LENGTH) + ticktock; } int GetCurrentYear() { return CurrentYear; } int GetDay(int x) { int tot, days, i, maxi; days = absolute_value((x - DAY_ONE) / (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; } string GetDayName(int x) { int days; days = absolute_value((x - DAY_ONE) / (DAY_LENGTH * HOUR_LENGTH)); return Days[days % sizeof(Days)]; } 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; } int GetHour(int x) { int y; 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); } int GetMinutes(int x) { int y; 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); } string GetMonth(int x) { int monthIndex; monthIndex = GetMonthIndex(x); return Months[monthIndex]->Name; } private int GetMonthIndex(int x) { int tot, days, i, maxi; if( x < DAY_ONE ) days = (DAY_ONE - x) / (DAY_LENGTH * HOUR_LENGTH); else days = (x - DAY_ONE) / (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; } 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; } int GetTime(int x) { 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 "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 + ({}), "twilight" : TwilightCalls + ({}), "night" : NightCalls + ({}), "midnight" : MidnightCalls + ({}) ]); } int GetYear(int x) { int i, tot; i = sizeof(Months); while(i--) tot += ((class month)Months[i])->Days; i = ((x - DAY_ONE) / (DAY_LENGTH * HOUR_LENGTH)) / tot; if( x < DAY_ONE ) return i; else return i + 1; } string GetYearString(int x) { if( x < 0 ) return (x * (-1)) + " BN"; else return x + " NM"; } 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 = (time() - DAY_ONE) % 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]) ) continue; else if( tmp ) tmp += capitalize(((class moon)Moons[moons[i]])->Id) + " is " + GetPhaseName(y) + ". "; else tmp = "\n" + capitalize(((class moon)Moons[moons[i]])->Id) + " is " + GetPhaseName(y) + ". "; 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), 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; } } string array GetMoons() { return map(keys(Moons), (: ((class moon)Moons[$1])->Name :)); } int eventShow(object who, string args) { string str; if( !who || !sizeof(args) ) return 0; if( !str = GetLong(args) ) return 0; if( (string)environment(who)->GetClimate() == "indoors" ) { who->eventPrint("You are indoors!"); return 1; } who->eventPrint(str); environment(who)->eventPrint((string)who->GetName() + " gazes toward the sky.", who); return 1; }