diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm index f684a04a43..e1f8e977da 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm @@ -1,5 +1,5 @@ /mob/living/carbon/human/proc/begin_reconstitute_form() //Scree's race ability.in exchange for: No cloning. - set name = "Begin Reconstitute Form" + set name = "Reconstitute Form" set category = "Abilities" if(world.time < last_special) @@ -9,124 +9,69 @@ var/confirm = alert(usr, "Are you sure you want to completely reconstruct your form? This process can take up to twenty minutes, depending on how hungry you are, and you will be unable to move.", "Confirm Regeneration", "Yes", "No") if(confirm == "Yes") - var/mob/living/carbon/human/C = src - var/nutrition_used = C.nutrition/2 + chimera_regenerate() - if(C.reviving == 1) //If they're already unable to - C << "You are already reconstructing, or your body is currently recovering from the intense process of your previous reconstitution." - return +/mob/living/carbon/human/proc/chimera_regenerate() + var/nutrition_used = nutrition/2 - if(C.stat == DEAD) //Uh oh, you died! - if(C.hasnutriment()) //Let's hope you have nutriment in you.... If not - var/time = (240+960/(1 + nutrition_used/75)) - C.weakened = 10000 //Since it takes 1 tick to lose one weaken. Due to prior rounding errors, you'd sometimes unweaken before regenning. This fixes that. - C.reviving = 1 - C.canmove = 0 //Make them unable to move. In case they somehow get up before the delay. - C << "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds." - C.does_not_breathe = 1 //effectively makes them spaceworthy while regenning + if(reviving == TRUE) //If they're already unable to + to_chat(src, "You are already reconstructing, or your body is currently recovering from the intense process of your previous reconstitution.") + return - for(var/obj/item/organ/E in C.bad_external_organs) - var/obj/item/organ/external/affected = E - for(var/datum/wound/W in affected.wounds) // Fix internal bleeds at the start of the rejuv process. - if(istype(W, /datum/wound/internal_bleeding)) - affected.wounds -= W - affected.update_damages() - - spawn(time SECONDS) - if(C) //Runtime prevention. - C << "Consciousness begins to stir as your new body awakens, ready to hatch.." - C.verbs += /mob/living/carbon/human/proc/hatch - return - else - return //Something went wrong. - else //Dead until nutrition injected. - C << "Your body is too damaged to regenerate without additional nutrients to feed what few living cells remain." - return - - else if(C.stat != DEAD) //If they're alive at the time of reviving. + if(stat == DEAD) //Uh oh, you died! + if(hasnutriment()) //Let's hope you have nutriment in you.... If not var/time = (240+960/(1 + nutrition_used/75)) - C.weakened = 10000 //Since it takes 1 tick to lose one weaken. Due to prior rounding errors, you'd sometimes unweaken before regenning. This fixes that. - C.reviving = 1 - C.canmove = 0 //Make them unable to move. In case they somehow get up before the delay. - C << "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds." - C.does_not_breathe = 1 //effectively makes them spaceworthy while regenning + reviving = TRUE + to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.") + //don't need all the weakened, does_not_breathe, canmove, heal IB crap here like you do for live ones'cause they're DEAD. spawn(time SECONDS) - if(C.stat != DEAD) //If they're still alive after regenning. - C << "Consciousness begins to stir as your new body awakens, ready to hatch.." - C.verbs += /mob/living/carbon/human/proc/hatch - return - else if(C.stat == DEAD) - if(C.hasnutriment()) //Let's hope you have nutriment in you.... If not - C << "Consciousness begins to stir as your new body awakens, ready to hatch.." - C.verbs += /mob/living/carbon/human/proc/hatch - else //Dead until nutrition injected. - C << "Your body was unable to regenerate, what few living cells remain require additional nutrients to complete the process." - C.reviving = 0 // so they can try again when they're given a kickstart + if(src) //Runtime prevention. + if (stat == DEAD) // let's make sure they've not been defibbed or whatever + to_chat(src, "Consciousness begins to stir as your new body awakens, ready to hatch.") + verbs += /mob/living/carbon/human/proc/hatch + return + else // their revive got aborted by being made not-dead. Remove their cooldown. + to_chat(src, "Your body has recovered from its ordeal, ready to regenerate itself again.") + reviving = FALSE return else - return //Something went wrong - else - return //Something went wrong + return //Something went wrong. + else //Dead until nutrition injected. + to_chat(src, "Your body is too damaged to regenerate without additional nutrients to feed what few living cells remain.") + return -/mob/living/carbon/human/proc/purge_impurities() //a lesser regeneration that just purges toxin/infections without healing. Does NOT clear reagents. - set name = "Purge Impurities" - set category = "Abilities" - - if(world.time < last_special) - return - - last_special = world.time + 50 //To prevent button spam. - - var/mob/living/carbon/human/C = src - - if(C.reviving == 1) //If they're already unable to - C << "Your body is currently still recovering from the last time you healed." - return - - C.reviving = 1 // apply cooldown, this also locks out their main regen. - C << "You start to purge your body of poisons and intruders..." - - var/grossness = min(100, toxloss*5) - - for(var/i = 0, i<10,i++) // tick some tox down. This'll clear 20 toxloss in total. - if(C) - C.adjustToxLoss(-2) - sleep(10) - - for(var/obj/item/organ/external/E in C.organs) //half the germ_level of everything. If they're anything short of outright necrotic they'll be fine. - var/obj/item/organ/external/G = E - if(G.germ_level) - grossness += G.germ_level/10 - G.germ_level = min(0, (G.germ_level/2) - 100) - - for(var/obj/item/organ/internal/I in C.internal_organs) - var/obj/item/organ/internal/G = I - if(G.germ_level) - grossness += G.germ_level/5 - G.germ_level = min(0, (G.germ_level/2) - 100) - - //and now comes the fun part because they're gross - for (var/i = 0, i< grossness/10,i++) - if (prob(min(100, grossness))) - C << "You feel nauseous..." - sleep(30) - if(prob(min(100, grossness/2))) // relatively small chance unless they really let themselves go to shit - C << "You double over, gagging!" - C.Stun(3) - C.vomit() - sleep(50) - - C << "You have finished purging your body of impurities." - - spawn(300 SECONDS) //5 minute wait until you can purge or regenerate again. - C.reviving = 0 + else if(stat != DEAD) //If they're alive at the time of regenerating. + var/time = (240+960/(1 + nutrition_used/75)) + weakened = 10000 //Since it takes 1 tick to lose one weaken. Due to prior rounding errors, you'd sometimes unweaken before regenning. This fixes that. + reviving = TRUE + canmove = 0 //Make them unable to move. In case they somehow get up before the delay. + to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.") + does_not_breathe = 1 //effectively makes them spaceworthy while regenning + spawn(time SECONDS) + if(stat != DEAD) //If they're still alive after regenning. + to_chat(src, "Consciousness begins to stir as your new body awakens, ready to hatch..") + verbs += /mob/living/carbon/human/proc/hatch + return + else if(stat == DEAD) + if(hasnutriment()) //Let's hope you have nutriment in you.... If not + to_chat(src, "Consciousness begins to stir as your new body awakens, ready to hatch..") + verbs += /mob/living/carbon/human/proc/hatch + return + else //Dead until nutrition injected. + to_chat(src, "Your body was unable to regenerate, what few living cells remain require additional nutrients to complete the process.") + reviving = FALSE // so they can try again when they're given a kickstart + return + else + return //Something went wrong + else + return //Something went wrong /mob/living/carbon/human/proc/hasnutriment() - if (src.bloodstr.has_reagent("nutriment", 30) || src.bloodstr.has_reagent("protein", 15)) //protein needs half as much. For reference, a steak contains 9u protein. + if (bloodstr.has_reagent("nutriment", 30) || src.bloodstr.has_reagent("protein", 15)) //protein needs half as much. For reference, a steak contains 9u protein. return 1 - else if (src.ingested.has_reagent("nutriment", 60) || src.ingested.has_reagent("protein", 30)) //try forcefeeding them, why not. Less effective. + else if (ingested.has_reagent("nutriment", 60) || src.ingested.has_reagent("protein", 30)) //try forcefeeding them, why not. Less effective. return 1 else return 0 @@ -142,59 +87,49 @@ var/confirm = alert(usr, "Are you sure you want to hatch right now? This will be very obvious to anyone in view.", "Confirm Regeneration", "Yes", "No") if(confirm == "Yes") - var/mob/living/carbon/human/C = src - if(C.stat == DEAD) //Uh oh, you died! - if(C.hasnutriment()) //Let's hope you have nutriment in you.... If not - if(C) //Runtime prevention. - C.nutrition -= C.nutrition/2 //Cut their nutrition in half. - var/old_nutrition = C.nutrition //Since the game is being annoying. - C << "Your new body awakens, bursting free from your old skin." - viewers(C) << "

The lifeless husk of [C] bursts open, revealing a new, intact copy in the pool of viscera.

" //Bloody hell... - var/T = get_turf(src) - new /obj/effect/gibspawner/human/scree(T) - var/braindamage = C.brainloss/2 //If you have 100 brainloss, it gives you 50. - C.does_not_breathe = 0 //start breathing again - C.revive() // I did have special snowflake code, but this is easier. - C.weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. - C.mutations.Remove(HUSK) - C.nutrition = old_nutrition - C.brainloss = (braindamage+10) //Gives them half their prior brain damage plus ten more. - C.update_canmove() - for(var/obj/item/W in C) - C.drop_from_inventory(W) - spawn(3600 SECONDS) //1 hour wait until you can revive. - C.reviving = 0 - C.verbs -= /mob/living/carbon/human/proc/hatch + if(stat == DEAD) //Uh oh, you died! + if(hasnutriment()) //Let's hope you have nutriment in you.... If not + if(src) //Runtime prevention. + chimera_hatch() + visible_message("

The lifeless husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.

") //Bloody hell... + brainloss += 10 //Reviving from dead means you take a lil' brainloss on top of whatever was healed in the revive. return else - return //Ruuntime prevention - else - return //Something went wrong. + return //Runtime prevention + else //don't have nutriment to hatch! Or you somehow died in between completing your revive and hitting hatch. + to_chat(src, "Your body was unable to regenerate, what few living cells remain require additional nutrients to complete the process.") + reviving = FALSE // so they can try again when they're given a kickstart + return - else if(C.stat != DEAD) //If they're alive at the time of reviving. - C.nutrition -= C.nutrition/2 //Cut their nutrition in half. - var/old_nutrition = C.nutrition //Since the game is being annoying. - C << "Your new body awakens, bursting free from your old skin." - viewers(C) << "

