From d27c64c3a8ec79c383f86012fea80da7dd89f9a8 Mon Sep 17 00:00:00 2001 From: coiax Date: Sat, 15 Dec 2018 23:44:53 +0000 Subject: [PATCH] Christmas code changes (#41763) * Christmas code changes :cl: coiax add: Santa can now examine presents to see what's inside. del: Santa no longer has a mass summon presents spell, because of his new regenerating bag! add: Santa's bag regenerates presents as long as Santa is holding it. balance: You can only find one gift under a christmas tree per round, no matter how many trees you search. balance: Santa's teleport does not announce where he's going. fix: Fixed Santa not having a full head and beard of white hair. fix: Fixed Santa not being genetically white-haired. fix: Fixed Concentrated Barber's Aid not growing extreme amounts of hair. /:cl: The `box` var has been moved down from `/datum/outfit/job` to `/datum/outfit`. Added unlimited christmas tree with presents, for testing. Santa's restriction against opening presents is now done by TRAIT_CANNOT_OPEN_PRESENTS. Santa's ability to see inside presents is done by the TRAIT_PRESENT_VISION, which also determines if Santa's Bag will regenerate presents every 30 to 60 seconds. Santa no longer starts with a breath mask and O2 tank, but instead has an internals box. Santa no longer has a no-access gold ID, he can teleport from room to room! Gifts determine what type is inside them on initialization, rather than when unwrapped. - Reasoning - Unlike last year, there are various possible methods of accessing christmas trees spawners, allowing for an unlimited number of anything presents. Cutting down the presents to one per round regardless of tree count will avoid this. Santa should be able to see what he's giving, because then he can reward the naughty and nice children with different gifts. * Missed a merge * Adds present investigate logs, and visible messages * Use the body+mind checking of mob.has_trait * Less globals, more static vars on types; also event renaming --- code/__DEFINES/logging.dm | 1 + code/__DEFINES/traits.dm | 3 +++ code/_globalvars/lists/flavor_misc.dm | 2 +- code/_globalvars/lists/mobs.dm | 1 + code/datums/components/storage/storage.dm | 5 ++-- code/datums/outfit.dm | 8 +++++++ code/game/objects/items/gift.dm | 22 ++++++++++++----- code/game/objects/items/storage/backpack.dm | 24 ++++++++++++++++--- code/game/objects/structures/flora.dm | 19 ++++++++++++--- code/modules/admin/admin_investigate.dm | 2 +- code/modules/antagonists/santa/santa.dm | 14 +++++------ code/modules/clothing/outfits/event.dm | 16 +++++-------- code/modules/events/holiday/xmas.dm | 2 +- code/modules/jobs/job_types/job.dm | 8 +------ .../chemistry/reagents/other_reagents.dm | 2 +- .../spells/spell_types/area_teleport.dm | 16 ++++++++----- code/modules/spells/spell_types/wizard.dm | 7 ++++++ 17 files changed, 104 insertions(+), 48 deletions(-) diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 2784f9d782b..67264694034 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -16,6 +16,7 @@ #define INVESTIGATE_EXONET "exonet" #define INVESTIGATE_NANITES "nanites" #define INVESTIGATE_CIRCUIT "circuit" +#define INVESTIGATE_PRESENTS "presents" // Logging types for log_message() #define LOG_ATTACK (1 << 0) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 962634f35df..2eb7107601a 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -57,6 +57,8 @@ #define TRAIT_PARALYSIS_R_ARM "para-r-arm" #define TRAIT_PARALYSIS_L_LEG "para-l-leg" #define TRAIT_PARALYSIS_R_LEG "para-r-leg" +#define TRAIT_CANNOT_OPEN_PRESENTS "cannot-open-presents" +#define TRAIT_PRESENT_VISION "present-vision" #define TRAIT_DISK_VERIFIER "disk-verifier" #define TRAIT_NOMOBSWAP "no-mob-swap" #define TRAIT_XRAY_VISION "xray_vision" @@ -108,6 +110,7 @@ #define GENETICS_SPELL "genetics_spell" #define EYES_COVERED "eyes_covered" #define CULT_EYES "cult_eyes" +#define TRAIT_SANTA "santa" #define SCRYING_ORB "scrying-orb" #define ABDUCTOR_ANTAGONIST "abductor-antagonist" #define NUKEOP_TRAIT "nuke-op" diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 35f548261bf..20554d476f8 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -36,7 +36,7 @@ GLOBAL_LIST_EMPTY(wings_open_list) GLOBAL_LIST_EMPTY(r_wings_list) GLOBAL_LIST_EMPTY(moth_wings_list) GLOBAL_LIST_EMPTY(caps_list) - + GLOBAL_LIST_INIT(color_list_ethereal, list("F Class(Green)" = "97ee63", "F2 Class (Light Green)" = "00fa9a", "F3 Class (Dark Green)" = "37835b", "M Class (Red)" = "9c3030", "M1 Class (Purple)" = "ee82ee", "G Class (Yellow)" = "fbdf56", "O Class (Blue)" = "3399ff", "A Class (Cyan)" = "00ffff")) GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 44741758cf2..3400079d3d9 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -38,6 +38,7 @@ GLOBAL_LIST_EMPTY(latejoin_ai_cores) GLOBAL_LIST_EMPTY(mob_config_movespeed_type_lookup) + /proc/update_config_movespeed_type_lookup(update_mobs = TRUE) var/list/mob_types = list() var/list/entry_value = CONFIG_GET(keyed_list/multiplicative_movespeed) diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 862f0f12c3c..64d1fe4f27a 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -588,7 +588,8 @@ to_chat(M, "[IP] cannot hold [I] as it's a storage item of the same size!") return FALSE //To prevent the stacking of same sized storage items. if(I.item_flags & NODROP) //SHOULD be handled in unEquip, but better safe than sorry. - to_chat(M, "\the [I] is stuck to your hand, you can't put it in \the [host]!") + if(!stop_messages) + to_chat(M, "\the [I] is stuck to your hand, you can't put it in \the [host]!") return FALSE var/datum/component/storage/concrete/master = master() if(!istype(master)) @@ -599,7 +600,7 @@ return FALSE //This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() -//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, +//The prevent_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, //such as when picking up all the items on a tile with one click. /datum/component/storage/proc/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) var/atom/parent = src.parent diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm index 1f5c28d3c2a..68165af956b 100755 --- a/code/datums/outfit.dm +++ b/code/datums/outfit.dm @@ -21,6 +21,7 @@ var/l_hand = null var/internals_slot = null //ID of slot containing a gas tank var/list/backpack_contents = null // In the list(path=count,otherpath=count) format + var/box // Internals box. Will be inserted at the start of backpack_contents var/list/implants = null var/accessory = null @@ -83,6 +84,13 @@ H.equip_to_slot_or_del(new l_pocket(H),SLOT_L_STORE) if(r_pocket) H.equip_to_slot_or_del(new r_pocket(H),SLOT_R_STORE) + + if(box) + if(!backpack_contents) + backpack_contents = list() + backpack_contents.Insert(1, box) + backpack_contents[box] = 1 + if(backpack_contents) for(var/path in backpack_contents) var/number = backpack_contents[path] diff --git a/code/game/objects/items/gift.dm b/code/game/objects/items/gift.dm index f97b3f99d6f..ab728949abb 100644 --- a/code/game/objects/items/gift.dm +++ b/code/game/objects/items/gift.dm @@ -18,25 +18,35 @@ GLOBAL_LIST_EMPTY(possible_gifts) item_state = "gift" resistance_flags = FLAMMABLE -/obj/item/a_gift/New() - ..() + var/obj/item/contains_type + +/obj/item/a_gift/Initialize() + . = ..() pixel_x = rand(-10,10) pixel_y = rand(-10,10) icon_state = "giftdeliverypackage[rand(1,5)]" + contains_type = get_gift_type() + /obj/item/a_gift/suicide_act(mob/user) user.visible_message("[user] peeks inside [src] and cries [user.p_them()]self to death! It looks like [user.p_they()] [user.p_were()] on the naughty list...") return (BRUTELOSS) +/obj/item/a_gift/examine(mob/M) + . = ..() + if(M.has_trait(TRAIT_PRESENT_VISION) || isobserver(M)) + to_chat(M, "It contains \a [initial(contains_type.name)].") + /obj/item/a_gift/attack_self(mob/M) - if(M && M.mind && M.mind.special_role == "Santa") + if(M.has_trait(TRAIT_CANNOT_OPEN_PRESENTS)) to_chat(M, "You're supposed to be spreading gifts, not opening them yourself!") return - var/gift_type = get_gift_type() - qdel(src) - var/obj/item/I = new gift_type(M) + + var/obj/item/I = new contains_type(get_turf(M)) + M.visible_message("[M] unwraps \the [src], finding \a [I] inside!") + I.investigate_log("([I.type]) was found in a present by [key_name(M)].", INVESTIGATE_PRESENTS) M.put_in_hands(I) I.add_fingerprint(M) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 7905217af67..5db76fd2d89 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -65,20 +65,22 @@ sleep(20) playsound(src, "rustle", 50, 1, -5) qdel(user) - return /obj/item/storage/backpack/holding/singularity_act(current_size) var/dist = max((current_size - 2),1) explosion(src.loc,(dist),(dist*2),(dist*4)) - return /obj/item/storage/backpack/santabag name = "Santa's Gift Bag" - desc = "Space Santa uses this to deliver toys to all the nice children in space in Christmas! Wow, it's pretty big!" + desc = "Space Santa uses this to deliver presents to all the nice children in space in Christmas! Wow, it's pretty big!" icon_state = "giftbag0" item_state = "giftbag" w_class = WEIGHT_CLASS_BULKY +/obj/item/storage/backpack/santabag/Initialize() + . = ..() + regenerate_presents() + /obj/item/storage/backpack/santabag/ComponentInitialize() . = ..() GET_COMPONENT(STR, /datum/component/storage) @@ -89,6 +91,22 @@ user.visible_message("[user] places [src] over [user.p_their()] head and pulls it tight! It looks like [user.p_they()] [user.p_are()]n't in the Christmas spirit...") return (OXYLOSS) +/obj/item/storage/backpack/santabag/proc/regenerate_presents() + addtimer(CALLBACK(src, .proc/regenerate_presents), rand(30 SECONDS, 60 SECONDS)) + + var/mob/M = get(loc, /mob) + if(!istype(M)) + return + if(M.has_trait(TRAIT_CANNOT_OPEN_PRESENTS)) + GET_COMPONENT(STR, /datum/component/storage) + var/turf/floor = get_turf(src) + var/obj/item/I = new /obj/item/a_gift/anything(floor) + if(STR.can_be_inserted(I, stop_messages=TRUE)) + STR.handle_item_insertion(I, prevent_warning=TRUE) + else + qdel(I) + + /obj/item/storage/backpack/cultpack name = "trophy rack" desc = "It's useful for both carrying extra gear and proudly declaring your insanity." diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 7c73a1fd8cc..0b7d3e0bd49 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -63,7 +63,13 @@ icon_state = "pinepresents" desc = "A wondrous decorated Christmas tree. It has presents!" var/gift_type = /obj/item/a_gift/anything - var/list/ckeys_that_took = list() + var/unlimited = FALSE + var/static/list/took_presents //shared between all xmas trees + +/obj/structure/flora/tree/pine/xmas/presents/Initialize() + . = ..() + if(!took_presents) + took_presents = list() /obj/structure/flora/tree/pine/xmas/presents/attack_hand(mob/living/user) . = ..() @@ -72,14 +78,21 @@ if(!user.ckey) return - if(ckeys_that_took[user.ckey]) + if(took_presents[user.ckey] && !unlimited) to_chat(user, "There are no presents with your name on.") return to_chat(user, "After a bit of rummaging, you locate a gift with your name on it!") - ckeys_that_took[user.ckey] = TRUE + + if(!unlimited) + took_presents[user.ckey] = TRUE + var/obj/item/G = new gift_type(src) user.put_in_hands(G) +/obj/structure/flora/tree/pine/xmas/presents/unlimited + desc = "A wonderous decorated Christmas tree. It has a seemly endless supply of presents!" + unlimited = TRUE + /obj/structure/flora/tree/dead icon = 'icons/obj/flora/deadtrees.dmi' desc = "A dead tree. How it died, you know not." diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index ebbef58cbb5..6285b14c686 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -4,7 +4,7 @@ var/F = file("[GLOB.log_directory]/[subject].html") WRITE_FILE(F, "[time_stamp()] [REF(src)] ([x],[y],[z]) || [src] [message]
") -/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES) ) +/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES, INVESTIGATE_PRESENTS) ) set name = "Investigate" set category = "Admin" if(!holder) diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm index ea334ad6653..83dd08f2b1a 100644 --- a/code/modules/antagonists/santa/santa.dm +++ b/code/modules/antagonists/santa/santa.dm @@ -8,24 +8,24 @@ give_equipment() give_objective() + owner.add_trait(TRAIT_CANNOT_OPEN_PRESENTS, TRAIT_SANTA) + owner.add_trait(TRAIT_PRESENT_VISION, TRAIT_SANTA) + /datum/antagonist/santa/greet() . = ..() - to_chat(owner, "You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.") + to_chat(owner, "You are Santa! Your objective is to bring joy to the people on this station. You have a magical bag, which generates presents as long as you have it! You can examine the presents to take a peek inside, to make sure that you give the right gift to the right person.") /datum/antagonist/santa/proc/give_equipment() var/mob/living/carbon/human/H = owner.current if(istype(H)) H.equipOutfit(/datum/outfit/santa) + H.dna.update_dna_identity() - owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents) - var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new - telespell.clothes_req = 0 //santa robes aren't actually magical. - owner.AddSpell(telespell) //does the station have chimneys? WHO KNOWS! + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport/santa) /datum/antagonist/santa/proc/give_objective() var/datum/objective/santa_objective = new() santa_objective.explanation_text = "Bring joy and presents to the station!" - santa_objective.completed = 1 //lets cut our santas some slack. + santa_objective.completed = TRUE //lets cut our santas some slack. santa_objective.owner = owner objectives |= santa_objective - diff --git a/code/modules/clothing/outfits/event.dm b/code/modules/clothing/outfits/event.dm index 347fc5c2d72..70d16f3ae96 100644 --- a/code/modules/clothing/outfits/event.dm +++ b/code/modules/clothing/outfits/event.dm @@ -6,11 +6,11 @@ suit = /obj/item/clothing/suit/space/santa head = /obj/item/clothing/head/santa back = /obj/item/storage/backpack/santabag - mask = /obj/item/clothing/mask/breath r_pocket = /obj/item/flashlight gloves = /obj/item/clothing/gloves/color/red - belt = /obj/item/tank/internals/emergency_oxygen/double - id = /obj/item/card/id/gold + + box = /obj/item/storage/box/engineer + backpack_contents = list(/obj/item/a_gift/anything = 5) /datum/outfit/santa/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) if(visualsOnly) @@ -19,12 +19,8 @@ H.mind.assigned_role = "Santa" H.mind.special_role = "Santa" - H.hair_style = "Long Hair" - H.facial_hair_style = "Full Beard" + H.hair_style = "Long Hair 3" + H.facial_hair_style = "Beard (Full)" H.hair_color = "FFF" H.facial_hair_color = "FFF" - - var/obj/item/storage/backpack/bag = H.back - var/obj/item/a_gift/gift = new(H) - while(SEND_SIGNAL(bag, COMSIG_TRY_STORAGE_INSERT, gift, null, TRUE, FALSE)) - gift = new(H) + H.update_hair() diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index c0da7534c59..dc9a4824ac7 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -63,7 +63,7 @@ christmas_tree = null /datum/round_event_control/santa - name = "Santa is coming to town! (Christmas)" + name = "Vist by Santa" holidayID = CHRISTMAS typepath = /datum/round_event/santa weight = 20 diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm index 9242000636d..59ea5c00fc4 100644 --- a/code/modules/jobs/job_types/job.dm +++ b/code/modules/jobs/job_types/job.dm @@ -158,11 +158,11 @@ belt = /obj/item/pda back = /obj/item/storage/backpack shoes = /obj/item/clothing/shoes/sneakers/black + box = /obj/item/storage/box/survival var/backpack = /obj/item/storage/backpack var/satchel = /obj/item/storage/backpack/satchel var/duffelbag = /obj/item/storage/backpack/duffelbag - var/box = /obj/item/storage/box/survival var/pda_slot = SLOT_BELT @@ -183,12 +183,6 @@ else back = backpack //Department backpack - if(box) - if(!backpack_contents) - backpack_contents = list() - backpack_contents.Insert(1, box) // Box always takes a first slot in backpack - backpack_contents[box] = 1 - /datum/outfit/job/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) if(visualsOnly) return diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index f35177fe68b..8aab5376795 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1546,7 +1546,7 @@ if(M && ishuman(M)) var/mob/living/carbon/human/H = M H.hair_style = "Very Long Hair" - H.facial_hair_style = "Very Long Beard" + H.facial_hair_style = "Beard (Very Long)" H.update_hair() /datum/reagent/saltpetre diff --git a/code/modules/spells/spell_types/area_teleport.dm b/code/modules/spells/spell_types/area_teleport.dm index 83f17969735..84e1eec2eae 100644 --- a/code/modules/spells/spell_types/area_teleport.dm +++ b/code/modules/spells/spell_types/area_teleport.dm @@ -8,6 +8,8 @@ var/sound1 = 'sound/weapons/zapbang.ogg' var/sound2 = 'sound/weapons/zapbang.ogg' + var/say_destination = TRUE + /obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1,mob/living/user = usr) var/thearea = before_cast(targets) if(!thearea || !cast_check(1)) @@ -69,20 +71,22 @@ do_teleport(target, L, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC) playsound(get_turf(user), sound2, 50,1) - return - /obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null,mob/user = usr) if(!invocation_area || !chosenarea) ..() else + var/words + if(say_destination) + words = "[invocation] [uppertext(chosenarea.name)]" + else + words = "[invocation]" + switch(invocation_type) if("shout") - user.say("[invocation] [uppertext(chosenarea.name)]", forced = "spell") + user.say(words, forced = "spell") if(user.gender==MALE) playsound(user.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) else playsound(user.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) if("whisper") - user.whisper("[invocation] [uppertext(chosenarea.name)]", forced = "spell") - - return + user.whisper(words, forced = "spell") diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 563ae028c46..2a67febb739 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -151,6 +151,13 @@ sound1 = 'sound/magic/teleport_diss.ogg' sound2 = 'sound/magic/teleport_app.ogg' +/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/santa + name = "Santa Teleport" + + invocation = "HO HO HO" + clothes_req = FALSE + say_destination = FALSE // Santa moves in mysterious ways + /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop name = "Stop Time" desc = "This spell stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen."