diff --git a/code/game/antagonist/antagonist_build.dm b/code/game/antagonist/antagonist_build.dm index f0f92c62b7..34631d36fb 100644 --- a/code/game/antagonist/antagonist_build.dm +++ b/code/game/antagonist/antagonist_build.dm @@ -28,7 +28,9 @@ // This could use work. if(flags & ANTAG_CLEAR_EQUIPMENT) for(var/obj/item/thing in player.contents) - del(thing) + player.drop_from_inventory(thing) + if(thing.loc != player) + del(thing) return 1 if(flags & ANTAG_SET_APPEARANCE) @@ -80,6 +82,7 @@ /datum/antagonist/proc/create_id(var/assignment, var/mob/living/carbon/human/player) var/obj/item/weapon/card/id/W = new id_type(player) + if(!W) return W.name = "[player.real_name]'s ID Card" W.access |= default_access W.assignment = "[assignment]" diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index 05fb6d1ec9..73c2c7fd78 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -44,8 +44,9 @@ var/datum/antagonist/deathsquad/deathsquad player.implant_loyalty(player) var/obj/item/weapon/card/id/id = create_id("Asset Protection", player) - id.access |= get_all_accesses() - id.icon_state = "centcom" + if(id) + id.access |= get_all_accesses() + id.icon_state = "centcom" create_radio(DTH_FREQ, player) /datum/antagonist/deathsquad/apply(var/datum/mind/player) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 9bfdf9f0b6..e1fda4965c 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -165,7 +165,7 @@ if((0 < beard) && (beard <= facial_hair_styles_list.len)) H.f_style = facial_hair_styles_list[beard] - H.update_body(0) + H.force_update_limbs() H.update_hair() return 1 diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 544776d144..8ad65194d1 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -98,8 +98,8 @@ var/global/datum/controller/gameticker/ticker src.mode = config.pick_mode(master_mode) if(!mode_started && !src.mode.can_start()) world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." - del(mode) current_state = GAME_STATE_PREGAME + mode = null job_master.ResetOccupations() return 0 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index ea56c749b8..829ee6e86d 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -151,7 +151,7 @@ var/list/slot_equipment_priority = list( \ remove_from_mob(W) if(!W) return 1 // self destroying objects (tk, grabs) - + W.forceMove(Target) update_icons() return 1 @@ -173,11 +173,11 @@ var/list/slot_equipment_priority = list( \ /* Removes the object from any slots the mob might have, calling the appropriate icon update proc. Does nothing else. - + DO NOT CALL THIS PROC DIRECTLY. It is meant to be called only by other inventory procs. It's probably okay to use it if you are transferring the item between slots on the same mob, but chances are you're safer calling remove_from_mob() or drop_from_inventory() anyways. - + As far as I can tell the proc exists so that mobs with different inventory slots can override the search through all the slots, without having to duplicate the rest of the item dropping. */ diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index d2aa61e635..05ceed7916 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -2,6 +2,9 @@ name = "brain" health = 400 //They need to live awhile longer than other organs. desc = "A piece of juicy meat found in a person's head." + organ_tag = "brain" + parent_organ = "head" + vital = 1 icon_state = "brain2" force = 1.0 w_class = 2.0 @@ -46,7 +49,7 @@ /obj/item/organ/brain/removed(var/mob/living/user) - ..() + name = "[owner.real_name]'s brain" var/mob/living/simple_animal/borer/borer = owner.has_brain_worms() @@ -57,6 +60,8 @@ if(istype(B) && istype(owner)) B.transfer_identity(owner) + ..() + /obj/item/organ/brain/replaced(var/mob/living/target) if(target.key) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 63eba6e781..da10a9ea00 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -31,10 +31,9 @@ var/d = rand(round(I.force / 4), I.force) if(istype(src, /mob/living/carbon/human)) var/mob/living/carbon/human/H = src - var/organ = H.get_organ("chest") - if (istype(organ, /obj/item/organ/external)) - var/obj/item/organ/external/temp = organ - if(temp.take_damage(d, 0)) + var/obj/item/organ/external/organ = H.get_organ("chest") + if (istype(organ)) + if(organ.take_damage(d, 0)) H.UpdateDamageIcon() H.updatehealth() else @@ -328,7 +327,7 @@ if(!item) return //Grab processing has a chance of returning null - + src.remove_from_mob(item) item.loc = src.loc diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 311942ca02..e2ef586f05 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -117,7 +117,7 @@ g_skin = green b_skin = blue - update_body() + force_update_limbs() return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) @@ -126,7 +126,7 @@ s_tone = tone - update_body() + force_update_limbs() return 1 /mob/living/carbon/human/proc/update_dna() @@ -186,3 +186,8 @@ /proc/q() var/mob/living/carbon/human/H = usr H.change_appearance(APPEARANCE_ALL) + +/mob/living/carbon/human/proc/force_update_limbs() + for(var/obj/item/organ/external/O in organs) + O.sync_colour_to_human(src) + update_body(0) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9c3057c52d..1e693fd63f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -20,6 +20,9 @@ else set_species() + if(species) + name = species.get_random_name(gender) + var/datum/reagents/R = new/datum/reagents(1000) reagents = R R.my_atom = src @@ -326,8 +329,8 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() - var/obj/item/organ/external/head/head = get_organ("head") - if( !head || head.disfigured || (head.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + var/obj/item/organ/external/head = get_organ("head") + if(!head || head.disfigured || (head.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible return "Unknown" return real_name @@ -1119,8 +1122,6 @@ species = all_species[new_species] - species.create_organs(src) - if(species.language) add_language(species.language) @@ -1137,6 +1138,8 @@ g_skin = 0 b_skin = 0 + species.create_organs(src) + species.handle_post_spawn(src) maxHealth = species.total_health @@ -1361,3 +1364,8 @@ U << "You pop [S]'s [current_limb.joint] back in!" S << "[U] pops your [current_limb.joint] back in!" current_limb.undislocate() + +/mob/living/carbon/human/drop_from_inventory(var/obj/item/W, var/atom/Target = null) + if(W in organs) + return + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index 853fb4e8d4..c037d81fb7 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -45,7 +45,7 @@ "heart" = /obj/item/organ/heart, "lungs" = /obj/item/organ/lungs, "liver" = /obj/item/organ/liver, - "kidneys" = /obj/item/organ/kidney, + "kidneys" = /obj/item/organ/kidneys, "brain" = /obj/item/organ/brain, "eyes" = /obj/item/organ/eyes, "stack" = /obj/item/organ/stack/vox diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 09f3360d45..b97e8ceed6 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -110,7 +110,7 @@ "heart" = /obj/item/organ/heart, "lungs" = /obj/item/organ/lungs, "liver" = /obj/item/organ/liver, - "kidneys" = /obj/item/organ/kidney, + "kidneys" = /obj/item/organ/kidneys, "brain" = /obj/item/organ/brain, "appendix" = /obj/item/organ/appendix, "eyes" = /obj/item/organ/eyes diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 00802c5da9..0bf4978297 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -967,6 +967,11 @@ default behaviour is: /mob/living/proc/slip(var/slipped_on,stun_duration=8) return 0 +/mob/living/carbon/drop_from_inventory(var/obj/item/W, var/atom/Target = null) + if(W in internal_organs) + return + ..() + /mob/living/carbon/proc/spin(spintime, speed) spawn() var/D = dir diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e4405c5767..482ec2e3a1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -729,7 +729,7 @@ note dizziness decrements automatically in the mob's Life() proc. stat(null,"Location:\t([x], [y], [z])") stat(null,"CPU:\t[world.cpu]") stat(null,"Instances:\t[world.contents.len]") - if(statpanel("Status") && processScheduler.getIsRunning()) + if(statpanel("Status") && processScheduler && processScheduler.getIsRunning()) var/datum/controller/process/process process = processScheduler.getProcess("ticker") diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 90e201b382..1d67b712f5 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -473,6 +473,7 @@ //new_character.dna.UpdateSE() // Do the initial caching of the player's body icons. + new_character.force_update_limbs() new_character.regenerate_icons() new_character.key = key //Manually transfer the key to log them in diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 5d307fffcf..f97df89080 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -235,12 +235,14 @@ var/list/organ_cache = list() owner.internal_organs_by_name[organ_tag] = null owner.internal_organs_by_name -= organ_tag + owner.internal_organs_by_name -= null owner.internal_organs -= src var/obj/item/organ/external/affected = owner.get_organ(parent_organ) if(affected) affected.internal_organs -= src loc = owner.loc + processing_objects |= src rejecting = null var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list if(!organ_blood || !organ_blood.data["blood_DNA"]) @@ -269,6 +271,7 @@ var/list/organ_cache = list() transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"] owner = target + processing_objects -= src target.internal_organs |= src affected.internal_organs |= src target.internal_organs_by_name[organ_tag] = src diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index b6f14b64bc..d8ba25d750 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -3,13 +3,16 @@ ****************************************************/ /obj/item/organ/external name = "external" + min_broken_damage = 30 + max_damage = 0 + dir = SOUTH + organ_tag = "limb" + var/icon_name = null var/body_part = null var/icon_position = 0 - var/model var/force_icon - var/damage_state = "00" var/brute_dam = 0 var/burn_dam = 0 @@ -18,7 +21,7 @@ var/icon/mob_icon var/gendered_icon = 0 var/limb_name - var/disfigured = 1 + var/disfigured = 0 var/cannot_amputate var/cannot_break var/s_tone @@ -26,38 +29,25 @@ var/list/wounds = list() var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len! var/perma_injury = 0 - var/obj/item/organ/external/parent var/list/obj/item/organ/external/children - - // Internal organs of this body part - var/list/internal_organs = list() - + var/list/internal_organs = list() // Internal organs of this body part var/damage_msg = "\red You feel an intense pain" var/broken_description - var/open = 0 var/stage = 0 var/cavity = 0 var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails. var/encased // Needs to be opened with a saw to access the organs. - var/obj/item/hidden = null var/list/implants = list() - - // how often wounds should be updated, a higher number means less often - var/wound_update_accuracy = 1 - + var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often var/joint = "joint" // Descriptive string used in dislocation. var/amputation_point // Descriptive string used in amputation. var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ. var/can_grasp var/can_stand - min_broken_damage = 30 - max_damage = 0 - dir = SOUTH - /obj/item/organ/external/attackby(obj/item/weapon/W as obj, mob/user as mob) switch(stage) if(0) @@ -650,8 +640,8 @@ Note that amputating the affected organ does in fact remove the infection from t wounds.Cut() if(parent) var/datum/wound/W - if(max_damage < 50) - W = new/datum/wound/lost_limb/small(max_damage) + if(clean || max_damage < 50) + W = new/datum/wound/lost_limb/small(max_damage/2) else W = new/datum/wound/lost_limb(max_damage) parent.children -= src @@ -940,6 +930,7 @@ Note that amputating the affected organ does in fact remove the infection from t gendered_icon = 1 cannot_amputate = 1 parent_organ = null + encased = "ribcage" /obj/item/organ/external/groin name = "lower body" @@ -1061,9 +1052,11 @@ Note that amputating the affected organ does in fact remove the infection from t joint = "jaw" amputation_point = "neck" gendered_icon = 1 + encased = "skull" /obj/item/organ/external/head/removed() if(owner) + name = "[owner.real_name]'s head" owner.u_equip(owner.glasses) owner.u_equip(owner.head) owner.u_equip(owner.l_ear) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index d5b6bf2a4e..b0e23df3d2 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -16,7 +16,9 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) s_tone = null s_col = null - if(human.s_tone && (human.species.flags & HAS_SKIN_TONE)) + if(status & ORGAN_ROBOT) + return + if(!isnull(human.s_tone) && (human.species.flags & HAS_SKIN_TONE)) s_tone = human.s_tone if(human.species.flags & HAS_SKIN_COLOR) s_col = list(human.r_skin, human.g_skin, human.b_skin) diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index c552631abf..46e22e1e5f 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -44,7 +44,7 @@ organ_tag = "kidneys" parent_organ = "groin" -/obj/item/organ/kidney/process() +/obj/item/organ/kidneys/process() ..() @@ -61,7 +61,6 @@ else if(is_broken()) owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) - /obj/item/organ/eyes name = "eyeballs" icon_state = "eyes" @@ -113,7 +112,7 @@ name = "liver" icon_state = "liver" organ_tag = "liver" - parent_organ = "chest" + parent_organ = "groin" /obj/item/organ/liver/process() @@ -175,6 +174,7 @@ name = "appendix" icon_state = "appendix" parent_organ = "groin" + organ_tag = "appendix" /obj/item/organ/appendix/removed() diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm index 388b53a256..4e49a785e7 100644 --- a/code/modules/projectiles/targeting.dm +++ b/code/modules/projectiles/targeting.dm @@ -23,7 +23,7 @@ //Removing the lock and the buttons. /obj/item/weapon/gun/dropped(mob/user as mob) stop_aim() - if (user.client) + if(user && user.client) user.client.remove_gun_icons() return ..() @@ -47,7 +47,7 @@ /obj/item/weapon/gun/proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params) //Lets not spam it. if(lock_time > world.time - 2) return - + user.set_dir(get_cardinal_dir(src, A)) if(isliving(A) && !(A in aim_targets)) Aim(A) //Clicked a mob, aim at them @@ -58,7 +58,7 @@ if(isliving(M) && (M in view(user)) && !(M in aim_targets)) Aim(M) //Aha! Aim at them! return 1 - + return 0 //Aiming at the target mob. @@ -83,12 +83,12 @@ if(src != M.get_active_hand()) stop_aim() return - + //reflex firing is disabled when help intent is set if (M.a_intent == I_HELP) M << "\red You refrain from firing your [src] as your intent is set to help." return - + M.last_move_intent = world.time var/firing_check = can_hit(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing. if(firing_check > 0) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index bb0a6314c8..8f5d7155dd 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -343,9 +343,11 @@ var/o_a = (O.gender == PLURAL) ? "" : "a " var/o_do = (O.gender == PLURAL) ? "don't" : "doesn't" - if(target.species.has_organ[O.organ_tag]) + if(O.organ_tag == "limb") + return 0 + else if(target.species.has_organ[O.organ_tag]) - if(!O.health) + if(O.is_damaged()) user << "\red \The [O.organ_tag] [o_is] in no state to be transplanted." return 2 @@ -355,7 +357,7 @@ user << "\red \The [target] already has [o_a][O.organ_tag]." return 2 - if(O && affected.name == O.parent_organ) + if(O && affected.limb_name == O.parent_organ) organ_compatible = 1 else user << "\red \The [O.organ_tag] [o_do] normally go in \the [affected.name]." diff --git a/code/modules/surgery/robolimbs.dm b/code/modules/surgery/robolimbs.dm index 5b524288f9..e845d8bb7b 100644 --- a/code/modules/surgery/robolimbs.dm +++ b/code/modules/surgery/robolimbs.dm @@ -39,8 +39,11 @@ if(L.part) for(var/part_name in L.part) - if(!isnull(target.get_organ(part_name))) continue + if(!isnull(target.get_organ(part_name))) + continue var/list/organ_data = target.species.has_limbs["[target_zone]"] + if(!organ_data) + continue var/new_limb_type = organ_data["path"] var/obj/item/organ/external/new_limb = new new_limb_type(target) new_limb.robotize(L.model_info)