From dd4a4a5b7f9975ceea76c333556799cf97fc7abd Mon Sep 17 00:00:00 2001 From: "VivianFoxfoot@gmail.com" Date: Sun, 1 Apr 2012 15:27:21 +0000 Subject: [PATCH] Minor fixes to the tensioner, changes to the borg deathsquad from 6->3 and fixes their cell Changes changling unstun time to 45 from 25 Fix for the datumvars file which had spaces instead of tabs Adds the starts of a rather robust erping system! In time, we can make SS13 as realistic an ERP simulator as it is an atmos one. Adds metadata support for clients, mostly to hold ERPing notes. This is included in the savefile. Adds code support for a parrot in! Just needs a sprite Bugfix to the 'resist' button, unless I don't understand how it works. I don't see how it could have ever worked before. Preferences are now attached to a mob git-svn-id: http://tgstation13.googlecode.com/svn/trunk@3386 316c924e-a436-60f5-8080-3fe189b3f50e --- code/datums/configuration.dm | 4 + code/datums/datumvars.dm | 2 +- code/datums/helper_datums/tension.dm | 2 +- .../gamemodes/changeling/changeling_powers.dm | 6 +- .../mob/living/carbon/alien/humanoid/life.dm | 4 + .../mob/living/carbon/alien/larva/life.dm | 2 + code/modules/mob/living/carbon/brain/life.dm | 2 + code/modules/mob/living/carbon/human/human.dm | 3 + code/modules/mob/living/carbon/human/life.dm | 12 +- .../modules/mob/living/carbon/metroid/life.dm | 1 + code/modules/mob/living/carbon/monkey/life.dm | 2 + code/modules/mob/living/living.dm | 56 ++ code/modules/mob/living/say.dm | 5 +- .../modules/mob/living/silicon/robot/robot.dm | 1 + code/modules/mob/mob_ERP.dm | 891 ++++++++++++++++++ code/modules/mob/mob_defines.dm | 7 +- code/modules/mob/new_player/preferences.dm | 35 +- code/modules/mob/new_player/savefile.dm | 6 + code/modules/mob/screen.dm | 25 +- code/modules/mob/simple_animal/life.dm | 41 +- code/modules/mob/simple_animal/parrot.dm | 91 ++ code/setup.dm | 2 + config/config.txt | 5 +- html/changelog.html | 13 + icons/obj/ERP.dmi | Bin 0 -> 282 bytes tgstation.dme | 3 + 26 files changed, 1196 insertions(+), 25 deletions(-) create mode 100644 code/modules/mob/mob_ERP.dm create mode 100644 code/modules/mob/simple_animal/parrot.dm create mode 100644 icons/obj/ERP.dmi diff --git a/code/datums/configuration.dm b/code/datums/configuration.dm index 2fc67fe9c3e..bc9a2205d8f 100644 --- a/code/datums/configuration.dm +++ b/code/datums/configuration.dm @@ -33,6 +33,7 @@ var/traitor_scaling = 0 //if amount of traitors scales based on amount of players var/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other var/Tensioner_Active = 0 // If the tensioner is running. + var/allow_ERP = 1 // If naughtyness is allowed! var/list/mode_names = list() var/list/modes = list() // allowed modes @@ -230,6 +231,9 @@ if ("feature_object_spell_system") config.feature_object_spell_system = 1 + if ("disallow_erp") + config.allow_ERP = 0 + if ("traitor_scaling") config.traitor_scaling = 1 diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 0148991467e..2cdf0bc0599 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -361,7 +361,7 @@ client if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500)) // not sure if this is completely right... - if(0) //(L.vars.len > 0) + if(0) //(L.vars.len > 0) html += "
    " html += "
