mud/lib/daemon/seasons.c
2020-09-06 05:43:07 -07:00

593 lines
18 KiB
C

/* /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 <function.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, pending;
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(!this_player() || !archp(this_player())) return 0;
if(!tick) tick = 0;
ticktock = tick;
remove_call_out(pending);
eventConfigure();
//return GetCurrentTime()/1200;
return GetCurrentTime();
}
int GetTickTock(){ return ticktock; }
int *GetMudTime(){
//return ({ GetHour(GetCurrentTime()), GetMinutes(GetCurrentTime()) });
return ({ GetHour(time()+ticktock), GetMinutes(time()+ticktock) });
}
static void create() {
string *lines;
int i, maxi;
daemon::create();
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;
DawnCalls = ({});
MorningCalls = ({});
NoonCalls = ({});
TwilightCalls = ({});
NightCalls = ({});
MidnightCalls = ({});
days = GetTime(time()+ticktock) / (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;
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";
pending = call_out( (: eventDawn :), Dawn - x);
}
else if( x < Morning ) {
TimeOfDay = "dawn";
pending = call_out( (: eventMorning :), Morning - x);
}
else if( x < Noon ) {
TimeOfDay = "day";
pending = call_out( (: eventNoon :), Noon - x);
}
else if( x < Twilight ) {
TimeOfDay = "day";
pending = call_out( (: eventTwilight :), Twilight - x);
}
else if( x < Night ) {
TimeOfDay = "twilight";
pending = call_out( (: eventNight :), Night - x );
}
else {
TimeOfDay = "night";
pending = call_out( (: eventMidnight :), (DAY_LENGTH * HOUR_LENGTH) - x);
}
}
static void eventDawn() {
object *obs;
int i;
pending = call_out( (: eventMorning :), Morning - GetCurrentTime() );
TimeOfDay = "dawn";
obs = filter(users(), (: environment($1) &&
environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!(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;
pending = call_out( (: eventNoon :), Noon - GetCurrentTime());
TimeOfDay = "day";
obs = filter(users(), (: environment($1) &&
environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!(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;
pending = call_out( (: eventTwilight :), Twilight - GetCurrentTime());
TimeOfDay = "day";
i = sizeof(NoonCalls);
while(i--) catch(evaluate(NoonCalls[i]));
}
static void eventTwilight() {
object *obs;
int i;
pending = call_out( (: eventNight :), Night - GetCurrentTime() );
TimeOfDay = "twilight";
obs = filter(users(), (: environment($1) &&
environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!(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;
pending = call_out( (: eventMidnight :),
(DAY_LENGTH * HOUR_LENGTH) - GetCurrentTime() );
TimeOfDay = "night";
obs = filter(users(), (: environment($1) &&
environment($1)->GetClimateExposed() &&
inherits(LIB_ROOM,environment($1)) &&
!(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;
}
pending = call_out( (: eventDawn :), Dawn);
TimeOfDay = "night";
i = sizeof(MidnightCalls);
while(i--) catch(evaluate(MidnightCalls[i]));
}
int GetCurrentDay() { return CurrentDay; }
string GetCurrentDayName() { return GetDayName(time()+ticktock); }
string GetCurrentMonth() { return CurrentMonth->Name; }
string GetCurrentSeason() { return CurrentSeason; }
// get seconds from the start of the day.
int GetCurrentTime() { return GetTime(time()+ticktock) % (DAY_LENGTH * HOUR_LENGTH); }
int GetCurrentYear() { return CurrentYear; }
varargs int GetDay(int x) {
int tot, days, i, maxi;
if(!x) x = time()+ticktock;
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;
}
varargs string GetDayName(int x) {
int days;
if(!x) x = time()+ticktock;
days = absolute_value(GetTime(x) / (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;
}
varargs int GetHour(int x) {
int y;
if(!x)
x = time()+ticktock;
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);
}
varargs int GetMinutes(int x) {
int y;
if(!x)
x = time()+ticktock;
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 varargs int GetMonthIndex(int x) {
int tot, days, i, maxi;
if(!x) x = time()+ticktock;
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;
}
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()+ticktock; 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()+ticktock;
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;
}
string GetYearString(int x) {
if( x < 0 ) return (x * (-1)) + " BN";
else return x + " NM";
}
/*
* 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()+ticktock) % 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( !environment(who)->GetClimateExposed() ) {
who->eventPrint("You can't see that from here!");
return 1;
}
who->eventPrint(str);
environment(who)->eventPrint(who->GetName() + " gazes toward the sky.", who);
return 1;
}