diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 662ad85ca14..5b561406f23 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -83,6 +83,28 @@ #define EVENT_LEVEL_MODERATE 2 #define EVENT_LEVEL_MAJOR 3 +#define JANUARY 1 +#define FEBRUARY 2 +#define MARCH 3 +#define APRIL 4 +#define MAY 5 +#define JUNE 6 +#define JULY 7 +#define AUGUST 8 +#define SEPTEMBER 9 +#define OCTOBER 10 +#define NOVEMBER 11 +#define DECEMBER 12 + +//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead +#define NEW_YEAR "New Year" +#define VALENTINES "Valentine's Day" +#define APRIL_FOOLS "April Fool's Day" +#define EASTER "Easter" +#define HALLOWEEN "Halloween" +#define CHRISTMAS "Christmas" +#define FRIDAY_13TH "Friday the 13th" + //Light color defs, for light-emitting things //Some defs may be pure color- this is for neatness, and configurability. Changing #define COLOR_ is a bad idea. #define LIGHT_COLOR_CYAN "#7BF9FF" @@ -105,4 +127,4 @@ #define LIGHT_COLOR_PURPLE "#CD00CD" #define LIGHT_COLOR_PINK "#FF33CC" -#define LIGHT_COLOR_WHITE "#FFFFFF" \ No newline at end of file +#define LIGHT_COLOR_WHITE "#FFFFFF" diff --git a/code/controllers/Processes/event.dm b/code/controllers/Processes/event.dm index 9948ef18ea6..64cd6031c8e 100644 --- a/code/controllers/Processes/event.dm +++ b/code/controllers/Processes/event.dm @@ -1,6 +1,48 @@ /datum/controller/process/event/setup() name = "event" schedule_interval = 20 // every 2 seconds + if(!holiday_master) + holiday_master = new + holiday_master.Setup() /datum/controller/process/event/doWork() - event_manager.process() \ No newline at end of file + event_manager.process() + holiday_master.process() + +///////// +//Holiday controller +///////// + +var/global/datum/controller/holiday/holiday_master //This has to be defined before world. + +/datum/controller/holiday + var/list/holidays + +/datum/controller/holiday/proc/Setup() + getHoliday() + +/datum/controller/holiday/proc/process() + if(holiday_master.holidays) + for(var/datum/holiday/H in holiday_master.holidays) + if(H.eventChance) + if(prob(H.eventChance)) + H.handle_event() + +/datum/controller/holiday/proc/getHoliday() + if(!config.allow_holidays) return //Holiday stuff was not enabled in the config! + + var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year + var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month + var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day + + for(var/H in typesof(/datum/holiday) - /datum/holiday) + var/datum/holiday/holiday = new H() + if(holiday.shouldCelebrate(DD, MM, YY)) + holiday.celebrate() + if(!holidays) + holidays = list() + holidays[holiday.name] = holiday + + if(holidays) + holidays = shuffle(holidays) + world.update_status() \ No newline at end of file diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 9f123cb82de..75253e430e4 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -153,6 +153,7 @@ var/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000) var/starlight = 0 // Whether space turfs have ambient light or not + var/allow_holidays = 0 /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode @@ -377,7 +378,7 @@ config.popup_admin_pm = 1 if("allow_holidays") - Holiday = 1 + config.allow_holidays = 1 if("use_irc_bot") use_irc_bot = 1 diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 98f1f81aafc..bafcec2807b 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -158,8 +158,11 @@ var/global/datum/controller/gameticker/ticker world << "Enjoy the game!" world << sound('sound/AI/welcome.ogg') // Skie - //Holiday Round-start stuff ~Carn - Holiday_Game_Start() + if(holiday_master.holidays) + world << "and..." + for(var/holidayname in holiday_master.holidays) + var/datum/holiday/holiday = holiday_master.holidays[holidayname] + world << "

[holiday.greet()]