The dormant husk of [C] bursts open, revealing a new, intact copy in the pool of viscera.

" //Bloody hell... - var/T = get_turf(src) - new /obj/effect/gibspawner/human/scree(T) - var/braindamage = C.brainloss/2 //If you have 100 brainloss, it gives you 50. - C.revive() // I did have special snowflake code, but this is easier. - C.weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. - C.mutations.Remove(HUSK) - C.nutrition = old_nutrition - C.brainloss = (braindamage) //Gives them half their prior brain damage plus ten more. - C.update_canmove() - for(var/obj/item/W in C) - C.drop_from_inventory(W) - spawn(3600 SECONDS) //1 hour wait until you can revive again. - C.reviving = 0 - C.does_not_breathe = 0 //start breathing again - C.verbs -= /mob/living/carbon/human/proc/hatch + else if(stat != DEAD) //If they're alive at the time of regenerating. + chimera_hatch() + visible_message("

The dormant husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.

") //Bloody hell... return else return //Runtime prevention. +/mob/living/carbon/human/proc/chimera_hatch() + nutrition -= nutrition/2 //Cut their nutrition in half. + var/old_nutrition = nutrition //Since the game is being annoying. + to_chat(src, "Your new body awakens, bursting free from your old skin.") + var/T = get_turf(src) + new /obj/effect/gibspawner/human/scree(T) + var/braindamage = brainloss/2 //If you have 100 brainloss, it gives you 50. + does_not_breathe = 0 //start breathing again + revive() // I did have special snowflake code, but this is easier. + weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. + mutations.Remove(HUSK) + nutrition = old_nutrition + brainloss = braindamage //Gives them half their prior brain damage. + update_canmove() + for(var/obj/item/W in src) + drop_from_inventory(W) + spawn(3600 SECONDS) //1 hour wait until you can revive. + reviving = FALSE + to_chat(src, "Your body has recovered from the strenuous effort of rebuilding itself.") + verbs -= /mob/living/carbon/human/proc/hatch + return + /obj/effect/gibspawner/human/scree fleshcolor = "#14AD8B" //Scree blood. bloodcolor = "#14AD8B" @@ -209,188 +144,190 @@ if(handling_hal) return //avoid conflict with actual hallucinations handling_hal = 1 - if(client && feral) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway. - sleep(rand(200,500)/(feral/10)) - var/halpick = rand(1,100) - switch(halpick) - if(0 to 15) //15% chance - //Screwy HUD - //src << "Screwy HUD" - hal_screwyhud = pick(1,2,3,3,4,4) - spawn(rand(100,250)) - hal_screwyhud = 0 - if(16 to 25) //10% chance - //Strange items - //src << "Traitor Items" - if(!halitem) - halitem = new - var/list/slots_free = list(ui_lhand,ui_rhand) - if(l_hand) slots_free -= ui_lhand - if(r_hand) slots_free -= ui_rhand - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(!H.belt) slots_free += ui_belt - if(!H.l_store) slots_free += ui_storage1 - if(!H.r_store) slots_free += ui_storage2 - if(slots_free.len) - halitem.screen_loc = pick(slots_free) - halitem.layer = 50 - switch(rand(1,6)) - if(1) //revolver - halitem.icon = 'icons/obj/gun.dmi' - halitem.icon_state = "revolver" - halitem.name = "Revolver" - if(2) //c4 - halitem.icon = 'icons/obj/assemblies.dmi' - halitem.icon_state = "plastic-explosive0" - halitem.name = "Mysterious Package" - if(prob(25)) - halitem.icon_state = "c4small_1" - if(3) //sword - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "sword1" - halitem.name = "Sword" - if(4) //stun baton - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "stunbaton" - halitem.name = "Stun Baton" - if(5) //emag - halitem.icon = 'icons/obj/card.dmi' - halitem.icon_state = "emag" - halitem.name = "Cryptographic Sequencer" - if(6) //flashbang - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "flashbang1" - halitem.name = "Flashbang" - if(client) client.screen += halitem - spawn(rand(100,250)) - if(client) - client.screen -= halitem - halitem = null - if(26 to 35) //10% chance - //Flashes of danger - //src << "Danger Flash" - if(!halimage) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) + if(client && feral >= 10) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway. + spawn(rand(200,500)/(feral/10)) + if(!feral) return //just to avoid fuckery in the event that they un-feral in the time it takes for the spawn to proc + var/halpick = rand(1,100) + switch(halpick) + if(0 to 15) //15% chance + //Screwy HUD + //src << "Screwy HUD" + hal_screwyhud = pick(1,2,3,3,4,4) + spawn(rand(100,250)) + hal_screwyhud = 0 + if(16 to 25) //10% chance + //Strange items + //src << "Traitor Items" + if(!halitem) + halitem = new + var/list/slots_free = list(ui_lhand,ui_rhand) + if(l_hand) slots_free -= ui_lhand + if(r_hand) slots_free -= ui_rhand + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + if(!H.belt) slots_free += ui_belt + if(!H.l_store) slots_free += ui_storage1 + if(!H.r_store) slots_free += ui_storage2 + if(slots_free.len) + halitem.screen_loc = pick(slots_free) + halitem.layer = 50 + switch(rand(1,6)) + if(1) //revolver + halitem.icon = 'icons/obj/gun.dmi' + halitem.icon_state = "revolver" + halitem.name = "Revolver" + if(2) //c4 + halitem.icon = 'icons/obj/assemblies.dmi' + halitem.icon_state = "plastic-explosive0" + halitem.name = "Mysterious Package" + if(prob(25)) + halitem.icon_state = "c4small_1" + if(3) //sword + halitem.icon = 'icons/obj/weapons.dmi' + halitem.icon_state = "sword1" + halitem.name = "Sword" + if(4) //stun baton + halitem.icon = 'icons/obj/weapons.dmi' + halitem.icon_state = "stunbaton" + halitem.name = "Stun Baton" + if(5) //emag + halitem.icon = 'icons/obj/card.dmi' + halitem.icon_state = "emag" + halitem.name = "Cryptographic Sequencer" + if(6) //flashbang + halitem.icon = 'icons/obj/grenade.dmi' + halitem.icon_state = "flashbang1" + halitem.name = "Flashbang" + if(client) client.screen += halitem + spawn(rand(100,250)) + if(client) + client.screen -= halitem + halitem = null + if(26 to 35) //10% chance + //Flashes of danger + //src << "Danger Flash" + if(!halimage) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,3)) - if(1) - //src << "Space" - halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER) - if(2) - //src << "Fire" - halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER) - if(3) - //src << "C4" - halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01) + switch(rand(1,3)) + if(1) + //src << "Space" + halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER) + if(2) + //src << "Fire" + halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER) + if(3) + //src << "C4" + halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01) - if(client) client.images += halimage - spawn(rand(10,50)) //Only seen for a brief moment. - if(client) client.images -= halimage - halimage = null + if(client) client.images += halimage + spawn(rand(10,50)) //Only seen for a brief moment. + if(client) client.images -= halimage + halimage = null - if(36 to 55) //20% chance - //Strange audio - //src << "Strange Audio" - switch(rand(1,12)) - if(1) src << 'sound/machines/airlock.ogg' - if(2) - if(prob(50))src << 'sound/effects/Explosion1.ogg' - else src << 'sound/effects/Explosion2.ogg' - if(3) src << 'sound/effects/explosionfar.ogg' - if(4) src << 'sound/effects/Glassbr1.ogg' - if(5) src << 'sound/effects/Glassbr2.ogg' - if(6) src << 'sound/effects/Glassbr3.ogg' - if(7) src << 'sound/machines/twobeep.ogg' - if(8) src << 'sound/machines/windowdoor.ogg' - if(9) - //To make it more realistic, I added two gunshots (enough to kill) - src << 'sound/weapons/Gunshot.ogg' - spawn(rand(10,30)) + if(36 to 55) //20% chance + //Strange audio + //src << "Strange Audio" + switch(rand(1,12)) + if(1) src << 'sound/machines/airlock.ogg' + if(2) + if(prob(50))src << 'sound/effects/Explosion1.ogg' + else src << 'sound/effects/Explosion2.ogg' + if(3) src << 'sound/effects/explosionfar.ogg' + if(4) src << 'sound/effects/Glassbr1.ogg' + if(5) src << 'sound/effects/Glassbr2.ogg' + if(6) src << 'sound/effects/Glassbr3.ogg' + if(7) src << 'sound/machines/twobeep.ogg' + if(8) src << 'sound/machines/windowdoor.ogg' + if(9) + //To make it more realistic, I added two gunshots (enough to kill) src << 'sound/weapons/Gunshot.ogg' - if(10) src << 'sound/weapons/smash.ogg' - if(11) - //Same as above, but with tasers. - src << 'sound/weapons/Taser.ogg' - spawn(rand(10,30)) + spawn(rand(10,30)) + src << 'sound/weapons/Gunshot.ogg' + if(10) src << 'sound/weapons/smash.ogg' + if(11) + //Same as above, but with tasers. src << 'sound/weapons/Taser.ogg' - //Rare audio - if(12) -//These sounds are (mostly) taken from Hidden: Source - var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\ - 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ - 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ - 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ - 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') - src << pick(creepyasssounds) - if(56 to 60) //5% chance - //Flashes of danger - //src << "Danger Flash" - if(!halbody) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,4)) - if(1) - halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER) - if(2,3) - halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER) - if(4) - halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER) - // if(5) - // halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER) + spawn(rand(10,30)) + src << 'sound/weapons/Taser.ogg' + //Rare audio + if(12) + //These sounds are (mostly) taken from Hidden: Source + var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\ + 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ + 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ + 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ + 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') + src << pick(creepyasssounds) + if(56 to 60) //5% chance + //Flashes of danger + //src << "Danger Flash" + if(!halbody) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) + switch(rand(1,4)) + if(1) + halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER) + if(2,3) + halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER) + if(4) + halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER) + // if(5) + // halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER) - if(client) client.images += halbody - spawn(rand(50,80)) //Only seen for a brief moment. - if(client) client.images -= halbody - halbody = null - if(61 to 85) //25% chance - //food - if(!halbody) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,10)) - if(1) - halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER) - if(2) - halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER) - if(3) - halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER) - if(4) - halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER) - if(5) - halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER) - if(6) - halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER) - if(7) - halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER) - if(8) - halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER) - if(9) - halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER) - if(10) - halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER) + if(client) client.images += halbody + spawn(rand(50,80)) //Only seen for a brief moment. + if(client) client.images -= halbody + halbody = null + if(61 to 85) //25% chance + //food + if(!halbody) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) + switch(rand(1,10)) + if(1) + halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER) + if(2) + halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER) + if(3) + halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER) + if(4) + halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER) + if(5) + halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER) + if(6) + halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER) + if(7) + halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER) + if(8) + halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER) + if(9) + halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER) + if(10) + halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER) + + if(client) client.images += halbody + spawn(rand(50,80)) //Only seen for a brief moment. + if(client) client.images -= halbody + halbody = null + if(86 to 100) //15% chance + //hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother. + var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice") + var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls") + var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!") + to_chat(src, "[pick(hiddenspeakers)] [pick(speakerverbs)], \"[pick(spookyphrases)]\"") - if(client) client.images += halbody - spawn(rand(50,80)) //Only seen for a brief moment. - if(client) client.images -= halbody - halbody = null - if(86 to 100) //15% chance - //disorientation - if(client) - client.dir = pick(2,4,8) - spawn(rand(20,50)) - client.dir = 1 handling_hal = 0 return diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm index f5cb361465..9f74592b8e 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm @@ -24,7 +24,6 @@ inherent_verbs = list( /mob/living/carbon/human/proc/begin_reconstitute_form, /mob/living/carbon/human/proc/sonar_ping, - /mob/living/carbon/human/proc/purge_impurities, /mob/living/carbon/human/proc/succubus_drain, /mob/living/carbon/human/proc/succubus_drain_finalize, /mob/living/carbon/human/proc/succubus_drain_lethal, @@ -48,7 +47,7 @@ //primitive_form = "Farwa" spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED //Whitelisted as restricted is broken. - flags = NO_SCAN //Dying as a chimera is, quite literally, a death sentence. Well, if it wasn't for their revive, that is. + flags = NO_SCAN | NO_INFECT //Dying as a chimera is, quite literally, a death sentence. Well, if it wasn't for their revive, that is. appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR flesh_color = "#AFA59E" @@ -145,11 +144,9 @@ H << " Every movement, every flick, every sight and sound has your full attention, your hunting instincts on high alert... In fact, [M] looks extremely appetizing..." if(H.stat == CONSCIOUS) H.emote("twitch") - if(!H.handling_hal) - H.handle_feral() - else // nobody around - if(!H.handling_hal) H.handle_feral() + else // nobody around + H.handle_feral() if(prob(2)) //periodic nagmessages if(H.nutrition <= 100) //If hungry, nag them to go and find someone or something to eat. H << " Confusing sights and sounds and smells surround you - scary and disorienting it may be, but the drive to hunt, to feed, to survive, compels you." diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks_vr.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks_vr.dm index b530b9834e..b904067813 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks_vr.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks_vr.dm @@ -28,3 +28,29 @@ M.make_dizzy(24) // Intentionally higher than normal to compensate for it's previous effects. if(dose * strength >= strength * 2.5) // Slurring takes longer. Again, intentional. M.slurring = max(M.slurring, 30) + +/datum/reagent/ethanol/monstertamer + name = "Monster Tamer" + id = "monstertamer" + description = "A questionably-delicious blend of a carnivore's favorite food and a potent neural depressant." + taste_description = "the gross yet satisfying combination of chewing on a raw steak while downing a shot of whiskey" + strength = 50 + color = "#d3785d" + metabolism = REM * 2.5 // about right for mixing nutriment and ethanol. + + glass_name = "Monster Tamer" + glass_desc = "This looks like a vaguely-alcoholic slurry of meat. Gross." + +/datum/reagent/ethanol/monstertamer/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) + ..() + + if(M.species.gets_food_nutrition) //it's still food! + M.nutrition += (nutriment_factor * removed)/2 // For hunger and fatness + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.feral > 0 && H.nutrition > 100 && H.traumatic_shock < min(60, H.nutrition/10) && H.jitteriness < 100) // same check as feral triggers to stop them immediately re-feralling + H.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm. + if (H.feral <=0) //check if they're unferalled + H.feral = 0 + H << "Your mind starts to clear, soothed into a state of clarity as your senses return." + log_and_message_admins("is no longer feral.", H) diff --git a/code/modules/reagents/Chemistry-Recipes_vr.dm b/code/modules/reagents/Chemistry-Recipes_vr.dm index 806d0e6cd0..ed94d5a05b 100644 --- a/code/modules/reagents/Chemistry-Recipes_vr.dm +++ b/code/modules/reagents/Chemistry-Recipes_vr.dm @@ -47,6 +47,22 @@ s.start() holder.clear_reagents() +/datum/chemical_reaction/xenolazarus + name = "Discount Lazarus" + id = "discountlazarus" + result = null + required_reagents = list("monstertamer" = 5, "clonexadone" = 5) + +/datum/chemical_reaction/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button + if(ishuman(holder.my_atom)) + var/mob/living/carbon/human/H = holder.my_atom + if(H.stat == DEAD && (/mob/living/carbon/human/proc/begin_reconstitute_form in H.verbs)) //no magical regen for non-regenners, and can't force the reaction on live ones + if(H.hasnutriment() && !H.reviving) // make sure it actually has the conditions to revive + H.visible_message("[H] shudders briefly, then relaxes, faint movements stirring within.") + H.chimera_regenerate() + else + H.visible_message("[H] twitches for a moment, but remains still.") + /////////////////////////////////////////////////////////////////////////////////// /// Vore Drugs @@ -89,7 +105,7 @@ result = "grubshake" required_reagents = list("shockchem" = 5, "water" = 25) result_amount = 30 - + /datum/chemical_reaction/drinks/deathbell name = "Deathbell" id = "deathbell" @@ -97,6 +113,13 @@ required_reagents = list("antifreeze" = 1, "gargleblaster" = 1, "syndicatebomb" =1) result_amount = 3 +/datum/chemical_reaction/drinks/monstertamer + name = "Monster Tamer" + id = "monstertamer" + result = "monstertamer" + required_reagents = list("whiskey" = 1, "protein" = 1) + result_amount = 2 + /////////////////////////////// //SLIME CORES BELOW HERE/////// ///////////////////////////////