" else diff --git a/code/datums/helper_datums/tension.dm b/code/datums/helper_datums/tension.dm index db98affa090..7fc8e3fe6a9 100644 --- a/code/datums/helper_datums/tension.dm +++ b/code/datums/helper_datums/tension.dm @@ -715,7 +715,7 @@ var/global/datum/tension/tension_master candidates.Remove(G) if(candidates.len) - var/numagents = 6 + var/numagents = 3 //Spawns commandos and equips them. for (var/obj/effect/landmark/L in world) diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 3f3967ae194..cfab04b57bf 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -759,18 +759,18 @@ /client/proc/changeling_unstun() set category = "Changeling" - set name = "Epinephrine Sacs (25)" + set name = "Epinephrine Sacs (45)" set desc = "Removes all stuns" if(!usr.changeling) usr << "\red You're not a changeling, something's wrong!" return - if(usr.changeling.chem_charges < 25) + if(usr.changeling.chem_charges < 45) usr << "\red We don't have enough stored chemicals to do that!" return - usr.changeling.chem_charges -= 25 + usr.changeling.chem_charges -= 45 var/mob/living/carbon/human/C = usr diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index f6186ce36bc..6760429a780 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -14,8 +14,12 @@ if (src.monkeyizing) return + ..() + if (src.stat != 2) //still breathing + + //First, resolve location and get a breath if(air_master.current_cycle%4==2) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 43c44bf6df6..5f381f75e35 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -14,6 +14,8 @@ if (monkeyizing) return + ..() + if (stat != 2) //still breathing //First, resolve location and get a breath diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 3ced037a7c1..ef7a98d2976 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -4,6 +4,8 @@ set invisibility = 0 set background = 1 + ..() + var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE if(loc) environment = loc.return_air() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f9b432785e5..a78cd172d1e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -240,6 +240,9 @@ if (istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)&&wear_suit:s_initialized) stat("Energy Charge", round(wear_suit:cell:charge/100)) + if(sexuality && sexuality.showERPverbs) + stat("Current Pleasure:", sexuality.pleasure) + /mob/living/carbon/human/ex_act(severity) flick("flash", flash) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b55e93d0faa..23de3087113 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -19,6 +19,8 @@ if(!loc) // Fixing a null error that occurs when the mob isn't found in the world -- TLE return + ..() + var/datum/gas_mixture/environment = loc.return_air() if (stat != 2) //still breathing @@ -94,8 +96,6 @@ if(!currentTurf.sd_lumcount) playsound_local(src,pick(scarySounds),50, 1, -1) - ..() //for organs - /mob/living/carbon/human proc clamp_values() @@ -330,8 +330,10 @@ return null update_canmove() - if(paralysis || stunned || weakened || buckled || (changeling && changeling.changeling_fakedeath)) canmove = 0 - else canmove = 1 + if(paralysis || stunned || weakened || buckled || (changeling && changeling.changeling_fakedeath) || (sexuality && sexuality.sexualact)) + canmove = 0 + else + canmove = 1 handle_breath(datum/gas_mixture/breath) if(nodamage) @@ -666,7 +668,7 @@ src << "\red You suddenly feel blubbery!" mutations |= FAT update_body() - if (overeatduration < 100 && mutations & FAT) + if ((overeatduration < 100 && mutations & FAT) && !(sexuality && sexuality.vagina && sexuality.vagina.pregnancy)) src << "\blue You feel fit again!" mutations &= ~FAT update_body() diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index edda63cf6f6..c9750b2120f 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -5,6 +5,7 @@ if (src.monkeyizing) return + ..() var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE if(src.loc) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 9b41dc5fe16..97506dbfbee 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -14,6 +14,8 @@ if (src.monkeyizing) return + ..() + var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE if(src.loc) environment = loc.return_air() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6ff0f13b519..87df58fe5cd 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1,3 +1,59 @@ +/mob/living/Life() + // Putting this here because after initiation, another check per living mob isn't going to be that heavy, and other than that, christ. There's no single unifing place to make sure stuff is initiated. + // All mobs will have a Sexuality, and if its gender is initalized, we can assume we're done here. + + if(config.allow_ERP) + if(!src.sexuality.gender || src.sexuality.gender == "None") + if(gender) + if(gender == MALE) + makeMale() + + else if(gender == FEMALE) + makeFemale() + + else if(gender == NEUTER && (istype(src , /mob/living/carbon/alien/))) + makeHerm() + + else if(gender == NEUTER && (istype(src , /mob/living/carbon/monkey/))) + if(prob(50)) + makeMale() + else + makeFemale() + + else + sexuality.gender = "None" + + if(gender != sexuality.gender) // Sex change! + sexuality.gender = null // Todo, handle better later. + return + + if(src.sexuality.gender == FEMALE || sexuality.gender == "Herm") + if (sexuality.vagina.womb_fluid_contents.len) // Handles stuff leaking out of her womb and pregnancy chance + handleWombContents() + + if (sexuality.vagina.fluid_contents.len) // Handles any cocks or toys inside of her + handleVaginaContents() + + if(sexuality.vagina.pregnancy) + handlePregnancy() + // else + // handleMenstrationChance() // Menstration sucks. + + + + + // While I'm doing a terriblly lazy way of initalizing things, why don't I make it so people's preferences tag along with them. This could be useful in fixing the fucking cloned-as-unknown thing, making me not have to dynamically load them during tensioner, and of course, storing metadata. + + if(!src.storedpreferences) + src.storedpreferences = new + storedpreferences.savefile_load(src, 0) + + + + ..() + return + + /mob/living/verb/succumb() set hidden = 1 if ((src.health < 0 && src.health > -95.0)) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 45c9bc8029f..94e4a34dbca 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -133,8 +133,9 @@ //world << "channel_prefix=[channel_prefix]; message_mode=[message_mode]" if (message_mode) message = trim(copytext(message, 3)) - if (!ishuman(src) && (message_mode=="department" || (message_mode in radiochannels))) - message_mode = null //only humans can use headsets + //if (!ishuman(src) && (message_mode=="department" || (message_mode in radiochannels))) + // message_mode = null //only humans can use headsets + // Check removed so parrots can use headsets! if (!message) return diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index aaa88f63156..1714154a71a 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -33,6 +33,7 @@ lawupdate = 0 scrambledcodes = 1 src << "Follow your laws." + cell.maxcharge = 25000 cell.charge = 25000 module = new /obj/item/weapon/robot_module/syndicate(src) hands.icon_state = "standard" diff --git a/code/modules/mob/mob_ERP.dm b/code/modules/mob/mob_ERP.dm new file mode 100644 index 00000000000..afdc23b1ce1 --- /dev/null +++ b/code/modules/mob/mob_ERP.dm @@ -0,0 +1,891 @@ +// Most variables are initalized to a semi-random value on creation, in /mob/living/Life() (file code\modules\mob\living\living.dm) + +#define ORGASM_PLEASURE 200 + + +/mob + + var/datum/sexuality/sexuality = new // All mobs have this, others may or may not be defined. + +/datum/penis + var/num = 1 // Assuming all penies on a mob are of equal length and girth. + var/length =1 + var/girth = 1 + var/volume = 1 // Calculated on creation to be PI*(girth/2)*length + var/glans_sensitivity = 5 + var/orgasmtime = 30 + var/cumamount = 50 + var/erect = 0 + var/list/coating = list() + var/list/contents = list() // Not strictly contents (Although I suppose sounding would go under here too) but more chastity stuff. Maybe sounding. + var/location = null + var/hasKnot = 0 + var/hasBarbs = 0 + var/ballSize = 1 + var/isStrapon = 0 + +/datum/penis/proc/erect() + erect = 1 + return + + + + + + + + + + +/datum/vagina + var/depth = 1 + var/opening_width = 1 + var/cervix_width =1 + var/vaginal_elasticity = 0.5 + var/cervix_elasticity = 0.1 + var/list/womb_contents = list() //Solid things not including a baby. Used mostly for cervix penetration. + var/list/womb_fluid_contents = list() + var/datum/pregnancy/pregnancy = null + var/clit_sensitivity = 5 + var/lubricated = 0 + var/list/contents = list() // I was going to go with isOccupied, but what about double penetration in one hole? + var/list/fluid_contents = list() + var/list/outercontents = list() // Clips, pericings and chastity stuff. + var/isVirgin = 1 + +/datum/vagina/proc/impregnate(var/datum/fluid/cum/C) + var/datum/pregnancy/P = new + + if(prob(50)) + P.species = src.type + else + P.species = C.species + + pregnancy = P + +/datum/pregnancy + var/species = null + var/time = 0 + + + + + + + + + + + + + + +/datum/breasts + var/num = 2 + var/size = 5 + var/milkcontent = 0 + var/milking = 0 + var/list/contents = list() // Not strictly contents, pericings and clips and such on the nipples, moreso. + var/nipplesensitivity = 5 + + +/datum/ass + var/depth = 1 + var/anal_width = 1 + var/anal_elasticity = 0.5 + var/hasProstate = 0 + var/contents = list() + var/isVirgin = 1 + + +/datum/mouth // And throat. May also be used for muzzle. + var/deepthroating = 0 // If they can't breathe. Also bypasses spit/swallow! + var/list/contents = list() + var/length = 1 + var/gagreflex = 10 // Going to make it so you can train this out of a mob. + + + + + + + + + + + + + + + + + +/datum/underwear + var/contents = list() + + + + + + + + + + + + + + + + + + + + + + + +/datum/sexuality + var/gender = null // None, Male, Female, or Herm. What naughtybits they have. Defined again inside sexuality so that neuter-nouned mobs like Aliens can have naughtybits, and to also support gender-swapping! Wizard spell? + // A gender of null means their sexuality is yet to be lazy-intialized. + var/bladder = 20 + var/pleasure = 50 + var/isHairPullable = 1 + var/aggressive = 0 + var/collar = null + + var/datum/penis/penis = null + var/datum/vagina/vagina = null + var/datum/breasts/breasts = null + var/datum/ass/ass = null + var/datum/mouth/mouth = null + var/datum/underwear/underwear = new + + var/flatchest = 1 + var/multicocked = 0 + var/multibreasts = 0 // For Jarsh. + var/hastail = 0 + var/hasfur = 0 + + var/sexualact = null + var/reachingin = 0 + var/mob/living/initiatior = null + var/mob/living/initiated = null // Sorry, no orgies here. Maybe later. + + var/showERPverbs = 0 + + +/datum/sexuality/proc/resist() // TODO: Provide a specific resist message for every action, make it harder to resist some actions than others. + if(sexualact) + if(!aggressive) + initiatior << "\blue [usr] pulls away!" + initiated << "\blue [usr] pulls away!" + usr.canmove = 1 + sexualact = null + else + if(prob(10)) + initiatior << "\blue [usr] thrashes away!" + initiated << "\blue [usr] thrashes away!" + usr.canmove = 1 + initiatior.sexuality.sexualact = null + initiated.sexuality.sexualact = null + aggressive = 0 + initiatior.AdjustWeakened(3) + else + initiatior << "\blue [usr] tries to struggle away!" + initiated << "\blue [usr] tries to struggle away!" + return + +/datum/sexuality/proc/orgasm() + while(sexualact) + if(penis) + if(penis.location) + if(istype(penis.location, /datum/vagina)) //TODO: Add support for condoms. + var/found = 0 + for(var/datum/fluid/cum/C in penis.location:womb_fluid_contents) + if(C.creator == usr) + C.amount += 5 + found = 1 + break + if(!found) + var/datum/fluid/cum/C = new + C.amount = 5 + C.species = usr.type + C.creator = usr + if(istype(usr, /mob/living/carbon/)) + C.DNA = usr:dna + penis.location:womb_fluid_contents += C + if(prob(30)) + usr << "You finish orgasming." + sexualact = null + + + + sleep(20) + return + + + + + + + + + + + + + + + + + +/datum/fluid + var/name = null + var/desc = null + var/viscosity = null + var/colour = null + var/texture = null + var/taste = null + var/warmpth = null + var/amount = 0 + +/datum/fluid/urine + name = "Urine" + desc = "Golden yellow and musky." + viscosity = 1 + colour = "Golden yellow." + texture = "Water" + taste = "Musky" + warmpth = "Warm" + amount = 5 + +/datum/fluid/cum + name = "Semen" + desc = "This really should be inside someone." + viscosity = 1 + colour = "Milky white." + texture = "Stringy" + taste = "Pungent" + warmpth = "Warm" + amount = 5 + var/species = null + var/creator = null + var/datum/dna/DNA = null + + + +/datum/fluid/proc/leak(var/amount = 1, ) + var/datum/fluid/newfluid = new src.type(src) + var/transferamount = 0 + + if((src) && (newfluid)) + for(var/V in src.vars) + if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key", "amount"))) + newfluid.vars[V] = src.vars[V] + + + + if(src.amount < 2) + transferamount = src.amount + src.amount = 0 + else + transferamount = 2 + src.amount = src.amount - 2 + + if(src in usr.sexuality.vagina.womb_contents) + usr.sexuality.vagina.contents += newfluid + + else if(src in usr.sexuality.vagina.contents) + + if(prob(20)) + if(usr.underwear !=6) + usr.sexuality.underwear.contents += newfluid +/* else if( + var/turf/T = get_turf(usr) // Todo, make an overlay for the stuff dripping onto the floor or dampening the crotch of a jumpsuit. + if(T) + newfluid.loc = T + */ + newfluid.amount = transferamount + + + + + + + + + + + + + + + + + + + + + + +/mob/living/verb/Examine_OOC() + set name = "Examine Meta-Info (OOC)" + set category = "OOC" + set src in view() + + + if(config.allow_ERP) + + usr << "[src]'s Metainfo:" + if(src.storedpreferences) + usr << "[src] [src.storedpreferences.allow_ERP ? "allows" : "does not allow"] ERP with them!" + usr << "[src]'s ERP Notes: [src.storedpreferences.ERP_Notes]" + + else + usr << "[src] does not have any stored infomation!" + + else + usr << "OOC Metadata is not supported by this server!" + + return + +/mob/living/carbon/human/verb/toggleUnderwear() + set name = "Toggle Underwear" + set category = "IC" + set desc = "Remove or put back on your underwear." + + + if(!src.w_uniform && !src.wear_suit) + + if(underwear == 6) + if(storedpreferences.underwear == 6) + underwear = pick(1,2,3,4,5) + else + underwear = storedpreferences.underwear + + usr << "You pull your underwear out of hammerspace and put it on." + + else + underwear = 6 + usr << "You pull your underwear off and stuff it into hammerspace." + + else + usr << "You have to take your outer clothing off first!" + + update_body() + + + + + + + + + + + + +/mob/living/proc/makeMale() + src.sexuality.gender = MALE + + src.sexuality.penis = new + + src.sexuality.penis.length = rand(1,4) + src.sexuality.penis.girth = rand(1,3) + src.sexuality.penis.volume = PI*(src.sexuality.penis.girth/2)*src.sexuality.penis.length + src.sexuality.penis.glans_sensitivity = rand(2,6) + + src.sexuality.breasts = new + + src.sexuality.breasts.size = rand(0,1) + src.sexuality.breasts.nipplesensitivity = rand(1,4) + + src.sexuality.ass = new + + src.sexuality.ass.depth = rand(2,5) + src.sexuality.ass.anal_width = rand(1,3) + src.sexuality.ass.anal_elasticity = rand(1,4)/4 + src.sexuality.ass.hasProstate = 1 + + src.sexuality.mouth = new + + src.sexuality.mouth.length = rand(1,2) + + return + +/mob/living/proc/makeFemale() + src.sexuality.gender = FEMALE + src.sexuality.flatchest = 0 + + src.sexuality.vagina = new + + src.sexuality.vagina.depth = rand(3,6) + src.sexuality.vagina.opening_width = rand(1,2) + src.sexuality.vagina.cervix_width =rand(1,2)/3 + src.sexuality.vagina.vaginal_elasticity = rand(1,2)/2 + src.sexuality.vagina.cervix_elasticity = rand(1,10)/20 + src.sexuality.vagina.clit_sensitivity = rand(4,8) + + src.sexuality.breasts = new + + src.sexuality.breasts.size = rand(3,7) + src.sexuality.breasts.nipplesensitivity = rand(4,8) + src.sexuality.breasts.milkcontent = rand(10,20) + + src.sexuality.ass = new + + src.sexuality.ass.depth = rand(2,5) + src.sexuality.ass.anal_width = rand(1,3) + src.sexuality.ass.anal_elasticity = rand(1,4)/4 + + src.sexuality.mouth = new + + src.sexuality.mouth.length = rand(1,2) + return + +/mob/living/proc/makeHerm() + src.sexuality.gender = "Herm" + src.sexuality.flatchest = 0 + + + src.sexuality.penis = new + + src.sexuality.penis.length = rand(1,4) + src.sexuality.penis.girth = rand(1,3) + src.sexuality.penis.volume = PI*(src.sexuality.penis.girth/2)*src.sexuality.penis.length + src.sexuality.penis.glans_sensitivity = rand(2,6) + + src.sexuality.vagina = new + + src.sexuality.vagina.depth = rand(3,6) + src.sexuality.vagina.opening_width = rand(1,2) + src.sexuality.vagina.cervix_width =rand(1,2)/3 + src.sexuality.vagina.vaginal_elasticity = rand(1,2)/2 + src.sexuality.vagina.cervix_elasticity = rand(1,10)/20 + src.sexuality.vagina.clit_sensitivity = rand(4,8) + + src.sexuality.breasts = new + + src.sexuality.breasts.size = rand(3,7) + src.sexuality.breasts.nipplesensitivity = rand(4,8) + src.sexuality.breasts.milkcontent = rand(10,20) + + src.sexuality.ass = new + + src.sexuality.ass.depth = rand(2,5) + src.sexuality.ass.anal_width = rand(1,3) + src.sexuality.ass.anal_elasticity = rand(1,4)/4 + + src.sexuality.mouth = new + + src.sexuality.mouth.length = rand(1,2) + return + + + + + + + + + + + + + + + + + + + + + + +/mob/living/proc/handlePregnancy() + sexuality.vagina.pregnancy.time++ + if(prob(25)) + sexuality.breasts.milkcontent = max(100, sexuality.breasts.milkcontent+10) + sexuality.breasts.milking = 1 + if(prob(1)) + usr << "You feel nausous." + + if(sexuality.vagina.pregnancy.time > 250 && istype(usr, /mob/living/carbon/human)) + mutations |= FAT + usr:update_body() + return + + +/mob/living/proc/handleWombContents() + for(var/datum/fluid/cum/C in src.sexuality.vagina.womb_fluid_contents) + if(!sexuality.vagina.pregnancy) + if(prob(10)) + sexuality.vagina.impregnate(C) + if(sexuality.vagina.womb_fluid_contents.len && !sexuality.vagina.womb_contents.len) + for(var/datum/fluid/F in src.sexuality.vagina.womb_fluid_contents) + F.leak() + + + + return + +/mob/living/proc/handleVaginaContents() + if(sexuality.vagina.contents.len) + for(var/datum/fluid/F in src.sexuality.vagina.fluid_contents) + if(prob(20)) + F.leak() + + return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/mob/living/verb/addERPVerbs() + set name = "Show ERP Verbs" + set category = "OOC" + set desc = "Show ERP Verbs" + + if(!config.allow_ERP) + src << "This station's policies strictly prohibit that sort of thing!" + return + + if(!src.storedpreferences || !src.storedpreferences.allow_ERP) + src << "You don't feel that kind of thing is very professional at work." + return + + if(src.sexuality) + src.sexuality.showERPverbs = 1 + + for(var/Verb in ERPVerbs) + if(!(Verb in src.verbs)) + src.verbs += Verb + + +/mob/living/verb/removeERPVerbs() + set name = "Hide ERP Verbs" + set category = "OOC" + set desc = "Hide ERP Verbs" + for(var/Verb in src.verbs) + if((Verb in ERPVerbs)) + src.verbs -= Verb + if(src.sexuality) + src.sexuality.showERPverbs = 0 + +var/list/ERPVerbs = typesof(/client/ERP/command/proc/) + + + + +/* +/client/ERP/command/proc/ERP_Masturbate() + set name = "Masturbate" + set desc = "Pleasure yourself." + set category = "ERP" + usr.sexuality.pleasure += 1 + +/client/ERP/command/proc/ERP_Watersports() + set name = "Watersports" + set desc = "Absolutely humuilating!" + set category = "ERP" + usr.sexuality.pleasure = 5 + usr.sexuality.bladder -=5 +*/ + + + + + + +/client/ERP/command/proc/ERP_Fuck() + set name = "Intercourse" + set desc = "The fun part." + set category = "ERP" + + var/list/partners = list() + for(var/mob/living/carbon/C in oview(1)) + partners += C + var/mob/T = input(usr, "Who do you wish to fuck?") as null | anything in partners + + + + if(T && T in oview(1)) + if(!T.sexuality) + return + + if(!T.storedpreferences || !T.storedpreferences.allow_ERP) + usr << pick("You don't feel comfortable doing that.","That wouldn't be very professional.","That could strain your working relationship.") + return + + var/list/holes = list() + + if(T.sexuality.vagina) + holes += "Vagina" + +/* + if(T.sexuality.mouth) + holes += "Mouth" + if(T.sexuality.ass) + holes += "Ass" + + if(T.sexuality.penis) + holes += "Penis (Mount)" +*/ + + if(!holes.len) + usr << "Sorry, only girls can be fucked! (Right now)" + return + + var/answer = input(usr, "Where do you wish to fuck them?") as null | anything in holes + + switch(answer) + + if("Mouth") + call(/client/ERP/proc/ERP_Mouthfuck)(T) + if("Ass") + call(/client/ERP/proc/ERP_Assfuck)(T) + + if("Vagina") + call(/client/ERP/proc/ERP_Vaginafuck)(T) + + if("Penis (Mount)") + call(/client/ERP/proc/ERP_Mount)(T) + + + usr.verbs -= /client/ERP/command/proc/ERP_Fuck + + spawn(5) + usr.verbs += /client/ERP/command/proc/ERP_Fuck + + + return + +/client/ERP/proc/ERP_Mouthfuck(var/mob/partner) + + return + +/client/ERP/proc/ERP_Assfuck(var/mob/partner) + + return + +/client/ERP/proc/ERP_Vaginafuck(var/mob/partner) + + + + var/list/ways = list() + if(usr.sexuality.penis) + ways += "Penis" + + ways += "Fingers" + + for(var/obj/item/toy/sextoy/S in usr.contents) + ways += S + + var/answer = input(usr, "How do you wish to fuck them?") as null | anything in ways + switch(answer) + if("Penis") + if(istype(partner, /mob/living/carbon/human)) + if(partner:w_uniform || partner:wear_suit) // TODO: Make a flag that allows clothing that exposes the crotch. + usr << "[partner] has clothing covering them!" + return + if(partner:underwear != 6) + if(usr.sexuality.reachingin) + usr << "You pull [partner]'s underwear to the side..." + else + usr << "You can't really fuck them through their underwear." + return + + usr.sexuality.sexualact = "Vagina-Penis" + usr.sexuality.initiatior = usr + usr.sexuality.initiated = partner + partner.sexuality.sexualact = "Vagnia-Penis" + partner.sexuality.initiatior = usr + partner.sexuality.initiated = partner + + if(usr.sexuality.aggressive) //TODO: Actually use the width calcuations and stuff! + usr << "You insert your penis roughly into [partner]" + partner << "[usr] shoves themself into your folds!" + + else + usr << "You slowly insert yourself into [partner]" + partner << "[usr] slowly pushes himself into your folds." + + usr.sexuality.penis.location = partner.sexuality.vagina + partner.sexuality.vagina.isVirgin = 0 + + while(usr.sexuality.sexualact && partner.sexuality.sexualact) + if(usr.sexuality.aggressive) + usr.sexuality.pleasure += 6 + partner.sexuality.pleasure += 3 + + else + usr.sexuality.pleasure += 4 + partner.sexuality.pleasure += 2 + + if(prob(5)) + var/found = 0 + for(var/datum/fluid/cum/C in usr.sexuality.penis.location:fluid_contents) + if(C.creator == usr) + C.amount += 1 + found = 1 + break + if(!found) + var/datum/fluid/cum/C = new + C.amount = 1 + C.species = usr.type + C.creator = usr + if(istype(usr, /mob/living/carbon/)) + C.DNA = usr:dna + partner.sexuality.vagina.fluid_contents += C + + if(partner.sexuality.pleasure > ORGASM_PLEASURE) + partner.sexuality.pleasure = 20 + usr << "You feel [partner] convulse around your shaft!" + partner << "You orgasm!" + partner.sexuality.orgasm() + + + if(usr.sexuality.pleasure > ORGASM_PLEASURE) + usr.sexuality.pleasure = 20 + partner << "You feel [usr]'s heat shooting inside of you!" + usr << "You begin to climax inside of [partner]!" + usr.sexuality.orgasm() + + sleep(15) + + + + + + return + +/client/ERP/proc/ERP_Mount(var/mob/partner) + + return + + + + +/* TODO: Finish these. +/client/ERP/command/proc/ERP_Kiss() + set name = "Kiss" + set desc = "The loving part." + set category = "ERP" + +/client/ERP/command/proc/ERP_Oral() + set name = "Give Oral" + set desc = "Another fun part." + set category = "ERP" + +/client/ERP/command/proc/ERP_Pull() + set name = "Pull/Pinch" + set desc = "The painful part. Causes agressive sex." + set category = "ERP" + +*/ + +/client/ERP/command/proc/ERP_Underunderwear() + set name = "Reach into underwear" + set desc = "Reach into someone else's underwear" + set category = "ERP" + + + var/list/partners = list() + for(var/mob/living/carbon/C in oview(1)) + partners += C + var/mob/T = input(usr, "Whose underwear do you want to reach into?") as null | anything in partners + + + + if(T && T in view(1)) + if(!T.sexuality) + return + + if(!T.storedpreferences || !T.storedpreferences.allow_ERP) + usr << pick("You don't feel comfortable doing that.","That wouldn't be very professional.","That could strain your working relationship.") + return + + if(T.underwear == 6) + usr << "It's hard to reach into underwear they're not wearing!" + return + + usr << "You start to stick your hands into [T]'s underwear..." + T << "[usr] starts to stick their hands into your underwear!" + usr.sexuality.sexualact = "Underwear" + usr.sexuality.initiatior = usr + usr.sexuality.initiated = T + T.sexuality.sexualact = "Underwear" + T.sexuality.initiatior = usr + T.sexuality.initiated = T + + if(do_mob(usr, T)) + if(T.sexuality.sexualact) + usr.sexuality.reachingin = 1 + + usr.verbs -= /client/ERP/command/proc/ERP_Underunderwear + + spawn(5) + usr.verbs += /client/ERP/command/proc/ERP_Underunderwear + + + return + + + +/obj/item/toy/sextoy/ + name = "A sex toy!" + icon = 'ERP.dmi' + icon_state = "dragon_dildo" + +/obj/item/toy/sextoy/New() + if(!config.allow_ERP) + del(src) + + + + + + + + + + + + + + + diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index f6fa02d7abc..902de94967e 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -269,4 +269,9 @@ the mob is also allowed to move without any sort of restriction. For instance, i var/area/lastarea = null - var/digitalcamo = 0 // Can they be tracked by the AI? \ No newline at end of file + var/digitalcamo = 0 // Can they be tracked by the AI? + + // Note: Some mob ERP defines are located in mob_ERP.dm + + + var/datum/preferences/storedpreferences = null \ No newline at end of file diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm index a9332b20f41..6c2c077d34a 100644 --- a/code/modules/mob/new_player/preferences.dm +++ b/code/modules/mob/new_player/preferences.dm @@ -40,6 +40,10 @@ var/const BE_MONKEY =(1<<8) BE_PAI =(1<<9) + + + + datum/preferences var real_name @@ -110,6 +114,10 @@ datum/preferences job_engsec_low = 0 + // Naughty. + allow_ERP = 1 + ERP_Notes = "" + New() @@ -138,6 +146,12 @@ datum/preferences dat += "Play admin midis: [midis == 1 ? "Yes" : "No"]
" dat += "Ghost ears: [ghost_ears == 0 ? "Nearest Creatures" : "All Speech"]
" + + if(config.allow_ERP) + dat += "Allow ERP? [allow_ERP == 1 ? "Yes" : "No"]
" + dat += "OOC Notes/ERP Preferences: Edit
" + + if((user.client) && (user.client.holder) && (user.client.holder.rank) && (user.client.holder.level >= 5)) dat += "
OOC
" dat += "Change colour
__
" @@ -409,12 +423,29 @@ datum/preferences if(link_tags["age"]) switch(link_tags["age"]) if("input") - var/new_age = input(user, "Please select type in age: 20-45", "Character Generation") as num + var/new_age = input(user, "Please select type in age: 15-45", "Character Generation") as num if(new_age) - age = max(min(round(text2num(new_age)), 45), 20) + age = max(min(round(text2num(new_age)), 45), 15) if("random") age = rand (20, 45) + if(link_tags["ERP"]) + allow_ERP = !allow_ERP + + if(link_tags["OOC"]) + var/tempnote = "" + tempnote = input(user, "Please enter your OOC/ERP Notes!:", "Erp notes" , ERP_Notes) as text + var/list/bad_characters = list("_", "\"", "<", ">", ";", "\[", "\]", "{", "}", "|", "\\","0","1","2","3","4","5","6","7","8","9") + for(var/c in bad_characters) + tempnote = dd_replacetext(tempnote, c, "") + + if(length(tempnote) >= 255) + alert("That name is too long. (255 character max, please)") + return + + ERP_Notes = tempnote + return + if(link_tags["b_type"]) switch(link_tags["b_type"]) if("input") diff --git a/code/modules/mob/new_player/savefile.dm b/code/modules/mob/new_player/savefile.dm index 33635246d48..57917f35abe 100644 --- a/code/modules/mob/new_player/savefile.dm +++ b/code/modules/mob/new_player/savefile.dm @@ -60,6 +60,9 @@ datum/preferences/proc/savefile_save(mob/user) F["ooccolor"] << src.ooccolor F["lastchangelog"] << src.lastchangelog + F["allow_ERP"] << src.allow_ERP + F["ERP_Notes"] << src.ERP_Notes + return 1 // loads the savefile corresponding to the mob's ckey @@ -125,6 +128,9 @@ datum/preferences/proc/savefile_load(mob/user) F["job_engsec_med"] >> src.job_engsec_med F["job_engsec_low"] >> src.job_engsec_low + F["allow_ERP"] >> src.allow_ERP + F["ERP_Notes"] >> src.ERP_Notes + //NOTE: Conversion things go inside this if statement //When updating the save file remember to add 1 to BOTH the savefile constants //Also take the old conversion things that no longer apply out of this if diff --git a/code/modules/mob/screen.dm b/code/modules/mob/screen.dm index 19c853d54f9..63546a52ac6 100644 --- a/code/modules/mob/screen.dm +++ b/code/modules/mob/screen.dm @@ -423,13 +423,16 @@ if("hand") usr:swap_hand() if("resist") - if(usr.next_move < world.time) + if(usr.next_move > world.time) return usr.next_move = world.time + 20 if ((!( usr.stat ) && usr.canmove && !( usr.restrained() ))) + var/resisting = 0 for(var/obj/O in usr.requests) del(O) + resisting++ for(var/obj/item/weapon/grab/G in usr.grabbed_by) + resisting++ if (G.state == 1) del(G) else @@ -444,9 +447,9 @@ for(var/mob/O in viewers(usr, null)) O.show_message(text("\red [] has broken free of []'s headlock!", usr, G.assailant), 1) del(G) - for(var/mob/O in viewers(usr, null)) - O.show_message(text("\red [] resists!", usr), 1) - + if(resisting) + for(var/mob/O in viewers(usr, null)) + O.show_message(text("\red [] resists!", usr), 1) if(usr:handcuffed && usr:canmove && (usr.last_special <= world.time)) usr.next_move = world.time + 100 usr.last_special = world.time + 100 @@ -456,7 +459,8 @@ O.show_message(text("\red [] is trying to break the handcuffs!", usr), 1) spawn(0) if(do_after(usr, 50)) - if(!usr:handcuffed || usr:buckled) return + if(!usr:handcuffed || usr:buckled) + return for(var/mob/O in viewers(usr)) O.show_message(text("\red [] manages to break the handcuffs!", usr), 1) usr << "\green You successfully break your handcuffs." @@ -468,13 +472,13 @@ O.show_message(text("\red [] attempts to remove the handcuffs!", usr), 1) spawn(0) if(do_after(usr, 1200)) - if(!usr:handcuffed || usr:buckled) return // time leniency for lag which also might make this whole thing pointless but the server + if(!usr:handcuffed || usr:buckled) + return // time leniency for lag which also might make this whole thing pointless but the server for(var/mob/O in viewers(usr))// lags so hard that 40s isn't lenient enough - Quarxink O.show_message(text("\red [] manages to remove the handcuffs!", usr), 1) usr << "\blue You successfully remove your handcuffs." usr:handcuffed:loc = usr:loc usr:handcuffed = null - if(usr:handcuffed && (usr.last_special <= world.time) && usr:buckled) usr.next_move = world.time + 100 usr.last_special = world.time + 100 @@ -483,11 +487,16 @@ O.show_message(text("\red [] attempts to unbuckle themself!", usr), 1) spawn(0) if(do_after(usr, 1200)) - if(!usr:buckled) return + if(!usr:buckled) + return for(var/mob/O in viewers(usr)) O.show_message(text("\red [] manages to unbuckle themself!", usr), 1) usr << "\blue You successfully unbuckle yourself." usr:buckled.manual_unbuckle(usr) + + if(usr.sexuality) + usr.sexuality.resist() + if("module") if(issilicon(usr)) if(usr:module) diff --git a/code/modules/mob/simple_animal/life.dm b/code/modules/mob/simple_animal/life.dm index b86d70a9c57..7816457a940 100644 --- a/code/modules/mob/simple_animal/life.dm +++ b/code/modules/mob/simple_animal/life.dm @@ -70,20 +70,59 @@ density = 1 return + if(health < 1) Die() if(health > maxHealth) health = maxHealth + + // Stun/Weaken + + if (paralysis || stunned || weakened) //Stunned etc. + if (stunned > 0) + AdjustStunned(-1) + stat = 0 + if (weakened > 0) + AdjustWeakened(-1) + lying = 1 + stat = 0 + if (paralysis > 0) + AdjustParalysis(-1) + blinded = 1 + lying = 1 + stat = 1 + var/h = hand + hand = 0 + drop_item() + hand = 1 + drop_item() + hand = h + + else //Not stunned. + lying = 0 + stat = 0 + + if(paralysis || stunned || weakened || buckled) + canmove = 0 + else + canmove = 1 + //Movement if(!ckey && !stop_automated_movement) - if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc. + if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. turns_since_move++ if(turns_since_move >= turns_per_move) Move(get_step(src,pick(cardinal))) turns_since_move = 0 + + + + + + //Speaking if(speak_chance) if(prob(speak_chance)) diff --git a/code/modules/mob/simple_animal/parrot.dm b/code/modules/mob/simple_animal/parrot.dm new file mode 100644 index 00000000000..e31ab772792 --- /dev/null +++ b/code/modules/mob/simple_animal/parrot.dm @@ -0,0 +1,91 @@ +/mob/living/simple_animal/parrot + name = "\improper Parrot" + desc = "It's a parrot! No dirty words!" + icon = 'mob.dmi' + icon_state = "cat" + icon_living = "cat" + icon_dead = "cat_dead" + speak = list("Hi","Hello!","Cracker?","BAWWWWK george mellons griffing me") + speak_emote = list("squawks","says","yells") + emote_hear = list("squawks","bawks") + emote_see = list("flutters its wings", "glares at you") + speak_chance = 1 + turns_per_move = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker/ + response_help = "pets the" + response_disarm = "gently moves aside the" + response_harm = "swats the" + + var/obj/item/device/radio/headset/ears = new /obj/item/device/radio/headset/heads/ce() + +/mob/living/simple_animal/parrot/DrProfessor + name = "Doctor Professor Parrot, PhD" + desc = "That's the Doctor Professor. He has more degrees than all of the engineering team put together, and has several published papers on quantum cracker theory." + speak = list(":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN RIG SUIT?",":e OH GOD ITS FREE CALL THE SHUTTLE") + response_harm = "is attacked in the face by" + +/obj/item/weapon/reagent_containers/food/snacks/cracker/ + name = "Cracker" + desc = "It's a salted cracker." + +/mob/living/simple_animal/parrot/show_inv(mob/user as mob) + user.machine = src + if(user.stat) return + + var/dat = "
Inventory of [name]

