mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-03 05:21:27 +00:00
* Initial work on tgui conversion for DNA Consoles * Some initial button logic complete TODO: Scanner Open button should disable while scanner is locked TODO: Scramble DNA should disable while on cooldown * Tabs for the tab God * Dropdown changes, genetic sequencer modifications * Mutation and genetic sequencer functionality Almost complete. Need to implement Advanced Injectors still. * Mostly done, converted most of genetic makeup code * Tactical pocket linting * More changes * Everything except advanced injectors complete * First complete alpha version * Fixed debug/testing change * Removal of more debugging code * Fix pulse bug * Bugbusters * Fix for accidental changes * Fix broken genetics disk changes, fix list of lists * Squash tgui tab-key bugs and clean up attackby * Code documenting, refactoring, bugfixing, spellcheck * Documentation and misc bug squashes and runtime error fixes * Fixes, features and tweaks * Special check for those who have shuffled off this mortal coil * New interface concept for console storage * Mini code refactor * Massive refactoring of DnaConsole interface (WIP) - De-spaghettifying of LawyerCode - Fixed the flex-basis bug, and removed ForcedBox since it's no longer needed. - Added a Divider component. * Implemented requested changes. Removed list() versions of strings. Removed used TGUI-exclusive constants from data object. Currently unused ones still remain, can be removed if they're no longer necessary. Fixed other DM data structures to serialise as JS Arrays instead of Objects. Minor TGUI logic fixes for various edge cases. Added some comments in DnaConsole.js outlining some minor notes and TODOs. * Fixes "Save to X" being disabled. * Included 2px outline CSS * Additional minor logic patches Don't want certain buttons active unless the mutation relation to them is also active * Makes these transforms use a timer * Fixed transformation race condition and stuff. * Mutation source defined in DM. Conditional formatting improvements. * Custom cache directory with BYOND_CACHE env var * Fix gene cycler on index of -1 * Framework and TODO for next interface element. Cleared TODO list a bit. * Fix 1px shift in gene cycle buttons * Pass raw event with GeneCycler * More robust combining logic * Fix some cycler bugs, start working on enzymes * Conditional highlighting for unsolved mutations and X'd genes. * Lint for the Lint God * Enzyme UI and more refactoring incoming * Finish tgui refactoring, enzymes injectors done * Whack-a-Bug * Unlinted. Advanced injectors moved and improved. Implemented disk genetic data readout. * Partial linting * Assorted bug fixes * Remove debugging code * DNA Consoles are now more conversational. Initial state set. * Final tweaks, implemented mutation combining, complete? * Fixes tooltop, re-enables delayed enzyme transfer, cleans up some data params * 10 Fix a bug, 20 make a bug, 30 goto 10 * The definition of irony * Don't drink and derive, kids || How I learned to stop coding while drunk and rely on stylemistake to Flex on my formatting. * uniqBy * Add support for dropdowns with disabilities. * Cleanup * Remove current mutation from combinations * Dividing * Document BYOND_CACHE env var * Outline cleanup * Declare radiation constants since they were removed in DM * Combine mutations only after checking for null * Advanced Injectors actually work now. * Comment cleanup, DMDOC, stard and end processing at appropriate times * Pressing Ctrl-S occasionally helps things * Fix enzyme mutator timeout bug, added injector timeout display. * Rebuild tgui * Rebuild tgui Co-authored-by: Aleksej Komarov <stylemistake@gmail.com> Co-authored-by: spookydonut <github@spooksoftware.com>
652 lines
19 KiB
Plaintext
652 lines
19 KiB
Plaintext
#define TRANSFORMATION_DURATION 22
|
|
|
|
/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG))
|
|
if (notransform || transformation_timer)
|
|
return
|
|
|
|
if(tr_flags & TR_KEEPITEMS)
|
|
var/Itemlist = get_equipped_items(TRUE)
|
|
Itemlist += held_items
|
|
for(var/obj/item/W in Itemlist)
|
|
dropItemToGround(W)
|
|
|
|
//Make mob invisible and spawn animation
|
|
notransform = TRUE
|
|
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
|
icon = null
|
|
cut_overlays()
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
|
|
new /obj/effect/temp_visual/monkeyify(loc)
|
|
|
|
transformation_timer = addtimer(CALLBACK(src, .proc/finish_monkeyize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
|
|
|
/mob/living/carbon/proc/finish_monkeyize(tr_flags)
|
|
transformation_timer = null
|
|
|
|
var/list/missing_bodyparts_zones = get_missing_limbs()
|
|
|
|
var/list/stored_implants = list()
|
|
|
|
if (tr_flags & TR_KEEPIMPLANTS)
|
|
for(var/X in implants)
|
|
var/obj/item/implant/IMP = X
|
|
stored_implants += IMP
|
|
IMP.removed(src, 1, 1)
|
|
|
|
var/list/int_organs = list()
|
|
var/obj/item/cavity_object
|
|
|
|
var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST)
|
|
if(CH.cavity_item)
|
|
cavity_object = CH.cavity_item
|
|
CH.cavity_item = null
|
|
|
|
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
|
|
|
|
// hash the original name?
|
|
if(tr_flags & TR_HASHNAME)
|
|
O.name = "monkey ([copytext_char(md5(real_name), 2, 6)])"
|
|
O.real_name = "monkey ([copytext_char(md5(real_name), 2, 6)])"
|
|
|
|
//handle DNA and other attributes
|
|
dna.transfer_identity(O)
|
|
O.updateappearance(icon_update=0)
|
|
|
|
if(tr_flags & TR_KEEPSE)
|
|
O.dna.mutation_index = dna.mutation_index
|
|
O.dna.default_mutation_genes = dna.default_mutation_genes
|
|
O.dna.set_se(1, GET_INITIALIZED_MUTATION(RACEMUT))
|
|
|
|
if(suiciding)
|
|
O.set_suicide(suiciding)
|
|
if(hellbound)
|
|
O.hellbound = hellbound
|
|
O.a_intent = INTENT_HARM
|
|
|
|
//keep viruses?
|
|
if (tr_flags & TR_KEEPVIRUS)
|
|
O.diseases = diseases
|
|
diseases = list()
|
|
for(var/thing in O.diseases)
|
|
var/datum/disease/D = thing
|
|
D.affected_mob = O
|
|
|
|
//keep damage?
|
|
if (tr_flags & TR_KEEPDAMAGE)
|
|
O.setToxLoss(getToxLoss(), 0)
|
|
O.adjustBruteLoss(getBruteLoss(), 0)
|
|
O.setOxyLoss(getOxyLoss(), 0)
|
|
O.setCloneLoss(getCloneLoss(), 0)
|
|
O.adjustFireLoss(getFireLoss(), 0)
|
|
O.setOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN))
|
|
O.updatehealth()
|
|
O.radiation = radiation
|
|
|
|
//re-add implants to new mob
|
|
if (tr_flags & TR_KEEPIMPLANTS)
|
|
for(var/Y in implants)
|
|
var/obj/item/implant/IMP = Y
|
|
IMP.implant(O, null, 1)
|
|
|
|
//re-add organs to new mob. this order prevents moving the mind to a brain at any point
|
|
if(tr_flags & TR_KEEPORGANS)
|
|
for(var/X in O.internal_organs)
|
|
var/obj/item/organ/I = X
|
|
I.Remove(O, 1)
|
|
|
|
if(mind)
|
|
mind.transfer_to(O)
|
|
var/datum/antagonist/changeling/changeling = O.mind.has_antag_datum(/datum/antagonist/changeling)
|
|
if(changeling)
|
|
var/datum/action/changeling/humanform/hf = new
|
|
changeling.purchasedpowers += hf
|
|
changeling.regain_powers()
|
|
|
|
for(var/X in internal_organs)
|
|
var/obj/item/organ/I = X
|
|
int_organs += I
|
|
I.Remove(src, 1)
|
|
|
|
for(var/X in int_organs)
|
|
var/obj/item/organ/I = X
|
|
I.Insert(O, 1)
|
|
|
|
var/obj/item/bodypart/chest/torso = O.get_bodypart(BODY_ZONE_CHEST)
|
|
if(cavity_object)
|
|
torso.cavity_item = cavity_object //cavity item is given to the new chest
|
|
cavity_object.forceMove(O)
|
|
|
|
for(var/missing_zone in missing_bodyparts_zones)
|
|
var/obj/item/bodypart/BP = O.get_bodypart(missing_zone)
|
|
BP.drop_limb(1)
|
|
if(!(tr_flags & TR_KEEPORGANS)) //we didn't already get rid of the organs of the newly spawned mob
|
|
for(var/X in O.internal_organs)
|
|
var/obj/item/organ/G = X
|
|
if(BP.body_zone == check_zone(G.zone))
|
|
if(mind && mind.has_antag_datum(/datum/antagonist/changeling) && istype(G, /obj/item/organ/brain))
|
|
continue //so headless changelings don't lose their brain when transforming
|
|
qdel(G) //we lose the organs in the missing limbs
|
|
qdel(BP)
|
|
|
|
//transfer stuns
|
|
if(tr_flags & TR_KEEPSTUNS)
|
|
O.Stun(AmountStun(), ignore_canstun = TRUE)
|
|
O.Knockdown(AmountKnockdown(), ignore_canstun = TRUE)
|
|
O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE)
|
|
O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE)
|
|
O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE)
|
|
O.Sleeping(AmountSleeping(), ignore_canstun = TRUE)
|
|
|
|
//transfer reagents
|
|
if(tr_flags & TR_KEEPREAGENTS)
|
|
reagents.trans_to(O, reagents.total_volume)
|
|
|
|
//transfer mind if we didn't yet
|
|
if(mind)
|
|
mind.transfer_to(O)
|
|
var/datum/antagonist/changeling/changeling = O.mind.has_antag_datum(/datum/antagonist/changeling)
|
|
if(changeling)
|
|
var/datum/action/changeling/humanform/hf = new
|
|
changeling.purchasedpowers += hf
|
|
changeling.regain_powers()
|
|
|
|
|
|
if (tr_flags & TR_DEFAULTMSG)
|
|
to_chat(O, "<B>You are now a monkey.</B>")
|
|
|
|
for(var/A in loc.vars)
|
|
if(loc.vars[A] == src)
|
|
loc.vars[A] = O
|
|
|
|
transfer_observers_to(O)
|
|
|
|
. = O
|
|
|
|
qdel(src)
|
|
|
|
////////////////////////// Humanize //////////////////////////////
|
|
//Could probably be merged with monkeyize but other transformations got their own procs, too
|
|
|
|
/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG))
|
|
if (notransform || transformation_timer)
|
|
return
|
|
|
|
//now the rest
|
|
if (tr_flags & TR_KEEPITEMS)
|
|
var/Itemlist = get_equipped_items(TRUE)
|
|
Itemlist += held_items
|
|
for(var/obj/item/W in Itemlist)
|
|
dropItemToGround(W, TRUE)
|
|
if (client)
|
|
client.screen -= W
|
|
|
|
//Make mob invisible and spawn animation
|
|
notransform = TRUE
|
|
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
|
|
|
icon = null
|
|
cut_overlays()
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
new /obj/effect/temp_visual/monkeyify/humanify(loc)
|
|
|
|
transformation_timer = addtimer(CALLBACK(src, .proc/finish_humanize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
|
|
|
/mob/living/carbon/proc/finish_humanize(tr_flags)
|
|
transformation_timer = null
|
|
|
|
var/list/stored_implants = list()
|
|
var/list/int_organs = list()
|
|
|
|
if (tr_flags & TR_KEEPIMPLANTS)
|
|
for(var/X in implants)
|
|
var/obj/item/implant/IMP = X
|
|
stored_implants += IMP
|
|
IMP.removed(src, 1, 1)
|
|
|
|
var/list/missing_bodyparts_zones = get_missing_limbs()
|
|
|
|
var/obj/item/cavity_object
|
|
|
|
var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST)
|
|
if(CH.cavity_item)
|
|
cavity_object = CH.cavity_item
|
|
CH.cavity_item = null
|
|
|
|
var/mob/living/carbon/human/O = new( loc )
|
|
for(var/obj/item/C in O.loc)
|
|
if(C.anchored)
|
|
continue
|
|
O.equip_to_appropriate_slot(C)
|
|
|
|
dna.transfer_identity(O)
|
|
O.updateappearance(mutcolor_update=1)
|
|
|
|
if(findtext(O.dna.real_name, "monkey", 1, 7)) //7 == length("monkey") + 1
|
|
O.real_name = random_unique_name(O.gender)
|
|
O.dna.generate_unique_enzymes(O)
|
|
else
|
|
O.real_name = O.dna.real_name
|
|
O.name = O.real_name
|
|
|
|
if(tr_flags & TR_KEEPSE)
|
|
O.dna.mutation_index = dna.mutation_index
|
|
O.dna.default_mutation_genes = dna.default_mutation_genes
|
|
O.dna.set_se(0, GET_INITIALIZED_MUTATION(RACEMUT))
|
|
O.domutcheck()
|
|
|
|
if(suiciding)
|
|
O.set_suicide(suiciding)
|
|
if(hellbound)
|
|
O.hellbound = hellbound
|
|
|
|
//keep viruses?
|
|
if (tr_flags & TR_KEEPVIRUS)
|
|
O.diseases = diseases
|
|
diseases = list()
|
|
for(var/thing in O.diseases)
|
|
var/datum/disease/D = thing
|
|
D.affected_mob = O
|
|
O.med_hud_set_status()
|
|
|
|
//keep damage?
|
|
if (tr_flags & TR_KEEPDAMAGE)
|
|
O.setToxLoss(getToxLoss(), 0)
|
|
O.adjustBruteLoss(getBruteLoss(), 0)
|
|
O.setOxyLoss(getOxyLoss(), 0)
|
|
O.setCloneLoss(getCloneLoss(), 0)
|
|
O.adjustFireLoss(getFireLoss(), 0)
|
|
O.adjustOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN))
|
|
O.updatehealth()
|
|
O.radiation = radiation
|
|
|
|
//re-add implants to new mob
|
|
if (tr_flags & TR_KEEPIMPLANTS)
|
|
for(var/Y in implants)
|
|
var/obj/item/implant/IMP = Y
|
|
IMP.implant(O, null, 1)
|
|
|
|
if(tr_flags & TR_KEEPORGANS)
|
|
for(var/X in O.internal_organs)
|
|
var/obj/item/organ/I = X
|
|
I.Remove(O, 1)
|
|
|
|
if(mind)
|
|
mind.transfer_to(O)
|
|
var/datum/antagonist/changeling/changeling = O.mind.has_antag_datum(/datum/antagonist/changeling)
|
|
if(changeling)
|
|
for(var/datum/action/changeling/humanform/HF in changeling.purchasedpowers)
|
|
changeling.purchasedpowers -= HF
|
|
changeling.regain_powers()
|
|
|
|
for(var/X in internal_organs)
|
|
var/obj/item/organ/I = X
|
|
int_organs += I
|
|
I.Remove(src, 1)
|
|
|
|
for(var/X in int_organs)
|
|
var/obj/item/organ/I = X
|
|
I.Insert(O, 1)
|
|
|
|
|
|
var/obj/item/bodypart/chest/torso = get_bodypart(BODY_ZONE_CHEST)
|
|
if(cavity_object)
|
|
torso.cavity_item = cavity_object //cavity item is given to the new chest
|
|
cavity_object.forceMove(O)
|
|
|
|
for(var/missing_zone in missing_bodyparts_zones)
|
|
var/obj/item/bodypart/BP = O.get_bodypart(missing_zone)
|
|
BP.drop_limb(1)
|
|
if(!(tr_flags & TR_KEEPORGANS)) //we didn't already get rid of the organs of the newly spawned mob
|
|
for(var/X in O.internal_organs)
|
|
var/obj/item/organ/G = X
|
|
if(BP.body_zone == check_zone(G.zone))
|
|
if(mind && mind.has_antag_datum(/datum/antagonist/changeling) && istype(G, /obj/item/organ/brain))
|
|
continue //so headless changelings don't lose their brain when transforming
|
|
qdel(G) //we lose the organs in the missing limbs
|
|
qdel(BP)
|
|
|
|
//transfer stuns
|
|
if(tr_flags & TR_KEEPSTUNS)
|
|
O.Stun(AmountStun(), ignore_canstun = TRUE)
|
|
O.Knockdown(AmountKnockdown(), ignore_canstun = TRUE)
|
|
O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE)
|
|
O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE)
|
|
O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE)
|
|
O.Sleeping(AmountSleeping(), ignore_canstun = TRUE)
|
|
|
|
//transfer reagents
|
|
if(tr_flags & TR_KEEPREAGENTS)
|
|
reagents.trans_to(O, reagents.total_volume)
|
|
|
|
if(mind)
|
|
mind.transfer_to(O)
|
|
var/datum/antagonist/changeling/changeling = O.mind.has_antag_datum(/datum/antagonist/changeling)
|
|
if(changeling)
|
|
for(var/datum/action/changeling/humanform/HF in changeling.purchasedpowers)
|
|
changeling.purchasedpowers -= HF
|
|
changeling.regain_powers()
|
|
|
|
O.a_intent = INTENT_HELP
|
|
if (tr_flags & TR_DEFAULTMSG)
|
|
to_chat(O, "<B>You are now a human.</B>")
|
|
|
|
transfer_observers_to(O)
|
|
|
|
. = O
|
|
|
|
for(var/A in loc.vars)
|
|
if(loc.vars[A] == src)
|
|
loc.vars[A] = O
|
|
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/human/AIize(transfer_after = TRUE, client/preference_source)
|
|
if (notransform)
|
|
return
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
return ..()
|
|
|
|
/mob/living/carbon/AIize(transfer_after = TRUE, client/preference_source)
|
|
if (notransform)
|
|
return
|
|
notransform = TRUE
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
return ..()
|
|
|
|
/mob/proc/AIize(transfer_after = TRUE, client/preference_source)
|
|
var/list/turf/landmark_loc = list()
|
|
for(var/obj/effect/landmark/start/ai/sloc in GLOB.landmarks_list)
|
|
if(locate(/mob/living/silicon/ai) in sloc.loc)
|
|
continue
|
|
if(sloc.primary_ai)
|
|
LAZYCLEARLIST(landmark_loc)
|
|
landmark_loc += sloc.loc
|
|
break
|
|
landmark_loc += sloc.loc
|
|
if(!landmark_loc.len)
|
|
to_chat(src, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.")
|
|
for(var/obj/effect/landmark/start/ai/sloc in GLOB.landmarks_list)
|
|
landmark_loc += sloc.loc
|
|
|
|
if(!landmark_loc.len)
|
|
message_admins("Could not find ai landmark for [src]. Yell at a mapper! We are spawning them at their current location.")
|
|
landmark_loc += loc
|
|
|
|
if(client)
|
|
stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
|
|
|
if(!transfer_after)
|
|
mind.active = FALSE
|
|
|
|
. = new /mob/living/silicon/ai(pick(landmark_loc), null, src)
|
|
|
|
if(preference_source)
|
|
apply_pref_name("ai",preference_source)
|
|
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/human/proc/Robotize(delete_items = 0, transfer_after = TRUE)
|
|
if (notransform)
|
|
return
|
|
notransform = TRUE
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
for(var/obj/item/W in src)
|
|
if(delete_items)
|
|
qdel(W)
|
|
else
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/mob/living/silicon/robot/R = new /mob/living/silicon/robot(loc)
|
|
|
|
R.gender = gender
|
|
R.invisibility = 0
|
|
|
|
if(client)
|
|
R.updatename(client)
|
|
|
|
if(mind) //TODO
|
|
if(!transfer_after)
|
|
mind.active = FALSE
|
|
mind.transfer_to(R)
|
|
else if(transfer_after)
|
|
R.key = key
|
|
|
|
if(R.mmi)
|
|
R.mmi.name = "[initial(R.mmi.name)]: [real_name]"
|
|
if(R.mmi.brain)
|
|
R.mmi.brain.name = "[real_name]'s brain"
|
|
if(R.mmi.brainmob)
|
|
R.mmi.brainmob.real_name = real_name //the name of the brain inside the cyborg is the robotized human's name.
|
|
R.mmi.brainmob.name = real_name
|
|
|
|
R.job = "Cyborg"
|
|
R.notify_ai(NEW_BORG)
|
|
|
|
. = R
|
|
qdel(src)
|
|
|
|
//human -> alien
|
|
/mob/living/carbon/human/proc/Alienize()
|
|
if (notransform)
|
|
return
|
|
notransform = TRUE
|
|
mobility_flags = NONE
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/alien_caste = pick("Hunter","Sentinel","Drone")
|
|
var/mob/living/carbon/alien/humanoid/new_xeno
|
|
switch(alien_caste)
|
|
if("Hunter")
|
|
new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc)
|
|
if("Sentinel")
|
|
new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc)
|
|
if("Drone")
|
|
new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
|
|
|
|
new_xeno.a_intent = INTENT_HARM
|
|
new_xeno.key = key
|
|
update_atom_languages()
|
|
|
|
to_chat(new_xeno, "<B>You are now an alien.</B>")
|
|
. = new_xeno
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/human/proc/slimeize(reproduce as num)
|
|
if (notransform)
|
|
return
|
|
notransform = TRUE
|
|
mobility_flags = NONE
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/mob/living/simple_animal/slime/new_slime
|
|
if(reproduce)
|
|
var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring)
|
|
var/list/babies = list()
|
|
for(var/i=1,i<=number,i++)
|
|
var/mob/living/simple_animal/slime/M = new/mob/living/simple_animal/slime(loc)
|
|
M.set_nutrition(round(nutrition/number))
|
|
step_away(M,src)
|
|
babies += M
|
|
new_slime = pick(babies)
|
|
else
|
|
new_slime = new /mob/living/simple_animal/slime(loc)
|
|
new_slime.a_intent = INTENT_HARM
|
|
new_slime.key = key
|
|
|
|
to_chat(new_slime, "<B>You are now a slime. Skreee!</B>")
|
|
. = new_slime
|
|
qdel(src)
|
|
|
|
/mob/proc/become_overmind(starting_points = 60)
|
|
var/mob/camera/blob/B = new /mob/camera/blob(get_turf(src), starting_points)
|
|
B.key = key
|
|
. = B
|
|
qdel(src)
|
|
|
|
|
|
/mob/living/carbon/human/proc/corgize()
|
|
if (notransform)
|
|
return
|
|
notransform = TRUE
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
for(var/t in bodyparts) //this really should not be necessary
|
|
qdel(t)
|
|
|
|
var/mob/living/simple_animal/pet/dog/corgi/new_corgi = new /mob/living/simple_animal/pet/dog/corgi (loc)
|
|
new_corgi.a_intent = INTENT_HARM
|
|
new_corgi.key = key
|
|
|
|
to_chat(new_corgi, "<B>You are now a Corgi. Yap Yap!</B>")
|
|
. = new_corgi
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/proc/gorillize()
|
|
if(notransform)
|
|
return
|
|
notransform = TRUE
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
SSblackbox.record_feedback("amount", "gorillas_created", 1)
|
|
|
|
var/Itemlist = get_equipped_items(TRUE)
|
|
Itemlist += held_items
|
|
for(var/obj/item/W in Itemlist)
|
|
dropItemToGround(W, TRUE)
|
|
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
var/mob/living/simple_animal/hostile/gorilla/new_gorilla = new (get_turf(src))
|
|
new_gorilla.a_intent = INTENT_HARM
|
|
if(mind)
|
|
mind.transfer_to(new_gorilla)
|
|
else
|
|
new_gorilla.key = key
|
|
to_chat(new_gorilla, "<B>You are now a gorilla. Ooga ooga!</B>")
|
|
. = new_gorilla
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/human/Animalize()
|
|
|
|
var/list/mobtypes = typesof(/mob/living/simple_animal)
|
|
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in sortList(mobtypes, /proc/cmp_typepaths_asc)
|
|
|
|
if(!safe_animal(mobpath))
|
|
to_chat(usr, "<span class='danger'>Sorry but this mob type is currently unavailable.</span>")
|
|
return
|
|
|
|
if(notransform)
|
|
return
|
|
notransform = TRUE
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
|
|
regenerate_icons()
|
|
icon = null
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/mob/new_mob = new mobpath(src.loc)
|
|
|
|
new_mob.key = key
|
|
new_mob.a_intent = INTENT_HARM
|
|
|
|
|
|
to_chat(new_mob, "<span class='boldnotice'>You suddenly feel more... animalistic.</span>")
|
|
. = new_mob
|
|
qdel(src)
|
|
|
|
/mob/proc/Animalize()
|
|
|
|
var/list/mobtypes = typesof(/mob/living/simple_animal)
|
|
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in sortList(mobtypes, /proc/cmp_typepaths_asc)
|
|
|
|
if(!safe_animal(mobpath))
|
|
to_chat(usr, "<span class='danger'>Sorry but this mob type is currently unavailable.</span>")
|
|
return
|
|
|
|
var/mob/new_mob = new mobpath(src.loc)
|
|
|
|
new_mob.key = key
|
|
new_mob.a_intent = INTENT_HARM
|
|
to_chat(new_mob, "<span class='boldnotice'>You feel more... animalistic.</span>")
|
|
|
|
. = new_mob
|
|
qdel(src)
|
|
|
|
/* Certain mob types have problems and should not be allowed to be controlled by players.
|
|
*
|
|
* This proc is here to force coders to manually place their mob in this list, hopefully tested.
|
|
* This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them.
|
|
*/
|
|
/mob/proc/safe_animal(MP)
|
|
|
|
//Bad mobs! - Remember to add a comment explaining what's wrong with the mob
|
|
if(!MP)
|
|
return 0 //Sanity, this should never happen.
|
|
|
|
if(ispath(MP, /mob/living/simple_animal/hostile/construct))
|
|
return 0 //Verbs do not appear for players.
|
|
|
|
//Good mobs!
|
|
if(ispath(MP, /mob/living/simple_animal/pet/cat))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/pet/dog/corgi))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/crab))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/hostile/carp))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/shade))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/hostile/killertomato))
|
|
return 1
|
|
if(ispath(MP, /mob/living/simple_animal/mouse))
|
|
return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak)
|
|
if(ispath(MP, /mob/living/simple_animal/hostile/bear))
|
|
return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak)
|
|
if(ispath(MP, /mob/living/simple_animal/parrot))
|
|
return 1 //Parrots are no longer unfinished! -Nodrak
|
|
|
|
//Not in here? Must be untested!
|
|
return 0
|
|
|
|
#undef TRANSFORMATION_DURATION
|