mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-04 05:51:54 +00:00
## About The Pull Request this pr transforms cats into basic pets! cats now have some new behavior. they can carry fish and hunted mice in their mouths to deliver it to kittens, and kittens will eat them.   if a kitten sees you holding food, it will point at you and meow loudly until u give it the food. becareful when putting male cats near each other, there is a small chance they get into a heated argument and meow loudly at each other until one of them flees. also added a new small cat house for cats. cats will use these homes if u build one near them (using 5 wood planks)  Chefs can craft the cake cat and breadcat. these are useful cats because they can help the chef around in the kitchen. they will turn stoves and grills off when food is ready, so they dont burn. and the cake cat will help the chef decorate his donuts ## Why It's Good For The Game refactors cats into basic mobs and gives them a deeper ai ## Changelog 🆑 refactor: cats are now basic pets. please report any bugs. add: the cake cat and bread cat can now help the chef around in the kitchen /🆑
410 lines
13 KiB
Plaintext
410 lines
13 KiB
Plaintext
#define TRANSFORMATION_DURATION 22
|
|
/// Will be removed once the transformation is complete.
|
|
#define TEMPORARY_TRANSFORMATION_TRAIT "temporary_transformation"
|
|
/// Considered "permanent" since we'll be deleting the old mob and the client will be inserted into a new one (without this trait)
|
|
#define PERMANENT_TRANSFORMATION_TRAIT "permanent_transformation"
|
|
|
|
/mob/living/carbon/proc/monkeyize(instant = FALSE)
|
|
if (transformation_timer || HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
|
|
if(ismonkey(src))
|
|
return
|
|
|
|
if(instant)
|
|
finish_monkeyize()
|
|
return
|
|
|
|
//Make mob invisible and spawn animation
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
|
icon = null
|
|
cut_overlays()
|
|
|
|
var/obj/effect = new /obj/effect/temp_visual/monkeyify(loc)
|
|
effect.SetInvisibility(invisibility)
|
|
SetInvisibility(INVISIBILITY_MAXIMUM, id=type)
|
|
|
|
transformation_timer = addtimer(CALLBACK(src, PROC_REF(finish_monkeyize)), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
|
|
|
/mob/living/carbon/proc/finish_monkeyize()
|
|
transformation_timer = null
|
|
to_chat(src, span_boldnotice("You are now a monkey."))
|
|
REMOVE_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
icon = initial(icon)
|
|
RemoveInvisibility(type)
|
|
set_species(/datum/species/monkey)
|
|
name = "monkey"
|
|
set_name()
|
|
SEND_SIGNAL(src, COMSIG_HUMAN_MONKEYIZE)
|
|
uncuff()
|
|
return src
|
|
|
|
////////////////////////// Humanize //////////////////////////////
|
|
//Could probably be merged with monkeyize but other transformations got their own procs, too
|
|
|
|
/mob/living/carbon/proc/humanize(species = /datum/species/human, instant = FALSE)
|
|
if (transformation_timer || HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
|
|
if(!ismonkey(src))
|
|
return
|
|
|
|
if(instant)
|
|
finish_humanize(species)
|
|
return
|
|
|
|
//Make mob invisible and spawn animation
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
|
icon = null
|
|
cut_overlays()
|
|
|
|
var/obj/effect = new /obj/effect/temp_visual/monkeyify/humanify(loc)
|
|
effect.SetInvisibility(invisibility)
|
|
SetInvisibility(INVISIBILITY_MAXIMUM, id=type)
|
|
|
|
transformation_timer = addtimer(CALLBACK(src, PROC_REF(finish_humanize), species), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
|
|
|
/mob/living/carbon/proc/finish_humanize(species = /datum/species/human)
|
|
transformation_timer = null
|
|
to_chat(src, span_boldnotice("You are now a human."))
|
|
REMOVE_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
icon = initial(icon)
|
|
RemoveInvisibility(type)
|
|
set_species(species)
|
|
SEND_SIGNAL(src, COMSIG_MONKEY_HUMANIZE)
|
|
return src
|
|
|
|
/mob/proc/AIize(client/preference_source, move = TRUE)
|
|
var/list/turf/landmark_loc = list()
|
|
|
|
if(!move)
|
|
landmark_loc += loc
|
|
else
|
|
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(!length(landmark_loc))
|
|
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(!length(landmark_loc))
|
|
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)
|
|
|
|
var/mob/living/silicon/ai/our_AI = new /mob/living/silicon/ai(pick(landmark_loc), null, src)
|
|
. = our_AI
|
|
|
|
if(preference_source)
|
|
apply_pref_name(/datum/preference/name/ai, preference_source)
|
|
our_AI.apply_pref_hologram_display(preference_source)
|
|
our_AI.set_core_display_icon(null, preference_source)
|
|
|
|
qdel(src)
|
|
|
|
/mob/living/carbon/AIize(client/preference_source, transfer_after = TRUE)
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
return ..()
|
|
|
|
/mob/living/carbon/human/AIize(client/preference_source, transfer_after = TRUE)
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
return ..()
|
|
|
|
/mob/proc/Robotize(delete_items = 0, transfer_after = TRUE)
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
var/mob/living/silicon/robot/new_borg = new /mob/living/silicon/robot(loc)
|
|
|
|
new_borg.gender = gender
|
|
new_borg.SetInvisibility(INVISIBILITY_NONE)
|
|
|
|
if(client)
|
|
new_borg.updatename(client)
|
|
|
|
if(mind) //TODO //TODO WHAT
|
|
if(!transfer_after)
|
|
mind.active = FALSE
|
|
mind.transfer_to(new_borg)
|
|
else if(transfer_after)
|
|
new_borg.key = key
|
|
|
|
if(new_borg.mmi)
|
|
new_borg.mmi.name = "[initial(new_borg.mmi.name)]: [real_name]"
|
|
if(new_borg.mmi.brain)
|
|
new_borg.mmi.brain.name = "[real_name]'s brain"
|
|
if(new_borg.mmi.brainmob)
|
|
new_borg.mmi.brainmob.real_name = real_name //the name of the brain inside the cyborg is the robotized human's name.
|
|
new_borg.mmi.brainmob.name = real_name
|
|
|
|
new_borg.job = JOB_CYBORG
|
|
new_borg.notify_ai(AI_NOTIFICATION_NEW_BORG)
|
|
|
|
. = new_borg
|
|
if(new_borg.ckey && is_banned_from(new_borg.ckey, JOB_CYBORG))
|
|
INVOKE_ASYNC(new_borg, TYPE_PROC_REF(/mob/living/silicon/robot, replace_banned_cyborg))
|
|
qdel(src)
|
|
|
|
/mob/living/Robotize(delete_items = 0, transfer_after = TRUE)
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
for(var/obj/item/W in src)
|
|
if(delete_items)
|
|
qdel(W)
|
|
else
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
|
|
REMOVE_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT)
|
|
return ..()
|
|
|
|
/mob/living/silicon/robot/proc/replace_banned_cyborg()
|
|
to_chat(src, "<b>You are job banned from cyborg! Appeal your job ban if you want to avoid this in the future!</b>")
|
|
ghostize(FALSE)
|
|
|
|
var/list/mob/dead/observer/candidates = poll_candidates_for_mob("Do you want to play as [src]?", "Cyborg", null, 5 SECONDS, src)
|
|
if(LAZYLEN(candidates))
|
|
var/mob/dead/observer/chosen_candidate = pick(candidates)
|
|
message_admins("[key_name_admin(chosen_candidate)] has taken control of ([key_name_admin(src)]) to replace a jobbanned player.")
|
|
key = chosen_candidate.key
|
|
|
|
//human -> alien
|
|
/mob/living/carbon/human/proc/Alienize()
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_GENERIC)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/alien_caste = pick("Hunter","Sentinel","Drone")
|
|
var/mob/living/carbon/alien/adult/new_xeno
|
|
switch(alien_caste)
|
|
if("Hunter")
|
|
new_xeno = new /mob/living/carbon/alien/adult/hunter(loc)
|
|
if("Sentinel")
|
|
new_xeno = new /mob/living/carbon/alien/adult/sentinel(loc)
|
|
if("Drone")
|
|
new_xeno = new /mob/living/carbon/alien/adult/drone(loc)
|
|
|
|
new_xeno.set_combat_mode(TRUE)
|
|
new_xeno.key = key
|
|
|
|
to_chat(new_xeno, span_boldnotice("You are now an alien."))
|
|
qdel(src)
|
|
return new_xeno
|
|
|
|
/mob/living/carbon/human/proc/slimeize(reproduce as num)
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_GENERIC)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(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 in 1 to number)
|
|
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.set_combat_mode(TRUE)
|
|
new_slime.key = key
|
|
|
|
to_chat(new_slime, span_boldnotice("You are now a slime. Skreee!"))
|
|
qdel(src)
|
|
return new_slime
|
|
|
|
/mob/proc/become_overmind(starting_points = OVERMIND_STARTING_POINTS)
|
|
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(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
for(var/t in bodyparts) //this really should not be necessary
|
|
qdel(t)
|
|
|
|
var/mob/living/basic/pet/dog/corgi/new_corgi = new /mob/living/basic/pet/dog/corgi (loc)
|
|
new_corgi.set_combat_mode(TRUE)
|
|
new_corgi.key = key
|
|
|
|
to_chat(new_corgi, span_boldnotice("You are now a Corgi. Yap Yap!"))
|
|
qdel(src)
|
|
return new_corgi
|
|
|
|
/mob/living/carbon/proc/gorillize()
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
SSblackbox.record_feedback("amount", "gorillas_created", 1)
|
|
|
|
var/Itemlist = get_equipped_items(include_pockets = TRUE)
|
|
Itemlist += held_items
|
|
for(var/obj/item/W in Itemlist)
|
|
dropItemToGround(W, TRUE)
|
|
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
var/mob/living/basic/gorilla/new_gorilla = new (get_turf(src))
|
|
new_gorilla.set_combat_mode(TRUE)
|
|
if(mind)
|
|
mind.transfer_to(new_gorilla)
|
|
else
|
|
new_gorilla.key = key
|
|
to_chat(new_gorilla, span_boldnotice("You are now a gorilla. Ooga ooga!"))
|
|
qdel(src)
|
|
return new_gorilla
|
|
|
|
/mob/living/carbon/human/Animalize()
|
|
|
|
var/list/mobtypes = typesof(/mob/living/simple_animal) + typesof(/mob/living/basic)
|
|
var/mobpath = tgui_input_list(usr, "Which type of mob should [src] turn into?", "Choose a type", sort_list(mobtypes, GLOBAL_PROC_REF(cmp_typepaths_asc)))
|
|
if(isnull(mobpath))
|
|
return
|
|
if(!safe_animal(mobpath))
|
|
to_chat(usr, span_danger("Sorry but this mob type is currently unavailable."))
|
|
return
|
|
|
|
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
|
|
Paralyze(1, ignore_canstun = TRUE)
|
|
|
|
for(var/obj/item/W in src)
|
|
dropItemToGround(W)
|
|
|
|
regenerate_icons()
|
|
icon = null
|
|
SetInvisibility(INVISIBILITY_MAXIMUM)
|
|
|
|
for(var/t in bodyparts)
|
|
qdel(t)
|
|
|
|
var/mob/living/new_mob = new mobpath(src.loc)
|
|
|
|
new_mob.key = key
|
|
new_mob.set_combat_mode(TRUE)
|
|
|
|
to_chat(new_mob, span_boldnotice("You suddenly feel more... animalistic."))
|
|
qdel(src)
|
|
return new_mob
|
|
|
|
/mob/proc/Animalize()
|
|
|
|
var/list/mobtypes = typesof(/mob/living/simple_animal) + typesof(/mob/living/basic)
|
|
var/mobpath = tgui_input_list(usr, "Which type of mob should [src] turn into?", "Choose a type", sort_list(mobtypes, GLOBAL_PROC_REF(cmp_typepaths_asc)))
|
|
if(isnull(mobpath))
|
|
return
|
|
if(!safe_animal(mobpath))
|
|
to_chat(usr, span_danger("Sorry but this mob type is currently unavailable."))
|
|
return
|
|
|
|
var/mob/living/new_mob = new mobpath(src.loc)
|
|
|
|
new_mob.key = key
|
|
new_mob.set_combat_mode(TRUE)
|
|
to_chat(new_mob, span_boldnotice("You feel more... animalistic."))
|
|
|
|
. = 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 shouldn't 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 FALSE //Sanity, this should never happen.
|
|
|
|
if(ispath(MP, /mob/living/basic/construct))
|
|
return FALSE //Verbs do not appear for players.
|
|
|
|
//Good mobs!
|
|
if(ispath(MP, /mob/living/basic/pet/cat))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/pet/dog/corgi))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/crab))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/carp))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/mushroom))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/shade))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/killer_tomato))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/mouse))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/bear))
|
|
return TRUE
|
|
if(ispath(MP, /mob/living/basic/parrot))
|
|
return TRUE //Parrots are no longer unfinished! -Nodrak
|
|
|
|
//Not in here? Must be untested!
|
|
return FALSE
|
|
|
|
#undef PERMANENT_TRANSFORMATION_TRAIT
|
|
#undef TEMPORARY_TRANSFORMATION_TRAIT
|
|
#undef TRANSFORMATION_DURATION
|