" + if(ears) + dat += "
Headset: [ears] (Remove)" + else + dat += "
Headset: Nothing" + + user << browse(dat, text("window=mob[];size=325x500", name)) + onclose(user, "mob[real_name]") + return + + + +/mob/living/simple_animal/parrot/Topic(href, href_list) + if(usr.stat) return + + //Removing from inventory + if(href_list["remove_inv"]) + if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + var/remove_from = href_list["remove_inv"] + switch(remove_from) + if("ears") + if(ears) + src.say(":e BAWWWWWK LEAVE THE HEADSET BAWKKKKK!") + ears.loc = src.loc + ears = null + else + usr << "\red There is nothing to remove from its [remove_from]." + return + + //Adding things to inventory + else if(href_list["add_inv"]) + if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + var/add_to = href_list["add_inv"] + if(!usr.get_active_hand()) + usr << "\red You have nothing in your hand to put on its [add_to]." + return + switch(add_to) + if("ears") + if(ears) + usr << "\red It's already wearing something." + return + else + var/obj/item/item_to_add = usr.get_active_hand() + if(!item_to_add) + return + + if( !istype(item_to_add, /obj/item/device/radio/headset) ) + usr << "\red This object won't fit." + return + + usr.drop_item() + item_to_add.loc = src + src.ears = item_to_add + else + ..() diff --git a/code/setup.dm b/code/setup.dm index c53ce76659f..613c7747ba3 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -1,3 +1,5 @@ +#define PI 3.1415 + #define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol) #define ONE_ATMOSPHERE 101.325 //kPa diff --git a/config/config.txt b/config/config.txt index bf799f8362e..1eeb676d2d2 100644 --- a/config/config.txt +++ b/config/config.txt @@ -72,11 +72,14 @@ ALLOW_RANDOM_EVENTS #TRAITOR_SCALING ## If security is prohibited from being most antagonists -PROTECT_ROLES_FROM_ANTAGONIST +#PROTECT_ROLES_FROM_ANTAGONIST ## If the auto-tensioner is active by default. It creates more tratiors/other antagonists if it consideers the round slowing down. TENSIONER_ACTIVE +## If naughtness isn't allowed! +#DISALLOW_ERP + ## allow players to initiate a restart vote ALLOW_VOTE_RESTART diff --git a/html/changelog.html b/html/changelog.html index 2c312c78f9e..356963dbd6e 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -130,6 +130,13 @@ should be listed in the changelog upon commit tho. Thanks. --> +

