From 3d9fd8d6a0feeafbe0621a86cfa3938d7f67a340 Mon Sep 17 00:00:00 2001 From: MrPerson Date: Fri, 15 May 2015 20:52:39 -0700 Subject: [PATCH] Change holidays into datums Holidays are now actual datums with procs and vars and everything. Holidays run a proc called celebrate() when it's time to celebrate them. Currently none of them do anything but that should change, wink wink. Holidays can now run for more than a day. The important ones, april fools, christmas, halloween, new years, and easter, all last at least a week. The idea is so people can celebrate christmas in game without having to, you know, actually play on fucking christmas. And also to put a time limit on how long stuff like the annoying spookoween closet skeletons will stick around so it doesn't overstay its welcome and become annoying as shit like last year. The event SS now allows more than 1 holiday to run at a time. This matters for new years + christmas, easter + april fools, easter + 4/20, and any holiday that can happen on friday the 13th. The events get stored in a list that's only initialized if there's an active holiday so testing for potential holidays is still pretty easy. Added more easter dates so we won't have to add more until 2040. The current batch run out in 2017. :-------------PARACODE NOTES------------: Tied to event process Extra procs for holidays to be able to run special events alone Admin manual-override functionality maintained and ported to new system --- code/__DEFINES/misc.dm | 24 +- code/controllers/Processes/event.dm | 44 +++- code/controllers/configuration.dm | 3 +- code/game/gamemodes/gameticker.dm | 7 +- code/modules/admin/admin_verbs.dm | 2 +- code/modules/holiday/christmas.dm | 65 +++++ code/modules/holiday/holiday.dm | 358 ++++++++++++++++++++++++++++ code/modules/paperwork/paper.dm | 2 +- code/modules/paperwork/paperbin.dm | 2 +- paradise.dme | 6 +- 10 files changed, 501 insertions(+), 12 deletions(-) create mode 100644 code/modules/holiday/christmas.dm create mode 100644 code/modules/holiday/holiday.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index bb6a0aad684..b067f268d88 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -81,4 +81,26 @@ #define EVENT_LEVEL_MUNDANE 1 #define EVENT_LEVEL_MODERATE 2 -#define EVENT_LEVEL_MAJOR 3 \ No newline at end of file +#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" \ No newline at end of file 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 564e5e2a9dc..1de6bcf1870 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" @@ -1122,6 +1119,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" @@ -1719,7 +1718,6 @@ #include "code\modules\shuttles\shuttle_specops.dm" #include "code\modules\shuttles\shuttle_supply.dm" #include "code\modules\shuttles\shuttles_multi.dm" -#include "code\modules\shuttles\whiteship.dm" #include "code\modules\store\items.dm" #include "code\modules\store\store.dm" #include "code\modules\supermatter\supermatter.dm"