" spawn(0) // Forking dynamic room selection var/list/area/dynamic/source/available_source_candidates = typesof(/area/dynamic/source) - /area/dynamic/source diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 24fddb2e288..363f3d504da 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -108,8 +108,8 @@ var/list/admin_verbs_spawn = list( /client/proc/respawn_character ) var/list/admin_verbs_server = list( - /client/proc/Set_Holiday, /client/proc/ToRban, + /client/proc/Set_Holiday, /datum/admins/proc/startnow, /datum/admins/proc/restart, /datum/admins/proc/delay, diff --git a/code/modules/holiday/christmas.dm b/code/modules/holiday/christmas.dm new file mode 100644 index 00000000000..9636a1681f6 --- /dev/null +++ b/code/modules/holiday/christmas.dm @@ -0,0 +1,65 @@ +/datum/holiday/xmas/celebrate() + for(var/obj/structure/flora/tree/pine/xmas in world) + if(!(xmas.z in config.station_levels)) continue + for(var/turf/simulated/floor/T in orange(1,xmas)) + for(var/i=1,i<=rand(1,5),i++) + new /obj/item/weapon/a_gift(T) + for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) + Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) + +/datum/holiday/xmas/handle_event() + spawnTree() + +/datum/holiday/xmas/proc/spawnTree() + for(var/obj/structure/flora/tree/pine/xmas in world) + var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) + evil_tree.icon_state = xmas.icon_state + evil_tree.icon_living = evil_tree.icon_state + evil_tree.icon_dead = evil_tree.icon_state + evil_tree.icon_gib = evil_tree.icon_state + del(xmas) + +/obj/item/weapon/toy/xmas_cracker + name = "xmas cracker" + icon = 'icons/obj/christmas.dmi' + icon_state = "cracker" + desc = "Directions for use: Requires two people, one to pull each end." + var/cracked = 0 + +/obj/item/weapon/toy/xmas_cracker/New() + ..() + +/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user) + if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) + target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.") + var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc) + Joke.name = "[pick("awful","terrible","unfunny")] joke" + Joke.info = pick("What did one snowman say to the other?\n\n'Is it me or can you smell carrots?'", + "Why couldn't the snowman get laid?\n\nHe was frigid!", + "Where are santa's helpers educated?\n\nNowhere, they're ELF-taught.", + "What happened to the man who stole advent calanders?\n\nHe got 25 days.", + "What does Santa get when he gets stuck in a chimney?\n\nClaus-trophobia.", + "Where do you find chili beans?\n\nThe north pole.", + "What do you get from eating tree decorations?\n\nTinsilitis!", + "What do snowmen wear on their heads?\n\nIce caps!", + "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", + "Why doesn’t Santa have any children?\n\nBecause he only comes down the chimney.") + new /obj/item/clothing/head/festive(target.loc) + user.update_icons() + cracked = 1 + icon_state = "cracker1" + var/obj/item/weapon/toy/xmas_cracker/other_half = new /obj/item/weapon/toy/xmas_cracker(target) + other_half.cracked = 1 + other_half.icon_state = "cracker2" + target.put_in_active_hand(other_half) + playsound(user, 'sound/effects/snap.ogg', 50, 1) + return 1 + return ..() + +/obj/item/clothing/head/festive + name = "festive paper hat" + icon_state = "xmashat" + desc = "A crappy paper hat that you are REQUIRED to wear." + flags_inv = 0 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + diff --git a/code/modules/holiday/holiday.dm b/code/modules/holiday/holiday.dm new file mode 100644 index 00000000000..727c899d2eb --- /dev/null +++ b/code/modules/holiday/holiday.dm @@ -0,0 +1,358 @@ +/datum/holiday + var/name = "Bugsgiving" + //Right now, only holidays that take place on a certain day or within a time period are supported + //It would be nice to support things like "the second monday in march" or "the first sunday after the second sunday in june" + var/begin_day = 1 + var/begin_month = 0 + var/end_day = 0 // Default of 0 means the holiday lasts a single day + var/end_month = 0 + var/eventChance = 0 + +// This proc gets run before the game starts when the holiday is activated. Do festive shit here. +/datum/holiday/proc/celebrate() + +// When the round starts, this proc is ran to get a text message to display to everyone to wish them a happy holiday +/datum/holiday/proc/greet() + return "Have a happy [name]!" + +// Returns special prefixes for the station name on certain days. You wind up with names like "Christmas Object Epsilon". See new_station_name() +/datum/holiday/proc/getStationPrefix() + //get the first word of the Holiday and use that + var/i = findtext(name," ",1,0) + return copytext(name,1,i) + +// Return 1 if this holidy should be celebrated today +/datum/holiday/proc/shouldCelebrate(dd, mm, yy) + if(!end_day) + end_day = begin_day + if(!end_month) + end_month = begin_month + + if(end_month > begin_month) //holiday spans multiple months in one year + if(mm == end_month) //in final month + if(dd <= end_day) + return 1 + + else if(mm == begin_month)//in first month + if(dd >= begin_day) + return 1 + + else if(mm in begin_month to end_month) //holiday spans 3+ months and we're in the middle, day doesn't matter at all + return 1 + + else if(end_month == begin_month) // starts and stops in same month, simplest case + if(mm == begin_month && (dd in begin_day to end_day)) + return 1 + + else // starts in one year, ends in the next + if(mm >= begin_month && dd >= begin_day) // Holiday ends next year + return 1 + if(mm <= end_month && dd <= end_day) // Holiday started last year + return 1 + + return 0 + +/datum/holiday/proc/handle_event() //used for special holiday events + return + +// The actual holidays + +/datum/holiday/new_year + name = NEW_YEAR + begin_day = 30 // 1 day early + begin_month = DECEMBER + end_day = 5 //4 days extra + end_month = JANUARY + +/datum/holiday/groundhog + name = "Groundhog Day" + begin_day = 2 + begin_month = FEBRUARY + +/datum/holiday/valentines + name = VALENTINES + begin_day = 9 //6 days early + begin_month = FEBRUARY + end_day = 15 //1 day extra + +/datum/holiday/random_kindness + name = "Random Acts of Kindness Day" + begin_day = 17 + begin_month = FEBRUARY + +/datum/holiday/random_kindness/greet() + return "Go do some random acts of kindness for a stranger!" //haha yeah right + +/datum/holiday/pi + name = "Pi Day" + begin_day = 14 + begin_month = MARCH + +/datum/holiday/no_this_is_patrick + name = "St. Patrick's Day" + begin_day = 17 + begin_month = MARCH + +/datum/holiday/april_fools + name = APRIL_FOOLS + begin_day = 1 + begin_month = APRIL + end_day = 8 //7 days extra so everyone can enjoy the festivities + +/datum/holiday/fourtwenty + name = "Four-Twenty" + begin_day = 20 + begin_month = APRIL + +/datum/holiday/earth + name = "Earth Day" + begin_day = 22 + begin_month = APRIL + +/datum/holiday/labor + name = "Labor Day" + begin_day = 1 + begin_month = MAY + +/datum/holiday/firefighter + name = "Firefighter's Day" + begin_day = 4 + begin_month = MAY + +// No holidays in June :'( + +/datum/holiday/doctor + name = "Doctor's Day" + begin_day = 1 + begin_month = JULY + +/datum/holiday/UFO + name = "UFO Day" + begin_day = 2 + begin_month = JULY + +/datum/holiday/writer + name = "Writer's Day" + begin_day = 8 + begin_month = JULY + +/datum/holiday/friendship + name = "Friendship Day" + begin_day = 30 + begin_month = JULY + +/datum/holiday/friendship/greet() + return "Have a magical [name]!" + +/datum/holiday/beer + name = "Beer Day" + begin_day = 5 + begin_month = AUGUST + +/datum/holiday/pirate + name = "Talk-Like-a-Pirate Day" + begin_day = 19 + begin_month = SEPTEMBER + +/datum/holiday/pirate/greet() + return "Ye be talkin' like a pirate today or else ye'r walkin' tha plank, matey!" + +/datum/holiday/questions + name = "Stupid-Questions Day" + begin_day = 28 + begin_month = SEPTEMBER + +/datum/holiday/questions/greet() + return "Are you having a happy [name]?" + +/datum/holiday/animal + name = "Animal's Day" + begin_day = 4 + begin_month = OCTOBER + +/datum/holiday/smile + name = "Smiling Day" + begin_day = 7 + begin_month = OCTOBER + +/datum/holiday/boss + name = "Boss' Day" + begin_day = 16 + begin_month = OCTOBER + +/datum/holiday/halloween + name = HALLOWEEN + begin_day = 24 //7 days early + begin_month = OCTOBER + end_day = 7 //7 days extra + end_month = NOVEMBER + +/datum/holiday/halloween/greet() + return "Have a spooky Halloween!" + +/datum/holiday/vegan + name = "Vegan Day" + begin_day = 1 + begin_month = NOVEMBER + +/datum/holiday/kindness + name = "Kindness Day" + begin_day = 13 + begin_month = NOVEMBER + +/datum/holiday/flowers + name = "Flowers Day" + begin_day = 19 + begin_month = NOVEMBER + +/datum/holiday/hello + name = "Saying-'Hello' Day" + begin_day = 21 + begin_month = NOVEMBER + +/datum/holiday/hello/greet() + return "[pick(list("Aloha", "Bonjour", "Hello", "Hi", "Greetings", "Salutations", "Bienvenidos", "Hola", "Howdy"))]! " + ..() + +/datum/holiday/human_rights + name = "Human-Rights Day" + begin_day = 10 + begin_month = DECEMBER + +/datum/holiday/monkey + name = "Monkey Day" + begin_day = 14 + begin_month = DECEMBER + +/datum/holiday/xmas + name = CHRISTMAS + begin_day = 18 //7 days early + begin_month = DECEMBER + end_day = 8 //14 days extra, christmas is important + end_month = JANUARY + eventChance = 20 + +/datum/holiday/xmas/greet() + return "Have a merry Christmas!" + +/datum/holiday/boxing + name = "Boxing Day" + begin_day = 26 + begin_month = DECEMBER + +/datum/holiday/friday_thirteenth + name = "Friday the 13th" + +/datum/holiday/friday_thirteenth/shouldCelebrate(dd, mm, yy) + if(dd == 13) + if(time2text(world.timeofday, "DDD") == "Fri") + return 1 + return 0 + +/datum/holiday/friday_thirteenth/getStationPrefix() + return pick("Mike","Friday","Evil","Myers","Murder","Deathly","Stabby") + +/datum/holiday/easter + name = EASTER + var/const/days_early = 1 //to make editing the holiday easier + var/const/days_extra = 6 + +/datum/holiday/easter/shouldCelebrate(dd, mm, yy) +// Easter's celebration day is as snowflakey as Uhangi's code + + if(!begin_month) + + var/yy_string = "[yy]" +// year = days after March 22that Easter falls on that year. +// For 2015 Easter is on April 5th, so 2015 = 14 since the 5th is 14 days past the 22nd +// If it's 2040 and this is still in use, invent a time machine and teach me a better way to do this. Also tell us about HL3. + var/list/easters = list( + "15" = 14,\ + "16" = 6,\ + "17" = 25,\ + "18" = 10,\ + "19" = 30,\ + "20" = 22,\ + "21" = 13,\ + "22" = 26,\ + "23" = 18,\ + "24" = 9,\ + "25" = 29,\ + "26" = 14,\ + "27" = 6,\ + "28" = 25,\ + "29" = 10,\ + "30" = 30,\ + "31" = 23,\ + "32" = 6,\ + "33" = 26,\ + "34" = 18,\ + "35" = 3,\ + "36" = 22,\ + "37" = 14,\ + "38" = 34,\ + "39" = 19,\ + "40" = 9,\ + ) + + begin_day = easters[yy_string] + if(begin_day <= 9) + begin_day += 22 + begin_month = MARCH + else + begin_day -= 9 + begin_month = APRIL + + end_day = begin_day + days_extra + end_month = begin_month + if(end_day >= 32 && end_month == MARCH) //begins in march, ends in april + end_day -= 31 + end_month++ + if(end_day >= 31 && end_month == APRIL) //begins in april, ends in june + end_day -= 30 + end_month++ + + begin_day -= days_early + if(begin_day <= 0) + if(begin_month == APRIL) + begin_day += 31 + begin_month-- //begins in march, ends in april + +// world << "Easter calculates to be on [begin_day] of [begin_month] ([days_early] early) to [end_day] of [end_month] ([days_extra] extra) for 20[yy]" + return ..() + + +/client/proc/Set_Holiday(T as text|null) + set name = ".Set Holiday" + set category = "Event" + set desc = "Force-set the Holiday variable to make the game think it's a certain day." + if(!check_rights(R_SERVER)) return + + var/list/choice = list() + for(var/H in typesof(/datum/holiday) - /datum/holiday) + choice += "[H]" + + choice += "--CANCEL--" + + var/selected = input("What holiday would you like to force?","Holiday Forcing","--CANCEL--") in choice + + if(selected == "--CANCEL--") + return + + var/selected2path = text2path(selected) + if(!ispath(selected2path) || !selected2path) return + + var/datum/holiday/H = new selected2path + if(!istype(H)) return + + H.celebrate() + if(!holiday_master.holidays) + holiday_master.holidays = list() + holiday_master.holidays[H.name] = H + + station_name = null + station_name() + //update our hub status + world.update_status() + + message_admins("\blue ADMIN: Event: [key_name(src)] force-set Holiday to \"[H]\"") + log_admin("[key_name(src)] force-set Holiday to \"[H]\"") \ No newline at end of file diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index ac55fa53d1a..7ec4763d572 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -86,7 +86,7 @@ /obj/item/weapon/paper/attack_self(mob/living/user as mob) src.examine(user) - if(rigged && (Holiday == "April Fool's Day")) + if(rigged && (holiday_master.holidays && holiday_master.holidays[APRIL_FOOLS])) if(spam_flag == 0) spam_flag = 1 playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index a30412156ee..67d1eacab72 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -71,7 +71,7 @@ papers.Remove(P) else P = new /obj/item/weapon/paper - if(Holiday == "April Fool's Day") + if(holiday_master.holidays && holiday_master.holidays[APRIL_FOOLS]) if(prob(30)) P.info = "HONK HONK HONK HONK HONK HONK HONK
HOOOOOOOOOOOOOOOOOOOOOONK
APRIL FOOLS
" P.rigged = 1 diff --git a/paradise.dme b/paradise.dme index 6c38167ecc7..4ba9dd736c0 100644 --- a/paradise.dme +++ b/paradise.dme @@ -308,9 +308,6 @@ #include "code\game\gamemodes\events\clang.dm" #include "code\game\gamemodes\events\power_failure.dm" #include "code\game\gamemodes\events\wormholes.dm" -#include "code\game\gamemodes\events\holidays\Christmas.dm" -#include "code\game\gamemodes\events\holidays\Holidays.dm" -#include "code\game\gamemodes\events\holidays\Other.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\heist\heist.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" @@ -1133,6 +1130,8 @@ #include "code\modules\food\recipes_microwave.dm" #include "code\modules\food\recipes_oven.dm" #include "code\modules\genetics\side_effects.dm" +#include "code\modules\holiday\christmas.dm" +#include "code\modules\holiday\holiday.dm" #include "code\modules\hydroponics\_hydro_setup.dm" #include "code\modules\hydroponics\grown.dm" #include "code\modules\hydroponics\grown_inedible.dm"