+

Sunday, April 1st

+ + +
+ +

April Fools Day! Get hype!

Doohl updated:

@@ -160,6 +167,12 @@ should be listed in the changelog upon commit tho. Thanks. -->
  • You can make wooden cyborgs.
  • Added a few sex-related commands.
  • +

    PolymorphBlue updated:

    +
    diff --git a/icons/obj/ERP.dmi b/icons/obj/ERP.dmi new file mode 100644 index 0000000000000000000000000000000000000000..7494b4e03de20a152f69d063612049b8a6476d6b GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$ef*8>L*%rri8#`w(Sgrpll zLB^6GzhDN3XE)M-oPw&5h!U67;^d;tf|AVqJO+k}Il*BCMWx@r1Q&e#`b5iHSL@uF z^T8WJ4K5l#c%*aQNAn~@QBUs<3*#W;%f?;`a~@4PGATqMSaYd{p{>2XovN|AYJ6w6 zvFhd(5*j%tj?N65GGjJZqPF&qUppIo*%=gX%Y0nAe9a}G-Oipajv*3LlM@ywaWq`& zQ4C;vEux`ZqQ#~xGFP!H!NQ@3lecxo2`MQlrm2mqj-?#9y5Ud>qi@-Pvm6bPjRrRv bxtSTZToTRdm^L{ZXdHv5tDnm{r-UW|5NTzt literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 15737658ea2..2a923ae4f06 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -174,6 +174,7 @@ #define FILE_DIR "icons/vending_icons" #define FILE_DIR "interface" #define FILE_DIR "maps" +#define FILE_DIR "maps/backup" #define FILE_DIR "sound" #define FILE_DIR "sound/AI" #define FILE_DIR "sound/ambience" @@ -815,6 +816,7 @@ #include "code\modules\mob\mob.dm" #include "code\modules\mob\mob_cleanup.dm" #include "code\modules\mob\mob_defines.dm" +#include "code\modules\mob\mob_ERP.dm" #include "code\modules\mob\mob_grab.dm" #include "code\modules\mob\mob_helpers.dm" #include "code\modules\mob\mob_movement.dm" @@ -941,6 +943,7 @@ #include "code\modules\mob\simple_animal\corgi.dm" #include "code\modules\mob\simple_animal\crab.dm" #include "code\modules\mob\simple_animal\life.dm" +#include "code\modules\mob\simple_animal\parrot.dm" #include "code\modules\mob\simple_animal\shade.dm" #include "code\modules\mob\simple_animal\worm.dm" #include "code\modules\paperwork\clipboard.dm"