diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
index 2b99823c49d..8a1d2bd8e7b 100644
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
@@ -45,6 +45,9 @@
var/obj/item/organ/internal/nano/refactory/refactory
var/datum/modifier/healing
+ var/obj/prev_left_hand
+ var/obj/prev_right_hand
+
player_msg = "In this form, you can move a little faster, your health will regenerate as long as you have metal in you, and you can ventcrawl!"
can_buckle = TRUE //Blobsurfing
@@ -152,8 +155,14 @@
var/obj/item/organ/internal/O = organ
O.removed()
O.forceMove(drop_location())
- QDEL_NULL(humanform) //Don't leave it just sitting in nullspace
- animate(src,alpha = 0,time = 2 SECONDS)
+ var/list/items = humanform.get_equipped_items()
+ if(prev_left_hand) items += prev_left_hand
+ if(prev_right_hand) items += prev_right_hand
+ for(var/obj/object in items)
+ object.forceMove(drop_location())
+ qdel_null(humanform) //Don't leave it just sitting in nullspace
+
+animate(src,alpha = 0,time = 2 SECONDS)
sleep(2 SECONDS)
qdel(src)
@@ -193,6 +202,13 @@
/mob/living/simple_animal/protean_blob/DoPunch(var/atom/A)
if(refactory && istype(A,/obj/item/stack/material))
var/obj/item/stack/material/S = A
+ var/substance = S.material.name
+ var/list/edible_materials = list("steel", "plasteel", "diamond", "mhydrogen") //Can't eat all materials, just useful ones.
+ var allowed = FALSE
+ for(var/material in edible_materials)
+ if(material == substance) allowed = TRUE
+ if(!allowed)
+ return
if(refactory.add_stored_material(S.material.name,1*S.perunit) && S.use(1))
visible_message("[name] gloms over some of \the [S], absorbing it.")
else
@@ -201,6 +217,13 @@
/mob/living/simple_animal/protean_blob/attackby(var/obj/item/O, var/mob/user)
if(refactory && istype(O,/obj/item/stack/material))
var/obj/item/stack/material/S = O
+ var/substance = S.material.name
+ var/list/edible_materials = list("steel", "plasteel", "diamond", "mhydrogen") //Can't eat all materials, just useful ones.
+ var allowed = FALSE
+ for(var/material in edible_materials)
+ if(material == substance) allowed = TRUE
+ if(!allowed)
+ return
if(refactory.add_stored_material(S.material.name,1*S.perunit) && S.use(1))
visible_message("[name] gloms over some of \the [S], absorbing it.")
else
@@ -213,11 +236,13 @@
// Helpers - Unsafe, WILL perform change.
/mob/living/carbon/human/proc/nano_intoblob()
+ handle_grasp() //It's possible to blob out before some key parts of the life loop. This results in things getting dropped at null. TODO: Fix the code so this can be done better.
+ remove_micros(src, src) //Living things don't fare well in roblobs.
if(buckled)
buckled.unbuckle_mob()
if(LAZYLEN(buckled_mobs))
for(var/buckledmob in buckled_mobs)
- unbuckle_mob(buckledmob, force = TRUE)
+ riding_datum.force_dismount(buckledmob)
if(pulledby)
pulledby.stop_pulling()
stop_pulling()
@@ -256,6 +281,9 @@
blob.transform = matrix()*size_multiplier
blob.size_multiplier = size_multiplier
+ if(l_hand) blob.prev_left_hand = l_hand //Won't save them if dropped above, but necessary if handdrop is disabled.
+ if(r_hand) blob.prev_right_hand = r_hand
+
//Put our owner in it (don't transfer var/mind)
blob.ckey = ckey
temporary_form = blob
@@ -265,7 +293,7 @@
//Message
blob.visible_message("[src.name] collapses into a gooey blob!")
-
+
//Duration of the to_puddle iconstate that the blob starts with
sleep(13)
blob.update_icon() //Will remove the collapse anim
@@ -281,6 +309,13 @@
//Return our blob in case someone wants it
return blob
+//For some reason, there's no way to force drop all the mobs grabbed. This ought to fix that. And be moved elsewhere. Call with caution, doesn't handle cycles.
+/proc/remove_micros(var/src, var/mob/root)
+ for(var/obj/item/I in src)
+ remove_micros(I, root) //Recursion. I'm honestly depending on there being no containment loop, but at the cost of performance that can be fixed too.
+ if(istype(I, /obj/item/weapon/holder))
+ root.remove_from_mob(I)
+
/mob/living/carbon/human/proc/nano_outofblob(var/mob/living/simple_animal/protean_blob/blob)
if(!istype(blob))
return
@@ -288,11 +323,11 @@
buckled.unbuckle_mob()
if(LAZYLEN(buckled_mobs))
for(var/buckledmob in buckled_mobs)
- unbuckle_mob(buckledmob, force = TRUE)
+ riding_datum.force_dismount(buckledmob)
if(pulledby)
pulledby.stop_pulling()
stop_pulling()
-
+
//Stop healing if we are
if(blob.healing)
blob.healing.expire()
@@ -302,7 +337,7 @@
//Message
blob.visible_message("[src.name] reshapes into a humanoid appearance!")
-
+
//Duration of above animation
sleep(8)
@@ -319,7 +354,6 @@
//Put our owner in it (don't transfer var/mind)
ckey = blob.ckey
temporary_form = null
- Life(1) //Fix my blindness right meow
//Transfer vore organs
vore_selected = blob.vore_selected
@@ -327,7 +361,12 @@
var/obj/belly/B = belly
B.forceMove(src)
B.owner = src
-
+
+ if(blob.prev_left_hand) put_in_l_hand(blob.prev_left_hand) //The restore for when reforming.
+ if(blob.prev_right_hand) put_in_r_hand(blob.prev_right_hand)
+
+ Life(1) //Fix my blindness right meow //Has to be moved up here, there exists a circumstance where blob could be deleted without vore organs moving right.
+
//Get rid of friend blob
qdel(blob)
diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm
index 4b3b6891add..d6f65e6f636 100644
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm
@@ -24,7 +24,7 @@
return
//Organ is missing, needs restoring
- if(!organs_by_name[choice])
+ if(!organs_by_name[choice] || istype(organs_by_name[choice], /obj/item/organ/external/stump)) //allows limb stumps to regenerate like removed limbs.
if(refactory.get_stored_material(DEFAULT_WALL_MATERIAL) < PER_LIMB_STEEL_COST)
to_chat(src,"You're missing that limb, and need to store at least [PER_LIMB_STEEL_COST] steel to regenerate it.")
return
@@ -33,6 +33,10 @@
return
if(!refactory.use_stored_material(DEFAULT_WALL_MATERIAL,PER_LIMB_STEEL_COST))
return
+ if(organs_by_name[choice])
+ var/obj/item/organ/external/oldlimb = organs_by_name[choice]
+ oldlimb.removed()
+ qdel(oldlimb)
var/mob/living/simple_animal/protean_blob/blob = nano_intoblob()
active_regen = TRUE
@@ -60,7 +64,7 @@
usable_manufacturers[company] = M
if(!usable_manufacturers.len)
return
- var/manu_choice = input(src, "Which manufacturer do you wish to mimmic for this limb?", "Manufacturer for [choice]") as null|anything in usable_manufacturers
+ var/manu_choice = input(src, "Which manufacturer do you wish to mimic for this limb?", "Manufacturer for [choice]") as null|anything in usable_manufacturers
if(!manu_choice)
return //Changed mind
@@ -70,13 +74,13 @@
return //Lost it meanwhile
eo.robotize(manu_choice)
- visible_message("[src]'s ")
+ visible_message("[src]'s [choice] loses its shape, then reforms.")
update_icons_body()
////
// Full Refactor
////
-/mob/living/carbon/human/proc/nano_regenerate()
+/mob/living/carbon/human/proc/nano_regenerate() //fixed the proc, it used to leave active_regen true.
set name = "Ref - Whole Body"
set desc = "Allows you to regrow limbs and replace organs, given you have enough materials."
set category = "Abilities"
@@ -97,7 +101,7 @@
to_chat(src, "You are already refactoring!")
return
- var/swap_not_rebuild = alert(src,"Do you want to rebuild, or reshape?","Rebuild or Reshape","Rebuild","Cancel","Reshape")
+ var/swap_not_rebuild = alert(src,"Do you want to rebuild, or reshape?","Rebuild or Reshape","Reshape","Cancel","Rebuild")
if(swap_not_rebuild == "Cancel")
return
if(swap_not_rebuild == "Reshape")
@@ -113,7 +117,7 @@
usable_manufacturers[company] = M
if(!usable_manufacturers.len)
return
- var/manu_choice = input(src, "Which manufacturer do you wish to mimmic?", "Manufacturer") as null|anything in usable_manufacturers
+ var/manu_choice = input(src, "Which manufacturer do you wish to mimic?", "Manufacturer") as null|anything in usable_manufacturers
if(!manu_choice)
return //Changed mind
@@ -123,7 +127,7 @@
var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
to_chat(src, "Remain still while the process takes place! It will take 5 seconds.")
visible_message("[src]'s form collapses into an amorphous blob of black ichor...")
-
+
var/mob/living/simple_animal/protean_blob/blob = nano_intoblob()
active_regen = TRUE
if(do_after(blob,5 SECONDS))
@@ -145,13 +149,13 @@
visible_message("[src]'s form begins to shift and ripple as if made of oil...")
active_regen = TRUE
- nano_intoblob()
- if(do_after(src,delay_length))
+ var/mob/living/simple_animal/protean_blob/blob = nano_intoblob()
+ if(do_after(blob, delay_length, null, 0))
if(stat != DEAD && refactory)
var/list/holder = refactory.materials
species.create_organs(src)
var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
- torso.robotize(synthetic.company)
+ torso.robotize() //synthetic wasn't defined here.
LAZYCLEARLIST(blood_DNA)
LAZYCLEARLIST(feet_blood_DNA)
blood_color = null
@@ -162,9 +166,15 @@
log_debug("[src] protean-regen'd but lacked a refactory when done.")
else
new_refactory.materials = holder
- to_chat(src, "Your refactoring is complete!")
+ to_chat(src, "Your refactoring is complete.") //Guarantees the message shows no matter how bad the timing.
+ to_chat(blob, "Your refactoring is complete!")
+ else
+ to_chat(src, "Your refactoring has failed.")
+ to_chat(blob, "Your refactoring has failed!")
else
- to_chat(src, "Your refactoring is interrupted!")
+ to_chat(src, "Your refactoring is interrupted.")
+ to_chat(blob, "Your refactoring is interrupted!")
+ active_regen = FALSE
nano_outofblob()
@@ -189,11 +199,19 @@
return
var/obj/item/stack/material/matstack = held
+ var/substance = matstack.material.name
+ var/list/edible_materials = list("steel", "plasteel", "diamond", "mhydrogen") //Can't eat all materials, just useful ones.
+ var allowed = FALSE
+ for(var/material in edible_materials)
+ if(material == substance) allowed = TRUE
+ if(!allowed)
+ to_chat(src,"You can't process [substance]!")
+ return //Only a few things matter, the rest are best not cluttering the lists.
+
var/howmuch = input(src,"How much do you want to store? (0-[matstack.amount])","Select amount") as null|num
if(!howmuch || matstack != get_active_hand() || howmuch > matstack.amount)
return //Quietly fail
- var/substance = matstack.material.name
var/actually_added = refactory.add_stored_material(substance,howmuch*matstack.perunit)
matstack.use(Ceiling(actually_added/matstack.perunit))
if(actually_added && actually_added < howmuch)
@@ -222,7 +240,7 @@
to_chat(temporary_form,"You can only do this while not stunned.")
else
nano_outofblob(temporary_form)
-
+
//Human form
else if(stat)
to_chat(src,"You can only do this while not stunned.")
@@ -241,7 +259,7 @@
if(stat)
to_chat(src,"You must be awake and standing to perform this action!")
return
-
+
var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in playable_species
if(new_species)
impersonate_bodytype = new_species
@@ -269,7 +287,7 @@
return
var/size_factor = new_size/100
-
+
//Will be: -1.75 for 200->25, and 1.75 for 25->200
var/sizediff = size_factor - user.size_multiplier
@@ -361,7 +379,7 @@
desc = "Rebuild or replace a single limb, assuming you have 2000 steel."
icon_state = "limb"
to_call = /mob/living/carbon/human/proc/nano_partswap
-
+
/obj/effect/protean_ability/reform_body
ability_name = "Ref - Whole Body"
desc = "Rebuild your entire body into whatever design you want, assuming you have 10,000 metal."
diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
index 05237f5742a..52aad66fccf 100644
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
@@ -21,6 +21,7 @@
health_hud_intensity = 2
num_alternate_languages = 3
species_language = LANGUAGE_SOL_COMMON
+ assisted_langs = list(LANGUAGE_EAL)
color_mult = TRUE
breath_type = null
@@ -115,7 +116,7 @@
/datum/species/protean/create_organs(var/mob/living/carbon/human/H)
var/obj/item/device/nif/saved_nif = H.nif
if(saved_nif)
- H.nif.unimplant()
+ H.nif.unimplant(H) //Needs reference to owner to unimplant right.
H.nif.forceMove(null)
..()
if(saved_nif)
@@ -162,13 +163,14 @@
/datum/species/protean/handle_death(var/mob/living/carbon/human/H)
to_chat(H,"You died as a Protean. Please sit out of the round for at least 30 minutes before respawning, to represent the time it would take to ship a new-you to the station.")
- spawn(1)
+ spawn(1) //This spawn is here so that if the protean_blob calls qdel, it doesn't try to gib the humanform.
if(H)
H.gib()
/datum/species/protean/handle_environment_special(var/mob/living/carbon/human/H)
if((H.getActualBruteLoss() + H.getActualFireLoss()) > H.maxHealth*0.5 && isturf(H.loc)) //So, only if we're not a blob (we're in nullspace) or in someone (or a locker, really, but whatever)
H.nano_intoblob()
+ return ..() //Any instakill shot runtimes since there are no organs after this. No point to not skip these checks, going to nullspace anyway.
var/obj/item/organ/internal/nano/refactory/refactory = locate() in H.internal_organs
if(refactory && !(refactory.status & ORGAN_DEAD))
diff --git a/code/modules/organs/subtypes/nano.dm b/code/modules/organs/subtypes/nano.dm
index 39398f5909a..fe23f37f851 100644
--- a/code/modules/organs/subtypes/nano.dm
+++ b/code/modules/organs/subtypes/nano.dm
@@ -109,9 +109,9 @@
/obj/item/organ/internal/nano/refactory/proc/use_stored_material(var/material,var/amt)
if(status & ORGAN_DEAD)
return 0
-
+
var/available = materials[material]
-
+
//Success
if(available >= amt)
var/new_amt = available-amt
@@ -141,12 +141,13 @@
. = ..()
icon_state = "posi1"
+
/obj/item/organ/internal/mmi_holder/posibrain/nano/update_from_mmi()
. = ..()
icon = initial(icon)
icon_state = "posi1"
stored_mmi.icon_state = "posi1"
-
+
stored_mmi.brainmob.languages = owner.languages
// The 'out on the ground' object, not the organ holder