From 598daee493cdb6c2aa89f53bb3b476f2b4e6fd14 Mon Sep 17 00:00:00 2001 From: coiax Date: Thu, 16 Jun 2016 22:36:47 +0100 Subject: [PATCH] Polymorph retains name and equipment (where possible) (#18587) Fixes bug where wabbajack statue's eyes didn't close Removes indentation and tidies the wabbajack() proc Corrected an inaccurate comment in mob.dm Mass Polymorph no longer uses a spawn() Adds syndicate medical borg, cak to possible forms Polymorphed drones now have random appearances GODMODE mobs are now immune to polymorph Wabbajack altars now ghost their sleepers after 10 seconds, because they tend to just be abandoned and left there. It's all a dream to them, if and when they get pulled from the altar. --- code/modules/admin/verbs/randomverbs.dm | 34 +-- code/modules/mob/living/living.dm | 5 +- .../friendly/drone/extra_drone_types.dm | 18 ++ .../mob/living/simple_animal/slime/slime.dm | 2 +- code/modules/mob/mob.dm | 2 +- code/modules/projectiles/projectile/magic.dm | 279 +++++++++--------- code/modules/shuttle/special.dm | 25 +- 7 files changed, 202 insertions(+), 163 deletions(-) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 6208b86e000..546dd4548d2 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1043,30 +1043,22 @@ var/list/datum/outfit/custom_outfits = list() //Admin created outfits if(confirm != "Yes") return - var/keep_name = alert(src, "Do you want mobs to retain their names?", "Keep The Names?", "Yes", "No") - var/list/mobs = shuffle(living_mob_list.Copy()) // might change while iterating var/who_did_it = key_name_admin(usr) - spawn(5) // let other things clear this tick - for(var/mob/living/M in mobs) - CHECK_TICK - - if(!M || !M.name || !M.real_name) - continue - - M.audible_message("...wabbajack...wabbajack...") - playsound(M.loc, 'sound/magic/Staff_Change.ogg', 50, 1, -1) - var/name = M.name - var/real_name = M.real_name - - var/mob/living/new_mob = wabbajack(M) - if(keep_name == "Yes" && new_mob) - new_mob.name = name - new_mob.real_name = real_name - - - message_admins("Mass polymorph started by [who_did_it] is complete.") message_admins("[key_name_admin(usr)] started polymorphed all living mobs.") log_admin("[key_name(usr)] polymorphed all living mobs.") feedback_add_details("admin_verb","MASSWABBAJACK") + + for(var/mob/living/M in mobs) + CHECK_TICK + + if(!M) + continue + + M.audible_message("...wabbajack...wabbajack...") + playsound(M.loc, 'sound/magic/Staff_Change.ogg', 50, 1, -1) + + wabbajack(M) + + message_admins("Mass polymorph started by [who_did_it] is complete.") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 50435deed93..fa493a7df28 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1029,6 +1029,9 @@ Sorry Giacom. Please don't be mad :( // Called when we are hit by a bolt of polymorph and changed // Generally the mob we are currently in, is about to be deleted /mob/living/proc/wabbajack_act(mob/living/new_mob) + new_mob.name = name + new_mob.real_name = real_name + if(mind) mind.transfer_to(new_mob) else @@ -1039,4 +1042,4 @@ Sorry Giacom. Please don't be mad :( G.summoner = new_mob G.Recall() G << "Your summoner has changed \ - form to [new_mob]!" + form!" diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index f37da30e127..e3a1f466c33 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -5,6 +5,7 @@ //Drones with custom shells //Drones with overriden procs //Drones with camogear for hat related memes +//Drone type for use with polymorph (no preloaded items, random appearance) //More types of drones @@ -69,3 +70,20 @@ desc = "A shell of a snowflake drone, a maintenance drone with a built in holographic projector to display hats and masks." drone_type = /mob/living/simple_animal/drone/snowflake +/mob/living/simple_animal/drone/polymorphed + default_storage = null + default_hatmask = null + picked = TRUE + +/mob/living/simple_animal/drone/polymorphed/New() + . = ..() + liberate() + visualAppearence = pick(MAINTDRONE, REPAIRDRONE, SCOUTDRONE) + if(visualAppearence == MAINTDRONE) + var/colour = pick("grey", "blue", "red", "green", "pink", "orange") + icon_state = "[visualAppearence]_[colour]" + else + icon_state = visualAppearence + + icon_living = icon_state + icon_dead = "[visualAppearence]_dead" diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 62e5bc05980..f2324e83116 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -419,4 +419,4 @@ var/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange", return 3 /mob/living/simple_animal/slime/random/New(loc, new_colour, new_is_adult) - . = ..(loc, pick(slime_colours), new_is_adult) + . = ..(loc, pick(slime_colours), prob(50)) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8d7f208a87c..49fdc9e6ed0 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -233,7 +233,7 @@ var/next_mob_id = 0 if(!istype(W)) return 0 for(var/slot in W.slot_equipment_priority) - if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //qdel_on_fail = 0; disable_warning = 0; redraw_mob = 1 + if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //qdel_on_fail = 0; disable_warning = 1; redraw_mob = 1 return 1 return 0 diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 464fe662962..c3c379534f0 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -134,153 +134,162 @@ wabbajack(change) /proc/wabbajack(mob/living/M) - if(istype(M)) - if(istype(M, /mob/living) && M.stat != DEAD) - if(M.notransform) - return - M.notransform = 1 - M.canmove = 0 - M.icon = null - M.overlays.Cut() - M.invisibility = INVISIBILITY_ABSTRACT + if(!istype(M) || M.stat == DEAD || M.notransform || (GODMODE & M.status_flags)) + return - if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/Robot = M - if(Robot.mmi) - qdel(Robot.mmi) - Robot.notify_ai(1) + M.notransform = 1 + M.canmove = 0 + M.icon = null + M.overlays.Cut() + M.invisibility = INVISIBILITY_ABSTRACT + + var/list/contents = M.contents.Copy() + + if(istype(M, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/Robot = M + if(Robot.mmi) + qdel(Robot.mmi) + Robot.notify_ai(1) + else + for(var/obj/item/W in contents) + if(!M.unEquip(W)) + qdel(W) + + var/mob/living/new_mob + + var/randomize = pick("monkey","robot","slime","xeno","humanoid","animal") + switch(randomize) + if("monkey") + new_mob = new /mob/living/carbon/monkey(M.loc) + if("robot") + var/robot = pick("cyborg","syndiborg","drone") + switch(robot) + if("cyborg") + new_mob = new /mob/living/silicon/robot(M.loc) + if("syndiborg") + var/path + if(prob(50)) + path = /mob/living/silicon/robot/syndicate + else + path = /mob/living/silicon/robot/syndicate/medical + new_mob = new path(M.loc) + if("drone") + new_mob = new /mob/living/simple_animal/drone/polymorphed(M.loc) + if(issilicon(new_mob)) + new_mob.gender = M.gender + new_mob.invisibility = 0 + new_mob.job = "Cyborg" + var/mob/living/silicon/robot/Robot = new_mob + Robot.mmi.transfer_identity(M) //Does not transfer key/client. + if("slime") + new_mob = new /mob/living/simple_animal/slime/random(M.loc) + if("xeno") + if(prob(50)) + new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) else - for(var/obj/item/W in M) - if(!M.unEquip(W)) - qdel(W) + new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - var/mob/living/new_mob + if("animal") + var/path + if(prob(50)) + var/beast = pick("carp","bear","mushroom","statue", "bat", "goat","killertomato", "spiderbase", "spiderhunter", "blobbernaut", "magicarp", "chaosmagicarp") + switch(beast) + if("carp") + path = /mob/living/simple_animal/hostile/carp + if("bear") + path = /mob/living/simple_animal/hostile/bear + if("mushroom") + path = /mob/living/simple_animal/hostile/mushroom + if("statue") + path = /mob/living/simple_animal/hostile/statue + if("bat") + path = /mob/living/simple_animal/hostile/retaliate/bat + if("goat") + path = /mob/living/simple_animal/hostile/retaliate/goat + if("killertomato") + path = /mob/living/simple_animal/hostile/killertomato + if("spiderbase") + path = /mob/living/simple_animal/hostile/poison/giant_spider + if("spiderhunter") + path = /mob/living/simple_animal/hostile/poison/giant_spider/hunter + if("blobbernaut") + path = /mob/living/simple_animal/hostile/blob/blobbernaut/independent + if("magicarp") + path = /mob/living/simple_animal/hostile/carp/ranged + if("chaosmagicarp") + path = /mob/living/simple_animal/hostile/carp/ranged/chaos + else + var/animal = pick("parrot","corgi","crab","pug","cat","mouse","chicken","cow","lizard","chick","fox","butterfly","cak") + switch(animal) + if("parrot") + path = /mob/living/simple_animal/parrot + if("corgi") + path = /mob/living/simple_animal/pet/dog/corgi + if("crab") + path = /mob/living/simple_animal/crab + if("pug") + path = /mob/living/simple_animal/pet/dog/pug + if("cat") + path = /mob/living/simple_animal/pet/cat + if("mouse") + path = /mob/living/simple_animal/mouse + if("chicken") + path = /mob/living/simple_animal/chicken + if("cow") + path = /mob/living/simple_animal/cow + if("lizard") + path = /mob/living/simple_animal/hostile/lizard + if("fox") + path = /mob/living/simple_animal/pet/fox + if("butterfly") + path = /mob/living/simple_animal/butterfly + if("cak") + path = /mob/living/simple_animal/pet/cat/cak + if("chick") + path = /mob/living/simple_animal/chick - var/randomize = pick("monkey","robot","slime","xeno","humanoid","animal") - switch(randomize) - if("monkey") - new_mob = new /mob/living/carbon/monkey(M.loc) - new_mob.languages |= HUMAN - if("robot") - var/robot = pick("cyborg","syndiborg","drone") - switch(robot) - if("cyborg") - new_mob = new /mob/living/silicon/robot(M.loc) - if("syndiborg") - new_mob = new /mob/living/silicon/robot/syndicate(M.loc) - if("drone") - new_mob = new /mob/living/simple_animal/drone(M.loc) - var/mob/living/simple_animal/drone/D = new_mob - D.liberate() // F R E E D R O N E - if(issilicon(new_mob)) - new_mob.gender = M.gender - new_mob.invisibility = 0 - new_mob.job = "Cyborg" - var/mob/living/silicon/robot/Robot = new_mob - Robot.mmi.transfer_identity(M) //Does not transfer key/client. - else - new_mob.languages |= HUMAN - if("slime") - var/mob/living/simple_animal/slime/random/slimey - slimey = new(get_turf(M), null, new_is_adult=prob(50)) - new_mob = slimey - new_mob.languages |= HUMAN - if("xeno") - if(prob(50)) - new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) - else - new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - new_mob.languages |= HUMAN + new_mob = new path(M.loc) - if("animal") - if(prob(50)) - var/beast = pick("carp","bear","mushroom","statue", "bat", "goat","killertomato", "spiderbase", "spiderhunter", "blobbernaut", "magicarp", "chaosmagicarp") - switch(beast) - if("carp") - new_mob = new /mob/living/simple_animal/hostile/carp(M.loc) - if("bear") - new_mob = new /mob/living/simple_animal/hostile/bear(M.loc) - if("mushroom") - new_mob = new /mob/living/simple_animal/hostile/mushroom(M.loc) - if("statue") - new_mob = new /mob/living/simple_animal/hostile/statue(M.loc) - if("bat") - new_mob = new /mob/living/simple_animal/hostile/retaliate/bat(M.loc) - if("goat") - new_mob = new /mob/living/simple_animal/hostile/retaliate/goat(M.loc) - if("killertomato") - new_mob = new /mob/living/simple_animal/hostile/killertomato(M.loc) - if("spiderbase") - new_mob = new /mob/living/simple_animal/hostile/poison/giant_spider(M.loc) - if("spiderhunter") - new_mob = new /mob/living/simple_animal/hostile/poison/giant_spider/hunter(M.loc) - if("blobbernaut") - new_mob = new /mob/living/simple_animal/hostile/blob/blobbernaut/independent(M.loc) - if("magicarp") - new_mob = new /mob/living/simple_animal/hostile/carp/ranged(M.loc) - if("chaosmagicarp") - new_mob = new /mob/living/simple_animal/hostile/carp/ranged/chaos(M.loc) - else - var/animal = pick("parrot","corgi","crab","pug","cat","mouse","chicken","cow","lizard","chick","fox","butterfly") - switch(animal) - if("parrot") - new_mob = new /mob/living/simple_animal/parrot(M.loc) - if("corgi") - new_mob = new /mob/living/simple_animal/pet/dog/corgi(M.loc) - if("crab") - new_mob = new /mob/living/simple_animal/crab(M.loc) - if("pug") - new_mob = new /mob/living/simple_animal/pet/dog/pug(M.loc) - if("cat") - new_mob = new /mob/living/simple_animal/pet/cat(M.loc) - if("mouse") - new_mob = new /mob/living/simple_animal/mouse(M.loc) - if("chicken") - new_mob = new /mob/living/simple_animal/chicken(M.loc) - if("cow") - new_mob = new /mob/living/simple_animal/cow(M.loc) - if("lizard") - new_mob = new /mob/living/simple_animal/hostile/lizard(M.loc) - if("fox") - new_mob = new /mob/living/simple_animal/pet/fox(M.loc) - if("butterfly") - new_mob = new /mob/living/simple_animal/butterfly(M.loc) - else - new_mob = new /mob/living/simple_animal/chick(M.loc) - new_mob.languages |= HUMAN - if("humanoid") - new_mob = new /mob/living/carbon/human(M.loc) + if("humanoid") + new_mob = new /mob/living/carbon/human(M.loc) - var/datum/preferences/A = new() //Randomize appearance for the human - A.copy_to(new_mob, icon_updates=0) + var/datum/preferences/A = new() //Randomize appearance for the human + A.copy_to(new_mob, icon_updates=0) - var/mob/living/carbon/human/H = new_mob - if(prob(50)) - var/list/all_species = list() - for(var/speciestype in subtypesof(/datum/species)) - var/datum/species/S = new speciestype() - if(!S.dangerous_existence) - all_species += speciestype - H.set_species(pick(all_species), icon_update=0) - H.real_name = H.dna.species.random_name(H.gender,1) - H.update_body() - H.update_hair() - H.update_body_parts() - H.dna.update_dna_identity() - else - return + var/mob/living/carbon/human/H = new_mob + if(prob(50)) + var/list/all_species = list() + for(var/speciestype in subtypesof(/datum/species)) + var/datum/species/S = new speciestype() + if(!S.dangerous_existence) + all_species += speciestype + H.set_species(pick(all_species), icon_update=0) + H.update_body() + H.update_hair() + H.update_body_parts() + H.dna.update_dna_identity() - new_mob.attack_log = M.attack_log - M.attack_log += text("\[[time_stamp()]\] [M.real_name] ([M.ckey]) became [new_mob.real_name].") + if(!new_mob) + return - new_mob.a_intent = "harm" + new_mob.languages |= HUMAN + new_mob.attack_log = M.attack_log - M.wabbajack_act(new_mob) + // Some forms can still wear some items + for(var/obj/item/W in contents) + new_mob.equip_to_appropriate_slot(W) - new_mob << "Your form morphs into that of a [randomize]." + M.attack_log += text("\[[time_stamp()]\] [M.real_name] ([M.ckey]) became [new_mob.real_name].") - qdel(M) - return new_mob + new_mob.a_intent = "harm" + + M.wabbajack_act(new_mob) + + new_mob << "Your form morphs into that of \ + a [randomize]." + + qdel(M) + return new_mob /obj/item/projectile/magic/animate name = "bolt of animation" diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 5f8d9cae8d2..6e2f38b3768 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -11,6 +11,7 @@ icon_state = "wabbajack_statue" icon_state_on = "wabbajack_statue_on" var/list/active_tables = list() + var/tables_required = 2 active = FALSE /obj/machinery/power/emitter/energycannon/magical/New() @@ -27,18 +28,17 @@ /obj/machinery/power/emitter/energycannon/magical/process() . = ..() - if(active_tables.len >= 2) + if(active_tables.len >= tables_required) if(!active) visible_message("\ [src] opens its eyes.") - update_icon() active = TRUE else if(active) visible_message("\ [src] closes its eyes.") - update_icon() active = FALSE + update_icon() /obj/machinery/power/emitter/energycannon/magical/attack_hand(mob/user) @@ -55,6 +55,8 @@ /obj/structure/table/abductor/wabbajack name = "wabbajack altar" + desc = "Whether you're sleeping or waking, it's going to be \ + quite chaotic." health = 1000 verb_say = "chants" var/obj/machinery/power/emitter/energycannon/magical/our_statue @@ -77,6 +79,12 @@ our_statue = M break + if(!our_statue) + name = "inert [name]" + return + else + name = initial(name) + var/turf/T = get_turf(src) var/list/found = list() for(var/mob/living/carbon/C in T) @@ -90,7 +98,8 @@ L.visible_message("A strange purple glow \ wraps itself around [L] as they suddenly fall unconcious.", "[desc]") - + // Don't let them sit suround unconscious forever + addtimer(src, "sleeper_dreams", 100, FALSE, L) // Existing sleepers for(var/i in found) @@ -103,6 +112,7 @@ L.color = initial(L.color) L.visible_message("The glow from [L] fades \ away.") + L.grab_ghost() sleepers = found @@ -114,6 +124,13 @@ else our_statue.active_tables -= src +/obj/structure/table/abductor/wabbajack/proc/sleeper_dreams(mob/living/sleeper) + if(sleeper in sleepers) + sleeper << "While you slumber, you have \ + the strangest dream, like you can see yourself from the outside.\ + " + sleeper.ghostize(TRUE) + /obj/structure/table/abductor/wabbajack/left desc = "You sleep so it may wake."