Merge pull request #627 from ArchieBeepBoop/spooky

The Spookening: Ports Jacqueline the Pumpqueen event + Dullahan and subsequent Fixes
This commit is contained in:
Dahlular
2020-10-29 22:51:07 -06:00
committed by GitHub
34 changed files with 857 additions and 116 deletions
+4
View File
@@ -99,3 +99,7 @@
*/
#define ELEMENT_BESPOKE (1 << 1)
#define COMSIG_MOVABLE_UPDATE_GLIDE_SIZE "movable_glide_size" //Called when the movable's glide size is updated: (new_glide_size)
#define COMSIG_LIVING_FULLY_HEAL "living_fully_healed" //from base of /mob/living/fully_heal(): (admin_revive)
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
+2
View File
@@ -76,6 +76,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ishumanbasic(A) (is_species(A, /datum/species/human))
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
#define isvampire(A) (is_species(A,/datum/species/vampire))
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
// Citadel specific species
#define isipcperson(A) (is_species(A, /datum/species/ipc))
+1
View File
@@ -263,6 +263,7 @@
var/atom/A = processing_list[1]
if(A.flags_1 & HEAR_1)
. += A
SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing_list, .)
processing_list.Cut(1, 2)
processing_list += A.contents
+4 -1
View File
@@ -127,6 +127,9 @@
screen_obj.icon_state = "mood[mood_level]"
/datum/component/mood/process() //Called on SSmood process
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
qdel(src)
return
var/mob/living/owner = parent
switch(mood_level)
@@ -284,7 +287,7 @@
RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click)
/datum/component/mood/proc/unmodify_hud(datum/source)
if(!screen_obj)
if(!screen_obj || !parent)
return
var/mob/living/owner = parent
var/datum/hud/hud = owner.hud_used
@@ -80,7 +80,7 @@
return TRUE
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
var/thermal_protection = H.get_thermal_protection()
var/thermal_protection = H.easy_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves
+1 -1
View File
@@ -107,7 +107,7 @@
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
var/obj/item/mmi/as_mmi = AM
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM)
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
if(brain_holder)
emergency_stop(AM)
else if(isliving(AM))
@@ -288,7 +288,7 @@
contained = "\[[contained]\]"
var/where = "[AREACOORD(location)]"
if(carry.my_atom.fingerprintslast)
if(carry.my_atom && carry.my_atom.fingerprintslast)
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
@@ -209,7 +209,7 @@
if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
cold_protection = H.get_cold_protection(air1.temperature)
cold_protection = H.get_thermal_protection(air1.temperature, TRUE)
if(abs(temperature_delta) > 1)
var/air_heat_capacity = air1.heat_capacity()
@@ -335,6 +335,23 @@
item_state = "officertanjacket"
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/ran
name = "Shikigami costume"
desc = "A costume that looks like a certain shikigami, is super fluffy."
icon_state = "ran_suit"
item_state = "ran_suit"
body_parts_covered = CHEST|GROIN|LEGS
flags_inv = HIDEJUMPSUIT|HIDETAUR
heat_protection = CHEST|GROIN|LEGS //fluffy tails!
//2061
/obj/item/clothing/head/ran
name = "Shikigami hat"
desc = "A hat that looks like it keeps any fluffy ears contained super warm, has little charms over it."
icon_state = "ran_hat"
item_state = "ran_hat"
flags_inv = HIDEEARS
/*
* Misc
*/
@@ -401,6 +401,7 @@ h1.alert, h2.alert {color: #000000;}
.redtext {color: #FF0000; font-size: 24px;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
.spooky {color: #FF6100;}
.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
@keyframes velvet {
0% { color: #400020; }
@@ -0,0 +1,158 @@
/obj/effect/landmark/barthpot
name = "barthpot"
/obj/item/barthpot
name = "Bartholomew"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "barthpot"
anchored = TRUE
var/items_list = list()
speech_span = "spooky"
var/active = TRUE
/obj/item/barthpot/Destroy()
var/obj/item/barthpot/n = new src(loc)
n.items_list = items_list
..()
/obj/item/barthpot/attackby(obj/item/I, mob/user, params)
if(!active)
say("Meow!")
return
for(var/I2 in items_list)
if(istype(I, I2))
qdel(I)
new /obj/item/reagent_containers/food/snacks/special_candy(loc)
to_chat(user, "<span class='notice'>You add the [I.name] to the pot and watch as it melts into the mixture, a candy crystalising in it's wake.</span>")
say("Hooray! Thank you!")
items_list -= I2
return
say("It doesn't seem like that's magical enough!")
/obj/item/barthpot/attack_hand(mob/user)
if(!active)
say("Meow!")
return
say("Hello there, I'm Bartholomew, Jacqueline's Familiar.")
sleep(20)
say("I'm currently seeking items to put into my pot, if we get the right items, it should crystalise into a magic candy!")
if(!iscarbon(user))
say("Though... I'm not sure you can help me.")
var/message = "From what I can tell, "
if(LAZYLEN(items_list) < 5)
generate_items()
for(var/I2 in items_list)
if(!I2)
items_list -= I2
continue
var/obj/item/I3 = new I2
message += "a [I3.name], "
message += "currently seem to have the most magic potential."
sleep(15)
say("[message]")
sleep(15)
//To help people find her
for(var/mob/living/simple_animal/jacq/J in GLOB.simple_animals[1])
var/turf/L1 = J.loc
if(!L1) //Incase someone uh.. puts her in a locker
return
var/area/L2 = L1.loc
if(L2)
say("Also, it seems that Jacqueline is currently at the [L2], if you're looking for her too.")
/obj/item/barthpot/proc/generate_items()
var/length = LAZYLEN(items_list)
var/rand_items = list(/obj/item/bodybag = 1,
/obj/item/clothing/glasses/meson = 2,
/obj/item/clothing/glasses/sunglasses = 1,
/obj/item/clothing/gloves/color/fyellow = 1,
/obj/item/clothing/head/hardhat = 1,
/obj/item/clothing/head/hardhat/red = 1,
/obj/item/clothing/head/that = 1,
/obj/item/clothing/head/ushanka = 1,
/obj/item/clothing/head/welding = 1,
/obj/item/clothing/mask/gas = 10,
/obj/item/clothing/suit/hazardvest = 1,
/obj/item/clothing/suit/hooded/flashsuit = 1,
/obj/item/assembly/prox_sensor = 4,
/obj/item/assembly/timer = 3,
/obj/item/flashlight = 6,
/obj/item/flashlight/pen = 1,
/obj/item/flashlight/glowstick = 4,
/obj/item/multitool = 2,
/obj/item/radio = 2,
/obj/item/t_scanner = 5,
/obj/item/airlock_painter = 1,
/obj/item/stack/cable_coil = 6,
/obj/item/stack/medical/bruise_pack = 1,
/obj/item/stack/rods = 3,
/obj/item/stack/sheet/cardboard = 2,
/obj/item/stack/sheet/metal = 1,
/obj/item/stack/sheet/mineral/plasma = 1,
/obj/item/stack/sheet/rglass = 1,
/obj/item/coin = 1,
/obj/item/crowbar = 4,
/obj/item/extinguisher = 3,
/obj/item/hand_labeler = 1,
/obj/item/paper = 6,
/obj/item/pen = 5,
/obj/item/reagent_containers/spray/pestspray = 1,
/obj/item/reagent_containers/rag = 3,
/obj/item/stock_parts/cell = 3,
/obj/item/storage/belt/utility = 2,
/obj/item/storage/box = 4,
/obj/item/reagent_containers/food/drinks/sillycup = 1,
/obj/item/storage/box/donkpockets = 1,
/obj/item/storage/box/lights/mixed = 1,
/obj/item/storage/box/hug/medical = 1,
/obj/item/storage/fancy/cigarettes = 1,
/obj/item/storage/toolbox = 1,
/obj/item/screwdriver = 3,
/obj/item/tank/internals/emergency_oxygen = 2,
/obj/item/vending_refill/cola = 1,
/obj/item/weldingtool = 3,
/obj/item/wirecutters = 2,
/obj/item/wrench = 4,
/obj/item/weaponcrafting/receiver = 1,
/obj/item/geiger_counter = 3,
/obj/item/reagent_containers/food/snacks/grown/citrus/orange = 5,
/obj/item/assembly/infra = 1,
/obj/item/assembly/igniter = 2,
/obj/item/assembly/signaler = 2,
/obj/item/assembly/mousetrap = 5,
/obj/item/reagent_containers/syringe = 5,
/obj/item/clothing/gloves = 8,
/obj/item/storage/toolbox = 2,
/obj/item/reagent_containers/pill = 2,
/obj/item/clothing/shoes = 8,
/obj/item/clothing/head = 3,
/obj/item/reagent_containers/food/snacks = 3,
/obj/item/reagent_containers/syringe/dart = 2,
/obj/item/reagent_containers/food/drinks/soda_cans = 5)
if(length >= 5)
return TRUE
//var/metalist = pickweight(GLOB.maintenance_loot)
for(var/i = length, i <= 5, i+=1)
var/obj/item = pickweight(rand_items)
if(!item)
i-=1
continue
for(var/obj/item_dupe in items_list) //No duplicates
if(item_dupe == item)
i-=1
continue
items_list += item
return TRUE
/obj/item/pinpointer/jacq
name = "The Jacq-Tracq"
desc = "A handheld tracking device that locks onto witchy signals."
/obj/item/pinpointer/jacq/attack_self(mob/living/user)
for(var/mob/living/simple_animal/jacq/J in GLOB.simple_animals[1])
target = J
..()
@@ -5,19 +5,27 @@
//spooky recipes
/datum/recipe/sugarcookie/spookyskull
reagents = list("flour" = 5, "sugar" = 5, "milk" = 5)
items = list(
/obj/item/reagent_containers/food/snacks/egg,
/datum/crafting_recipe/food/sugarcookie/spookyskull
time = 15
name = "Sugar cookie"
reqs = list(
/datum/reagent/consumable/sugar = 5,
/obj/item/reagent_containers/food/snacks/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/sugarcookie/spookyskull
subcategory = CAT_PASTRY
/datum/recipe/sugarcookie/spookycoffin
reagents = list("flour" = 5, "sugar" = 5, "coffee" = 5)
items = list(
/obj/item/reagent_containers/food/snacks/egg,
/datum/crafting_recipe/food/sugarcookie/spookycoffin
time = 15
name = "Sugar cookie"
reqs = list(
/datum/reagent/consumable/sugar = 5,
/datum/reagent/consumable/coffee = 5,
/obj/item/reagent_containers/food/snacks/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/sugarcookie/spookycoffin
subcategory = CAT_PASTRY
//////////////////////////////
//Spookoween trapped closets//
@@ -34,12 +42,12 @@
var/trapped = 0
var/mob/trapped_mob
/obj/structure/closet/initialize()
/obj/structure/closet/Initialize()
..()
if(prob(30))
set_spooky_trap()
/obj/structure/closet/dump_contents()
/obj/structure/closet/dump_contents(var/override = TRUE)
..()
trigger_spooky_trap()
+482
View File
@@ -0,0 +1,482 @@
//Conversation
#define JACQ_HELLO (1<<0)
#define JACQ_CANDIES (1<<1)
#define JACQ_HEAD (1<<2)
#define JACQ_FAR (1<<3)
#define JACQ_WITCH (1<<4)
#define JACQ_EXPELL (1<<5)
#define JACQ_DATE (1<<6)
/////// EVENT
/datum/round_event_control/jacqueen
name = "Jacqueline's visit"
holidayID = "jacqueen"
typepath = /datum/round_event/jacqueen
weight = -1 //forces it to be called, regardless of weight
max_occurrences = 1
earliest_start = 0 MINUTES
/datum/round_event/jacqueen/start()
..()
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
playsound(H, 'sound/spookoween/ahaha.ogg', 100, 0.25)
for(var/obj/effect/landmark/barthpot/bp in GLOB.landmarks_list)
new /obj/item/barthpot(bp.loc)
new /mob/living/simple_animal/jacq(bp.loc)
/////// MOBS
//Whacha doing in here like? Yae wan tae ruin ta magicks?
/mob/living/simple_animal/jacq
name = "Jacqueline the Pumpqueen"
real_name = "Jacqueline"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "jacqueline"
maxHealth = 25
health = 25
density = FALSE
speech_span = "spooky"
friendly = "pets"
response_help = "chats with"
light_range = 3
light_color = "#ff9842"
var/last_poof
var/progression = list() //Keep track of where people are in the story.
var/active = TRUE //Turn this to false to keep normal mob behavour
var/cached_z
/mob/living/simple_animal/jacq/Initialize()
..()
cached_z = z
poof()
/mob/living/simple_animal/jacq/Life()
..()
if(!ckey)
if((last_poof+3 MINUTES) < world.realtime)
poof()
/mob/living/simple_animal/jacq/Destroy() //I.e invincible
visible_message("<b>[src]</b> cackles, <span class='spooky'>\"You'll nae get rid a me that easily!\"</span>")
playsound(loc, 'sound/spookoween/ahaha.ogg', 100, 0.25)
var/mob/living/simple_animal/jacq/Jacq = new src.type(loc)
Jacq.progression = progression
..()
/mob/living/simple_animal/jacq/death() //What is alive may never die
visible_message("<b>[src]</b> cackles, <span class='spooky'>\"You'll nae get rid a me that easily!\"</span>")
playsound(loc, 'sound/spookoween/ahaha.ogg', 100, 0.25)
health = 25
poof()
/mob/living/simple_animal/jacq/attack_hand(mob/living/carbon/human/M)
if(!active)
say("Hello there [gender_check(M)]!")
return ..()
if(!ckey)
canmove = FALSE
chit_chat(M)
canmove = TRUE
..()
/mob/living/simple_animal/jacq/attack_paw(mob/living/carbon/monkey/M)
if(!active)
say("Hello there [gender_check(M)]!")
return ..()
if(!ckey)
canmove = FALSE
chit_chat(M)
canmove = TRUE
..()
/mob/living/simple_animal/jacq/proc/poof()
last_poof = world.realtime
var/datum/reagents/R = new/datum/reagents(100)//Hey, just in case.
var/datum/effect_system/smoke_spread/chem/s = new()
R.add_reagent("secretcatchem", (10))
s.set_up(R, 0, loc)
s.start()
visible_message("<b>[src]</b> disappears in a puff of smoke!")
canmove = TRUE
health = 25
var/hp_list = list()
for(var/obj/machinery/holopad/hp in world)
hp_list += hp
var/nono_areas = list("AI ")
for(var/i = 0, i <= 6, i+=1) //Attempts a jump 6 times.
var/obj/machinery/holopad/hp = pick(hp_list)
if(forceMove(pick(hp.loc)))
var/jacq_please_no = FALSE
for(var/no_area in nono_areas)
var/turf/L1 = hp.loc
if(!L1) //Incase the area isn't a turf (i.e. in a locker)
continue
var/area/L2 = L1.loc
if(L2)
if(findtext(L2.name, no_area))
jacq_please_no = TRUE
if(jacq_please_no)
i-=1
continue
//Try to go to populated areas
var/list/seen = viewers(8, get_turf(src))
for(var/victim in seen)
if(ishuman(victim))
if(z == cached_z)
return TRUE
return FALSE
/mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C)
var/gender = "lamb"
if(C)
if(C.gender == MALE)
gender = "laddie"
if(C.gender == FEMALE)
gender = "lassie"
return gender
//Ye wee bugger, gerrout of it. Ye've nae tae enjoy reading the code fer mae secrets like.
/mob/living/simple_animal/jacq/proc/chit_chat(mob/living/carbon/C)
//Very important
var/gender = gender_check(C)
if(C)
if(C.gender == MALE)
gender = "laddie"
if(C.gender == FEMALE)
gender = "lassie"
if(!progression["[C.real_name]"] || !(progression["[C.real_name]"] & JACQ_HELLO))
visible_message("<b>[src]</b> smiles ominously at [C], <span class='spooky'>\"Well halo there [gender]! Ah'm Jacqueline, tae great Pumpqueen, great tae meet ye.\"</span>")
sleep(20)
visible_message("<b>[src]</b> continues, <span class='spooky'>\"Ah'm sure yae well stunned, but ah've got nae taem fer that. Ah'm after the candies around this station. If yae get mae enoof o the wee buggers, Ah'll give ye a treat, or if yae feeling bold, Ah ken trick ye instead.</span>\" giving [C] a wide grin.")
if(!progression["[C.real_name]"])
progression["[C.real_name]"] = NONE //TO MAKE SURE THAT THE LIST ENTRY EXISTS.
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_HELLO
var/choices = list("Trick", "Treat", "How do I get candies?")
var/choice = input(C, "Trick or Treat?", "Trick or Treat?") in choices
switch(choice)
if("Trick")
trick(C)
return
if("Treat")
if(check_candies(C))
treat(C, gender)
else
visible_message("<b>[src]</b> raises an eyebrow, <span class='spooky'>\"You've nae got any candies Ah want! They're the orange round ones, now bugger off an go get em first.\"</span>")
return
if("How do I get candies?")
visible_message("<b>[src]</b> says, <span class='spooky'>\"Gae find my familiar; Bartholomew. Ee's tendin the cauldron which ken bring oot t' magic energy in items scattered aroond. Knowing him, ee's probably gone tae somewhere with books.\"</span>")
return
/mob/living/simple_animal/jacq/proc/treat(mob/living/carbon/C, gender)
visible_message("<b>[src]</b> gives off a glowing smile, <span class='spooky'>\"What ken Ah offer ye? I can magic up an object, a potion or a plushie fer ye.\"</span>")
var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Jacqueline Tracker - 2 candies", "Plushie - 1 candy", "Can I get to know you instead?", "Become a pumpkinhead dullahan (perma) - 4 candies")
var/choice_reward = input(usr, "Trick or Treat?", "Trick or Treat?") in choices_reward
//rewards
switch(choice_reward)
if("Become a pumpkinhead dullahan (perma) - 4 candies")
if(!take_candies(C, 4))
visible_message("<b>[src]</b> raises an eyebrown, <span class='spooky'>\"It's 4 candies for that [gender]! Thems the rules!\"</span>")
return
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"Off comes your head, a pumpkin taking it's stead!\"</span>")
C.reagents.add_reagent("pumpkinmutationtoxin", 5)
sleep(20)
poof()
return
if("Object - 3 candies")
if(!take_candies(C, 3))
visible_message("<b>[src]</b> raises an eyebrown, <span class='spooky'>\"It's 3 candies per trinket [gender]! Thems the rules!\"</span>")
return
var/new_obj = pick(subtypesof(/obj))
//for(var/item in blacklist)
// if(new_obj == item)
// panic()
var/reward = new new_obj(C.loc)
C.put_in_hands(reward)
visible_message("<b>[src]</b> waves her hands, magicking up a [reward] from thin air, <span class='spooky'>\"There ye are [gender], enjoy! \"</span>")
sleep(20)
poof()
return
if("Potion - 2 candies")
if(!take_candies(C, 2))
visible_message("<b>[src]</b> raises an eyebrow, <span class='spooky'>\"It's 2 candies per potion [gender]! Thems the rules!\"</span>")
return
var/reward = new /obj/item/reagent_containers/potion_container(C.loc)
C.put_in_hands(reward)
visible_message("<b>[src]</b> waves her hands, magicking up a [reward] from thin air, <span class='spooky'>\"There ye are [gender], enjoy! \"</span>")
sleep(20)
poof()
return
if("Plushie - 1 candy")
if(!take_candies(C, 1))
visible_message("<b>[src]</b> raises an eyebrow, <span class='spooky'>\"It's 1 candy per plushie [gender]! Thems the rules!\"</span>")
return
new /obj/item/toy/plush/random(C.loc)
visible_message("<b>[src]</b> waves her hands, magicking up a plushie from thin air, <span class='spooky'>\"There ye are [gender], enjoy! \"</span>")
sleep(20)
poof()
return
if("Jacqueline Tracker - 2 candies")
if(!take_candies(C, 2))
visible_message("<b>[src]</b> raises an eyebrow, <span class='spooky'>\"It's 1 candy per plushie [gender]! Thems the rules!\"</span>")
return
new /obj/item/pinpointer/jacq(C.loc)
visible_message("<b>[src]</b> waves her hands, magicking up a tracker from thin air, <span class='spooky'>\"Feels weird to magic up a tracker fer meself but, here ye are [gender], enjoy! \"</span>")
sleep(20)
poof()
return
//chitchats!
if("Can I get to know you instead?")
var/choices = list()
//Figure out where the C is in the story
if(!progression["[C.real_name]"]) //I really don't want to get here withoot a hello, but just to be safe
progression["[C.real_name]"] = NONE
if(!(progression["[C.real_name]"] & JACQ_FAR))
if(progression["[C.real_name]"] & JACQ_CANDIES)
choices += "You really came all this way for candy?"
else
choices += "Why do you want the candies?"
if(!(progression["[C.real_name]"] & JACQ_HEAD))
choices += "What is that on your head?"
if(!(progression["[C.real_name]"] & JACQ_EXPELL))
if(progression["[C.real_name]"] & JACQ_WITCH)
choices += "So you got ex-spell-ed?"
else
choices += "Are you a witch?"
//for Kepler, delete this, or just delete the whole story aspect if you want.
//If fully completed
/*
if(progression["[C.real_name]"] & JACQ_FAR)//Damnit this is a pain
if(progression["[C.real_name]"] & JACQ_EXPELL) //I give up
if(progression["[C.real_name]"] & JACQ_HEAD) //This is only an event thing
choices += "Can I take you out on a date?"
*/
if(progression["[C.real_name]"] == 63)//Damnit this is a pain
choices += "Can I take you out on a date?"
//If you've nothing to ask
if(!LAZYLEN(choices))
visible_message("<b>[src]</b> sighs, <span class='spooky'>\"Ah'm all questioned oot fer noo, [gender].\"</span>")
return
//Otherwise, lets go!
visible_message("<b>[src]</b> says, <span class='spooky'>\"A question? Sure, it'll cost you a candy though!\"</span>")
choices += "Nevermind"
//Candies for chitchats
var/choice = input(C, "What do you want to ask?", "What do you want to ask?") in choices
if(!take_candies(C, 1))
visible_message("<b>[src]</b> raises an eyebrow, <span class='spooky'>\"It's a candy per question [gender]! Thems the rules!\"</span>")
return
//Talking
switch(choice)
if("Why do you want the candies?")
visible_message("<b>[src]</b> says, <span class='spooky'>\"Ave ye tried them? They're full of all sorts of reagents. Ah'm after them so ah ken magic em up an hopefully find rare stuff fer me brews. Honestly it's a lot easier magicking up tatt fer ye lot than runnin aroond on me own like. I'd ask me familiars but most a my familiars are funny fellows 'n constantly bugger off on adventures when given simple objectives like; Go grab me a tea cake or watch over me cauldron. Ah mean, ye might run into Bartholomew my cat. Ee's supposed tae be tending my cauldron, but I've nae idea where ee's got tae.\"</span>")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_CANDIES
sleep(30)
if("You really came all this way for candy?")
visible_message("<b>[src]</b> l ooks tae the side sheepishly, <span class='spooky'>\"Aye, well, tae be honest, Ah'm here tae see me sis, but dunnae let her knew that. She's an alchemist too like, but she dunnae use a caldron like mae, she buggered off like tae her posh ivory tower tae learn bloody chemistry instead!\"</span> <b>[src]</b> scowls, <span class='spooky'>\"She's tae black sheep o' the family too, so we dunnae see eye tae eye sometimes on alchemy. Ah mean, she puts <i> moles </i> in her brews! Ye dunnae put moles in yer brews! Yae threw your brews at tae wee bastards an blew em up!\"</span> <b>[src]</b> sighs, <span class='spooky'>\"But she's a heart o gold so.. Ah wanted tae see her an check up oon her, make sure she's okay.\"</span>")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_FAR
sleep(30)
if("What is that on your head?")
visible_message("<b>[src]</b> pats the pumpkin atop her head, <span class='spooky'>\"This thing? This ain't nae ordinary pumpkin! Me Ma grew this monster ooer a year o love, dedication an hard work. Honestly it felt like she loved this thing more than any of us, which Ah knew ain't true an it's not like she was hartless or anything but.. well, we had a falling oot when Ah got back home with all me stuff in tow. An all she had done is sent me owl after owl over t' last year aboot this bloody pumpkin and ah had enough. So ah took it, an put it on me head. You know, as ye do. Ah am the great Pumpqueen after all, Ah deserve this.\"</span>")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_HEAD
sleep(30)
if("Are you a witch?")
visible_message("<b>[src]</b> grumbles, <span class='spooky'>\"If ye must know, Ah got kicked oot of the witch academy fer being too much of a \"loose cannon\". A bloody loose cannon? Nae they were just pissed off Ah had the brass tae proclaim myself as the Pumpqueen! And also maybe the time Ah went and blew up one of the towers by trying tae make a huge batch of astrogen might've had something tae do with it. Ah mean it would've worked fine if the cauldrons weren't so shite and were actually upgraded by the faculty. So technically no, I'm not a witch.\"</span>")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_WITCH
sleep(30)
if("So you got ex-spell-ed?")
visible_message("<b>[src]</b> Gives you a blank look at the pun, before continuing, <span class='spooky'>\"Not quite, Ah know Ah ken get back into the academy, it's only an explosion, they happen all the time, but, tae be fair it's my fault that things came tae their explosive climax. You don't know what it's like when you're after a witch doctorate, everyone else is doing well, everyone's making new spells and the like, and I'm just good at making explosions really, or fireworks. So, Ah did something Ah knew was dangerous, because Ah had tae do something tae stand oot, but Ah know this life ain't fer me, Ah don't want tae be locked up in dusty towers, grinding reagent after reagent together, trying tae find new reactions, some of the wizards in there haven't left fer years. Ah want tae live, Ah want tae fly around on a broom, turn people into cats fer a day and disappear cackling! That's what got me into witchcraft!\"</span> she throws her arms up in the arm, spinning the pumpkin upon her head slightly. She carefully spins it back to face you, giving oot a soft sigh, <span class='spooky'>\"Ah know my mother's obsession with this dumb thing on my head is just her trying tae fill the void of me and my sis moving oot, and it really shouldn't be on my head. And Ah know that I'm really here tae get help from my sis.. She's the sensible one, and she gives good hugs.\"</span>")
sleep(30)
visible_message("<b>[src]</b> says, <span class='spooky'>\"Thanks [C], Ah guess Ah didn't realise Ah needed someone tae talk tae but, I'm glad ye spent all your candies talking tae me. Funny how things seem much worse in yer head.\"</span>")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_EXPELL
sleep(30)
if("Can I take you out on a date?")
visible_message("<b>[src]</b> blushes, <span class='spooky'>\"...You want tae ask me oot on a date? Me? After all that nonsense Ah just said? It seems a waste of a candy honestly.\"</span>")
//progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_DATE
visible_message("<b>[src]</b> looks to the side, deep in thought.</span>")
dating_start(C, gender)
if("Nevermind")
visible_message("<b>[src]</b> shrugs, <span class='spooky'>\"Suit yerself then, here's your candy back.\"</span>")
new /obj/item/reagent_containers/food/snacks/special_candy(loc)
/mob/living/simple_animal/jacq/proc/trick(mob/living/carbon/C, gender)
var/option
if(ishuman(C))
option = rand(1,6)
else
option = rand(1,5)
switch(option)
if(1)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"Hocus pocus, making friends is now your focus!\"</span>")
var/message = pick("make a tasty sandwich for", "compose a poem for", "aquire a nice outfit to give to", "strike up a conversation about pumpkins with", "write a letter and deliver it to", "give a nice hat to")
var/mob/living/L2 = pick(GLOB.player_list)
message += " [L2.name]."
to_chat(C, "<span class='big warning'> You feel an overwhelming desire to [message]")
if(2)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"If only you had a better upbringing, your ears are now full of my singing!\"</span>")
var/client/C2 = C.client
C2.chatOutput.sendMusic("https://puu.sh/ExBbv.mp4", 1)//I hope this works!
if(3)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"You're cute little bumpkin, On your head is a pumpkin!\"</span>")
if(C.head)
var/obj/item/W = C.head
C.dropItemToGround(W, TRUE)
var/jaqc_latern = new /obj/item/clothing/head/hardhat/pumpkinhead/jaqc
C.equip_to_slot(jaqc_latern, SLOT_HEAD, 1, 1)
if(4)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"In your body there's something amiss, you'll find it's a chem made by my sis!\"</span>")
C.reagents.add_reagent("eigenstate", 30)
if(5)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"A new familiar for me, and you'll see it's thee!\"</span>")
C.reagents.add_reagent("secretcatchem", 30)
if(6)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"While you may not be a ghost, for this sheet you'll always be it's host.\"</span>")
var/mob/living/carbon/human/H = C
if(H.wear_suit)
var/obj/item/W = H.wear_suit
H.dropItemToGround(W, TRUE)
var/ghost = new /obj/item/clothing/suit/ghost_sheet/sticky
H.equip_to_slot(ghost, SLOT_WEAR_SUIT, 1, 1)
poof()
//Blame Fel
/mob/living/simple_animal/jacq/proc/dating_start(mob/living/carbon/C, gender)
var/candies = pollGhostCandidates("Do you want to go on a date with [C] as Jacqueline the great pumpqueen?")
//sleep(30) //If the poll doesn't autopause.
if(candies)
candies = shuffle(candies)//Shake those ghosts up!
for(var/mob/dead/observer/C2 in candies)
if(C2.key && C2)
key = C2.key
message_admins("[C2]/[C2.key] has agreed to go on a date with [C] as Jacqueline.")
log_game("HALLOWEEN: [C2]/[C2.key] has agreed to go on a date with [C] as Jacqueline")
to_chat(src, "<span class='big spooky'>You are Jacqueline the great pumpqueen, witch Extraordinaire! You're a very Scottish lass with a kind heart, but also a little crazy. You also blew up the wizarding school and you're suspended for a while, so you visited the station before heading home. On your head lies the prize pumpkin of your Mother's pumpkin patch. You're currently on a date with [C] and well, I didn't think anyone would get this far. <i> Please be good so I can do events like this in the future. </i> </span>")
return
else
candies =- C2
visible_message("<b>[src]</b> looks to the side, <span class='spooky'>\"Look, Ah like ye but, Ah don't think Ah can right now. If ye can't tell, the stations covered in volatile candies, I've a few other laddies and lassies running after me treats, and tae top it all off, I've the gods breathing down me neck, watching every treat Ah make fer the lot of yous.\" she sighs, \"But that's not a no, right? That's.. just a nae right noo.\"</span>")
sleep(20)
visible_message("<b>[src]</b> takes off the pumpkin on her head, a rich blush on her cheeks. She leans over planting a kiss upon your forehead quickly befere popping the pumpkin back on her head.")
sleep(10)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"There, that aught tae be worth a candy.\"</span>")
sleep(20)
poof()
/obj/item/clothing/head/hardhat/pumpkinhead/jaqc
name = "Jacq o' latern"
desc = "A jacqueline o' lantern! You can't seem to get rid of it."
icon_state = "hardhat0_pumpkin_j"
item_state = "hardhat0_pumpkin_j"
item_color = "pumpkin_j"
brightness_on = 4
/obj/item/clothing/head/hardhat/pumpkinhead/jaqc/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT)
/obj/item/clothing/suit/ghost_sheet/sticky
/obj/item/clothing/suit/ghost_sheet/sticky/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT)
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user)
if(iscarbon(user))
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
return
else
..()
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user)
if(iscarbon(user))
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
return
else
..()
/datum/reagent/mutationtoxin/pumpkinhead
name = "Pumpkin head mutation toxin"
id = "pumpkinmutationtoxin"
race = /datum/species/dullahan/pumpkin
mutationtext = "<span class='spooky'>The pain subsides. You feel your head roll off your shoulders... and you smell pumpkin."
//I couldn't get the replace head sprite with a pumpkin to work so, it is what it is.
/mob/living/simple_animal/jacq/proc/check_candies(mob/living/carbon/C)
var/invs = C.get_contents()
var/candy_count = 0
for(var/item in invs)
if(istype(item, /obj/item/reagent_containers/food/snacks/special_candy))
candy_count++
return candy_count
/mob/living/simple_animal/jacq/proc/take_candies(mob/living/carbon/C, candy_amount = 1)
var/inv = C.get_contents()
var/candies = list()
for(var/item in inv)
if(istype(item, /obj/item/reagent_containers/food/snacks/special_candy))
candies += item
if(LAZYLEN(candies) == candy_amount)
break
if(LAZYLEN(candies) == candy_amount) //I know it's a double check but eh, to be safe.
for(var/candy in candies)
qdel(candy)
return TRUE
return FALSE
//Potions
/obj/item/reagent_containers/potion_container
name = "potion"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "jacq_potion"
desc = "A potion with a strange concoction within. Be careful, as if it's thrown it explodes in a puff of smoke like Jacqueline."
/obj/item/reagent_containers/potion_container/Initialize()
.=..()
var/R = get_random_reagent_id()
reagents.add_reagent(R, 30)
name = "[R] Potion"
/obj/item/reagent_containers/potion_container/throw_impact(atom/target)
..()
sleep(20)
var/datum/effect_system/smoke_spread/chem/s = new()
s.set_up(src.reagents, 3, src.loc)
s.start()
qdel(src)
//Candies
/obj/item/reagent_containers/food/snacks/special_candy
name = "Magic candy"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "jacq_candy"
desc = "A candy with strange magic within. Be careful, as the magic isn't always helpful."
/obj/item/reagent_containers/food/snacks/special_candy/Initialize()
.=..()
reagents.add_reagent(get_random_reagent_id(), 5)
+10
View File
@@ -333,6 +333,16 @@
/datum/holiday/halloween/getStationPrefix()
return pick("Bone-Rattling","Mr. Bones' Own","2SPOOKY","Spooky","Scary","Skeletons")
/datum/holiday/jacqueen //Subset of halloween
name = "jacqueen"
begin_day = 27
begin_month = OCTOBER
end_day = 2
end_month = NOVEMBER
/datum/holiday/jacqueen/greet()
return "Jacqueline the great Pumpqueen has come to visit!"
/datum/holiday/vegan
name = "Vegan Day"
begin_day = 1
+43 -49
View File
@@ -3,7 +3,7 @@
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
// bitflags for the percentual amount of protection a piece of clothing which covers the body part offers.
// Used with human/proc/get_heat_protection() and human/proc/get_cold_protection()
// Used with human/proc/get_thermal_protection()
// The values here should add up to 1.
// Hands and feet have 2.5%, arms and legs 7.5%, each of the torso parts has 15% and the head has 30%
#define THERMAL_PROTECTION_HEAD 0.3
@@ -50,16 +50,17 @@
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if (wear_suit && head && istype(wear_suit, /obj/item/clothing) && istype(head, /obj/item/clothing))
var/headless = !get_bodypart(BODY_ZONE_HEAD) //should the mob be perennially headless (see dullahans), we only take the suit into account, so they can into space.
if (wear_suit && istype(wear_suit, /obj/item/clothing) && (headless || (head && istype(head, /obj/item/clothing))))
var/obj/item/clothing/CS = wear_suit
var/obj/item/clothing/CH = head
if (CS.clothing_flags & CH.clothing_flags & STOPSPRESSUREDAMAGE)
if (CS.clothing_flags & STOPSPRESSUREDAMAGE && (headless || (CH.clothing_flags & STOPSPRESSUREDAMAGE)))
return ONE_ATMOSPHERE
if(istype(loc, /obj/belly)) //START OF CIT CHANGES - Makes it so you don't suffocate while inside vore organs. Remind me to modularize this some time - Bhijn
return ONE_ATMOSPHERE
if(istype(loc, /obj/item/dogborg/sleeper))
return ONE_ATMOSPHERE //END OF CIT CHANGES
return pressure
return ..()
/mob/living/carbon/human/handle_traits()
@@ -133,7 +134,7 @@
if(dna)
dna.species.handle_fire(src)
/mob/living/carbon/human/proc/get_thermal_protection()
/mob/living/carbon/human/proc/easy_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
//CITADEL EDIT Vore code required overrides
if(istype(loc, /obj/item/dogborg/sleeper))
@@ -165,7 +166,6 @@
..()
//END FIRE CODE
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
@@ -191,37 +191,6 @@
return thermal_protection_flags
/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = get_heat_protection_flags(temperature)
var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
if(thermal_protection_flags & CHEST)
thermal_protection += THERMAL_PROTECTION_CHEST
if(thermal_protection_flags & GROIN)
thermal_protection += THERMAL_PROTECTION_GROIN
if(thermal_protection_flags & LEG_LEFT)
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
if(thermal_protection_flags & LEG_RIGHT)
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
if(thermal_protection_flags & FOOT_LEFT)
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
if(thermal_protection_flags & FOOT_RIGHT)
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
if(thermal_protection_flags & ARM_LEFT)
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
if(thermal_protection_flags & ARM_RIGHT)
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
if(thermal_protection_flags & HAND_LEFT)
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
//See proc/get_heat_protection_flags(temperature) for the description of this proc.
/mob/living/carbon/human/proc/get_cold_protection_flags(temperature)
var/thermal_protection_flags = 0
@@ -248,17 +217,42 @@
return thermal_protection_flags
/mob/living/carbon/human/proc/get_cold_protection(temperature)
//CITADEL EDIT Mandatory for vore code.
if(istype(loc, /obj/item/dogborg/sleeper))
return TRUE //freezing to death in sleepers ruins fun.
if(isbelly(loc))
return TRUE
if(ismob(loc))
return TRUE //because lazy and being inside somemone insulates you from space
//END EDIT
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
/mob/living/carbon/human/proc/get_thermal_protection(temperature, cold = FALSE)
if(cold)
//CITADEL EDIT Mandatory for vore code.
if(istype(loc, /obj/item/dogborg/sleeper) || isbelly(loc) || ismob(loc))
return 1 //freezing to death in sleepers ruins fun.
//END EDIT
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = cold ? get_cold_protection_flags(temperature) : get_heat_protection_flags(temperature)
var/missing_body_parts_flags = ~get_body_parts_flags()
var/max_protection = 1
if(missing_body_parts_flags) //I don't like copypasta as much as proc overhead. Do you want me to make these into a macro?
DISABLE_BITFIELD(thermal_protection_flags, missing_body_parts_flags)
if(missing_body_parts_flags & HEAD)
max_protection -= THERMAL_PROTECTION_HEAD
if(missing_body_parts_flags & CHEST)
max_protection -= THERMAL_PROTECTION_CHEST
if(missing_body_parts_flags & GROIN)
max_protection -= THERMAL_PROTECTION_GROIN
if(missing_body_parts_flags & LEG_LEFT)
max_protection -= THERMAL_PROTECTION_LEG_LEFT
if(missing_body_parts_flags & LEG_RIGHT)
max_protection -= THERMAL_PROTECTION_LEG_RIGHT
if(missing_body_parts_flags & FOOT_LEFT)
max_protection -= THERMAL_PROTECTION_FOOT_LEFT
if(missing_body_parts_flags & FOOT_RIGHT)
max_protection -= THERMAL_PROTECTION_FOOT_RIGHT
if(missing_body_parts_flags & ARM_LEFT)
max_protection -= THERMAL_PROTECTION_ARM_LEFT
if(missing_body_parts_flags & ARM_RIGHT)
max_protection -= THERMAL_PROTECTION_ARM_RIGHT
if(missing_body_parts_flags & HAND_LEFT)
max_protection -= THERMAL_PROTECTION_HAND_LEFT
if(missing_body_parts_flags & HAND_RIGHT)
max_protection -= THERMAL_PROTECTION_HAND_RIGHT
if(max_protection == 0) //Is it even a man if it doesn't have a body at all? Early return to avoid division by zero.
return 1
var/thermal_protection = 0
if(thermal_protection_flags)
@@ -285,7 +279,7 @@
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
return round(thermal_protection/max_protection, 0.001)
/mob/living/carbon/human/handle_random_events()
//Puke if toxloss is too high
@@ -1877,13 +1877,13 @@ GLOBAL_LIST_EMPTY(roundstart_races)
natural = H.natural_bodytemperature_stabilization()
var/thermal_protection = 1
if(loc_temp < H.bodytemperature) //Place is colder than we are
thermal_protection -= H.get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
thermal_protection -= H.get_thermal_protection(loc_temp, TRUE) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //we're cold, insulation helps us retain body heat and will reduce the heat we lose to the environment
H.adjust_bodytemperature((thermal_protection+1)*natural + max(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_COLD_DIVISOR, BODYTEMP_COOLING_MAX))
else //we're sweating, insulation hinders our ability to reduce heat - and it will reduce the amount of cooling you get from the environment
H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + max((thermal_protection * (loc_temp - H.bodytemperature) + BODYTEMP_NORMAL - H.bodytemperature) / BODYTEMP_COLD_DIVISOR , BODYTEMP_COOLING_MAX)) //Extra calculation for hardsuits to bleed off heat
else //Place is hotter than we are
thermal_protection -= H.get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
thermal_protection -= H.get_thermal_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //and we're cold, insulation enhances our ability to retain body heat but reduces the heat we get from the environment
H.adjust_bodytemperature((thermal_protection+1)*natural + min(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR, BODYTEMP_HEATING_MAX))
else //we're sweating, insulation hinders out ability to reduce heat - but will reduce the amount of heat we get from the environment
@@ -2022,7 +2022,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(!(I.resistance_flags & FIRE_PROOF))
I.take_damage(H.fire_stacks, BURN, "fire", 0)
var/thermal_protection = H.get_thermal_protection()
var/thermal_protection = H.easy_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
return
@@ -13,9 +13,14 @@
blacklisted = TRUE
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
var/pumpkin = FALSE
var/obj/item/dullahan_relay/myhead
/datum/species/dullahan/pumpkin
name = "Pumpkin Head Dullahan"
id = "pumpkindullahan"
pumpkin = TRUE
/datum/species/dullahan/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
@@ -24,17 +29,25 @@
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
H.flags_1 &= ~HEAR_1
DISABLE_BITFIELD(H.flags_1, HEAR_1)
var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD)
if(head)
if(pumpkin)//Pumpkinhead!
head.animal_origin = 100
head.icon = 'icons/obj/clothing/hats.dmi'
head.icon_state = "hardhat1_pumpkin_j"
head.custom_head = TRUE
head.drop_limb()
head.flags_1 = HEAR_1
head.throwforce = 25
myhead = new /obj/item/dullahan_relay (head, H)
H.put_in_hands(head)
if(!QDELETED(head)) //drop_limb() deletes the limb if it's no drop location and dummy humans used for rendering icons are located in nullspace. Do the math.
head.throwforce = 25
myhead = new /obj/item/dullahan_relay (head, H)
H.put_in_hands(head)
var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES)
for(var/datum/action/item_action/organ_action/OA in E.actions)
OA.Trigger()
/datum/species/dullahan/on_species_loss(mob/living/carbon/human/H)
H.flags_1 |= ~HEAR_1
ENABLE_BITFIELD(H.flags_1, HEAR_1)
H.reset_perspective(H)
if(myhead)
var/obj/item/dullahan_relay/DR = myhead
@@ -73,7 +86,7 @@
/obj/item/organ/tongue/dullahan/handle_speech(datum/source, list/speech_args)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
if(isobj(D.myhead.loc))
var/obj/O = D.myhead.loc
@@ -88,6 +101,7 @@
desc = "An abstraction."
actions_types = list(/datum/action/item_action/organ_action/dullahan)
zone = "abstract"
tint = INFINITY // used to switch the vision perspective to the head on species_gain().
/datum/action/item_action/organ_action/dullahan
name = "Toggle Perspective"
@@ -103,39 +117,55 @@
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
D.update_vision_perspective(H)
/obj/item/dullahan_relay
name = "dullahan relay"
var/mob/living/owner
flags_1 = HEAR_1
/obj/item/dullahan_relay/Initialize(mapload,new_owner)
/obj/item/dullahan_relay/Initialize(mapload, mob/living/carbon/human/new_owner)
. = ..()
if(!new_owner)
return INITIALIZE_HINT_QDEL
owner = new_owner
START_PROCESSING(SSobj, src)
RegisterSignal(owner, COMSIG_CLICK_SHIFT, .proc/examinate_check)
RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
RegisterSignal(owner, COMSIG_LIVING_FULLY_HEAL, .proc/retrieve_head)
/obj/item/dullahan_relay/proc/examinate_check(atom/source, mob/user)
if(user.client.eye == src)
return COMPONENT_ALLOW_EXAMINATE
/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers)
if(!QDELETED(owner))
hearers += owner
/obj/item/dullahan_relay/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
/obj/item/dullahan_relay/proc/retrieve_head(datum/source, admin_revive = FALSE)
if(admin_revive) //retrieving the owner's head for ahealing purposes.
var/obj/item/bodypart/head/H = loc
var/turf/T = get_turf(owner)
if(H && istype(H) && T && !(H in owner.GetAllContents()))
H.forceMove(T)
/obj/item/dullahan_relay/process()
if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner))
. = PROCESS_KILL
qdel(src)
/obj/item/dullahan_relay/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
. = ..()
if(!QDELETED(owner))
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
to_chat(owner,message)
else
qdel(src)
/obj/item/dullahan_relay/Destroy()
if(!QDELETED(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
D.myhead = null
owner.gib()
owner = null
..()
..()
+1
View File
@@ -536,6 +536,7 @@
for(var/organ in C.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
SEND_SIGNAL(src, COMSIG_LIVING_FULLY_HEAL, admin_revive)
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
@@ -334,12 +334,13 @@
//Regenerates all limbs. Returns amount of limbs regenerated
/mob/living/proc/regenerate_limbs(noheal, excluded_limbs)
return 0
/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_limbs)
/mob/living/carbon/regenerate_limbs(noheal, list/excluded_limbs)
/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
. = ..()
var/list/limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
if(excluded_limbs)
if(excluded_limbs.len)
limb_list -= excluded_limbs
for(var/Z in limb_list)
. += regenerate_limb(Z, noheal)
+6
View File
@@ -32,6 +32,8 @@
var/lip_style = null
var/lip_color = "white"
//If the head is a special sprite
var/custom_head
/obj/item/bodypart/head/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
@@ -118,6 +120,8 @@
..()
/obj/item/bodypart/head/update_icon_dropped()
if(custom_head)
return
var/list/standing = get_limb_icon(1)
if(!standing.len)
icon_state = initial(icon_state)//no overlays found, we default back to initial icon.
@@ -128,6 +132,8 @@
add_overlay(standing)
/obj/item/bodypart/head/get_limb_icon(dropped)
if(custom_head)
return
cut_overlays()
. = ..()
if(dropped) //certain overlays only appear when the limb is being detached from its owner.
+16 -2
View File
@@ -18,8 +18,6 @@
return FALSE
/mob/proc/has_left_hand(check_disabled = TRUE)
return TRUE
@@ -335,3 +333,19 @@
else
S.adjusted = ALT_STYLE
H.update_inv_wear_suit()
/mob/living/carbon/proc/get_body_parts_flags()
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
switch(L.body_part)
if(CHEST)
. |= GROIN
if(LEG_LEFT)
. |= FOOT_LEFT
if(LEG_RIGHT)
. |= FOOT_RIGHT
if(ARM_LEFT)
. |= HAND_LEFT
if(ARM_RIGHT)
. |= HAND_RIGHT
. |= L.body_part
+3 -1
View File
@@ -107,7 +107,9 @@
/obj/item/clothing/under/scratch = 1,
/obj/item/clothing/under/sailor = 1,
/obj/item/clothing/ears/headphones = 2,
/obj/item/clothing/head/wig/random = 3)
/obj/item/clothing/head/wig/random = 3,
/obj/item/clothing/suit/ran = 2,
/obj/item/clothing/head/ran = 2)
contraband = list(/obj/item/clothing/suit/judgerobe = 1,
/obj/item/clothing/head/powdered_wig = 1,
/obj/item/gun/magic/wand = 2,