diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm
index 94059c0880..767894050d 100644
--- a/code/__DEFINES/loadout.dm
+++ b/code/__DEFINES/loadout.dm
@@ -54,3 +54,16 @@
//donator items
#define LOADOUT_CATEGORY_DONATOR "Donator"
+
+//how many prosthetics can we have
+#define MAXIMUM_LOADOUT_PROSTHETICS 2
+
+//what limbs can be amputated or be prosthetic
+#define LOADOUT_ALLOWED_LIMB_TARGETS list(BODY_ZONE_L_ARM,BODY_ZONE_R_ARM,BODY_ZONE_L_LEG,BODY_ZONE_R_LEG)
+
+//options for modifiying limbs
+#define LOADOUT_LIMB_NORMAL "Normal"
+#define LOADOUT_LIMB_PROSTHETIC "Prosthetic"
+#define LOADOUT_LIMB_AMPUTATED "Amputated"
+
+#define LOADOUT_LIMBS list(LOADOUT_LIMB_NORMAL,LOADOUT_LIMB_PROSTHETIC,LOADOUT_LIMB_AMPUTATED) //you can amputate your legs/arms though
\ No newline at end of file
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 0bc4e6665a..9af86653f4 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -396,6 +396,7 @@ SUBSYSTEM_DEF(ticker)
SSjob.EquipRank(N, player.mind.assigned_role, 0)
if(CONFIG_GET(flag/roundstart_traits) && ishuman(N.new_character))
SSquirks.AssignQuirks(N.new_character, N.client, TRUE, TRUE, SSjob.GetJob(player.mind.assigned_role), FALSE, N)
+ N.client.prefs.post_copy_to(player)
CHECK_TICK
if(captainless)
for(var/mob/dead/new_player/N in GLOB.player_list)
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index 68b5d6f987..a1ff38862b 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -211,24 +211,27 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/paraplegic/on_spawn()
- if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
- quirk_holder.buckled.unbuckle_mob(quirk_holder)
+ if(quirk_holder.client)
+ modified_limbs = quirk_holder.client.prefs.modified_limbs
+ if(!(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !character.has_quirk(/datum/quirk/paraplegic) && !isjellyperson(character))
+ if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
+ quirk_holder.buckled.unbuckle_mob(quirk_holder)
- var/turf/T = get_turf(quirk_holder)
- var/obj/structure/chair/spawn_chair = locate() in T
+ var/turf/T = get_turf(quirk_holder)
+ var/obj/structure/chair/spawn_chair = locate() in T
- var/obj/vehicle/ridden/wheelchair/wheels = new(T)
- if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
- wheels.setDir(spawn_chair.dir)
+ var/obj/vehicle/ridden/wheelchair/wheels = new(T)
+ if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
+ wheels.setDir(spawn_chair.dir)
- wheels.buckle_mob(quirk_holder)
+ wheels.buckle_mob(quirk_holder)
- // During the spawning process, they may have dropped what they were holding, due to the paralysis
- // So put the things back in their hands.
+ // During the spawning process, they may have dropped what they were holding, due to the paralysis
+ // So put the things back in their hands.
- for(var/obj/item/I in T)
- if(I.fingerprintslast == quirk_holder.ckey)
- quirk_holder.put_in_hands(I)
+ for(var/obj/item/I in T)
+ if(I.fingerprintslast == quirk_holder.ckey)
+ quirk_holder.put_in_hands(I)
/datum/quirk/poor_aim
name = "Poor Aim"
@@ -244,42 +247,6 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
mob_trait = TRAIT_PROSOPAGNOSIA
medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces."
-/datum/quirk/prosthetic_limb
- name = "Prosthetic Limb"
- desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!"
- value = -1
- var/slot_string = "limb"
-
-/datum/quirk/prosthetic_limb/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/limb_slot
- if(HAS_TRAIT(H, TRAIT_PARA))//Prevent paraplegic legs being replaced
- limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
- else
- limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
- var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot)
- var/obj/item/bodypart/prosthetic
- switch(limb_slot)
- if(BODY_ZONE_L_ARM)
- prosthetic = new/obj/item/bodypart/l_arm/robot/surplus(quirk_holder)
- slot_string = "left arm"
- if(BODY_ZONE_R_ARM)
- prosthetic = new/obj/item/bodypart/r_arm/robot/surplus(quirk_holder)
- slot_string = "right arm"
- if(BODY_ZONE_L_LEG)
- prosthetic = new/obj/item/bodypart/l_leg/robot/surplus(quirk_holder)
- slot_string = "left leg"
- if(BODY_ZONE_R_LEG)
- prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(quirk_holder)
- slot_string = "right leg"
- prosthetic.replace_limb(H)
- qdel(old_part)
- H.regenerate_icons()
-
-/datum/quirk/prosthetic_limb/post_add()
- to_chat(quirk_holder, "Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
- you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.")
-
/datum/quirk/insanity
name = "Reality Dissociation Syndrome"
desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. This is not a license to grief."
diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm
index 6f1aec287b..ac2206863a 100644
--- a/code/game/objects/items/miscellaneous.dm
+++ b/code/game/objects/items/miscellaneous.dm
@@ -272,4 +272,3 @@
icon_state = "skub"
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("skubbed")
-
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 778b5175a7..380e5c5412 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -163,6 +163,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
)
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
var/custom_tongue = "default" //if your tongue is to be something other than your races
+ var/modified_limbs = list()
/// Security record note section
var/security_records
@@ -425,12 +426,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
"
if(gender != NEUTER && pref_species.sexes)
dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
"
+ dat += "Limb Modification:
"
+ dat += "Modify Limbs
"
+ for(var/modification in modified_limbs)
+ dat += "[modification]: [modified_limbs[modification]]
"
+ dat += "
"
dat += "Species:[pref_species.name]
"
dat += "Custom Species Name:[custom_species ? custom_species : "None"]
"
dat += "Random Body:Randomize!
"
dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
"
dat += "
Cycle background:[bgstate]
"
-
var/use_skintones = pref_species.use_skintones
if(use_skintones)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -1223,6 +1228,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
for(var/V in all_quirks)
var/datum/quirk/T = SSquirks.quirks[V]
bal -= initial(T.value)
+ for(var/modification in modified_limbs)
+ if(modified_limbs[modification] == "Prosthetic")
+ return bal + 1 //max 1 point regardless of how many prosthetics
return bal
/datum/preferences/proc/GetPositiveQuirkCount()
@@ -1475,6 +1483,26 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("cycle_bg")
bgstate = next_list_item(bgstate, bgstate_options)
+ if("modify_limbs")
+ var/limb_type = input(user, "Choose the limb to modify:", "Character Preference") as null|anything in LOADOUT_ALLOWED_LIMB_TARGETS
+ if(limb_type)
+ var/modification_type = input(user, "Choose the modification to the limb:", "Character Preference") as null|anything in LOADOUT_LIMBS
+ if(modification_type)
+ if(modification_type == LOADOUT_LIMB_PROSTHETIC)
+ var/number_of_prosthetics = 0
+ for(var/modification in modified_limbs)
+ if(modified_limbs[modification] == LOADOUT_LIMB_PROSTHETIC)
+ number_of_prosthetics += 1
+ if(number_of_prosthetics >= MAXIMUM_LOADOUT_PROSTHETICS)
+ to_chat(user, "You can only have up to two prosthetic limbs!")
+ return
+ else
+ if(modification_type == LOADOUT_LIMB_NORMAL)
+ modified_limbs -= limb_type
+ ShowChoices(user)
+ return 1
+ modified_limbs[limb_type] = modification_type
+
if("underwear")
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_list
if(new_underwear)
@@ -2544,6 +2572,27 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(custom_speech_verb != "default")
character.dna.species.say_mod = custom_speech_verb
+ //limb stuff
+ character.regenerate_limbs() //possible optimisation: check for changes before regenerating?
+ for(var/modified_limb in modified_limbs)
+ var/modification = modified_limbs[modified_limb]
+ var/obj/item/bodypart/old_part = character.get_bodypart(modified_limb)
+ if(modification == LOADOUT_LIMB_PROSTHETIC)
+ var/obj/item/bodypart/new_limb
+ switch(modified_limb)
+ if(BODY_ZONE_L_ARM)
+ new_limb = new/obj/item/bodypart/l_arm/robot/surplus(character)
+ if(BODY_ZONE_R_ARM)
+ new_limb = new/obj/item/bodypart/r_arm/robot/surplus(character)
+ if(BODY_ZONE_L_LEG)
+ new_limb = new/obj/item/bodypart/l_leg/robot/surplus(character)
+ if(BODY_ZONE_R_LEG)
+ new_limb = new/obj/item/bodypart/r_leg/robot/surplus(character)
+ new_limb.replace_limb(character)
+ qdel(old_part)
+
+ if(length(modified_limbs))
+ character.regenerate_icons()
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
@@ -2552,6 +2601,18 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.update_body()
character.update_hair()
+/datum/preferences/proc/post_copy_to(mob/living/carbon/human/character)
+ //if no legs, and not a paraplegic or a slime, give them a free wheelchair
+ if(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !character.has_quirk(/datum/quirk/paraplegic) && !isjellyperson(character))
+ if(character.buckled)
+ character.buckled.unbuckle_mob(character)
+ var/turf/T = get_turf(character)
+ var/obj/structure/chair/spawn_chair = locate() in T
+ var/obj/vehicle/ridden/wheelchair/wheels = new(T)
+ if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
+ wheels.setDir(spawn_chair.dir)
+ wheels.buckle_mob(character)
+
/datum/preferences/proc/get_default_name(name_id)
switch(name_id)
if("human")
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index a8183e4940..ecf11f180b 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -514,6 +514,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["scars3"] >> scars_list["3"]
S["scars4"] >> scars_list["4"]
S["scars5"] >> scars_list["5"]
+ S["modified_limbs"] >> modified_limbs
//Custom names
@@ -870,6 +871,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["scars3"] , scars_list["3"])
WRITE_FILE(S["scars4"] , scars_list["4"])
WRITE_FILE(S["scars5"] , scars_list["5"])
+ WRITE_FILE(S["modified_limbs"] , modified_limbs)
//gear loadout
if(chosen_gear.len)
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 768c4c943e..7cbdd3afb6 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -414,6 +414,8 @@
give_magic(humanc)
if(GLOB.curse_of_madness_triggered)
give_madness(humanc, GLOB.curse_of_madness_triggered)
+ if(humanc.client)
+ humanc.client.prefs.post_copy_to(humanc)
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character