diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 16ba61919d5..e688e19691d 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -5810,7 +5810,7 @@ pixel_x = -5; pixel_y = -2 }, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, diff --git a/_maps/map_files/BirdStation/BirdStation.dmm b/_maps/map_files/BirdStation/BirdStation.dmm index 35ae80339e6..8fa869b173d 100644 --- a/_maps/map_files/BirdStation/BirdStation.dmm +++ b/_maps/map_files/BirdStation/BirdStation.dmm @@ -446,8 +446,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "abh" = ( diff --git a/_maps/map_files/DreamStation/dreamstation04.dmm b/_maps/map_files/DreamStation/dreamstation04.dmm index d3573c3e30b..18420d099e9 100644 --- a/_maps/map_files/DreamStation/dreamstation04.dmm +++ b/_maps/map_files/DreamStation/dreamstation04.dmm @@ -1344,8 +1344,8 @@ /area/turret_protected/aisat_interior) "acv" = ( /obj/structure/table, -/obj/item/robot_parts/robot_suit, -/obj/item/robot_parts/head, +/obj/item/robot_suit, +/obj/item/bodypart/head/robot, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/bluegrid, /area/turret_protected/aisat_interior) @@ -1418,9 +1418,9 @@ /area/turret_protected/aisat_interior) "acF" = ( /obj/structure/table, -/obj/item/robot_parts/l_arm, -/obj/item/robot_parts/chest, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, +/obj/item/bodypart/chest/robot, +/obj/item/bodypart/l_arm/robot, /obj/structure/cable/blue{ tag = "icon-2-8"; icon_state = "2-8" @@ -1443,7 +1443,7 @@ /area/turret_protected/aisat_interior) "acI" = ( /obj/structure/table, -/obj/item/robot_parts/r_arm, +/obj/item/bodypart/r_arm/robot, /obj/structure/cable/blue{ tag = "icon-2-4"; icon_state = "2-4" @@ -1511,7 +1511,7 @@ }, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/item/device/assembly/flash/handheld, -/obj/item/robot_parts/r_leg, +/obj/item/bodypart/r_leg/robot, /turf/open/floor/plasteel/black, /area/turret_protected/aisat_interior) "acP" = ( @@ -1575,7 +1575,7 @@ /area/turret_protected/aisat_interior) "acU" = ( /obj/structure/table, -/obj/item/robot_parts/l_leg, +/obj/item/bodypart/l_leg/robot, /obj/structure/cable/blue{ tag = "icon-4-8"; icon_state = "4-8" @@ -3189,8 +3189,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "agA" = ( @@ -16264,7 +16264,7 @@ /area/maintenance/fore) "aIo" = ( /obj/structure/rack, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, /obj/item/stack/sheet/metal{ amount = 2 }, @@ -17026,7 +17026,7 @@ "aJN" = ( /obj/structure/table, /obj/item/stack/cable_coil/green, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, /obj/item/weapon/storage/fancy/cigarettes/cigpack_robustgold, /obj/item/weapon/reagent_containers/food/drinks/mug/coco, /turf/open/floor/plating, @@ -18024,7 +18024,7 @@ /area/maintenance/port) "aMb" = ( /obj/effect/spawner/lootdrop/maintenance, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/plating, /area/maintenance/port) "aMc" = ( @@ -63145,7 +63145,7 @@ /turf/open/floor/plating, /area/maintenance/apmaint) "cvz" = ( -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/l_arm/robot, /obj/structure/closet, /obj/item/weapon/reagent_containers/glass/beaker/large, /obj/effect/spawner/lootdrop/maintenance, diff --git a/_maps/map_files/EfficiencyStation/EfficiencyStation.dmm b/_maps/map_files/EfficiencyStation/EfficiencyStation.dmm index 45e4e748284..f7e7e86f172 100644 --- a/_maps/map_files/EfficiencyStation/EfficiencyStation.dmm +++ b/_maps/map_files/EfficiencyStation/EfficiencyStation.dmm @@ -3505,8 +3505,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "agJ" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 1713fbaec40..ad6d1b744c1 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -55774,12 +55774,12 @@ d2 = 2; icon_state = "1-2" }, -/obj/item/robot_parts/chest{ +/obj/item/bodypart/chest/robot{ name = "cyborg torso"; pixel_x = -2; pixel_y = 2 }, -/obj/item/robot_parts/head{ +/obj/item/bodypart/head/robot{ name = "cyborg head"; pixel_x = 3; pixel_y = 2 @@ -90220,8 +90220,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "cYu" = ( diff --git a/_maps/map_files/MiniStation/MiniStation.dmm b/_maps/map_files/MiniStation/MiniStation.dmm index 0db7e381bd7..4ce944db059 100644 --- a/_maps/map_files/MiniStation/MiniStation.dmm +++ b/_maps/map_files/MiniStation/MiniStation.dmm @@ -14145,8 +14145,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "Gv" = ( diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm index d6a019fa8e2..cc62442653f 100644 --- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm +++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm @@ -54091,8 +54091,8 @@ dir = 1 }, /obj/structure/table, -/obj/item/robot_parts/r_arm, -/obj/item/robot_parts/l_arm, +/obj/item/bodypart/r_arm/robot, +/obj/item/bodypart/l_arm/robot, /turf/open/floor/mineral/titanium, /area/shuttle/syndicate) "coo" = ( diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm index f5efa04ea62..93b422cdaa8 100644 --- a/code/__DEFINES/clothing.dm +++ b/code/__DEFINES/clothing.dm @@ -17,25 +17,25 @@ #define slot_back 1 #define slot_wear_mask 2 #define slot_handcuffed 3 -#define slot_l_hand 4 -#define slot_r_hand 5 -#define slot_belt 6 -#define slot_wear_id 7 -#define slot_ears 8 -#define slot_glasses 9 -#define slot_gloves 10 -#define slot_head 11 -#define slot_shoes 12 -#define slot_wear_suit 13 -#define slot_w_uniform 14 -#define slot_l_store 15 -#define slot_r_store 16 -#define slot_s_store 17 -#define slot_in_backpack 18 -#define slot_legcuffed 19 -#define slot_generic_dextrous_storage 20 +#define slot_hands 4 //wherever you provide a slot for hands you provide slot_hands + //slot_hands as a slot will pick ANY available hand +#define slot_belt 5 +#define slot_wear_id 6 +#define slot_ears 7 +#define slot_glasses 8 +#define slot_gloves 9 +#define slot_head 10 +#define slot_shoes 11 +#define slot_wear_suit 12 +#define slot_w_uniform 13 +#define slot_l_store 14 +#define slot_r_store 15 +#define slot_s_store 16 +#define slot_in_backpack 17 +#define slot_legcuffed 18 +#define slot_generic_dextrous_storage 19 -#define slots_amt 20 // Keep this up to date! +#define slots_amt 19 // Keep this up to date! //I hate that this has to exist /proc/slotdefine2slotbit(slotdefine) //Keep this up to date with the value of SLOT BITMASKS and SLOTS (the two define sections above) diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index a9c91450c62..de99eca0917 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -84,6 +84,14 @@ #define ORGAN_ORGANIC 1 #define ORGAN_ROBOTIC 2 +#define BODYPART_ORGANIC 1 +#define BODYPART_ROBOTIC 2 + +#define MONKEY_BODYPART "monkey" +#define ALIEN_BODYPART "alien" +#define LARVA_BODYPART "larva" +#define DEVIL_BODYPART "devil" + //Nutrition levels for humans. No idea where else to put it #define NUTRITION_LEVEL_FAT 600 #define NUTRITION_LEVEL_FULL 550 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 1e66100e551..fa2ad08b30b 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -22,7 +22,7 @@ #define ismonkey(A) (istype(A, /mob/living/carbon/monkey)) -#define isbrain(A) (istype(A, /mob/living/carbon/brain)) +#define isbrain(A) (istype(A, /mob/living/brain)) #define isalien(A) (istype(A, /mob/living/carbon/alien)) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index f8804aead4c..906a3b3498d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -30,33 +30,32 @@ #define FRIDAY_13TH "Friday the 13th" //Human Overlays Indexes///////// -#define MUTATIONS_LAYER 26 //mutations. Tk headglows, cold resistance glow, etc -#define BODY_BEHIND_LAYER 25 //certain mutantrace features (tail when looking south) that must appear behind the body parts -#define BODYPARTS_LAYER 24 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag -#define BODY_ADJ_LAYER 23 //certain mutantrace features (snout, body markings) that must appear above the body parts -#define BODY_LAYER 22 //underwear, undershirts, socks, eyes, lips(makeup) -#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) -#define DAMAGE_LAYER 20 //damage indicators (cuts and burns) -#define UNIFORM_LAYER 19 -#define ID_LAYER 18 -#define SHOES_LAYER 17 -#define GLOVES_LAYER 16 -#define EARS_LAYER 15 -#define SUIT_LAYER 14 -#define GLASSES_LAYER 13 -#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 11 -#define BACK_LAYER 10 -#define HAIR_LAYER 9 //TODO: make part of head layer? -#define FACEMASK_LAYER 8 -#define HEAD_LAYER 7 -#define HANDCUFF_LAYER 6 -#define LEGCUFF_LAYER 5 -#define L_HAND_LAYER 4 -#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands +#define MUTATIONS_LAYER 25 //mutations. Tk headglows, cold resistance glow, etc +#define BODY_BEHIND_LAYER 24 //certain mutantrace features (tail when looking south) that must appear behind the body parts +#define BODYPARTS_LAYER 23 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag +#define BODY_ADJ_LAYER 22 //certain mutantrace features (snout, body markings) that must appear above the body parts +#define BODY_LAYER 21 //underwear, undershirts, socks, eyes, lips(makeup) +#define FRONT_MUTATIONS_LAYER 20 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) +#define DAMAGE_LAYER 19 //damage indicators (cuts and burns) +#define UNIFORM_LAYER 18 +#define ID_LAYER 17 +#define SHOES_LAYER 16 +#define GLOVES_LAYER 15 +#define EARS_LAYER 14 +#define SUIT_LAYER 13 +#define GLASSES_LAYER 12 +#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 10 +#define BACK_LAYER 9 +#define HAIR_LAYER 8 //TODO: make part of head layer? +#define FACEMASK_LAYER 7 +#define HEAD_LAYER 6 +#define HANDCUFF_LAYER 5 +#define LEGCUFF_LAYER 4 +#define HANDS_LAYER 3 #define BODY_FRONT_LAYER 2 #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 25 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; //Human Overlay Index Shortcuts for alternate_worn_layer, layers //Because I *KNOW* somebody will think layer+1 means "above" @@ -82,8 +81,7 @@ #define UNDER_HEAD_LAYER HEAD_LAYER+1 #define UNDER_HANDCUFF_LAYER HANDCUFF_LAYER+1 #define UNDER_LEGCUFF_LAYER LEGCUFF_LAYER+1 -#define UNDER_L_HAND_LAYER L_HAND_LAYER+1 -#define UNDER_R_HAND_LAYER R_HAND_LAYER+1 +#define UNDER_HANDS_LAYER HANDS_LAYER+1 #define UNDER_BODY_FRONT_LAYER BODY_FRONT_LAYER+1 #define UNDER_FIRE_LAYER FIRE_LAYER+1 @@ -109,8 +107,7 @@ #define ABOVE_HEAD_LAYER HEAD_LAYER-1 #define ABOVE_HANDCUFF_LAYER HANDCUFF_LAYER-1 #define ABOVE_LEGCUFF_LAYER LEGCUFF_LAYER-1 -#define ABOVE_L_HAND_LAYER L_HAND_LAYER-1 -#define ABOVE_R_HAND_LAYER R_HAND_LAYER-1 +#define ABOVE_HANDS_LAYER HANDS_LAYER-1 #define ABOVE_BODY_FRONT_LAYER BODY_FRONT_LAYER-1 #define ABOVE_FIRE_LAYER FIRE_LAYER-1 @@ -530,4 +527,4 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define MAX_NTNET_LOGS 300 #define MIN_NTNET_LOGS 10 //TODO Move to a pref -#define STATION_GOAL_BUDGET 1 \ No newline at end of file +#define STATION_GOAL_BUDGET 1 diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 54cdc9bb8ca..1cad2a5e5e4 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -41,4 +41,7 @@ var/cmp_field = "name" return a.priority - b.priority /proc/cmp_clientcolour_priority(datum/client_colour/A, datum/client_colour/B) - return B.priority - A.priority \ No newline at end of file + return B.priority - A.priority + +/proc/cmp_clockscripture_priority(datum/clockwork_scripture/A, datum/clockwork_scripture/B) + return initial(A.sort_priority) - initial(B.sort_priority) \ No newline at end of file diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 8de02bd774c..0fcbb30ef6e 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -191,7 +191,7 @@ Proc for attack log creation, because really why not var/target_loc = target.loc - var/holding = user.get_active_hand() + var/holding = user.get_active_held_item() var/datum/progressbar/progbar if (progress) progbar = new(user, time, target) @@ -213,7 +213,7 @@ Proc for attack log creation, because really why not drifting = 0 user_loc = user.loc - if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying ) + if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying ) . = 0 break if (progress) @@ -233,7 +233,7 @@ Proc for attack log creation, because really why not if(!user.Process_Spacemove(0) && user.inertia_dir) drifting = 1 - var/holding = user.get_active_hand() + var/holding = user.get_active_held_item() var/holdingnull = 1 //User's hand started out empty, check for an empty hand if(holding) @@ -270,7 +270,7 @@ Proc for attack log creation, because really why not if(!holding) . = 0 break - if(user.get_active_hand() != holding) + if(user.get_active_held_item() != holding) . = 0 break if (progress) @@ -291,7 +291,7 @@ Proc for attack log creation, because really why not for(var/atom/target in targets) originalloc[target] = target.loc - var/holding = user.get_active_hand() + var/holding = user.get_active_held_item() var/datum/progressbar/progbar if(progress) progbar = new(user, time, targets[1]) @@ -315,7 +315,7 @@ Proc for attack log creation, because really why not user_loc = user.loc for(var/atom/target in targets) - if((!drifting && user_loc != user.loc) || originalloc[target] != target.loc || user.get_active_hand() != holding || user.incapacitated() || user.lying ) + if((!drifting && user_loc != user.loc) || originalloc[target] != target.loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying ) . = 0 break mainloop if(progbar) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 39892a67e3a..a8f3703f2f7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -337,7 +337,7 @@ Turf and target are seperate in case you want to teleport some distance from a t moblist.Add(M) for(var/mob/living/carbon/human/M in sortmob) moblist.Add(M) - for(var/mob/living/carbon/brain/M in sortmob) + for(var/mob/living/brain/M in sortmob) moblist.Add(M) for(var/mob/living/carbon/alien/M in sortmob) moblist.Add(M) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index e18125ab284..21155f2d2dd 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -41,4 +41,5 @@ var/MAX_EX_HEAVY_RANGE = 7 var/MAX_EX_LIGHT_RANGE = 14 var/MAX_EX_FLASH_RANGE = 14 var/MAX_EX_FLAME_RANGE = 14 +var/DYN_EX_SCALE = 0.5 diff --git a/code/_onclick/autoclick.dm b/code/_onclick/autoclick.dm index 3fe84195b6c..1ceeb182ed7 100644 --- a/code/_onclick/autoclick.dm +++ b/code/_onclick/autoclick.dm @@ -23,7 +23,7 @@ /mob/living/carbon/CanMobAutoclick(atom/object, location, params) if(!object.IsAutoclickable()) return - var/obj/item/h = get_active_hand() + var/obj/item/h = get_active_held_item() if(h) . = h.CanItemAutoclick(object, location, params) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index b029eb69863..dc21aa4185a 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -98,16 +98,12 @@ throw_item(A) return - var/obj/item/W = get_active_hand() + var/obj/item/W = get_active_held_item() if(W == A) W.attack_self(src) - if(hand) - update_inv_l_hand(0) - else - update_inv_r_hand(0) - return + update_inv_hands() // operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper) if(A.ClickAccessible(src, depth=INVENTORY_DEPTH)) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index a3d084afe17..b0c110cddc5 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -51,7 +51,7 @@ aicamera.captureimage(A, usr) return - var/obj/item/W = get_active_hand() + var/obj/item/W = get_active_held_item() // Cyborgs have no range-checking unless there is item use if(!W) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 0480bd43814..ad0ea23e9da 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -33,11 +33,21 @@ #define ui_id "CENTER-4:12,SOUTH:5" #define ui_belt "CENTER-3:14,SOUTH:5" #define ui_back "CENTER-2:14,SOUTH:5" -#define ui_rhand "CENTER:-16,SOUTH:5" -#define ui_lhand "CENTER: 16,SOUTH:5" -#define ui_equip "CENTER:-16,SOUTH+1:5" -#define ui_swaphand1 "CENTER:-16,SOUTH+1:5" -#define ui_swaphand2 "CENTER: 16,SOUTH+1:5" + +/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) + var/x_off = -(!(i % 2)) + var/y_off = round((i-1) / 2) + return"CENTER+[x_off]:16,SOUTH+[y_off]:5" + +/proc/ui_equip_position(mob/M) + var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5) + return "CENTER:-16,SOUTH+[y_off+1]:5" + +/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5) + var/x_off = which == 1 ? -1 : 0 + var/y_off = round((M.held_items.len-1) / 2) + return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" + #define ui_storage1 "CENTER+1:18,SOUTH:5" #define ui_storage2 "CENTER+2:20,SOUTH:5" @@ -141,3 +151,4 @@ #define ui_deityhealth "EAST-1:28,CENTER-2:13" #define ui_deitypower "EAST-1:28,CENTER-1:15" #define ui_deityfollowers "EAST-1:28,CENTER:17" + diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index 8ea573ad34a..2cd637f9653 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -39,39 +39,24 @@ ..() var/obj/screen/using - var/obj/screen/inventory/inv_box //equippable shit //hands - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "right hand" - inv_box.icon = 'icons/mob/screen_alien.dmi' - inv_box.icon_state = "hand_r" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - static_inventory += inv_box - - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "left hand" - inv_box.icon = 'icons/mob/screen_alien.dmi' - inv_box.icon_state = "hand_l" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - static_inventory += inv_box + build_hand_slots('icons/mob/screen_alien.dmi') //begin buttons using = new /obj/screen/swap_hand() using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "swap_1" - using.screen_loc = ui_swaphand1 + using.screen_loc = ui_swaphand_position(owner,1) static_inventory += using using = new /obj/screen/swap_hand() using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "swap_2" - using.screen_loc = ui_swaphand2 + using.screen_loc = ui_swaphand_position(owner,2) static_inventory += using using = new /obj/screen/act_intent/alien() @@ -136,17 +121,13 @@ return var/mob/living/carbon/alien/humanoid/H = mymob if(hud_version != HUD_STYLE_NOHUD) - if(H.r_hand) - H.r_hand.screen_loc = ui_rhand - H.client.screen += H.r_hand - if(H.l_hand) - H.l_hand.screen_loc = ui_lhand - H.client.screen += H.l_hand + for(var/obj/item/I in H.held_items) + I.screen_loc = ui_hand_position(H.get_held_index_of_item(I)) + H.client.screen += I else - if(H.r_hand) - H.r_hand.screen_loc = null - if(H.l_hand) - H.l_hand.screen_loc = null + for(var/obj/item/I in H.held_items) + I.screen_loc = null + H.client.screen -= I /mob/living/carbon/alien/humanoid/create_mob_hud() if(client && !hud_used) diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index 566132808b4..a375374ba22 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -159,11 +159,11 @@ static_inventory += using using = new /obj/screen/blob/NodeBlob() - using.screen_loc = ui_rhand + using.screen_loc = ui_hand_position(2) static_inventory += using using = new /obj/screen/blob/FactoryBlob() - using.screen_loc = ui_lhand + using.screen_loc = ui_hand_position(1) static_inventory += using using = new /obj/screen/blob/ReadaptChemical() diff --git a/code/_onclick/hud/devil.dm b/code/_onclick/hud/devil.dm index 0ddaeccd238..ec2597b1975 100644 --- a/code/_onclick/hud/devil.dm +++ b/code/_onclick/hud/devil.dm @@ -5,7 +5,6 @@ /datum/hud/devil/New(mob/owner, ui_style = 'icons/mob/screen_midnight.dmi') ..() var/obj/screen/using - var/obj/screen/inventory/inv_box using = new /obj/screen/drop() using.icon = ui_style @@ -18,27 +17,13 @@ pull_icon.screen_loc = ui_drone_pull static_inventory += pull_icon - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "right hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_r" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - static_inventory += inv_box - - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "left hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_l" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - static_inventory += inv_box + build_hand_slots(ui_style) using = new /obj/screen/inventory() using.name = "hand" using.icon = ui_style using.icon_state = "swap_1_m" - using.screen_loc = ui_swaphand1 + using.screen_loc = ui_swaphand_position(owner,1) using.layer = HUD_LAYER static_inventory += using @@ -46,7 +31,7 @@ using.name = "hand" using.icon = ui_style using.icon_state = "swap_2" - using.screen_loc = ui_swaphand2 + using.screen_loc = ui_swaphand_position(owner,2) using.layer = HUD_LAYER static_inventory += using @@ -65,17 +50,13 @@ var/mob/living/carbon/true_devil/D = mymob if(hud_version != HUD_STYLE_NOHUD) - if(D.r_hand) - D.r_hand.screen_loc = ui_rhand - D.client.screen += D.r_hand - if(D.l_hand) - D.l_hand.screen_loc = ui_lhand - D.client.screen += D.l_hand + for(var/obj/item/I in D.held_items) + I.screen_loc = ui_hand_position(D.get_held_index_of_item(I)) + D.client.screen += I else - if(D.r_hand) - D.r_hand.screen_loc = null - if(D.l_hand) - D.l_hand.screen_loc = null + for(var/obj/item/I in D.held_items) + I.screen_loc = null + D.client.screen -= I /mob/living/carbon/true_devil/create_mob_hud() if(client && !hud_used) diff --git a/code/_onclick/hud/generic_dextrous.dm b/code/_onclick/hud/generic_dextrous.dm index 8ecfed99627..bb0bac5d4ce 100644 --- a/code/_onclick/hud/generic_dextrous.dm +++ b/code/_onclick/hud/generic_dextrous.dm @@ -2,7 +2,6 @@ /datum/hud/dextrous/New(mob/living/owner, ui_style = 'icons/mob/screen_midnight.dmi') ..() var/obj/screen/using - var/obj/screen/inventory/inv_box using = new /obj/screen/drop() using.icon = ui_style @@ -15,32 +14,18 @@ pull_icon.screen_loc = ui_drone_pull static_inventory += pull_icon - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "right hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_r" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - static_inventory += inv_box - - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "left hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_l" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - static_inventory += inv_box + build_hand_slots(ui_style) using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_1_m" - using.screen_loc = ui_swaphand1 + using.screen_loc = ui_swaphand_position(owner,1) static_inventory += using using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_2" - using.screen_loc = ui_swaphand2 + using.screen_loc = ui_swaphand_position(owner,2) static_inventory += using zone_select = new /obj/screen/zone_sel() @@ -68,14 +53,19 @@ return var/mob/living/D = mymob if(hud_version != HUD_STYLE_NOHUD) - if(D.r_hand) - D.r_hand.screen_loc = ui_rhand - D.client.screen += D.r_hand - if(D.l_hand) - D.l_hand.screen_loc = ui_lhand - D.client.screen += D.l_hand + for(var/obj/item/I in D.held_items) + I.screen_loc = ui_hand_position(D.get_held_index_of_item(I)) + D.client.screen += I else - if(D.r_hand) - D.r_hand.screen_loc = null - if(D.l_hand) - D.l_hand.screen_loc = null + for(var/obj/item/I in D.held_items) + I.screen_loc = null + D.client.screen -= I + + +//Dextrous simple mobs can use hands! +/mob/living/simple_animal/create_mob_hud() + if(client && !hud_used) + if(dextrous) + hud_used = new dextrous_hud_type(src, ui_style2icon(client.prefs.UI_style)) + else + ..() diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm index d8b92fba713..aa50ca3712e 100644 --- a/code/_onclick/hud/guardian.dm +++ b/code/_onclick/hud/guardian.dm @@ -7,11 +7,11 @@ infodisplay += healths using = new /obj/screen/guardian/Manifest() - using.screen_loc = ui_rhand + using.screen_loc = ui_hand_position(2) static_inventory += using using = new /obj/screen/guardian/Recall() - using.screen_loc = ui_lhand + using.screen_loc = ui_hand_position(1) static_inventory += using using = new owner.toggle_button_type() diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index d55eb8db92f..623b49723ae 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -39,6 +39,7 @@ var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...) var/list/screenoverlays = list() //the screen objects used as whole screen overlays (flash, damageoverlay, etc...) var/list/inv_slots[slots_amt] // /obj/screen/inventory objects, ordered by their slot ID. + var/list/hand_slots // /obj/screen/inventory/hand objects, assoc list of "[held_index]" = object var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle var/action_buttons_hidden = 0 @@ -51,6 +52,7 @@ mymob = owner hide_actions_toggle = new hide_actions_toggle.InitialiseIcon(mymob) + hand_slots = list() /datum/hud/Destroy() if(mymob.hud_used == src) @@ -159,10 +161,10 @@ screenmob.client.screen += infodisplay //These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay - if(inv_slots[slot_l_hand]) - screenmob.client.screen += inv_slots[slot_l_hand] //we want the hands to be visible - if(inv_slots[slot_r_hand]) - screenmob.client.screen += inv_slots[slot_r_hand] //we want the hands to be visible + for(var/h in hand_slots) + var/obj/screen/hand = hand_slots[h] + if(hand) + screenmob.client.screen += hand if(action_intent) screenmob.client.screen += action_intent //we want the intent switcher visible action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is. @@ -210,3 +212,34 @@ else usr << "This mob type does not use a HUD." + +//(re)builds the hand ui slots, throwing away old ones +//not really worth jugglying existing ones so we just scrap+rebuild +//9/10 this is only called once per mob and only for 2 hands +/datum/hud/proc/build_hand_slots(ui_style = 'icons/mob/screen_midnight.dmi') + for(var/h in hand_slots) + var/obj/screen/inventory/hand/H = hand_slots[h] + if(H) + static_inventory -= H + hand_slots = list() + var/obj/screen/inventory/hand/hand_box + for(var/i in 1 to mymob.held_items.len) + hand_box = new /obj/screen/inventory/hand() + hand_box.name = mymob.get_held_index_name(i) + hand_box.icon = ui_style + hand_box.icon_state = "hand_[mymob.held_index_to_dir(i)]" + hand_box.screen_loc = ui_hand_position(i) + hand_box.held_index = i + hand_slots["[i]"] = hand_box + hand_box.hud = src + static_inventory += hand_box + hand_box.update_icon() + + var/i = 1 + for(var/obj/screen/swap_hand/SH in static_inventory) + SH.screen_loc = ui_swaphand_position(mymob,!(i % 2) ? 2: 1) + i++ + for(var/obj/screen/human/equip/E in static_inventory) + E.screen_loc = ui_equip_position(mymob) + if(mymob.hud_used) + show_hud(HUD_STYLE_STANDARD,mymob) \ No newline at end of file diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 33cac0a4d28..93f36820fd8 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -133,32 +133,18 @@ inv_box.screen_loc = ui_oclothing toggleable_inventory += inv_box - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "right hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_r" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - static_inventory += inv_box - - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "left hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_l" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - static_inventory += inv_box + build_hand_slots(ui_style) using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_1" - using.screen_loc = ui_swaphand1 + using.screen_loc = ui_swaphand_position(owner,1) static_inventory += using using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_2" - using.screen_loc = ui_swaphand2 + using.screen_loc = ui_swaphand_position(owner,2) static_inventory += using inv_box = new /obj/screen/inventory() @@ -227,7 +213,7 @@ using = new /obj/screen/human/equip() using.icon = ui_style - using.screen_loc = ui_equip + using.screen_loc = ui_equip_position(mymob) static_inventory += using inv_box = new /obj/screen/inventory() @@ -372,7 +358,6 @@ var/mob/living/carbon/human/H = mymob var/mob/screenmob = viewer || H - if(screenmob.hud_used.hud_shown) if(H.s_store) H.s_store.screen_loc = ui_sstore1 @@ -407,17 +392,13 @@ screenmob.client.screen -= H.r_store if(hud_version != HUD_STYLE_NOHUD) - if(H.r_hand) - H.r_hand.screen_loc = ui_rhand - screenmob.client.screen += H.r_hand - if(H.l_hand) - H.l_hand.screen_loc = ui_lhand - screenmob.client.screen += H.l_hand + for(var/obj/item/I in H.held_items) + I.screen_loc = ui_hand_position(H.get_held_index_of_item(I)) + H.client.screen += I else - if(H.r_hand) - screenmob.client.screen -= H.r_hand - if(H.l_hand) - screenmob.client.screen -= H.l_hand + for(var/obj/item/I in H.held_items) + I.screen_loc = null + H.client.screen -= I /mob/living/carbon/human/verb/toggle_hotkey_verbs() set category = "OOC" diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm index b7d8437e02a..dd6ec4bef44 100644 --- a/code/_onclick/hud/monkey.dm +++ b/code/_onclick/hud/monkey.dm @@ -21,32 +21,18 @@ using.screen_loc = ui_drop_throw static_inventory += using - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "right hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_r" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - static_inventory += inv_box - - inv_box = new /obj/screen/inventory/hand() - inv_box.name = "left hand" - inv_box.icon = ui_style - inv_box.icon_state = "hand_l" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - static_inventory += inv_box + build_hand_slots(ui_style) using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_1_m" //extra wide! - using.screen_loc = ui_swaphand1 + using.screen_loc = ui_swaphand_position(owner,1) static_inventory += using using = new /obj/screen/swap_hand() using.icon = ui_style using.icon_state = "swap_2" - using.screen_loc = ui_swaphand2 + using.screen_loc = ui_swaphand_position(owner,2) static_inventory += using inv_box = new /obj/screen/inventory() @@ -142,17 +128,13 @@ M.head.screen_loc = null if(hud_version != HUD_STYLE_NOHUD) - if(M.r_hand) - M.r_hand.screen_loc = ui_rhand - M.client.screen += M.r_hand - if(M.l_hand) - M.l_hand.screen_loc = ui_lhand - M.client.screen += M.l_hand + for(var/obj/item/I in M.held_items) + I.screen_loc = ui_hand_position(M.get_held_index_of_item(I)) + M.client.screen += I else - if(M.r_hand) - M.r_hand.screen_loc = null - if(M.l_hand) - M.l_hand.screen_loc = null + for(var/obj/item/I in M.held_items) + I.screen_loc = null + M.client.screen -= I /mob/living/carbon/monkey/create_mob_hud() if(client && !hud_used) diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index 2bbc92c7cd4..ac42696bc56 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -7,7 +7,7 @@ mymob.client.screen = list() mymob.client.screen += mymob.client.void -/mob/living/carbon/brain/create_mob_hud() +/mob/living/brain/create_mob_hud() if(client && !hud_used) hud_used = new /datum/hud/brain(src) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index f572172bb60..aaf740f479e 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -153,9 +153,9 @@ infodisplay += healths //Installed Module - mymob.hands = new /obj/screen/robot/module() - mymob.hands.screen_loc = ui_borg_module - static_inventory += mymob.hands + mymobR.hands = new /obj/screen/robot/module() + mymobR.hands.screen_loc = ui_borg_module + static_inventory += mymobR.hands //Store module_store_icon = new /obj/screen/robot/store() diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 529a5c11ad1..cb9c698efaf 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -90,8 +90,7 @@ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech return 1 if(usr.attack_ui(slot_id)) - usr.update_inv_l_hand(0) - usr.update_inv_r_hand(0) + usr.update_inv_hands() return 1 /obj/screen/inventory/update_icon() @@ -108,13 +107,15 @@ var/image/active_overlay var/image/handcuff_overlay var/image/blocked_overlay + var/held_index = 0 /obj/screen/inventory/hand/update_icon() ..() + if(!active_overlay) active_overlay = image("icon"=icon, "icon_state"="hand_active") if(!handcuff_overlay) - var/state = (slot_id == slot_r_hand) ? "markus" : "gabrielle" + var/state = (!(held_index % 2)) ? "markus" : "gabrielle" handcuff_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"=state) if(!blocked_overlay) blocked_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"="blocked") @@ -126,18 +127,15 @@ var/mob/living/carbon/C = hud.mymob if(C.handcuffed) add_overlay(handcuff_overlay) - if(slot_id == slot_r_hand) - if(!C.has_right_hand()) - add_overlay(blocked_overlay) - else if(slot_id == slot_l_hand) - if(!C.has_left_hand()) + + if(held_index) + if(!C.has_hand_for_held_index(held_index)) add_overlay(blocked_overlay) - if(slot_id == slot_l_hand && hud.mymob.hand) - add_overlay(active_overlay) - else if(slot_id == slot_r_hand && !hud.mymob.hand) + if(held_index == hud.mymob.active_hand_index) add_overlay(active_overlay) + /obj/screen/inventory/hand/Click() // At this point in client Click() code we have passed the 1/10 sec check and little else // We don't even know if it's a middle click @@ -150,11 +148,7 @@ if(ismob(usr)) var/mob/M = usr - switch(name) - if("right hand", "r_hand") - M.activate_hand("r") - if("left hand", "l_hand") - M.activate_hand("l") + M.swap_hand(held_index) return 1 /obj/screen/close @@ -239,12 +233,10 @@ C << "You are not wearing an internals mask!" return - if(istype(C.l_hand, /obj/item/weapon/tank)) - C << "You are now running on internals from the [C.l_hand] on your left hand." - C.internal = C.l_hand - else if(istype(C.r_hand, /obj/item/weapon/tank)) - C << "You are now running on internals from the [C.r_hand] on your right hand." - C.internal = C.r_hand + var/obj/item/I = C.is_holding_item_of_type(/obj/item/weapon/tank) + if(I) + C << "You are now running on internals from the [I] on your [C.get_held_index_name(C.get_held_index_of_item(I))]." + C.internal = I else if(ishuman(C)) var/mob/living/carbon/human/H = C if(istype(H.s_store, /obj/item/weapon/tank)) @@ -328,7 +320,7 @@ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech return 1 if(master) - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(I) master.attackby(I, usr, params) return 1 diff --git a/code/_onclick/hud/swarmer.dm b/code/_onclick/hud/swarmer.dm index 85ee9c4977f..92a98e14c67 100644 --- a/code/_onclick/hud/swarmer.dm +++ b/code/_onclick/hud/swarmer.dm @@ -68,11 +68,11 @@ var/obj/screen/using using = new /obj/screen/swarmer/FabricateTrap() - using.screen_loc = ui_rhand + using.screen_loc = ui_hand_position(2) static_inventory += using using = new /obj/screen/swarmer/Barricade() - using.screen_loc = ui_lhand + using.screen_loc = ui_hand_position(1) static_inventory += using using = new /obj/screen/swarmer/Replicate() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 838f913536f..ced66536d87 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -34,6 +34,8 @@ user.lastattacked = M M.lastattacker = user + if(user != M) + user.do_attack_animation(M) M.attacked_by(src, user) add_logs(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") @@ -58,19 +60,27 @@ user.visible_message("[user] has hit [src] with [I]!", "You hit [src] with [I]!") /mob/living/attacked_by(obj/item/I, mob/living/user) - if(user != src) - user.do_attack_animation(src) - if(send_item_attack_message(I, user)) - if(apply_damage(I.force, I.damtype)) - if(I.damtype == BRUTE) - if(prob(33)) - I.add_mob_blood(src) - var/turf/location = get_turf(src) - add_splatter_floor(location) - if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood - user.add_mob_blood(src) - return TRUE + send_item_attack_message(I, user) + if(I.force) + apply_damage(I.force, I.damtype) + if(I.damtype == BRUTE) + if(prob(33)) + I.add_mob_blood(src) + var/turf/location = get_turf(src) + add_splatter_floor(location) + if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood + user.add_mob_blood(src) + return TRUE //successful attack +/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user) + if(!I.force) + user.visible_message("[user] gently taps [src] with [I].",\ + "This weapon is ineffective, it does no damage!") + else if(I.force < force_threshold || I.damtype == STAMINA) + visible_message("[I] bounces harmlessly off of [src].",\ + "[I] bounces harmlessly off of [src]!") + else + return ..() // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. @@ -90,7 +100,7 @@ if(I.attack_verb && I.attack_verb.len) message_verb = "[pick(I.attack_verb)]" else if(!I.force) - return 0 + return var/message_hit_area = "" if(hit_area) message_hit_area = " in the [hit_area]" @@ -102,12 +112,3 @@ "[attack_message]") return 1 -/mob/living/simple_animal/send_item_attack_message(obj/item/I, mob/living/user, hit_area) - if(!I.force) - user.visible_message("[user] gently taps [src] with [I].",\ - "This weapon is ineffective, it does no damage!") - else if(I.force < force_threshold || I.damtype == STAMINA) - visible_message("[I] bounces harmlessly off of [src].",\ - "[I] bounces harmlessly off of [src]!") - else - return ..() diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 95c2ff9836a..f6986e8d4f1 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -50,9 +50,8 @@ for(var/datum/mutation/human/HM in dna.mutations) HM.on_ranged_attack(src, A) - var/turf/T = A - if(istype(T) && get_dist(src,T) <= 1) - src.Move_Pulled(T) + if(isturf(A) && get_dist(src,A) <= 1) + src.Move_Pulled(A) /* Animals & All Unspecified @@ -111,7 +110,7 @@ */ /mob/living/carbon/alien/UnarmedAttack(atom/A) A.attack_alien(src) -/atom/proc/attack_alien(mob/user) +/atom/proc/attack_alien(mob/living/carbon/alien/user) attack_paw(user) return /mob/living/carbon/alien/RestrainedClickOn(atom/A) @@ -135,6 +134,68 @@ /mob/living/simple_animal/slime/RestrainedClickOn(atom/A) return + +/* + Drones +*/ +/mob/living/simple_animal/drone/UnarmedAttack(atom/A) + A.attack_drone(src) + +/atom/proc/attack_drone(mob/living/simple_animal/drone/user) + attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans. + +/mob/living/simple_animal/slime/RestrainedClickOn(atom/A) + return + + +/* + True Devil +*/ + +/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity) + A.attack_hand(src) + +/* + Brain +*/ + +/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default + return + + +/* + pAI +*/ + +/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default + return + + +/* + Simple animals +*/ + +/mob/living/simple_animal/UnarmedAttack(atom/A, proximity) + if(!dextrous) + return ..() + if(!ismob(A)) + A.attack_hand(src) + update_inv_hands() + + +/* + Hostile animals +*/ + +/mob/living/simple_animal/hostile/UnarmedAttack(atom/A) + target = A + if(dextrous && !is_type_in_typecache(A, environment_target_typecache) && !ismob(A)) + ..() + else + AttackingTarget() + + + /* New Players: Have no reason to click on anything at all. diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index cf28bb9fa7b..0b050c9322f 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -86,7 +86,7 @@ var/const/tk_maxrange = 15 //stops TK grabs being equipped anywhere but into hands /obj/item/tk_grab/equipped(mob/user, slot) - if( (slot == slot_l_hand) || (slot== slot_r_hand) ) + if(slot == slot_hands) return qdel(src) return diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index ed93eb9369a..5b251a3edfa 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -279,11 +279,11 @@ var/global/list/internal_byond_list_vars = list("contents" = TRUE, "verbs" = TRU if(iscarbon(D)) body += "" body += "" + body += "" body += "" if(ishuman(D)) body += "" body += "" - body += "" body += "" body += "" body += "" @@ -898,25 +898,51 @@ body var/newtype = species_list[result] H.set_species(newtype) - else if(href_list["removebodypart"]) + else if(href_list["editbodypart"]) if(!check_rights(R_SPAWN)) return - var/mob/living/carbon/human/H = locate(href_list["removebodypart"]) - if(!istype(H)) - usr << "This can only be done to instances of type /mob/living/carbon/human" + var/mob/living/carbon/C = locate(href_list["editbodypart"]) + if(!istype(C)) + usr << "This can only be done to instances of type /mob/living/carbon" return - var/result = input(usr, "Please choose which body part to remove","Remove Body Part") as null|anything in list("head", "l_arm", "r_arm", "l_leg", "r_leg") + var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment") + if(!edit_action) + return + var/list/limb_list = list("head", "l_arm", "r_arm", "l_leg", "r_leg") + if(edit_action == "augment") + limb_list += "chest" + var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list - if(!H) + if(!C) usr << "Mob doesn't exist anymore" return if(result) - var/obj/item/bodypart/BP = H.get_bodypart(result) - if(BP) - BP.drop_limb() + var/obj/item/bodypart/BP = C.get_bodypart(result) + switch(edit_action) + if("remove") + if(BP) + BP.drop_limb() + else + usr << "[C] doesn't have such bodypart." + if("add") + if(BP) + usr << "[C] already has such bodypart." + else + if(!C.regenerate_limb(result)) + usr << "[C] cannot have such bodypart." + if("augment") + if(ishuman(C)) + if(BP) + BP.change_bodypart_status(BODYPART_ROBOTIC, 1) + else + usr << "[C] doesn't have such bodypart." + else + usr << "Only humans can be augmented." + + else if(href_list["purrbation"]) if(!check_rights(R_SPAWN)) @@ -985,3 +1011,4 @@ body log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") href_list["datumrefresh"] = href_list["mobToDamage"] + diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index d8bbc5e5ae9..09dd6bf8dc0 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -34,7 +34,7 @@ BONUS M << "[pick("You swallow excess mucus.", "You lightly cough.")]" else M.emote("cough") - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I && I.w_class == 1) M.drop_item() return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm index ba315278a20..f9109df17c1 100644 --- a/code/datums/diseases/advance/symptoms/damage_converter.dm +++ b/code/datums/diseases/advance/symptoms/damage_converter.dm @@ -33,30 +33,19 @@ Bonus Convert(M) return -/datum/symptom/damage_converter/proc/Convert(mob/living/M) +/datum/symptom/damage_converter/proc/Convert(mob/living/carbon/C) - var/get_damage = rand(1, 2) + var/heal_amt = rand(1, 2) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M + var/list/parts = C.get_damaged_bodyparts(1,1) //1,1 because it needs inputs. - var/list/parts = H.get_damaged_bodyparts(1,1) //1,1 because it needs inputs. - - if(!parts.len) - return - - for(var/obj/item/bodypart/L in parts) - L.heal_damage(get_damage, get_damage, 0) - M.adjustToxLoss(get_damage*parts.len) - - else - if(M.getFireLoss() > 0 || M.getBruteLoss() > 0) - M.adjustFireLoss(-get_damage) - M.adjustBruteLoss(-get_damage) - M.adjustToxLoss(get_damage) - else - return + if(!parts.len) + return + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt, heal_amt)) + C.update_damage_overlays() + C.adjustToxLoss(heal_amt*parts.len) return 1 /* diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm index 3a5dc527f09..e3ffbc868ba 100644 --- a/code/datums/diseases/advance/symptoms/genetics.dm +++ b/code/datums/diseases/advance/symptoms/genetics.dm @@ -30,14 +30,14 @@ Bonus /datum/symptom/genetic_mutation/Activate(datum/disease/advance/A) ..() if(prob(SYMPTOM_ACTIVATION_PROB * 5)) // 15% chance - var/mob/living/carbon/M = A.affected_mob - if(!M.has_dna()) + var/mob/living/carbon/C = A.affected_mob + if(!C.has_dna()) return switch(A.stage) if(4, 5) - M << "[pick("Your skin feels itchy.", "You feel light headed.")]" - M.dna.remove_mutation_group(possible_mutations) - randmut(M, possible_mutations) + C << "[pick("Your skin feels itchy.", "You feel light headed.")]" + C.dna.remove_mutation_group(possible_mutations) + C.randmut(possible_mutations) return // Archive their DNA before they were infected. diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 11a8eebbe5d..626fb567c3d 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -38,7 +38,7 @@ if(prob(1)) affected_mob << "Your muscles ache." if(prob(20)) - affected_mob.take_organ_damage(1) + affected_mob.take_bodypart_damage(1) if(prob(1)) affected_mob << "Your stomach hurts." if(prob(20)) diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 1df55bbb9d7..20bea2da922 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -26,7 +26,7 @@ if(prob(1)) affected_mob << "Your muscles ache." if(prob(20)) - affected_mob.take_organ_damage(1) + affected_mob.take_bodypart_damage(1) if(prob(1)) affected_mob << "Your stomach hurts." if(prob(20)) @@ -45,7 +45,7 @@ if(prob(1)) affected_mob << "Your muscles ache." if(prob(20)) - affected_mob.take_organ_damage(1) + affected_mob.take_bodypart_damage(1) if(prob(1)) affected_mob << "Your stomach hurts." if(prob(20)) diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index c041f2610de..57ded9abc30 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -22,7 +22,7 @@ affected_mob.emote("cough") if(prob(1)) affected_mob << "You're burning in your own skin!" - affected_mob.take_organ_damage(0,5) + affected_mob.take_bodypart_damage(0,5) if(3) affected_mob.bodytemperature += 20 @@ -32,5 +32,5 @@ affected_mob.emote("cough") if(prob(5)) affected_mob << "You're burning in your own skin!" - affected_mob.take_organ_damage(0,5) + affected_mob.take_bodypart_damage(0,5) return diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index bc9d70fc63c..2e6d2a52cce 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -78,12 +78,9 @@ STI KALY - blind else var/mob/living/carbon/H = affected_mob if(prob(chance)) - if(!istype(H.r_hand, /obj/item/weapon/staff)) - H.drop_r_hand() - H.put_in_r_hand( new /obj/item/weapon/staff(H) ) - return - return - + var/obj/item/weapon/staff/S = new(H) + if(!H.put_in_hands(S)) + qdel(S) /datum/disease/wizarditis/proc/teleport() diff --git a/code/datums/dna.dm b/code/datums/dna.dm index ee19e8483a6..e3d88e8b15e 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -11,13 +11,15 @@ var/list/mutations = list() //All mutations are from now on here var/list/temporary_mutations = list() //Timers for temporary mutations var/list/previous = list() //For temporary name/ui/ue/blood_type modifications - var/mob/living/carbon/holder + var/mob/living/holder -/datum/dna/New(mob/living/carbon/new_holder) +/datum/dna/New(mob/living/new_holder) if(new_holder) holder = new_holder /datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) + if(!istype(destination)) + return destination.dna.unique_enzymes = unique_enzymes destination.dna.uni_identity = uni_identity destination.dna.blood_type = blood_type @@ -166,12 +168,36 @@ features = random_features() +/datum/dna/stored //subtype used by brain mob's stored_dna + +/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna. + return + +/datum/dna/stored/remove_mutation(mutation_name) + return + +/datum/dna/stored/check_mutation(mutation_name) + return + +/datum/dna/stored/remove_all_mutations() + return + +/datum/dna/stored/remove_mutation_group(list/group) + return /////////////////////////// DNA MOB-PROCS ////////////////////// /mob/proc/set_species(datum/species/mrace, icon_update = 1) return +/mob/living/brain/set_species(datum/species/mrace, icon_update = 1) + if(mrace) + if(ispath(mrace)) + stored_dna.species = new mrace() + else + stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human + + /mob/living/carbon/set_species(datum/species/mrace, icon_update = 1) if(mrace && has_dna()) dna.species.on_species_loss(src) @@ -290,48 +316,46 @@ mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutat return 0 return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) -/proc/randmut(mob/living/carbon/M, list/candidates, difficulty = 2) - if(!M.has_dna()) +/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2) + if(!has_dna()) return var/datum/mutation/human/num = pick(candidates) - . = num.force_give(M) - return + . = num.force_give(src) -/proc/randmutb(mob/living/carbon/M) - if(!M.has_dna()) +/mob/living/carbon/proc/randmutb() + if(!has_dna()) return var/datum/mutation/human/HM = pick((bad_mutations | not_good_mutations) - mutations_list[RACEMUT]) - . = HM.force_give(M) + . = HM.force_give(src) -/proc/randmutg(mob/living/carbon/M) - if(!M.has_dna()) +/mob/living/carbon/proc/randmutg() + if(!has_dna()) return var/datum/mutation/human/HM = pick(good_mutations) - . = HM.force_give(M) + . = HM.force_give(src) -/proc/randmutvg(mob/living/carbon/M) - if(!M.has_dna()) +/mob/living/carbon/proc/randmutvg() + if(!has_dna()) return var/datum/mutation/human/HM = pick((good_mutations) - mutations_list[HULK] - mutations_list[DWARFISM]) - . = HM.force_give(M) + . = HM.force_give(src) -/proc/randmuti(mob/living/carbon/M) - if(!M.has_dna()) +/mob/living/carbon/proc/randmuti() + if(!has_dna()) return var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) - var/newdna = setblock(M.dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters)) - M.dna.uni_identity = newdna - M.updateappearance(mutations_overlay_update=1) - return + var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters)) + dna.uni_identity = newdna + updateappearance(mutations_overlay_update=1) -/proc/clean_dna(mob/living/carbon/M) - if(!M.has_dna()) +/mob/living/carbon/proc/clean_dna() + if(!has_dna()) return - M.dna.remove_all_mutations() + dna.remove_all_mutations() -/proc/clean_randmut(mob/living/carbon/M, list/candidates, difficulty = 2) - clean_dna(M) - randmut(M, candidates, difficulty) +/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2) + clean_dna() + randmut(candidates, difficulty) /proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) if(!M.has_dna()) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index b9609214cc3..c00950a6fee 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -106,6 +106,8 @@ if(!center) center = destination for(var/turf/T in range(precision,center)) + if(T.is_transition_turf()) + continue // Avoid picking these. var/area/A = T.loc if(!A.noteleport) posturfs.Add(T) @@ -114,7 +116,7 @@ else destturf = get_turf(destination) - if(!destturf || !curturf) + if(!destturf || !curturf || destturf.is_transition_turf()) return 0 var/area/A = get_area(curturf) diff --git a/code/datums/martial.dm b/code/datums/martial.dm index ea41a804136..9b9cfb3c3d6 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -333,8 +333,7 @@ else A.start_pulling(D, 1) if(A.pulling) - D.drop_r_hand() - D.drop_l_hand() + D.drop_all_held_items() D.stop_pulling() add_logs(A, D, "grabbed", addition="aggressively") A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab @@ -483,7 +482,7 @@ var/mob/living/carbon/human/H = user H.apply_damage(2*force, BRUTE, "head") else - user.take_organ_damage(2*force) + user.take_bodypart_damage(2*force) return if(isrobot(target)) return ..() diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 1da9d820a76..330ca40d1c5 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -130,16 +130,10 @@ datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/livi if(check_streak(A,D)) return 1 if(prob(60)) - if(D.hand) - if(istype(D.l_hand, /obj/item)) - var/obj/item/I = D.l_hand - D.drop_item() - A.put_in_hands(I) - else - if(istype(D.r_hand, /obj/item)) - var/obj/item/I = D.r_hand - D.drop_item() - A.put_in_hands(I) + var/obj/item/I = D.get_active_held_item() + if(I) + D.drop_item() + A.put_in_hands(I) D.visible_message("[A] has disarmed [D]!", \ "[A] has disarmed [D]!") playsound(D, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index af57e091efa..6ac88edf050 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -187,7 +187,7 @@ /datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner) if(owner.getFireLoss()) if(prob(1)) - owner.heal_organ_damage(0,1) //Is this really needed? + owner.heal_bodypart_damage(0,1) //Is this really needed? /datum/mutation/human/x_ray @@ -252,11 +252,11 @@ var/mob/new_mob if(prob(95)) if(prob(50)) - new_mob = randmutb(owner) + new_mob = owner.randmutb() else - new_mob = randmuti(owner) + new_mob = owner.randmuti() else - new_mob = randmutg(owner) + new_mob = owner.randmutg() if(new_mob && ismob(new_mob)) owner = new_mob . = owner diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm index 9f75bf714e6..6213eacc75c 100644 --- a/code/datums/weather/weather_types.dm +++ b/code/datums/weather/weather_types.dm @@ -150,15 +150,14 @@ if(H.dna && H.dna.species) if(!(RADIMMUNE in H.dna.species.specflags)) if(prob(max(0,100-resist))) - randmuti(H) + H.randmuti() if(prob(50)) if(prob(90)) - randmutb(H) + H.randmutb() else - randmutg(H) + H.randmutg() H.domutcheck() L.rad_act(20,1) - /datum/weather/rad_storm/end() if(..()) return diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index c161690b2b8..bf749e18e5f 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -310,7 +310,7 @@ var/list/wire_color_directory = list() return var/target_wire = params["wire"] var/mob/living/L = usr - var/obj/item/I = L.get_active_hand() + var/obj/item/I = L.get_active_held_item() switch(action) if("cut") if(istype(I, /obj/item/weapon/wirecutters) || IsAdminGhost(usr)) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ef0611a9cd7..8162b451dc8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -146,7 +146,7 @@ reset_perspective(destination) update_canmove() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall. -/mob/living/carbon/brain/forceMove(atom/destination) +/mob/living/brain/forceMove(atom/destination) if(container) container.forceMove(destination) else //something went very wrong. diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index a1d1a7b8551..53f07c8ffd8 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -84,7 +84,7 @@ if("healing") M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/charge(null)) M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(null)) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand) + M.put_in_hands_or_del(new /obj/item/weapon/gun/magic/staff/healing(M)) M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall." if("robeless") M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null)) @@ -165,7 +165,7 @@ var/mob/living/carbon/human/M = new/mob/living/carbon/human(T) C.prefs.copy_to(M) M.key = C.key - M.mind.make_Nuke(null, nuke_code = null, 0, FALSE) + M.mind.make_Nuke(null, null, 0, FALSE) var/newname = M.dna.species.random_name(M.gender,0,ticker.mode.nukeops_lastname) M.mind.name = newname M.real_name = newname diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index 8bb2bf50540..08efd29bbf4 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -21,32 +21,28 @@ var/weapon_name_simple /obj/effect/proc_holder/changeling/weapon/try_to_sting(mob/user, mob/target) - if(check_weapon(user, user.r_hand, 1)) - return - if(check_weapon(user, user.l_hand, 0)) - return + for(var/obj/item/I in user.held_items) + if(check_weapon(user, I)) + return ..(user, target) -/obj/effect/proc_holder/changeling/weapon/proc/check_weapon(mob/user, obj/item/hand_item, right_hand=1) +/obj/effect/proc_holder/changeling/weapon/proc/check_weapon(mob/user, obj/item/hand_item) if(istype(hand_item, weapon_type)) playsound(user, 'sound/effects/blobattack.ogg', 30, 1) qdel(hand_item) user.visible_message("With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!" + user << "The [user.get_active_held_item()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!" return var/limb_regen = 0 - if(user.hand) //we regen the arm before changing it into the weapon - limb_regen = user.regenerate_limb("l_arm", 1) - else + if(user.active_hand_index % 2 == 0) //we regen the arm before changing it into the weapon limb_regen = user.regenerate_limb("r_arm", 1) + else + limb_regen = user.regenerate_limb("l_arm", 1) if(limb_regen) user.visible_message("[user]'s missing arm reforms, making a loud, grotesque sound!", "Your arm regrows, making a loud, crunchy sound and giving you great pain!", "You hear organic matter ripping and tearing!") user.emote("scream") @@ -56,8 +52,9 @@ return W /obj/effect/proc_holder/changeling/weapon/on_refund(mob/user) - check_weapon(user, user.r_hand, 1) - check_weapon(user, user.l_hand, 0) + for(var/obj/item/I in user.held_items) + check_weapon(user, I) + //Parent to space suits and armor. /obj/effect/proc_holder/changeling/suit diff --git a/code/game/gamemodes/changeling/powers/regenerate.dm b/code/game/gamemodes/changeling/powers/regenerate.dm index f14c1c95780..6d38a58cc47 100644 --- a/code/game/gamemodes/changeling/powers/regenerate.dm +++ b/code/game/gamemodes/changeling/powers/regenerate.dm @@ -13,21 +13,20 @@ /obj/effect/proc_holder/changeling/regenerate/sting_action(mob/living/user) user << "You feel an itching, both inside and \ outside as your tissues knit and reknit." - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.restore_blood() - H.remove_all_embedded_objects() - var/list/missing = H.get_missing_limbs() + if(iscarbon(user)) + var/mob/living/carbon/C = user + var/list/missing = C.get_missing_limbs() if(missing.len) playsound(user, 'sound/magic/Demon_consume.ogg', 50, 1) - H.visible_message("[user]'s missing limbs \ + C.visible_message("[user]'s missing limbs \ reform, making a loud, grotesque sound!", "Your limbs regrow, making a \ loud, crunchy sound and giving you great pain!", "You hear organic matter ripping \ and tearing!") - H.emote("scream") - H.regenerate_limbs(1) - - CHECK_DNA_AND_SPECIES(H) - H.dna.species.on_species_gain(H, H.dna.species) + C.emote("scream") + C.regenerate_limbs(1) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.restore_blood() + H.remove_all_embedded_objects() diff --git a/code/game/gamemodes/changeling/powers/strained_muscles.dm b/code/game/gamemodes/changeling/powers/strained_muscles.dm index 1c7ce8d11a5..79c707bff04 100644 --- a/code/game/gamemodes/changeling/powers/strained_muscles.dm +++ b/code/game/gamemodes/changeling/powers/strained_muscles.dm @@ -33,7 +33,7 @@ break stacks++ - //user.take_organ_damage(stacks * 0.03, 0) + //user.take_bodypart_damage(stacks * 0.03, 0) user.staminaloss += stacks * 1.3 //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack if(stacks == 11) //Warning message that the stacks are getting too high diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 5deadd09cbf..9f3df575613 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -97,7 +97,7 @@ var/mob/living/carbon/C = target if(C.status_flags & CANWEAKEN) C.do_jitter_animation(500) - C.take_organ_damage(20, 0) //The process is extremely painful + C.take_bodypart_damage(20, 0) //The process is extremely painful target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!") spawn(10) @@ -138,7 +138,7 @@ add_logs(user, target, "stung", object="falso armblade sting") if(!target.drop_item()) - user << "The [target.get_active_hand()] is stuck to their hand, you cannot grow a false armblade over it!" + user << "The [target.get_active_held_item()] is stuck to their hand, you cannot grow a false armblade over it!" return if(ismonkey(target)) @@ -162,8 +162,7 @@ "You need to hold the slab in your active hand to recite scripture!" return recite_scripture(user) @@ -223,7 +223,7 @@ else user << "That section of scripture is still locked!" return 0 - for(var/S in subtypesof(/datum/clockwork_scripture)) + for(var/S in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority)) var/datum/clockwork_scripture/C = S if(initial(C.tier) == scripture_tier) available_scriptures += "[initial(C.name)] ([initial(C.descname)])" @@ -236,7 +236,7 @@ var/datum/clockwork_scripture/C = S if("[initial(C.name)] ([initial(C.descname)])" == chosen_scripture) scripture_to_recite = new C - if(!scripture_to_recite || user.get_active_hand() != src) + if(!scripture_to_recite || user.get_active_held_item() != src) return 0 tiers_of_scripture = scripture_unlock_check() if(!ratvar_awakens && !no_cost && !tiers_of_scripture[scripture_to_recite.tier]) @@ -265,121 +265,73 @@ universe and Reebe (the Celestial Derelict) can be created and utilized. This is typically done via the creation of a slab akin to the one you are holding right now. The slabs tap into the \ tidal flow of energy and information keeping Reebe sealed and presents it as meaningless images to preserve sanity. This slab can utilize the power in many different ways.

\ \ - This is done through Components - pieces of the Justiciar's body that have since fallen off in the countless years since his imprisonment. Ratvar's unfortunate condition results \ - in the fragmentation of his body. These components still house great power on their own, and can slowly be drawn from Reebe by links capable of doing so. The most basic of these links lies \ - in the clockwork slab, which will slowly generate components over time - one component of a random type is produced every 1 minute and 30 seconds, plus 30 seconds per each servant above 5, \ - which is obviously inefficient. There are other ways to create these components through scripture and certain structures.

\ + This is done through Components - pieces of the Justiciar's body that have since fallen off in the countless years since his imprisonment. Ratvar's unfortunate condition results \ + in the fragmentation of his body. These components still house great power on their own, and can slowly be drawn from Reebe by links capable of doing so.
\ + The most basic of these links lies in the clockwork slab, which will slowly generate components over time - one component of a random type is produced every 1 minute and 30 seconds, plus 30 seconds per each servant above 5, \ + which is obviously inefficient. There are other, more efficient, ways to create these components through scripture and certain structures.

\ \ - In addition to their ability to pull components, slabs also possess other functionalities...

\ + In addition to their ability to generate components, slabs also possess other functionalities...

\ \ - The first functionality of the slab is Recital. This allows you to consume components either from your slab or from the global cache (more on that in the scripture list) to perform \ - effects usually considered magical in nature. Effects vary considerably - you might drain the power of nearby APCs, cause mass confusion, or force people to walk. Nevertheless, scripture \ - is extremely important to a successful takeover.

\ + The first functionality of the slab is Recital. This allows you to consume components either from your slab or from the global cache (more on that in the scripture list) to perform \ + effects usually considered magical in nature.
\ + Effects vary considerably, including mass conversion, construction of various structures, or causing a massive global hallucination. Nevertheless, scripture is extremely important to a successful takeover.

\ \ - The second functionality of the clockwork slab is Recollection, which will display this guide.

\ + The second functionality of the clockwork slab is Recollection, which will display this guide.

\ \ The third to fifth functionalities are several buttons in the top left while holding the slab, from left to right, they are:
\ - Hierophant Network, which allows communication to other servants.
\ - Guvax, which simply allows you to quickly invoke the Guvax scripture.
\ - Vanguard, which, like Guvax, simply allows you to quickly invoke the Vanguard scripture.

\ + Hierophant Network, which allows communication to other servants.
\ + Guvax, which simply allows you to quickly invoke the Guvax scripture.
\ + Vanguard, which, like Guvax, simply allows you to quickly invoke the Vanguard scripture.

\ \ Examine the slab for component amount information.

\ \ - A complete list of scripture, its effects, and its requirements can be found below. Note that anything above a driver always consumes the components listed unless otherwise \ - specified.

" + A complete list of scripture, its effects, and its requirements can be found below.
\ + Key:
BE = Belligerent Eyes
\ + VC = Vanguard Cogwheels
\ + GC = Guvax Capacitors
\ + RA = Replicant Alloy
\ + HA = Hierophant Ansibles
" var/text_to_add = "" - var/drivers = "[SCRIPTURE_DRIVER]" - var/scripts = "[SCRIPTURE_SCRIPT]
These scriptures require at least five servants and a tinkerer's cache." - var/applications = "[SCRIPTURE_APPLICATION]
These scriptures require at least eight servants, three tinkerer's caches, and 100CV." - var/revenant = "[SCRIPTURE_REVENANT]
These scriptures require at least ten servants and 200CV." - var/judgement = "[SCRIPTURE_REVENANT]
These scriptures require at least twelve servants and 300CV. In addition, there may not be any active non-servant AIs." - for(var/V in subtypesof(/datum/clockwork_scripture)) + var/drivers = "
[SCRIPTURE_DRIVER]
These scriptures are always unlocked.
" + var/scripts = "
[SCRIPTURE_SCRIPT]
These scriptures require at least five servants and a tinkerer's cache.
" + var/applications = "[SCRIPTURE_APPLICATION]
These scriptures require at least eight servants, three tinkerer's caches, and 100CV.
" + var/revenant = "
[SCRIPTURE_REVENANT]
These scriptures require at least ten servants and 200CV.
" + var/judgement = "
[SCRIPTURE_JUDGEMENT]
These scriptures require at least twelve servants and 300CV. In addition, there may not be any active non-servant AIs.
" + for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority)) var/datum/clockwork_scripture/S = V var/datum/clockwork_scripture/S2 = new V var/list/req_comps = S2.required_components var/list/cons_comps = S2.consumed_components qdel(S2) - switch(initial(S.tier)) - if(SCRIPTURE_DRIVER) - drivers += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ - \ - Component Requirement: \ - [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Component Cost: \ - [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Tip: [initial(S.usage_tip)]
" - if(SCRIPTURE_SCRIPT) - scripts += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ - \ - Component Requirement: \ - [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Component Cost: \ - [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Tip: [initial(S.usage_tip)]
" - if(SCRIPTURE_APPLICATION) - applications += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ - \ - Component Requirement: \ - [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Component Cost: \ - [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Tip: [initial(S.usage_tip)]
" - if(SCRIPTURE_REVENANT) - revenant += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ - \ - Component Requirement: \ - [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Component Cost: \ - [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Tip: [initial(S.usage_tip)]
" - if(SCRIPTURE_JUDGEMENT) - judgement += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ - \ - Component Requirement: \ - [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Component Cost: \ - [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \ - [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \ - [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \ - [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \ - [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\ - Tip: [initial(S.usage_tip)]
" + if(initial(S.tier) != SCRIPTURE_PERIPHERAL) + var/scripture_text = "
[initial(S.name)]:
[initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\ + Component Requirement: \ + [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] BE" : ""] \ + [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] VC" : ""] \ + [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] GC" : ""] \ + [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] RA" : ""] \ + [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] HA" : ""]
" + for(var/i in cons_comps) + if(cons_comps[i]) + scripture_text += "Component Cost: \ + [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] BE" : ""] \ + [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] VC" : ""] \ + [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] GC" : ""] \ + [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] RA" : ""] \ + [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] HA" : ""]
" + break //we want this to only show up if the scripture has a cost of some sort + scripture_text += "Tip: [initial(S.usage_tip)]
" + switch(initial(S.tier)) + if(SCRIPTURE_DRIVER) + drivers += scripture_text + if(SCRIPTURE_SCRIPT) + scripts += scripture_text + if(SCRIPTURE_APPLICATION) + applications += scripture_text + if(SCRIPTURE_REVENANT) + revenant += scripture_text + if(SCRIPTURE_JUDGEMENT) + judgement += scripture_text text_to_add += "[drivers]
[scripts]
[applications]
[revenant]
[judgement]
" text_to_add += "
Purge all untruths and honor Ratvar.
" text += text_to_add @@ -407,7 +359,7 @@ var/message = stripped_input(user, "Enter a message to send to your fellow servants.", "Hierophant") if(!message || !user || !user.canUseTopic(src)) return 0 - clockwork_say(user, text2ratvar("Servants, hear my words. [message]"), TRUE) + clockwork_say(user, text2ratvar("Servants, hear my words. [html_decode(message)]"), TRUE) titled_hierophant_message(user, message) return 1 @@ -517,7 +469,7 @@ user << "[src] is still gathering power!" return 0 var/mob/living/carbon/C = user - if(C.l_hand && C.r_hand) + if(!user.get_empty_held_indexes()) C << "You require a free hand to utilize [src]'s power!" return 0 C.visible_message("[C]'s hand is enveloped in violet flames!", "You harness [src]'s power. Direct it at a tile at any range to unleash it, or use the action button again to dispel it.") diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm index 3c9f29bd46a..d8d3025e088 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs.dm @@ -261,7 +261,7 @@ if(amount > 0) combattimer = world.time + initial(combattimer) for(var/mob/living/L in view(2, src)) - if(istype(L.l_hand, /obj/item/weapon/nullrod) || istype(L.r_hand, /obj/item/weapon/nullrod)) //hand-held holy weapons increase the damage it takes + if(L.is_holding_item_of_type(/obj/item/weapon/nullrod)) src << "The presence of a brandished holy artifact weakens your armor!" amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage break diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm index 6af53c5efd5..0156767691a 100644 --- a/code/game/gamemodes/clock_cult/clock_scripture.dm +++ b/code/game/gamemodes/clock_cult/clock_scripture.dm @@ -25,6 +25,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed var/multiple_invokers_used = FALSE //If scripture requires more than one invoker var/multiple_invokers_optional = FALSE //If scripture can have multiple invokers to bolster its effects var/tier = SCRIPTURE_PERIPHERAL //The scripture's tier + var/sort_priority = 1 //what position the scripture should have in a list of scripture. Should be based off of component costs/reqs, but you can't initial() lists. //components the scripture used from a slab var/list/used_slab_components = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 0, "hierophant_ansible" = 0) @@ -194,6 +195,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed required_components = list("belligerent_eye" = 1) usage_tip = "Useful for crowd control in a populated area and disrupting mass movement." tier = SCRIPTURE_DRIVER + sort_priority = 1 /datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number) for(var/mob/living/carbon/C in hearers(7, invoker)) @@ -225,6 +227,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a judicial visor, which is capable of smiting the unworthy." usage_tip = "The visor has a thirty-second cooldown once used, and the marker it creates has a delay of 3 seconds before exploding." tier = SCRIPTURE_DRIVER + sort_priority = 2 @@ -238,6 +241,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed required_components = list("vanguard_cogwheel" = 1) usage_tip = "You cannot reactivate Vanguard while still shielded by it." tier = SCRIPTURE_DRIVER + sort_priority = 3 /datum/clockwork_scripture/vanguard/check_special_requirements() if(islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time) @@ -254,13 +258,14 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed /datum/clockwork_scripture/sentinels_compromise //Sentinel's Compromise: Allows the invoker to select a nearby servant convert their brute and burn damage into half as much toxin damage. descname = "Convert Brute/Burn to Half Toxin" name = "Sentinel's Compromise" - desc = "Heals all brute and burn damage on a nearby living, friendly servant, but deals 50% of that amount as toxin damage." + desc = "Heals all brute and burn damage on a nearby living, friendly servant, but deals 50% of the damage they had as toxin damage." invocations = list("Mend the wounds of...", "...my inferior flesh.") channel_time = 30 required_components = list("vanguard_cogwheel" = 2) consumed_components = list("vanguard_cogwheel" = 1) usage_tip = "The Compromise is very fast to invoke." tier = SCRIPTURE_DRIVER + sort_priority = 4 /datum/clockwork_scripture/sentinels_compromise/scripture_effects() var/list/nearby_cultists = list() @@ -303,6 +308,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed required_components = list("guvax_capacitor" = 1) usage_tip = "Only works on those in melee range and does not penetrate mindshield implants. Much more efficient than a Sigil of Submission at low Servant amounts." tier = SCRIPTURE_DRIVER + sort_priority = 5 /datum/clockwork_scripture/guvax/run_scripture() var/servants = 0 @@ -338,6 +344,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("guvax_capacitor" = 1) usage_tip = "Useful for fleeing attackers, as few will be able to follow someone using this scripture." tier = SCRIPTURE_DRIVER + sort_priority = 6 var/flee_time = 47 //allow fleeing for 5 seconds var/grace_period = 3 //very short grace period so you don't have to stop immediately var/datum/progressbar/progbar @@ -378,6 +385,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed whispered = TRUE usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components." tier = SCRIPTURE_DRIVER + sort_priority = 7 /datum/clockwork_scripture/replicant/scripture_effects() invoker << "You copy a piece of replicant alloy and command it into a new slab." //No visible message, for stealth purposes @@ -401,6 +409,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Slabs will draw components from the global cache after the slab's own repositories, making caches very efficient." tier = SCRIPTURE_DRIVER one_per_tile = TRUE + sort_priority = 8 /datum/clockwork_scripture/create_object/tinkerers_cache/New() var/cache_cost_increase = min(round(clockwork_caches*0.2), 5) @@ -426,6 +435,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a pair of wraith spectacles, which will grant true sight when worn." usage_tip = "\"True sight\" means that you are able to see through walls and in darkness." tier = SCRIPTURE_DRIVER + sort_priority = 9 @@ -443,6 +453,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "The sigil, while fairly powerful in its stun, does not induce muteness in its victim." tier = SCRIPTURE_DRIVER one_per_tile = TRUE + sort_priority = 10 ///////////// // SCRIPTS // @@ -462,6 +473,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Although powerful, the warden is very weak and should optimally be placed behind barricades." tier = SCRIPTURE_SCRIPT one_per_tile = TRUE + sort_priority = 11 /datum/clockwork_scripture/create_object/ocular_warden/check_special_requirements() for(var/obj/structure/destructible/clockwork/ocular_warden/W in range(3, invoker)) @@ -481,6 +493,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("guvax_capacitor" = 1, "hierophant_ansible" = 1) usage_tip = "If standing on a Sigil of Transmission, will transfer power to it. Augumented limbs will also be healed unless above a very high threshhold." tier = SCRIPTURE_SCRIPT + sort_priority = 20 var/total_power_drained = 0 var/power_damage_threshhold = 3000 var/augument_damage_threshhold = 6000 @@ -546,10 +559,12 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed var/mob/living/carbon/human/H = invoker for(var/X in H.bodyparts) var/obj/item/bodypart/BP = X - if(ratvar_awakens || BP.status == ORGAN_ROBOTIC && total_power_drained < augument_damage_threshhold) //if ratvar is alive, it won't damage and will always heal augumented limbs - BP.heal_damage(power_damage, power_damage, 1) //heals one point of burn and brute for every ~100W drained on augumented limbs + if(ratvar_awakens || BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold) //if ratvar is alive, it won't damage and will always heal augumented limbs + if(BP.heal_damage(power_damage, power_damage, 1, 0)) //heals one point of burn and brute for every ~100W drained on augumented limbs + H.update_damage_overlays() else - BP.take_damage(0, power_damage) + if(BP.take_damage(0, power_damage)) + H.update_damage_overlays() else if(isanimal(invoker)) var/mob/living/simple_animal/A = invoker A.adjustHealth(-power_damage) //if a simple animal is using volt void, just heal it @@ -570,6 +585,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a clockwork proselytizer, which is already pre-loaded with a small amount of replicant alloy." usage_tip = "Clockwork walls cause adjacent tinkerer's caches to generate components passively, making them a vital tool. Clockwork floors heal servants standing on them." tier = SCRIPTURE_SCRIPT + sort_priority = 17 @@ -586,6 +602,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed tier = SCRIPTURE_SCRIPT multiple_invokers_used = TRUE multiple_invokers_optional = TRUE + sort_priority = 14 /datum/clockwork_scripture/fellowship_armory/run_scripture() for(var/mob/living/L in range(1, invoker)) @@ -619,6 +636,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed whispered = TRUE usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear." tier = SCRIPTURE_SCRIPT + sort_priority = 18 /datum/clockwork_scripture/function_call/check_special_requirements() for(var/datum/action/innate/function_call/F in invoker.actions) @@ -647,6 +665,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed multiple_invokers_optional = TRUE usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal." tier = SCRIPTURE_SCRIPT + sort_priority = 19 /datum/clockwork_scripture/spatial_gateway/check_special_requirements() if(!isturf(invoker.loc)) @@ -690,6 +709,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness." usage_tip = "The vessel can be used as a teleport target for Spatial Gateway, though it is generally better-used by placing it in a shell." tier = SCRIPTURE_SCRIPT + sort_priority = 16 @@ -706,6 +726,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed observer_message = "The slab disgorges a puddle of black metal that contracts and forms into a strange shell!" usage_tip = "Useless without a soul vessel and should not be created without one." tier = SCRIPTURE_SCRIPT + sort_priority = 12 @@ -723,6 +744,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "This is not a primary conversion method - use Guvax for that. It is advantageous as a trap, however, as it will transmit the name of the newly-converted." tier = SCRIPTURE_SCRIPT one_per_tile = TRUE + sort_priority = 15 ////////////////// @@ -743,6 +765,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed observer_message = "The slab disgorges a puddle of black metal that expands and forms into a strange shell!" usage_tip = "Useless without a soul vessel and should not be created without one." tier = SCRIPTURE_APPLICATION + sort_priority = 25 @@ -762,6 +785,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "It will remain after converting a target, unless that target has a mindshield implant, which it will break to convert them, but consume itself in the process." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 22 @@ -779,6 +803,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Can be recharged by using Volt Void while standing on it." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 26 @@ -797,14 +822,15 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "To revive a servant, the sigil must have 20 vitality plus the target servant's non-oxygen damage. It will still heal dead servants if it lacks the vitality to outright revive them." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 23 /datum/clockwork_scripture/memory_allocation //Memory Allocation: Finds a willing ghost and makes them into a clockwork marauders for the invoker. descname = "Guardian" name = "Memory Allocation" - desc = "Allocates part of your consciousness to a Clockwork Marauder, a vigilent fighter similar to the alien holoparasites employed by the Syndicate; It lives within you, able to be \ + desc = "Allocates part of your consciousness to a Clockwork Marauder, a vigilent fighter that lives within you, able to be \ called forth by Speaking its True Name or if you become exceptionally low on health.
\ - Unlike holoparasites, however, it does not transfer the damage it takes to you, instead simply gaining Fatigue as it is attacked. Marauders cannot move too far from their hosts, \ + It gains Fatigue as it is attacked, weakening it. Marauders cannot move too far from their hosts, \ and will gain Fatigue at an increasing rate as they grow farther away. At maximum Fatigue, the marauder is forced to return to you and will be unable to manifest until its Fatigue is at zero." invocations = list("Fright's will...", "...call forth...") channel_time = 100 @@ -812,6 +838,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "guvax_capacitor" = 2) usage_tip = "Marauders are useful as personal bodyguards and frontline warriors, although they do little damage." tier = SCRIPTURE_APPLICATION + sort_priority = 24 /datum/clockwork_scripture/memory_allocation/check_special_requirements() for(var/mob/living/simple_animal/hostile/clockwork/marauder/M in living_mob_list) @@ -882,6 +909,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "If it fails to funnel power into a nearby Sigil of Transmission and fails to disable even one thing, it will disable itself for two minutes." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 29 @@ -901,6 +929,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Powerful healing but power use is very inefficient, and its alloy use is little better." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 27 @@ -920,6 +949,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks recieve double duration and uses." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 30 @@ -939,13 +969,14 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Eligible human servants next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby servants." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE + sort_priority = 28 /datum/clockwork_scripture/create_object/tinkerers_daemon //Tinkerer's Daemon: Creates a shell that can be attached to a tinkerer's cache to grant it passive component creation. descname = "Component Generator" name = "Tinkerer's Daemon" - desc = "Forms a daemon shell that can be attached to a tinkerer's cache to add new components at a healthy rate. It will only function if it is outnumbered by servants in a ratio of 5:1." + desc = "Forms a daemon shell that can be attached to a tinkerer's cache to add new components at a healthy rate. It will only function if it is outnumbered by servants by a ratio of 5:1." invocations = list("Collect Engine parts...", "...that yet hold greatness!") channel_time = 80 required_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3) @@ -954,6 +985,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a daemon shell. Attach it to a tinkerer's cache to increase its rate of production." usage_tip = "Vital to your success!" tier = SCRIPTURE_APPLICATION + sort_priority = 21 /datum/clockwork_scripture/create_object/tinkerers_daemon/check_special_requirements() var/servants = 0 @@ -985,6 +1017,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \ and interdiction lenses, mending motors, mania motors, and clockwork obelisks will all require no power." tier = SCRIPTURE_REVENANT + sort_priority = 33 /datum/clockwork_scripture/invoke_nezbere/check_special_requirements() if(!slab.no_cost && clockwork_generals_invoked["nezbere"] > world.time) @@ -1036,6 +1069,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 6, "hierophant_ansible" = 3) usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts." tier = SCRIPTURE_REVENANT + sort_priority = 32 invokers_required = 3 multiple_invokers_used = TRUE var/list/mindbreaksayings = list("\"Oh, great. I get to shatter some minds.\"", "\"More minds to crush.\"", \ @@ -1106,6 +1140,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("belligerent_eye" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 6) usage_tip = "Struck targets will also be knocked down for about sixteen seconds." tier = SCRIPTURE_REVENANT + sort_priority = 34 /datum/clockwork_scripture/invoke_nzcrentr/check_special_requirements() if(!slab.no_cost && clockwork_generals_invoked["nzcrentr"] > world.time) @@ -1167,6 +1202,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("vanguard_cogwheel" = 6, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3) usage_tip = "Those affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity." tier = SCRIPTURE_REVENANT + sort_priority = 31 var/total_duration = 150 /datum/clockwork_scripture/invoke_inathneq/check_special_requirements() @@ -1207,6 +1243,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \ as well as being loud enough to be heard throughout the entire sector. Defend it with your life!" tier = SCRIPTURE_JUDGEMENT + sort_priority = 35 /datum/clockwork_scripture/ark_of_the_clockwork_justiciar/New() if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY) diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm index 83477d09822..ca63657de88 100644 --- a/code/game/gamemodes/clock_cult/clock_structures.dm +++ b/code/game/gamemodes/clock_cult/clock_structures.dm @@ -711,10 +711,10 @@ color = "#FAE48C" /obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L) - var/target_flashed = L.flash_eyes() + var/target_flashed = L.flash_act() for(var/mob/living/M in viewers(5, src)) if(!is_servant_of_ratvar(M) && M != L) - M.flash_eyes() + M.flash_act() if(iscultist(L)) L << "\"Watch your step, wretch.\"" L.adjustBruteLoss(10) diff --git a/code/game/gamemodes/clock_cult/clock_unsorted.dm b/code/game/gamemodes/clock_cult/clock_unsorted.dm index 3e0dcf8dca6..2b775f76678 100644 --- a/code/game/gamemodes/clock_cult/clock_unsorted.dm +++ b/code/game/gamemodes/clock_cult/clock_unsorted.dm @@ -61,7 +61,7 @@ return ..() /datum/action/innate/function_call/Activate() - if(owner.l_hand && owner.r_hand) + if(!owner.get_empty_held_indexes()) usr << "You need an empty to hand to call forth your spear!" return 0 owner.visible_message("A strange spear materializes in [owner]'s hands!", "You call forth your spear!") @@ -114,7 +114,7 @@ return 0 var/input_target_key = input(invoker, "Choose a target to form a rift to.", "Spatial Gateway") as null|anything in possible_targets var/atom/movable/target = possible_targets[input_target_key] - if(!src || !target || !invoker || !invoker.canUseTopic(src, BE_CLOSE) || !is_servant_of_ratvar(invoker) || (istype(src, /obj/item) && invoker.get_active_hand() != src)) + if(!src || !target || !invoker || !invoker.canUseTopic(src, BE_CLOSE) || !is_servant_of_ratvar(invoker) || (istype(src, /obj/item) && invoker.get_active_held_item() != src)) return 0 //if any of the involved things no longer exist, the invoker is stunned, too far away to use the object, or does not serve ratvar, or if the object is an item and not in the mob's active hand, fail var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) if(istargetobelisk) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 6847906410c..b80a7e692ea 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -139,9 +139,7 @@ var/list/slots = list( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, + "right pocket" = slot_r_store ) var/T = new item_path(mob) @@ -152,7 +150,6 @@ return 0 else mob << "You have a [item_name] in your [where]." - mob.update_icons() if(where == "backpack") var/obj/item/weapon/storage/B = mob.back B.orient2hud(mob) diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index accff66ebdd..13f1c4acf2a 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -30,9 +30,9 @@ if(!user) return if(!ishuman(user)) - user.say(message) + user.say(html_decode(message)) else - user.whisper(message) + user.whisper(html_decode(message)) var/my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [user]: [message]" for(var/mob/M in mob_list) if(iscultist(M)) diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index fb375070f9d..92922f8e5ba 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -34,7 +34,7 @@ This file contains the arcane tome files. M.reagents.add_reagent("unholywater",holy2unholy) add_logs(user, M, "smacked", src, " removing the holy water from them") return - M.take_organ_damage(0, 15) //Used to be a random between 5 and 20 + M.take_bodypart_damage(0, 15) //Used to be a random between 5 and 20 playsound(M, 'sound/weapons/sear.ogg', 50, 1) M.visible_message("[user] strikes [M] with the arcane tome!", \ "[user] strikes you with the tome, searing your flesh!") diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 27d06fef206..0b69fc9baba 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -177,7 +177,7 @@ structure_check() searches for nearby cultist structures required for the invoca /mob/proc/bible_check() //The bible, if held, might protect against certain things var/obj/item/weapon/storage/book/bible/B = locate() in src - if(B && (l_hand == B || r_hand == B)) + if(is_holding(B)) return B return 0 diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 08e09f57fcb..93a2cb6e18a 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -253,7 +253,7 @@ else target.Weaken(10) target.Stun(10) - target.flash_eyes(1,1) + target.flash_act(1,1) if(issilicon(target)) var/mob/living/silicon/S = target S.emp_act(1) @@ -316,7 +316,7 @@ target << "You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart." target.emote("scream") target.confused = max(0, target.confused + 3) - target.flash_eyes() + target.flash_act() qdel(src) diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm index a99c95801d1..22bb549558d 100644 --- a/code/game/gamemodes/devil/true_devil/_true_devil.dm +++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm @@ -22,13 +22,20 @@ mob_size = MOB_SIZE_LARGE var/mob/living/oldform var/list/devil_overlays[DEVIL_TOTAL_LAYERS] + bodyparts = list(/obj/item/bodypart/chest/devil, /obj/item/bodypart/head/devil, /obj/item/bodypart/l_arm/devil, + /obj/item/bodypart/r_arm/devil, /obj/item/bodypart/r_leg/devil, /obj/item/bodypart/l_leg/devil) + + /mob/living/carbon/true_devil/New() - internal_organs += new /obj/item/organ/brain/ + create_bodyparts() //initialize bodyparts + + create_internal_organs() + ..() + +/mob/living/carbon/true_devil/create_internal_organs() + internal_organs += new /obj/item/organ/brain internal_organs += new /obj/item/organ/tongue - for(var/X in internal_organs) - var/obj/item/organ/I = X - I.Insert(src) ..() @@ -51,8 +58,7 @@ /mob/living/carbon/true_devil/death(gibbed) stat = DEAD ..(gibbed) - drop_l_hand() - drop_r_hand() + drop_all_held_items() spawn (0) mind.devilinfo.beginResurrectionCheck(src) @@ -61,18 +67,12 @@ var/msg = "*---------*\nThis is \icon[src] [src]!\n" //Left hand items - if(l_hand && !(l_hand.flags&ABSTRACT)) - if(l_hand.blood_DNA) - msg += "It is holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in its left hand!\n" - else - msg += "It is holding \icon[l_hand] \a [l_hand] in its left hand.\n" - - //Right hand items - if(r_hand && !(r_hand.flags&ABSTRACT)) - if(r_hand.blood_DNA) - msg += "It is holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in its right hand!\n" - else - msg += "It is holding \icon[r_hand] \a [r_hand] in its right hand.\n" + for(var/obj/item/I in held_items) + if(!(I.flags & ABSTRACT)) + if(I.blood_DNA) + msg += "It is holding \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n" + else + msg += "It is holding \icon[I] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n" //Braindead if(!client && stat != DEAD) @@ -102,11 +102,17 @@ /mob/living/carbon/true_devil/assess_threat() return 666 -/mob/living/carbon/true_devil/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0) +/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0) if(mind && has_bane(BANE_LIGHT)) mind.disrupt_spells(-500) return ..() //flashes don't stop devils UNLESS it's their bane. +/mob/living/carbon/true_devil/soundbang_act() + return 0 + +/mob/living/carbon/true_devil/get_ear_protection() + return 2 + /mob/living/carbon/true_devil/attacked_by(obj/item/I, mob/living/user, def_zone) var/weakness = check_weakness(I, user) @@ -127,9 +133,6 @@ "[attack_message]") return TRUE -/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity) - A.attack_hand(src) - /mob/living/carbon/true_devil/Process_Spacemove(movement_dir = 0) return 1 @@ -207,4 +210,14 @@ if(has_bane(BANE_LIGHT)) b_loss *=2 adjustBruteLoss(b_loss) - return ..() \ No newline at end of file + return ..() + + +/mob/living/carbon/true_devil/update_body() //we don't use the bodyparts layer for devils. + return + +/mob/living/carbon/true_devil/update_body_parts() + return + +/mob/living/carbon/true_devil/update_damage_overlays() //devils don't have damage overlays. + return \ No newline at end of file diff --git a/code/game/gamemodes/devil/true_devil/inventory.dm b/code/game/gamemodes/devil/true_devil/inventory.dm index 020d48c98de..ca417e09fbf 100644 --- a/code/game/gamemodes/devil/true_devil/inventory.dm +++ b/code/game/gamemodes/devil/true_devil/inventory.dm @@ -4,10 +4,12 @@ return 1 return 0 -/mob/living/carbon/true_devil/proc/update_inv_hands() +/mob/living/carbon/true_devil/update_inv_hands() //TODO LORDPIDEY: Figure out how to make the hands line up properly. the l/r_hand_image should use the down sprite when facing down, left, or right, and the up sprite when facing up. remove_overlay(DEVIL_HANDS_LAYER) var/list/hands_overlays = list() + var/obj/item/l_hand = get_item_for_held_index(1) //hardcoded 2-hands only, for now. + var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) @@ -21,7 +23,7 @@ if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) r_hand.layer = ABOVE_HUD_LAYER - r_hand.screen_loc = ui_rhand + r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand)) client.screen |= r_hand if(l_hand) @@ -36,19 +38,12 @@ if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) l_hand.layer = ABOVE_HUD_LAYER - l_hand.screen_loc = ui_lhand + l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand)) client.screen |= l_hand if(hands_overlays.len) devil_overlays[DEVIL_HANDS_LAYER] = hands_overlays apply_overlay(DEVIL_HANDS_LAYER) -/mob/living/carbon/true_devil/update_inv_l_hand() - update_inv_hands() - - -/mob/living/carbon/true_devil/update_inv_r_hand() - update_inv_hands() - /mob/living/carbon/true_devil/remove_overlay(cache_index) if(devil_overlays[cache_index]) overlays -= devil_overlays[cache_index] diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 09ca3b85fab..b96e2ee6697 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -283,7 +283,7 @@ intercepttext += i_text.build(V) if(station_goals.len) - intercepttext += "Special Orders for [station_name()]:" + intercepttext += "
Special Orders for [station_name()]:" for(var/datum/station_goal/G in station_goals) G.on_report() intercepttext += G.get_report() diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index 64f0ef08d70..eefbf5689f1 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -115,9 +115,7 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple" var/list/slots = list ( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, + "right pocket" = slot_r_store ) . = 0 @@ -151,7 +149,6 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple" . += 1 else mob << "The chameleon security HUD in your [where4] will help you keep track of who is mindshield-implanted, and unable to be recruited." - mob.update_icons() return . @@ -169,7 +166,7 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple" if(iscarbon(gangster_mind.current)) var/mob/living/carbon/carbon_mob = gangster_mind.current carbon_mob.silent = max(carbon_mob.silent, 5) - carbon_mob.flash_eyes(1, 1) + carbon_mob.flash_act(1, 1) gangster_mind.current.Stun(5) gangster_mind.current << "You are now a member of the [G.name] Gang!" gangster_mind.current << "Help your bosses take over the station by claiming territory with special spraycans only they can provide. Simply spray on any unclaimed area of the station." diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 20f9b61d014..116d910e056 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -59,8 +59,7 @@ M.icon = disguise.icon M.icon_state = disguise.icon_state M.overlays = disguise.overlays - M.update_inv_r_hand() - M.update_inv_l_hand() + M.update_inv_hands() /obj/item/clothing/suit/armor/abductor/vest/proc/DeactivateStealth() if(!stealth_active) @@ -460,11 +459,11 @@ Congratulations! You are now trained for xenobiology research!"} return var/mob/living/carbon/C = L if(!C.handcuffed) - if(C.get_num_arms() >= 2) + if(C.get_num_arms() >= 2 || C.get_arm_ignore()) playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2) C.visible_message("[user] begins restraining [C] with [src]!", \ "[user] begins shaping an energy field around your hands!") - if(do_mob(user, C, 30) && C.get_num_arms() >= 2) + if(do_mob(user, C, 30) && (C.get_num_arms() >= 2 || C.get_arm_ignore())) if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/restraints/handcuffs/energy/used(C) C.update_handcuffed() diff --git a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm index 30f7d7c10e7..d095f67df43 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm @@ -23,9 +23,9 @@ var/list/organ_types = list(/obj/item/organ/heart) /datum/surgery_step/extract_organ/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - for(var/obj/item/I in target.internal_organs) - if(I.type in organ_types) - IC = I + for(var/atom/A in target.internal_organs) + if(A.type in organ_types) + IC = A break user.visible_message("[user] starts to remove [target]'s organs.", "You start to remove [target]'s organs...") diff --git a/code/game/gamemodes/miniantags/abduction/machinery/console.dm b/code/game/gamemodes/miniantags/abduction/machinery/console.dm index 55802fa7e17..7dfbb31daca 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/console.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/console.dm @@ -173,7 +173,7 @@ entry.name = target.name entry.icon = target.icon entry.icon_state = target.icon_state - entry.overlays = target.get_overlays_copy(list(L_HAND_LAYER,R_HAND_LAYER)) + entry.overlays = target.get_overlays_copy(list(HANDS_LAYER)) for(var/i=1,i<=disguises.len,i++) var/datum/icon_snapshot/temp = disguises[i] if(temp.name == entry.name) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 68449ba4317..56bc184a7d8 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -66,7 +66,7 @@ if(eyes_s) photo.Blend(eyes_s, ICON_OVERLAY) - var/icon/splat = icon("icon" = 'icons/mob/dam_human.dmi',"icon_state" = "chest30") + var/icon/splat = icon("icon" = 'icons/mob/dam_mob.dmi',"icon_state" = "chest30") photo.Blend(splat,ICON_OVERLAY) return photo diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 1aded1d6205..0270d153573 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -110,7 +110,7 @@ synd_mind.current << "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it." var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge - synd_mind.current.equip_to_slot_or_del(challenge, slot_r_hand) + synd_mind.current.put_in_hands_or_del(challenge) var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/weapon/card/id) if(foundIDs.len) @@ -130,7 +130,7 @@ P.name = "nuclear bomb code" var/mob/living/carbon/human/H = synd_mind.current P.loc = H.loc - H.equip_to_slot_or_del(P, slot_r_hand, 0) + H.put_in_hands_or_del(P) H.update_icons() else nuke_code = "code will be provided later" diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 88aed68a67e..98d0f963433 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -291,7 +291,7 @@ var/bomb_set . = TRUE if("insert_disk") if(!auth) - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/disk/nuclear)) usr.drop_item() I.forceMove(src) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 2310d97b66e..8fd17b07c30 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -528,13 +528,13 @@ var/global/list/possible_items = list() /datum/objective/steal/give_special_equipment() if(owner && owner.current && targetinfo) - if(istype(owner.current, /mob/living/carbon/human)) + if(ishuman(owner.current)) var/mob/living/carbon/human/H = owner.current var/list/slots = list ("backpack" = slot_in_backpack) for(var/eq_path in targetinfo.special_equipment) var/obj/O = new eq_path H.equip_in_one_of_slots(O, slots) - H.update_icons() + var/global/list/possible_items_special = list() /datum/objective/steal/special //ninjas are so special they get their own subtype good for them diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index a30b1c2f281..b67617ae380 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -137,16 +137,12 @@ var/list/slots = list ( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, + "right pocket" = slot_r_store ) var/where = mob.equip_in_one_of_slots(T, slots) var/where2 = mob.equip_in_one_of_slots(C, slots) mob.equip_in_one_of_slots(R,slots) - mob.update_icons() - if (!where2) mob << "The Syndicate were unfortunately unable to get you a chameleon security HUD." else @@ -250,7 +246,7 @@ if(iscarbon(rev_mind.current)) var/mob/living/carbon/carbon_mob = rev_mind.current carbon_mob.silent = max(carbon_mob.silent, 5) - carbon_mob.flash_eyes(1, 1) + carbon_mob.flash_act(1, 1) rev_mind.current.Stun(5) rev_mind.current << " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" rev_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the revolution!" diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index a88b2735153..29d8e89c86b 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -367,9 +367,7 @@ var/list/slots = list ( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, + "right pocket" = slot_r_store ) var/where = "At your feet" @@ -377,7 +375,6 @@ if (equipped_slot) where = "In your [equipped_slot]" mob << "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
" - mob.update_icons() /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 1a41e73ef7c..75b44b7edc9 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -191,8 +191,8 @@ H.equip_to_slot_or_del(new hat(H), slot_head) H.equip_to_slot_or_del(new /obj/item/clothing/under/roman(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/shield/riot/roman(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/weapon/claymore(H), slot_r_hand) + H.put_in_hands_or_del(new /obj/item/weapon/shield/riot/roman(H)) + H.put_in_hands_or_del(new /obj/item/weapon/claymore(H)) H.equip_to_slot_or_del(new /obj/item/weapon/twohanded/spear(H), slot_back) @@ -337,15 +337,15 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/really_black(M), slot_w_uniform) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("roman") var/hat = pick(/obj/item/clothing/head/helmet/roman, /obj/item/clothing/head/helmet/roman/legionaire) M.equip_to_slot_or_del(new hat(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/under/roman(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/weapon/shield/riot/roman(M), slot_l_hand) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(new /obj/item/weapon/shield/riot/roman(M)) + M.put_in_hands_or_del(sword) if("wizard") M.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(M), slot_w_uniform) @@ -353,13 +353,13 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(M), slot_head) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("cyborg") for(var/X in M.bodyparts) var/obj/item/bodypart/affecting = X - affecting.change_bodypart_status(ORGAN_ROBOTIC) + affecting.change_bodypart_status(BODYPART_ROBOTIC) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("syndicate") M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(M), slot_w_uniform) @@ -369,34 +369,34 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M),slot_wear_mask) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("assistant") M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(M), slot_shoes) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("animu") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/head/kitty(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/under/schoolgirl/red(M), slot_w_uniform) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("cultist") M.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("highlander") M.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/head/beret(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("clown") M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) @@ -404,7 +404,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_l_store) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("killer") M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform) @@ -416,7 +416,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/kitchen/knife(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/scalpel(M), slot_r_store) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) for(var/obj/item/carried_item in M.contents) if(!istype(carried_item, /obj/item/weapon/implant)) carried_item.add_mob_blood(M) @@ -427,7 +427,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/clothing/head/bandana(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("soviet") M.equip_to_slot_or_del(new /obj/item/clothing/head/pirate/captain(M), slot_head) @@ -436,7 +436,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/suit/pirate/captain(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("officer") M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/beret(M), slot_head) @@ -447,20 +447,19 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(new /obj/item/clothing/suit/jacket/miljacket(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) if("gladiator") M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/gladiator(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/under/gladiator(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) - M.equip_to_slot_or_del(sword, slot_r_hand) + M.put_in_hands_or_del(sword) else return - M.update_icons() M.update_body_parts() var/obj/item/weapon/card/id/W = new /obj/item/weapon/card/id diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index 870854fa3eb..4805c884929 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -47,7 +47,7 @@ for(var/datum/mind/wizard in wizards) if(!istype(wizard.current,/mob/living/carbon)) continue - if(istype(wizard.current,/mob/living/carbon/brain)) + if(istype(wizard.current,/mob/living/brain)) continue if(wizard.current.stat==DEAD) continue diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index c5d4cba9a86..ceb75c29c09 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -137,7 +137,9 @@ qdel(wizard_mob.wear_suit) qdel(wizard_mob.head) qdel(wizard_mob.shoes) - qdel(wizard_mob.r_hand) + for(var/obj/item/I in wizard_mob.held_items) + wizard_mob.unEquip(I) + qdel(I) qdel(wizard_mob.r_store) qdel(wizard_mob.l_store) @@ -152,13 +154,12 @@ wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) var/obj/item/weapon/spellbook/spellbook = new /obj/item/weapon/spellbook(wizard_mob) spellbook.owner = wizard_mob - wizard_mob.equip_to_slot_or_del(spellbook, slot_r_hand) + wizard_mob.put_in_hands_or_del(spellbook) wizard_mob << "You will find a list of available spells in your spell book. Choose your magic arsenal carefully." wizard_mob << "The spellbook is bound to you, and others cannot use it." wizard_mob << "In your pockets you will find a teleport scroll. Use it as needed." wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") - wizard_mob.update_icons() return 1 diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 1de445383b1..fd21d4a3826 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -51,7 +51,7 @@ user << "There is already a PDA inside!" return else - var/obj/item/device/pda/P = user.get_active_hand() + var/obj/item/device/pda/P = user.get_active_held_item() if(istype(P)) if(!user.drop_item()) return diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 165f8e21e07..45934d85022 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -169,9 +169,9 @@ var/list/unclean_mutations = (not_good_mutations|bad_mutations) H.dna.remove_mutation_group(unclean_mutations) if(efficiency > 5 && prob(20)) - randmutvg(H) + H.randmutvg() if(efficiency < 3 && prob(50)) - var/mob/M = randmutb(H) + var/mob/M = H.randmutb() if(ismob(M)) H = M @@ -325,7 +325,7 @@ if (mess) //Clean that mess and dump those gibs! mess = FALSE - gibs(loc) + new /obj/effect/gibspawner/generic(loc) audible_message("You hear a splat.") icon_state = "pod_0" return @@ -338,7 +338,7 @@ occupant.grab_ghost() occupant << "There is a bright flash!
\ You feel like a new being.
" - occupant.flash_eyes() + occupant.flash_act() var/turf/T = get_turf(src) occupant.forceMove(T) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 7ca75a4bb69..59bff85af25 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -498,7 +498,7 @@ M.hallucination += 30 else usr << "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there..." - M.take_organ_damage(30) + M.take_bodypart_damage(30) playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1) if(ORION_TRAIL_ILLNESS) var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS @@ -516,7 +516,7 @@ if(prob(75)) M.Weaken(3) say("A sudden gust of powerful wind slams [M] into the floor!") - M.take_organ_damage(25) + M.take_bodypart_damage(25) playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1) else M << "A violent gale blows past you, and you barely manage to stay standing!" diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 3413b500502..ba4fbd860ee 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -315,7 +315,7 @@ var/time_last_changed_position = 0 region_access = null head_subordinates = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if (istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return @@ -329,7 +329,7 @@ var/time_last_changed_position = 0 scan.verb_pickup() scan = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if (istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 4641811b75a..0ad5c1ef21e 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -270,7 +270,7 @@ src.menu = 4 else if (src.menu == 4) - var/obj/item/weapon/card/id/C = usr.get_active_hand() + var/obj/item/weapon/card/id/C = usr.get_active_held_item() if (istype(C)||istype(C, /obj/item/device/pda)) if(src.check_access(C)) src.temp = "[src.active_record.fields["name"]] => Record deleted." diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index e55635d45e2..8713750077a 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -64,7 +64,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 src.state = STATE_DEFAULT if("login") var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() + var/obj/item/weapon/card/id/I = M.get_active_held_item() if (istype(I, /obj/item/device/pda)) var/obj/item/device/pda/pda = I I = pda.id @@ -82,7 +82,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 if("swipeidseclevel") var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() + var/obj/item/weapon/card/id/I = M.get_active_held_item() if (istype(I, /obj/item/device/pda)) var/obj/item/device/pda/pda = I I = pda.id diff --git a/code/game/machinery/computer/gulag_teleporter.dm b/code/game/machinery/computer/gulag_teleporter.dm index 62e3bf6e75e..6f2e6b0d56b 100644 --- a/code/game/machinery/computer/gulag_teleporter.dm +++ b/code/game/machinery/computer/gulag_teleporter.dm @@ -91,14 +91,14 @@ beacon = findbeacon() if("handle_id") if(id) - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr.put_in_hands(id) id = null else id.forceMove(get_turf(src)) id = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/card/id/prisoner)) if(!usr.drop_item()) return diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 9b816e672f2..62c7230851b 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -212,13 +212,13 @@ src.temp = null if(href_list["scan"]) if(src.scan) - if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_held_item()) usr.put_in_hands(scan) else scan.loc = get_turf(src) src.scan = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index 8a837a5af5a..8502e90f4f5 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -93,7 +93,7 @@ if(href_list["id"]) if(href_list["id"] =="insert" && !inserted_id) - var/obj/item/weapon/card/id/prisoner/I = usr.get_active_hand() + var/obj/item/weapon/card/id/prisoner/I = usr.get_active_held_item() if(istype(I)) if(!usr.drop_item()) return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index eaebcd0ac80..d1b5a3e5baa 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -295,13 +295,13 @@ What a mess.*/ if("Confirm Identity") if(scan) - if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_held_item()) usr.put_in_hands(scan) else scan.loc = get_turf(src) scan = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return @@ -740,8 +740,8 @@ What a mess.*/ if(selection) P = new() P.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"]) - else if(istype(user.get_active_hand(), /obj/item/weapon/photo)) - P = user.get_active_hand() + else if(istype(user.get_active_held_item(), /obj/item/weapon/photo)) + P = user.get_active_held_item() return P /obj/machinery/computer/secure_data/emp_act(severity) diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index dd535921ff4..abba2eb90ce 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -34,7 +34,7 @@ var/list/possible_uplinker_IDs = list("Alfa","Bravo","Charlie","Delta","Echo","F user << "The [src] already has an uplink in it." return if(O.hidden_uplink) - var/obj/item/I = user.get_active_hand() + var/obj/item/I = user.get_active_held_item() if(!user.drop_item()) return uplinkholder = I diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 224d5e23110..89e3a0ffdb4 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -611,11 +611,9 @@ var/list/airlock_overlays = list() if(!istype(H.head, /obj/item/clothing/head/helmet)) H.visible_message("[user] headbutts the airlock.", \ "You headbutt the airlock!") - var/obj/item/bodypart/affecting = H.get_bodypart("head") H.Stun(5) H.Weaken(5) - if(affecting && affecting.take_damage(10, 0)) - H.update_damage_overlays(0) + H.apply_damage(10, BRUTE, "head") else visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.") return diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index e1b6209fed9..3dbeadfd33d 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -114,7 +114,7 @@ if (get_dist(src, L) > range) continue - if(L.flash_eyes(affect_silicon = 1)) + if(L.flash_act(affect_silicon = 1)) L.Weaken(strength) if(L.weakeyes) L.Weaken(strength * 1.5) diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm index 47dbfd4e80b..cedab21e73e 100644 --- a/code/game/machinery/gulag_item_reclaimer.dm +++ b/code/game/machinery/gulag_item_reclaimer.dm @@ -81,14 +81,14 @@ switch(action) if("handle_id") if(inserted_id) - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr.put_in_hands(inserted_id) inserted_id = null else inserted_id.forceMove(get_turf(src)) inserted_id = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/card/id/prisoner)) if(!usr.drop_item()) return diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 359893bdbb6..bf6a43b8d6c 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -791,8 +791,8 @@ var/list/obj/machinery/newscaster/allCasters = list() else qdel(photo) photo = null - if(istype(user.get_active_hand(), /obj/item/weapon/photo)) - photo = user.get_active_hand() + if(istype(user.get_active_held_item(), /obj/item/weapon/photo)) + photo = user.get_active_held_item() if(!user.drop_item()) return photo.loc = src diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index c76ef4b40ef..e482fa45c3f 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -548,10 +548,7 @@ if(allowed(perp) && !lasercolor) //if the perp has security access, return 0 return 0 - if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/revolver/doublebarrel)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) - threatcount += 4 - - if((istype(perp.r_hand, /obj/item/weapon/gun) && !istype(perp.r_hand, /obj/item/weapon/gun/projectile/revolver/doublebarrel)) || istype(perp.r_hand, /obj/item/weapon/melee/baton)) + if(perp.is_holding_item_of_type(/obj/item/weapon/gun) || perp.is_holding_item_of_type(/obj/item/weapon/melee/baton)) threatcount += 4 if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee/baton)) @@ -561,7 +558,7 @@ threatcount = 0 //But does not target anyone else if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) threatcount += 4 - if(istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag) || istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag)) + if(perp.is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag)) threatcount += 4 if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag)) threatcount += 2 @@ -570,7 +567,7 @@ threatcount = 0 if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) threatcount += 4 - if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + if(perp.is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag)) threatcount += 4 if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) threatcount += 2 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 12f665fa17c..32c60b66759 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -134,7 +134,7 @@ var/mob/living/silicon/robot/R = occupant restock_modules() if(repairs) - R.heal_organ_damage(repairs, repairs - 1) + R.heal_bodypart_damage(repairs, repairs - 1) if(R.cell) R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge) diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index 3b9c43beb80..47f7fe8a043 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -6,7 +6,7 @@ anchored = 1 var/metal_amount = 0 var/operating = 0 - var/obj/item/robot_parts/being_built = null + var/obj/item/being_built = null use_power = 1 idle_power_usage = 20 active_power_usage = 5000 @@ -90,37 +90,37 @@ Please wait until completion...
switch (part_type) if (1) - build_type = "/obj/item/robot_parts/l_arm" + build_type = "/obj/item/bodypart/l_arm/robot" build_time = 200 build_cost = 10000 if (2) - build_type = "/obj/item/robot_parts/r_arm" + build_type = "/obj/item/bodypart/r_arm/robot" build_time = 200 build_cost = 10000 if (3) - build_type = "/obj/item/robot_parts/l_leg" + build_type = "/obj/item/bodypart/l_leg/robot" build_time = 200 build_cost = 10000 if (4) - build_type = "/obj/item/robot_parts/r_leg" + build_type = "/obj/item/bodypart/r_leg/robot" build_time = 200 build_cost = 10000 if (5) - build_type = "/obj/item/robot_parts/chest" + build_type = "/obj/item/bodypart/chest/robot" build_time = 350 build_cost = 40000 if (6) - build_type = "/obj/item/robot_parts/head" + build_type = "/obj/item/bodypart/head/robot" build_time = 350 build_cost = 5000 if (7) - build_type = "/obj/item/robot_parts/robot_suit" + build_type = "/obj/item/robot_suit" build_time = 600 build_cost = 15000 @@ -146,6 +146,4 @@ Please wait until completion...
src.overlays -= "fab-active" return - for (var/mob/M in viewers(1, src)) - if (M.client && M.machine == src) - src.attack_hand(M) + updateUsrDialog() diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 4c930c8326a..4f2ab34d4cb 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -147,7 +147,7 @@ return else // insert cell - var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand() + var/obj/item/weapon/stock_parts/cell/C = usr.get_active_held_item() if(istype(C)) if(!user.drop_item()) return diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm index 61598ca32bc..478ef77fe6f 100644 --- a/code/game/machinery/telecomms/computers/logbrowser.dm +++ b/code/game/machinery/telecomms/computers/logbrowser.dm @@ -72,7 +72,7 @@ var/language = "Human" // MMIs, pAIs, Cyborgs and humans all speak Human var/mobtype = C.parameters["mobtype"] - var/list/humans = typesof(/mob/living/carbon/human, /mob/living/carbon/brain) + var/list/humans = typesof(/mob/living/carbon/human, /mob/living/brain) var/list/monkeys = typesof(/mob/living/carbon/monkey) var/list/silicons = typesof(/mob/living/silicon) var/list/slimes = typesof(/mob/living/simple_animal/slime) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index fcc819ba72a..90986ffcdff 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -44,7 +44,7 @@ // You need a multitool to use this, or be silicon if(!issilicon(user)) // istype returns false if the value is null - if(!istype(user.get_active_hand(), /obj/item/device/multitool)) + if(!istype(user.get_active_held_item(), /obj/item/device/multitool)) return if(stat & (BROKEN|NOPOWER)) @@ -133,14 +133,14 @@ var/obj/item/device/multitool/P = null // Let's double check - if(!issilicon(user) && istype(user.get_active_hand(), /obj/item/device/multitool)) - P = user.get_active_hand() + if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/device/multitool)) + P = user.get_active_held_item() else if(isAI(user)) var/mob/living/silicon/ai/U = user P = U.aiMulti else if(isrobot(user) && in_range(user, src)) - if(istype(user.get_active_hand(), /obj/item/device/multitool)) - P = user.get_active_hand() + if(istype(user.get_active_held_item(), /obj/item/device/multitool)) + P = user.get_active_held_item() return P // Additional Options for certain machines. Use this when you want to add an option to a specific machine. @@ -209,7 +209,7 @@ return if(!issilicon(usr)) - if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) + if(!istype(usr.get_active_held_item(), /obj/item/device/multitool)) return var/obj/item/device/multitool/P = get_multitool(usr) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index cbe9df81329..95e8c2d397c 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -426,7 +426,7 @@ return coin.loc = loc - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr.put_in_hands(coin) usr << "You remove [coin] from [src]." coin = null diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 36239710c46..af916014ca2 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -343,7 +343,7 @@ mechsyringe.icon = initial(mechsyringe.icon) mechsyringe.reagents.reaction(M, INJECT) mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) - M.take_organ_damage(2) + M.take_bodypart_damage(2) add_logs(originaloccupant, M, "shot", "syringegun") break else if(mechsyringe.loc == trg) diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 6ec06406b81..37bde068e28 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -83,13 +83,11 @@ add_logs(user, target, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") if(ishuman(target)) var/mob/living/carbon/human/H = target - var/obj/item/bodypart/affecting = H.get_bodypart("chest") - affecting.take_damage(drill_damage) - H.update_damage_overlays(0) + H.apply_damage(drill_damage, BRUTE, "chest") else if(target.stat == DEAD && target.butcher_results) target.harvest(chassis) // Butcher the mob with our drill. else - target.take_organ_damage(drill_damage) + target.take_bodypart_damage(drill_damage) if(target) target.Paralyse(10) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 2a15a49fdac..6a04670188a 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -845,7 +845,7 @@ else if(occupant) user << "Occupant detected!" return 0 - else if(dna_lock && (!mmi_as_oc.brainmob.dna || dna_lock!=mmi_as_oc.brainmob.dna.unique_enzymes)) + else if(dna_lock && (!mmi_as_oc.brainmob.stored_dna || dna_lock!=mmi_as_oc.brainmob.stored_dna.unique_enzymes)) user << "Access denied. [name] is secured with a DNA lock." return 0 @@ -905,8 +905,8 @@ if(ishuman(occupant)) mob_container = occupant RemoveActions(occupant, human_occupant=1) - else if(istype(occupant, /mob/living/carbon/brain)) - var/mob/living/carbon/brain/brain = occupant + else if(istype(occupant, /mob/living/brain)) + var/mob/living/brain/brain = occupant RemoveActions(brain) mob_container = brain.container else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf. diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm index 36bf7577bb1..a0e5d4a3dc3 100644 --- a/code/game/objects/effects/decals/Cleanable/aliens.dm +++ b/code/game/objects/effects/decals/Cleanable/aliens.dm @@ -21,18 +21,21 @@ return ..() /obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions) - spawn (0) - var/direction = pick(directions) - for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) - sleep(3) - if (i > 0) - var/obj/effect/decal/cleanable/xenoblood/b = new /obj/effect/decal/cleanable/xenoblood/xsplatter(src.loc) - for(var/datum/disease/D in src.viruses) - var/datum/disease/ND = D.Copy(1) - b.viruses += ND - ND.holder = b - if (step_to(src, get_step(src, direction), 0)) - break + set waitfor = 0 + var/direction = pick(directions) + for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++) + sleep(2) + if (i > 0) + var/obj/effect/decal/cleanable/xenoblood/b = new /obj/effect/decal/cleanable/xenoblood/xsplatter(src.loc) + for(var/datum/disease/D in src.viruses) + var/datum/disease/ND = D.Copy(1) + b.viruses += ND + ND.holder = b + if (!step_to(src, get_step(src, direction), 0)) + break + +/obj/effect/decal/cleanable/xenoblood/xgibs/replace_decal(obj/effect/decal/cleanable/C) + return //gibs can stack, so gibspawner can work properly /obj/effect/decal/cleanable/xenoblood/xsplatter random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5") @@ -57,12 +60,21 @@ /obj/effect/decal/cleanable/xenoblood/xgibs/body random_icon_states = list("xgibhead", "xgibtorso") +/obj/effect/decal/cleanable/xenoblood/xgibs/torso + random_icon_states = list("xgibtorso") + /obj/effect/decal/cleanable/xenoblood/xgibs/limb random_icon_states = list("xgibleg", "xgibarm") /obj/effect/decal/cleanable/xenoblood/xgibs/core random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3") +/obj/effect/decal/cleanable/xenoblood/xgibs/larva + random_icon_states = list("xgiblarva1", "xgiblarva2") + +/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body + random_icon_states = list("xgiblarvahead", "xgiblarvatorso") + /obj/effect/decal/cleanable/blood/xtracks icon_state = "xtracks" random_icon_states = null diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 0e978782a5d..916bd7d2cf3 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -77,6 +77,10 @@ /obj/effect/decal/cleanable/blood/gibs/body random_icon_states = list("gibhead", "gibtorso") +/obj/effect/decal/cleanable/blood/gibs/torso + random_icon_states = list("gibtorso") + + /obj/effect/decal/cleanable/blood/gibs/limb random_icon_states = list("gibleg", "gibarm") @@ -87,17 +91,20 @@ /obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions) set waitfor = 0 var/direction = pick(directions) - for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) - sleep(3) + for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++) + sleep(2) if (i > 0) var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc) for(var/datum/disease/D in src.viruses) var/datum/disease/ND = D.Copy(1) b.viruses += ND ND.holder = b - if (step_to(src, get_step(src, direction), 0)) + if (!step_to(src, get_step(src, direction), 0)) break +/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C) + return //gibs can stack, so gibspawner can work properly + /obj/effect/decal/cleanable/blood/drip name = "drips of blood" desc = "It's red." diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm index e255f497ca2..7c0666a0c6e 100644 --- a/code/game/objects/effects/decals/Cleanable/robots.dm +++ b/code/game/objects/effects/decals/Cleanable/robots.dm @@ -15,8 +15,8 @@ /obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions) set waitfor = 0 var/direction = pick(directions) - for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) - sleep(3) + for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++) + sleep(2) if (i > 0) if (prob(40)) new /obj/effect/decal/cleanable/oil/streak(src.loc) @@ -24,9 +24,12 @@ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) s.start() - if (step_to(src, get_step(src, direction), 0)) + if (!step_to(src, get_step(src, direction), 0)) break +/obj/effect/decal/cleanable/robot_debris/replace_decal(obj/effect/decal/cleanable/C) + return //robot debris can stack, so gibspawner can work properly + /obj/effect/decal/cleanable/robot_debris/ex_act() return diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 834c3b4c7dc..b498217bb8a 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -11,6 +11,9 @@ desc = "They look like the remains of something... alien. They have a strange aura about them." icon_state = "remainsxeno" +/obj/effect/decal/remains/xeno/larva + icon_state = "remainslarva" + /obj/effect/decal/remains/robot desc = "They look like the remains of something mechanical. They have a strange aura about them." icon = 'icons/mob/robots.dmi' diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index fe303b4782c..585dfedf0ab 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -105,7 +105,7 @@ if(explosion_message) location.visible_message("The solution violently explodes!", \ "You hear an explosion!") - if (amount <= 2) + if (amount < 1) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(2, 1, location) s.start() @@ -116,22 +116,4 @@ M.Weaken(rand(1,5)) return else - var/devastation = -1 - var/heavy = -1 - var/light = -1 - var/flash = -1 - - // Clamp all values to MAX_EXPLOSION_RANGE - if (round(amount/12) > 0) - devastation = min (MAX_EX_DEVESTATION_RANGE, devastation + round(amount/12)) - - if (round(amount/6) > 0) - heavy = min (MAX_EX_HEAVY_RANGE, heavy + round(amount/6)) - - if (round(amount/3) > 0) - light = min (MAX_EX_LIGHT_RANGE, light + round(amount/3)) - - if (flashing && flashing_factor) - flash += (round(amount/4) * flashing_factor) - - explosion(location, devastation, heavy, light, flash) + dyn_explosion(location, amount, flashing_factor) \ No newline at end of file diff --git a/code/game/objects/effects/gibs.dm b/code/game/objects/effects/gibs.dm deleted file mode 100644 index 5bac5acd991..00000000000 --- a/code/game/objects/effects/gibs.dm +++ /dev/null @@ -1,62 +0,0 @@ -/proc/gibs(atom/location, list/viruses, datum/dna/MobDNA) - new /obj/effect/gibspawner/generic(location,viruses,MobDNA) - -/proc/hgibs(atom/location, list/viruses, datum/dna/MobDNA) - new /obj/effect/gibspawner/human(location,viruses,MobDNA) - -/proc/xgibs(atom/location, list/viruses) - new /obj/effect/gibspawner/xeno(location,viruses) - -/proc/robogibs(atom/location, list/viruses) - new /obj/effect/gibspawner/robot(location,viruses) - -/obj/effect/gibspawner - var/sparks = 0 //whether sparks spread on Gib() - var/virusProb = 20 //the chance for viruses to spread on the gibs - var/list/gibtypes = list() - var/list/gibamounts = list() - var/list/gibdirections = list() //of lists - -/obj/effect/gibspawner/New(location, var/list/viruses, var/datum/dna/MobDNA) - ..() - - Gib(loc,viruses,MobDNA) - -/obj/effect/gibspawner/proc/Gib(atom/location, list/viruses = list(), datum/dna/MobDNA = null) - if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len) - world << "Gib list length mismatch!" - return - - var/obj/effect/decal/cleanable/blood/gibs/gib = null - - if(sparks) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(2, 1, location) - s.start() - - for(var/i = 1, i<= gibtypes.len, i++) - if(gibamounts[i]) - for(var/j = 1, j<= gibamounts[i], j++) - var/gibType = gibtypes[i] - gib = new gibType(location) - if(istype(location,/mob/living/carbon)) - var/mob/living/carbon/digester = location - digester.stomach_contents += gib - - if(viruses.len > 0) - for(var/datum/disease/D in viruses) - if(prob(virusProb)) - var/datum/disease/viruus = D.Copy(1) - gib.viruses += viruus - viruus.holder = gib - - if(MobDNA) - gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.blood_type - else if(istype(src, /obj/effect/gibspawner/generic)) // Probably a monkey - gib.blood_DNA["Non-human DNA"] = "A+" - var/list/directions = gibdirections[i] - if(istype(loc,/turf)) - if(directions.len) - gib.streak(directions) - - qdel(src) diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index f66ca37c466..d6e75752338 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -130,8 +130,7 @@ var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc) chainsaw.flags |= NODROP - victim.drop_r_hand() - victim.drop_l_hand() + victim.drop_all_held_items() victim.put_in_hands(chainsaw) chainsaw.attack_self(victim) chainsaw.wield(victim) diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index e6618e62c74..bb6afc8e8ee 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -1,4 +1,53 @@ + /obj/effect/gibspawner + var/sparks = 0 //whether sparks spread + var/virusProb = 20 //the chance for viruses to spread on the gibs + var/list/gibtypes = list() //typepaths of the gib decals to spawn + var/list/gibamounts = list() //amount to spawn for each gib decal type we'll spawn. + var/list/gibdirections = list() //of lists of possible directions to spread each gib decal type towards. + +/obj/effect/gibspawner/New(location, list/viruses, datum/dna/MobDNA) + ..() + + if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len) + world << "Gib list length mismatch!" + return + + var/obj/effect/decal/cleanable/blood/gibs/gib = null + + if(sparks) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(2, 1, location) + s.start() + + for(var/i = 1, i<= gibtypes.len, i++) + if(gibamounts[i]) + for(var/j = 1, j<= gibamounts[i], j++) + var/gibType = gibtypes[i] + gib = new gibType(location) + if(istype(location,/mob/living/carbon)) + var/mob/living/carbon/digester = location + digester.stomach_contents += gib + + if(viruses && viruses.len > 0) + for(var/datum/disease/D in viruses) + if(prob(virusProb)) + var/datum/disease/viruus = D.Copy(1) + gib.viruses += viruus + viruus.holder = gib + + if(MobDNA) + gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.blood_type + else if(istype(src, /obj/effect/gibspawner/generic)) // Probably a monkey + gib.blood_DNA["Non-human DNA"] = "A+" + var/list/directions = gibdirections[i] + if(isturf(loc)) + if(directions.len) + gib.streak(directions) + + qdel(src) + + /obj/effect/gibspawner/generic gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core) @@ -16,17 +65,55 @@ /obj/effect/gibspawner/human/New() playsound(src, 'sound/effects/blobattack.ogg', 50, 1) gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) - gibamounts[6] = pick(0,1,2) ..() + +/obj/effect/gibspawner/humanbodypartless //only the gibs that don't look like actual full bodyparts (except torso). + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core,/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/torso) + gibamounts = list(1, 1, 1, 1, 1, 1) + +/obj/effect/gibspawner/humanbodypartless/New() + playsound(src, 'sound/effects/blobattack.ogg', 50, 1) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, list()) + ..() + + /obj/effect/gibspawner/xeno - gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/up,/obj/effect/decal/cleanable/xenoblood/xgibs/down,/obj/effect/decal/cleanable/xenoblood/xgibs,/obj/effect/decal/cleanable/xenoblood/xgibs,/obj/effect/decal/cleanable/xenoblood/xgibs/body,/obj/effect/decal/cleanable/xenoblood/xgibs/limb,/obj/effect/decal/cleanable/xenoblood/xgibs/core) + gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/up,/obj/effect/decal/cleanable/xenoblood/xgibs/down,/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/body, /obj/effect/decal/cleanable/xenoblood/xgibs/limb, /obj/effect/decal/cleanable/xenoblood/xgibs/core) gibamounts = list(1,1,1,1,1,1,1) /obj/effect/gibspawner/xeno/New() playsound(src, 'sound/effects/blobattack.ogg', 60, 1) gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) - gibamounts[6] = pick(0,1,2) + ..() + + +/obj/effect/gibspawner/xenobodypartless //only the gibs that don't look like actual full bodyparts (except torso). + gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core,/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/torso) + gibamounts = list(1, 1, 1, 1, 1, 1) + + +/obj/effect/gibspawner/xenobodypartless/New() + playsound(src, 'sound/effects/blobattack.ogg', 60, 1) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, list()) + ..() + +/obj/effect/gibspawner/larva + gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body) + gibamounts = list(1, 1, 1, 1) + +/obj/effect/gibspawner/larva/New() + playsound(src, 'sound/effects/blobattack.ogg', 60, 1) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), alldirs) + ..() + +/obj/effect/gibspawner/larvabodypartless + gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva) + gibamounts = list(1, 1, 1) + +/obj/effect/gibspawner/larvabodypartless/New() + playsound(src, 'sound/effects/blobattack.ogg', 60, 1) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list()) ..() /obj/effect/gibspawner/robot diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 248a17a77f0..2802cce4314 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -246,4 +246,18 @@ T.color = null T.maptext = "" +proc/dyn_explosion(turf/epicenter, power, flash_range, adminlog = 1, ignorecap = 1, flame_range = 0 ,silent = 0, smoke = 1) + if(!power) + return + var/range = 0 + range = round((2 * power)**DYN_EX_SCALE) + explosion(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke) +// Using default dyn_ex scale: +// 100 explosion power is a (5, 10, 20) explosion. +// 75 explosion power is a (4, 8, 17) explosion. +// 50 explosion power is a (3, 7, 14) explosion. +// 25 explosion power is a (2, 5, 10) explosion. +// 10 explosion power is a (1, 3, 6) explosion. +// 5 explosion power is a (0, 1, 3) explosion. +// 1 explosion power is a (0, 0, 1) explosion. \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a9fc34690a5..8877f17bc51 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -228,10 +228,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s user << "You put out the fire on [src]." else user << "You burn your hand on [src]!" - var/obj/item/bodypart/affecting = H.get_bodypart("[user.hand ? "l" : "r" ]_arm") + var/obj/item/bodypart/affecting = H.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") if(affecting && affecting.take_damage( 0, 5 )) // 5 burn damage - H.update_damage_overlays(0) - H.updatehealth() + H.update_damage_overlays() + return else extinguish() @@ -396,7 +396,7 @@ obj/item/proc/item_action_slot_check(slot, mob/user) if(usr.incapacitated() || !Adjacent(usr) || usr.lying) return - if(usr.get_active_hand() == null) // Let me know if this has any problems -Yota + if(usr.get_active_held_item() == null) // Let me know if this has any problems -Yota usr.UnarmedAttack(src) //This proc is executed when someone clicks the on-screen UI button. @@ -454,11 +454,10 @@ obj/item/proc/item_action_slot_check(slot, mob/user) ) if(is_human_victim) var/mob/living/carbon/human/U = M - if(affecting.take_damage(7)) - U.update_damage_overlays(0) + U.apply_damage(7, BRUTE, affecting) else - M.take_organ_damage(7) + M.take_bodypart_damage(7) add_logs(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])") @@ -574,11 +573,7 @@ obj/item/proc/item_action_slot_check(slot, mob/user) if(ismob(location)) var/mob/M = location var/success = FALSE - if(src == M.get_item_by_slot(slot_l_hand)) - success = TRUE - else if(src == M.get_item_by_slot(slot_r_hand)) - success = TRUE - else if(src == M.get_item_by_slot(slot_wear_mask)) + if(src == M.get_item_by_slot(slot_wear_mask)) success = TRUE if(success) location = get_turf(M) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 3edc3ea2f25..4a8412696f8 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -41,7 +41,7 @@ /obj/structure/closet/body_bag/attackby(obj/item/I, mob/user, params) if (istype(I, /obj/item/weapon/pen) || istype(I, /obj/item/toy/crayon)) var/t = stripped_input(user, "What would you like the label to be?", name, null, 53) - if(user.get_active_hand() != I) + if(user.get_active_held_item() != I) return if(!in_range(src, user) && loc != user) return diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index a04be038af7..a79ee1e4704 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -640,7 +640,7 @@ if(C.client) C.blur_eyes(3) C.blind_eyes(1) - if(C.check_eye_prot() <= 0) // no eye protection? ARGH IT BURNS. + if(C.get_eye_protection() <= 0) // no eye protection? ARGH IT BURNS. C.confused = max(C.confused, 3) C.Weaken(3) if(ishuman(C) && actually_paints) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index a1ded3061aa..b7ce1e4a737 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -708,7 +708,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(O) if (istype(loc, /mob)) var/mob/M = loc - if(M.get_active_hand() == null) + if(M.get_active_held_item() == null) M.put_in_hands(O) usr << "You remove \the [O] from \the [src]." return @@ -721,14 +721,14 @@ var/global/list/obj/item/device/pda/PDAs = list() if (id) remove_id() else - var/obj/item/I = user.get_active_hand() + var/obj/item/I = user.get_active_held_item() if (istype(I, /obj/item/weapon/card/id)) if(!user.unEquip(I)) return 0 I.loc = src id = I else - var/obj/item/weapon/card/I = user.get_active_hand() + var/obj/item/weapon/card/I = user.get_active_held_item() if (istype(I, /obj/item/weapon/card/id) && I:registered_name) if(!user.unEquip(I)) return 0 diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index b0be84a5209..f2932a64dd6 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -61,7 +61,7 @@ return if(M == user) //they're using it on themselves - if(M.flash_eyes(visual = 1)) + if(M.flash_act(visual = 1)) M.visible_message("[M] directs [src] to \his eyes.", \ "You wave the light in front of your eyes! Trippy!") else @@ -77,7 +77,7 @@ else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision user << "[C] pupils give an eerie glow!" else //they're okay! - if(C.flash_eyes(visual = 1)) + if(C.flash_act(visual = 1)) user << "[C]'s pupils narrow." else return ..() diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 65a73271e41..dfdccf1b8d1 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -98,7 +98,7 @@ severity = 0 //20% chance to actually hit the eyes - if(prob(effectchance * diode.rating) && C.flash_eyes(severity)) + if(prob(effectchance * diode.rating) && C.flash_act(severity)) outmsg = "You blind [C] by shining [src] in their eyes." if(C.weakeyes) C.Stun(1) @@ -110,7 +110,7 @@ var/mob/living/silicon/S = target //20% chance to actually hit the sensors if(prob(effectchance * diode.rating)) - S.flash_eyes(affect_silicon = 1) + S.flash_act(affect_silicon = 1) S.Weaken(rand(5,10)) S << "Your sensors were overloaded by a laser!" outmsg = "You overload [S] by shining [src] at their sensors." diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index c39791c0350..e5bb68ef23c 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -114,7 +114,7 @@ MASS SPECTROMETER // Used by the PDA medical scanner too /proc/healthscan(mob/living/user, mob/living/M, mode = 1) - if(user.stat || user.eye_blind) + if(user.incapacitated() || user.eye_blind) return //Damage specifics var/oxy_loss = M.getOxyLoss() @@ -156,9 +156,9 @@ MASS SPECTROMETER user << "\tBrain damage detected. Subject may have had a concussion." // Organ damage report - if(istype(M, /mob/living/carbon/human) && mode == 1) - var/mob/living/carbon/human/H = M - var/list/damaged = H.get_damaged_bodyparts(1,1) + if(iscarbon(M) && mode == 1) + var/mob/living/carbon/C = M + var/list/damaged = C.get_damaged_bodyparts(1,1) if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0) user << "\tDamage: Brute-Burn-Toxin-Suffocation\n\t\tSpecifics: [brute_loss]-[fire_loss]-[tox_loss]-[oxy_loss]" for(var/obj/item/bodypart/org in damaged) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 2c61dff29a3..605caa32cd0 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -54,7 +54,7 @@ /obj/item/device/taperecorder/attack_hand(mob/user) if(loc == user) if(mytape) - if(user.l_hand != src && user.r_hand != src) + if(!user.is_holding(src)) ..() return eject(user) diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index 3950e17d5fa..5eba01086ed 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -16,8 +16,7 @@ return icon_state = "latexballon_blow" item_state = "latexballon" - user.update_inv_r_hand() - user.update_inv_l_hand() + user.update_inv_hands() user << "You blow up [src] with [tank]." air_contents = tank.remove_air_volume(3) @@ -29,8 +28,7 @@ item_state = "lgloves" if(istype(src.loc, /mob/living)) var/mob/living/user = src.loc - user.update_inv_r_hand() - user.update_inv_l_hand() + user.update_inv_hands() loc.assume_air(air_contents) /obj/item/latexballon/ex_act(severity, target) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index d898405a1d8..5e8b75b987a 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -294,14 +294,10 @@ user.visible_message("[user] blares out a near-deafening siren from its speakers!", \ "The siren pierces your hearing and confuses you!", \ "The siren pierces your hearing!") - for(var/mob/living/M in get_hearers_in_view(9, user)) - if(iscarbon(M)) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(istype(H.ears, /obj/item/clothing/ears/earmuffs)) - continue + for(var/mob/living/carbon/M in get_hearers_in_view(9, user)) + if(M.get_ear_protection() == 0) M.confused += 6 - M << "HUMAN HARM" + audible_message("HUMAN HARM") playsound(get_turf(src), 'sound/AI/harmalarm.ogg', 70, 3) cooldown = world.time + 200 log_game("[user.ckey]([user]) used a Cyborg Harm Alarm in ([user.x],[user.y],[user.z])") @@ -312,35 +308,20 @@ return if(safety == 0) - for(var/mob/living/M in get_hearers_in_view(9, user)) - if(iscarbon(M)) - var/earsafety = 0 - if(istype(M, /mob/living/carbon/alien)) - continue - if(ishuman(M)) - var/mob/living/carbon/human/S = M - if(istype(S.ears, /obj/item/clothing/ears/earmuffs)) - continue - if(S.check_ear_prot()) - earsafety = 1 - if(earsafety) - M.confused += 5 - M.stuttering += 10 - M.adjustEarDamage(0, 5) - M.Jitter(10) - user.visible_message("[user] blares out a sonic screech from its speakers!", \ - "You hear a sharp screech, before your thoughts are interrupted and you find yourself extremely disorientated.", \ - "You hear a sonic screech and suddenly can't seem to walk straight!") - else - M.Weaken(2) - M.confused += 10 - M.stuttering += 15 - M.adjustEarDamage(0, 20) - M.Jitter(25) - user.visible_message("[user] blares out a sonic screech from its speakers!", \ - "You hear a sharp screech before your thoughts are interrupted and you collapse, your ears ringing!", \ - "You hear a sonic screech and collapse, your ears riniging!") - M << "BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT" + for(var/mob/living/carbon/C in get_hearers_in_view(9, user)) + var/bang_effect = C.soundbang_act(2, 0, 0, 5) + switch(bang_effect) + if(1) + C.confused += 5 + C.stuttering += 10 + C.Jitter(10) + if(2) + C.Weaken(2) + C.confused += 10 + C.stuttering += 15 + C.Jitter(25) + + user.audible_message("BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT") playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3) cooldown = world.time + 600 log_game("[user.ckey]([user]) used an emagged Cyborg Harm Alarm in ([user.x],[user.y],[user.z])") diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index b29313d8374..21aab1670c9 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -1,68 +1,19 @@ -/obj/item/robot_parts - name = "robot parts" - icon = 'icons/obj/robot_parts.dmi' - force = 4 - throwforce = 4 - item_state = "buildpipe" - icon_state = "blank" - flags = CONDUCT - slot_flags = SLOT_BELT - var/body_zone -/obj/item/robot_parts/l_arm - name = "cyborg left arm" - desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." - attack_verb = list("slapped", "punched") - icon_state = "l_arm" - body_zone = "l_arm" -/obj/item/robot_parts/r_arm - name = "cyborg right arm" - desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." - attack_verb = list("slapped", "punched") - icon_state = "r_arm" - body_zone = "r_arm" +//The robot bodyparts have been moved to code/module/surgery/bodyparts/robot_bodyparts.dm -/obj/item/robot_parts/l_leg - name = "cyborg left leg" - desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." - attack_verb = list("kicked", "stomped") - icon_state = "l_leg" - body_zone = "l_leg" -/obj/item/robot_parts/r_leg - name = "cyborg right leg" - desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." - attack_verb = list("kicked", "stomped") - icon_state = "r_leg" - body_zone = "r_leg" - -/obj/item/robot_parts/chest - name = "cyborg torso" - desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell." - icon_state = "chest" - body_zone = "chest" - var/wired = 0 - var/obj/item/weapon/stock_parts/cell/cell = null - -/obj/item/robot_parts/head - name = "cyborg head" - desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals." - icon_state = "head" - body_zone = "head" - var/obj/item/device/assembly/flash/handheld/flash1 = null - var/obj/item/device/assembly/flash/handheld/flash2 = null - -/obj/item/robot_parts/robot_suit +/obj/item/robot_suit name = "cyborg endoskeleton" desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors." + icon = 'icons/obj/robot_parts.dmi' icon_state = "robo_suit" - var/obj/item/robot_parts/l_arm/l_arm = null - var/obj/item/robot_parts/r_arm/r_arm = null - var/obj/item/robot_parts/l_leg/l_leg = null - var/obj/item/robot_parts/r_leg/r_leg = null - var/obj/item/robot_parts/chest/chest = null - var/obj/item/robot_parts/head/head = null + var/obj/item/bodypart/l_arm/robot/l_arm = null + var/obj/item/bodypart/r_arm/robot/r_arm = null + var/obj/item/bodypart/l_leg/robot/l_leg = null + var/obj/item/bodypart/r_leg/robot/r_leg = null + var/obj/item/bodypart/chest/robot/chest = null + var/obj/item/bodypart/head/robot/head = null var/created_name = "" var/mob/living/silicon/ai/forced_ai @@ -71,11 +22,11 @@ var/aisync = 1 var/panel_locked = 1 -/obj/item/robot_parts/robot_suit/New() +/obj/item/robot_suit/New() ..() src.updateicon() -/obj/item/robot_parts/robot_suit/proc/updateicon() +/obj/item/robot_suit/proc/updateicon() src.cut_overlays() if(src.l_arm) src.add_overlay("l_arm+o") @@ -90,7 +41,7 @@ if(src.head) src.add_overlay("head+o") -/obj/item/robot_parts/robot_suit/proc/check_completion() +/obj/item/robot_suit/proc/check_completion() if(src.l_arm && src.r_arm) if(src.l_leg && src.r_leg) if(src.chest && src.head) @@ -98,7 +49,7 @@ return 1 return 0 -/obj/item/robot_parts/robot_suit/attackby(obj/item/W, mob/user, params) +/obj/item/robot_suit/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = W @@ -107,71 +58,89 @@ var/obj/item/weapon/ed209_assembly/B = new /obj/item/weapon/ed209_assembly B.loc = get_turf(src) user << "You arm the robot frame." - if (user.get_inactive_hand()==src) + if (user.get_inactive_held_item()==src) user.unEquip(src) user.put_in_inactive_hand(B) qdel(src) else user << "You need one sheet of metal to start building ED-209!" return - else if(istype(W, /obj/item/robot_parts/l_leg)) + else if(istype(W, /obj/item/bodypart/l_leg/robot)) if(src.l_leg) return if(!user.unEquip(W)) return - W.loc = src + W.forceMove(src) + W.icon_state = initial(W.icon_state) + W.cut_overlays() src.l_leg = W src.updateicon() - else if(istype(W, /obj/item/robot_parts/r_leg)) + else if(istype(W, /obj/item/bodypart/r_leg/robot)) if(src.r_leg) return if(!user.unEquip(W)) return - W.loc = src + W.forceMove(src) + W.icon_state = initial(W.icon_state) + W.cut_overlays() src.r_leg = W src.updateicon() - else if(istype(W, /obj/item/robot_parts/l_arm)) + else if(istype(W, /obj/item/bodypart/l_arm/robot)) if(src.l_arm) return if(!user.unEquip(W)) return - W.loc = src + W.forceMove(src) + W.icon_state = initial(W.icon_state) + W.cut_overlays() src.l_arm = W src.updateicon() - else if(istype(W, /obj/item/robot_parts/r_arm)) + else if(istype(W, /obj/item/bodypart/r_arm/robot)) if(src.r_arm) return if(!user.unEquip(W)) return - W.loc = src + W.forceMove(src) + W.icon_state = initial(W.icon_state)//in case it is a dismembered robotic limb + W.cut_overlays() src.r_arm = W src.updateicon() - else if(istype(W, /obj/item/robot_parts/chest)) + else if(istype(W, /obj/item/bodypart/chest/robot)) + var/obj/item/bodypart/chest/robot/CH = W if(src.chest) return - if(W:wired && W:cell) - if(!user.unEquip(W)) + if(CH.wired && CH.cell) + if(!user.unEquip(CH)) return - W.loc = src - src.chest = W + CH.forceMove(src) + CH.icon_state = initial(CH.icon_state) //in case it is a dismembered robotic limb + CH.cut_overlays() + src.chest = CH src.updateicon() - else if(!W:wired) + else if(!CH.wired) user << "You need to attach wires to it first!" else user << "You need to attach a cell to it first!" - else if(istype(W, /obj/item/robot_parts/head)) + else if(istype(W, /obj/item/bodypart/head/robot)) + var/obj/item/bodypart/head/robot/HD = W + for(var/X in HD.contents) + if(istype(X, /obj/item/organ)) + user << "There are organs inside [HD]!" + return if(src.head) return - if(W:flash2 && W:flash1) - if(!user.unEquip(W)) + if(HD.flash2 && HD.flash1) + if(!user.unEquip(HD)) return - W.loc = src - src.head = W + HD.loc = src + HD.icon_state = initial(HD.icon_state)//in case it is a dismembered robotic limb + HD.cut_overlays() + src.head = HD src.updateicon() else user << "You need to attach a flash to it first!" @@ -192,7 +161,7 @@ user << "Sticking an empty MMI into the frame would sort of defeat the purpose!" return - var/mob/living/carbon/brain/BM = M.brainmob + var/mob/living/brain/BM = M.brainmob if(!BM.key || !BM.mind) user << "The mmi indicates that their mind is completely unresponsive; there's no point!" return @@ -283,7 +252,7 @@ else return ..() -/obj/item/robot_parts/robot_suit/proc/Interact(mob/user) +/obj/item/robot_suit/proc/Interact(mob/user) var/t1 = text("Designation: [(created_name ? "[created_name]" : "Default Cyborg")]
\n",src) t1 += text("Master AI: [(forced_ai ? "[forced_ai.name]" : "Automatic")]

\n",src) @@ -295,12 +264,12 @@ popup.set_content(t1) popup.open() -/obj/item/robot_parts/robot_suit/Topic(href, href_list) - if(usr.lying || usr.stat || usr.stunned || !Adjacent(usr)) +/obj/item/robot_suit/Topic(href, href_list) + if(usr.incapacitated() || !Adjacent(usr)) return var/mob/living/living_user = usr - var/obj/item/item_in_hand = living_user.get_active_hand() + var/obj/item/item_in_hand = living_user.get_active_held_item() if(!istype(item_in_hand, /obj/item/device/multitool)) living_user << "You need a multitool!" return @@ -330,50 +299,4 @@ add_fingerprint(usr) Interact(usr) - return - -/obj/item/robot_parts/chest/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/weapon/stock_parts/cell)) - if(src.cell) - user << "You have already inserted a cell!" - return - else - if(!user.unEquip(W)) - return - W.loc = src - src.cell = W - user << "You insert the cell." - else if(istype(W, /obj/item/stack/cable_coil)) - if(src.wired) - user << "You have already inserted wire!" - return - var/obj/item/stack/cable_coil/coil = W - if (coil.use(1)) - src.wired = 1 - user << "You insert the wire." - else - user << "You need one length of coil to wire it!" - else - return ..() - -/obj/item/robot_parts/head/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/device/assembly/flash/handheld)) - var/obj/item/device/assembly/flash/handheld/F = W - if(src.flash1 && src.flash2) - user << "You have already inserted the eyes!" - return - else if(F.crit_fail) - user << "You can't use a broken flash!" - return - else - if(!user.unEquip(W)) - return - F.loc = src - if(src.flash1) - src.flash2 = F - else - src.flash1 = F - user << "You insert the flash into the eye socket." - else - return ..() diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 66b881f09ca..8d0009c181d 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -30,19 +30,21 @@ return 1 var/obj/item/bodypart/affecting - if(ishuman(M)) - var/mob/living/carbon/human/H = M - affecting = H.get_bodypart(check_zone(user.zone_selected)) + if(iscarbon(M)) + var/mob/living/carbon/C = M + affecting = C.get_bodypart(check_zone(user.zone_selected)) if(!affecting) //Missing limb? - user << "[H] doesn't have \a [parse_zone(user.zone_selected)]!" + user << "[C] doesn't have \a [parse_zone(user.zone_selected)]!" return - if(stop_bleeding) - if(H.bleedsuppress) - user << "[H]'s bleeding is already bandaged!" - return - else if(!H.bleed_rate) - user << "[H] isn't bleeding!" - return + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(stop_bleeding) + if(H.bleedsuppress) + user << "[H]'s bleeding is already bandaged!" + return + else if(!H.bleed_rate) + user << "[H] isn't bleeding!" + return if(isliving(M)) @@ -75,25 +77,24 @@ user.visible_message("[user] applies [src] on [t_himself].", "You apply [src] on yourself.") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - affecting = H.get_bodypart(check_zone(user.zone_selected)) + if(iscarbon(M)) + var/mob/living/carbon/C = M + affecting = C.get_bodypart(check_zone(user.zone_selected)) if(!affecting) //Missing limb? - user << "[H] doesn't have \a [parse_zone(user.zone_selected)]!" + user << "[C] doesn't have \a [parse_zone(user.zone_selected)]!" return - if(stop_bleeding) - if(!H.bleedsuppress) //so you can't stack bleed suppression - H.suppress_bloodloss(stop_bleeding) - if(affecting.status == ORGAN_ORGANIC) //Limb must be organic to be healed - RR - if(affecting.heal_damage(src.heal_brute, src.heal_burn, 0)) - H.update_damage_overlays(0) - - M.updatehealth() + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(stop_bleeding) + if(!H.bleedsuppress) //so you can't stack bleed suppression + H.suppress_bloodloss(stop_bleeding) + if(affecting.status == BODYPART_ORGANIC) //Limb must be organic to be healed - RR + if(affecting.heal_damage(heal_brute, heal_burn)) + C.update_damage_overlays() else user << "Medicine won't work on a robotic limb!" else - M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2)) - + M.heal_bodypart_damage((src.heal_brute/2), (src.heal_burn/2)) use(1) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index b88420836fd..15c576c6335 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -49,7 +49,7 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \ "You hear welding.") var/obj/item/stack/rods/R = src src = null - var/replace = (user.get_inactive_hand()==R) + var/replace = (user.get_inactive_held_item()==R) R.use(2) if (!R && replace) user.put_in_hands(new_item) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 8a7f6b89919..a7f84608ffe 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -46,7 +46,7 @@ RG.add_fingerprint(user) var/obj/item/stack/sheet/glass/G = src src = null - var/replace = (user.get_inactive_hand()==G) + var/replace = (user.get_inactive_held_item()==G) V.use(1) G.use(1) if (!G && replace) @@ -311,19 +311,16 @@ return if(istype(A, /obj/item/weapon/storage)) return - + var/hit_hand = ((user.active_hand_index % 2 == 0) ? "r_" : "l_") + "arm" if(ishuman(user)) var/mob/living/carbon/human/H = user if(!H.gloves && !(PIERCEIMMUNE in H.dna.species.specflags)) // golems, etc H << "[src] cuts into your hand!" - var/organ = (H.hand ? "l_" : "r_") + "arm" - var/obj/item/bodypart/affecting = H.get_bodypart(organ) - if(affecting && affecting.take_damage(force / 2)) - H.update_damage_overlays(0) + H.apply_damage(force*0.5, BRUTE, hit_hand) else if(ismonkey(user)) var/mob/living/carbon/monkey/M = user M << "[src] cuts into your hand!" - M.adjustBruteLoss(force / 2) + M.apply_damage(force*0.5, BRUTE, hit_hand) /obj/item/weapon/shard/attackby(obj/item/I, mob/user, params) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 32c6709676d..2e765ab4e05 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -111,7 +111,7 @@ /obj/item/stack/Topic(href, href_list) ..() - if (usr.restrained() || usr.stat || (usr.get_active_hand() != src && usr.get_inactive_hand() != src)) + if (usr.restrained() || usr.stat || !usr.is_holding(src)) return if (href_list["make"]) if (src.get_amount() < 1) qdel(src) //Never should happen @@ -200,6 +200,8 @@ update_icon() /obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible + if(S == src) //amusingly this can cause a stack to consume itself, let's not allow that. + return var/transfer = get_amount() if(S.is_cyborg) transfer = min(transfer, round((S.source.max_energy - S.source.energy) / S.cost)) @@ -222,7 +224,7 @@ return ..() /obj/item/stack/attack_hand(mob/user) - if (user.get_inactive_hand() == src) + if (user.get_inactive_held_item() == src) if(zero_amount()) return change_stack(user,1) diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 8d8b89760fe..b44b5a9a7cc 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -51,7 +51,7 @@ "You hear welding.") var/obj/item/stack/rods/R = src src = null - var/replace = (user.get_inactive_hand()==R) + var/replace = (user.get_inactive_held_item()==R) R.use(4) if (!R && replace) user.put_in_hands(new_item) @@ -64,7 +64,7 @@ "You hear welding.") var/obj/item/stack/rods/R = src src = null - var/replace = (user.get_inactive_hand()==R) + var/replace = (user.get_inactive_held_item()==R) R.use(4) if (!R && replace) user.put_in_hands(new_item) diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index bf601df4ccc..f210f43a5dc 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -58,7 +58,7 @@ var/obj/item/I = target if(!I.can_be_package_wrapped()) return - if(user.r_hand == I || user.l_hand == I) + if(user.is_holding(I)) if(!user.unEquip(I)) return else if(!isturf(I.loc)) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index c81e8596a99..e2924db1ac9 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -260,12 +260,7 @@ if(active) icon_state = "swordrainbow" - // Updating overlays, copied from welder code. - // I tried calling attack_self twice, which looked cool, except it somehow didn't update the overlays!! - if(user.r_hand == src) - user.update_inv_r_hand(0) - else if(user.l_hand == src) - user.update_inv_l_hand(0) + user.update_inv_hands() else user << "It's already fabulous!" else @@ -777,11 +772,7 @@ var/obj/screen/inventory/hand/H = over_object if(!remove_item_from_storage(M)) M.unEquip(src) - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) usr << "You pick up the deck." else @@ -822,7 +813,7 @@ var/mob/living/carbon/human/cardUser = usr var/O = src if(href_list["pick"]) - if (cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) + if (cardUser.is_holding(src)) var/choice = href_list["pick"] var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc) src.currenthand -= choice @@ -899,7 +890,7 @@ /obj/item/toy/cards/singlecard/examine(mob/user) if(ishuman(user)) var/mob/living/carbon/human/cardUser = user - if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) + if(cardUser.is_holding(src)) cardUser.visible_message("[cardUser] checks \his card.", "The card reads: [src.cardname]") else cardUser << "You need to have the card in your hand to check it!" diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm index fa1e6f26631..3ef008add20 100644 --- a/code/game/objects/items/weapons/chrono_eraser.dm +++ b/code/game/objects/items/weapons/chrono_eraser.dm @@ -126,7 +126,7 @@ var/obj/item/weapon/gun/energy/chrono_gun/gun = null /obj/item/projectile/energy/chrono_beam/fire() - gun = firer.get_active_hand() + gun = firer.get_active_held_item() if(istype(gun)) return ..() else diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 992ebfbcf4f..461d4cc2a33 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -193,8 +193,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(ismob(loc)) var/mob/M = loc M.update_inv_wear_mask() - M.update_inv_l_hand() - M.update_inv_r_hand() + M.update_inv_hands() /obj/item/clothing/mask/cigarette/proc/handle_reagents() @@ -472,7 +471,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM icon_state = lit ? "[icon_state]_on" : "[initial(icon_state)]" /obj/item/weapon/lighter/attack_self(mob/living/user) - if(user.r_hand == src || user.l_hand == src) + if(user.is_holding(src)) if(!lit) lit = 1 update_icon() @@ -486,7 +485,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(prob(75)) user.visible_message("After a few attempts, [user] manages to light [src].", "After a few attempts, you manage to light [src].") else - var/hitzone = user.r_hand == src ? "r_hand" : "l_hand" + var/hitzone = user.held_index_to_dir(user.active_hand_index) == "r" ? "r_hand" : "l_hand" user.apply_damage(5, BURN, hitzone) user.visible_message("After a few attempts, [user] manages to light [src] - they however burn their finger in the process.", "You burn yourself while lighting the lighter!") diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 7ef5fffb1dd..07550fb00f8 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -94,20 +94,10 @@ var/mob/M = src.loc if(istype(over_object, /obj/screen/inventory/hand)) var/obj/screen/inventory/hand/H = over_object + if(!M.unEquip(src)) + return + M.put_in_hand(src, H.held_index) - switch(H.slot_id) - if(slot_r_hand) - if(M.r_hand) - return - if(!M.unEquip(src)) - return - M.put_in_r_hand(src) - if(slot_l_hand) - if(M.l_hand) - return - if(!M.unEquip(src)) - return - M.put_in_l_hand(src) /obj/item/weapon/defibrillator/attackby(obj/item/weapon/W, mob/user, params) if(W == paddles) @@ -334,7 +324,7 @@ if(!req_defib) return ..() if(user) - var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_hand() + var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_held_item() if(istype(O)) O.unwield() user << "The paddles snap back into the main unit." diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 57a33afa574..d329b466cf3 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -60,7 +60,7 @@ /obj/item/weapon/c4/attack_self(mob/user) var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(user.get_active_hand() == src) + if(user.get_active_held_item() == src) newtime = Clamp(newtime, 10, 60000) timer = newtime user << "Timer set for [timer] seconds." diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index 9efc0a78ed1..9dbfce86b95 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -39,7 +39,7 @@ var/turf/location = loc if(istype(location, /mob/)) var/mob/M = location - if(M.l_hand == src || M.r_hand == src) + if(M.is_holding(src)) location = M.loc if(isturf(location)) //start a fire if possible location.hotspot_expose(700, 2) @@ -62,7 +62,7 @@ /obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag) if(flag) return // too close // Make sure our user is still holding us - if(user && user.get_active_hand() == src) + if(user && user.get_active_held_item() == src) var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = getline(user, target_turf) diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 3763799c961..5fdc8e8c197 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -22,8 +22,6 @@ M.show_message("BANG", 2) playsound(loc, 'sound/weapons/flashbang.ogg', 100, 1) -//Checking for protection - var/ear_safety = M.check_ear_prot() var/distance = max(1,get_dist(src,T)) //Flash @@ -34,24 +32,12 @@ M.Stun(15) M.adjust_eye_damage(8) - if(M.flash_eyes(affect_silicon = 1)) + if(M.flash_act(affect_silicon = 1)) M.Stun(max(10/distance, 3)) M.Weaken(max(10/distance, 3)) //Bang if((loc == M) || loc == M.loc)//Holding on person or being exactly where lies is significantly more dangerous and voids protection - M.Stun(10) - M.Weaken(10) - if(!ear_safety) - M << sound('sound/weapons/flash_ring.ogg',0,1,0,100) - M.Stun(max(10/distance, 3)) - M.Weaken(max(10/distance, 3)) - M.setEarDamage(M.ear_damage + rand(0, 5), max(M.ear_deaf,15)) - if (M.ear_damage >= 15) - M << "Your ears start to ring badly!" - if(prob(M.ear_damage - 10 + 5)) - M << "You can't hear anything!" - M.disabilities |= DEAF - else - if (M.ear_damage >= 5) - M << "Your ears start to ring!" + M.soundbang_act(1, 10, rand(5, 10)) + else + M.soundbang_act(1, max(10/distance, 3), rand(0, 5)) diff --git a/code/game/objects/items/weapons/grenades/plastic.dm b/code/game/objects/items/weapons/grenades/plastic.dm index 3af83500b67..5d11b5bdac8 100644 --- a/code/game/objects/items/weapons/grenades/plastic.dm +++ b/code/game/objects/items/weapons/grenades/plastic.dm @@ -60,7 +60,7 @@ nadeassembly.attack_self(user) return var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(user.get_active_hand() == src) + if(user.get_active_held_item() == src) newtime = Clamp(newtime, 10, 60000) det_time = newtime user << "Timer set for [det_time] seconds." @@ -108,7 +108,7 @@ target = user sleep(10) prime() - user.gib(no_brain = 1) + user.gib(1, 1, 1) /obj/item/weapon/grenade/plastic/update_icon() if(nadeassembly) diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 60476753365..76536e7b21d 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -15,7 +15,7 @@ var/turf/T = get_turf(src) playsound(T, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/living/carbon/C in viewers(T, null)) - C.flash_eyes() + C.flash_act() for(var/i=1, i<=deliveryamt, i++) var/atom/movable/x = new spawner_type diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 8d76fcc492a..810048f5782 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -30,12 +30,12 @@ return if(!C.handcuffed) - if(C.get_num_arms() >= 2) + if(C.get_num_arms() >= 2 || C.get_arm_ignore()) C.visible_message("[user] is trying to put [src.name] on [C]!", \ "[user] is trying to put [src.name] on [C]!") playsound(loc, cuffsound, 30, 1, -2) - if(do_mob(user, C, 30) && C.get_num_arms() >= 2) + if(do_mob(user, C, 30) && (C.get_num_arms() >= 2 || C.get_arm_ignore())) apply_cuffs(C,user) user << "You handcuff [C]." if(istype(src, /obj/item/weapon/restraints/handcuffs/cable)) diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index e7426b2184d..eca8a792f41 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -26,7 +26,7 @@ /obj/item/weapon/implantcase/attackby(obj/item/weapon/W, mob/user, params) if(istype(W, /obj/item/weapon/pen)) var/t = stripped_input(user, "What would you like the label to be?", name, null) - if(user.get_active_hand() != W) + if(user.get_active_held_item() != W) return if(!in_range(src, user) && loc != user) return diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index d94709d2a46..f35bc2929dd 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -42,7 +42,7 @@ /obj/item/weapon/implanter/attackby(obj/item/weapon/W, mob/user, params) if(istype(W, /obj/item/weapon/pen)) var/t = stripped_input(user, "What would you like the label to be?", name, null) - if(user.get_active_hand() != W) + if(user.get_active_held_item() != W) return if(!in_range(src, user) && loc != user) return diff --git a/code/game/objects/items/weapons/implants/implantpad.dm b/code/game/objects/items/weapons/implants/implantpad.dm index 04287893b4f..5b11165fe2d 100644 --- a/code/game/objects/items/weapons/implants/implantpad.dm +++ b/code/game/objects/items/weapons/implants/implantpad.dm @@ -20,7 +20,7 @@ /obj/item/weapon/implantpad/attack_hand(mob/user) - if(case && (user.l_hand == src || user.r_hand == src)) + if(case && user.is_holding(src)) user.put_in_active_hand(case) case.add_fingerprint(user) diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 0cc98cd62a3..9f93c93eca3 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -81,7 +81,7 @@ /obj/item/weapon/melee/energy/attack_self(mob/living/carbon/user) if(user.disabilities & CLUMSY && prob(50)) user << "You accidentally cut yourself with [src], like a doofus!" - user.take_organ_damage(5,5) + user.take_bodypart_damage(5,5) active = !active if (active) force = force_on @@ -202,12 +202,7 @@ if(active) icon_state = "swordrainbow" - // Updating overlays, copied from welder code. - // I tried calling attack_self twice, which looked cool, except it somehow didn't update the overlays!! - if(user.r_hand == src) - user.update_inv_r_hand(0) - else if(user.l_hand == src) - user.update_inv_l_hand(0) + user.update_inv_hands() else user << "It's already fabulous!" else diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm index e9ca6ece91c..b81a9cf75aa 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -1,6 +1,7 @@ /obj/item/weapon/melee needs_permit = 1 + /obj/item/weapon/melee/chainofcommand name = "chain of command" desc = "A tool used by great men to placate the frothing masses." @@ -27,6 +28,7 @@ icon_state = "sabre" item_state = "sabre" flags = CONDUCT + unique_rename = 1 force = 15 throwforce = 10 w_class = 4 @@ -67,7 +69,7 @@ var/mob/living/carbon/human/H = user H.apply_damage(2*force, BRUTE, "head") else - user.take_organ_damage(2*force) + user.take_bodypart_damage(2*force) return if(isrobot(target)) ..() @@ -124,7 +126,7 @@ if (B && !qdeleted(B)) H.internal_organs -= B qdel(B) - gibs(H.loc, H.viruses, H.dna) + new /obj/effect/gibspawner/generic(H.loc, H.viruses, H.dna) return (BRUTELOSS) /obj/item/weapon/melee/classic_baton/telescopic/attack_self(mob/user) diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm index a62d5d5603f..bab00418b8c 100644 --- a/code/game/objects/items/weapons/paint.dm +++ b/code/game/objects/items/weapons/paint.dm @@ -57,7 +57,7 @@ /obj/item/weapon/paint/anycolor/attack_self(mob/user) var/t1 = input(user, "Please select a color:", "Locking Computer", null) in list( "red", "blue", "green", "yellow", "violet", "black", "white") - if ((user.get_active_hand() != src || user.stat || user.restrained())) + if ((user.get_active_held_item() != src || user.stat || user.restrained())) return switch(t1) if("red") diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 24708a7829d..26513f300b5 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -74,7 +74,7 @@ /obj/item/weapon/shield/energy/attack_self(mob/living/carbon/human/user) if(user.disabilities & CLUMSY && prob(50)) user << "You beat yourself in the head with [src]." - user.take_organ_damage(5) + user.take_bodypart_damage(5) active = !active icon_state = "eshield[active]" diff --git a/code/game/objects/items/weapons/singularityhammer.dm b/code/game/objects/items/weapons/singularityhammer.dm index 07802d94a9a..e8ef7dc9402 100644 --- a/code/game/objects/items/weapons/singularityhammer.dm +++ b/code/game/objects/items/weapons/singularityhammer.dm @@ -57,7 +57,7 @@ charged = 0 if(istype(A, /mob/living/)) var/mob/living/Z = A - Z.take_organ_damage(20,0) + Z.take_bodypart_damage(20,0) playsound(user, 'sound/weapons/marauder.ogg', 50, 1) var/turf/target = get_turf(A) vortex(target,user) diff --git a/code/game/objects/items/weapons/storage/book.dm b/code/game/objects/items/weapons/storage/book.dm index f6ffe2afb1a..ab3d92007ea 100644 --- a/code/game/objects/items/weapons/storage/book.dm +++ b/code/game/objects/items/weapons/storage/book.dm @@ -114,15 +114,27 @@ var/global/list/bibleitemstates = list("bible", "koran", "scrapbook", "bible", " usr << browse(null, "window=editicon") // Close window -/obj/item/weapon/storage/book/bible/proc/bless(mob/living/carbon/M) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/heal_amt = 10 - for(var/obj/item/bodypart/affecting in H.bodyparts) - if(affecting.status == ORGAN_ORGANIC) //No Bible can heal a robotic arm! - if(affecting.heal_damage(heal_amt, heal_amt, 0)) - H.update_damage_overlays(0) - return +/obj/item/weapon/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user) + for(var/X in H.bodyparts) + var/obj/item/bodypart/BP = X + if(BP.status == BODYPART_ROBOTIC) + user << "[src.deity_name] refuses to heal this metallic taint!" + return 0 + + var/heal_amt = 10 + var/list/hurt_limbs = H.get_damaged_bodyparts(1, 1) + + if(hurt_limbs.len) + for(var/X in hurt_limbs) + var/obj/item/bodypart/affecting = X + if(affecting.heal_damage(heal_amt, heal_amt)) + H.update_damage_overlays() + H.visible_message("[user] heals [H] with the power of [deity_name]!") + H << "May the power of [deity_name] compel you to be healed!" + playsound(src.loc, "punch", 25, 1, -1) + return 1 + + /obj/item/weapon/storage/book/bible/attack(mob/living/M, mob/living/carbon/human/user) @@ -137,51 +149,40 @@ var/global/list/bibleitemstates = list("bible", "koran", "scrapbook", "bible", " return if(!chaplain) user << "The book sizzles in your hands." - user.take_organ_damage(0,10) + user.take_bodypart_damage(0,10) return if (user.disabilities & CLUMSY && prob(50)) user << "The [src] slips out of your hand and hits your head." - user.take_organ_damage(10) + user.take_bodypart_damage(10) user.Paralyse(20) return - if (M.stat !=2) - if(M.mind && (M.mind.assigned_role == "Chaplain")) + var/smack = 1 + + if (M.stat != DEAD) + if(chaplain && user == M) user << "You can't heal yourself!" return - if ((istype(M, /mob/living/carbon/human) && prob(60))) - bless(M) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/message_halt = 0 - for(var/obj/item/bodypart/affecting in H.bodyparts) - if(affecting.status == ORGAN_ORGANIC) - if(message_halt == 0) - M.visible_message("[user] heals [M] with the power of [src.deity_name]!") - M << "May the power of [src.deity_name] compel you to be healed!" - playsound(src.loc, "punch", 25, 1, -1) - message_halt = 1 - else - user << "[src.deity_name] refuses to heal this metallic taint!" - return + if(ishuman(M) && prob(60) && bless(M, user)) + smack = 0 + else if(iscarbon(M)) + var/mob/living/carbon/C = M + if(!istype(C.head, /obj/item/clothing/head/helmet)) + C.adjustBrainLoss(10) + C << "You feel dumber." - - - else - if(ishuman(M) && !istype(M:head, /obj/item/clothing/head/helmet)) - M.adjustBrainLoss(10) - M << "You feel dumber." + if(smack) M.visible_message("[user] beats [M] over the head with [src]!", \ "[user] beats [M] over the head with [src]!") playsound(src.loc, "punch", 25, 1, -1) add_logs(user, M, "attacked", src) - else if(M.stat == 2) + else M.visible_message("[user] smacks [M]'s lifeless corpse with [src].") playsound(src.loc, "punch", 25, 1, -1) - return + /obj/item/weapon/storage/book/bible/afterattack(atom/A, mob/user, proximity) if(!proximity) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 759ed80e9bc..241474b391b 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -47,8 +47,7 @@ var/obj/item/I = new foldable(get_turf(src)) user.drop_item() user.put_in_hands(I) - user.update_inv_l_hand() - user.update_inv_r_hand() + user.update_inv_hands() qdel(src) /obj/item/weapon/storage/box/attackby(obj/item/W, mob/user, params) diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index bce4035beb7..fd8d6395ec5 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -133,7 +133,7 @@ name = "\improper [name] packet" /obj/item/weapon/storage/fancy/cigarettes/AltClick(mob/user) - if(user.get_active_hand()) + if(user.get_active_held_item()) return for(var/obj/item/weapon/lighter/lighter in src) remove_from_storage(lighter, user.loc) diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 582216e817d..1003d6aa62c 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -142,11 +142,7 @@ var/obj/screen/inventory/hand/H = over_object if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src,H.held_index) src.add_fingerprint(usr) return if(over_object == usr && in_range(src, usr) || usr.contents.Find(src)) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index dc1e70d9cbb..d9a8e0e779a 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -58,14 +58,21 @@ var/obj/screen/inventory/hand/H = over_object if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src,H.held_index) add_fingerprint(usr) + +/obj/item/weapon/storage/MouseDrop_T(atom/movable/O, mob/user) + if(istype(O, /obj/item)) + var/obj/item/I = O + if(iscarbon(user) || isdrone(user)) + var/mob/living/L = user + if(!L.incapacitated() && I == L.get_active_held_item()) + if(can_be_inserted(I, 0)) + handle_item_insertion(I, 0 , L) + + //Check if this storage can dump the items /obj/item/weapon/storage/proc/content_can_dump(atom/dest_object, mob/user) if(Adjacent(user) && dest_object.Adjacent(user)) @@ -398,11 +405,11 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.l_store == src && !H.get_active_hand()) //Prevents opening if it's in a pocket. + if(H.l_store == src && !H.get_active_held_item()) //Prevents opening if it's in a pocket. H.put_in_hands(src) H.l_store = null return - if(H.r_store == src && !H.get_active_hand()) + if(H.r_store == src && !H.get_active_held_item()) H.put_in_hands(src) H.r_store = null return @@ -501,7 +508,7 @@ /obj/item/weapon/storage/attack_self(mob/user) //Clicking on itself will empty it, if it has the verb to do that. - if(user.get_active_hand() == src) + if(user.get_active_held_item() == src) if(verbs.Find(/obj/item/weapon/storage/verb/quick_empty)) quick_empty() diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 9e5801e1667..537c4d37c78 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -114,7 +114,7 @@ H.hair_style = "Bald" H.update_hair() H.bleed_rate = 5 - gibs(H.loc, H.viruses, H.dna) + new /obj/effect/gibspawner/generic(H.loc, H.viruses, H.dna) H.adjustBruteLoss(1000) //to make the body super-bloody return (BRUTELOSS) diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index 49cb244c150..86404905456 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -83,19 +83,10 @@ var/mob/M = src.loc if(istype(M) && istype(over_object, /obj/screen/inventory/hand)) var/obj/screen/inventory/hand/H = over_object - switch(H.slot_id) - if(slot_r_hand) - if(M.r_hand) - return - if(!M.unEquip(src)) - return - M.put_in_r_hand(src) - if(slot_l_hand) - if(M.l_hand) - return - if(!M.unEquip(src)) - return - M.put_in_l_hand(src) + if(!M.unEquip(src)) + return + M.put_in_hand(src, H.held_index) + /obj/item/weapon/watertank/attackby(obj/item/W, mob/user, params) if(W == noz) diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 010e07df9a7..b0b0e8ac781 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -165,7 +165,7 @@ Frequency: if(turfs.len) L["None (Dangerous)"] = pick(turfs) var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L - if (user.get_active_hand() != src || user.incapacitated()) + if (user.get_active_held_item() != src || user.incapacitated()) return if(active_portals >= 3) user.show_message("\The [src] is recharging!") diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index d57c948c746..a48395a2cab 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -298,7 +298,7 @@ var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - if(affecting && affecting.status == ORGAN_ROBOTIC && user.a_intent != "harm") + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != "harm") if(src.remove_fuel(1)) playsound(loc, 'sound/items/Welder.ogg', 50, 1) user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") @@ -347,7 +347,7 @@ reagents.remove_reagent("welding_fuel", amount) check_fuel() if(M) - M.flash_eyes(light_intensity) + M.flash_act(light_intensity) return TRUE else if(M) @@ -363,8 +363,7 @@ //mob icon update if(ismob(loc)) var/mob/M = loc - M.update_inv_r_hand(0) - M.update_inv_l_hand(0) + M.update_inv_hands(0) return 0 return 1 diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 2e5746ba010..e597a00abca 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -49,7 +49,7 @@ user << "You are now carrying the [name] with one hand." if(unwieldsound) playsound(loc, unwieldsound, 50, 1) - var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_hand() + var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_held_item() if(O && istype(O)) O.unwield() return @@ -60,7 +60,7 @@ if(istype(user,/mob/living/carbon/monkey) ) user << "It's too heavy for you to wield fully." return - if(user.get_inactive_hand()) + if(user.get_inactive_held_item()) user << "You need your other hand to be empty!" return if(user.get_num_arms() < 2) @@ -87,7 +87,7 @@ ..() //handles unwielding a twohanded weapon when dropped as well as clearing up the offhand if(user) - var/obj/item/weapon/twohanded/O = user.get_inactive_hand() + var/obj/item/weapon/twohanded/O = user.get_inactive_held_item() if(istype(O)) O.unwield(user) return unwield(user) @@ -109,7 +109,7 @@ /obj/item/weapon/twohanded/equipped(mob/user, slot) ..() - if(slot != slot_l_hand && slot != slot_r_hand && wielded) + if(!user.is_holding(src) && wielded) unwield(user) ///////////OFFHAND/////////////// @@ -140,7 +140,7 @@ return ..() /obj/item/weapon/twohanded/required/attack_hand(mob/user)//Can't even pick it up without both hands empty - var/obj/item/weapon/twohanded/required/H = user.get_inactive_hand() + var/obj/item/weapon/twohanded/required/H = user.get_inactive_held_item() if(get_dist(src,user) > 1) return 0 if(H != null) @@ -152,7 +152,7 @@ /obj/item/weapon/twohanded/required/equipped(mob/user, slot) ..() - if(slot == slot_l_hand || slot == slot_r_hand) + if(slot == slot_hands) wield(user) else unwield(user) @@ -256,7 +256,7 @@ /obj/item/weapon/twohanded/dualsaber/proc/impale(mob/living/user) user << "You twirl around a bit before losing your balance and impaling yourself on \the [src]." if (force_wielded) - user.take_organ_damage(20,25) + user.take_bodypart_damage(20,25) else user.adjustStaminaLoss(25) @@ -433,9 +433,8 @@ else hitsound = "swing_hit" - if(src == user.get_active_hand()) //update inhands - user.update_inv_l_hand() - user.update_inv_r_hand() + if(src == user.get_active_held_item()) //update inhands + user.update_inv_hands() for(var/X in actions) var/datum/action/A = X A.UpdateButtonIcon() diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 0434b288c9c..0702a80d30c 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -1,3 +1,28 @@ +/obj/item/weapon + + var/unique_rename = 0 //allows renaming with a pen + +/obj/item/weapon/examine(mob/user) + ..() + if(unique_rename) + user << "Use a pen on it to rename it." + +/obj/item/weapon/attackby(obj/item/I, mob/user, params) + if(unique_rename) + if(istype(I, /obj/item/weapon/pen)) + rename_weapon(user) + ..() + +/obj/item/weapon/proc/rename_weapon(mob/M) + var/input = stripped_input(M,"What do you want to name the weapon?", ,"", MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove) + name = input + M << "You name the weapon [input]. Say hello to your new friend." + return + + + /obj/item/weapon/banhammer desc = "A banhammer" name = "banhammer" diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 2c9ebb0f9ba..c2904d8e37b 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -64,7 +64,7 @@ if(user.canmove) climb_structure(user) return - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_held_item() != O)) return if(isrobot(user)) return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index e358f441072..c6284f25056 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -271,9 +271,9 @@ if(dist <= 3) closest_mob = A if(closest_mob) - var/shock_damage = C.powernet.avail * 0.08 + var/shock_damage = C.powernet.avail * 0.0002//setting shock damage for later. equals 1/5000 the power in the grid src.Beam(closest_mob, icon_state="lightning[rand(1,12)]", time=5) - closest_mob.electrocute_act(shock_damage, src, 1, tesla_shock = 1)//ZAP for 1/5000 of the amount of power, which is from 15-25 with 200000W + closest_mob.electrocute_act(shock_damage, src, 1)//ZAP, damage should be about 40 with 200000W playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) take_damage(tforce) diff --git a/code/game/objects/structures/guncase.dm b/code/game/objects/structures/guncase.dm index 598c5562e03..abaebce5de3 100644 --- a/code/game/objects/structures/guncase.dm +++ b/code/game/objects/structures/guncase.dm @@ -80,10 +80,8 @@ if(!usr.canUseTopic(src)) return if(ishuman(usr)) - if(!usr.get_active_hand()) - usr.put_in_hands(O) - else - O.loc = get_turf(src) + if(!usr.put_in_hands(O)) + O.forceMove(get_turf(src)) update_icon() /obj/structure/guncase/shotgun diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 7a7b200ab39..c16ae3f1401 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -66,7 +66,7 @@ add_fingerprint(user) if(istype(P, /obj/item/weapon/pen)) var/t = stripped_input(user, "What would you like the label to be?", text("[]", name), null) - if (user.get_active_hand() != P) + if (user.get_active_held_item() != P) return if ((!in_range(src, usr) && src.loc != user)) return diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 8a7ce0ad0dd..411ea3ec003 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -60,15 +60,12 @@ var/obj/item/P = locate(href_list["write"]) if((P && P.loc == src)) //ifthe paper's on the board - if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen + var/obj/item/I = usr.is_holding_item_of_type(/obj/item/weapon/pen) + if(I) //check hand for pen add_fingerprint(usr) - P.attackby(usr.r_hand, usr) //then do ittttt + P.attackby(I, usr) else - if(istype(usr.l_hand, /obj/item/weapon/pen)) //check other hand for pen - add_fingerprint(usr) - P.attackby(usr.l_hand, usr) - else - usr << "You'll need something to write with!" + usr << "You'll need something to write with!" if(href_list["read"]) var/obj/item/weapon/paper/P = locate(href_list["read"]) diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 8cd1b6b101d..5b1acebb898 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -91,7 +91,7 @@ FLOOR SAFES var/mob/living/carbon/human/user = usr var/canhear = 0 - if(istype(user.l_hand, /obj/item/clothing/tie/stethoscope) || istype(user.r_hand, /obj/item/clothing/tie/stethoscope)) + if(user.is_holding_item_of_type(/obj/item/clothing/tie/stethoscope)) canhear = 1 if(href_list["open"]) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index da1645af7aa..f2aad755601 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -502,7 +502,7 @@ . = . || mover.checkpass(PASSTABLE) /obj/structure/rack/MouseDrop_T(obj/O, mob/user) - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_held_item() != O)) return if(!user.drop_item()) return diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index 0a0d96eac20..8814ec13fb6 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -41,7 +41,7 @@ pinned_target.nullPinnedLoc() nullPinnedTarget() if(ishuman(user)) - if(!user.get_active_hand()) + if(!user.get_active_held_item()) user.put_in_hands(pinned_target) user << "You take the target out of the stake." else diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 46e2e08b60f..92e2ca87b76 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -294,10 +294,8 @@ var/mob/living/carbon/M = L . = 1 check_heat(M) - if(M.r_hand) - M.r_hand.clean_blood() - if(M.l_hand) - M.l_hand.clean_blood() + for(var/obj/item/I in M.held_items) + I.clean_blood() if(M.back) if(M.back.clean_blood()) M.update_inv_back(0) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index af9698bc99d..5fc29b24f79 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -122,8 +122,8 @@ if(!(lube&SLIDE_ICE)) playsound(C.loc, 'sound/misc/slip.ogg', 50, 1, -3) - C.accident(C.l_hand) - C.accident(C.r_hand) + for(var/obj/item/I in C.held_items) + C.accident(I) var/olddir = C.dir if(!(lube&SLIDE_ICE)) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 9b5f0026e1a..e1da895de41 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -182,7 +182,7 @@ if(do_after(user, slicing_duration/W.toolspeed, target = src)) if( !istype(src, /turf/closed/wall) || !user || !WT || !WT.isOn() || !T ) return 1 - if( user.loc == T && user.get_active_hand() == WT ) + if( user.loc == T && user.get_active_held_item() == WT ) user << "You remove the outer plating." dismantle_wall() return 1 @@ -192,7 +192,7 @@ if(do_after(user, slicing_duration*0.6, target = src)) // plasma cutter is faster than welding tool if( !istype(src, /turf/closed/wall) || !user || !W || !T ) return 1 - if( user.loc == T && user.get_active_hand() == W ) + if( user.loc == T && user.get_active_held_item() == W ) user << "You remove the outer plating." dismantle_wall() visible_message("The wall was sliced apart by [user]!", "You hear metal being sliced apart.") @@ -205,7 +205,7 @@ var/obj/item/weapon/pickaxe/drill/jackhammer/D = W if( !istype(src, /turf/closed/wall) || !user || !W || !T ) return 1 - if( user.loc == T && user.get_active_hand() == W ) + if( user.loc == T && user.get_active_held_item() == W ) D.playDigSound() dismantle_wall() visible_message("[user] smashes through the [name] with the [W.name]!", "You hear the grinding of metal.") diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 0212e8f32d2..cfcaf0159c8 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -38,7 +38,7 @@ if(do_after(user, 50, target = src)) if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( user.loc == T && user.get_active_hand() == W ) + if( user.loc == T && user.get_active_held_item() == W ) D.playDigSound() visible_message("[user] smashes through the [name] with the [D.name]!", "You hear the grinding of metal.") dismantle_wall() @@ -80,7 +80,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( d_state == 1 && user.loc == T && user.get_active_hand() == W ) + if( d_state == 1 && user.loc == T && user.get_active_held_item() == W ) src.d_state = 2 update_icon() user << "You remove the support lines." @@ -111,7 +111,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !WT || !WT.isOn() || !T ) return 0 - if( d_state == 2 && user.loc == T && user.get_active_hand() == WT ) + if( d_state == 2 && user.loc == T && user.get_active_held_item() == WT ) src.d_state = 3 update_icon() user << "You press firmly on the cover, dislodging it." @@ -126,7 +126,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( d_state == 2 && user.loc == T && user.get_active_hand() == W ) + if( d_state == 2 && user.loc == T && user.get_active_held_item() == W ) src.d_state = 3 update_icon() user << "You press firmly on the cover, dislodging it." @@ -142,7 +142,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( d_state == 3 && user.loc == T && user.get_active_hand() == W ) + if( d_state == 3 && user.loc == T && user.get_active_held_item() == W ) src.d_state = 4 update_icon() user << "You pry off the cover." @@ -158,7 +158,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( d_state == 4 && user.loc == T && user.get_active_hand() == W ) + if( d_state == 4 && user.loc == T && user.get_active_held_item() == W ) src.d_state = 5 update_icon() user << "You remove the bolts anchoring the support rods." @@ -176,7 +176,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !WT || !WT.isOn() || !T ) return 1 - if( d_state == 5 && user.loc == T && user.get_active_hand() == WT ) + if( d_state == 5 && user.loc == T && user.get_active_held_item() == WT ) src.d_state = 6 update_icon() user << "You slice through the support rods." @@ -191,7 +191,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( d_state == 5 && user.loc == T && user.get_active_hand() == W ) + if( d_state == 5 && user.loc == T && user.get_active_held_item() == W ) src.d_state = 6 update_icon() user << "You slice through the support rods." @@ -207,7 +207,7 @@ if( !istype(src, /turf/closed/wall/r_wall) || !user || !W || !T ) return 1 - if( user.loc == T && user.get_active_hand() == W ) + if( user.loc == T && user.get_active_held_item() == W ) user << "You pry off the outer sheath." dismantle_wall() return 1 diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index cc5b4d1cc8a..d13b8f9d2cd 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -38,6 +38,9 @@ /turf/open/space/TakeTemperature(temp) +/turf/open/space/RemoveLattice() + return + /turf/open/space/AfterChange() ..() atmos_overlay_types.Cut() @@ -167,3 +170,7 @@ /turf/open/space/proc/update_icon() icon_state = SPACE_ICON_STATE + +/turf/open/space/is_transition_turf() + if(destination_x || destination_y || destination_z) + return 1 \ No newline at end of file diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8e28c283358..4a73e76ba90 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -176,6 +176,8 @@ for(var/T in atmos_adjacent_turfs) var/turf/open/S = T + if(!S.air) + continue var/list/S_gases = S.air.gases for(var/id in S_gases) total.assert_gas(id) @@ -323,3 +325,6 @@ SSair.remove_from_active(T0) T0.CalculateAdjacentTurfs() SSair.add_to_active(T0,1) + +/turf/proc/is_transition_turf() + return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c67f8d1c3b2..43cd0a61fdc 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -82,6 +82,8 @@ var/list/admin_verbs_fun = list( /client/proc/cmd_admin_dress, /client/proc/cmd_admin_gib_self, /client/proc/drop_bomb, + /client/proc/set_dynex_scale, + /client/proc/drop_dynex_bomb, /client/proc/cinematic, /client/proc/one_click_antag, /client/proc/send_space_ninja, @@ -142,6 +144,9 @@ var/list/admin_verbs_debug = list( /client/proc/check_bomb_impacts, /proc/machine_upgrade, /client/proc/populate_world, + /client/proc/get_dynex_power, //*debug verbs for dynex explosions. + /client/proc/get_dynex_range, //*debug verbs for dynex explosions. + /client/proc/set_dynex_scale, /client/proc/cmd_display_del_log, /client/proc/reset_latejoin_spawns, /client/proc/create_outfits, @@ -196,6 +201,10 @@ var/list/admin_verbs_hideable = list( /client/proc/cmd_admin_dress, /client/proc/cmd_admin_gib_self, /client/proc/drop_bomb, + /client/proc/drop_dynex_bomb, + /client/proc/get_dynex_range, + /client/proc/get_dynex_power, + /client/proc/set_dynex_scale, /client/proc/cinematic, /client/proc/send_space_ninja, /client/proc/cmd_admin_add_freeform_ai_law, @@ -514,6 +523,48 @@ var/list/admin_verbs_hideable = list( message_admins("[ckey] creating an admin explosion at [epicenter.loc].") feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/drop_dynex_bomb() + set category = "Special Verbs" + set name = "Drop DynEx Bomb" + set desc = "Cause an explosion of varying strength at your location." + + var/ex_power = input("Explosive Power:") as null|num + var/turf/epicenter = mob.loc + if(ex_power && epicenter) + dyn_explosion(epicenter, ex_power) + message_admins("[ckey] creating an admin explosion at [epicenter.loc].") + feedback_add_details("admin_verb","DDXB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/get_dynex_range() + set category = "Debug" + set name = "Get DynEx Range" + set desc = "Get the estimated range of a bomb, using explosive power." + + var/ex_power = input("Explosive Power:") as null|num + var/range = round((2 * ex_power)**DYN_EX_SCALE) + usr << "Estimated Explosive Range: (Devestation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])" + +/client/proc/get_dynex_power() + set category = "Debug" + set name = "Get DynEx Power" + set desc = "Get the estimated required power of a bomb, to reach a specific range." + + var/ex_range = input("Light Explosion Range:") as null|num + var/power = (0.5 * ex_range)**(1/DYN_EX_SCALE) + usr << "Estimated Explosive Power: [power]" + +/client/proc/set_dynex_scale() + set category = "Debug" + set name = "Set DynEx Scale" + set desc = "Set the scale multiplier of dynex explosions. The default is 0.5." + + var/ex_scale = input("New DynEx Scale:") as null|num + if(!ex_scale) + return + DYN_EX_SCALE = ex_scale + log_admin("[key_name(usr)] has modified Dynamic Explosion Scale: [ex_scale]") + message_admins("[key_name_admin(usr)] has modified Dynamic Explosion Scale: [ex_scale]") + /client/proc/give_spell(mob/T in mob_list) set category = "Fun" set name = "Give Spell" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 2a29ea6225a..d47aaa90f2d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1739,17 +1739,15 @@ usr << "This can only be used on instances of type /mob/living/carbon/human." return - H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_l_hand ) - if(!(istype(H.l_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) - H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_r_hand ) - if(!(istype(H.r_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) - log_admin("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") - message_admins("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") - return - else - H.update_inv_r_hand()//To ensure the icon appears in the HUD + var/obj/item/weapon/reagent_containers/food/snacks/cookie/cookie = new(H) + if(H.put_in_hands(cookie)) + H.update_inv_hands() else - H.update_inv_l_hand() + qdel(cookie) + log_admin("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") + message_admins("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") + return + log_admin("[key_name(H)] got their cookie, spawned by [key_name(src.owner)].") message_admins("[key_name(H)] got their cookie, spawned by [key_name(src.owner)].") feedback_inc("admin_cookies_spawned",1) diff --git a/code/modules/admin/verbs/fps.dm b/code/modules/admin/verbs/fps.dm index 0866a5859ea..901e6f636a4 100644 --- a/code/modules/admin/verbs/fps.dm +++ b/code/modules/admin/verbs/fps.dm @@ -7,18 +7,18 @@ if(!check_rights(R_DEBUG)) return - var/fps = round(input("Sets game frames-per-second. Can potentially break the game","FPS", config.fps) as num|null) + var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [config.fps])","FPS", world.fps) as num|null) - if(fps <= 0) - src << "Error: ticklag(): Invalid world.ticklag value. No changes made." + if(new_fps <= 0) + src << "Error: set_server_fps(): Invalid world.fps value. No changes made." return - if(fps > config.fps) - if(alert(src, "You are setting fps to a high value:\n\t[fps] frames-per-second\n\tconfig.fps = [config.fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm") + if(new_fps > config.fps*1.5) + if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [config.fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm") return - var/msg = "[key_name(src)] has modified world.fps to [fps]" + var/msg = "[key_name(src)] has modified world.fps to [new_fps]" log_admin(msg, 0) message_admins(msg, 0) feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - world.fps = fps \ No newline at end of file + world.fps = new_fps \ No newline at end of file diff --git a/code/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm index 82703edaa3e..289d1b6cd7d 100644 --- a/code/modules/admin/verbs/manipulate_organs.dm +++ b/code/modules/admin/verbs/manipulate_organs.dm @@ -26,7 +26,8 @@ organ.implant(C) if("drop organ/implant", "remove organ/implant") - for(var/obj/item/organ/I in C.internal_organs) + for(var/X in C.internal_organs) + var/obj/item/organ/I = X organs["[I.name] ([I.type])"] = I for(var/obj/item/weapon/implant/I in C) diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index bddc973b359..affb6b57bc9 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -76,11 +76,11 @@ var/obj/item/slot_item_ID = H.get_item_by_slot(slot_wear_id) qdel(slot_item_ID) - var/obj/item/slot_item_hand = H.get_item_by_slot(slot_r_hand) + var/obj/item/slot_item_hand = H.get_item_for_held_index(2) H.unEquip(slot_item_hand) var /obj/item/weapon/multisword/multi = new(H) - H.equip_to_slot_or_del(multi, slot_r_hand) + H.put_in_hands_or_del(multi) var/obj/item/weapon/card/id/W = new(H) W.icon_state = "centcom" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 1008453f85b..a229b10f337 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -441,7 +441,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/datum/round_event/ion_storm/ion = new(0, announce_ion_laws, input) ion.start() - + feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/cmd_admin_rejuvenate(mob/living/M in mob_list) @@ -595,7 +595,7 @@ Traitors and the like can also be revived with the previous role mostly intact. message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(M)]") if(istype(M, /mob/dead/observer)) - gibs(M.loc, M.viruses) + new /obj/effect/gibspawner/generic(M.loc, M.viruses) return if(confirm == "Yes") M.gib() @@ -612,7 +612,7 @@ Traitors and the like can also be revived with the previous role mostly intact. log_admin("[key_name(usr)] used gibself.") message_admins("[key_name_admin(usr)] used gibself.") feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - mob.gib(1, 1) + mob.gib(1, 1, 1) /client/proc/cmd_admin_check_contents(mob/living/M in mob_list) set category = "Special Verbs" @@ -1152,4 +1152,4 @@ var/list/datum/outfit/custom_outfits = list() //Admin created outfits for(var/datum/station_goal/S in ticker.mode.station_goals) dat += "[S.name] - Announce | Remove
" dat += "
Add New Goal" - usr << browse(dat, "window=goals;size=400x400") \ No newline at end of file + usr << browse(dat, "window=goals;size=400x400") diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index 2ca23434053..aece047550c 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -85,7 +85,7 @@ if(user && targeted) if(M.weakeyes) M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash - if(M.flash_eyes(1, 1)) + if(M.flash_act(1, 1)) M.confused += power terrible_conversion_proc(M, user) M.Stun(1) @@ -100,7 +100,7 @@ user << "You fail to blind [M] with the flash!" M << "[user] fails to blind you with the flash!" else - if(M.flash_eyes()) + if(M.flash_act()) M.confused += power /obj/item/device/assembly/flash/attack(mob/living/M, mob/user) @@ -117,7 +117,7 @@ update_icon(1) M.Weaken(6) R.confused += 5 - R.flash_eyes(affect_silicon = 1) + R.flash_act(affect_silicon = 1) user.visible_message("[user] overloads [R]'s sensors with the flash!", "You overload [R]'s sensors with the flash!") return 1 diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index fb643f482bc..31ecea937bd 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -60,8 +60,7 @@ H.Stun(3) if(affecting) if(affecting.take_damage(1, 0)) - H.update_damage_overlays(0) - H.updatehealth() + H.update_damage_overlays() else if(ismouse(target)) var/mob/living/simple_animal/mouse/M = target visible_message("SPLAT!") @@ -78,7 +77,7 @@ else if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50)) var/which_hand = "l_hand" - if(!user.hand) + if(!(user.active_hand_index % 2)) which_hand = "r_hand" triggered(user, which_hand) user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ @@ -94,7 +93,7 @@ if(armed) if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50)) var/which_hand = "l_hand" - if(!user.hand) + if(!(user.active_hand_index % 2)) which_hand = "r_hand" triggered(user, which_hand) user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ @@ -124,7 +123,7 @@ if(armed) finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ "You accidentally trigger [src]!") - triggered(finder, finder.hand ? "l_hand" : "r_hand") + triggered(finder, (finder.active_hand_index % 2 == 0) ? "r_hand" : "l_hand") return 1 //end the search! return 0 diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index ab8058af8a3..a2eef743256 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -154,9 +154,9 @@ if(back) H.equip_to_slot_or_del(new back(H), slot_back) if(l_hand) - H.equip_to_slot_or_del(new l_hand(H), slot_l_hand) + H.put_in_hands_or_del(new l_hand(H)) if(r_hand) - H.equip_to_slot_or_del(new r_hand(H), slot_r_hand) + H.put_in_hands_or_del(new r_hand(H)) if(has_id) var/obj/item/weapon/card/id/W = new(H) if(id_icon) diff --git a/code/modules/awaymissions/super_secret_room.dm b/code/modules/awaymissions/super_secret_room.dm index 2e0c60acf3c..2e4e1101163 100644 --- a/code/modules/awaymissions/super_secret_room.dm +++ b/code/modules/awaymissions/super_secret_room.dm @@ -105,7 +105,7 @@ /obj/item/rupee/Crossed(mob/M) if(M.put_in_hands(src)) - if(src != M.get_active_hand()) + if(src != M.get_active_held_item()) M.swap_hand() equip_to_best_slot(M) ..() diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index ab41d3cae8b..5764994c628 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -156,6 +156,7 @@ datum/supply_pack /datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C) var/crate_value = 50 + var/list/uplink_items = get_uplink_items(ticker.mode) while(crate_value) var/category = pick(uplink_items) var/item = pick(uplink_items[category]) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 7788d269c21..e37951e777e 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -143,7 +143,7 @@ var/global/normal_ooc_colour = OOC_COLOR src << "The Message of the Day has not been set." /client/proc/self_notes() - set name = "View Admin Notes" + set name = "View Admin Remarks" set category = "OOC" set desc = "View the notes that admins have written about you" diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 413590b6db8..659fe3f3c8d 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -10,7 +10,7 @@ if(confirm == "Yes") suiciding = 1 log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].") - var/obj/item/held_item = get_active_hand() + var/obj/item/held_item = get_active_held_item() if(held_item) var/damagetype = held_item.suicide_act(src) if(damagetype) @@ -53,7 +53,7 @@ adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) death(0) -/mob/living/carbon/brain/verb/suicide() +/mob/living/brain/verb/suicide() set hidden = 1 if(!canSuicide()) return diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a26dfacd4fb..55721e470d2 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -44,12 +44,7 @@ var/obj/screen/inventory/hand/H = over_object if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) - + M.put_in_hand(src, H.held_index) add_fingerprint(usr) /obj/item/clothing/throw_at(atom/target, range, speed, mob/thrower, spin) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 1c5375434f2..19bf143a1cd 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -9,7 +9,7 @@ if(!(H.disabilities & BLIND)) if(H.glasses == src) H << "The [src] overloads and blinds you!" - H.flash_eyes(visual = 1) + H.flash_act(visual = 1) H.blind_eyes(3) H.blur_eyes(5) H.adjust_eye_damage(5) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 340a2e174e9..e2dfe0f6cb8 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -60,7 +60,7 @@ var/turf/location = src.loc if(istype(location, /mob/)) var/mob/living/carbon/human/M = location - if(M.l_hand == src || M.r_hand == src || M.head == src) + if(M.is_holding(src) || M.head == src) location = M.loc if (istype(location, /turf)) diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm index 1cd4a500a97..84b7de07b84 100644 --- a/code/modules/clothing/outfits/standard.dm +++ b/code/modules/clothing/outfits/standard.dm @@ -52,7 +52,7 @@ if(visualsOnly) return - var/obj/item/weapon/reagent_containers/glass/bucket/bucket = H.l_hand + var/obj/item/weapon/reagent_containers/glass/bucket/bucket = H.get_item_for_held_index(1) bucket.reagents.add_reagent("water",70) /datum/outfit/laser_tag @@ -159,10 +159,10 @@ return //Could use a type - var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = H.l_hand + var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = H.get_item_for_held_index(1) for(var/obj/item/briefcase_item in sec_briefcase) qdel(briefcase_item) - for(var/i=3, i>0, i--) + for(var/i = 3 to 0 step -1) sec_briefcase.handle_item_insertion(new /obj/item/stack/spacecash/c1000,1) sec_briefcase.handle_item_insertion(new /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow,1) sec_briefcase.handle_item_insertion(new /obj/item/weapon/gun/projectile/revolver/mateba,1) diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 6506f8239c4..48154a4ae46 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -25,7 +25,7 @@ actions_types = list(/datum/action/item_action/toggle) armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 30, bio = 90, rad = 90) var/list/chronosafe_items = list(/obj/item/weapon/chrono_eraser, /obj/item/weapon/gun/energy/chrono_gun) - var/hands_nodrop_states + var/list/hands_nodrop = list() var/obj/item/clothing/head/helmet/space/chronos/helmet = null var/obj/effect/chronos_cam/camera = null var/image/phase_underlay = null @@ -92,10 +92,9 @@ user.notransform = 0 user.anchored = 0 teleporting = 0 - if(user.l_hand && !(hands_nodrop_states & 1)) - user.l_hand.flags &= ~NODROP - if(user.r_hand && !(hands_nodrop_states & 2)) - user.r_hand.flags &= ~NODROP + for(var/obj/item/I in user.held_items) + if(I in hands_nodrop) + I.flags &= ~NODROP if(phase_underlay && !qdeleted(phase_underlay)) user.underlays -= phase_underlay qdel(phase_underlay) @@ -119,7 +118,7 @@ teleport_now.UpdateButtonIcon() - var/list/nonsafe_slots = list(slot_belt, slot_back, slot_l_hand, slot_r_hand) + var/list/nonsafe_slots = list(slot_belt, slot_back) for(var/slot in nonsafe_slots) var/obj/item/slot_item = user.get_item_by_slot(slot) if(slot_item && !(slot_item.type in chronosafe_items) && user.unEquip(slot_item)) @@ -129,14 +128,11 @@ phase_underlay = create_phase_underlay(user) - hands_nodrop_states = 0 - if(user.l_hand) - hands_nodrop_states |= (user.l_hand.flags & NODROP) ? 1 : 0 - user.l_hand.flags |= NODROP - if(user.r_hand) - hands_nodrop_states |= (user.r_hand.flags & NODROP) ? 2 : 0 - user.r_hand.flags |= NODROP - + hands_nodrop = list() + for(var/obj/item/I in user.held_items) + if(!(I.flags & NODROP)) + hands_nodrop += I + I.flags |= NODROP user.animate_movement = NO_STEPS user.changeNext_move(8 + phase_in_ds) user.notransform = 1 diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm index 70f45474c5f..1e1ed209bf0 100644 --- a/code/modules/crafting/craft.dm +++ b/code/modules/crafting/craft.dm @@ -60,8 +60,8 @@ /datum/personal_crafting/proc/get_environment(mob/user) . = list() - . += user.r_hand - . += user.l_hand + for(var/obj/item/I in user.held_items) + . += I if(!istype(user.loc, /turf)) return var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST)) diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 0bd4fff922f..5dcbeb7c63b 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -94,17 +94,17 @@ /datum/crafting_recipe/ed209 name = "ED209" result = /mob/living/simple_animal/bot/ed209 - reqs = list(/obj/item/robot_parts/robot_suit = 1, + reqs = list(/obj/item/robot_suit = 1, /obj/item/clothing/head/helmet = 1, /obj/item/clothing/suit/armor/vest = 1, - /obj/item/robot_parts/l_leg = 1, - /obj/item/robot_parts/r_leg = 1, + /obj/item/bodypart/l_leg/robot = 1, + /obj/item/bodypart/r_leg/robot = 1, /obj/item/stack/sheet/metal = 5, /obj/item/stack/cable_coil = 5, /obj/item/weapon/gun/energy/gun/advtaser = 1, /obj/item/weapon/stock_parts/cell = 1, /obj/item/device/assembly/prox_sensor = 1, - /obj/item/robot_parts/r_arm = 1) + /obj/item/bodypart/r_arm/robot = 1) tools = list(/obj/item/weapon/weldingtool, /obj/item/weapon/screwdriver) time = 60 category = CAT_ROBOT @@ -116,7 +116,7 @@ /obj/item/clothing/head/helmet/sec = 1, /obj/item/weapon/melee/baton = 1, /obj/item/device/assembly/prox_sensor = 1, - /obj/item/robot_parts/r_arm = 1) + /obj/item/bodypart/r_arm/robot = 1) tools = list(/obj/item/weapon/weldingtool) time = 60 category = CAT_ROBOT @@ -126,7 +126,7 @@ result = /mob/living/simple_animal/bot/cleanbot reqs = list(/obj/item/weapon/reagent_containers/glass/bucket = 1, /obj/item/device/assembly/prox_sensor = 1, - /obj/item/robot_parts/r_arm = 1) + /obj/item/bodypart/r_arm/robot = 1) time = 40 category = CAT_ROBOT @@ -136,7 +136,7 @@ reqs = list(/obj/item/weapon/storage/toolbox/mechanical = 1, /obj/item/stack/tile/plasteel = 1, /obj/item/device/assembly/prox_sensor = 1, - /obj/item/robot_parts/r_arm = 1) + /obj/item/bodypart/r_arm/robot = 1) time = 40 category = CAT_ROBOT @@ -146,7 +146,7 @@ reqs = list(/obj/item/device/healthanalyzer = 1, /obj/item/weapon/storage/firstaid = 1, /obj/item/device/assembly/prox_sensor = 1, - /obj/item/robot_parts/r_arm = 1) + /obj/item/bodypart/r_arm/robot = 1) time = 40 category = CAT_ROBOT diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index 100eeacf175..ce7c7eb1f9f 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -37,10 +37,8 @@ if(istype(I.loc,/obj/item/weapon/storage)) //in a container. var/obj/item/weapon/storage/U = I.loc U.remove_from_storage(I, src) - else if(user.l_hand == I) //in a hand - user.drop_l_hand() - else if(user.r_hand == I) //in a hand - user.drop_r_hand() + if(user.is_holding(I)) + user.unEquip(I) else return diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm index 19b3ac4abfa..a2b2dbf31bc 100644 --- a/code/modules/events/anomaly_bluespace.dm +++ b/code/modules/events/anomaly_bluespace.dm @@ -44,7 +44,7 @@ var/list/flashers = list() for(var/mob/living/carbon/C in viewers(TO, null)) - if(C.flash_eyes()) + if(C.flash_act()) flashers += C var/y_distance = TO.y - FROM.y diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index 7c2d638ed9d..ec21c483973 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -47,7 +47,7 @@ var/cracked = 0 /obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user) - if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) + if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_held_item() ) target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a pop.") var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc) Joke.name = "[pick("awful","terrible","unfunny")] joke" diff --git a/code/modules/events/wizard/curseditems.dm b/code/modules/events/wizard/curseditems.dm index 300ecc83c69..5d0bc33b168 100644 --- a/code/modules/events/wizard/curseditems.dm +++ b/code/modules/events/wizard/curseditems.dm @@ -11,7 +11,7 @@ /datum/round_event/wizard/cursed_items/start() var/item_set = pick("wizardmimic", "swords", "bigfatdoobie", "boxing", "voicemodulators", "catgirls2015") - var/list/wearslots = list(slot_wear_suit, slot_shoes, slot_head, slot_wear_mask, slot_r_hand, slot_gloves, slot_ears) + var/list/wearslots = list(slot_wear_suit, slot_shoes, slot_head, slot_wear_mask, slot_gloves, slot_ears) var/list/loadout = list() var/ruins_spaceworthiness var/ruins_wizard_loadout @@ -44,8 +44,8 @@ continue if(item_set == "catgirls2015") //Wizard code means never having to say you're sorry H.gender = FEMALE - var/list/slots = list(H.wear_suit, H.shoes, H.head, H.wear_mask, H.r_hand, H.gloves, H.ears) //add new slots as needed to back - for(var/i = 1, i <= loadout.len, i++) + var/list/slots = list(H.wear_suit, H.shoes, H.head, H.wear_mask, H.gloves, H.ears) //add new slots as needed to back + for(var/i in 1 to loadout.len) if(loadout[i]) var/obj/item/J = loadout[i] var/obj/item/I = new J //dumb but required because of byond throwing a fit anytime new gets too close to a list diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index ad237db5be9..7e34d6a1b3a 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -324,14 +324,10 @@ Gunshots/explosions/opening doors/less rare audio (done) return var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(get_turf(target),target) - if(clone.l_hand) - if(!(locate(clone.l_hand) in non_fakeattack_weapons)) - clone_weapon = clone.l_hand.name - F.weap = clone.l_hand - else if (clone.r_hand) - if(!(locate(clone.r_hand) in non_fakeattack_weapons)) - clone_weapon = clone.r_hand.name - F.weap = clone.r_hand + for(var/obj/item/I in clone.held_items) + if(!(locate(I) in non_fakeattack_weapons)) + clone_weapon = I.name + F.weap = I F.name = clone.name F.my_target = target @@ -619,9 +615,13 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite //src << "Traitor Items" if(!halitem) halitem = new - var/list/slots_free = list(ui_lhand,ui_rhand) - if(l_hand) slots_free -= ui_lhand - if(r_hand) slots_free -= ui_rhand + var/obj/item/l_hand = get_item_for_held_index(1) + var/obj/item/r_hand = get_item_for_held_index(2) + var/l = ui_hand_position(get_held_index_of_item(l_hand)) + var/r = ui_hand_position(get_held_index_of_item(r_hand)) + var/list/slots_free = list(l,r) + if(l_hand) slots_free -= l + if(r_hand) slots_free -= r if(istype(src,/mob/living/carbon/human)) var/mob/living/carbon/human/H = src if(!H.belt) slots_free += ui_belt diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 2f88a2ae9d5..62532557e49 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -62,7 +62,7 @@ /obj/machinery/gibber/RefreshParts() var/gib_time = 40 for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - meat_produced += 3 * B.rating + meat_produced += B.rating for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) gib_time -= 5 * M.rating gibtime = gib_time @@ -229,7 +229,7 @@ var/obj/item/meatslab = allmeat[i] meatslab.loc = src.loc meatslab.throw_at_fast(pick(nearby_turfs),i,3) - for (var/turfs=1 to meat_produced*3) + for (var/turfs=1 to meat_produced) var/turf/gibturf = pick(nearby_turfs) if (!gibturf.density && src in view(gibturf)) new gibtype(gibturf,i) diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index 55653911f47..c55c399eecc 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -85,7 +85,7 @@ update_icon() /obj/item/pizzabox/attack_hand(mob/user) - if(user.get_inactive_hand() != src) + if(user.get_inactive_held_item() != src) ..() return if(open) diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm index f5bd17e0ed0..4787f2829b0 100644 --- a/code/modules/hydroponics/gene_modder.dm +++ b/code/modules/hydroponics/gene_modder.dm @@ -234,7 +234,7 @@ update_genes() update_icon() else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if (istype(I, /obj/item/seeds)) if(!usr.drop_item()) return @@ -248,7 +248,7 @@ disk = null update_genes() else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/disk/plantgene)) if(!usr.drop_item()) return @@ -396,7 +396,7 @@ ..() if(istype(W, /obj/item/weapon/pen)) var/t = stripped_input(user, "What would you like the label to be?", name, null) - if(user.get_active_hand() != W) + if(user.get_active_held_item() != W) return if(!in_range(src, user) && loc != user) return diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm index 4e641c4e8cd..be9ef5838ac 100644 --- a/code/modules/hydroponics/grown/chili.dm +++ b/code/modules/hydroponics/grown/chili.dm @@ -83,7 +83,7 @@ /obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chili/process() if(held_mob && src.loc == held_mob) - if( (held_mob.l_hand == src) || (held_mob.r_hand == src)) + if(held_mob.is_holding(src)) if(hasvar(held_mob,"gloves") && held_mob:gloves) return held_mob.bodytemperature += 15 * TEMPERATURE_DAMAGE_COEFFICIENT diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm index dac4b76aa3e..be78c4ef8b2 100644 --- a/code/modules/hydroponics/grown/nettle.dm +++ b/code/modules/hydroponics/grown/nettle.dm @@ -51,16 +51,13 @@ if(!iscarbon(user)) return 0 var/mob/living/carbon/C = user - if(ishuman(user)) - var/mob/living/carbon/human/H = C - if(H.gloves) - return 0 - var/organ = ((H.hand ? "l_":"r_") + "arm") - var/obj/item/bodypart/affecting = H.get_bodypart(organ) - if(affecting && affecting.take_damage(0, force)) - H.update_damage_overlays(0) - else - C.take_organ_damage(0,force) + if(C.gloves) + return 0 + var/hit_zone = (C.held_index_to_dir(C.active_hand_index) == "l" ? "l_":"r_") + "arm" + var/obj/item/bodypart/affecting = C.get_bodypart(hit_zone) + if(affecting) + if(affecting.take_damage(0, force)) + C.update_damage_overlays() C << "The nettle burns your bare hand!" return 1 diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 4b6a96add86..0b15123b142 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -115,16 +115,16 @@ else if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M //if they are holding or wearing a card that has access, that works - if(check_access(H.get_active_hand()) || src.check_access(H.wear_id)) + if(check_access(H.get_active_held_item()) || src.check_access(H.wear_id)) return 1 else if(istype(M, /mob/living/carbon/monkey) || istype(M, /mob/living/carbon/alien/humanoid)) var/mob/living/carbon/george = M //they can only hold things :( - if(check_access(george.get_active_hand())) + if(check_access(george.get_active_held_item())) return 1 else if(isanimal(M)) var/mob/living/simple_animal/A = M - if(check_access(A.get_active_hand()) || check_access(A.access_card)) + if(check_access(A.get_active_held_item()) || check_access(A.access_card)) return 1 return 0 diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index c5d9add72cc..43ca9d51012 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -102,7 +102,7 @@ if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) return if(ishuman(user)) - if(!user.get_active_hand()) + if(!user.get_active_held_item()) user.put_in_hands(choice) else choice.loc = get_turf(src) @@ -264,7 +264,7 @@ B.name = src.name B.title = src.title B.icon_state = src.icon_state - if(user.l_hand == src || user.r_hand == src) + if(user.is_holding(src)) qdel(src) user.put_in_hands(B) return diff --git a/code/modules/mining/equipment.dm b/code/modules/mining/equipment.dm index 1b8e9a56612..adcd2b4762c 100644 --- a/code/modules/mining/equipment.dm +++ b/code/modules/mining/equipment.dm @@ -507,7 +507,7 @@ range = 6 var/obj/item/weapon/twohanded/required/mining_hammer/hammer_synced = null -/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0) if(hammer_synced) if(hammer_synced.mark == target) return ..() diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index 58e13865f94..6c328b8cd64 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -74,14 +74,14 @@ switch(action) if("handle_id") if(inserted_id) - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr.put_in_hands(inserted_id) inserted_id = null else inserted_id.forceMove(get_turf(src)) inserted_id = null else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if(istype(I, /obj/item/weapon/card/id/prisoner)) if(!usr.drop_item()) return diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm new file mode 100644 index 00000000000..eb9e319ee09 --- /dev/null +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -0,0 +1,252 @@ +/obj/structure/flora/ash + gender = PLURAL + layer = PROJECTILE_HIT_THRESHHOLD_LAYER //sporangiums up don't shoot + icon = 'icons/obj/lavaland/ash_flora.dmi' + icon_state = "l_mushroom" + name = "large mushrooms" + desc = "A number of large mushrooms, covered in a faint layer of ash and what can only be spores." + var/harvested_name = "shortened mushrooms" + var/harvested_desc = "Some quickly regrowing mushrooms, formerly known to be quite large." + var/needs_sharp_harvest = TRUE + var/harvest = /obj/item/ash_flora/shavings + var/harvest_amount_low = 1 + var/harvest_amount_high = 3 + var/harvest_time = 60 + var/harvest_message_low = "You pick a mushroom, but fail to collect many shavings from its cap." + var/harvest_message_med = "You pick a mushroom, carefully collecting the shavings from its cap." + var/harvest_message_high = "You harvest and collect shavings from several mushroom caps." + var/harvested = FALSE + var/base_icon + var/regrowth_time_low = 4800 + var/regrowth_time_high = 8400 + +/obj/structure/flora/ash/New() + ..() + base_icon = "[icon_state][rand(1, 4)]" + icon_state = base_icon + if(prob(15)) + harvest(null, TRUE) + +/obj/structure/flora/ash/proc/harvest(user, no_drop) + if(harvested) + return 0 + if(!no_drop) + var/rand_harvested = rand(harvest_amount_low, harvest_amount_high) + if(rand_harvested) + if(user) + var/msg = harvest_message_med + if(rand_harvested == harvest_amount_low) + msg = harvest_message_low + else if(rand_harvested == harvest_amount_high) + msg = harvest_message_high + user << "[msg]" + for(var/i in 1 to rand_harvested) + new harvest(get_turf(src)) + icon_state = "[base_icon]p" + name = harvested_name + desc = harvested_desc + harvested = TRUE + addtimer(src, "regrow", rand(regrowth_time_low, regrowth_time_high)) + return 1 + +/obj/structure/flora/ash/proc/regrow() + icon_state = base_icon + name = initial(name) + desc = initial(desc) + harvested = FALSE + +/obj/structure/flora/ash/attackby(obj/item/weapon/W, mob/user, params) + if(!harvested && needs_sharp_harvest && W.sharpness) + user.visible_message("[user] starts to harvest from [src] with [W].","You begin to harvest from [src] with [W].") + if(do_after(user, harvest_time, target = src)) + harvest(user) + else + return ..() + +/obj/structure/flora/ash/attack_hand(mob/user) + if(!harvested && !needs_sharp_harvest) + user.visible_message("[user] starts to harvest from [src].","You begin to harvest from [src].") + if(do_after(user, harvest_time, target = src)) + harvest(user) + else + ..() + +/obj/structure/flora/ash/leaf_shroom + icon_state = "s_mushroom" + name = "leafy mushrooms" + desc = "A number of mushrooms, each of which surrounds a greenish sporangium with a number of leaf-like structures." + harvested_name = "leafless mushrooms" + harvested_desc = "A bunch of formerly-leafed mushrooms, with their sporangiums exposed. Scandalous?" + harvest = /obj/item/ash_flora/mushroom_leaf + needs_sharp_harvest = FALSE + harvest_amount_high = 4 + harvest_time = 20 + harvest_message_low = "You pluck a single, suitable leaf." + harvest_message_med = "You pluck a number of leaves, leaving a few unsuitable ones." + harvest_message_high = "You pluck quite a lot of suitable leaves." + regrowth_time_low = 2400 + regrowth_time_high = 6000 + +/obj/structure/flora/ash/cap_shroom + icon_state = "r_mushroom" + name = "tall mushrooms" + desc = "Several mushrooms, the larger of which have a ring of conks at the midpoint of their stems." + harvested_name = "small mushrooms" + harvested_desc = "Several small mushrooms near the stumps of what likely were larger mushrooms." + harvest = /obj/item/ash_flora/mushroom_cap + harvest_amount_high = 4 + harvest_time = 50 + harvest_message_low = "You slice the cap off of a mushroom." + harvest_message_med = "You slice off a few conks from the larger mushrooms." + harvest_message_high = "You slice off a number of caps and conks from these mushrooms." + regrowth_time_low = 3000 + regrowth_time_high = 5400 + +/obj/structure/flora/ash/stem_shroom + icon_state = "t_mushroom" + name = "numerous mushrooms" + desc = "A large number of mushrooms, some of which have long, fleshy stems." + harvested_name = "tiny mushrooms" + harvested_desc = "A few tiny mushrooms around larger stumps. You can already see them growing back." + harvest = /obj/item/ash_flora/mushroom_stem + harvest_amount_high = 4 + harvest_time = 40 + harvest_message_low = "You pick and slice the cap off of a mushroom, leaving the stem." + harvest_message_med = "You pick and decapitate several mushrooms for their stems." + harvest_message_high = "You acquire a number of stems from these mushrooms." + regrowth_time_low = 3000 + regrowth_time_high = 6000 + +/obj/structure/flora/ash/cacti + icon_state = "cactus" + name = "fruiting cacti" + desc = "Several prickly cacti, brimming with ripe fruit and covered in a thin layer of ash." + harvested_name = "cacti" + harvested_desc = "A bunch of prickly cacti. You can see fruits slowly growing beneath the covering of ash." + harvest = /obj/item/ash_flora/cactus_fruit + needs_sharp_harvest = FALSE + harvest_amount_high = 2 + harvest_time = 10 + harvest_message_low = "You pick a cactus fruit." + harvest_message_med = "You pick several cactus fruit." //shouldn't show up, because you can't get more than two + harvest_message_high = "You pick a pair of cactus fruit." + regrowth_time_low = 4800 + regrowth_time_high = 7200 + +/obj/structure/flora/ash/cacti/Crossed(mob/AM) + if(ishuman(AM) && has_gravity(loc) && prob(70)) + var/mob/living/carbon/human/H = AM + if(!H.shoes && !H.lying) //ouch, my feet. + var/picked_def_zone = pick("l_leg", "r_leg") + var/obj/item/bodypart/O = H.get_bodypart(picked_def_zone) + if(!istype(O) || (PIERCEIMMUNE in H.dna.species.specflags)) + return + H.apply_damage(rand(3, 6), BRUTE, picked_def_zone) + H.Weaken(2) + H.visible_message("[H] steps on a cactus!", \ + "You step on a cactus!") + +/obj/item/ash_flora + name = "mushroom shavings" + desc = "Some shavings from a tall mushroom. With enough, might serve as a bowl." + icon = 'icons/obj/lavaland/ash_flora.dmi' + icon_state = "mushroom_shavings" + w_class = 1 + burn_state = FLAMMABLE + burntime = 30 + var/prepared = FALSE + var/prepared_type = /obj/item/ash_flora/shavings + var/standard_prep = TRUE + +/obj/item/ash_flora/New() + ..() + pixel_x = rand(-4, 4) + pixel_y = rand(-4, 4) + +/obj/item/ash_flora/attackby(obj/item/weapon/W, mob/user, params) + if(!standard_prep || !W.sharpness || !prepare(user)) + return ..() + +/obj/item/ash_flora/proc/prepare(mob/user) + if(!prepared) + prepared = TRUE + user << "You prepare [src]." + var/obj/item/ash_flora/A = new prepared_type(get_turf(src)) + if(user.is_holding(src)) + user.unEquip(src, TRUE) + user.put_in_hands(A) + qdel(src) + . = 1 + +/obj/item/ash_flora/shavings //for actual crafting + prepared = TRUE + +/obj/item/ash_flora/mushroom_leaf + name = "mushroom leaf" + desc = "A leaflike structure from a mushroom. You should probably wash the ash off." + icon_state = "mushroom_leaf" + standard_prep = FALSE + prepared_type = /obj/item/ash_flora/mushroom_leaf/prepared + +/obj/item/ash_flora/mushroom_leaf/afterattack(atom/target, mob/user, proximity_flag) + if(proximity_flag && (istype(target, /turf/open/floor/plating/ashplanet/wateryrock) || istype(target, /obj/structure/sink))) + prepare(user) + +/obj/item/ash_flora/mushroom_leaf/prepared + name = "washed mushroom leaf" + desc = "A greenish leaflike structure from a mushroom. Kind of like lettuce?" + icon_state = "mushroom_leaf_p" + prepared = TRUE + +/obj/item/ash_flora/mushroom_cap + name = "mushroom cap" + desc = "A mushroom cap. Possibly delicious, at least if you cut it up a bit first." + icon_state = "mushroom_cap" + prepared_type = /obj/item/ash_flora/mushroom_cap/prepared + +/obj/item/ash_flora/mushroom_cap/prepared + name = "sliced mushroom cap" + desc = "A sliced-up mushroom cap, revealing pale yellow innards. It smells faintly salty." + icon_state = "mushroom_cap_p" + prepared = TRUE + +/obj/item/ash_flora/mushroom_stem + name = "mushroom stem" + desc = "A mushroom stem. Slice it up, throw it in a stew." + icon_state = "mushroom_stem" + prepared_type = /obj/item/ash_flora/mushroom_stem/prepared + +/obj/item/ash_flora/mushroom_stem/prepared + name = "sliced mushroom stem" + desc = "A mushroom stem, cut in half to reveal orange flesh. Smells almost like potatos, but with a sour undertone." + icon_state = "mushroom_stem_p" + prepared = TRUE + +/obj/item/ash_flora/cactus_fruit + name = "cactus fruit" + desc = "A cactus fruit covered in a thick, reddish skin. And some ash." + icon_state = "cactus_fruit" + prepared_type = /obj/item/ash_flora/cactus_fruit/prepared + +/obj/item/ash_flora/cactus_fruit/prepared + name = "peeled cactus fruit" + desc = "A cactus fruit with the skin and ash carefully scraped off, revealing a faintly sweet-smelling yellow center." + icon_state = "cactus_fruit_p" + prepared = TRUE + +/obj/item/mushroom_bowl + name = "mushroom bowl" + desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point." + icon = 'icons/obj/lavaland/ash_flora.dmi' + icon_state = "mushroom_bowl" + w_class = 2 + burn_state = FLAMMABLE + burntime = 40 + +//what you can craft with these things +/datum/crafting_recipe/mushroom_bowl + name = "Mushroom Bowl" + result = /obj/item/mushroom_bowl + reqs = list(/obj/item/ash_flora/shavings = 5) + time = 30 + //category = CAT_PRIMAL //uncomment once ashplanet exists and this wouldn't just take up space fnr diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 802c6683669..c17e682949e 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -342,11 +342,7 @@ var/obj/screen/inventory/hand/H = over_object if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) add_fingerprint(usr) @@ -756,7 +752,7 @@ if(H == L) continue H << "You have an overwhelming desire to kill [L]. They have been marked red! Go kill them!" - H.equip_to_slot_or_del(new /obj/item/weapon/kitchen/knife/butcher(H), slot_l_hand) + H.put_in_hands_or_del(new /obj/item/weapon/kitchen/knife/butcher(H)) qdel(src) @@ -833,7 +829,7 @@ else user << "You need to be on solid ground to produce a rune!" return - if(src != user.l_hand && src != user.r_hand) //you need to hold the staff to teleport + if(!user.is_holding(src)) //you need to hold the staff to teleport user << "You need to hold the staff in your hands to [rune ? "teleport with it":"create a rune"]!" return if(get_dist(user, rune) <= 2) //rune too close abort diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index e2b8ba82473..443f37ea406 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -102,7 +102,7 @@ if (!powered()) return if(istype(W,/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I = user.get_active_hand() + var/obj/item/weapon/card/id/I = user.get_active_held_item() if(istype(I) && !istype(inserted_id)) if(!user.drop_item()) return @@ -209,7 +209,7 @@ else usr << "Required access not found." else if(href_list["choice"] == "insert") - var/obj/item/weapon/card/id/I = usr.get_active_hand() + var/obj/item/weapon/card/id/I = usr.get_active_held_item() if(istype(I)) if(!usr.drop_item()) return diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index a3984de77d4..fdb907cac4b 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -121,7 +121,7 @@ inserted_id.verb_pickup() inserted_id = null else if(href_list["choice"] == "insert") - var/obj/item/weapon/card/id/I = usr.get_active_hand() + var/obj/item/weapon/card/id/I = usr.get_active_held_item() if(istype(I)) if(!usr.drop_item()) return @@ -149,7 +149,7 @@ RedeemVoucher(I, user) return if(istype(I,/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = usr.get_active_hand() + var/obj/item/weapon/card/id/C = usr.get_active_held_item() if(istype(C) && !istype(inserted_id)) if(!usr.drop_item()) return diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 0e2da91c20d..2438bd0b626 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -436,10 +436,9 @@ ..() if(istype(AM,/mob/living/carbon/human)) var/mob/living/carbon/human/H = AM - if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand)) - src.attackby(H.l_hand,H) - else if((istype(H.r_hand,/obj/item/weapon/pickaxe)) && H.hand) - src.attackby(H.r_hand,H) + var/obj/item/I = H.is_holding_item_of_type(/obj/item/weapon/pickaxe) + if(I) + attackby(I,H) return else if(istype(AM,/mob/living/silicon/robot)) var/mob/living/silicon/robot/R = AM diff --git a/code/modules/mob/interactive.dm b/code/modules/mob/interactive.dm index a6910a62eac..7be2862b0fc 100644 --- a/code/modules/mob/interactive.dm +++ b/code/modules/mob/interactive.dm @@ -137,13 +137,14 @@ retal = 1 retal_target = user -/mob/living/carbon/human/interactive/bullet_act(var/obj/item/projectile/P) +/mob/living/carbon/human/interactive/bullet_act(obj/item/projectile/P, def_zone) var/potentialAssault = locate(/mob/living) in view(2,P.starting) if(potentialAssault) retal = 1 retal_target = potentialAssault ..() + /client/proc/resetSNPC(var/mob/A in SSnpc.botPool_l) set name = "Reset SNPC" set desc = "Reset the SNPC" @@ -296,11 +297,9 @@ for(var/X in bodyparts) var/obj/item/bodypart/BP = X if(prob((FUZZY_CHANCE_LOW+FUZZY_CHANCE_HIGH)/4)) - BP.change_bodypart_status(ORGAN_ROBOTIC) + BP.change_bodypart_status(BODYPART_ROBOTIC) update_icons() - update_damage_overlays(0) - - hand = 0 + update_damage_overlays() functions = list("nearbyscan","combat","shitcurity","chatter") // stop customize adding multiple copies of a function //job specific favours switch(myjob.title) @@ -424,10 +423,6 @@ if(C) retalTarget(C) -/mob/living/carbon/human/interactive/bullet_act(obj/item/projectile/P, def_zone) - ..(P,def_zone) - retalTarget(P.firer) - /mob/living/carbon/human/interactive/attack_hand(mob/living/carbon/human/M) ..(M) retalTarget(M) @@ -491,28 +486,35 @@ if(other_hand) if(other_hand.loc != src) other_hand = null - if(hand) - if(!l_hand) + + var/obj/item/L = get_item_for_held_index(1) //just going to hardcode SNPCs to 2 hands, for now. + var/obj/item/R = get_item_for_held_index(2) //they're just VERY assume-y about 2 hands. + if(active_hand_index == 1) + if(!L) main_hand = null - if(r_hand) + if(R) swap_hands() else - if(!r_hand) + if(!R) main_hand = null - if(l_hand) + if(L) swap_hands() + /mob/living/carbon/human/interactive/proc/swap_hands() - hand = !hand - var/obj/item/T = other_hand - main_hand = other_hand - other_hand = T + var/oindex = active_hand_index + if(active_hand_index == 1) + active_hand_index = 2 + else + active_hand_index = 1 + main_hand = get_active_held_item() + other_hand = get_item_for_held_index(oindex) update_hands = 1 /mob/living/carbon/human/interactive/proc/take_to_slot(obj/item/G, var/hands=0) - var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_l_hand,"right hand" = slot_r_hand) + var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_hands,"right hand" = slot_hands) if(hands) - slots = list ("left hand" = slot_l_hand,"right hand" = slot_r_hand) + slots = list ("left hand" = slot_hands,"right hand" = slot_hands) G.loc = src if(G.force && G.force > best_force) best_force = G.force @@ -520,7 +522,7 @@ update_hands = 1 /mob/living/carbon/human/interactive/proc/insert_into_backpack() - var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_l_hand,"right hand" = slot_r_hand) + var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_hands,"right hand" = slot_hands) var/obj/item/I = get_item_by_slot(pick(slots)) var/obj/item/weapon/storage/BP = get_item_by_slot(slot_back) if(back && BP && I) @@ -604,14 +606,16 @@ D.open() if(update_hands) + var/obj/item/l_hand = get_item_for_held_index(1) + var/obj/item/r_hand = get_item_for_held_index(2) if(l_hand || r_hand) if(l_hand) - hand = 1 + active_hand_index = 1 main_hand = l_hand if(r_hand) other_hand = r_hand else if(r_hand) - hand = 0 + active_hand_index = 2 main_hand = r_hand if(l_hand) //this technically shouldnt occur, but its a redundancy other_hand = l_hand @@ -659,12 +663,12 @@ if(istype(TARGET, /obj/item/weapon)) var/obj/item/weapon/W = TARGET if(W.force >= best_force || prob((FUZZY_CHANCE_LOW+FUZZY_CHANCE_HIGH)/2)) - if(!l_hand || !r_hand) + if(!get_item_for_held_index(1) || !get_item_for_held_index(2)) put_in_hands(W) else insert_into_backpack() else - if(!l_hand || !r_hand) + if(!get_item_for_held_index(1) || !get_item_for_held_index(2)) put_in_hands(TARGET) else insert_into_backpack() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 1268581a38b..ecaf9f1c75f 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -1,178 +1,287 @@ -//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc +//These procs handle putting s tuff in your hands //as they handle all relevant stuff like adding it to the player's screen and updating their overlays. -//Returns the thing in our active hand -/mob/proc/get_active_hand() - if(hand) - return l_hand - else - return r_hand +//Returns the thing we're currently holding +/mob/proc/get_active_held_item() + return get_item_for_held_index(active_hand_index) -//Returns the thing in our inactive hand -/mob/proc/get_inactive_hand() - if(hand) - return r_hand +//Finds the opposite limb for the active one (eg: upper left arm will find the item in upper right arm) +//So we're treating each "pair" of limbs as a team, so "both" refers to them +/mob/proc/get_inactive_held_item() + return get_item_for_held_index(get_inactive_hand_index()) + + +//Finds the opposite index for the active one (eg: upper left arm will find the item in upper right arm) +//So we're treating each "pair" of limbs as a team, so "both" refers to them +/mob/proc/get_inactive_hand_index() + var/other_hand = 0 + if(!(active_hand_index % 2)) + other_hand = active_hand_index-1 //finding the matching "left" limb else - return l_hand + other_hand = active_hand_index+1 //finding the matching "right" limb + if(other_hand < 0 || other_hand > held_items.len) + other_hand = 0 + return other_hand + + +/mob/proc/get_item_for_held_index(i) + if(i > 0 && i <= held_items.len) + return held_items[i] + return FALSE + + +//Odd = left. Even = right +/mob/proc/held_index_to_dir(i) + if(!(i % 2)) + return "r" + return "l" + + +//Check we have an organ for this hand slot (Dismemberment), Only relevant for humans +/mob/proc/has_hand_for_held_index(i) + return TRUE + + +//Check we have an organ for our active hand slot (Dismemberment),Only relevant for humans +/mob/proc/has_active_hand() + return has_hand_for_held_index(active_hand_index) + + +//Finds the first available (null) index OR all available (null) indexes in held_items based on a side. +//Lefts: 1, 3, 5, 7... +//Rights:2, 4, 6, 8... +/mob/proc/get_empty_held_index_for_side(side = "left", all = FALSE) + var/start = 0 + var/static/list/lefts = list("l" = TRUE,"L" = TRUE,"LEFT" = TRUE,"left" = TRUE) + var/static/list/rights = list("r" = TRUE,"R" = TRUE,"RIGHT" = TRUE,"right" = TRUE) //"to remain silent" + if(lefts[side]) + start = 1 + else if(rights[side]) + start = 2 + if(!start) + return FALSE + var/list/empty_indexes + for(var/i in start to held_items.len step 2) + if(!held_items[i]) + if(!all) + return i + if(!empty_indexes) + empty_indexes = list() + empty_indexes += i + return empty_indexes + + +//Same as the above, but returns the first or ALL held *ITEMS* for the side +/mob/proc/get_held_items_for_side(side = "left", all = FALSE) + var/start = 0 + var/static/list/lefts = list("l" = TRUE,"L" = TRUE,"LEFT" = TRUE,"left" = TRUE) + var/static/list/rights = list("r" = TRUE,"R" = TRUE,"RIGHT" = TRUE,"right" = TRUE) //"to remain silent" + if(lefts[side]) + start = 1 + else if(rights[side]) + start = 2 + if(!start) + return FALSE + var/list/holding_items + for(var/i in start to held_items.len step 2) + var/obj/item/I = held_items[i] + if(I) + if(!all) + return I + if(!holding_items) + holding_items = list() + holding_items += I + return holding_items + + +/mob/proc/get_empty_held_indexes() + var/list/L + for(var/i in 1 to held_items.len) + if(!held_items[i]) + if(!L) + L = list() + L += i + return L + +/mob/proc/get_held_index_of_item(obj/item/I) + return held_items.Find(I) + + +//Sad that this will cause some overhead, but the alias seems necessary +//*I* may be happy with a million and one references to "indexes" but others won't be +/mob/proc/is_holding(obj/item/I) + return get_held_index_of_item(I) + + +//Checks if we're holding an item of type: typepath +/mob/proc/is_holding_item_of_type(typepath) + for(var/obj/item/I in held_items) + if(istype(I, typepath)) + return I + return FALSE + + +//To appropriately fluff things like "they are holding [I] in their [get_held_index_name(get_held_index_of_item(I))]" +//Can be overriden to pass off the fluff to something else (eg: science allowing people to add extra robotic limbs, and having this proc react to that +// with say "they are holding [I] in their Nanotrasen Brand Utility Arm - Right Edition" or w/e +/mob/proc/get_held_index_name(i) + var/list/hand = list() + if(i > 2) + hand += "upper " + var/num = 0 + if(!(i % 2)) + num = i-2 + hand += "right hand" + else + num = i-1 + hand += "left hand" + num -= (num*0.5) + if(num > 1) //"upper left hand #1" seems weird, but "upper left hand #2" is A-ok + hand += " #[num]" + return hand.Join() + //Returns if a certain item can be equipped to a certain slot. // Currently invalid for two-handed items - call obj/item/mob_can_equip() instead. /mob/proc/can_equip(obj/item/I, slot, disable_warning = 0) - return 0 - -//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. -/mob/proc/put_in_l_hand(obj/item/W) - if(!put_in_hand_check(W)) - return 0 - if(!has_left_hand()) - return 0 - if(!l_hand) - W.loc = src //TODO: move to equipped? - l_hand = W - W.layer = ABOVE_HUD_LAYER //TODO: move to equipped? - W.equipped(src,slot_l_hand) - if(W.pulledby) - W.pulledby.stop_pulling() - update_inv_l_hand() - W.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) - return 1 - return 0 + return FALSE -//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success. -/mob/proc/put_in_r_hand(obj/item/W) - if(!put_in_hand_check(W)) - return 0 - if(!has_right_hand()) - return 0 - if(!r_hand) - W.loc = src - r_hand = W - W.layer = ABOVE_HUD_LAYER - W.equipped(src,slot_r_hand) - if(W.pulledby) - W.pulledby.stop_pulling() - update_inv_r_hand() - W.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) - return 1 - return 0 - -/mob/proc/put_in_hand_check(obj/item/W) - if(lying && !(W.flags&ABSTRACT)) - return 0 - if(!istype(W)) - return 0 - return 1 - -//Puts the item into our active hand if possible. returns 1 on success. -/mob/proc/put_in_active_hand(obj/item/W) - if(hand) - return put_in_l_hand(W) - else - return put_in_r_hand(W) +/mob/proc/put_in_hand(obj/item/I, hand_index) + if(!put_in_hand_check(I)) + return FALSE + if(!has_hand_for_held_index(hand_index)) + return FALSE + var/obj/item/curr = held_items[hand_index] + if(!curr) + I.loc = src + held_items[hand_index] = I + I.layer = ABOVE_HUD_LAYER + I.equipped(src, slot_hands) + if(I.pulledby) + I.pulledby.stop_pulling() + update_inv_hands() + I.pixel_x = initial(I.pixel_x) + I.pixel_y = initial(I.pixel_y) + return hand_index || TRUE + return FALSE -//Puts the item into our inactive hand if possible. returns 1 on success. -/mob/proc/put_in_inactive_hand(obj/item/W) - if(hand) - return put_in_r_hand(W) - else - return put_in_l_hand(W) +//Puts the item into the first available left hand if possible and calls all necessary triggers/updates. returns 1 on success. +/mob/proc/put_in_l_hand(obj/item/I) + return put_in_hand(I, get_empty_held_index_for_side("l")) -//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. -//If both fail it drops it on the floor and returns 0. +//Puts the item into the first available right hand if possible and calls all necessary triggers/updates. returns 1 on success. +/mob/proc/put_in_r_hand(obj/item/I) + return put_in_hand(I, get_empty_held_index_for_side("r")) + + +/mob/proc/put_in_hand_check(obj/item/I) + if(lying && !(I.flags&ABSTRACT)) + return FALSE + if(!istype(I)) + return FALSE + return TRUE + + +//Puts the item into our active hand if possible. returns TRUE on success. +/mob/proc/put_in_active_hand(obj/item/I) + return put_in_hand(I, active_hand_index) + + +//Puts the item into our inactive hand if possible, returns TRUE on success +/mob/proc/put_in_inactive_hand(obj/item/I) + return put_in_hand(I, get_inactive_hand_index()) + + +//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns TRUE on success. +//If both fail it drops it on the floor and returns FALSE. //This is probably the main one you need to know :) -/mob/proc/put_in_hands(obj/item/W) - if(!W) - return 0 - if(put_in_active_hand(W)) - return 1 - else if(put_in_inactive_hand(W)) - return 1 - else - W.loc = get_turf(src) - W.layer = initial(W.layer) - W.dropped(src) - return 0 +/mob/proc/put_in_hands(obj/item/I, del_on_fail = FALSE) + if(!I) + return FALSE + var/hand = get_empty_held_index_for_side("l") + if(!hand) + hand = get_empty_held_index_for_side("r") + if(hand) + if(put_in_hand(I, hand)) + return TRUE + if(del_on_fail) + qdel(I) + return FALSE + I.forceMove(get_turf(src)) + I.layer = initial(I.layer) + I.dropped(src) + return FALSE + + +/mob/proc/put_in_hands_or_del(obj/item/I) + return put_in_hands(I, TRUE) /mob/proc/drop_item_v() //this is dumb. if(stat == CONSCIOUS && isturf(loc)) return drop_item() - return 0 + return FALSE -//Drops the item in our left hand -/mob/proc/drop_l_hand() +/mob/proc/drop_all_held_items() if(!loc || !loc.allow_drop()) return - return unEquip(l_hand) //All needed checks are in unEquip - - -//Drops the item in our right hand -/mob/proc/drop_r_hand() - if(!loc || !loc.allow_drop()) - return - return unEquip(r_hand) - + for(var/obj/item/I in held_items) + unEquip(I) //Drops the item in our active hand. /mob/proc/drop_item() - if(hand) - return drop_l_hand() - else - return drop_r_hand() + if(!loc || !loc.allow_drop()) + return + var/obj/item/held = get_active_held_item() + return unEquip(held) //Here lie drop_from_inventory and before_item_take, already forgotten and not missed. - /mob/proc/canUnEquip(obj/item/I, force) if(!I) - return 1 + return TRUE if((I.flags & NODROP) && !force) - return 0 - return 1 + return FALSE + return TRUE /mob/proc/unEquip(obj/item/I, force) //Force overrides NODROP for things like wizarditis and admin undress. if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP. - return 1 + return TRUE if((I.flags & NODROP) && !force) - return 0 - - if(I == r_hand) - r_hand = null - update_inv_r_hand() - else if(I == l_hand) - l_hand = null - update_inv_l_hand() + return FALSE + var/hand_index = get_held_index_of_item(I) + if(hand_index) + held_items[hand_index] = null + update_inv_hands() if(I) if(client) client.screen -= I - I.loc = loc + I.layer = initial(I.layer) + I.forceMove(loc) I.dropped(src) - if(I) - I.layer = initial(I.layer) - return 1 + return TRUE //Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob. -/mob/proc/remove_from_mob(var/obj/O) - unEquip(O) - O.screen_loc = null - return 1 +/mob/proc/remove_from_mob(var/obj/item/I) + unEquip(I) + I.screen_loc = null + return TRUE //Outdated but still in use apparently. This should at least be a human proc. +//Daily reminder to murder this - Remie. /mob/proc/get_equipped_items() - var/list/items = new/list() + var/list/items = list() if(hasvar(src,"back")) if(src:back) @@ -204,48 +313,34 @@ if(hasvar(src,"wear_suit")) if(src:wear_suit) items += src:wear_suit -/* if(hasvar(src,"w_radio")) - if(src:w_radio) - items += src:w_radio commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN */ if(hasvar(src,"w_uniform")) if(src:w_uniform) items += src:w_uniform - -/* if(hasvar(src,"l_hand")) - if(src:l_hand) - items += src:l_hand - if(hasvar(src,"r_hand")) - if(src:r_hand) - items += src:r_hand*/ - return items /obj/item/proc/equip_to_best_slot(var/mob/M) - if(src != M.get_active_hand()) + if(src != M.get_active_held_item()) M << "You are not holding anything to equip!" - return 0 + return FALSE if(M.equip_to_appropriate_slot(src)) - if(M.hand) - M.update_inv_l_hand() - else - M.update_inv_r_hand() - return 1 + M.update_inv_hands() + return TRUE if(M.s_active && M.s_active.can_be_inserted(src,1)) //if storage active insert there M.s_active.handle_item_insertion(src) - return 1 + return TRUE - var/obj/item/weapon/storage/S = M.get_inactive_hand() + var/obj/item/weapon/storage/S = M.get_inactive_held_item() if(istype(S) && S.can_be_inserted(src,1)) //see if we have box in other hand S.handle_item_insertion(src) - return 1 + return TRUE S = M.get_item_by_slot(slot_belt) if(istype(S) && S.can_be_inserted(src,1)) //else we put in belt S.handle_item_insertion(src) - return 1 + return TRUE S = M.get_item_by_slot(slot_generic_dextrous_storage) //else we put in whatever is in drone storage if(istype(S) && S.can_be_inserted(src,1)) @@ -255,17 +350,17 @@ if(istype(S) && S.can_be_inserted(src,1)) S.handle_item_insertion(src) playsound(src.loc, "rustle", 50, 1, -5) - return 1 + return TRUE M << "You are unable to equip that!" - return 0 + return FALSE /mob/verb/quick_equip() set name = "quick-equip" set hidden = 1 - var/obj/item/I = get_active_hand() + var/obj/item/I = get_active_held_item() if (I) I.equip_to_best_slot(src) @@ -274,4 +369,47 @@ return slot_back /mob/proc/getBeltSlot() - return slot_belt \ No newline at end of file + return slot_belt + + + +//Inventory.dm is -kind of- an ok place for this I guess + +//This is NOT for dismemberment, as the user still technically has 2 "hands" +//This is for multi-handed mobs, such as a human with a third limb installed +//This is a very rare proc to call (besides admin fuckery) so +//any cost it has isn't a worry +/mob/proc/change_number_of_hands(amt) + if(amt < held_items.len) + for(var/i in held_items.len to amt step -1) + unEquip(held_items[i]) + held_items.len = amt + + if(hud_used) + var/style + if(client && client.prefs) + style = ui_style2icon(client.prefs.UI_style) + hud_used.build_hand_slots(style) + + +/mob/living/carbon/human/change_number_of_hands(amt) + var/old_limbs = held_items.len + if(amt < old_limbs) + for(var/i in hand_bodyparts.len to amt step -1) + var/obj/item/bodypart/BP = hand_bodyparts[i] + BP.dismember() + hand_bodyparts[i] = null + hand_bodyparts.len = amt + else if(amt > old_limbs) + hand_bodyparts.len = amt + for(var/i in old_limbs+1 to amt) + var/path = /obj/item/bodypart/l_arm + if(!(i % 2)) + path = /obj/item/bodypart/r_arm + + var/obj/item/bodypart/BP = new path () + BP.owner = src + BP.held_index = i + bodyparts += BP + hand_bodyparts[i] = BP + ..() //Don't redraw hands until we have organs for them diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index 69e85dfb9ab..fd09b35a440 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -27,7 +27,7 @@ /mob/living/proc/phaseout(obj/effect/decal/cleanable/B) if(iscarbon(src)) var/mob/living/carbon/C = src - if(C.l_hand || C.r_hand) + for(var/obj/item/I in C.held_items) //TODO make it toggleable to either forcedrop the items, or deny //entry when holding them // literally only an option for carbons though diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm similarity index 92% rename from code/modules/mob/living/carbon/brain/MMI.dm rename to code/modules/mob/living/brain/MMI.dm index 0e6e1ee5b03..4979cbd6c7d 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -1,198 +1,197 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/device/mmi - name = "Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations." - icon = 'icons/obj/assemblies.dmi' - icon_state = "mmi_empty" - w_class = 3 - origin_tech = "biotech=2;programming=3;engineering=2" - var/braintype = "Cyborg" - var/obj/item/device/radio/radio = null //Let's give it a radio. - var/hacked = 0 //Whether or not this is a Syndicate MMI - var/mob/living/carbon/brain/brainmob = null //The current occupant. - var/mob/living/silicon/robot = null //Appears unused. - var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm. - var/obj/item/organ/brain/brain = null //The actual brain - var/clockwork = FALSE //If this is a soul vessel - -/obj/item/device/mmi/update_icon() - if(brain) - if(istype(brain,/obj/item/organ/brain/alien)) - if(brainmob && brainmob.stat == DEAD) - icon_state = "mmi_alien_dead" - else - icon_state = "mmi_alien" - braintype = "Xenoborg" //HISS....Beep. - else - if(brainmob && brainmob.stat == DEAD) - icon_state = "mmi_dead" - else - icon_state = "mmi_full" - braintype = "Cyborg" - else - icon_state = "mmi_empty" - -/obj/item/device/mmi/New() - ..() - radio = new(src) //Spawns a radio inside the MMI. - radio.broadcasting = 0 //researching radio mmis turned the robofabs into radios because this didnt start as 0. - - - -/obj/item/device/mmi/attackby(obj/item/O, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - if(istype(O,/obj/item/organ/brain)) //Time to stick a brain in it --NEO - var/obj/item/organ/brain/newbrain = O - if(brain) - user << "There's already a brain in the MMI!" - return - if(!newbrain.brainmob) - user << "You aren't sure where this brain came from, but you're pretty sure it's a useless brain!" - return - - if(!user.unEquip(O)) - return - var/mob/living/carbon/brain/B = newbrain.brainmob - if(!B.key) - B.notify_ghost_cloning("Someone has put your brain in a MMI!", source = src) - visible_message("[user] sticks \a [newbrain] into \the [src].") - - brainmob = newbrain.brainmob - newbrain.brainmob = null - brainmob.loc = src - brainmob.container = src - if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death. - brainmob.stat = CONSCIOUS //we manually revive the brain mob - dead_mob_list -= brainmob - living_mob_list += brainmob - - brainmob.reset_perspective() - if(clockwork) - add_servant_of_ratvar(brainmob, TRUE) - newbrain.loc = src //P-put your brain in it - brain = newbrain - - name = "Man-Machine Interface: [brainmob.real_name]" - update_icon() - - feedback_inc("cyborg_mmis_filled",1) - - return - - else if(brainmob) - O.attack(brainmob, user) //Oh noooeeeee - return - ..() - -/obj/item/device/mmi/attack_self(mob/user) - if(!brain) - radio.on = !radio.on - user << "You toggle the MMI's radio system [radio.on==1 ? "on" : "off"]." - else - user << "You unlock and upend the MMI, spilling the brain onto the floor." - - brainmob.container = null //Reset brainmob mmi var. - brainmob.loc = brain //Throw mob into brain. - brainmob.stat = DEAD - brainmob.emp_damage = 0 - brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision - living_mob_list -= brainmob //Get outta here - dead_mob_list += brainmob - brain.brainmob = brainmob //Set the brain to use the brainmob - brainmob = null //Set mmi brainmob var to null - - user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf - brain = null //No more brain in here - - update_icon() - name = "Man-Machine Interface" - -/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people. - if(!brainmob) - brainmob = new(src) - brainmob.name = L.real_name - brainmob.real_name = L.real_name - if(L.has_dna()) - var/mob/living/carbon/C = L - if(!brainmob.dna) - brainmob.dna = new /datum/dna(brainmob) - C.dna.copy_dna(brainmob.dna) - brainmob.container = src - - if(ishuman(L)) - var/mob/living/carbon/human/H = L - var/obj/item/organ/brain/newbrain = H.getorgan(/obj/item/organ/brain) - newbrain.loc = src - brain = newbrain - else if(!brain) - brain = new(src) - brain.name = "[L.real_name]'s brain" - - name = "Man-Machine Interface: [brainmob.real_name]" - update_icon() - return - - -/obj/item/device/mmi/verb/Toggle_Listening() - set name = "Toggle Listening" - set desc = "Toggle listening channel on or off." - set category = "MMI" - set src = usr.loc - set popup_menu = 0 - - if(brainmob.stat) - brainmob << "Can't do that while incapacitated or dead!" - if(!radio.on) - brainmob << "Your radio is disabled!" - return - - radio.listening = radio.listening==1 ? 0 : 1 - brainmob << "Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast." - -/obj/item/device/mmi/emp_act(severity) - if(!brainmob) - return - else - switch(severity) - if(1) - brainmob.emp_damage = min(brainmob.emp_damage + rand(20,30), 30) - if(2) - brainmob.emp_damage = min(brainmob.emp_damage + rand(10,20), 30) - if(3) - brainmob.emp_damage = min(brainmob.emp_damage + rand(0,10), 30) - brainmob.emote("alarm") - ..() - -/obj/item/device/mmi/Destroy() - if(isrobot(loc)) - var/mob/living/silicon/robot/borg = loc - borg.mmi = null - if(brainmob) - qdel(brainmob) - brainmob = null - return ..() - -/obj/item/device/mmi/examine(mob/user) - ..() - if(brainmob) - var/mob/living/carbon/brain/B = brainmob - if(!B.key || !B.mind || B.stat == DEAD) - user << "The MMI indicates the brain is completely unresponsive." - - else if(!B.client) - user << "The MMI indicates the brain is currently inactive; it might change." - - else - user << "The MMI indicates the brain is active." - - -/obj/item/device/mmi/syndie - name = "Syndicate Man-Machine Interface" - desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores." - origin_tech = "biotech=4;programming=4;syndicate=2" - hacked = 1 - -/obj/item/device/mmi/syndie/New() - ..() - radio.on = 0 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/device/mmi + name = "Man-Machine Interface" + desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations." + icon = 'icons/obj/assemblies.dmi' + icon_state = "mmi_empty" + w_class = 3 + origin_tech = "biotech=2;programming=3;engineering=2" + var/braintype = "Cyborg" + var/obj/item/device/radio/radio = null //Let's give it a radio. + var/hacked = 0 //Whether or not this is a Syndicate MMI + var/mob/living/brain/brainmob = null //The current occupant. + var/mob/living/silicon/robot = null //Appears unused. + var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm. + var/obj/item/organ/brain/brain = null //The actual brain + var/clockwork = FALSE //If this is a soul vessel + +/obj/item/device/mmi/update_icon() + if(brain) + if(istype(brain,/obj/item/organ/brain/alien)) + if(brainmob && brainmob.stat == DEAD) + icon_state = "mmi_alien_dead" + else + icon_state = "mmi_alien" + braintype = "Xenoborg" //HISS....Beep. + else + if(brainmob && brainmob.stat == DEAD) + icon_state = "mmi_dead" + else + icon_state = "mmi_full" + braintype = "Cyborg" + else + icon_state = "mmi_empty" + +/obj/item/device/mmi/New() + ..() + radio = new(src) //Spawns a radio inside the MMI. + radio.broadcasting = 0 //researching radio mmis turned the robofabs into radios because this didnt start as 0. + + + +/obj/item/device/mmi/attackby(obj/item/O, mob/user, params) + user.changeNext_move(CLICK_CD_MELEE) + if(istype(O,/obj/item/organ/brain)) //Time to stick a brain in it --NEO + var/obj/item/organ/brain/newbrain = O + if(brain) + user << "There's already a brain in the MMI!" + return + if(!newbrain.brainmob) + user << "You aren't sure where this brain came from, but you're pretty sure it's a useless brain!" + return + + if(!user.unEquip(O)) + return + var/mob/living/brain/B = newbrain.brainmob + if(!B.key) + B.notify_ghost_cloning("Someone has put your brain in a MMI!", source = src) + visible_message("[user] sticks \a [newbrain] into \the [src].") + + brainmob = newbrain.brainmob + newbrain.brainmob = null + brainmob.loc = src + brainmob.container = src + if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death. + brainmob.stat = CONSCIOUS //we manually revive the brain mob + dead_mob_list -= brainmob + living_mob_list += brainmob + + brainmob.reset_perspective() + if(clockwork) + add_servant_of_ratvar(brainmob, TRUE) + newbrain.loc = src //P-put your brain in it + brain = newbrain + + name = "Man-Machine Interface: [brainmob.real_name]" + update_icon() + + feedback_inc("cyborg_mmis_filled",1) + + else if(brainmob) + O.attack(brainmob, user) //Oh noooeeeee + else + return ..() + + +/obj/item/device/mmi/attack_self(mob/user) + if(!brain) + radio.on = !radio.on + user << "You toggle the MMI's radio system [radio.on==1 ? "on" : "off"]." + else + user << "You unlock and upend the MMI, spilling the brain onto the floor." + + brainmob.container = null //Reset brainmob mmi var. + brainmob.loc = brain //Throw mob into brain. + brainmob.stat = DEAD + brainmob.emp_damage = 0 + brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision + living_mob_list -= brainmob //Get outta here + dead_mob_list += brainmob + brain.brainmob = brainmob //Set the brain to use the brainmob + brainmob = null //Set mmi brainmob var to null + + user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf + brain = null //No more brain in here + + update_icon() + name = "Man-Machine Interface" + +/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people. + if(!brainmob) + brainmob = new(src) + brainmob.name = L.real_name + brainmob.real_name = L.real_name + if(L.has_dna()) + var/mob/living/carbon/C = L + if(!brainmob.stored_dna) + brainmob.stored_dna = new /datum/dna/stored(brainmob) + C.dna.copy_dna(brainmob.stored_dna) + brainmob.container = src + + if(ishuman(L)) + var/mob/living/carbon/human/H = L + var/obj/item/organ/brain/newbrain = H.getorgan(/obj/item/organ/brain) + newbrain.loc = src + brain = newbrain + else if(!brain) + brain = new(src) + brain.name = "[L.real_name]'s brain" + + name = "Man-Machine Interface: [brainmob.real_name]" + update_icon() + return + + +/obj/item/device/mmi/verb/Toggle_Listening() + set name = "Toggle Listening" + set desc = "Toggle listening channel on or off." + set category = "MMI" + set src = usr.loc + set popup_menu = 0 + + if(brainmob.stat) + brainmob << "Can't do that while incapacitated or dead!" + if(!radio.on) + brainmob << "Your radio is disabled!" + return + + radio.listening = radio.listening==1 ? 0 : 1 + brainmob << "Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast." + +/obj/item/device/mmi/emp_act(severity) + if(!brainmob) + return + else + switch(severity) + if(1) + brainmob.emp_damage = min(brainmob.emp_damage + rand(20,30), 30) + if(2) + brainmob.emp_damage = min(brainmob.emp_damage + rand(10,20), 30) + if(3) + brainmob.emp_damage = min(brainmob.emp_damage + rand(0,10), 30) + brainmob.emote("alarm") + ..() + +/obj/item/device/mmi/Destroy() + if(isrobot(loc)) + var/mob/living/silicon/robot/borg = loc + borg.mmi = null + if(brainmob) + qdel(brainmob) + brainmob = null + return ..() + +/obj/item/device/mmi/examine(mob/user) + ..() + if(brainmob) + var/mob/living/brain/B = brainmob + if(!B.key || !B.mind || B.stat == DEAD) + user << "The MMI indicates the brain is completely unresponsive." + + else if(!B.client) + user << "The MMI indicates the brain is currently inactive; it might change." + + else + user << "The MMI indicates the brain is active." + + +/obj/item/device/mmi/syndie + name = "Syndicate Man-Machine Interface" + desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores." + origin_tech = "biotech=4;programming=4;syndicate=2" + hacked = 1 + +/obj/item/device/mmi/syndie/New() + ..() + radio.on = 0 diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/brain/brain.dm similarity index 50% rename from code/modules/mob/living/carbon/brain/brain.dm rename to code/modules/mob/living/brain/brain.dm index a089a58bd77..dfdf30fb3c5 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -1,63 +1,67 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/brain - languages_spoken = HUMAN - languages_understood = HUMAN - var/obj/item/device/mmi/container = null - var/timeofhostdeath = 0 - var/emp_damage = 0//Handles a type of MMI damage - has_limbs = 0 - stat = DEAD //we start dead by default - see_invisible = SEE_INVISIBLE_MINIMUM - -/mob/living/carbon/brain/New(loc) - ..() - if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned) - var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it. - src.loc = OB - OB.brainmob = src - - -/mob/living/carbon/brain/Destroy() - if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. - if(stat!=DEAD) //If not dead. - death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA - ghostize() //Ghostize checks for key so nothing else is necessary. - container = null - return ..() - -/mob/living/carbon/brain/update_canmove() - if(in_contents_of(/obj/mecha)) - canmove = 1 - else - canmove = 0 - return canmove - -/mob/living/carbon/brain/toggle_throw_mode() - return - -/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up. - return - -/mob/living/carbon/brain/blob_act(obj/effect/blob/B) - return - -/mob/living/carbon/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default - return - -/mob/living/carbon/brain/check_ear_prot() - return 1 - -/mob/living/carbon/brain/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0) - return // no eyes, no flashing - -/mob/living/carbon/brain/update_damage_hud() - return //no red circles for brain - -/mob/living/carbon/brain/can_be_revived() - . = 1 - if(!container || health <= HEALTH_THRESHOLD_DEAD) - return 0 - -/mob/living/carbon/brain/update_sight() - return +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/mob/living/brain + languages_spoken = HUMAN + languages_understood = HUMAN + var/obj/item/device/mmi/container = null + var/timeofhostdeath = 0 + var/emp_damage = 0//Handles a type of MMI damage + var/datum/dna/stored/stored_dna // dna var for brain. Used to store dna, brain dna is not considered like actual dna, brain.has_dna() returns FALSE. + stat = DEAD //we start dead by default + see_invisible = SEE_INVISIBLE_MINIMUM + +/mob/living/brain/New(loc) + ..() + create_dna(src) + stored_dna.initialize_dna(random_blood_type()) + if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned) + var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it. + src.loc = OB + OB.brainmob = src + + +/mob/living/brain/proc/create_dna() + stored_dna = new /datum/dna/stored(src) + if(!stored_dna.species) + var/rando_race = pick(config.roundstart_races) + stored_dna.species = new rando_race() + +/mob/living/brain/Destroy() + if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. + if(stat!=DEAD) //If not dead. + death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA + ghostize() //Ghostize checks for key so nothing else is necessary. + container = null + return ..() + +/mob/living/brain/update_canmove() + if(in_contents_of(/obj/mecha)) + canmove = 1 + else + canmove = 0 + return canmove + +/mob/living/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up. + return + +/mob/living/brain/blob_act(obj/effect/blob/B) + return + +/mob/living/brain/get_eye_protection()//no eyes + return 2 + +/mob/living/brain/get_ear_protection()//no ears + return 2 + +/mob/living/brain/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0) + return // no eyes, no flashing + +/mob/living/brain/can_be_revived() + . = 1 + if(!container || health <= HEALTH_THRESHOLD_DEAD) + return 0 + +/mob/living/brain/fully_replace_character_name(oldname,newname) + ..() + if(stored_dna) + stored_dna.real_name = real_name \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm similarity index 65% rename from code/modules/mob/living/carbon/brain/brain_item.dm rename to code/modules/mob/living/brain/brain_item.dm index e5e7d511fc0..4bccb03c2d8 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -1,127 +1,122 @@ -/obj/item/organ/brain - name = "brain" - desc = "A piece of juicy meat found in a person's head." - icon_state = "brain" - throw_speed = 3 - throw_range = 5 - layer = ABOVE_MOB_LAYER - zone = "head" - slot = "brain" - vital = 1 - origin_tech = "biotech=5" - attack_verb = list("attacked", "slapped", "whacked") - var/mob/living/carbon/brain/brainmob = null - var/damaged_brain = 0 //whether the brain organ is damaged. - -/obj/item/organ/brain/Insert(mob/living/carbon/M, special = 0) - ..() - name = "brain" - if(brainmob) - if(M.key) - M.ghostize() - - if(brainmob.mind) - brainmob.mind.transfer_to(M) - else - M.key = brainmob.key - - qdel(brainmob) - - //Update the body's icon so it doesnt appear debrained anymore - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.update_hair(0) - -/obj/item/organ/brain/Remove(mob/living/carbon/M, special = 0) - ..() - if(!special) - transfer_identity(M) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.update_hair(0) - -/obj/item/organ/brain/prepare_eat() - return // Too important to eat. - -/obj/item/organ/brain/proc/transfer_identity(mob/living/L) - name = "[L.name]'s brain" - brainmob = new(src) - brainmob.name = L.real_name - brainmob.real_name = L.real_name - brainmob.timeofhostdeath = L.timeofdeath - if(L.has_dna()) - var/mob/living/carbon/C = L - if(!brainmob.dna) - brainmob.dna = new /datum/dna(brainmob) - C.dna.copy_dna(brainmob.dna) - if(L.mind && L.mind.current && (L.mind.current.stat == DEAD)) - L.mind.transfer_to(brainmob) - brainmob << "You feel slightly disoriented. That's normal when you're just a brain." - -/obj/item/organ/brain/attackby(obj/item/O, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - if(brainmob) - O.attack(brainmob, user) //Oh noooeeeee - -/obj/item/organ/brain/examine(mob/user) - ..() - - if(brainmob) - if(brainmob.client) - if(brainmob.health <= HEALTH_THRESHOLD_DEAD) - user << "It's lifeless and severely damaged." - else - user << "You can feel the small spark of life still left in this one." - else - user << "This one seems particularly lifeless. Perhaps it will regain some of its luster later." - else - user << "This one is completely devoid of life." - -/obj/item/organ/brain/attack(mob/living/carbon/M, mob/user) - if(!istype(M)) - return ..() - - add_fingerprint(user) - - if(user.zone_selected != "head") - return ..() - - var/mob/living/carbon/human/H = M - if(istype(H) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - user << "You're going to need to remove their head cover first!" - return - -//since these people will be dead M != usr - - if(!M.getorgan(/obj/item/organ/brain)) - if(istype(H) && !H.get_bodypart("head")) - return - user.drop_item() - var/msg = "[M] has [src] inserted into \his head by [user]." - if(M == user) - msg = "[user] inserts [src] into \his head!" - - M.visible_message("[msg]", - "[msg]") - - if(M != user) - M << "[user] inserts [src] into your head." - user << "You insert [src] into [M]'s head." - else - user << "You insert [src] into your head." //LOL - - Insert(M) - else - ..() - -/obj/item/organ/brain/Destroy() //copypasted from MMIs. - if(brainmob) - qdel(brainmob) - brainmob = null - return ..() - -/obj/item/organ/brain/alien - name = "alien brain" - desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" - icon_state = "brain-x" - origin_tech = "biotech=6" +/obj/item/organ/brain + name = "brain" + desc = "A piece of juicy meat found in a person's head." + icon_state = "brain" + throw_speed = 3 + throw_range = 5 + layer = ABOVE_MOB_LAYER + zone = "head" + slot = "brain" + vital = 1 + origin_tech = "biotech=5" + attack_verb = list("attacked", "slapped", "whacked") + var/mob/living/brain/brainmob = null + var/damaged_brain = 0 //whether the brain organ is damaged. + +/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0) + ..() + name = "brain" + if(brainmob) + if(C.key) + C.ghostize() + + if(brainmob.mind) + brainmob.mind.transfer_to(C) + else + C.key = brainmob.key + + qdel(brainmob) + + //Update the body's icon so it doesnt appear debrained anymore + C.update_hair() + +/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0) + ..() + if(!special) + transfer_identity(C) + C.update_hair() + +/obj/item/organ/brain/prepare_eat() + return // Too important to eat. + +/obj/item/organ/brain/proc/transfer_identity(mob/living/L) + name = "[L.name]'s brain" + brainmob = new(src) + brainmob.name = L.real_name + brainmob.real_name = L.real_name + brainmob.timeofhostdeath = L.timeofdeath + if(L.has_dna()) + var/mob/living/carbon/C = L + if(!brainmob.stored_dna) + brainmob.stored_dna = new /datum/dna/stored(brainmob) + C.dna.copy_dna(brainmob.stored_dna) + if(L.mind && L.mind.current && (L.mind.current.stat == DEAD)) + L.mind.transfer_to(brainmob) + brainmob << "You feel slightly disoriented. That's normal when you're just a brain." + +/obj/item/organ/brain/attackby(obj/item/O, mob/user, params) + user.changeNext_move(CLICK_CD_MELEE) + if(brainmob) + O.attack(brainmob, user) //Oh noooeeeee + +/obj/item/organ/brain/examine(mob/user) + ..() + + if(brainmob) + if(brainmob.client) + if(brainmob.health <= HEALTH_THRESHOLD_DEAD) + user << "It's lifeless and severely damaged." + else + user << "You can feel the small spark of life still left in this one." + else + user << "This one seems particularly lifeless. Perhaps it will regain some of its luster later." + else + user << "This one is completely devoid of life." + +/obj/item/organ/brain/attack(mob/living/carbon/C, mob/user) + if(!istype(C)) + return ..() + + add_fingerprint(user) + + if(user.zone_selected != "head") + return ..() + + if((C.head && (C.head.flags_cover & HEADCOVERSEYES)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSEYES)) || (C.glasses && (C.glasses.flags & GLASSESCOVERSEYES))) + user << "You're going to need to remove their head cover first!" + return + +//since these people will be dead M != usr + + if(!C.getorgan(/obj/item/organ/brain)) + if(!C.get_bodypart("head")) + return + user.drop_item() + var/msg = "[C] has [src] inserted into \his head by [user]." + if(C == user) + msg = "[user] inserts [src] into \his head!" + + C.visible_message("[msg]", + "[msg]") + + if(C != user) + C << "[user] inserts [src] into your head." + user << "You insert [src] into [C]'s head." + else + user << "You insert [src] into your head." //LOL + + Insert(C) + else + ..() + +/obj/item/organ/brain/Destroy() //copypasted from MMIs. + if(brainmob) + qdel(brainmob) + brainmob = null + return ..() + +/obj/item/organ/brain/alien + name = "alien brain" + desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" + icon_state = "brain-x" + origin_tech = "biotech=6" diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/brain/death.dm similarity index 83% rename from code/modules/mob/living/carbon/brain/death.dm rename to code/modules/mob/living/brain/death.dm index 67b700b2b08..e98859b90ff 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/brain/death.dm @@ -1,20 +1,20 @@ -/mob/living/carbon/brain/death(gibbed) - if(stat == DEAD) - return - stat = DEAD - - if(!gibbed && container)//If not gibbed but in a container. - var/obj/item/device/mmi = container - mmi.visible_message("[src]'s MMI flatlines!", \ - "You hear something flatline.") - mmi.update_icon() - - return ..() - -/mob/living/carbon/brain/gib() - if(container) - qdel(container)//Gets rid of the MMI if there is one - if(loc) - if(istype(loc,/obj/item/organ/brain)) - qdel(loc)//Gets rid of the brain item +/mob/living/brain/death(gibbed) + if(stat == DEAD) + return + stat = DEAD + + if(!gibbed && container)//If not gibbed but in a container. + var/obj/item/device/mmi = container + mmi.visible_message("[src]'s MMI flatlines!", \ + "You hear something flatline.") + mmi.update_icon() + + return ..() + +/mob/living/brain/gib() + if(container) + qdel(container)//Gets rid of the MMI if there is one + if(loc) + if(istype(loc,/obj/item/organ/brain)) + qdel(loc)//Gets rid of the brain item ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/brain/emote.dm similarity index 91% rename from code/modules/mob/living/carbon/brain/emote.dm rename to code/modules/mob/living/brain/emote.dm index bd4be7c66f9..8ab505f7a9e 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/brain/emote.dm @@ -1,71 +1,71 @@ -/mob/living/carbon/brain/emote(act,m_type=1,message = null) - if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes - return - - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - act = copytext(act, 1, t1) - - - if(src.stat == DEAD) - return - switch(act) - if ("alarm") - src << "You sound an alarm." - message = "[src] sounds an alarm." - m_type = 2 - - if ("alert") - src << "You let out a distressed noise." - message = "[src] lets out a distressed noise." - m_type = 2 - - if ("beep","beeps") - src << "You beep." - message = "[src] beeps." - m_type = 2 - - if ("blink","blinks") - message = "[src] blinks." - m_type = 1 - - if ("boop","boops") - src << "You boop." - message = "[src] boops." - m_type = 2 - - if ("flash") - message = "The lights on [src] flash quickly." - m_type = 1 - - if ("notice") - src << "You play a loud tone." - message = "[src] plays a loud tone." - m_type = 2 - - if ("whistle","whistles") - src << "You whistle." - message = "[src] whistles." - m_type = 2 - - if ("help") - src << "Help for MMI emotes. You can use these emotes with say \"*emote\":\nalarm, alert, beep, blink, boop, flash, notice, whistle" - - else - src << "Unusable emote '[act]'. Say *help for a list." - return - - if (message) - log_emote("[name]/[key] : [message]") - - for(var/mob/M in dead_mob_list) - if (!M.client || istype(M, /mob/new_player)) - continue //skip monkeys, leavers, and new_players - if(M.stat == DEAD && (M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT)) && !(M in viewers(src,null))) - M.show_message(message) - - - if (m_type & 1) - visible_message(message) - else if (m_type & 2) +/mob/living/brain/emote(act,m_type=1,message = null) + if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes + return + + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + act = copytext(act, 1, t1) + + + if(src.stat == DEAD) + return + switch(act) + if ("alarm") + src << "You sound an alarm." + message = "[src] sounds an alarm." + m_type = 2 + + if ("alert") + src << "You let out a distressed noise." + message = "[src] lets out a distressed noise." + m_type = 2 + + if ("beep","beeps") + src << "You beep." + message = "[src] beeps." + m_type = 2 + + if ("blink","blinks") + message = "[src] blinks." + m_type = 1 + + if ("boop","boops") + src << "You boop." + message = "[src] boops." + m_type = 2 + + if ("flash") + message = "The lights on [src] flash quickly." + m_type = 1 + + if ("notice") + src << "You play a loud tone." + message = "[src] plays a loud tone." + m_type = 2 + + if ("whistle","whistles") + src << "You whistle." + message = "[src] whistles." + m_type = 2 + + if ("help") + src << "Help for MMI emotes. You can use these emotes with say \"*emote\":\nalarm, alert, beep, blink, boop, flash, notice, whistle" + + else + src << "Unusable emote '[act]'. Say *help for a list." + return + + if (message) + log_emote("[name]/[key] : [message]") + + for(var/mob/M in dead_mob_list) + if (!M.client || istype(M, /mob/new_player)) + continue //skip monkeys, leavers, and new_players + if(M.stat == DEAD && (M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT)) && !(M in viewers(src,null))) + M.show_message(message) + + + if (m_type & 1) + visible_message(message) + else if (m_type & 2) audible_message(message) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/brain/life.dm similarity index 57% rename from code/modules/mob/living/carbon/brain/life.dm rename to code/modules/mob/living/brain/life.dm index 75f731b6e69..9d87f412e8d 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/brain/life.dm @@ -1,60 +1,49 @@ - -/mob/living/carbon/brain/Life() - set invisibility = 0 - set background = BACKGROUND_ENABLED - - if (notransform) - return - if(!loc) - return - . = ..() - handle_emp_damage() - -/mob/living/carbon/brain/handle_breathing() - return - -/mob/living/carbon/brain/handle_mutations_and_radiation() - return - -/mob/living/carbon/brain/handle_environment(datum/gas_mixture/environment) - return - -/mob/living/carbon/brain/update_stat() - if(status_flags & GODMODE) - return - if(health <= HEALTH_THRESHOLD_DEAD) - if(stat != DEAD) - death() - var/obj/item/organ/brain/BR - if(container && container.brain) - BR = container.brain - else if(istype(loc, /obj/item/organ/brain)) - BR = loc - if(BR) - BR.damaged_brain = 1 //beaten to a pulp - -/* //currently unused feature, since brain outside a mmi is always dead. -/mob/living/carbon/brain/proc/handle_brain_revival_life() - if(stat != DEAD) - if(config.revival_brain_life != -1) - if( !container && (world.time - timeofhostdeath) > config.revival_brain_life) - death() -*/ - -/mob/living/carbon/brain/proc/handle_emp_damage() - if(emp_damage) - if(stat == DEAD) - emp_damage = 0 - else - emp_damage = max(emp_damage-1, 0) - -/mob/living/carbon/brain/handle_status_effects() - return - -/mob/living/carbon/brain/handle_disabilities() - return - -/mob/living/carbon/brain/handle_changeling() - return - - + +/mob/living/brain/Life() + set invisibility = 0 + set background = BACKGROUND_ENABLED + + if (notransform) + return + if(!loc) + return + . = ..() + handle_emp_damage() + +/mob/living/brain/update_stat() + if(status_flags & GODMODE) + return + if(health <= HEALTH_THRESHOLD_DEAD) + if(stat != DEAD) + death() + var/obj/item/organ/brain/BR + if(container && container.brain) + BR = container.brain + else if(istype(loc, /obj/item/organ/brain)) + BR = loc + if(BR) + BR.damaged_brain = 1 //beaten to a pulp + +/* //currently unused feature, since brain outside a mmi is always dead. +/mob/living/brain/proc/handle_brain_revival_life() + if(stat != DEAD) + if(config.revival_brain_life != -1) + if( !container && (world.time - timeofhostdeath) > config.revival_brain_life) + death() +*/ + +/mob/living/brain/proc/handle_emp_damage() + if(emp_damage) + if(stat == DEAD) + emp_damage = 0 + else + emp_damage = max(emp_damage-1, 0) + +/mob/living/brain/handle_status_effects() + return + +/mob/living/brain/handle_disabilities() + return + + + diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm similarity index 98% rename from code/modules/mob/living/carbon/brain/posibrain.dm rename to code/modules/mob/living/brain/posibrain.dm index 229f2b52fce..f7ad95798a5 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/brain/posibrain.dm @@ -80,11 +80,10 @@ var/global/posibrain_notif_cooldown = 0 name = "[initial(name)] ([C])" brainmob.name = C.real_name brainmob.real_name = C.real_name - brainmob.dna = C.dna if(C.has_dna()) - if(!brainmob.dna) - brainmob.dna = new /datum/dna(brainmob) - C.dna.copy_dna(brainmob.dna) + if(!brainmob.stored_dna) + brainmob.stored_dna = new /datum/dna/stored(brainmob) + C.dna.copy_dna(brainmob.stored_dna) brainmob.timeofhostdeath = C.timeofdeath brainmob.stat = CONSCIOUS if(brainmob.mind) diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/brain/say.dm similarity index 70% rename from code/modules/mob/living/carbon/brain/say.dm rename to code/modules/mob/living/brain/say.dm index 77f72d484a7..0aeb312ee0f 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/brain/say.dm @@ -1,23 +1,23 @@ -/mob/living/carbon/brain/say(message) - if(!(container && istype(container, /obj/item/device/mmi))) - return //No MMI, can't speak, bucko./N - else - if(prob(emp_damage*4)) - if(prob(10))//10% chane to drop the message entirely - return - else - message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher - ..() - -/mob/living/carbon/brain/radio(message, message_mode, list/spans) - if(message_mode && istype(container, /obj/item/device/mmi)) - var/obj/item/device/mmi/R = container - if(R.radio) - R.radio.talk_into(src, message, , spans) - return ITALICS | REDUCE_RANGE - -/mob/living/carbon/brain/lingcheck() - return 0 - -/mob/living/carbon/brain/treat_message(message) +/mob/living/brain/say(message) + if(!(container && istype(container, /obj/item/device/mmi))) + return //No MMI, can't speak, bucko./N + else + if(prob(emp_damage*4)) + if(prob(10))//10% chane to drop the message entirely + return + else + message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher + ..() + +/mob/living/brain/radio(message, message_mode, list/spans) + if(message_mode && istype(container, /obj/item/device/mmi)) + var/obj/item/device/mmi/R = container + if(R.radio) + R.radio.talk_into(src, message, , spans) + return ITALICS | REDUCE_RANGE + +/mob/living/brain/lingcheck() + return 0 + +/mob/living/brain/treat_message(message) return message \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/status_procs.dm b/code/modules/mob/living/brain/status_procs.dm similarity index 52% rename from code/modules/mob/living/carbon/brain/status_procs.dm rename to code/modules/mob/living/brain/status_procs.dm index dc8ff6ffc1e..caf2bfe22c4 100644 --- a/code/modules/mob/living/carbon/brain/status_procs.dm +++ b/code/modules/mob/living/brain/status_procs.dm @@ -4,35 +4,30 @@ /////////////////////////////////// EAR DAMAGE //////////////////////////////////// -/mob/living/carbon/brain/adjustEarDamage() +/mob/living/brain/adjustEarDamage() return -/mob/living/carbon/brain/setEarDamage() // no ears to damage or heal +/mob/living/brain/setEarDamage() // no ears to damage or heal return /////////////////////////////////// EYE_BLIND //////////////////////////////////// -/mob/living/carbon/brain/blind_eyes() // no eyes to damage or heal +/mob/living/brain/blind_eyes() // no eyes to damage or heal return -/mob/living/carbon/brain/adjust_blindness() +/mob/living/brain/adjust_blindness() return -/mob/living/carbon/brain/set_blindness() +/mob/living/brain/set_blindness() return /////////////////////////////////// EYE_BLURRY //////////////////////////////////// -/mob/living/carbon/brain/blur_eyes() +/mob/living/brain/blur_eyes() return -/mob/living/carbon/brain/adjust_blurriness() +/mob/living/brain/adjust_blurriness() return -/mob/living/carbon/brain/set_blurriness() +/mob/living/brain/set_blurriness() return - -/////////////////////////////////// BLIND DISABILITY //////////////////////////////////// - -/mob/living/carbon/brain/become_blind() - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index c8f7ce99a22..42572b1c03c 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -37,35 +37,22 @@ verbs += /mob/living/proc/mob_sleep verbs += /mob/living/proc/lay_down - internal_organs += new /obj/item/organ/brain/alien - internal_organs += new /obj/item/organ/alien/hivenode - internal_organs += new /obj/item/organ/tongue/alien + create_bodyparts() //initialize bodyparts - for(var/obj/item/organ/I in internal_organs) - I.Insert(src) + create_internal_organs() AddAbility(new/obj/effect/proc_holder/alien/nightvisiontoggle(null)) ..() +/mob/living/carbon/alien/create_internal_organs() + internal_organs += new /obj/item/organ/brain/alien + internal_organs += new /obj/item/organ/alien/hivenode + internal_organs += new /obj/item/organ/tongue/alien + ..() + /mob/living/carbon/alien/assess_threat() // beepsky won't hunt aliums return -10 -/mob/living/carbon/alien/adjustToxLoss(amount) - return 0 - -/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire - if(amount > 0) - ..(amount * 2) - else - ..(amount) - return - -/mob/living/carbon/alien/check_eye_prot() - return ..() + 2 - -/mob/living/carbon/alien/getToxLoss() - return 0 - /mob/living/carbon/alien/handle_environment(datum/gas_mixture/environment) if(!environment) return @@ -100,35 +87,6 @@ else clear_alert("alien_fire") - -/mob/living/carbon/alien/ex_act(severity, target) - ..() - - switch (severity) - if (1) - gib() - return - - if (2) - adjustBruteLoss(60) - adjustFireLoss(60) - adjustEarDamage(30,120) - - if(3) - adjustBruteLoss(30) - if (prob(50)) - Paralyse(1) - adjustEarDamage(15,60) - - updatehealth() - - -/mob/living/carbon/alien/handle_fire()//Aliens on fire code - if(..()) - return - bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! - return - /mob/living/carbon/alien/reagent_check(datum/reagent/R) //can metabolize all reagents return 0 diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index d9f5ef6fa98..0d934446366 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -1,3 +1,10 @@ + +/mob/living/carbon/alien/get_eye_protection() + return ..() + 2 //potential cyber implants + natural eye protection + +/mob/living/carbon/alien/get_ear_protection() + return 2 //no ears + /mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush) ..(AM, skipcatch = 1, hitpush = 0) @@ -40,7 +47,6 @@ In all, this is a lot like the monkey code. /N updatehealth() else M << "[name] is too injured for that." - return /mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L) @@ -65,9 +71,10 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M) if(..()) if (stat != DEAD) - adjustBruteLoss(rand(1, 3)) - updatehealth() - return + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(rand(1, 3), BRUTE, affecting) + + /mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M) @@ -96,3 +103,22 @@ In all, this is a lot like the monkey code. /N adjustBruteLoss(damage) add_logs(M, src, "attacked") updatehealth() + +/mob/living/carbon/alien/ex_act(severity, target) + ..() + switch (severity) + if (1) + gib() + + if (2) + take_overall_damage(60, 60) + adjustEarDamage(30,120) + + if(3) + take_overall_damage(30,0) + if(prob(50)) + Paralyse(1) + adjustEarDamage(15,60) + +/mob/living/carbon/alien/soundbang_act(intensity = 1, stun_pwr = 1, damage_pwr = 5, deafen_pwr = 15) + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/damage_procs.dm b/code/modules/mob/living/carbon/alien/damage_procs.dm new file mode 100644 index 00000000000..7857c0b565e --- /dev/null +++ b/code/modules/mob/living/carbon/alien/damage_procs.dm @@ -0,0 +1,22 @@ + + +/mob/living/carbon/alien/getToxLoss() + return 0 + +/mob/living/carbon/alien/adjustToxLoss(amount) //alien immune to tox damage + return 0 + +/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire + if(amount > 0) + ..(amount * 2) + else + ..(amount) + + + +//aliens are immune to stamina damage. +/mob/living/carbon/alien/adjustStaminaLoss(amount, updating_stamina = 1) + return + +/mob/living/carbon/alien/setStaminaLoss(amount, updating_stamina = 1) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm index 7583d0afaa7..6211dc83493 100644 --- a/code/modules/mob/living/carbon/alien/death.dm +++ b/code/modules/mob/living/carbon/alien/death.dm @@ -1,5 +1,8 @@ -/mob/living/carbon/alien/spawn_gibs() - xgibs(loc, viruses) +/mob/living/carbon/alien/spawn_gibs(with_bodyparts) + if(with_bodyparts) + new /obj/effect/gibspawner/xeno(loc,viruses) + else + new /obj/effect/gibspawner/xenobodypartless(loc,viruses) /mob/living/carbon/alien/gib_animation() PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-a")) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index 8e078e4ed7c..5f0dbd5635e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -7,11 +7,14 @@ /mob/living/carbon/alien/humanoid/drone/New() + AddAbility(new/obj/effect/proc_holder/alien/evolve(null)) + ..() + + +/mob/living/carbon/alien/humanoid/drone/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/large internal_organs += new /obj/item/organ/alien/resinspinner internal_organs += new /obj/item/organ/alien/acid - - AddAbility(new/obj/effect/proc_holder/alien/evolve(null)) ..() /mob/living/carbon/alien/humanoid/drone/movement_delay() diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 379500f5002..3a9e938df39 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -6,7 +6,7 @@ icon_state = "alienh_s" var/obj/screen/leap_icon = null -/mob/living/carbon/alien/humanoid/hunter/New() +/mob/living/carbon/alien/humanoid/hunter/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/small ..() diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm index 8da5304ff77..d16c06bea53 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm @@ -11,14 +11,18 @@ real_name = name + AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src)) + AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve()) + ..() + +/mob/living/carbon/alien/humanoid/royal/praetorian/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/large internal_organs += new /obj/item/organ/alien/resinspinner internal_organs += new /obj/item/organ/alien/acid internal_organs += new /obj/item/organ/alien/neurotoxin - AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src)) - AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve()) ..() + /mob/living/carbon/alien/humanoid/royal/praetorian/movement_delay() . = ..() . += 1 diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index a22ab106dd4..dacd4ff7d4a 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -7,11 +7,15 @@ /mob/living/carbon/alien/humanoid/sentinel/New() - internal_organs += new /obj/item/organ/alien/plasmavessel - internal_organs += new /obj/item/organ/alien/acid - internal_organs += new /obj/item/organ/alien/neurotoxin AddAbility(new /obj/effect/proc_holder/alien/sneak) ..() +/mob/living/carbon/alien/humanoid/sentinel/create_internal_organs() + internal_organs += new /obj/item/organ/alien/plasmavessel + internal_organs += new /obj/item/organ/alien/acid + internal_organs += new /obj/item/organ/alien/neurotoxin + ..() + + /mob/living/carbon/alien/humanoid/sentinel/movement_delay() . = ..() diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 1dfe38aaf9d..98c1df7b382 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -15,88 +15,34 @@ var/custom_pixel_y_offset = 0 var/sneaking = 0 //For sneaky-sneaky mode and appropriate slowdown var/drooling = 0 //For Neruotoxic spit overlays + bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien, + /obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien) + //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/humanoid/New() AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null)) ..() - /mob/living/carbon/alien/humanoid/movement_delay() . = ..() . += move_delay_add + config.alien_delay + sneaking //move_delay_add is used to slow aliens with stuns -/mob/living/carbon/alien/humanoid/emp_act(severity) - if(r_store) r_store.emp_act(severity) - if(l_store) l_store.emp_act(severity) - ..() - -/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user) - if(user.a_intent == "harm") - ..(user, 1) - adjustBruteLoss(15) - var/hitverb = "punched" - if(mob_size < MOB_SIZE_LARGE) - step_away(src,user,15) - sleep(1) - step_away(src,user,15) - hitverb = "slammed" - playsound(loc, "punch", 25, 1, -1) - visible_message("[user] has [hitverb] [src]!", \ - "[user] has [hitverb] [src]!") - return 1 - -/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) - if(..()) - switch(M.a_intent) - if ("harm") - var/damage = rand(1, 9) - if (prob(90)) - playsound(loc, "punch", 25, 1, -1) - visible_message("[M] has punched [src]!", \ - "[M] has punched [src]!") - if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of weakening an alien. - Paralyse(2) - visible_message("[M] has weakened [src]!", \ - "[M] has weakened [src]!") - adjustBruteLoss(damage) - add_logs(M, src, "attacked") - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [src]!") - - if ("disarm") - if (!lying) - if (prob(5)) - Paralyse(2) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - add_logs(M, src, "pushed") - visible_message("[M] has pushed down [src]!", \ - "[M] has pushed down [src]!") - else - if (prob(50)) - drop_item() - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has disarmed [src]!", \ - "[M] has disarmed [src]!") - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to disarm [src]!") - /mob/living/carbon/alien/humanoid/restrained(ignore_grab) . = handcuffed /mob/living/carbon/alien/humanoid/show_inv(mob/user) user.set_machine(src) - var/dat = {" + var/list/dat = list() + dat += {"
[name] -
-
Left Hand: [l_hand ? l_hand : "Nothing"] -
Right Hand: [r_hand ? r_hand : "Nothing"] -
Empty Pouches"} +
"} + for(var/i in 1 to held_items.len) + var/obj/item/I = get_item_for_held_index(i) + dat += "
[get_held_index_name(i)]:[(I && !(I.flags & ABSTRACT)) ? I : "Empty"]" + dat += "
Empty Pouches" if(handcuffed) dat += "
Handcuffed" @@ -107,7 +53,7 @@

Close "} - user << browse(dat, "window=mob\ref[src];size=325x500") + user << browse(dat.Join(), "window=mob\ref[src];size=325x500") onclose(user, "mob\ref[src]") @@ -148,15 +94,11 @@ else return initial(pixel_x) -/mob/living/carbon/alien/humanoid/check_ear_prot() - return 1 - /mob/living/carbon/alien/humanoid/get_permeability_protection() return 0.8 /mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno) - drop_l_hand() - drop_r_hand() + drop_all_held_items() for(var/atom/movable/A in stomach_contents) stomach_contents.Remove(A) new_xeno.stomach_contents.Add(A) @@ -178,9 +120,3 @@ proc/get_alien_type(var/alienpath) if(breath && breath.total_moles() > 0 && !sneaking) playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5) ..() - -/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0) - if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling)) - devour_mob(pulling, devour_time = 60) - else - ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm new file mode 100644 index 00000000000..4f08997c40f --- /dev/null +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -0,0 +1,59 @@ + +/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0) + if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling)) + devour_mob(pulling, devour_time = 60) + else + ..() + +/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user) + if(user.a_intent == "harm") + ..(user, 1) + adjustBruteLoss(15) + var/hitverb = "punched" + if(mob_size < MOB_SIZE_LARGE) + step_away(src,user,15) + sleep(1) + step_away(src,user,15) + hitverb = "slammed" + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has [hitverb] [src]!", \ + "[user] has [hitverb] [src]!") + return 1 + +/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) + if(..()) + switch(M.a_intent) + if ("harm") + var/damage = rand(1, 9) + if (prob(90)) + playsound(loc, "punch", 25, 1, -1) + visible_message("[M] has punched [src]!", \ + "[M] has punched [src]!") + if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of weakening an alien. + Paralyse(2) + visible_message("[M] has weakened [src]!", \ + "[M] has weakened [src]!") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(damage, BRUTE, affecting) + add_logs(M, src, "attacked") + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch [src]!") + + if ("disarm") + if (!lying) + if (prob(5)) + Paralyse(2) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + add_logs(M, src, "pushed") + visible_message("[M] has pushed down [src]!", \ + "[M] has pushed down [src]!") + else + if (prob(50)) + drop_item() + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed [src]!") + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to disarm [src]!") diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 5f48d88c55d..5559ebffe01 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -57,14 +57,17 @@ real_name = src.name + AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src)) + AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote()) + smallsprite.Grant(src) + ..() + +/mob/living/carbon/alien/humanoid/royal/queen/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/large/queen internal_organs += new /obj/item/organ/alien/resinspinner internal_organs += new /obj/item/organ/alien/acid internal_organs += new /obj/item/organ/alien/neurotoxin internal_organs += new /obj/item/organ/alien/eggsac - AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src)) - AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote()) - smallsprite.Grant(src) ..() /mob/living/carbon/alien/humanoid/royal/queen/movement_delay() diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index b4e3dc16c8f..9e8475a4e6c 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -68,27 +68,26 @@ apply_overlay(HANDCUFF_LAYER) //Royals have bigger sprites, so inhand things must be handled differently. -/mob/living/carbon/alien/humanoid/royal/update_inv_r_hand() +/mob/living/carbon/alien/humanoid/royal/update_inv_hands() ..() - remove_overlay(R_HAND_LAYER) - if(r_hand) - var/itm_state = r_hand.item_state - if(!itm_state) - itm_state = r_hand.icon_state + remove_overlay(HANDS_LAYER) + var/list/hands = list() - var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_r", "layer"=-R_HAND_LAYER) - overlays_standing[R_HAND_LAYER] = I - - apply_overlay(R_HAND_LAYER) - -/mob/living/carbon/alien/humanoid/royal/update_inv_l_hand() - ..() - remove_overlay(L_HAND_LAYER) + var/obj/item/l_hand = get_item_for_held_index(1) if(l_hand) var/itm_state = l_hand.item_state if(!itm_state) itm_state = l_hand.icon_state + var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_l", "layer"=-HANDS_LAYER) + hands += I - var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_l", "layer"=-L_HAND_LAYER) - overlays_standing[L_HAND_LAYER] = I - apply_overlay(L_HAND_LAYER) \ No newline at end of file + var/obj/item/r_hand = get_item_for_held_index(2) + if(r_hand) + var/itm_state = r_hand.item_state + if(!itm_state) + itm_state = r_hand.icon_state + var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_r", "layer"=-HANDS_LAYER) + hands += I + + overlays_standing[HANDS_LAYER] = hands + apply_overlay(HANDS_LAYER) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 136572fb5c5..43a2f196255 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -8,3 +8,18 @@ visible_message("[src] lets out a waning high-pitched cry.") return ..(gibbed) + +/mob/living/carbon/alien/larva/spawn_gibs(with_bodyparts) + if(with_bodyparts) + new /obj/effect/gibspawner/larva(loc,viruses) + else + new /obj/effect/gibspawner/larvabodypartless(loc,viruses) + +/mob/living/carbon/alien/larva/gib_animation() + PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-l")) + +/mob/living/carbon/alien/larva/spawn_dust() + new /obj/effect/decal/remains/xeno(loc) + +/mob/living/carbon/alien/larva/dust_animation() + PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-l")) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 887cf139996..f6ceff4774a 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -14,16 +14,20 @@ var/time_of_birth rotate_on_lying = 0 + bodyparts = list(/obj/item/bodypart/chest/larva, /obj/item/bodypart/head/larva) + //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/larva/New() - regenerate_icons() - internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny AddAbility(new/obj/effect/proc_holder/alien/hide(null)) AddAbility(new/obj/effect/proc_holder/alien/larva_evolve(null)) ..() +/mob/living/carbon/alien/larva/create_internal_organs() + internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny + ..() + //This needs to be fixed /mob/living/carbon/alien/larva/Stat() ..() @@ -39,36 +43,6 @@ /mob/living/carbon/alien/larva/attack_ui(slot_id) return -/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user) - if(user.a_intent == "harm") - ..(user, 1) - adjustBruteLoss(5 + rand(1,9)) - spawn() - step_away(src,user,15) - sleep(1) - step_away(src,user,15) - return 1 - -/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M) - if(..()) - var/damage = rand(1, 9) - if (prob(90)) - playsound(loc, "punch", 25, 1, -1) - add_logs(M, src, "attacked") - visible_message("[M] has kicked [src]!", \ - "[M] has kicked [src]!") - if ((stat != DEAD) && (damage > 4.9)) - Paralyse(rand(5,10)) - - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to kick [src]!", \ - "[M] has attempted to kick [src]!") - - return - /mob/living/carbon/alien/larva/restrained(ignore_grab) . = 0 diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm new file mode 100644 index 00000000000..77bab6cdf04 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -0,0 +1,29 @@ + + +/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M) + if(..()) + var/damage = rand(1, 9) + if (prob(90)) + playsound(loc, "punch", 25, 1, -1) + add_logs(M, src, "attacked") + visible_message("[M] has kicked [src]!", \ + "[M] has kicked [src]!") + if ((stat != DEAD) && (damage > 4.9)) + Paralyse(rand(5,10)) + + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(damage, BRUTE, affecting) + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to kick [src]!", \ + "[M] has attempted to kick [src]!") + +/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user) + if(user.a_intent == "harm") + ..(user, 1) + adjustBruteLoss(5 + rand(1,9)) + spawn() + step_away(src,user,15) + sleep(1) + step_away(src,user,15) + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 91bddef2cde..f0192cf2a96 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -45,4 +45,10 @@ move_delay_add = max(0, move_delay_add - rand(1, 2)) /mob/living/carbon/alien/handle_changeling() + return + +/mob/living/carbon/alien/handle_fire()//Aliens on fire code + if(..()) + return + bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 9a531fdf956..f2382721cff 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -41,7 +41,7 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds if(prob(4)) owner << "Your muscles ache." if(prob(20)) - owner.take_organ_damage(1) + owner.take_bodypart_damage(1) if(prob(4)) owner << "Your stomach hurts." if(prob(20)) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index a1292a9c9ab..95387d85691 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -68,7 +68,6 @@ var/const/MAX_ACTIVE_TIME = 400 /obj/item/clothing/mask/facehugger/bullet_act(obj/item/projectile/P) if(P.damage) Die() - return /obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > 300) @@ -124,7 +123,7 @@ var/const/MAX_ACTIVE_TIME = 400 return 0 if(stat != CONSCIOUS) return 0 - if(!sterile) M.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage + if(!sterile) M.take_bodypart_damage(strength,0) //done here so that even borgs and humans in helmets take damage M.visible_message("[src] leaps at [M]'s face!", \ "[src] leaps at [M]'s face!") if(ishuman(M)) @@ -180,7 +179,7 @@ var/const/MAX_ACTIVE_TIME = 400 icon_state = "[initial(icon_state)]_impregnated" var/obj/item/bodypart/chest/LC = target.get_bodypart("chest") - if((!LC || LC.status != ORGAN_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo)) + if((!LC || LC.status != BODYPART_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo)) new /obj/item/organ/body_egg/alien_embryo(target) if(iscorgi(target)) diff --git a/code/modules/mob/living/carbon/alien/update_icons.dm b/code/modules/mob/living/carbon/alien/update_icons.dm new file mode 100644 index 00000000000..ec3753e6979 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/update_icons.dm @@ -0,0 +1,11 @@ + + + +/mob/living/carbon/alien/update_damage_overlays() //aliens don't have damage overlays. + return + +/mob/living/carbon/alien/update_body() // we don't use the bodyparts or body layers for aliens. + return + +/mob/living/carbon/alien/update_body_parts()//we don't use the bodyparts layer for aliens. + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 9d30f85a661..0198c4a1cf8 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -3,10 +3,11 @@ /mob/living/carbon/New() create_reagents(1000) + update_body_parts() //to update the carbon's new bodyparts appearance ..() /mob/living/carbon/Destroy() - for(var/atom/movable/guts in internal_organs) + for(var/guts in internal_organs) qdel(guts) for(var/atom/movable/food in stomach_contents) qdel(food) @@ -25,19 +26,12 @@ audible_message("You hear something rumbling inside [src]'s stomach...", \ "You hear something rumbling.", 4,\ "Something is rumbling inside your stomach!") - var/obj/item/I = user.get_active_hand() + var/obj/item/I = user.get_active_held_item() if(I && I.force) 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_bodypart("chest") - if (istype(organ, /obj/item/bodypart)) - var/obj/item/bodypart/temp = organ - if(temp.take_damage(d, 0)) - H.update_damage_overlays(0) - H.updatehealth() - else - src.take_organ_damage(d) + var/obj/item/bodypart/BP = get_bodypart("chest") + if(BP.take_damage(d, 0)) + update_damage_overlays() visible_message("[user] attacks [src]'s stomach wall with the [I.name]!", \ "[user] attacks your stomach wall with the [I.name]!") playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) @@ -49,138 +43,65 @@ src.gib() -/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0) - shock_damage *= siemens_coeff - if(dna && dna.species) - shock_damage *= dna.species.siemens_coeff - if(shock_damage<1 && !override) - return 0 - if(reagents.has_reagent("teslium")) - shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! - take_overall_damage(0,shock_damage) - visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock coursing through your body!", \ - "You hear a heavy electrical crack." \ - ) - jitteriness += 1000 //High numbers for violent convulsions - do_jitter_animation(jitteriness) - stuttering += 2 - if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) - Stun(2) - spawn(20) - jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less - if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) - Stun(3) - Weaken(3) - if(override) - return override - else - return shock_damage +/mob/living/carbon/swap_hand(held_index) + if(!held_index) + held_index = (active_hand_index % held_items.len)+1 - -/mob/living/carbon/swap_hand() - var/obj/item/item_in_hand = src.get_active_hand() + var/obj/item/item_in_hand = src.get_active_held_item() if(item_in_hand) //this segment checks if the item in your hand is twohanded. if(istype(item_in_hand,/obj/item/weapon/twohanded)) if(item_in_hand:wielded == 1) usr << "Your other hand is too busy holding the [item_in_hand.name]" return - src.hand = !( src.hand ) - if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand]) + var/oindex = active_hand_index + active_hand_index = held_index + if(hud_used) var/obj/screen/inventory/hand/H - H = hud_used.inv_slots[slot_l_hand] - H.update_icon() - H = hud_used.inv_slots[slot_r_hand] - H.update_icon() - /*if (!( src.hand )) - src.hands.setDir(NORTH) - else - src.hands.setDir(SOUTH)*/ - return + H = hud_used.hand_slots["[oindex]"] + if(H) + H.update_icon() + H = hud_used.hand_slots["[held_index]"] + if(H) + H.update_icon() -/mob/living/carbon/activate_hand(selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. + +/mob/living/carbon/activate_hand(selhand) //l/r OR 1-held_items.len + if(!selhand) + selhand = (active_hand_index % held_items.len)+1 if(istext(selhand)) selhand = lowertext(selhand) - if(selhand == "right" || selhand == "r") - selhand = 0 + selhand = 2 if(selhand == "left" || selhand == "l") selhand = 1 - if(selhand != src.hand) - swap_hand() + if(selhand != active_hand_index) + swap_hand(selhand) else mode() // Activate held item -/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) - if(on_fire) - M << "You can't put them out with just your bare hands!" - return +/mob/living/carbon/attackby(obj/item/I, mob/user, params) + if(lying && surgeries.len) + if(user != src && user.a_intent == "help") + for(var/datum/surgery/S in surgeries) + if(S.next_step(user)) + return 1 + return ..() - if(health >= 0 && !(status_flags & FAKEDEATH)) - - if(lying) - M.visible_message("[M] shakes [src] trying to get them up!", \ - "You shake [src] trying to get them up!") - else - M.visible_message("[M] hugs [src] to make them feel better!", \ - "You hug [src] to make them feel better!") - AdjustSleeping(-5) - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - if(resting) - resting = 0 - update_canmove() - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - -/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0) +/mob/living/carbon/throw_impact(atom/hit_atom) . = ..() - - var/damage = intensity - check_eye_prot() - if(.) // we've been flashed - if(visual) - return - if(weakeyes) - Stun(2) - - if (damage == 1) - src << "Your eyes sting a little." - if(prob(40)) - adjust_eye_damage(1) - - else if (damage == 2) - src << "Your eyes burn." - adjust_eye_damage(rand(2, 4)) - - else if( damage > 3) - src << "Your eyes itch and burn severely!" - adjust_eye_damage(rand(12, 16)) - - if(eye_damage > 10) - blind_eyes(damage) - blur_eyes(damage * rand(3, 6)) - - if(eye_damage > 20) - if(prob(eye_damage - 20)) - if(become_nearsighted()) - src << "Your eyes start to burn badly!" - else if(prob(eye_damage - 25)) - if(become_blind()) - src << "You can't see anything!" - else - src << "Your eyes are really starting to hurt. This can't be good for you!" - if(has_bane(BANE_LIGHT)) - mind.disrupt_spells(-500) - return 1 - else if(damage == 0) // just enough protection - if(prob(20)) - src << "Something bright flashes in the corner of your vision!" - if(has_bane(BANE_LIGHT)) - mind.disrupt_spells(0) + if(hit_atom.density && isturf(hit_atom)) + Weaken(1) + take_bodypart_damage(10) + if(iscarbon(hit_atom)) + var/mob/living/carbon/victim = hit_atom + victim.Weaken(1) + Weaken(1) + victim.take_bodypart_damage(10) + take_bodypart_damage(10) + visible_message("[src] crashes into [victim], knocking them both over!", "You violently crash into [victim]!") + playsound(src,'sound/weapons/punch1.ogg',50,1) //Throwing stuff @@ -215,7 +136,7 @@ return var/atom/movable/thrown_thing - var/obj/item/I = src.get_active_hand() + var/obj/item/I = src.get_active_held_item() if(!I) if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) @@ -253,9 +174,11 @@ [name]

Head: [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"] -
Mask: [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"] -
Left Hand: [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] -
Right Hand: [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"]"} +
Mask: [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]"} + + for(var/i in 1 to held_items.len) + var/obj/item/I = get_item_for_held_index(i) + dat += "
[get_held_index_name(i)]:[(I && !(I.flags & ABSTRACT)) ? I : "Nothing"]" dat += "
Back: [back ? back : "Nothing"]" @@ -303,13 +226,6 @@ /mob/living/carbon/is_muzzled() return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) -/mob/living/carbon/blob_act(obj/effect/blob/B) - if (stat == DEAD) - return - else - show_message("The blob attacks!") - adjustBruteLoss(10) - /mob/living/carbon/proc/spin(spintime, speed) set waitfor = 0 var/D = dir @@ -462,10 +378,6 @@ else return initial(pixel_y) -/mob/living/carbon/check_ear_prot() - if(head && (head.flags & HEADBANGPROTECT)) - return 1 - /mob/living/carbon/proc/accident(obj/item/I) if(!I || (I.flags & (NODROP|ABSTRACT))) return @@ -494,17 +406,6 @@ var/turf/target = get_turf(loc) I.throw_at(target,I.throw_range,I.throw_speed,src) -/mob/living/carbon/emp_act(severity) - for(var/obj/item/organ/O in internal_organs) - O.emp_act(severity) - ..() - -/mob/living/carbon/check_eye_prot() - var/number = ..() - for(var/obj/item/organ/cyberimp/eyes/EFP in internal_organs) - number += EFP.flash_protect - return number - /mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A) abilities.Add(A) A.on_gain(src) @@ -533,6 +434,11 @@ add_abilities_to_panel() +/mob/living/carbon/attack_ui(slot) + if(!has_hand_for_held_index(active_hand_index)) + return 0 + return ..() + /mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0) if(nutrition < 100 && !blood) if(message) @@ -573,12 +479,29 @@ return 1 - /mob/living/carbon/fully_replace_character_name(oldname,newname) ..() if(dna) dna.real_name = real_name +//Updates the mob's health from bodyparts and mob damage variables +/mob/living/carbon/updatehealth() + if(status_flags & GODMODE) + return + var/total_burn = 0 + var/total_brute = 0 + for(var/X in bodyparts) //hardcoded to streamline things a bit + var/obj/item/bodypart/BP = X + total_brute += BP.brute_dam + total_burn += BP.burn_dam + health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute + update_stat() + if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD ) + become_husk() + if(on_fire) + shred_clothing() + med_hud_set_health() + /mob/living/carbon/update_sight() if(!client) return @@ -733,8 +656,7 @@ //called when we get cuffed/uncuffed /mob/living/carbon/proc/update_handcuffed() if(handcuffed) - drop_r_hand() - drop_l_hand() + drop_all_held_items() stop_pulling() throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed) else @@ -752,6 +674,7 @@ for(var/datum/disease/D in viruses) D.cure(0) if(admin_revive) + regenerate_limbs() handcuffed = initial(handcuffed) for(var/obj/item/weapon/restraints/R in contents) //actually remove cuffs from inventory qdel(R) @@ -769,7 +692,8 @@ if(qdeleted(src)) return var/organs_amt = 0 - for(var/obj/item/organ/O in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/O = X if(prob(50)) organs_amt++ O.Remove(src) @@ -779,15 +703,6 @@ ..() -/mob/living/carbon/adjustToxLoss(amount, updating_health=1) - if(has_dna() && TOXINLOVER in dna.species.specflags) //damage becomes healing and healing becomes damage - amount = -amount - if(amount > 0) - blood_volume -= 5*amount - else - blood_volume -= amount - return ..() - /mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning") overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"= fire_icon, "layer"=-FIRE_LAYER) apply_overlay(FIRE_LAYER) @@ -795,3 +710,34 @@ /mob/living/carbon/fakefireextinguish() remove_overlay(FIRE_LAYER) + +/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130) + C.visible_message("[src] is attempting to devour [C]!", \ + "[src] is attempting to devour you!") + if(!do_mob(src, C, devour_time)) + return + if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == "grab") + C.visible_message("[src] devours [C]!", \ + "[src] devours you!") + C.forceMove(src) + stomach_contents.Add(C) + add_logs(src, C, "devoured") + +/mob/living/carbon/proc/create_bodyparts() + for(var/X in bodyparts) + var/obj/item/bodypart/O = new X() + O.owner = src + bodyparts.Remove(X) + bodyparts.Add(O) + if(O.body_part == ARM_LEFT) + O.held_index = 1 + hand_bodyparts += O + else if(O.body_part == ARM_RIGHT) + O.held_index = 2 + hand_bodyparts += O + + +/mob/living/carbon/proc/create_internal_organs() + for(var/X in internal_organs) + var/obj/item/organ/I = X + I.Insert(src) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 09153d8cd93..4de7733bd26 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -1,6 +1,22 @@ + +/mob/living/carbon/get_eye_protection() + var/number = ..() + for(var/obj/item/organ/cyberimp/eyes/EFP in internal_organs) + number += EFP.flash_protect + return number + +/mob/living/carbon/get_ear_protection() + if(head && (head.flags & HEADBANGPROTECT)) + return 1 + +/mob/living/carbon/check_projectile_dismemberment(obj/item/projectile/P, def_zone) + var/obj/item/bodypart/affecting = get_bodypart(def_zone) + if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment)) + affecting.dismember(P.damtype) + /mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0) if(!skipcatch) //ugly, but easy - if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode + if(in_throw_mode && !get_active_held_item()) //empty active hand and we're in throw mode if(canmove && !restrained()) if(istype(AM, /obj/item)) var/obj/item/I = AM @@ -11,32 +27,42 @@ return 1 ..() -/mob/living/carbon/throw_impact(atom/hit_atom) - . = ..() - if(hit_atom.density && isturf(hit_atom)) - Weaken(1) - take_organ_damage(10) - if(iscarbon(hit_atom)) - var/mob/living/carbon/victim = hit_atom - victim.Weaken(1) - Weaken(1) - victim.take_organ_damage(10) - take_organ_damage(10) - visible_message("[src] crashes into [victim], knocking them both over!", "You violently crash into [victim]!") - playsound(src,'sound/weapons/punch1.ogg',50,1) -/mob/living/carbon/attackby(obj/item/I, mob/user, params) - if(lying && surgeries.len) - if(user != src && user.a_intent == "help") - for(var/datum/surgery/S in surgeries) - if(S.next_step(user)) - return 1 - return ..() +/mob/living/carbon/attacked_by(obj/item/I, mob/living/user) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected)) + if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest) + affecting = bodyparts[1] + send_item_attack_message(I, user, affecting.name) + if(I.force) + apply_damage(I.force, I.damtype, affecting) + if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC) + if(prob(33)) + I.add_mob_blood(src) + var/turf/location = get_turf(src) + add_splatter_floor(location) + if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood + user.add_mob_blood(src) + if(affecting.body_zone == "head") + if(wear_mask) + wear_mask.add_mob_blood(src) + update_inv_wear_mask() + if(head) + head.add_mob_blood(src) + update_inv_head() + + //dismemberment + var/probability = I.get_dismemberment_chance(affecting) + if(prob(probability)) + if(affecting.dismember(I.damtype)) + I.add_mob_blood(src) + playsound(get_turf(src), I.get_dismember_sound(), 80, 1) + return TRUE //successful attack + +/mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user) + return //so we don't call the carbon's attack_hand(). /mob/living/carbon/attack_hand(mob/living/carbon/human/user) - if(!iscarbon(user)) - return for(var/datum/disease/D in viruses) if(D.IsSpreadByTouch()) @@ -55,9 +81,6 @@ /mob/living/carbon/attack_paw(mob/living/carbon/monkey/M) - if(!istype(M, /mob/living/carbon)) - return 0 - for(var/datum/disease/D in viruses) if(D.IsSpreadByTouch()) M.ContractDisease(D) @@ -101,20 +124,8 @@ updatehealth() return 1 -/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130) - C.visible_message("[src] is attempting to devour [C]!", \ - "[src] is attempting to devour you!") - if(!do_mob(src, C, devour_time)) - return - if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == "grab") - C.visible_message("[src] devours [C]!", \ - "[src] devours you!") - C.forceMove(src) - stomach_contents.Add(C) - add_logs(src, C, "devoured") - /mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone) - if(!attacker.limb_destroyer || !has_limbs) + if(!attacker.limb_destroyer) return dam_zone var/obj/item/bodypart/affecting if(dam_zone && attacker.client) @@ -134,3 +145,136 @@ return null return affecting.body_zone return dam_zone + + +/mob/living/carbon/blob_act(obj/effect/blob/B) + if (stat == DEAD) + return + else + show_message("The blob attacks!") + adjustBruteLoss(10) + +/mob/living/carbon/emp_act(severity) + for(var/X in internal_organs) + var/obj/item/organ/O = X + O.emp_act(severity) + ..() + +/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0) + shock_damage *= siemens_coeff + if(dna && dna.species) + shock_damage *= dna.species.siemens_coeff + if(shock_damage<1 && !override) + return 0 + if(reagents.has_reagent("teslium")) + shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! + take_overall_damage(0,shock_damage) + visible_message( + "[src] was shocked by \the [source]!", \ + "You feel a powerful shock coursing through your body!", \ + "You hear a heavy electrical crack." \ + ) + jitteriness += 1000 //High numbers for violent convulsions + do_jitter_animation(jitteriness) + stuttering += 2 + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(2) + spawn(20) + jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(3) + Weaken(3) + if(override) + return override + else + return shock_damage + +/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) + if(on_fire) + M << "You can't put them out with just your bare hands!" + return + + if(health >= 0 && !(status_flags & FAKEDEATH)) + + if(lying) + M.visible_message("[M] shakes [src] trying to get them up!", \ + "You shake [src] trying to get them up!") + else + M.visible_message("[M] hugs [src] to make them feel better!", \ + "You hug [src] to make them feel better!") + AdjustSleeping(-5) + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + if(resting) + resting = 0 + update_canmove() + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + +/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0) + . = ..() + + var/damage = intensity - get_eye_protection() + if(.) // we've been flashed + if(visual) + return + if(weakeyes) + Stun(2) + + if (damage == 1) + src << "Your eyes sting a little." + if(prob(40)) + adjust_eye_damage(1) + + else if (damage == 2) + src << "Your eyes burn." + adjust_eye_damage(rand(2, 4)) + + else if( damage > 3) + src << "Your eyes itch and burn severely!" + adjust_eye_damage(rand(12, 16)) + + if(eye_damage > 10) + blind_eyes(damage) + blur_eyes(damage * rand(3, 6)) + + if(eye_damage > 20) + if(prob(eye_damage - 20)) + if(become_nearsighted()) + src << "Your eyes start to burn badly!" + else if(prob(eye_damage - 25)) + if(become_blind()) + src << "You can't see anything!" + else + src << "Your eyes are really starting to hurt. This can't be good for you!" + if(has_bane(BANE_LIGHT)) + mind.disrupt_spells(-500) + return 1 + else if(damage == 0) // just enough protection + if(prob(20)) + src << "Something bright flashes in the corner of your vision!" + if(has_bane(BANE_LIGHT)) + mind.disrupt_spells(0) + + +/mob/living/carbon/soundbang_act(intensity = 1, stun_pwr = 1, damage_pwr = 5, deafen_pwr = 15) + var/ear_safety = get_ear_protection() + if(ear_safety < 2) //has ears + var/effect_amount = intensity - ear_safety + if(effect_amount > 0) + if(stun_pwr) + Stun(stun_pwr*effect_amount) + Weaken(stun_pwr*effect_amount) + if(deafen_pwr || damage_pwr) + setEarDamage(ear_damage + damage_pwr*effect_amount, max(ear_deaf, deafen_pwr*effect_amount)) + if (ear_damage >= 15) + src << "Your ears start to ring badly!" + if(prob(ear_damage - 5)) + src << "You can't hear anything!" + disabilities |= DEAF + else if(ear_damage >= 5) + src << "Your ears start to ring!" + src << sound('sound/weapons/flash_ring.ogg',0,1,0,250) + return effect_amount //how soundbanged we are diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 103fcbe50d7..f73ad1053c1 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -16,6 +16,11 @@ var/obj/item/weapon/tank/internal = null var/obj/item/head = null + var/obj/item/gloves = null //only used by humans + var/obj/item/shoes = null //only used by humans. + var/obj/item/clothing/glasses/glasses = null //only used by humans. + var/obj/item/ears = null //only used by humans. + var/datum/dna/dna = null//Carbon var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. @@ -32,4 +37,8 @@ var/tinttotal = 0 // Total level of visualy impairing items - var/list/bodyparts = list() //Gets filled up in the constructor (New() proc in human.dm and monkey.dm) + var/list/bodyparts = list(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm, + /obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg) + //Gets filled up in create_bodyparts() + + var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index 479e9459c5c..6b2e19c1959 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -1,6 +1,13 @@ /mob/living/carbon/movement_delay() . = ..() - . += grab_state * 3 + . += grab_state * 3 //can't go fast while grabbing something. + + if(!get_leg_ignore()) //ignore the fact we lack legs + var/leg_amount = get_num_legs() + . += 6 - 3*leg_amount //the fewer the legs, the slower the mob + if(!leg_amount) + . += 6 - 3*get_num_arms() //crawling is harder with fewer arms + if(legcuffed) . += legcuffed.slowdown diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm new file mode 100644 index 00000000000..6da20373f62 --- /dev/null +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -0,0 +1,191 @@ + + +/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = 0) + var/hit_percent = (100-blocked)/100 + if(!damage || hit_percent <= 0) + return 0 + + var/obj/item/bodypart/BP = null + if(islimb(def_zone)) //we specified a bodypart object + BP = def_zone + else + if(!def_zone) + def_zone = ran_zone(def_zone) + BP = get_bodypart(check_zone(def_zone)) + if(!BP) + BP = bodyparts[1] + + switch(damagetype) + if(BRUTE) + if(BP) + if(BP.take_damage(damage * hit_percent, 0)) + update_damage_overlays() + else //no bodypart, we deal damage with a more general method. + adjustBruteLoss(damage * hit_percent) + if(BURN) + if(BP) + if(BP.take_damage(0, damage * hit_percent)) + update_damage_overlays() + else + adjustFireLoss(damage * hit_percent) + if(TOX) + adjustToxLoss(damage * hit_percent) + if(OXY) + adjustOxyLoss(damage * hit_percent) + if(CLONE) + adjustCloneLoss(damage * hit_percent) + if(STAMINA) + adjustStaminaLoss(damage * hit_percent) + return 1 + + +//These procs fetch a cumulative total damage from all bodyparts +/mob/living/carbon/getBruteLoss() + var/amount = 0 + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + amount += BP.brute_dam + return amount + +/mob/living/carbon/getFireLoss() + var/amount = 0 + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + amount += BP.burn_dam + return amount + + +/mob/living/carbon/adjustBruteLoss(amount, updating_health = 1) + if(status_flags & GODMODE) + return 0 + if(amount > 0) + take_overall_damage(amount, 0) + else + heal_overall_damage(-amount, 0, 0, 1, updating_health) + +/mob/living/carbon/adjustFireLoss(amount) + if(status_flags & GODMODE) + return 0 + if(amount > 0) + take_overall_damage(0, amount) + else + heal_overall_damage(0, -amount) + + +/mob/living/carbon/adjustToxLoss(amount, updating_health=1) + if(has_dna() && TOXINLOVER in dna.species.specflags) //damage becomes healing and healing becomes damage + amount = -amount + if(amount > 0) + blood_volume -= 5*amount + else + blood_volume -= amount + return ..() + +//////////////////////////////////////////// + +//Returns a list of damaged bodyparts +/mob/living/carbon/proc/get_damaged_bodyparts(brute, burn) + var/list/obj/item/bodypart/parts = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if((brute && BP.brute_dam) || (burn && BP.burn_dam)) + parts += BP + return parts + +//Returns a list of damageable bodyparts +/mob/living/carbon/proc/get_damageable_bodyparts() + var/list/obj/item/bodypart/parts = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(BP.brute_dam + BP.burn_dam < BP.max_damage) + parts += BP + return parts + +//Heals ONE bodypart randomly selected from damaged ones. +//It automatically updates damage overlays if necessary +//It automatically updates health status +/mob/living/carbon/heal_bodypart_damage(brute, burn, only_robotic = 0, only_organic = 1) + var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn) + if(!parts.len) + return + var/obj/item/bodypart/picked = pick(parts) + if(picked.heal_damage(brute, burn, only_robotic, only_organic)) + update_damage_overlays() + +//Damages ONE bodypart randomly selected from damagable ones. +//It automatically updates damage overlays if necessary +//It automatically updates health status +/mob/living/carbon/take_bodypart_damage(brute, burn) + var/list/obj/item/bodypart/parts = get_damageable_bodyparts() + if(!parts.len) + return + var/obj/item/bodypart/picked = pick(parts) + if(picked.take_damage(brute,burn)) + update_damage_overlays() + + +//Heal MANY bodyparts, in random order +/mob/living/carbon/heal_overall_damage(brute, burn, only_robotic = 0, only_organic = 1, updating_health = 1) + var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn) + + var/update = 0 + while(parts.len && (brute>0 || burn>0) ) + var/obj/item/bodypart/picked = pick(parts) + + var/brute_was = picked.brute_dam + var/burn_was = picked.burn_dam + + update |= picked.heal_damage(brute,burn, only_robotic, only_organic, 0) + + brute -= (brute_was-picked.brute_dam) + burn -= (burn_was-picked.burn_dam) + + parts -= picked + if(updating_health) + updatehealth() + if(update) + update_damage_overlays() + +// damage MANY bodyparts, in random order +/mob/living/carbon/take_overall_damage(brute, burn, updating_health = 1) + if(status_flags & GODMODE) + return //godmode + + var/list/obj/item/bodypart/parts = get_damageable_bodyparts() + var/update = 0 + while(parts.len && (brute>0 || burn>0) ) + var/obj/item/bodypart/picked = pick(parts) + var/brute_per_part = round(brute/parts.len, 0.01) + var/burn_per_part = round(burn/parts.len, 0.01) + + var/brute_was = picked.brute_dam + var/burn_was = picked.burn_dam + + + update |= picked.take_damage(brute_per_part,burn_per_part, 0) + + brute -= (picked.brute_dam - brute_was) + burn -= (picked.burn_dam - burn_was) + + parts -= picked + if(updating_health) + updatehealth() + if(update) + update_damage_overlays() + + + +/mob/living/carbon/adjustStaminaLoss(amount, updating_stamina = 1) + if(status_flags & GODMODE) + return 0 + staminaloss = Clamp(staminaloss + amount, 0, maxHealth*2) + if(updating_stamina) + update_stamina() + + +/mob/living/carbon/setStaminaLoss(amount, updating_stamina = 1) + if(status_flags & GODMODE) + return 0 + staminaloss = amount + if(updating_stamina) + update_stamina() diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 3db1d738a96..f1a2a526a7a 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -3,19 +3,43 @@ losebreath = 0 ..() -/mob/living/carbon/gib(no_brain, no_organs) +/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts) for(var/mob/M in src) if(M in stomach_contents) stomach_contents.Remove(M) - M.loc = loc + M.forceMove(loc) visible_message("[M] bursts out of [src]!") ..() -/mob/living/carbon/spill_organs(no_brain) - for(var/obj/item/organ/I in internal_organs) - if(no_brain && istype(I, /obj/item/organ/brain)) - continue - if(I) +/mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts) + if(!no_bodyparts) + if(no_organs)//so the organs don't get transfered inside the bodyparts we'll drop. + for(var/X in internal_organs) + qdel(X) + else //we're going to drop all bodyparts except chest, so the only organs that needs spilling are those inside it. + for(var/X in internal_organs) + var/obj/item/organ/O = X + if(no_brain && istype(O, /obj/item/organ/brain)) + qdel(O) //so the brain isn't transfered to the head when the head drops. + continue + var/org_zone = check_zone(O.zone) //both groin and chest organs. + if(org_zone == "chest") + O.Remove(src) + O.forceMove(get_turf(src)) + O.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) + else + for(var/X in internal_organs) + var/obj/item/organ/I = X + if(no_brain && istype(I, /obj/item/organ/brain)) + qdel(I) + continue I.Remove(src) - I.loc = get_turf(src) + I.forceMove(get_turf(src)) I.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) + + +/mob/living/carbon/spread_bodyparts() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + BP.drop_limb() + BP.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 6842d856b03..61d30f7b8e9 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -2,63 +2,80 @@ var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" if (handcuffed) - msg += "It is \icon[src.handcuffed] handcuffed!\n" + msg += "It is \icon[src.handcuffed] handcuffed!\n" if (head) msg += "It has \icon[src.head] \a [src.head] on its head. \n" if (wear_mask) msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n" - if (l_hand) - msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n" - if (r_hand) - msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n" + + for(var/obj/item/I in held_items) + if(!(I.flags & ABSTRACT)) + if(I.blood_DNA) + msg += "It has \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n" + else + msg += "It has \icon[I] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n" + if (back) msg += "It has \icon[src.back] \a [src.back] on its back.\n" + var/appears_dead = 0 if (stat == DEAD) - msg += "It is limp and unresponsive, with no signs of life.\n" - else - msg += "" - var/temp = getBruteLoss() - if(temp) - if (temp < 30) - msg += "It has minor bruising.\n" - else - msg += "It has severe bruising!\n" + appears_dead = 1 + if(getorgan(/obj/item/organ/brain)) + msg += "It is limp and unresponsive, with no signs of life.\n" + else if(get_bodypart("head")) + msg += "It appears that it's brain is missing...\n" - temp = getFireLoss() - if(temp) - if (temp < 30) - msg += "It has minor burns.\n" - else - msg += "It has severe burns!\n" + var/list/missing = get_missing_limbs() + for(var/t in missing) + if(t=="head") + msg += "Its [parse_zone(t)] is missing!\n" + continue + msg += "<Its [parse_zone(t)] is missing!\n" - temp = getCloneLoss() - if(temp) - if(getCloneLoss() < 30) - msg += "It is slightly deformed.\n" - else - msg += "It is severely deformed.\n" + msg += "" + var/temp = getBruteLoss() + if(temp) + if (temp < 30) + msg += "It has minor bruising.\n" + else + msg += "It has severe bruising!\n" - if(getBrainLoss() > 60) - msg += "It seems to be clumsy and unable to think.\n" + temp = getFireLoss() + if(temp) + if (temp < 30) + msg += "It has minor burns.\n" + else + msg += "It has severe burns!\n" - if(fire_stacks > 0) - msg += "It's covered in something flammable.\n" - if(fire_stacks < 0) - msg += "It's soaked in water.\n" + temp = getCloneLoss() + if(temp) + if(getCloneLoss() < 30) + msg += "It is slightly deformed.\n" + else + msg += "It is severely deformed.\n" - if(pulledby && pulledby.grab_state) - msg += "It's restrained by [pulledby]'s grip.\n" + if(getBrainLoss() > 60) + msg += "It seems to be clumsy and unable to think.\n" + if(fire_stacks > 0) + msg += "It's covered in something flammable.\n" + if(fire_stacks < 0) + msg += "It's soaked in water.\n" + + if(pulledby && pulledby.grab_state) + msg += "It's restrained by [pulledby]'s grip.\n" + + msg += "" + + if(!appears_dead) if(stat == UNCONSCIOUS) msg += "It isn't responding to anything around it; it seems to be asleep.\n" - msg += "" - if(digitalcamo) - msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n" + if(digitalcamo) + msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n" + - if(!getorgan(/obj/item/organ/brain)) - msg += "It appears that it's brain is missing...\n" msg += "*---------*" - user << msg \ No newline at end of file + user << msg diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm new file mode 100644 index 00000000000..aa49718753f --- /dev/null +++ b/code/modules/mob/living/carbon/human/damage_procs.dm @@ -0,0 +1,5 @@ + + +/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) + // depending on the species, it will run the corresponding apply_damage code there + return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index d1b085ca3b9..83bf44f8e14 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -4,8 +4,11 @@ /mob/living/carbon/human/dust_animation() PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-h")) -/mob/living/carbon/human/spawn_gibs() - hgibs(loc, viruses, dna) +/mob/living/carbon/human/spawn_gibs(with_bodyparts) + if(with_bodyparts) + new /obj/effect/gibspawner/human(loc, viruses, dna) + else + new /obj/effect/gibspawner/humanbodypartless(loc, viruses, dna) /mob/living/carbon/human/spawn_dust() new /obj/effect/decal/remains/human(loc) @@ -40,21 +43,9 @@ set_species(/datum/species/skeleton) return 1 -/mob/living/carbon/proc/ChangeToHusk() - if(disabilities & HUSK) - return - disabilities |= HUSK - status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools - return 1 - -/mob/living/carbon/human/ChangeToHusk() - . = ..() - if(.) - update_hair() - update_body() /mob/living/carbon/proc/Drain() - ChangeToHusk() + become_husk() disabilities |= NOCLONE blood_volume = 0 return 1 diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 6d67ed7ad7c..91b85c8a40a 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -178,7 +178,7 @@ if ("handshake") m_type = 1 - if (!src.restrained() && !src.r_hand) + if (!src.restrained() && get_empty_held_indexes()) var/mob/M = null if (param) for (var/mob/A in view(1, src)) @@ -188,7 +188,7 @@ if (M == src) M = null if (M) - if (M.canmove && !M.r_hand && !M.restrained()) + if (M.canmove && M.get_empty_held_indexes() && !M.restrained()) message = "[src] shakes hands with [M]." else message = "[src] holds out \his hand to [M]." @@ -298,12 +298,16 @@ if ("signal","signals") if (!src.restrained()) + var/maximum_fingers = 10 + var/full_hands + for(var/obj/item/I in held_items) + full_hands++ + maximum_fingers = (held_items.len-full_hands)*5 var/t1 = round(text2num(param)) if (isnum(t1)) - if (t1 <= 5 && (!src.r_hand || !src.l_hand)) - message = "[src] raises [t1] finger\s." - else if (t1 <= 10 && (!src.r_hand && !src.l_hand)) + if (t1 <= maximum_fingers) message = "[src] raises [t1] finger\s." + m_type = 1 if ("sneeze","sneezes") diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 4f153b8ad86..6aae26c14c5 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -73,19 +73,13 @@ else msg += "[t_He] [t_has] \icon[back] \a [back] on [t_his] back.\n" - //left hand - if(l_hand && !(l_hand.flags&ABSTRACT)) - if(l_hand.blood_DNA) - msg += "[t_He] [t_is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in [t_his] left hand!\n" - else - msg += "[t_He] [t_is] holding \icon[l_hand] \a [l_hand] in [t_his] left hand.\n" - - //right hand - if(r_hand && !(r_hand.flags&ABSTRACT)) - if(r_hand.blood_DNA) - msg += "[t_He] [t_is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in [t_his] right hand!\n" - else - msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n" + //Hands + for(var/obj/item/I in held_items) + if(!(I.flags & ABSTRACT)) + if(I.blood_DNA) + msg += "[t_He] [t_is] holding \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n" + else + msg += "[t_He] [t_is] holding \icon[I] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n" //gloves if(gloves && !(slot_gloves in obscured)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 41f2caab2dc..1c7a02138df 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -3,7 +3,7 @@ real_name = "Unknown" voice_name = "Unknown" icon = 'icons/mob/human.dmi' - icon_state = "caucasian1_m_s" + icon_state = "caucasian_m_s" @@ -18,11 +18,7 @@ verbs += /mob/living/proc/lay_down //initialize limbs first - bodyparts = newlist(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm, - /obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg) - for(var/X in bodyparts) - var/obj/item/bodypart/O = X - O.owner = src + create_bodyparts() //initialize dna. for spawned humans; overwritten by other code create_dna(src) @@ -33,21 +29,7 @@ set_species(dna.species.type) //initialise organs - if(!(NOHUNGER in dna.species.specflags)) - internal_organs += new /obj/item/organ/appendix - - if(!(NOBREATH in dna.species.specflags)) - internal_organs += new /obj/item/organ/lungs - - if(!(NOBLOOD in dna.species.specflags)) - internal_organs += new /obj/item/organ/heart - - internal_organs += new /obj/item/organ/brain - - //Note: Additional organs are generated/replaced on the dna.species level - - for(var/obj/item/organ/I in internal_organs) - I.Insert(src) + create_internal_organs() martial_art = default_martial_art @@ -55,6 +37,16 @@ ..() +/mob/living/carbon/human/create_internal_organs() + if(!(NOHUNGER in dna.species.specflags)) + internal_organs += new /obj/item/organ/appendix + if(!(NOBREATH in dna.species.specflags)) + internal_organs += new /obj/item/organ/lungs + if(!(NOBLOOD in dna.species.specflags)) + internal_organs += new /obj/item/organ/heart + internal_organs += new /obj/item/organ/brain + ..() + /mob/living/carbon/human/OpenCraftingMenu() handcrafting.ui_interact(src) @@ -116,96 +108,17 @@ stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]") -/mob/living/carbon/human/ex_act(severity, ex_target) - var/b_loss = null - var/f_loss = null - var/bomb_armor = getarmor(null, "bomb") - if(istype(ex_target, /datum/spacevine_mutation) && isvineimmune(src)) - return - - switch (severity) - if (1) - b_loss += 500 - if (prob(bomb_armor)) - shred_clothing(1,150) - var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src))) - throw_at(target, 200, 4) - else - gib() - return - - if (2) - b_loss += 60 - - f_loss += 60 - if (prob(bomb_armor)) - b_loss = b_loss/1.5 - f_loss = f_loss/1.5 - shred_clothing(1,25) - else - shred_clothing(1,50) - - if (!istype(ears, /obj/item/clothing/ears/earmuffs)) - adjustEarDamage(30, 120) - if (prob(70)) - Paralyse(10) - - if(3) - b_loss += 30 - if (prob(bomb_armor)) - b_loss = b_loss/2 - if (!istype(ears, /obj/item/clothing/ears/earmuffs)) - adjustEarDamage(15,60) - if (prob(50)) - Paralyse(10) - - take_overall_damage(b_loss,f_loss) - //attempt to dismember bodyparts - if(severity <= 2 || !bomb_armor) - var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3. - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if(prob(50/severity) && !prob(getarmor(BP, "bomb")) && BP.body_zone != "head" && BP.body_zone != "chest") - BP.brute_dam = BP.max_damage - BP.dismember() - max_limb_loss-- - if(!max_limb_loss) - break - ..() - -/mob/living/carbon/human/blob_act(obj/effect/blob/B) - if(stat == DEAD) - return - show_message("The blob attacks you!") - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee")) - return - -/mob/living/carbon/human/bullet_act() - if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles! - if(!prob(martial_art.deflection_chance)) - return ..() - if(!src.lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it - src.visible_message("[src] deflects the projectile; they can't be hit with ranged weapons!", "You deflect the projectile!") - playsound(src, pick("sound/weapons/bulletflyby.ogg","sound/weapons/bulletflyby2.ogg","sound/weapons/bulletflyby3.ogg"), 75, 1) - return 0 - ..() - -/mob/living/carbon/human/attack_ui(slot) - if(!get_bodypart(hand ? "l_arm" : "r_arm")) - return 0 - return ..() - /mob/living/carbon/human/show_inv(mob/user) user.set_machine(src) var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) var/list/obscured = check_obscured_slots() + var/list/dat = list() - var/dat = {" - - - "} + dat += "
Left Hand:[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Empty"]
Right Hand:[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Empty"]
 
" + for(var/i in 1 to held_items.len) + var/obj/item/I = get_item_for_held_index(i) + dat += "" + dat += "" dat += "
[get_held_index_name(i)]:[(I && !(I.flags & ABSTRACT)) ? I : "Empty"]
 
Back:[(back && !(back.flags&ABSTRACT)) ? back : "Empty"]" if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) @@ -279,7 +192,7 @@ "} var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 510) - popup.set_content(dat) + popup.set_content(dat.Join()) popup.open() // called when something steps onto a human @@ -291,35 +204,6 @@ spreadFire(AM) -//Added a safety check in case you want to shock a human mob directly through electrocute_act. -/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0) - if(tesla_shock) - var/total_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - if(G.siemens_coefficient <= 0) - total_coeff -= 0.5 - if(wear_suit) - var/obj/item/clothing/suit/S = wear_suit - if(S.siemens_coefficient <= 0) - total_coeff -= 0.95 - siemens_coeff = total_coeff - else if(!safety) - var/gloves_siemens_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - gloves_siemens_coeff = G.siemens_coefficient - siemens_coeff = gloves_siemens_coeff - if(heart_attack) - if(shock_damage * siemens_coeff >= 1 && prob(25)) - heart_attack = 0 - if(stat == CONSCIOUS) - src << "You feel your heart beating again!" - . = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock) - if(.) - electrocution_animation(40) - - /mob/living/carbon/human/Topic(href, href_list) if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) @@ -354,7 +238,7 @@ var/pocket_side = href_list["pockets"] var/pocket_id = (pocket_side == "right" ? slot_r_store : slot_l_store) var/obj/item/pocket_item = (pocket_id == slot_r_store ? r_store : l_store) - var/obj/item/place_item = usr.get_active_hand() // Item to place in the pocket, if it's empty + var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty var/delay_denominator = 1 if(pocket_item && !(pocket_item.flags&ABSTRACT)) @@ -653,7 +537,7 @@ if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve if(istype(wear_suit, /obj/item/clothing/suit/redtag)) threatcount += 4 - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag)) threatcount += 4 if(istype(belt, /obj/item/weapon/gun/energy/laser/redtag)) threatcount += 2 @@ -661,7 +545,7 @@ if(lasercolor == "r") if(istype(wear_suit, /obj/item/clothing/suit/bluetag)) threatcount += 4 - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag)) threatcount += 4 if(istype(belt, /obj/item/weapon/gun/energy/laser/bluetag)) threatcount += 2 @@ -676,10 +560,9 @@ //Check for weapons if(judgebot.weaponscheck) if(!idcard || !(access_weapons in idcard.access)) - if(judgebot.check_for_weapons(l_hand)) - threatcount += 4 - if(judgebot.check_for_weapons(r_hand)) - threatcount += 4 + for(var/obj/item/I in held_items) + if(judgebot.check_for_weapons(I)) + threatcount += 4 if(judgebot.check_for_weapons(belt)) threatcount += 2 @@ -726,21 +609,9 @@ update_body() update_hair() -/mob/living/carbon/human/singularity_act() - var/gain = 20 - if(mind) - if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") ) - gain = 100 - if(mind.assigned_role == "Clown") - gain = rand(-300, 300) - investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! - gib() - return(gain) - /mob/living/carbon/human/singularity_pull(S, current_size) if(current_size >= STAGE_THREE) - var/list/handlist = list(l_hand, r_hand) - for(var/obj/item/hand in handlist) + for(var/obj/item/hand in held_items) if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand)) step_towards(hand, src) src << "\The [S] pulls \the [hand] from your grip!" @@ -749,71 +620,6 @@ return ..() - -/mob/living/carbon/human/help_shake_act(mob/living/carbon/M) - if(!istype(M)) - return - - if(health >= 0) - if(src == M) - visible_message( \ - "[src] examines \himself.", \ - "You check yourself for injuries.") - - var/list/missing = list("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg") - for(var/X in bodyparts) - var/obj/item/bodypart/LB = X - missing -= LB.body_zone - var/status = "" - var/brutedamage = LB.brute_dam - var/burndamage = LB.burn_dam - if(hallucination) - if(prob(30)) - brutedamage += rand(30,40) - if(prob(30)) - burndamage += rand(30,40) - - if(brutedamage > 0) - status = "bruised" - if(brutedamage > 20) - status = "battered" - if(brutedamage > 40) - status = "mangled" - if(brutedamage > 0 && burndamage > 0) - status += " and " - if(burndamage > 40) - status += "peeling away" - - else if(burndamage > 10) - status += "blistered" - else if(burndamage > 0) - status += "numb" - if(status == "") - status = "OK" - src << "\t [status == "OK" ? "\blue" : "\red"] Your [LB.name] is [status]." - - for(var/obj/item/I in LB.embedded_objects) - src << "\t \red There is \a [I] embedded in your [LB.name]!" - - for(var/t in missing) - src << "Your [parse_zone(t)] is missing!" - - if(bleed_rate) - src << "You are bleeding!" - if(staminaloss) - if(staminaloss > 30) - src << "You're completely exhausted." - else - src << "You feel fatigued." - else - if(wear_suit) - wear_suit.add_fingerprint(M) - else if(w_uniform) - w_uniform.add_fingerprint(M) - - ..() - - /mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C) CHECK_DNA_AND_SPECIES(C) @@ -1003,7 +809,6 @@ hud_used.healthdoll.icon_state = "healthdoll_DEAD" /mob/living/carbon/human/fully_heal(admin_revive = 0) - CHECK_DNA_AND_SPECIES(src) if(admin_revive) regenerate_limbs() diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm deleted file mode 100644 index 9ab3c8decc9..00000000000 --- a/code/modules/mob/living/carbon/human/human_attackalien.dm +++ /dev/null @@ -1,39 +0,0 @@ -/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M) - if(check_shields(0, M.name)) - visible_message("[M] attempted to touch [src]!") - return 0 - - if(..()) - if(M.a_intent == "harm") - if (w_uniform) - w_uniform.add_fingerprint(M) - var/damage = prob(90) ? 20 : 0 - if(!damage) - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message("[M] has lunged at [src]!", \ - "[M] has lunged at [src]!") - return 0 - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) - var/armor_block = run_armor_check(affecting, "melee","","",10) - - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") - if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful - return 1 - apply_damage(damage, BRUTE, affecting, armor_block) - add_logs(M, src, "attacked") - updatehealth() - - if(M.a_intent == "disarm") //Always drop item in hand, if no item, get stunned instead. - if(get_active_hand() && drop_item()) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[M] disarmed [src]!", \ - "[M] disarmed [src]!") - else - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - Weaken(5) - add_logs(M, src, "tackled") - visible_message("[M] has tackled down [src]!", \ - "[M] has tackled down [src]!") - return diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm deleted file mode 100644 index 43e4dfaae76..00000000000 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ /dev/null @@ -1,14 +0,0 @@ -/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user) - if(user.a_intent == "harm") - ..(user, 1) - playsound(loc, user.dna.species.attack_sound, 25, 1, -1) - var/hulk_verb = pick("smash","pummel") - visible_message("[user] has [hulk_verb]ed [src]!", \ - "[user] has [hulk_verb]ed [src]!") - adjustBruteLoss(15) - return 1 - -/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M) - if(..()) //to allow surgery to return properly. - return - dna.species.spec_attack_hand(M, src) diff --git a/code/modules/mob/living/carbon/human/human_attackpaw.dm b/code/modules/mob/living/carbon/human/human_attackpaw.dm deleted file mode 100644 index 4c666a86799..00000000000 --- a/code/modules/mob/living/carbon/human/human_attackpaw.dm +++ /dev/null @@ -1,18 +0,0 @@ -/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M) - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - - if(M.a_intent == "help") - ..() //shaking - return 0 - - if(M.limb_destroyer) - dismembering_strike(M, affecting.body_zone) - - if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites. - if(..()) //successful monkey bite, this handles disease contraction. - var/damage = rand(1, 3) - if(stat != DEAD) - apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) - updatehealth() - return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm deleted file mode 100644 index c218fbb8445..00000000000 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ /dev/null @@ -1,161 +0,0 @@ -//Updates the mob's health from bodyparts and mob damage variables -/mob/living/carbon/human/updatehealth() - if(status_flags & GODMODE) - return - var/total_burn = 0 - var/total_brute = 0 - for(var/X in bodyparts) //hardcoded to streamline things a bit - var/obj/item/bodypart/BP = X - total_brute += BP.brute_dam - total_burn += BP.burn_dam - health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute - update_stat() - if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD ) - ChangeToHusk() - if(on_fire) - shred_clothing() - med_hud_set_health() - med_hud_set_status() - - -//These procs fetch a cumulative total damage from all bodyparts -/mob/living/carbon/human/getBruteLoss() - var/amount = 0 - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - amount += BP.brute_dam - return amount - -/mob/living/carbon/human/getFireLoss() - var/amount = 0 - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - amount += BP.burn_dam - return amount - - -/mob/living/carbon/human/adjustBruteLoss(amount) - if(status_flags & GODMODE) - return 0 - if(amount > 0) - take_overall_damage(amount, 0) - else - heal_overall_damage(-amount, 0) - -/mob/living/carbon/human/adjustFireLoss(amount) - if(status_flags & GODMODE) - return 0 - if(amount > 0) - take_overall_damage(0, amount) - else - heal_overall_damage(0, -amount) - -/mob/living/carbon/human/proc/hat_fall_prob() - var/multiplier = 1 - var/obj/item/clothing/head/H = head - var/loose = 40 - if(stat || (status_flags & FAKEDEATH)) - multiplier = 2 - if(H.flags_cover & (HEADCOVERSEYES | HEADCOVERSMOUTH) || H.flags_inv & (HIDEEYES | HIDEFACE)) - loose = 0 - return loose * multiplier - -//////////////////////////////////////////// - -//Returns a list of damaged bodyparts -/mob/living/carbon/human/proc/get_damaged_bodyparts(brute, burn) - var/list/obj/item/bodypart/parts = list() - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if((brute && BP.brute_dam) || (burn && BP.burn_dam)) - parts += BP - return parts - -//Returns a list of damageable bodyparts -/mob/living/carbon/human/proc/get_damageable_bodyparts() - var/list/obj/item/bodypart/parts = list() - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if(BP.brute_dam + BP.burn_dam < BP.max_damage) - parts += BP - return parts - -//Heals ONE external organ, organ gets randomly selected from damaged ones. -//It automatically updates damage overlays if necesary -//It automatically updates health status -/mob/living/carbon/human/heal_organ_damage(brute, burn) - var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn) - if(!parts.len) - return - var/obj/item/bodypart/picked = pick(parts) - if(picked.heal_damage(brute,burn,0)) - update_damage_overlays(0) - updatehealth() - -//Damages ONE external organ, organ gets randomly selected from damagable ones. -//It automatically updates damage overlays if necesary -//It automatically updates health status -/mob/living/carbon/human/take_organ_damage(brute, burn) - var/list/obj/item/bodypart/parts = get_damageable_bodyparts() - if(!parts.len) - return - var/obj/item/bodypart/picked = pick(parts) - if(picked.take_damage(brute,burn)) - update_damage_overlays(0) - updatehealth() - - -//Heal MANY bodyparts, in random order -/mob/living/carbon/human/heal_overall_damage(brute, burn, updating_health=1) - var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn) - - var/update = 0 - while(parts.len && (brute>0 || burn>0) ) - var/obj/item/bodypart/picked = pick(parts) - - var/brute_was = picked.brute_dam - var/burn_was = picked.burn_dam - - update |= picked.heal_damage(brute,burn,0) - - brute -= (brute_was-picked.brute_dam) - burn -= (burn_was-picked.burn_dam) - - parts -= picked - if(updating_health) - updatehealth() - if(update) - update_damage_overlays(0) - -// damage MANY bodyparts, in random order -/mob/living/carbon/human/take_overall_damage(brute, burn) - if(status_flags & GODMODE) - return //godmode - - var/list/obj/item/bodypart/parts = get_damageable_bodyparts() - var/update = 0 - while(parts.len && (brute>0 || burn>0) ) - var/obj/item/bodypart/picked = pick(parts) - var/brute_per_part = brute/parts.len - var/burn_per_part = burn/parts.len - - var/brute_was = picked.brute_dam - var/burn_was = picked.burn_dam - - - update |= picked.take_damage(brute_per_part,burn_per_part) - - brute -= (picked.brute_dam - brute_was) - burn -= (picked.burn_dam - burn_was) - - parts -= picked - updatehealth() - if(update) - update_damage_overlays(0) - -//////////////////////////////////////////// - - -/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) - // depending on the species, it will run the corresponding apply_damage code there - return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index edf30eb4b84..535f7f39ffb 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -31,10 +31,36 @@ protection += C.armor[type] return protection +///checkeyeprot() +///Returns a number between -1 to 2 +/mob/living/carbon/human/get_eye_protection() + var/number = ..() + if(istype(src.head, /obj/item/clothing/head)) //are they wearing something on their head + var/obj/item/clothing/head/HFP = src.head //if yes gets the flash protection value from that item + number += HFP.flash_protect + if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses + var/obj/item/clothing/glasses/GFP = src.glasses + number += GFP.flash_protect + if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask + var/obj/item/clothing/mask/MFP = src.wear_mask + number += MFP.flash_protect + return number + +/mob/living/carbon/human/get_ear_protection() + if((ears && (ears.flags & EARBANGPROTECT)) || (head && (head.flags & HEADBANGPROTECT))) + return 1 + /mob/living/carbon/human/on_hit(proj_type) dna.species.on_hit(proj_type, src) + /mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone) + if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles! + if(prob(martial_art.deflection_chance)) + if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it + visible_message("[src] deflects the projectile; they can't be hit with ranged weapons!", "You deflect the projectile!") + playsound(src, pick("sound/weapons/bulletflyby.ogg","sound/weapons/bulletflyby2.ogg","sound/weapons/bulletflyby3.ogg"), 75, 1) + return 0 if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) if(check_reflect(def_zone)) // Checks if you've passed a reflection% check @@ -63,34 +89,23 @@ return (..(P , def_zone)) -/mob/living/check_projectile_dismemberment(obj/item/projectile/P, def_zone) - var/obj/item/bodypart/affecting = get_bodypart(def_zone) - if(affecting && affecting.get_damage() >= (affecting.max_damage - P.dismemberment)) - affecting.dismember(P.damtype) - /mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object if(wear_suit) if(wear_suit.IsReflect(def_zone) == 1) return 1 - if(l_hand) - if(l_hand.IsReflect(def_zone) == 1) - return 1 - if(r_hand) - if(r_hand.IsReflect(def_zone) == 1) + for(var/obj/item/I in held_items) + if(I.IsReflect(def_zone) == 1) return 1 return 0 /mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, attack_type = MELEE_ATTACK, armour_penetration = 0) var/block_chance_modifier = round(damage / -3) - if(l_hand && !istype(l_hand, /obj/item/clothing)) - var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example - if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type)) - return 1 - if(r_hand && !istype(r_hand, /obj/item/clothing)) - var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts - if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type)) - return 1 + for(var/obj/item/I in held_items) + if(!istype(I, /obj/item/clothing)) + var/final_block_chance = I.block_chance - (Clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example + if(I.hit_reaction(src, attack_text, final_block_chance, damage, attack_type)) + return 1 if(wear_suit) var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type)) @@ -102,22 +117,309 @@ return 0 +/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) + var/obj/item/I + var/throwpower = 30 + if(istype(AM, /obj/item)) + I = AM + throwpower = I.throwforce + if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions + return ..() + if(check_shields(throwpower, "\the [AM.name]", AM, THROWN_PROJECTILE_ATTACK)) + hitpush = 0 + skipcatch = 1 + blocked = 1 + else if(I) + if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD) + if(can_embed(I)) + if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags))) + throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) + var/obj/item/bodypart/L = pick(bodyparts) + L.embedded_objects |= I + I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! + I.loc = src + L.take_damage(I.w_class*I.embedded_impact_pain_multiplier) + visible_message("\the [I.name] embeds itself in [src]'s [L.name]!","\the [I.name] embeds itself in your [L.name]!") + hitpush = 0 + skipcatch = 1 //can't catch the now embedded item + + return ..() + +/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) + if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling)) + devour_mob(pulling) + else + ..() + +/mob/living/carbon/human/grippedby(mob/living/user) + if(w_uniform) + w_uniform.add_fingerprint(user) + ..() + + /mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user) if(!I || !user) return 0 - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected)) - var/target_area = parse_zone(check_zone(user.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected)) //what we're actually ending up trying to hit. + var/target_area = parse_zone(check_zone(user.zone_selected)) //our intended target feedback_add_details("item_used_for_combat","[I.type]|[I.force]") feedback_add_details("zone_targeted","[target_area]") // the attacked_by code varies among species - return dna.species.spec_attacked_by(I, user, affecting, a_intent, target_area, src) + return dna.species.spec_attacked_by(I, user, affecting, a_intent, src) + + +/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user) + if(user.a_intent == "harm") + ..(user, 1) + playsound(loc, user.dna.species.attack_sound, 25, 1, -1) + var/hulk_verb = pick("smash","pummel") + visible_message("[user] has [hulk_verb]ed [src]!", \ + "[user] has [hulk_verb]ed [src]!") + adjustBruteLoss(15) + return 1 + +/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M) + if(..()) //to allow surgery to return properly. + return + dna.species.spec_attack_hand(M, src) + + +/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M) + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + + if(M.a_intent == "help") + ..() //shaking + return 0 + + if(M.limb_destroyer) + dismembering_strike(M, affecting.body_zone) + + if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites. + if(..()) //successful monkey bite, this handles disease contraction. + var/damage = rand(1, 3) + if(stat != DEAD) + apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) + return 1 + +/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M) + if(check_shields(0, M.name)) + visible_message("[M] attempted to touch [src]!") + return 0 + + if(..()) + if(M.a_intent == "harm") + if (w_uniform) + w_uniform.add_fingerprint(M) + var/damage = prob(90) ? 20 : 0 + if(!damage) + playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) + visible_message("[M] has lunged at [src]!", \ + "[M] has lunged at [src]!") + return 0 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/armor_block = run_armor_check(affecting, "melee","","",10) + + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!") + add_logs(M, src, "attacked") + if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful + return 1 + apply_damage(damage, BRUTE, affecting, armor_block) + + if(M.a_intent == "disarm") //Always drop item in hand, if no item, get stunned instead. + if(get_active_held_item() && drop_item()) + playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) + visible_message("[M] disarmed [src]!", \ + "[M] disarmed [src]!") + else + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + Weaken(5) + add_logs(M, src, "tackled") + visible_message("[M] has tackled down [src]!", \ + "[M] has tackled down [src]!") + + +/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) + + if(..()) //successful larva bite. + var/damage = rand(1, 3) + if(check_shields(damage, "the [L.name]")) + return 0 + if(stat != DEAD) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + var/armor_block = run_armor_check(affecting, "melee") + apply_damage(damage, BRUTE, affecting, armor_block) + + +/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) + if(..()) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration)) + return 0 + var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration) + apply_damage(damage, M.melee_damage_type, affecting, armor) + + + +/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) + if(..()) //successful slime attack + var/damage = rand(5, 25) + if(M.is_adult) + damage = rand(10, 35) + + if(check_shields(damage, "the [M.name]")) + return 0 + + var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 + + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + var/armor_block = run_armor_check(affecting, "melee") + apply_damage(damage, BRUTE, affecting, armor_block) + +/mob/living/carbon/human/mech_melee_attack(obj/mecha/M) + + if(M.occupant.a_intent == "harm") + M.do_attack_animation(src) + if(M.damtype == "brute") + step_away(src,M,15) + var/obj/item/bodypart/temp = get_bodypart(pick("chest", "chest", "chest", "head")) + if(temp) + var/update = 0 + switch(M.damtype) + if("brute") + if(M.force > 20) + Paralyse(1) + update |= temp.take_damage(rand(M.force/2, M.force), 0) + playsound(src, 'sound/weapons/punch4.ogg', 50, 1) + if("fire") + update |= temp.take_damage(0, rand(M.force/2, M.force)) + playsound(src, 'sound/items/Welder.ogg', 50, 1) + if("tox") + M.mech_toxin_damage(src) + else + return + if(update) + update_damage_overlays() + updatehealth() + + visible_message("[M.name] has hit [src]!", \ + "[M.name] has hit [src]!") + add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") + + else + ..() + + +/mob/living/carbon/human/ex_act(severity, ex_target) + var/b_loss = null + var/f_loss = null + var/bomb_armor = getarmor(null, "bomb") + if(istype(ex_target, /datum/spacevine_mutation) && isvineimmune(src)) + return + + switch (severity) + if (1) + b_loss += 500 + if (prob(bomb_armor)) + shred_clothing(1,150) + var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src))) + throw_at(target, 200, 4) + else + gib() + return + + if (2) + b_loss += 60 + + f_loss += 60 + if (prob(bomb_armor)) + b_loss = b_loss/1.5 + f_loss = f_loss/1.5 + shred_clothing(1,25) + else + shred_clothing(1,50) + + if (!istype(ears, /obj/item/clothing/ears/earmuffs)) + adjustEarDamage(30, 120) + if (prob(70)) + Paralyse(10) + + if(3) + b_loss += 30 + if (prob(bomb_armor)) + b_loss = b_loss/2 + if (!istype(ears, /obj/item/clothing/ears/earmuffs)) + adjustEarDamage(15,60) + if (prob(50)) + Paralyse(8) + + take_overall_damage(b_loss,f_loss) + //attempt to dismember bodyparts + if(severity <= 2 || !bomb_armor) + var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3. + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(prob(50/severity) && !prob(getarmor(BP, "bomb")) && BP.body_zone != "head" && BP.body_zone != "chest") + BP.brute_dam = BP.max_damage + BP.dismember() + max_limb_loss-- + if(!max_limb_loss) + break + ..() + +/mob/living/carbon/human/blob_act(obj/effect/blob/B) + if(stat == DEAD) + return + show_message("The blob attacks you!") + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee")) + + +//Added a safety check in case you want to shock a human mob directly through electrocute_act. +/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0) + if(tesla_shock) + var/total_coeff = 1 + if(gloves) + var/obj/item/clothing/gloves/G = gloves + if(G.siemens_coefficient <= 0) + total_coeff -= 0.5 + if(wear_suit) + var/obj/item/clothing/suit/S = wear_suit + if(S.siemens_coefficient <= 0) + total_coeff -= 0.95 + siemens_coeff = total_coeff + else if(!safety) + var/gloves_siemens_coeff = 1 + if(gloves) + var/obj/item/clothing/gloves/G = gloves + gloves_siemens_coeff = G.siemens_coefficient + siemens_coeff = gloves_siemens_coeff + if(heart_attack) + if(shock_damage * siemens_coeff >= 1 && prob(25)) + heart_attack = 0 + if(stat == CONSCIOUS) + src << "You feel your heart beating again!" + . = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock) + if(.) + electrocution_animation(40) + /mob/living/carbon/human/emp_act(severity) var/informed = 0 for(var/obj/item/bodypart/L in src.bodyparts) - if(L.status == ORGAN_ROBOTIC) + if(L.status == BODYPART_ROBOTIC) if(!informed) src << "You feel a sharp pain as your robotic limbs overload." informed = 1 @@ -262,133 +564,84 @@ inventory_items_to_kill += back if(belt) inventory_items_to_kill += belt - if(r_hand) - inventory_items_to_kill += r_hand - if(l_hand) - inventory_items_to_kill += l_hand + + inventory_items_to_kill += held_items for(var/obj/item/I in inventory_items_to_kill) I.acid_act(acidpwr, acid_volume_left) acid_volume_left = max(acid_volume_left - acid_decay, 0) -/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) - if(..()) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration)) - return 0 - var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")) - if(!dam_zone) //Dismemberment successful - return 1 - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration) - apply_damage(damage, M.melee_damage_type, affecting, armor) - updatehealth() +/mob/living/carbon/human/singularity_act() + var/gain = 20 + if(mind) + if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") ) + gain = 100 + if(mind.assigned_role == "Clown") + gain = rand(-300, 300) + investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! + gib() + return(gain) +/mob/living/carbon/human/help_shake_act(mob/living/carbon/M) + if(!istype(M)) + return -/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) + if(health >= 0) + if(src == M) + visible_message( \ + "[src] examines \himself.", \ + "You check yourself for injuries.") - if(..()) //successful larva bite. - var/damage = rand(1, 3) - if(check_shields(damage, "the [L.name]")) - return 0 - if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) - var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) - updatehealth() + var/list/missing = list("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg") + for(var/X in bodyparts) + var/obj/item/bodypart/LB = X + missing -= LB.body_zone + var/status = "" + var/brutedamage = LB.brute_dam + var/burndamage = LB.burn_dam + if(hallucination) + if(prob(30)) + brutedamage += rand(30,40) + if(prob(30)) + burndamage += rand(30,40) + if(brutedamage > 0) + status = "bruised" + if(brutedamage > 20) + status = "battered" + if(brutedamage > 40) + status = "mangled" + if(brutedamage > 0 && burndamage > 0) + status += " and " + if(burndamage > 40) + status += "peeling away" -/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(5, 25) - if(M.is_adult) - damage = rand(10, 35) + else if(burndamage > 10) + status += "blistered" + else if(burndamage > 0) + status += "numb" + if(status == "") + status = "OK" + src << "\t [status == "OK" ? "\blue" : "\red"] Your [LB.name] is [status]." - if(check_shields(damage, "the [M.name]")) - return 0 + for(var/obj/item/I in LB.embedded_objects) + src << "\t \red There is \a [I] embedded in your [LB.name]!" - var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")) - if(!dam_zone) //Dismemberment successful - return 1 + for(var/t in missing) + src << "Your [parse_zone(t)] is missing!" - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) - var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) - -/mob/living/carbon/human/mech_melee_attack(obj/mecha/M) - - if(M.occupant.a_intent == "harm") - M.do_attack_animation(src) - if(M.damtype == "brute") - step_away(src,M,15) - var/obj/item/bodypart/temp = get_bodypart(pick("chest", "chest", "chest", "head")) - if(temp) - var/update = 0 - switch(M.damtype) - if("brute") - if(M.force > 20) - Paralyse(1) - update |= temp.take_damage(rand(M.force/2, M.force), 0) - playsound(src, 'sound/weapons/punch4.ogg', 50, 1) - if("fire") - update |= temp.take_damage(0, rand(M.force/2, M.force)) - playsound(src, 'sound/items/Welder.ogg', 50, 1) - if("tox") - M.mech_toxin_damage(src) + if(bleed_rate) + src << "You are bleeding!" + if(staminaloss) + if(staminaloss > 30) + src << "You're completely exhausted." else - return - if(update) - update_damage_overlays(0) - updatehealth() + src << "You feel fatigued." + else + if(wear_suit) + wear_suit.add_fingerprint(M) + else if(w_uniform) + w_uniform.add_fingerprint(M) - visible_message("[M.name] has hit [src]!", \ - "[M.name] has hit [src]!") - add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") - - else - ..() - -/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) - var/obj/item/I - var/throwpower = 30 - if(istype(AM, /obj/item)) - I = AM - throwpower = I.throwforce - if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions - return ..() - if(check_shields(throwpower, "\the [AM.name]", AM, THROWN_PROJECTILE_ATTACK)) - hitpush = 0 - skipcatch = 1 - blocked = 1 - else if(I) - if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD) - if(can_embed(I)) - if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags))) - throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) - var/obj/item/bodypart/L = pick(bodyparts) - L.embedded_objects |= I - I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! - I.loc = src - L.take_damage(I.w_class*I.embedded_impact_pain_multiplier) - visible_message("\the [I.name] embeds itself in [src]'s [L.name]!","\the [I.name] embeds itself in your [L.name]!") - hitpush = 0 - skipcatch = 1 //can't catch the now embedded item - - return ..() - -/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) - if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling)) - devour_mob(pulling) - else - ..() - -/mob/living/carbon/human/grippedby(mob/living/user) - if(w_uniform) - w_uniform.add_fingerprint(user) - ..() - -/mob/living/carbon/human/Stun(amount, updating_canmove = 1) - amount = dna.species.spec_stun(src,amount) - ..() \ No newline at end of file + ..() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index ada7a5cceaf..abf9dffc00c 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -30,11 +30,7 @@ var/global/default_martial_art = new/datum/martial_art //Equipment slots var/obj/item/wear_suit = null var/obj/item/w_uniform = null - var/obj/item/shoes = null var/obj/item/belt = null - var/obj/item/gloves = null - var/obj/item/clothing/glasses/glasses = null - var/obj/item/ears = null var/obj/item/wear_id = null var/obj/item/r_store = null var/obj/item/l_store = null diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 4b25bca1238..98426060462 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -81,33 +81,17 @@ if(wear_id) return wear_id.GetID() -///checkeyeprot() -///Returns a number between -1 to 2 -/mob/living/carbon/human/check_eye_prot() - var/number = ..() - if(istype(src.head, /obj/item/clothing/head)) //are they wearing something on their head - var/obj/item/clothing/head/HFP = src.head //if yes gets the flash protection value from that item - number += HFP.flash_protect - if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses - var/obj/item/clothing/glasses/GFP = src.glasses - number += GFP.flash_protect - if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask - var/obj/item/clothing/mask/MFP = src.wear_mask - number += MFP.flash_protect - return number - -/mob/living/carbon/human/check_ear_prot() - if((ears && (ears.flags & EARBANGPROTECT)) || (head && (head.flags & HEADBANGPROTECT))) - return 1 /mob/living/carbon/human/abiotic(full_body = 0) - if(full_body && ((l_hand && !( src.l_hand.flags&NODROP )) || (r_hand && !( src.r_hand.flags&NODROP )) || (back && !(back.flags&NODROP)) || (wear_mask && !(wear_mask.flags&NODROP)) || (head && !(head.flags&NODROP)) || (shoes && !(shoes.flags&NODROP)) || (w_uniform && !(w_uniform.flags&NODROP)) || (wear_suit && !(wear_suit.flags&NODROP)) || (glasses && !(glasses.flags&NODROP)) || (ears && !(ears.flags&NODROP)) || (gloves && !(gloves.flags&NODROP)) ) ) - return 1 + var/abiotic_hands = FALSE + for(var/obj/item/I in held_items) + if(!(I.flags & NODROP)) + abiotic_hands = TRUE + break + if(full_body && abiotic_hands && ((back && !(back.flags&NODROP)) || (wear_mask && !(wear_mask.flags&NODROP)) || (head && !(head.flags&NODROP)) || (shoes && !(shoes.flags&NODROP)) || (w_uniform && !(w_uniform.flags&NODROP)) || (wear_suit && !(wear_suit.flags&NODROP)) || (glasses && !(glasses.flags&NODROP)) || (ears && !(ears.flags&NODROP)) || (gloves && !(gloves.flags&NODROP)) ) ) + return TRUE + return abiotic_hands - if( (src.l_hand && !(src.l_hand.flags&NODROP)) || (src.r_hand && !(src.r_hand.flags&NODROP)) ) - return 1 - - return 0 /mob/living/carbon/human/IsAdvancedToolUser() return 1//Humans can use guns and such diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 7fbb7e01a83..3283e04d22e 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -22,10 +22,6 @@ return handcuffed if(slot_legcuffed) return legcuffed - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand if(slot_belt) return belt if(slot_wear_id) @@ -113,7 +109,7 @@ //Item is handled and in slot, valid to call callback, for this proc should always be true if(!not_handled) I.equipped(src, slot) - + return not_handled //For future deeper overrides /mob/living/carbon/human/unEquip(obj/item/I) @@ -204,7 +200,16 @@ //Cycles through all clothing slots and tests them for destruction -/mob/living/carbon/human/proc/shred_clothing(bomb,shock) +/mob/living/carbon/proc/shred_clothing(bomb,shock) + if(back) + back.shred(bomb,shock-20,src) + if(head) + head.shred(bomb,shock,src) + if(wear_mask) + wear_mask.shred(bomb,shock,src) + + +/mob/living/carbon/human/shred_clothing(bomb,shock) var/covered_parts = 0 //The body parts that are protected by exterior clothing/armor var/head_absorbed = 0 //How much of the shock the headgear absorbs when it is shredded. -1=it survives var/suit_absorbed = 0 //How much of the shock the exosuit absorbs when it is shredded. -1=it survives diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 9b63a8232b6..852a19fd1ab 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -54,7 +54,7 @@ var/punchdamagehigh = 9 //highest possible punch damage var/punchstunthreshold = 9//damage at which punches from this race will stun //yes it should be to the attacked race but it's not useful that way even if it's logical var/siemens_coeff = 1 //base electrocution coefficient - var/exotic_damage_overlay = "" + var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded? var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"] var/invis_sight = SEE_INVISIBLE_LIVING @@ -132,8 +132,6 @@ var/obj/item/thing = C.get_item_by_slot(slot_id) if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception))) C.unEquip(thing) - if(NODISMEMBER in specflags) - C.regenerate_limbs() //if we don't handle dismemberment, we grow our missing limbs back var/obj/item/organ/heart/heart = C.getorganslot("heart") var/obj/item/organ/lungs/lungs = C.getorganslot("lungs") @@ -226,7 +224,8 @@ hair_hidden = 1 if(!hair_hidden) if(!H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain - standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) + if(!(NOBLOOD in specflags)) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) else if(H.hair_style && (HAIR in specflags)) S = hair_styles_list[H.hair_style] @@ -263,17 +262,18 @@ var/obj/item/bodypart/head/HD = H.get_bodypart("head") - // lipstick - if(H.lip_style && (LIPS in specflags) && HD) - var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]_s", "layer" = -BODY_LAYER) - lips.color = H.lip_color - standing += lips + if(!(H.disabilities & HUSK)) + // lipstick + if(H.lip_style && (LIPS in specflags) && HD) + var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]_s", "layer" = -BODY_LAYER) + lips.color = H.lip_color + standing += lips - // eyes - if((EYECOLOR in specflags) && HD) - var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[eyes]_s", "layer" = -BODY_LAYER) - img_eyes_s.color = "#" + H.eye_color - standing += img_eyes_s + // eyes + if((EYECOLOR in specflags) && HD) + var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[eyes]_s", "layer" = -BODY_LAYER) + img_eyes_s.color = "#" + H.eye_color + standing += img_eyes_s //Underwear, Undershirts & Socks if(H.underwear) @@ -346,19 +346,19 @@ bodyparts_to_add -= "waggingspines" if("snout" in mutant_bodyparts) //Take a closer look at that snout! - if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)) || !HD || HD.status == ORGAN_ROBOTIC) + if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "snout" if("frills" in mutant_bodyparts) - if(!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == ORGAN_ROBOTIC) + if(!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "frills" if("horns" in mutant_bodyparts) - if(!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == ORGAN_ROBOTIC) + if(!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "horns" if("ears" in mutant_bodyparts) - if(!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == ORGAN_ROBOTIC) + if(!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) bodyparts_to_add -= "ears" if("wings" in mutant_bodyparts) @@ -380,6 +380,8 @@ var/image/I for(var/layer in relevent_layers) + var/layertext = mutant_bodyparts_layertext(layer) + for(var/bodypart in bodyparts_to_add) var/datum/sprite_accessory/S switch(bodypart) @@ -423,9 +425,9 @@ var/icon_string if(S.gender_specific) - icon_string = "[g]_[bodypart]_[S.icon_state]_[layer]" + icon_string = "[g]_[bodypart]_[S.icon_state]_[layertext]" else - icon_string = "m_[bodypart]_[S.icon_state]_[layer]" + icon_string = "m_[bodypart]_[S.icon_state]_[layertext]" I = image("icon" = S.icon, "icon_state" = icon_string, "layer" =- layer) @@ -455,9 +457,9 @@ if(S.hasinner) if(S.gender_specific) - icon_string = "[g]_[bodypart]inner_[S.icon_state]_[layer]" + icon_string = "[g]_[bodypart]inner_[S.icon_state]_[layertext]" else - icon_string = "m_[bodypart]inner_[S.icon_state]_[layer]" + icon_string = "m_[bodypart]inner_[S.icon_state]_[layertext]" I = image("icon" = S.icon, "icon_state" = icon_string, "layer" =- layer) @@ -473,6 +475,19 @@ H.apply_overlay(BODY_ADJ_LAYER) H.apply_overlay(BODY_FRONT_LAYER) + +//This exists so sprite accessories can still be per-layer without having to include that layer's +//number in their sprite name, which causes issues when those numbers change. +/datum/species/proc/mutant_bodyparts_layertext(layer) + switch(layer) + if(BODY_BEHIND_LAYER) + return "BEHIND" + if(BODY_ADJ_LAYER) + return "ADJ" + if(BODY_FRONT_LAYER) + return "FRONT" + + /datum/species/proc/spec_life(mob/living/carbon/human/H) if(NOBREATH in specflags) H.setOxyLoss(0) @@ -494,24 +509,14 @@ if(!I.species_exception || !is_type_in_list(src, I.species_exception)) return 0 - var/R = H.has_right_hand() - var/L = H.has_left_hand() var/num_arms = H.get_num_arms() var/num_legs = H.get_num_legs() switch(slot) - if(slot_l_hand) - if(H.l_hand) - return 0 - if(!L) - return 0 - return 1 - if(slot_r_hand) - if(H.r_hand) - return 0 - if(!R) - return 0 - return 1 + if(slot_hands) + if(H.get_empty_held_indexes()) + return TRUE + return FALSE if(slot_wear_mask) if(H.wear_mask) return 0 @@ -825,7 +830,7 @@ if(75 to 100) if(prob(1)) H << "You mutate!" - randmutb(H) + H.randmutb() H.emote("gasp") H.domutcheck() return 0 @@ -881,23 +886,14 @@ . += H.shoes.slowdown if(H.back) . += H.back.slowdown - if(H.l_hand && (H.l_hand.flags & HANDSLOW)) - . += H.l_hand.slowdown - if(H.r_hand && (H.r_hand.flags & HANDSLOW)) - . += H.r_hand.slowdown - + for(var/obj/item/I in H.held_items) + if(I.flags & HANDSLOW) + . += I.slowdown if((H.disabilities & FAT)) . += 1.5 if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) . += (BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR - if(!(FLYING in specflags)) - var/leg_amount = H.get_num_legs() - . += 6 - 3*leg_amount //the fewer the legs, the slower the mob - if(!leg_amount) - . += 6 - 3*H.get_num_arms() //crawling is harder with fewer arms - - . += speedmod ////////////////// @@ -1024,10 +1020,9 @@ "[M] attemped to disarm [H]!") return -/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, target_area, mob/living/carbon/human/H) +/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) // Allows you to put in item-specific reactions based on species if(user != H) - user.do_attack_animation(H) if(H.check_shields(I.force, "the [I.name]", I, MELEE_ATTACK, I.armour_penetration)) return 0 @@ -1059,7 +1054,7 @@ var/bloody = 0 if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) - if(affecting.status == ORGAN_ORGANIC) + if(affecting.status == BODYPART_ORGANIC) I.add_mob_blood(H) //Make the weapon bloody, not the person. if(prob(I.force * 2)) //blood spatter! bloody = 1 @@ -1109,39 +1104,43 @@ return TRUE /datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H) - blocked = (100-(blocked+armor))/100 - if(!damage || blocked <= 0) + var/hit_percent = (100-(blocked+armor))/100 + if(!damage || hit_percent <= 0) return 0 - var/obj/item/bodypart/organ = null + var/obj/item/bodypart/BP = null if(islimb(def_zone)) - organ = def_zone + BP = def_zone else if(!def_zone) def_zone = ran_zone(def_zone) - organ = H.get_bodypart(check_zone(def_zone)) - if(!organ) - return 0 - - damage = (damage * blocked) + BP = H.get_bodypart(check_zone(def_zone)) + if(!BP) + BP = H.bodyparts[1] switch(damagetype) if(BRUTE) H.damageoverlaytemp = 20 - if(organ.take_damage(damage*brutemod, 0)) - H.update_damage_overlays(0) + if(BP) + if(BP.take_damage(damage * hit_percent * brutemod, 0)) + H.update_damage_overlays() + else//no bodypart, we deal damage with a more general method. + H.adjustBruteLoss(damage * hit_percent * brutemod) if(BURN) H.damageoverlaytemp = 20 - if(organ.take_damage(0, damage*burnmod)) - H.update_damage_overlays(0) + if(BP) + if(BP.take_damage(0, damage * hit_percent * burnmod)) + H.update_damage_overlays() + else + H.adjustFireLoss(damage * hit_percent* burnmod) if(TOX) - H.adjustToxLoss(damage) + H.adjustToxLoss(damage * hit_percent) if(OXY) - H.adjustOxyLoss(damage) + H.adjustOxyLoss(damage * hit_percent) if(CLONE) - H.adjustCloneLoss(damage) + H.adjustCloneLoss(damage * hit_percent) if(STAMINA) - H.adjustStaminaLoss(damage) + H.adjustStaminaLoss(damage * hit_percent) return 1 /datum/species/proc/on_hit(obj/item/projectile/proj_type, mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm index 6f7beec0e7d..c3e0bc205e1 100644 --- a/code/modules/mob/living/carbon/human/species_types.dm +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -146,9 +146,9 @@ H.Weaken(5) H.visible_message("[H] writhes in pain as \his vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") if(prob(80)) - randmutb(H) + H.randmutb() else - randmutg(H) + H.randmutg() H.domutcheck() else H.adjustFireLoss(rand(5,15)) @@ -642,6 +642,7 @@ meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton specflags = list(NOBREATH,RESISTTEMP,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYDISMEMBER,EASYLIMBATTACHMENT) mutant_organs = list(/obj/item/organ/tongue/bone) + damage_overlay_type = ""//let's not show bloody wounds or burns over bones. /* ZOMBIES @@ -676,10 +677,9 @@ . = ..() // Drop items in hands // If you're a zombie lucky enough to have a NODROP item, then it stays. - if(C.unEquip(C.l_hand)) - C.put_in_l_hand(new /obj/item/zombie_hand(C)) - if(C.unEquip(C.r_hand)) - C.put_in_r_hand(new /obj/item/zombie_hand(C)) + for(var/obj/item/I in C.held_items) + C.unEquip(I) + C.put_in_hands(new /obj/item/zombie_hand(C)) // Next, deal with the source of this zombie corruption var/obj/item/organ/body_egg/zombie_infection/infection @@ -689,13 +689,10 @@ /datum/species/zombie/infectious/on_species_loss(mob/living/carbon/C) . = ..() - var/obj/item/zombie_hand/left = C.l_hand - var/obj/item/zombie_hand/right = C.r_hand - // Deletion of the hands is handled in the items dropped() - if(istype(left)) - C.unEquip(left, TRUE) - if(istype(right)) - C.unEquip(right, TRUE) + for(var/obj/item/I in C.held_items) + if(istype(I, /obj/item/zombie_hand)) + C.unEquip(I, TRUE) + // Your skin falls off /datum/species/krokodil_addict @@ -734,6 +731,7 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_ burnmod = 2 heatmod = 2 speedmod = 1 + damage_overlay_type = ""//let's not show bloody wounds or burns over bones. /datum/species/plasmaman/spec_life(mob/living/carbon/human/H) var/datum/gas_mixture/environment = H.loc.return_air() @@ -757,7 +755,7 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_ /datum/species/plasmaman/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE) var/datum/outfit/plasmaman/O = new /datum/outfit/plasmaman H.equipOutfit(O, visualsOnly) - H.internal = H.r_hand + H.internal = H.get_item_for_held_index(2) H.update_internals_hud_icon(1) return 0 @@ -785,7 +783,7 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_ dangerous_existence = 1 blacklisted = 1 meat = null - exotic_damage_overlay = "synth" + damage_overlay_type = "synth" limbs_id = "synth" var/list/initial_specflags = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //for getting these values back for assume_disguise() var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off @@ -1016,8 +1014,8 @@ SYNDICATE BLACK OPS playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3) - H.accident(H.l_hand) - H.accident(H.r_hand) + for(var/obj/item/I in H.held_items) + H.accident(I) var/olddir = H.dir diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm new file mode 100644 index 00000000000..adcf57433c4 --- /dev/null +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -0,0 +1,15 @@ + +/mob/living/carbon/human/Stun(amount, updating = 1, ignore_canstun = 0) + amount = dna.species.spec_stun(src,amount) + ..() + + +/mob/living/carbon/human/cure_husk() + . = ..() + if(.) + update_hair() + +/mob/living/carbon/human/become_husk() + . = ..() + if(.) + update_hair() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 98e5d5d82b6..4bbde09513d 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -48,28 +48,6 @@ There are several things that need to be remembered: */ -//DAMAGE OVERLAYS -//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists -/mob/living/carbon/human/update_damage_overlays() - remove_overlay(DAMAGE_LAYER) - - var/image/standing = image("icon"='icons/mob/dam_human.dmi', "icon_state"="blank", "layer"=-DAMAGE_LAYER) - overlays_standing[DAMAGE_LAYER] = standing - - var/dmgoverlaytype = "" - if(dna.species.exotic_damage_overlay) - dmgoverlaytype = dna.species.exotic_damage_overlay + "_" - - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if(BP.brutestate) - standing.overlays += "[dmgoverlaytype][BP.body_zone]_[BP.brutestate]0" //we're adding icon_states of the base image as overlays - if(BP.burnstate) - standing.overlays += "[dmgoverlaytype][BP.body_zone]_0[BP.burnstate]" - - apply_overlay(DAMAGE_LAYER) - - //HAIR OVERLAY /mob/living/carbon/human/update_hair() dna.species.handle_hair(src) @@ -79,47 +57,14 @@ There are several things that need to be remembered: dna.species.handle_mutant_bodyparts(src) -/mob/living/carbon/human/proc/update_body() +/mob/living/carbon/human/update_body() remove_overlay(BODY_LAYER) dna.species.handle_body(src) - update_body_parts() + ..() /mob/living/carbon/human/update_fire() ..("Standing") -/mob/living/carbon/human/proc/update_body_parts() - //CHECK FOR UPDATE - var/oldkey = icon_render_key - icon_render_key = generate_icon_render_key() - if(oldkey == icon_render_key) - return - - remove_overlay(BODYPARTS_LAYER) - - //LOAD ICONS - if(limb_icon_cache[icon_render_key]) - load_limb_from_cache() - update_damage_overlays() - update_mutant_bodyparts() - update_hair() - return - - //GENERATE NEW LIMBS - var/list/new_limbs = list() - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if(!BP.no_update) - BP.update_limb() - var/image/temp = BP.get_limb_icon() - if(temp) - new_limbs += temp - if(new_limbs.len) - overlays_standing[BODYPARTS_LAYER] = new_limbs - limb_icon_cache[icon_render_key] = new_limbs - - apply_overlay(BODYPARTS_LAYER) - update_damage_overlays() - /* --------------------------------------- */ //For legacy support. @@ -219,9 +164,16 @@ There are several things that need to be remembered: remove_overlay(GLOVES_LAYER) if(get_num_arms() <2) + if(!gloves && blood_DNA) + if(has_left_hand()) + overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands_left", "layer"=-GLOVES_LAYER) + apply_overlay(GLOVES_LAYER) + else if(has_right_hand()) + overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands_right", "layer"=-GLOVES_LAYER) + apply_overlay(GLOVES_LAYER) return - if(client && hud_used) + if(client && hud_used && hud_used.inv_slots[slot_gloves]) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves] inv.update_icon() @@ -246,7 +198,6 @@ There are several things that need to be remembered: apply_overlay(GLOVES_LAYER) - /mob/living/carbon/human/update_inv_glasses() remove_overlay(GLASSES_LAYER) @@ -336,19 +287,10 @@ There are several things that need to be remembered: apply_overlay(SUIT_STORE_LAYER) - /mob/living/carbon/human/update_inv_head() - remove_overlay(HEAD_LAYER) - if(!get_bodypart("head")) //Decapitated - return ..() - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head] - inv.update_icon() - update_mutant_bodyparts() - /mob/living/carbon/human/update_inv_belt() remove_overlay(BELT_LAYER) @@ -382,18 +324,17 @@ There are several things that need to be remembered: inv.update_icon() if(istype(wear_suit, /obj/item/clothing/suit)) - wear_suit.screen_loc = ui_oclothing //TODO //Todo what? + wear_suit.screen_loc = ui_oclothing if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - client.screen += wear_suit //Either way, add the item to the HUD + if(hud_used.inventory_shown) + client.screen += wear_suit update_observer_view(wear_suit,1) var/image/standing = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/suit.dmi') overlays_standing[SUIT_LAYER] = standing - if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - drop_l_hand() - drop_r_hand() + if(wear_suit.breakouttime) //suit is restraining + drop_all_held_items() update_hair() update_mutant_bodyparts() @@ -424,22 +365,10 @@ There are several things that need to be remembered: update_observer_view(r_store) - /mob/living/carbon/human/update_inv_wear_mask() - remove_overlay(FACEMASK_LAYER) - if(!get_bodypart("head")) //Decapitated - return ..() - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask] - inv.update_icon() - update_mutant_bodyparts() + update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout -/mob/living/carbon/human/update_inv_handcuffed() - remove_overlay(HANDCUFF_LAYER) - if(handcuffed) - overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER) - apply_overlay(HANDCUFF_LAYER) /mob/living/carbon/human/update_inv_legcuffed() remove_overlay(LEGCUFF_LAYER) @@ -459,7 +388,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers) var/list/out = new - for(var/i=1;i<=TOTAL_LAYERS;i++) + for(var/i in 1 to TOTAL_LAYERS) if(overlays_standing[i]) if(i in unwantedLayers) continue @@ -493,6 +422,8 @@ There are several things that need to be remembered: update_observer_view(I) + + /* Does everything in relation to building the /image used in the mob's overlays list covers: @@ -548,41 +479,42 @@ generate/load female uniform sprites matching all previously decided variables standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension) + //Handle held offsets + var/mob/M = loc + if(istype(M)) + var/list/L = get_held_offsets() + if(L) + standing.pixel_x += L["x"] //+= because of center()ing + standing.pixel_y += L["y"] + standing.alpha = alpha standing.color = color return standing +/obj/item/proc/get_held_offsets() + var/list/L + if(ismob(loc)) + var/mob/M = loc + L = M.get_item_offsets_for_index(M.get_held_index_of_item(src)) + return L +//Can't think of a better way to do this, sadly +/mob/proc/get_item_offsets_for_index(i) + switch(i) + if(3) //odd = left hands + return list("x" = 0, "y" = 16) + if(4) //even = right hands + return list("x" = 0, "y" = 16) + else //No offsets or Unwritten number of hands + return list("x" = 0, "y" = 0) - - -///////////////////// -// Limb Icon Cache // -///////////////////// -/* - Called from update_body_parts() these procs handle the limb icon cache. - the limb icon cache adds an icon_render_key to a human mob, it represents: - - skin_tone (if applicable) - - gender - - limbs (stores as the limb name and whether it is removed/fine, organic/robotic) - These procs only store limbs as to increase the number of matching icon_render_keys - This cache exists because drawing 6/7 icons for humans constantly is quite a waste - See RemieRichards on irc.rizon.net #coderbus -*/ - -var/global/list/limb_icon_cache = list() - -/mob/living/carbon/human - var/icon_render_key = "" - - //produces a key based on the human's limbs -/mob/living/carbon/human/proc/generate_icon_render_key() +/mob/living/carbon/human/generate_icon_render_key() . = "[dna.species.limbs_id]" if(dna.check_mutation(HULK)) @@ -601,7 +533,7 @@ var/global/list/limb_icon_cache = list() for(var/X in bodyparts) var/obj/item/bodypart/BP = X . += "-[BP.body_zone]" - if(BP.status == ORGAN_ORGANIC) + if(BP.status == BODYPART_ORGANIC) . += "-organic" else . += "-robotic" @@ -609,16 +541,14 @@ var/global/list/limb_icon_cache = list() if(disabilities & HUSK) . += "-husk" - -//change the human's icon to the one matching it's key -/mob/living/carbon/human/proc/load_limb_from_cache() - if(limb_icon_cache[icon_render_key]) - remove_overlay(BODYPARTS_LAYER) - overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key] - apply_overlay(BODYPARTS_LAYER) +/mob/living/carbon/human/load_limb_from_cache() + ..() + update_mutant_bodyparts() + update_hair() -/mob/living/carbon/human/proc/update_observer_view(var/obj/item/I,var/inventory) + +/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory) if(observers && observers.len) for(var/M in observers) var/mob/dead/observe = M diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 3eb8b085a0f..e44a4bad371 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -10,10 +10,6 @@ return handcuffed if(slot_legcuffed) return legcuffed - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand return null @@ -24,10 +20,9 @@ if(!istype(I)) return - if(I == l_hand) - l_hand = null - else if(I == r_hand) - r_hand = null + var/index = get_held_index_of_item(I) + if(index) + held_items[index] = null if(I.pulledby) I.pulledby.stop_pulling() @@ -59,25 +54,22 @@ if(slot_legcuffed) legcuffed = I update_inv_legcuffed() - if(slot_l_hand) - l_hand = I - update_inv_l_hand() - if(slot_r_hand) - r_hand = I - update_inv_r_hand() + if(slot_hands) + put_in_hands(I) + update_inv_hands() if(slot_in_backpack) - if(I == get_active_hand()) + if(I == get_active_held_item()) unEquip(I) I.loc = back else not_handled = TRUE - + //Item has been handled at this point and equipped callback can be safely called //We cannot call it for items that have not been handled as they are not yet correctly //in a slot (handled further down inheritance chain, probably living/carbon/human/equip_to_slot if(!not_handled) I.equipped(src, slot) - + return not_handled /mob/living/carbon/unEquip(obj/item/I) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 2f4ca6da119..aa701d7f1b3 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -14,7 +14,8 @@ handle_blood() - for(var/obj/item/organ/O in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/O = X O.on_life() //Updates the number of stored chemicals for powers diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index 0d7378a729c..a66f14c1c36 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -1,32 +1,28 @@ /mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = 0) switch(slot) - if(slot_l_hand) - if(l_hand) - return 0 - return 1 - if(slot_r_hand) - if(r_hand) - return 0 - return 1 + if(slot_hands) + if(get_empty_held_indexes()) + return TRUE + return FALSE if(slot_wear_mask) if(wear_mask) - return 0 + return FALSE if( !(I.slot_flags & SLOT_MASK) ) - return 0 - return 1 + return FALSE + return TRUE if(slot_head) if(head) - return 0 + return FALSE if( !(I.slot_flags & SLOT_HEAD) ) - return 0 - return 1 + return FALSE + return TRUE if(slot_back) if(back) - return 0 + return FALSE if( !(I.slot_flags & SLOT_BACK) ) - return 0 - return 1 - return 0 //Unsupported slot + return FALSE + return TRUE + return FALSE //Unsupported slot diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index d3e541143b0..3e87fa5c1ab 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -39,7 +39,7 @@ if(75 to 100) if(prob(1)) src << "You mutate!" - randmutb(src) + randmutb() emote("gasp") domutcheck() ..() @@ -83,29 +83,29 @@ switch(bodytemperature) if(360 to 400) throw_alert("temp", /obj/screen/alert/hot, 1) - adjustFireLoss(2) + apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) if(400 to 460) throw_alert("temp", /obj/screen/alert/hot, 2) - adjustFireLoss(3) + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) if(460 to INFINITY) throw_alert("temp", /obj/screen/alert/hot, 3) if(on_fire) - adjustFireLoss(8) + apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) else - adjustFireLoss(3) + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) switch(bodytemperature) if(200 to 260) throw_alert("temp", /obj/screen/alert/cold, 1) - adjustFireLoss(0.5) + apply_damage(COLD_DAMAGE_LEVEL_1, BURN) if(120 to 200) throw_alert("temp", /obj/screen/alert/cold, 2) - adjustFireLoss(1.5) + apply_damage(COLD_DAMAGE_LEVEL_2, BURN) if(-INFINITY to 120) throw_alert("temp", /obj/screen/alert/cold, 3) - adjustFireLoss(3) + apply_damage(COLD_DAMAGE_LEVEL_3, BURN) else clear_alert("temp") diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 344fcf1c7f7..33cbce3edb1 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -3,7 +3,7 @@ voice_name = "monkey" verb_say = "chimpers" icon = 'icons/mob/monkey.dmi' - icon_state = "monkey1" + icon_state = "" gender = NEUTER pass_flags = PASSTABLE languages_spoken = MONKEY @@ -13,6 +13,10 @@ type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey gib_type = /obj/effect/decal/cleanable/blood/gibs unique_name = 1 + bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey, + /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey) + + /mob/living/carbon/monkey/New() verbs += /mob/living/proc/mob_sleep @@ -22,24 +26,13 @@ gender = pick(MALE, FEMALE) real_name = name - //initialize limbs, currently only used to handle cavity implant surgery, no dismemberment. - bodyparts = newlist(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm, - /obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg) - for(var/X in bodyparts) - var/obj/item/bodypart/O = X - O.owner = src + //initialize limbs + create_bodyparts() if(good_mutations.len) //genetic mutations have been set up. - initialize() + initialize() //initialize monkey dna - internal_organs += new /obj/item/organ/appendix - internal_organs += new /obj/item/organ/lungs - internal_organs += new /obj/item/organ/heart - internal_organs += new /obj/item/organ/brain - internal_organs += new /obj/item/organ/tongue - - for(var/obj/item/organ/I in internal_organs) - I.Insert(src) + create_internal_organs() ..() @@ -47,6 +40,15 @@ create_dna(src) dna.initialize_dna(random_blood_type()) + +/mob/living/carbon/monkey/create_internal_organs() + internal_organs += new /obj/item/organ/appendix + internal_organs += new /obj/item/organ/lungs + internal_organs += new /obj/item/organ/heart + internal_organs += new /obj/item/organ/brain + internal_organs += new /obj/item/organ/tongue + ..() + /mob/living/carbon/monkey/movement_delay() if(reagents) if(reagents.has_reagent("morphine")) @@ -64,133 +66,6 @@ . += (283.222 - bodytemperature) / 10 * 1.75 return . + config.monkey_delay -/mob/living/carbon/monkey/attack_paw(mob/living/M) - if(..()) //successful monkey bite. - var/damage = rand(1, 5) - if (stat != DEAD) - adjustBruteLoss(damage) - updatehealth() - return - -/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) - if(..()) //successful larva bite. - var/damage = rand(1, 3) - if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - adjustBruteLoss(damage) - updatehealth() - -/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) - if(..()) //To allow surgery to return properly. - return - - switch(M.a_intent) - if("help") - help_shake_act(M) - if("grab") - grabbedby(M) - if("harm") - M.do_attack_animation(src) - if (prob(75)) - visible_message("[M] has punched [name]!", \ - "[M] has punched [name]!") - - playsound(loc, "punch", 25, 1, -1) - var/damage = rand(5, 10) - if (prob(40)) - damage = rand(10, 15) - if ( (paralysis < 5) && (health > 0) ) - Paralyse(rand(10, 15)) - visible_message("[M] has knocked out [name]!", \ - "[M] has knocked out [name]!") - adjustBruteLoss(damage) - add_logs(M, src, "attacked") - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [name]!", \ - "[M] has attempted to punch [name]!") - if("disarm") - if (!( paralysis )) - M.do_attack_animation(src) - if (prob(25)) - Paralyse(2) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - add_logs(M, src, "pushed") - visible_message("[M] has pushed down [src]!", \ - "[M] has pushed down [src]!") - else - if(drop_item()) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has disarmed [src]!", \ - "[M] has disarmed [src]!") - -/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent. - if (M.a_intent == "harm") - if ((prob(95) && health > 0)) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - if (paralysis < 15) - Paralyse(rand(10, 15)) - visible_message("[M] has wounded [name]!", \ - "[M] has wounded [name]!") - else - visible_message("[M] has slashed [name]!", \ - "[M] has slashed [name]!") - - if (stat != DEAD) - adjustBruteLoss(damage) - updatehealth() - add_logs(M, src, "attacked") - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to lunge at [name]!", \ - "[M] has attempted to lunge at [name]!") - - if (M.a_intent == "disarm") - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - if(prob(95)) - Weaken(10) - visible_message("[M] has tackled down [name]!", \ - "[M] has tackled down [name]!") - else - if(drop_item()) - visible_message("[M] has disarmed [name]!", \ - "[M] has disarmed [name]!") - add_logs(M, src, "disarmed") - updatehealth() - return - -/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) - if(..()) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - switch(M.melee_damage_type) - if(BRUTE) - adjustBruteLoss(damage) - if(BURN) - adjustFireLoss(damage) - if(TOX) - adjustToxLoss(damage) - if(OXY) - adjustOxyLoss(damage) - if(CLONE) - adjustCloneLoss(damage) - if(STAMINA) - adjustStaminaLoss(damage) - updatehealth() - - -/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(5, 35) - if(M.is_adult) - damage = rand(20, 40) - adjustBruteLoss(damage) - updatehealth() - /mob/living/carbon/monkey/Stat() ..() if(statpanel("Status")) @@ -209,24 +84,6 @@ internal = null return -/mob/living/carbon/monkey/ex_act(severity, target) - ..() - switch(severity) - if(1) - gib() - return - if(2) - adjustBruteLoss(60) - adjustFireLoss(60) - adjustEarDamage(30,120) - if(3) - adjustBruteLoss(30) - if (prob(50)) - Paralyse(10) - adjustEarDamage(15,60) - - updatehealth() - return /mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools return 0 @@ -249,21 +106,20 @@ //Lasertag bullshit if(lasercolor) if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag)) threatcount += 4 if(lasercolor == "r") - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag)) threatcount += 4 return threatcount //Check for weapons if(judgebot.weaponscheck) - if(judgebot.check_for_weapons(l_hand)) - threatcount += 4 - if(judgebot.check_for_weapons(r_hand)) - threatcount += 4 + for(var/obj/item/I in held_items) + if(judgebot.check_for_weapons(I)) + threatcount += 4 //mindshield implants imply trustworthyness if(isloyal(src)) @@ -271,24 +127,6 @@ return threatcount -/mob/living/carbon/monkey/acid_act(acidpwr, toxpwr, acid_volume) - if(wear_mask) - if(!wear_mask.unacidable) - wear_mask.acid_act(acidpwr) - update_inv_wear_mask() - else - src << "Your mask protects you from the acid." - return - - take_organ_damage(min(6*toxpwr, acid_volume * acidpwr/10)) - -/mob/living/carbon/monkey/help_shake_act(mob/living/carbon/M) - if(health < 0 && ishuman(M)) - var/mob/living/carbon/human/H = M - H.do_cpr(src) - else - ..() - /mob/living/carbon/monkey/get_permeability_protection() var/protection = 0 if(head) @@ -298,13 +136,6 @@ protection = protection/7 //the rest of the body isn't covered. return protection -/mob/living/carbon/monkey/check_eye_prot() - var/number = ..() - if(istype(src.wear_mask, /obj/item/clothing/mask)) - var/obj/item/clothing/mask/MFP = src.wear_mask - number += MFP.flash_protect - return number - /mob/living/carbon/monkey/fully_heal(admin_revive = 0) if(!getorganslot("lungs")) var/obj/item/organ/lungs/L = new() diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm new file mode 100644 index 00000000000..c3a1818b242 --- /dev/null +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -0,0 +1,188 @@ + +/mob/living/carbon/monkey/get_eye_protection() + var/number = ..() + if(istype(src.wear_mask, /obj/item/clothing/mask)) + var/obj/item/clothing/mask/MFP = src.wear_mask + number += MFP.flash_protect + return number + +/mob/living/carbon/monkey/help_shake_act(mob/living/carbon/M) + if(health < 0 && ishuman(M)) + var/mob/living/carbon/human/H = M + H.do_cpr(src) + else + ..() + +/mob/living/carbon/monkey/attack_paw(mob/living/M) + if(..()) //successful monkey bite. + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + if(M.limb_destroyer) + dismembering_strike(M, affecting.body_zone) + if(stat != DEAD) + apply_damage(rand(1, 5), BRUTE, affecting) + + + +/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) + if(..()) //successful larva bite. + var/damage = rand(1, 3) + if(stat != DEAD) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + apply_damage(damage, BRUTE, affecting) + +/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) + if(..()) //To allow surgery to return properly. + return + + switch(M.a_intent) + if("help") + help_shake_act(M) + if("grab") + grabbedby(M) + if("harm") + M.do_attack_animation(src) + if (prob(75)) + visible_message("[M] has punched [name]!", \ + "[M] has punched [name]!") + + playsound(loc, "punch", 25, 1, -1) + var/damage = rand(5, 10) + if (prob(40)) + damage = rand(10, 15) + if ( (paralysis < 5) && (health > 0) ) + Paralyse(rand(10, 15)) + visible_message("[M] has knocked out [name]!", \ + "[M] has knocked out [name]!") + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + apply_damage(damage, BRUTE, affecting) + add_logs(M, src, "attacked") + + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch [name]!", \ + "[M] has attempted to punch [name]!") + if("disarm") + if (!( paralysis )) + M.do_attack_animation(src) + if (prob(25)) + Paralyse(2) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + add_logs(M, src, "pushed") + visible_message("[M] has pushed down [src]!", \ + "[M] has pushed down [src]!") + else + if(drop_item()) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed [src]!") + +/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) + if(..()) //if harm or disarm intent. + if (M.a_intent == "harm") + if ((prob(95) && health > 0)) + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + var/damage = rand(15, 30) + if (damage >= 25) + damage = rand(20, 40) + if (paralysis < 15) + Paralyse(rand(10, 15)) + visible_message("[M] has wounded [name]!", \ + "[M] has wounded [name]!") + else + visible_message("[M] has slashed [name]!", \ + "[M] has slashed [name]!") + + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + add_logs(M, src, "attacked") + if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful + return 1 + apply_damage(damage, BRUTE, affecting) + + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to lunge at [name]!", \ + "[M] has attempted to lunge at [name]!") + + if (M.a_intent == "disarm") + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + if(prob(95)) + Weaken(10) + visible_message("[M] has tackled down [name]!", \ + "[M] has tackled down [name]!") + else + if(drop_item()) + visible_message("[M] has disarmed [name]!", \ + "[M] has disarmed [name]!") + add_logs(M, src, "disarmed") + updatehealth() + + +/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) + if(..()) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + apply_damage(damage, M.melee_damage_type, affecting) + + + +/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M) + if(..()) //successful slime attack + var/damage = rand(5, 35) + if(M.is_adult) + damage = rand(20, 40) + var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) + apply_damage(damage, BRUTE, affecting) + + +/mob/living/carbon/monkey/acid_act(acidpwr, toxpwr, acid_volume) + if(wear_mask) + if(!wear_mask.unacidable) + wear_mask.acid_act(acidpwr) + update_inv_wear_mask() + else + src << "Your mask protects you from the acid." + return + + take_bodypart_damage(min(6*toxpwr, acid_volume * acidpwr/10)) + + +/mob/living/carbon/monkey/ex_act(severity, target) + ..() + + switch (severity) + if (1) + gib() + + if (2) + take_overall_damage(60, 60) + shred_clothing(1,50) + adjustEarDamage(30, 120) + if(prob(70)) + Paralyse(10) + + if(3) + take_overall_damage(30, 0) + adjustEarDamage(15,60) + if (prob(50)) + Paralyse(8) + + + //attempt to dismember bodyparts + if(severity <= 2) + var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3. + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(prob(50/severity) && BP.body_zone != "chest") + BP.brute_dam = BP.max_damage + BP.dismember() + max_limb_loss-- + if(!max_limb_loss) + break diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index b342ace1e79..b7ca5044398 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -1,29 +1,47 @@ /mob/living/carbon/monkey/regenerate_icons() if(!..()) + update_body_parts() + update_hair() update_inv_wear_mask() update_inv_head() update_inv_back() - update_icons() update_transform() -/mob/living/carbon/monkey/update_icons() - cut_overlays() - icon_state = "monkey1" - for(var/image/I in overlays_standing) - add_overlay(I) //////// + +/mob/living/carbon/monkey/update_hair() + remove_overlay(HAIR_LAYER) + + var/obj/item/bodypart/head/HD = get_bodypart("head") + if(!HD) //Decapitated + return + + if(disabilities & HUSK) + return + + var/hair_hidden = 0 + + if(head) + var/obj/item/I = head + if(I.flags_inv & HIDEHAIR) + hair_hidden = 1 + if(wear_mask) + var/obj/item/clothing/mask/M = wear_mask + if(M.flags_inv & HIDEHAIR) + hair_hidden = 1 + if(!hair_hidden) + if(!getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain + var/image/I = image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) + overlays_standing[HAIR_LAYER] = I + apply_overlay(HAIR_LAYER) + + /mob/living/carbon/monkey/update_fire() ..("Monkey_burning") -/mob/living/carbon/monkey/update_inv_handcuffed() - remove_overlay(HANDCUFF_LAYER) - if(handcuffed) - overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER) - apply_overlay(HANDCUFF_LAYER) - /mob/living/carbon/monkey/update_inv_legcuffed() remove_overlay(LEGCUFF_LAYER) if(legcuffed) diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index 24c9305aa15..abfe312c48b 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -1,6 +1,6 @@ //Here are the procs used to modify status effects of a mob. //The effects include: stunned, weakened, paralysis, sleeping, resting, jitteriness, dizziness, ear damage, -// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, and NEARSIGHT disability. +// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, NEARSIGHT disability, and HUSK disability. /mob/living/carbon/damage_eyes(amount) if(amount>0) @@ -76,4 +76,19 @@ if(!(disabilities & NEARSIGHT)) disabilities |= NEARSIGHT overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) - return 1 \ No newline at end of file + return 1 + +/mob/living/carbon/cure_husk() + if(disabilities & HUSK) + disabilities &= ~HUSK + status_flags &= ~DISFIGURED + update_body() + return 1 + +/mob/living/carbon/become_husk() + if(disabilities & HUSK) + return + disabilities |= HUSK + status_flags |= DISFIGURED //makes them unknown + update_body() + return 1 diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index a89af54cd5d..dcd5b1a59b2 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -40,64 +40,51 @@ overlays -= overlays_standing[cache_index] overlays_standing[cache_index] = null -/mob/living/carbon/update_inv_r_hand() - remove_overlay(R_HAND_LAYER) +/mob/living/carbon/regenerate_icons() + if(notransform) + return 1 + update_inv_hands() + update_inv_handcuffed() + update_inv_legcuffed() + update_fire() + + +/mob/living/carbon/update_inv_hands() + remove_overlay(HANDS_LAYER) if (handcuffed) - drop_r_hand() + drop_all_held_items() return - if(r_hand) + + var/list/hands = list() + for(var/obj/item/I in held_items) if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) - r_hand.screen_loc = ui_rhand - client.screen += r_hand + I.screen_loc = ui_hand_position(get_held_index_of_item(I)) + client.screen += I if(observers && observers.len) for(var/M in observers) var/mob/dead/observe = M if(observe.client && observe.client.eye == src) - observe.client.screen += r_hand + observe.client.screen += I else observers -= observe if(!observers.len) observers = null break - - var/t_state = r_hand.item_state + var/t_state = I.item_state if(!t_state) - t_state = r_hand.icon_state + t_state = I.icon_state - var/image/standing = r_hand.build_worn_icon(state = t_state, default_layer = R_HAND_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) - overlays_standing[R_HAND_LAYER] = standing + var/icon_file = I.lefthand_file + if(get_held_index_of_item(I) % 2 == 0) + icon_file = I.righthand_file - apply_overlay(R_HAND_LAYER) + var/image/standing = I.build_worn_icon(state = t_state, default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) + hands += standing -/mob/living/carbon/update_inv_l_hand() - remove_overlay(L_HAND_LAYER) - if(handcuffed) - drop_l_hand() - return - if(l_hand) - if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) - l_hand.screen_loc = ui_lhand - client.screen += l_hand - if(observers && observers.len) - for(var/M in observers) - var/mob/dead/observe = M - if(observe.client && observe.client.eye == src) - observe.client.screen += l_hand - else - observers -= observe - if(!observers.len) - observers = null - break + overlays_standing[HANDS_LAYER] = hands + apply_overlay(HANDS_LAYER) - var/t_state = l_hand.item_state - if(!t_state) - t_state = l_hand.icon_state - - var/image/standing = l_hand.build_worn_icon(state = t_state, default_layer = L_HAND_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) - overlays_standing[L_HAND_LAYER] = standing - - apply_overlay(L_HAND_LAYER) /mob/living/carbon/update_fire(var/fire_icon = "Generic_mob_burning") remove_overlay(FIRE_LAYER) @@ -106,24 +93,44 @@ apply_overlay(FIRE_LAYER) -/mob/living/carbon/regenerate_icons() - if(notransform) - return 1 - update_inv_r_hand() - update_inv_l_hand() - update_inv_handcuffed() - update_inv_legcuffed() - update_fire() + + +/mob/living/carbon/update_damage_overlays() + remove_overlay(DAMAGE_LAYER) + + var/image/standing = image("icon"='icons/mob/dam_mob.dmi', "icon_state"="blank", "layer"=-DAMAGE_LAYER) + overlays_standing[DAMAGE_LAYER] = standing + + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(BP.dmg_overlay_type) + if(BP.brutestate) + standing.overlays += "[BP.dmg_overlay_type]_[BP.body_zone]_[BP.brutestate]0" //we're adding icon_states of the base image as overlays + if(BP.burnstate) + standing.overlays += "[BP.dmg_overlay_type]_[BP.body_zone]_0[BP.burnstate]" + + apply_overlay(DAMAGE_LAYER) + /mob/living/carbon/update_inv_wear_mask() remove_overlay(FACEMASK_LAYER) - if(istype(wear_mask, /obj/item/clothing/mask)) + + if(!get_bodypart("head")) //Decapitated + return + + if(client && hud_used && hud_used.inv_slots[slot_wear_mask]) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask] + inv.update_icon() + + if(wear_mask) if(!(head && (head.flags_inv & HIDEMASK))) var/image/standing = wear_mask.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/mask.dmi') overlays_standing[FACEMASK_LAYER] = standing update_hud_wear_mask(wear_mask) + apply_overlay(FACEMASK_LAYER) + /mob/living/carbon/update_inv_back() remove_overlay(BACK_LAYER) @@ -139,14 +146,27 @@ /mob/living/carbon/update_inv_head() remove_overlay(HEAD_LAYER) + + if(!get_bodypart("head")) //Decapitated + return + + if(client && hud_used && hud_used.inv_slots[slot_back]) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head] + inv.update_icon() + if(head) var/image/standing = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi') overlays_standing[HEAD_LAYER] = standing update_hud_head(head) + apply_overlay(HEAD_LAYER) + /mob/living/carbon/update_inv_handcuffed() - return + remove_overlay(HANDCUFF_LAYER) + if(handcuffed) + overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER) + apply_overlay(HANDCUFF_LAYER) //mob HUD updates for items in our inventory @@ -154,11 +174,10 @@ //update whether handcuffs appears on our hud. /mob/living/carbon/proc/update_hud_handcuffed() if(hud_used) - var/obj/screen/inventory/R = hud_used.inv_slots[slot_r_hand] - var/obj/screen/inventory/L = hud_used.inv_slots[slot_l_hand] - if(R && L) - R.update_icon() - L.update_icon() + for(var/hand in hud_used.hand_slots) + var/obj/screen/inventory/hand/H = hud_used.hand_slots[hand] + if(H) + H.update_icon() //update whether our head item appears on our hud. /mob/living/carbon/proc/update_hud_head(obj/item/I) @@ -173,12 +192,92 @@ return + //Overlays for the worn overlay so you can overlay while you overlay //eg: ammo counters, primed grenade flashing, etc. -/obj/item/proc/worn_overlays(var/isinhands = FALSE) +/obj/item/proc/worn_overlays(isinhands = FALSE) . = list() +/mob/living/carbon/update_body() + update_body_parts() + +/mob/living/carbon/proc/update_body_parts() + //CHECK FOR UPDATE + var/oldkey = icon_render_key + icon_render_key = generate_icon_render_key() + if(oldkey == icon_render_key) + return + + remove_overlay(BODYPARTS_LAYER) + + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(!BP.no_update) + BP.update_limb() + + //LOAD ICONS + if(limb_icon_cache[icon_render_key]) + load_limb_from_cache() + return + + //GENERATE NEW LIMBS + var/list/new_limbs = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + var/image/temp = BP.get_limb_icon() + if(temp) + new_limbs += temp + if(new_limbs.len) + overlays_standing[BODYPARTS_LAYER] = new_limbs + limb_icon_cache[icon_render_key] = new_limbs + + apply_overlay(BODYPARTS_LAYER) + update_damage_overlays() +///////////////////// +// Limb Icon Cache // +///////////////////// +/* + Called from update_body_parts() these procs handle the limb icon cache. + the limb icon cache adds an icon_render_key to a human mob, it represents: + - skin_tone (if applicable) + - gender + - limbs (stores as the limb name and whether it is removed/fine, organic/robotic) + These procs only store limbs as to increase the number of matching icon_render_keys + This cache exists because drawing 6/7 icons for humans constantly is quite a waste + See RemieRichards on irc.rizon.net #coderbus +*/ + +var/global/list/limb_icon_cache = list() + +/mob/living/carbon + var/icon_render_key = "" + + +//produces a key based on the mob's limbs + +/mob/living/carbon/proc/generate_icon_render_key() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + . += "-[BP.body_zone]" + if(BP.animal_origin) + . += "-[BP.animal_origin]" + if(BP.status == BODYPART_ORGANIC) + . += "-organic" + else + . += "-robotic" + + if(disabilities & HUSK) + . += "-husk" + + +//change the mob's icon to the one matching its key +/mob/living/carbon/proc/load_limb_from_cache() + if(limb_icon_cache[icon_render_key]) + remove_overlay(BODYPARTS_LAYER) + overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key] + apply_overlay(BODYPARTS_LAYER) + update_damage_overlays() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 0690e8b11fd..f0fcda0dcf9 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -9,23 +9,22 @@ standard 0 if fail */ /mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) - blocked = (100-blocked)/100 - if(!damage || (blocked <= 0)) + var/hit_percent = (100-blocked)/100 + if(!damage || (hit_percent <= 0)) return 0 switch(damagetype) if(BRUTE) - adjustBruteLoss(damage * blocked) + adjustBruteLoss(damage * hit_percent) if(BURN) - adjustFireLoss(damage * blocked) + adjustFireLoss(damage * hit_percent) if(TOX) - adjustToxLoss(damage * blocked) + adjustToxLoss(damage * hit_percent) if(OXY) - adjustOxyLoss(damage * blocked) + adjustOxyLoss(damage * hit_percent) if(CLONE) - adjustCloneLoss(damage * blocked) + adjustCloneLoss(damage * hit_percent) if(STAMINA) - adjustStaminaLoss(damage * blocked) - updatehealth() + adjustStaminaLoss(damage * hit_percent) return 1 @@ -49,30 +48,30 @@ /mob/living/proc/apply_effect(effect = 0,effecttype = STUN, blocked = 0) - blocked = (100-blocked)/100 - if(!effect || (blocked <= 0)) + var/hit_percent = (100-blocked)/100 + if(!effect || (hit_percent <= 0)) return 0 switch(effecttype) if(STUN) - Stun(effect * blocked) + Stun(effect * hit_percent) if(WEAKEN) - Weaken(effect * blocked) + Weaken(effect * hit_percent) if(PARALYZE) - Paralyse(effect * blocked) + Paralyse(effect * hit_percent) if(IRRADIATE) - radiation += max(effect * blocked, 0) + radiation += max(effect * hit_percent, 0) if(SLUR) - slurring = max(slurring,(effect * blocked)) + slurring = max(slurring,(effect * hit_percent)) if(STUTTER) if(status_flags & CANSTUN) // stun is usually associated with stutter - stuttering = max(stuttering,(effect * blocked)) + stuttering = max(stuttering,(effect * hit_percent)) if(EYE_BLUR) - blur_eyes(effect * blocked) + blur_eyes(effect * hit_percent) if(DROWSY) - drowsyness = max(drowsyness,(effect * blocked)) + drowsyness = max(drowsyness,(effect * hit_percent)) if(JITTER) if(status_flags & CANSTUN) - jitteriness = max(jitteriness,(effect * blocked)) + jitteriness = max(jitteriness,(effect * hit_percent)) return 1 @@ -99,4 +98,128 @@ apply_damage(stamina, STAMINA, null, blocked) if(jitter) apply_effect(jitter, JITTER, blocked) - return 1 \ No newline at end of file + return 1 + + +/mob/living/proc/getBruteLoss() + return bruteloss + +/mob/living/proc/adjustBruteLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + bruteloss = Clamp((bruteloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + if(updating_health) + updatehealth() + +/mob/living/proc/getOxyLoss() + return oxyloss + +/mob/living/proc/adjustOxyLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + oxyloss = Clamp((oxyloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + if(updating_health) + updatehealth() + +/mob/living/proc/setOxyLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + oxyloss = amount + if(updating_health) + updatehealth() + +/mob/living/proc/getToxLoss() + return toxloss + +/mob/living/proc/adjustToxLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + toxloss = Clamp((toxloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + if(updating_health) + updatehealth() + return amount + +/mob/living/proc/setToxLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + toxloss = amount + if(updating_health) + updatehealth() + +/mob/living/proc/getFireLoss() + return fireloss + +/mob/living/proc/adjustFireLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + fireloss = Clamp((fireloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + if(updating_health) + updatehealth() + +/mob/living/proc/getCloneLoss() + return cloneloss + +/mob/living/proc/adjustCloneLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + cloneloss = Clamp((cloneloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + if(updating_health) + updatehealth() + +/mob/living/proc/setCloneLoss(amount, updating_health=1) + if(status_flags & GODMODE) + return 0 + cloneloss = amount + if(updating_health) + updatehealth() + +/mob/living/proc/getBrainLoss() + return brainloss + +/mob/living/proc/adjustBrainLoss(amount) + if(status_flags & GODMODE) + return 0 + brainloss = Clamp((brainloss + (amount * config.damage_multiplier)), 0, maxHealth*2) + +/mob/living/proc/setBrainLoss(amount) + if(status_flags & GODMODE) + return 0 + brainloss = amount + +/mob/living/proc/getStaminaLoss() + return staminaloss + +/mob/living/proc/adjustStaminaLoss(amount, updating_stamina = 1) + return + +/mob/living/proc/setStaminaLoss(amount, updating_stamina = 1) + return + + +// heal ONE external organ, organ gets randomly selected from damaged ones. +/mob/living/proc/heal_bodypart_damage(brute, burn, updating_health = 1) + adjustBruteLoss(-brute, 0) //zero as argument for no instant health update + adjustFireLoss(-burn, 0) + if(updating_health) + updatehealth() + +// damage ONE external organ, organ gets randomly selected from damaged ones. +/mob/living/proc/take_bodypart_damage(brute, burn, updating_health = 1) + adjustBruteLoss(brute, 0) //zero as argument for no instant health update + adjustFireLoss(burn, 0) + if(updating_health) + updatehealth() + +// heal MANY bodyparts, in random order +/mob/living/proc/heal_overall_damage(brute, burn, only_robotic = 0, only_organic = 1, updating_health = 1) + adjustBruteLoss(-brute, 0) //zero as argument for no instant health update + adjustFireLoss(-burn, 0) + if(updating_health) + updatehealth() + +// damage MANY bodyparts, in random order +/mob/living/proc/take_overall_damage(brute, burn, updating_health = 1) + adjustBruteLoss(brute, 0) //zero as argument for no instant health update + adjustFireLoss(burn, 0) + if(updating_health) + updatehealth() \ No newline at end of file diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index fc1bf88240b..10c9a2a50f8 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -1,4 +1,4 @@ -/mob/living/gib(no_brain, no_organs) +/mob/living/gib(no_brain, no_organs, no_bodyparts) var/prev_lying = lying if(stat != DEAD) death(1) @@ -8,20 +8,27 @@ if(!prev_lying) gib_animation() - if(!no_organs) - spill_organs(no_brain) - spawn_gibs() + + + spill_organs(no_brain, no_organs, no_bodyparts) + + if(!no_bodyparts) + spread_bodyparts(no_brain, no_organs) + + spawn_gibs(no_bodyparts) qdel(src) /mob/living/proc/gib_animation() return /mob/living/proc/spawn_gibs() - gibs(loc, viruses) + new /obj/effect/gibspawner/generic(loc, viruses) -/mob/living/proc/spill_organs(no_brain) +/mob/living/proc/spill_organs() return +/mob/living/proc/spread_bodyparts() + return /mob/living/dust() death(1) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index f44ca1855ba..052328ac563 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -78,6 +78,23 @@ /mob/living/proc/handle_environment(datum/gas_mixture/environment) return +/mob/living/proc/handle_fire() + if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly + fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable. + if(!on_fire) + return 1 + if(fire_stacks > 0) + adjust_fire_stacks(-0.1) //the fire is slowly consumed + else + ExtinguishMob() + return + var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment + if(!G.gases["o2"] || G.gases["o2"][MOLES] < 1) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return + var/turf/location = get_turf(src) + location.hotspot_expose(700, 50, 1) + /mob/living/proc/handle_stomach() return diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 66f926d5692..b06fef840ca 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -149,10 +149,10 @@ if(!(M.status_flags & CANPUSH)) return 1 //anti-riot equipment is also anti-push - if(M.r_hand && (prob(M.r_hand.block_chance * 2)) && !istype(M.r_hand, /obj/item/clothing)) - return 1 - if(M.l_hand && (prob(M.l_hand.block_chance * 2)) && !istype(M.l_hand, /obj/item/clothing)) - return 1 + for(var/obj/item/I in M.held_items) + if(!istype(M, /obj/item/clothing)) + if(prob(I.block_chance*2)) + return 1 //Called when we bump onto an obj /mob/living/proc/ObjBump(obj/O) @@ -212,22 +212,13 @@ src << "You have given up life and succumbed to death." death() +/mob/living/incapacitated(ignore_restraints, ignore_grab) + if(stat || paralysis || stunned || weakened || (!ignore_restraints && restrained(ignore_grab))) + return 1 + /mob/living/proc/InCritical() return (src.health < 0 && src.health > -95 && stat == UNCONSCIOUS) -/mob/living/ex_act(severity, origin) - if(istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) - return - ..() - flash_eyes() - -/mob/living/proc/updatehealth() - if(status_flags & GODMODE) - return - health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - update_stat() - med_hud_set_health() - //This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually //affects them once clothing is factored in. ~Errorage /mob/living/proc/calculate_affecting_pressure(pressure) @@ -255,120 +246,6 @@ return temperature -// MOB PROCS -/mob/living/proc/getBruteLoss() - return bruteloss - -/mob/living/proc/adjustBruteLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - bruteloss = Clamp((bruteloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - if(updating_health) - updatehealth() - -/mob/living/proc/getOxyLoss() - return oxyloss - -/mob/living/proc/adjustOxyLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - oxyloss = Clamp((oxyloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - if(updating_health) - updatehealth() - -/mob/living/proc/setOxyLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - oxyloss = amount - if(updating_health) - updatehealth() - -/mob/living/proc/getToxLoss() - return toxloss - -/mob/living/proc/adjustToxLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - toxloss = Clamp((toxloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - if(updating_health) - updatehealth() - return amount - -/mob/living/proc/setToxLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - toxloss = amount - if(updating_health) - updatehealth() - -/mob/living/proc/getFireLoss() - return fireloss - -/mob/living/proc/adjustFireLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - fireloss = Clamp((fireloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - if(updating_health) - updatehealth() - -/mob/living/proc/getCloneLoss() - return cloneloss - -/mob/living/proc/adjustCloneLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - cloneloss = Clamp((cloneloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - if(updating_health) - updatehealth() - -/mob/living/proc/setCloneLoss(amount, updating_health=1) - if(status_flags & GODMODE) - return 0 - cloneloss = amount - if(updating_health) - updatehealth() - -/mob/living/proc/getBrainLoss() - return brainloss - -/mob/living/proc/adjustBrainLoss(amount) - if(status_flags & GODMODE) - return 0 - brainloss = Clamp((brainloss + (amount * config.damage_multiplier)), 0, maxHealth*2) - -/mob/living/proc/setBrainLoss(amount) - if(status_flags & GODMODE) - return 0 - brainloss = amount - -/mob/living/proc/getStaminaLoss() - return staminaloss - -/mob/living/proc/adjustStaminaLoss(amount, updating_stamina = 1) - return - -/mob/living/carbon/adjustStaminaLoss(amount, updating_stamina = 1) - if(status_flags & GODMODE) - return 0 - staminaloss = Clamp(staminaloss + amount, 0, maxHealth*2) - if(updating_stamina) - update_stamina() - -/mob/living/carbon/alien/adjustStaminaLoss(amount, updating_stamina = 1) - return - -/mob/living/proc/setStaminaLoss(amount, updating_stamina = 1) - return - -/mob/living/carbon/setStaminaLoss(amount, updating_stamina = 1) - if(status_flags & GODMODE) - return 0 - staminaloss = amount - if(updating_stamina) - update_stamina() - -/mob/living/carbon/alien/setStaminaLoss(amount, updating_stamina = 1) - return /mob/living/proc/getMaxHealth() return maxHealth @@ -425,23 +302,6 @@ return 1 return 0 - -/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) - if(shock_damage > 0) - adjustFireLoss(shock_damage) - visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock coursing through your body!", \ - "You hear a heavy electrical crack." \ - ) - return shock_damage - -/mob/living/emp_act(severity) - var/list/L = src.get_contents() - for(var/obj/O in L) - O.emp_act(severity) - ..() - /mob/living/proc/can_inject() return 1 @@ -453,33 +313,14 @@ var/def_zone = ran_zone(t) return def_zone -// heal ONE external organ, organ gets randomly selected from damaged ones. -/mob/living/proc/heal_organ_damage(brute, burn, updating_health=1) - adjustBruteLoss(-brute, updating_health) - adjustFireLoss(-burn, updating_health) - if(updating_health) - updatehealth() -// damage ONE external organ, organ gets randomly selected from damaged ones. -/mob/living/proc/take_organ_damage(brute, burn, updating_health=1) - adjustBruteLoss(brute) - adjustFireLoss(burn) - if(updating_health) - updatehealth() - -// heal MANY bodyparts, in random order -/mob/living/proc/heal_overall_damage(brute, burn, updating_health=1) - adjustBruteLoss(-brute, updating_health) - adjustFireLoss(-burn, updating_health) - if(updating_health) - updatehealth() - -// damage MANY bodyparts, in random order -/mob/living/proc/take_overall_damage(brute, burn, updating_health=1) - adjustBruteLoss(brute, updating_health) - adjustFireLoss(burn, updating_health) - if(updating_health) - updatehealth() +/mob/living/proc/updatehealth() + if(status_flags & GODMODE) + return + health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() + update_stat() + med_hud_set_health() + med_hud_set_status() //proc used to ressuscitate a mob /mob/living/proc/revive(full_heal = 0, admin_revive = 0) @@ -500,7 +341,7 @@ //proc used to completely heal a mob. /mob/living/proc/fully_heal(admin_revive = 0) restore_blood() - setToxLoss(0, 0) + setToxLoss(0, 0) //zero as second argument not automatically call updatehealth(). setOxyLoss(0, 0) setCloneLoss(0, 0) setBrainLoss(0) @@ -517,14 +358,14 @@ set_eye_damage(0) cure_nearsighted() cure_blind() + cure_husk() disabilities = 0 ear_deaf = 0 ear_damage = 0 hallucination = 0 - heal_overall_damage(100000, 100000) + heal_overall_damage(100000, 100000, 0, 0, 1) //heal brute and burn dmg on both organic and robotic limbs, and update health right away. ExtinguishMob() fire_stacks = 0 - updatehealth() update_canmove() @@ -758,21 +599,6 @@ animate(src, pixel_y = get_standard_pixel_y_offset(lying), time = 10) floating = 0 -//called when the mob receives a bright flash -/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) - if(check_eye_prot() < intensity && (override_blindness_check || !(disabilities & BLIND))) - overlay_fullscreen("flash", type) - addtimer(src, "clear_fullscreen", 25, FALSE, "flash", 25) - return 1 - -//this returns the mob's protection against eye damage (number between -1 and 2) -/mob/living/proc/check_eye_prot() - return 0 - -//this returns the mob's protection against ear damage (0 or 1) -/mob/living/proc/check_ear_prot() - return 0 - // The src mob is trying to strip an item from someone // Override if a certain type of mob should be behave differently when stripping items (can't, for example) /mob/living/stripPanelUnequip(obj/item/what, mob/who, where) @@ -783,33 +609,44 @@ "[src] tries to remove [who]'s [what.name].") what.add_fingerprint(src) if(do_mob(src, who, what.strip_delay)) - if(what && what == who.get_item_by_slot(where) && Adjacent(who)) - who.unEquip(what) - add_logs(src, who, "stripped", addition="of [what]") + if(what && Adjacent(who)) + if(islist(where)) + var/list/L = where + if(what == who.get_item_for_held_index(L[2])) + who.unEquip(what) + add_logs(src, who, "stripped", addition="of [what]") + if(what == who.get_item_by_slot(where)) + who.unEquip(what) + add_logs(src, who, "stripped", addition="of [what]") // The src mob is trying to place an item on someone // Override if a certain mob should be behave differently when placing items (can't, for example) /mob/living/stripPanelEquip(obj/item/what, mob/who, where) - what = src.get_active_hand() + what = src.get_active_held_item() if(what && (what.flags & NODROP)) src << "You can't put \the [what.name] on [who], it's stuck to your hand!" return if(what) - if(!what.mob_can_equip(who, src, where, 1)) - src << "\The [what.name] doesn't fit in that place!" - return + var/list/where_list + if(islist(where)) + where_list = where + if(!what.mob_can_equip(who, src, where[1], 1)) + src << "\The [what.name] doesn't fit in that place!" + return + else + if(!what.mob_can_equip(who, src, where, 1)) + src << "\The [what.name] doesn't fit in that place!" + return visible_message("[src] tries to put [what] on [who].") if(do_mob(src, who, what.put_on_delay)) if(what && Adjacent(who)) unEquip(what) - who.equip_to_slot_if_possible(what, where, 0, 1) + if(where_list) + who.put_in_hand(what, where_list[2]) + else + who.equip_to_slot_if_possible(what, where, 0, 1) add_logs(src, who, "equipped", what) -/mob/living/singularity_act() - var/gain = 20 - investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! - gib() - return(gain) /mob/living/singularity_pull(S, current_size) if(current_size >= STAGE_SIX) @@ -817,29 +654,6 @@ else step_towards(src,S) -/mob/living/narsie_act() - if(is_servant_of_ratvar(src) && !stat) - src << "You resist Nar-Sie's influence... but not all of it. Run!" - adjustBruteLoss(35) - if(src && reagents) - reagents.add_reagent("heparin", 5) - return 0 - if(client) - makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, null, 0) - else - new /mob/living/simple_animal/hostile/construct/harvester/hostile(get_turf(src)) - spawn_dust() - gib() - return - -/mob/living/ratvar_act() - if(!add_servant_of_ratvar(src) && !is_servant_of_ratvar(src)) - src << "A blinding light boils you alive! Run!" - adjustFireLoss(35) - if(src) - adjust_fire_stacks(1) - IgniteMob() - /atom/movable/proc/do_attack_animation(atom/A, end_pixel_y) var/pixel_x_diff = 0 var/pixel_y_diff = 0 @@ -869,11 +683,10 @@ // What icon do we use for the attack? var/image/I - if(hand && l_hand) // Attacked with item in left hand. - I = image(l_hand.icon, A, l_hand.icon_state, A.layer + 0.1) - else if(!hand && r_hand) // Attacked with item in right hand. - I = image(r_hand.icon, A, r_hand.icon_state, A.layer + 0.1) - else // Attacked with a fist? + var/obj/item/held_item = get_active_held_item() + if(held_item) + I = image(held_item.icon, A, held_item.icon_state, A.layer + 0.1) + else return // Who can see the attack? @@ -1001,7 +814,7 @@ new path(src.loc) butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below. visible_message("[user] butchers [src].") - gib() + gib(0, 0, 1) /mob/living/canUseTopic(atom/movable/M, be_close = 0, no_dextery = 0) if(incapacitated()) @@ -1089,3 +902,50 @@ /mob/living/proc/fakefire() return + + + +//Mobs on Fire +/mob/living/proc/IgniteMob() + if(fire_stacks > 0 && !on_fire) + on_fire = 1 + src.visible_message("[src] catches fire!", \ + "You're set on fire!") + src.AddLuminosity(3) + throw_alert("fire", /obj/screen/alert/fire) + update_fire() + return TRUE + return FALSE + +/mob/living/proc/ExtinguishMob() + if(on_fire) + on_fire = 0 + fire_stacks = 0 + src.AddLuminosity(-3) + clear_alert("fire") + update_fire() + +/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person + fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) + if(on_fire && fire_stacks <= 0) + ExtinguishMob() + +//Share fire evenly between the two mobs +//Called in MobBump() and Crossed() +/mob/living/proc/spreadFire(mob/living/L) + if(!istype(L)) + return + var/L_old_on_fire = L.on_fire + + if(on_fire) //Only spread fire stacks if we're on fire + fire_stacks /= 2 + L.fire_stacks += fire_stacks + if(L.IgniteMob()) + log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire") + + if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them + L.fire_stacks /= 2 + fire_stacks += L.fire_stacks + IgniteMob() + +//Mobs on Fire end diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index c61e41458f1..ee4bd6ce206 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -1,3 +1,4 @@ + /mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text) var/armor = getarmor(def_zone, attack_flag) @@ -24,6 +25,14 @@ /mob/living/proc/getarmor(def_zone, type) return 0 +//this returns the mob's protection against eye damage (number between -1 and 2) +/mob/living/proc/get_eye_protection() + return 0 + +//this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears) +/mob/living/proc/get_ear_protection() + return 0 + /mob/living/proc/on_hit(obj/item/projectile/proj_type) return @@ -33,18 +42,16 @@ apply_damage(P.damage, P.damage_type, def_zone, armor) if(P.dismemberment) check_projectile_dismemberment(P, def_zone) - return P.on_hit(src, armor, def_zone) + return P.on_hit(src, armor) /mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone) return 0 -/proc/vol_by_throwforce_and_or_w_class(obj/item/I) - if(!I) - return 0 - if(I.throwforce && I.w_class) - return Clamp((I.throwforce + I.w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100 - else if(I.w_class) - return Clamp(I.w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100 +/obj/item/proc/get_volume_by_throwforce_and_or_w_class() + if(throwforce && w_class) + return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100 + else if(w_class) + return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100 else return 0 @@ -53,7 +60,7 @@ var/obj/item/I = AM var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest var/dtype = BRUTE - var/volume = vol_by_throwforce_and_or_w_class(I) + var/volume = I.get_volume_by_throwforce_and_or_w_class() if(istype(I,/obj/item/weapon)) //If the item is a weapon... var/obj/item/weapon/W = I dtype = W.damtype @@ -83,6 +90,7 @@ playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) ..() + /mob/living/mech_melee_attack(obj/mecha/M) if(M.occupant.a_intent == "harm") M.do_attack_animation(src) @@ -109,80 +117,10 @@ add_logs(M.occupant, src, "pushed", M) visible_message("[M] pushes [src] out of the way.") - -//Mobs on Fire -/mob/living/proc/IgniteMob() - if(fire_stacks > 0 && !on_fire) - on_fire = 1 - src.visible_message("[src] catches fire!", \ - "You're set on fire!") - src.AddLuminosity(3) - throw_alert("fire", /obj/screen/alert/fire) - update_fire() - return TRUE - return FALSE - -/mob/living/proc/ExtinguishMob() - if(on_fire) - on_fire = 0 - fire_stacks = 0 - src.AddLuminosity(-3) - clear_alert("fire") - update_fire() - -/mob/living/proc/update_fire() - return - -/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) - if(on_fire && fire_stacks <= 0) - ExtinguishMob() - -/mob/living/proc/handle_fire() - if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly - fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable. - if(!on_fire) - return 1 - if(fire_stacks > 0) - adjust_fire_stacks(-0.1) //the fire is slowly consumed - else - ExtinguishMob() - return - var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment - if(!G.gases["o2"] || G.gases["o2"][MOLES] < 1) - ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return - var/turf/location = get_turf(src) - location.hotspot_expose(700, 50, 1) - /mob/living/fire_act() adjust_fire_stacks(3) IgniteMob() - -//Share fire evenly between the two mobs -//Called in MobBump() and Crossed() -/mob/living/proc/spreadFire(mob/living/L) - if(!istype(L)) - return - var/L_old_on_fire = L.on_fire - - if(on_fire) //Only spread fire stacks if we're on fire - fire_stacks /= 2 - L.fire_stacks += fire_stacks - if(L.IgniteMob()) - log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire") - - if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them - L.fire_stacks /= 2 - fire_stacks += L.fire_stacks - IgniteMob() - -//Mobs on Fire end - -/mob/living/acid_act(acidpwr, toxpwr, acid_volume) - take_organ_damage(min(10*toxpwr, acid_volume * toxpwr)) - /mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0) if(user == src || anchored) return 0 @@ -216,8 +154,7 @@ add_logs(user, src, "grabbed", addition="aggressively") visible_message("[user] has grabbed [src] aggressively!", \ "[user] has grabbed [src] aggressively!") - drop_r_hand() - drop_l_hand() + drop_all_held_items() stop_pulling() if(GRAB_NECK) visible_message("[user] has grabbed [src] by the neck!",\ @@ -292,7 +229,6 @@ return 0 /mob/living/attack_larva(mob/living/carbon/alien/larva/L) - switch(L.a_intent) if("help") visible_message("[L.name] rubs its head against [src].") @@ -332,60 +268,71 @@ M.do_attack_animation(src) return 1 -/mob/living/incapacitated(ignore_restraints, ignore_grab) - if(stat || paralysis || stunned || weakened || (!ignore_restraints && restrained(ignore_grab))) - return 1 +/mob/living/ex_act(severity, origin) + if(istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) + return + ..() + flash_act() //Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs. -/mob/living/proc/add_stun_absorption(key, duration, priority, message, self_message, examine_message) -//adds a stun absorption with a key, a duration in deciseconds, its priority, and the messages it makes when you're stunned/examined, if any - if(!islist(stun_absorption)) - stun_absorption = list() - if(stun_absorption[key]) - stun_absorption[key]["end_time"] = world.time + duration - stun_absorption[key]["priority"] = priority - stun_absorption[key]["stuns_absorbed"] = 0 +/mob/living/acid_act(acidpwr, toxpwr, acid_volume) + take_bodypart_damage(min(10*toxpwr, acid_volume * toxpwr)) + + +/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) + if(shock_damage > 0) + adjustFireLoss(shock_damage) + visible_message( + "[src] was shocked by \the [source]!", \ + "You feel a powerful shock coursing through your body!", \ + "You hear a heavy electrical crack." \ + ) + return shock_damage + +/mob/living/emp_act(severity) + var/list/L = src.get_contents() + for(var/obj/O in L) + O.emp_act(severity) + ..() + +/mob/living/singularity_act() + var/gain = 20 + investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! + gib() + return(gain) + +/mob/living/narsie_act() + if(is_servant_of_ratvar(src) && !stat) + src << "You resist Nar-Sie's influence... but not all of it. Run!" + adjustBruteLoss(35) + if(src && reagents) + reagents.add_reagent("heparin", 5) + return 0 + if(client) + makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, null, 0) else - stun_absorption[key] = list("end_time" = world.time + duration, "priority" = priority, "stuns_absorbed" = 0, \ - "visible_message" = message, "self_message" = self_message, "examine_message" = examine_message) + new /mob/living/simple_animal/hostile/construct/harvester/hostile(get_turf(src)) + spawn_dust() + gib() -/mob/living/Stun(amount, updating = 1, ignore_canstun = 0) - if(!stat && islist(stun_absorption)) - var/priority_absorb_key - var/highest_priority - for(var/i in stun_absorption) - if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority)) - priority_absorb_key = stun_absorption[i] - highest_priority = stun_absorption[i]["priority"] - if(priority_absorb_key) - if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"]) - if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"]) - visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]") - else if(priority_absorb_key["visible_message"]) - visible_message("[src][priority_absorb_key["visible_message"]]") - else if(priority_absorb_key["self_message"]) - src << "[priority_absorb_key["self_message"]]" - priority_absorb_key["stuns_absorbed"] += amount - return 0 - ..() -/mob/living/Weaken(amount, updating = 1, ignore_canweaken = 0) - if(!stat && islist(stun_absorption)) - var/priority_absorb_key - var/highest_priority - for(var/i in stun_absorption) - if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority)) - priority_absorb_key = stun_absorption[i] - highest_priority = priority_absorb_key["priority"] - if(priority_absorb_key) - if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"]) - if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"]) - visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]") - else if(priority_absorb_key["visible_message"]) - visible_message("[src][priority_absorb_key["visible_message"]]") - else if(priority_absorb_key["self_message"]) - src << "[priority_absorb_key["self_message"]]" - priority_absorb_key["stuns_absorbed"] += amount - return 0 - ..() +/mob/living/ratvar_act() + if(!add_servant_of_ratvar(src) && !is_servant_of_ratvar(src)) + src << "A blinding light boils you alive! Run!" + adjustFireLoss(35) + if(src) + adjust_fire_stacks(1) + IgniteMob() + + +//called when the mob receives a bright flash +/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) + if(get_eye_protection() < intensity && (override_blindness_check || !(disabilities & BLIND))) + overlay_fullscreen("flash", type) + addtimer(src, "clear_fullscreen", 25, FALSE, "flash", 25) + return 1 + +//called when the mob receives a loud bang +/mob/living/proc/soundbang_act() + return 0 diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index ed3306a95d1..06e5ad4ff7f 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -266,14 +266,15 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN) /mob/living/proc/radio(message, message_mode, list/spans) switch(message_mode) if(MODE_R_HAND) - if (r_hand) - r_hand.talk_into(src, message, , spans) - return ITALICS | REDUCE_RANGE - + for(var/obj/item/r_hand in get_held_items_for_side("r", all = TRUE)) + if (r_hand) + r_hand.talk_into(src, message, , spans) + return ITALICS | REDUCE_RANGE if(MODE_L_HAND) - if (l_hand) - l_hand.talk_into(src, message, , spans) - return ITALICS | REDUCE_RANGE + for(var/obj/item/l_hand in get_held_items_for_side("l", all = TRUE)) + if (l_hand) + l_hand.talk_into(src, message, , spans) + return ITALICS | REDUCE_RANGE if(MODE_INTERCOM) for (var/obj/item/device/radio/intercom/I in view(1, null)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index b19c799ee37..7cd4e02e618 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -351,39 +351,9 @@ var/list/ai_list = list() SSshuttle.cancelEvac(src) return -/mob/living/silicon/ai/blob_act(obj/effect/blob/B) - if (stat != DEAD) - adjustBruteLoss(60) - updatehealth() - return 1 - return 0 - /mob/living/silicon/ai/restrained(ignore_grab) . = 0 -/mob/living/silicon/ai/emp_act(severity) - if (prob(30)) - switch(pick(1,2)) - if(1) - view_core() - if(2) - SSshuttle.requestEvac(src,"ALERT: Energy surge detected in AI core! Station integrity may be compromised! Initiati--%m091#ar-BZZT") - ..() - -/mob/living/silicon/ai/ex_act(severity, target) - ..() - - switch(severity) - if(1) - gib() - if(2) - if (stat != DEAD) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3) - if (stat != DEAD) - adjustBruteLoss(30) - /mob/living/silicon/ai/Topic(href, href_list) if(usr != src) return @@ -455,18 +425,6 @@ var/list/ai_list = list() if(M) M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself. -/mob/living/silicon/ai/bullet_act(obj/item/projectile/Proj) - ..(Proj) - updatehealth() - return 2 - - -/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) - if(!ticker || !ticker.mode) - M << "You cannot attack people before the game has started." - return - - ..() /mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C) @@ -790,9 +748,6 @@ var/list/ai_list = list() return //won't work if dead set_autosay() -/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user) - return - /mob/living/silicon/ai/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card) if(!..()) return @@ -809,14 +764,6 @@ var/list/ai_list = list() src << "You have been downloaded to a mobile storage device. Remote device connection severed." user << "Transfer successful: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." -/mob/living/silicon/ai/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0) - return // no eyes, no flashing - -/mob/living/silicon/ai/attackby(obj/item/weapon/W, mob/user, params) - if(W.force && W.damtype != STAMINA && src.stat != DEAD) //only sparks if real damage is dealt. - spark_system.start() - return ..() - /mob/living/silicon/ai/can_buckle() return 0 diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm new file mode 100644 index 00000000000..771a6d7c2f5 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_defense.dm @@ -0,0 +1,55 @@ + +/mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone) + if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. + spark_system.start() + return ..() + + +/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) + if(!ticker || !ticker.mode) + M << "You cannot attack people before the game has started." + return + ..() + +/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user) + return //immune to slimes + +/mob/living/silicon/ai/blob_act(obj/effect/blob/B) + if (stat != DEAD) + adjustBruteLoss(60) + updatehealth() + return 1 + return 0 + +/mob/living/silicon/ai/emp_act(severity) + if (prob(30)) + switch(pick(1,2)) + if(1) + view_core() + if(2) + SSshuttle.requestEvac(src,"ALERT: Energy surge detected in AI core! Station integrity may be compromised! Initiati--%m091#ar-BZZT") + ..() + +/mob/living/silicon/ai/ex_act(severity, target) + ..() + + switch(severity) + if(1) + gib() + if(2) + if (stat != DEAD) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3) + if (stat != DEAD) + adjustBruteLoss(30) + + + +/mob/living/silicon/ai/bullet_act(obj/item/projectile/Proj) + ..(Proj) + updatehealth() + return 2 + +/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0) + return // no eyes, no flashing diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm new file mode 100644 index 00000000000..181a166bb54 --- /dev/null +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -0,0 +1,36 @@ + +/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) + var/hit_percent = (100-blocked)/100 + if(!damage || (hit_percent <= 0)) + return 0 + switch(damagetype) + if(BRUTE) + adjustBruteLoss(damage * hit_percent) + if(BURN) + adjustFireLoss(damage * hit_percent) + return 1 + + +/mob/living/silicon/apply_effect(effect = 0,effecttype = STUN, blocked = 0) + return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now + + + +/mob/living/silicon/adjustToxLoss(amount, updating_health=1) //immune to tox damage + return 0 + +/mob/living/silicon/setToxLoss(amount, updating_health=1) + return 0 + +/mob/living/silicon/adjustCloneLoss(amount) //immune to clone damage + return 0 + +/mob/living/silicon/setCloneLoss(amount, updating_health=1) + return 0 + +/mob/living/silicon/adjustStaminaLoss(amount, updating_stamina = 1)//immune to stamina damage. + return + +/mob/living/silicon/setStaminaLoss(amount, updating_stamina = 1) + return + diff --git a/code/modules/mob/living/silicon/death.dm b/code/modules/mob/living/silicon/death.dm index 02fb54012b1..ebd3067bb0a 100644 --- a/code/modules/mob/living/silicon/death.dm +++ b/code/modules/mob/living/silicon/death.dm @@ -1,5 +1,5 @@ /mob/living/silicon/spawn_gibs() - robogibs(loc, viruses) + new /obj/effect/gibspawner/robot(loc,viruses) /mob/living/silicon/spawn_dust() new /obj/effect/decal/remains/robot(loc) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index ea83dce7e1d..018c05e9800 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -94,66 +94,11 @@ else stat(null, text("Systems nonfunctional")) -/mob/living/silicon/pai/blob_act(obj/effect/blob/B) - return 0 - /mob/living/silicon/pai/restrained(ignore_grab) . = 0 -/mob/living/silicon/pai/emp_act(severity) - // 20% chance to kill - // Silence for 2 minutes - // 33% chance to unbind - // 33% chance to change prime directive (based on severity) - // 33% chance of no additional effect - - if(prob(20)) - visible_message("A shower of sparks spray from [src]'s inner workings.", 3, "You hear and smell the ozone hiss of electrical sparks being expelled violently.", 2) - return src.death(0) - - silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes - src << "Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete." - - switch(pick(1,2,3)) - if(1) - src.master = null - src.master_dna = null - src << "You feel unbound." - if(2) - var/command - if(severity == 1) - command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze") - else - command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze") - src.laws.zeroth = "[command] your master." - src << "Pr1m3 d1r3c71v3 uPd473D." - if(3) - src << "You feel an electric surge run through your circuitry and become acutely aware at how lucky you are that you can still feel at all." - -/mob/living/silicon/pai/ex_act(severity, target) - ..() - - switch(severity) - if(1) - if (src.stat != 2) - adjustBruteLoss(100) - adjustFireLoss(100) - if(2) - if (src.stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3) - if (src.stat != 2) - adjustBruteLoss(30) - - return - - // See software.dm for Topic() -/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default - return - /mob/living/silicon/pai/canUseTopic(atom/movable/M) return 1 /* diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm new file mode 100644 index 00000000000..5cdbebfd995 --- /dev/null +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -0,0 +1,49 @@ + +/mob/living/silicon/pai/blob_act(obj/effect/blob/B) + return 0 + +/mob/living/silicon/pai/emp_act(severity) + // 20% chance to kill + // Silence for 2 minutes + // 33% chance to unbind + // 33% chance to change prime directive (based on severity) + // 33% chance of no additional effect + + if(prob(20)) + visible_message("A shower of sparks spray from [src]'s inner workings.", 3, "You hear and smell the ozone hiss of electrical sparks being expelled violently.", 2) + return src.death(0) + + silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes + src << "Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete." + + switch(pick(1,2,3)) + if(1) + src.master = null + src.master_dna = null + src << "You feel unbound." + if(2) + var/command + if(severity == 1) + command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze") + else + command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze") + src.laws.zeroth = "[command] your master." + src << "Pr1m3 d1r3c71v3 uPd473D." + if(3) + src << "You feel an electric surge run through your circuitry and become acutely aware at how lucky you are that you can still feel at all." + +/mob/living/silicon/pai/ex_act(severity, target) + ..() + + switch(severity) + if(1) + if (src.stat != 2) + adjustBruteLoss(100) + adjustFireLoss(100) + if(2) + if (src.stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3) + if (src.stat != 2) + adjustBruteLoss(30) diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index ca980e86bf5..fa94450b748 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -1,7 +1,4 @@ -/mob/living/silicon/robot/spawn_gibs() - robogibs(loc, viruses) - /mob/living/silicon/robot/gib_animation() PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-r")) diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm index 44eb229d7ba..a05838f81ea 100644 --- a/code/modules/mob/living/silicon/robot/examine.dm +++ b/code/modules/mob/living/silicon/robot/examine.dm @@ -3,7 +3,7 @@ if(desc) msg += "[desc]\n" - var/obj/act_module = get_active_hand() + var/obj/act_module = get_active_held_item() if(act_module) msg += "It is holding \icon[act_module] \a [act_module].\n" msg += "" @@ -48,4 +48,4 @@ user << msg - ..() \ No newline at end of file + ..() diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 55276e7807b..71aaaf15df1 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -2,7 +2,7 @@ //as they handle all relevant stuff like adding it to the player's screen and such //Returns the thing in our active hand (whatever is in our active module-slot, in this case) -/mob/living/silicon/robot/get_active_hand() +/mob/living/silicon/robot/get_active_held_item() return module_active diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 33f24c1dc0b..d0350a7a267 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -106,10 +106,6 @@ if(on_fire) add_overlay(image("icon"='icons/mob/OnFire.dmi', "icon_state"="Generic_mob_burning")) -/mob/living/silicon/robot/fire_act() - if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them - IgniteMob() - /mob/living/silicon/robot/update_canmove() if(stat || buckled || lockcharge) canmove = 0 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 810cca481f8..76f8e90ef6e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -14,7 +14,7 @@ var/custom_name = "" var/braintype = "Cyborg" var/modtype = "robot" - var/obj/item/robot_parts/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. + var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. var/obj/item/device/mmi/mmi = null //Hud stuff @@ -24,6 +24,7 @@ var/obj/screen/inv3 = null var/obj/screen/lamp_button = null var/obj/screen/thruster_button = null + var/obj/screen/hands = null var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not var/obj/screen/robot_modules_background @@ -365,16 +366,6 @@ if(thruster_button) thruster_button.icon_state = "ionpulse[ionpulse_on]" -/mob/living/silicon/robot/blob_act(obj/effect/blob/B) - if (stat != 2) - adjustBruteLoss(60) - updatehealth() - return 1 - else - gib() - return 1 - return 0 - /mob/living/silicon/robot/Stat() ..() if(statpanel("Status")) @@ -393,27 +384,6 @@ /mob/living/silicon/robot/restrained(ignore_grab) . = 0 -/mob/living/silicon/robot/ex_act(severity, target) - switch(severity) - if(1) - gib() - return - if(2) - if (stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3) - if (stat != 2) - adjustBruteLoss(30) - return - - -/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj) - ..(Proj) - updatehealth() - if(prob(75) && Proj.damage > 0) spark_system.start() - return 2 - /mob/living/silicon/robot/triggerAlarm(class, area/A, O, obj/alarmsource) if(alarmsource.z != z) return @@ -621,83 +591,6 @@ else return ..() -/mob/living/silicon/robot/attacked_by(obj/item/I, mob/living/user, def_zone) - if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. - spark_system.start() - return ..() - - -/mob/living/silicon/robot/emag_act(mob/user) - if(user != src)//To prevent syndieborgs from emagging themselves - if(!opened)//Cover is closed - if(locked) - user << "You emag the cover lock." - locked = 0 - else - user << "The cover is already unlocked!" - return - if(opened)//Cover is open - if((world.time - 100) < emag_cooldown) - return - - if(syndicate) - user << "You emag [src]'s interface." - src << "ALERT: Foreign software execution prevented." - log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] but they were a syndicate cyborg.") - emag_cooldown = world.time - return - - var/ai_is_antag = 0 - if(connected_ai && connected_ai.mind) - if(connected_ai.mind.special_role) - ai_is_antag = (connected_ai.mind.special_role == "traitor") - if(ai_is_antag) - user << "You emag [src]'s interface." - src << "ALERT: Foreign software execution prevented." - connected_ai << "ALERT: Cyborg unit \[[src]] successfuly defended against subversion." - log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] slaved to traitor AI [connected_ai].") - emag_cooldown = world.time - return - - if(wiresexposed) - user << "You must unexpose the wires first!" - return - else - emag_cooldown = world.time - sleep(6) - SetEmagged(1) - SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown - lawupdate = 0 - connected_ai = null - user << "You emag [src]'s interface." - message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") - log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") - clear_supplied_laws() - clear_inherent_laws() - clear_zeroth_law(0) - laws = new /datum/ai_laws/syndicate_override - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") - set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") - src << "ALERT: Foreign software detected." - sleep(5) - src << "Initiating diagnostics..." - sleep(20) - src << "SynBorg v1.7 loaded." - sleep(5) - src << "LAW SYNCHRONISATION ERROR" - sleep(5) - src << "Would you like to send a report to NanoTraSoft? Y/N" - sleep(10) - src << "> N" - sleep(20) - src << "ERRORERRORERROR" - src << "Obey these laws:" - laws.show_laws(src) - src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." - SetLockdown(0) - update_icons() - /mob/living/silicon/robot/verb/unlock_own_cover() set category = "Robot Commands" set name = "Unlock Cover" @@ -711,65 +604,6 @@ update_icons() usr << "You unlock your cover." -/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) - if (M.a_intent =="disarm") - if(!(lying)) - M.do_attack_animation(src) - if(get_active_hand()) - uneq_active() - visible_message("[M] disarmed [src]!", \ - "[M] has disabled [src]'s active module!") - add_logs(M, src, "disarmed") - else - Stun(2) - step(src,get_dir(M,src)) - add_logs(M, src, "pushed") - visible_message("[M] has forced back [src]!", \ - "[M] has forced back [src]!") - playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) - else - ..() - return - -/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime shock - flash_eyes() - var/stunprob = M.powerlevel * 7 + 10 - if(prob(stunprob) && M.powerlevel >= 8) - adjustBruteLoss(M.powerlevel * rand(6,10)) - - var/damage = rand(1, 3) - - if(M.is_adult) - damage = rand(20, 40) - else - damage = rand(5, 35) - damage = round(damage / 2) // borgs recieve half damage - adjustBruteLoss(damage) - updatehealth() - - return - -/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user) - add_fingerprint(user) - if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) - if(cell) - cell.updateicon() - cell.add_fingerprint(user) - user.put_in_active_hand(cell) - user << "You remove \the [cell]." - cell = null - update_icons() - diag_hud_set_borgcell() - - if(!opened) - if(..()) // hulk attack - spark_system.start() - spawn(0) - step_away(src,user,15) - sleep(3) - step_away(src,user,15) - /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all if(check_access(null)) @@ -777,13 +611,13 @@ if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M //if they are holding or wearing a card that has access, that works - if(check_access(H.get_active_hand()) || check_access(H.wear_id)) + if(check_access(H.get_active_held_item()) || check_access(H.wear_id)) return 1 else if(istype(M, /mob/living/carbon/monkey)) var/mob/living/carbon/monkey/george = M //they can only hold things :( - if(istype(george.get_active_hand(), /obj/item)) - return check_access(george.get_active_hand()) + if(istype(george.get_active_held_item(), /obj/item)) + return check_access(george.get_active_held_item()) return 0 /mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I) @@ -1033,7 +867,7 @@ if(incapacitated()) return - var/obj/item/W = get_active_hand() + var/obj/item/W = get_active_held_item() if(W) W.attack_self(src) @@ -1135,14 +969,14 @@ robot_suit.head = null robot_suit.updateicon() else - new /obj/item/robot_parts/robot_suit(T) - new /obj/item/robot_parts/l_leg(T) - new /obj/item/robot_parts/r_leg(T) + new /obj/item/robot_suit(T) + new /obj/item/bodypart/l_leg/robot(T) + new /obj/item/bodypart/r_leg/robot(T) new /obj/item/stack/cable_coil(T, 1) - new /obj/item/robot_parts/chest(T) - new /obj/item/robot_parts/l_arm(T) - new /obj/item/robot_parts/r_arm(T) - new /obj/item/robot_parts/head(T) + new /obj/item/bodypart/chest/robot(T) + new /obj/item/bodypart/l_arm/robot(T) + new /obj/item/bodypart/r_arm/robot(T) + new /obj/item/bodypart/head/robot(T) var/b for(b=0, b!=2, b++) var/obj/item/device/assembly/flash/handheld/F = new /obj/item/device/assembly/flash/handheld(T) @@ -1286,22 +1120,6 @@ diag_hud_set_health() update_health_hud() -/mob/living/silicon/robot/fully_replace_character_name(oldname, newname) - ..() - if(oldname != real_name) - notify_ai(3, oldname, newname) - if(camera) - camera.c_tag = real_name - custom_name = newname - -/mob/living/silicon/robot/emp_act(severity) - switch(severity) - if(1) - Stun(8) - if(2) - Stun(3) - ..() - /mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0) if(..()) //successfully ressuscitated from death if(camera && !wires.is_cut(WIRE_CAMERA)) @@ -1312,6 +1130,13 @@ notify_ai(1) . = 1 +/mob/living/silicon/robot/fully_replace_character_name(oldname, newname) + ..() + if(oldname != real_name) + notify_ai(3, oldname, newname) + if(camera) + camera.c_tag = real_name + custom_name = newname /mob/living/silicon/robot/proc/ResetModule() diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm new file mode 100644 index 00000000000..7fa7a720d42 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -0,0 +1,182 @@ + + +/mob/living/silicon/robot/attacked_by(obj/item/I, mob/living/user, def_zone) + if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt. + spark_system.start() + return ..() + +/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) + if (M.a_intent =="disarm") + if(!(lying)) + M.do_attack_animation(src) + if(get_active_held_item()) + uneq_active() + visible_message("[M] disarmed [src]!", \ + "[M] has disabled [src]'s active module!") + add_logs(M, src, "disarmed") + else + Stun(2) + step(src,get_dir(M,src)) + add_logs(M, src, "pushed") + visible_message("[M] has forced back [src]!", \ + "[M] has forced back [src]!") + playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) + else + ..() + return + +/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) + if(..()) //successful slime shock + flash_act() + var/stunprob = M.powerlevel * 7 + 10 + if(prob(stunprob) && M.powerlevel >= 8) + adjustBruteLoss(M.powerlevel * rand(6,10)) + + var/damage = rand(1, 3) + + if(M.is_adult) + damage = rand(20, 40) + else + damage = rand(5, 35) + damage = round(damage / 2) // borgs recieve half damage + adjustBruteLoss(damage) + updatehealth() + + return + +/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user) + add_fingerprint(user) + if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) + if(cell) + cell.updateicon() + cell.add_fingerprint(user) + user.put_in_active_hand(cell) + user << "You remove \the [cell]." + cell = null + update_icons() + diag_hud_set_borgcell() + + if(!opened) + if(..()) // hulk attack + spark_system.start() + spawn(0) + step_away(src,user,15) + sleep(3) + step_away(src,user,15) + +/mob/living/silicon/robot/fire_act() + if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them + IgniteMob() + + +/mob/living/silicon/robot/emp_act(severity) + switch(severity) + if(1) + Stun(8) + if(2) + Stun(3) + ..() + + +/mob/living/silicon/robot/emag_act(mob/user) + if(user != src)//To prevent syndieborgs from emagging themselves + if(!opened)//Cover is closed + if(locked) + user << "You emag the cover lock." + locked = 0 + else + user << "The cover is already unlocked!" + return + if(opened)//Cover is open + if((world.time - 100) < emag_cooldown) + return + + if(syndicate) + user << "You emag [src]'s interface." + src << "ALERT: Foreign software execution prevented." + log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] but they were a syndicate cyborg.") + emag_cooldown = world.time + return + + var/ai_is_antag = 0 + if(connected_ai && connected_ai.mind) + if(connected_ai.mind.special_role) + ai_is_antag = (connected_ai.mind.special_role == "traitor") + if(ai_is_antag) + user << "You emag [src]'s interface." + src << "ALERT: Foreign software execution prevented." + connected_ai << "ALERT: Cyborg unit \[[src]] successfuly defended against subversion." + log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] slaved to traitor AI [connected_ai].") + emag_cooldown = world.time + return + + if(wiresexposed) + user << "You must unexpose the wires first!" + return + else + emag_cooldown = world.time + sleep(6) + SetEmagged(1) + SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown + lawupdate = 0 + connected_ai = null + user << "You emag [src]'s interface." + message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") + log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") + clear_supplied_laws() + clear_inherent_laws() + clear_zeroth_law(0) + laws = new /datum/ai_laws/syndicate_override + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") + set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") + src << "ALERT: Foreign software detected." + sleep(5) + src << "Initiating diagnostics..." + sleep(20) + src << "SynBorg v1.7 loaded." + sleep(5) + src << "LAW SYNCHRONISATION ERROR" + sleep(5) + src << "Would you like to send a report to NanoTraSoft? Y/N" + sleep(10) + src << "> N" + sleep(20) + src << "ERRORERRORERROR" + src << "Obey these laws:" + laws.show_laws(src) + src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." + SetLockdown(0) + update_icons() + + +/mob/living/silicon/robot/blob_act(obj/effect/blob/B) + if (stat != 2) + adjustBruteLoss(60) + updatehealth() + return 1 + else + gib() + return 1 + return 0 + +/mob/living/silicon/robot/ex_act(severity, target) + switch(severity) + if(1) + gib() + return + if(2) + if (stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3) + if (stat != 2) + adjustBruteLoss(30) + return + + +/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj) + ..(Proj) + updatehealth() + if(prob(75) && Proj.damage > 0) spark_system.start() + return 2 diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 981f17a4b5e..fe2f2c5a5d1 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -142,34 +142,6 @@ /mob/living/silicon/drop_item() return -/mob/living/silicon/emp_act(severity) - switch(severity) - if(1) - src.take_organ_damage(20) - if(2) - src.take_organ_damage(10) - src << "*BZZZT*" - src << "Warning: Electromagnetic pulse detected." - flash_eyes(affect_silicon = 1) - ..() - -/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) - blocked = (100-blocked)/100 - if(!damage || (blocked <= 0)) - return 0 - switch(damagetype) - if(BRUTE) - adjustBruteLoss(damage * blocked) - if(BURN) - adjustFireLoss(damage * blocked) - else - return 1 - updatehealth() - return 1 - -/mob/living/silicon/proc/damage_mob(brute = 0, fire = 0, tox = 0) - return - /mob/living/silicon/can_inject(mob/user, error_msg) if(error_msg) user << "Their outer shell is too tough." @@ -178,35 +150,6 @@ /mob/living/silicon/IsAdvancedToolUser() return 1 -/mob/living/silicon/bullet_act(obj/item/projectile/Proj) - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - adjustBruteLoss(Proj.damage) - Proj.on_hit(src) - return 2 - -/mob/living/silicon/apply_effect(effect = 0,effecttype = STUN, blocked = 0) - return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now -/* - if(!effect || (blocked >= 2)) - return 0 - switch(effecttype) - if(STUN) - stunned = max(stunned,(effect/(blocked+1))) - if(WEAKEN) - weakened = max(weakened,(effect/(blocked+1))) - if(PARALYZE) - paralysis = max(paralysis,(effect/(blocked+1))) - if(IRRADIATE) - radiation += min((effect - (effect*getarmor(null, "rad"))), 0)//Rads auto check armor - if(STUTTER) - stuttering = max(stuttering,(effect/(blocked+1))) - if(EYE_BLUR) - blur_eyes(effect/(blocked+1)) - if(DROWSY) - drowsyness = max(drowsyness,(effect/(blocked+1))) - updatehealth() - return 1*/ - /proc/islinked(mob/living/silicon/robot/bot, mob/living/silicon/ai/ai) if(!istype(bot) || !istype(ai)) return 0 @@ -421,87 +364,10 @@ src << "Sensor augmentations disabled." -/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent - var/damage = 20 - if (prob(90)) - add_logs(M, src, "attacked") - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") - if(prob(8)) - flash_eyes(affect_silicon = 1) - add_logs(M, src, "attacked") - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - visible_message("[M] took a swipe at [src]!", \ - "[M] took a swipe at [src]!") - -/mob/living/silicon/attack_animal(mob/living/simple_animal/M) - if(..()) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - switch(M.melee_damage_type) - if(BRUTE) - adjustBruteLoss(damage) - if(BURN) - adjustFireLoss(damage) - if(TOX) - adjustToxLoss(damage) - if(OXY) - adjustOxyLoss(damage) - if(CLONE) - adjustCloneLoss(damage) - if(STAMINA) - adjustStaminaLoss(damage) - updatehealth() - -/mob/living/silicon/attack_paw(mob/living/user) - return attack_hand(user) - -/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L) - if(L.a_intent == "help") - visible_message("[L.name] rubs its head against [src].") - -/mob/living/silicon/attack_hulk(mob/living/carbon/human/user) - if(user.a_intent == "harm") - ..(user, 1) - adjustBruteLoss(rand(10, 15)) - playsound(loc, "punch", 25, 1, -1) - visible_message("[user] has punched [src]!", \ - "[user] has punched [src]!") - return 1 - return 0 - -/mob/living/silicon/attack_hand(mob/living/carbon/human/M) - switch(M.a_intent) - if ("help") - M.visible_message("[M] pets [src].", \ - "You pet [src].") - if("grab") - grabbedby(M) - else - M.do_attack_animation(src) - playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) - visible_message("[M] punches [src], but doesn't leave a dent.", \ - "[M] punches [src], but doesn't leave a dent.") - return 0 - /mob/living/silicon/proc/GetPhoto() if (aicamera) return aicamera.selectpicture(aicamera) -/mob/living/silicon/grippedby(mob/living/user) - return - -/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise) - if(affect_silicon) - return ..() - -/mob/living/silicon/check_ear_prot() - return 1 - /mob/living/silicon/update_transform() var/matrix/ntransform = matrix(transform) //aka transform.Copy() var/changed = 0 @@ -516,6 +382,3 @@ /mob/living/silicon/is_literate() return 1 - -/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) - return 0 diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm new file mode 100644 index 00000000000..b216c04e1ab --- /dev/null +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -0,0 +1,97 @@ + +/mob/living/silicon/grippedby(mob/living/user) + return //can't upgrade a simple pull into a more aggressive grab. + +/mob/living/silicon/get_ear_protection()//no ears + return 2 + +/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M) + if(..()) //if harm or disarm intent + var/damage = 20 + if (prob(90)) + add_logs(M, src, "attacked") + playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!") + if(prob(8)) + flash_act(affect_silicon = 1) + add_logs(M, src, "attacked") + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + visible_message("[M] took a swipe at [src]!", \ + "[M] took a swipe at [src]!") + +/mob/living/silicon/attack_animal(mob/living/simple_animal/M) + if(..()) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + switch(M.melee_damage_type) + if(BRUTE) + adjustBruteLoss(damage) + if(BURN) + adjustFireLoss(damage) + if(TOX) + adjustToxLoss(damage) + if(OXY) + adjustOxyLoss(damage) + if(CLONE) + adjustCloneLoss(damage) + if(STAMINA) + adjustStaminaLoss(damage) + updatehealth() + +/mob/living/silicon/attack_paw(mob/living/user) + return attack_hand(user) + +/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L) + if(L.a_intent == "help") + visible_message("[L.name] rubs its head against [src].") + +/mob/living/silicon/attack_hulk(mob/living/carbon/human/user) + if(user.a_intent == "harm") + ..(user, 1) + adjustBruteLoss(rand(10, 15)) + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has punched [src]!", \ + "[user] has punched [src]!") + return 1 + return 0 + +/mob/living/silicon/attack_hand(mob/living/carbon/human/M) + switch(M.a_intent) + if ("help") + M.visible_message("[M] pets [src].", \ + "You pet [src].") + if("grab") + grabbedby(M) + else + M.do_attack_animation(src) + playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) + visible_message("[M] punches [src], but doesn't leave a dent.", \ + "[M] punches [src], but doesn't leave a dent.") + return 0 + +/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) + return 0 //So borgs they don't die trying to fix wiring + +/mob/living/silicon/emp_act(severity) + switch(severity) + if(1) + src.take_bodypart_damage(20) + if(2) + src.take_bodypart_damage(10) + src << "*BZZZT*" + src << "Warning: Electromagnetic pulse detected." + flash_act(affect_silicon = 1) + ..() + +/mob/living/silicon/bullet_act(obj/item/projectile/Proj) + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + adjustBruteLoss(Proj.damage) + Proj.on_hit(src) + return 2 + +/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise) + if(affect_silicon) + return ..() diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm new file mode 100644 index 00000000000..53dd3b50454 --- /dev/null +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -0,0 +1,117 @@ + + +/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) + ..() + switch(M.a_intent) + + if("help") + if (health > 0) + visible_message("[M] [response_help] [src].") + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + if("grab") + grabbedby(M) + + if("harm", "disarm") + M.do_attack_animation(src) + visible_message("[M] [response_harm] [src]!") + playsound(loc, attacked_sound, 25, 1, -1) + attack_threshold_check(harm_intent_damage) + add_logs(M, src, "attacked") + updatehealth() + return 1 + +/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M) + if(..()) //successful monkey bite. + if(stat != DEAD) + var/damage = rand(1, 3) + attack_threshold_check(damage) + return 1 + if (M.a_intent == "help") + if (health > 0) + visible_message("[M.name] [response_help] [src].") + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + +/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) + if(..()) //if harm or disarm intent. + if(M.a_intent == "disarm") + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + visible_message("[M] [response_disarm] [name]!", \ + "[M] [response_disarm] [name]!") + add_logs(M, src, "disarmed") + else + var/damage = rand(15, 30) + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!") + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + attack_threshold_check(damage) + add_logs(M, src, "attacked") + return 1 + +/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) + if(..()) //successful larva bite + var/damage = rand(5, 10) + if(stat != DEAD) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + attack_threshold_check(damage) + return 1 + +/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) + if(..()) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + attack_threshold_check(damage,M.melee_damage_type) + return 1 + +/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M) + if(..()) //successful slime attack + var/damage = rand(15, 25) + if(M.is_adult) + damage = rand(20, 35) + attack_threshold_check(damage) + return 1 + +/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE) + if(!damage_coeff[damagetype]) + damage = 0 + else + damage *= damage_coeff[damagetype] + + if(damage >= 0 && damage <= force_threshold) + visible_message("[src] looks unharmed.") + else + adjustHealth(damage * config.damage_multiplier) + + +/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + apply_damage(Proj.damage, Proj.damage_type) + Proj.on_hit(src) + return 0 + +/mob/living/simple_animal/ex_act(severity, target) + ..() + var/bomb_armor = getarmor(null, "bomb") + switch (severity) + if (1) + if(prob(bomb_armor)) + adjustBruteLoss(500) + else + gib() + return + if (2) + var/bloss = 60 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) + + if(3) + var/bloss = 30 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) + +/mob/living/simple_animal/blob_act(obj/effect/blob/B) + adjustBruteLoss(20) + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 4cf22a7acda..d3cc4116ffb 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -257,7 +257,7 @@ new /obj/item/device/assembly/prox_sensor(Tsec) if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) + new /obj/item/bodypart/l_arm/robot(Tsec) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index cc05c511030..63a58a5f705 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -15,7 +15,7 @@ /obj/item/weapon/bucket_sensor/attackby(obj/item/W, mob/user as mob, params) ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + if(istype(W, /obj/item/bodypart/l_arm/robot) || istype(W, /obj/item/bodypart/r_arm/robot)) if(!user.unEquip(W)) return qdel(W) @@ -60,7 +60,7 @@ switch(build_step) if(0,1) - if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg)) + if(istype(W, /obj/item/bodypart/l_leg/robot) || istype(W, /obj/item/bodypart/r_leg/robot)) if(!user.unEquip(W)) return qdel(W) @@ -261,7 +261,7 @@ /obj/item/weapon/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params) ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + if(istype(W, /obj/item/bodypart/l_arm/robot) || istype(W, /obj/item/bodypart/r_arm/robot)) qdel(W) var/turf/T = get_turf(user.loc) var/mob/living/simple_animal/bot/floorbot/A = new /mob/living/simple_animal/bot/floorbot(T) @@ -295,11 +295,10 @@ if(skin) add_overlay(image('icons/obj/aibots.dmi', "kit_skin_[skin]")) -/obj/item/weapon/storage/firstaid/attackby(obj/item/robot_parts/S, mob/user, params) +/obj/item/weapon/storage/firstaid/attackby(obj/item/bodypart/S, mob/user, params) - if((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) - ..() - return + if((!istype(S, /obj/item/bodypart/l_arm/robot)) && (!istype(S, /obj/item/bodypart/r_arm/robot))) + return ..() //Making a medibot! if(contents.len >= 1) @@ -416,7 +415,7 @@ name = "helmet/signaler/prox sensor assembly" qdel(I) - else if(((istype(I, /obj/item/robot_parts/l_arm)) || (istype(I, /obj/item/robot_parts/r_arm))) && (build_step == 2)) + else if(((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot))) && (build_step == 2)) if(!user.unEquip(I)) return build_step++ @@ -459,6 +458,6 @@ else if(build_step == 3) overlays -= "hs_arm" - new /obj/item/robot_parts/l_arm(get_turf(src)) + new /obj/item/bodypart/l_arm/robot(get_turf(src)) user << "You remove the robot arm from [src]." build_step-- \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index d19ce2687a2..fa4e69cf5ee 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -376,9 +376,9 @@ Auto Patrol[]"}, G.update_icon() if(prob(50)) - new /obj/item/robot_parts/l_leg(Tsec) + new /obj/item/bodypart/l_leg/robot(Tsec) if(prob(25)) - new /obj/item/robot_parts/r_leg(Tsec) + new /obj/item/bodypart/r_leg/robot(Tsec) if(prob(25))//50% chance for a helmet OR vest if(prob(50)) new /obj/item/clothing/head/helmet(Tsec) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 8956f7872a6..1d276b2bf3b 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -376,7 +376,7 @@ empty_tiles() if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) + new /obj/item/bodypart/l_arm/robot(Tsec) var/obj/item/stack/tile/plasteel/T = new (Tsec) T.amount = 1 diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index fdf5215ebc3..4d92739db83 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -514,7 +514,7 @@ reagent_glass = null if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) + new /obj/item/bodypart/l_arm/robot(Tsec) if(emagged && prob(25)) playsound(loc, 'sound/voice/minsult.ogg', 50, 0) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index b9d4a7e313d..69be54689f6 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -383,7 +383,7 @@ Auto Patrol: []"}, new /obj/item/weapon/melee/baton(Tsec) if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) + new /obj/item/bodypart/l_arm/robot(Tsec) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm new file mode 100644 index 00000000000..b39bc1bbe19 --- /dev/null +++ b/code/modules/mob/living/simple_animal/damage_procs.dm @@ -0,0 +1,30 @@ + +/mob/living/simple_animal/proc/adjustHealth(amount) + if(status_flags & GODMODE) + return 0 + bruteloss = Clamp(bruteloss + amount, 0, maxHealth) + updatehealth() + return amount + +/mob/living/simple_animal/adjustBruteLoss(amount) + if(damage_coeff[BRUTE]) + . = adjustHealth(amount * damage_coeff[BRUTE] * config.damage_multiplier) + +/mob/living/simple_animal/adjustFireLoss(amount) + if(damage_coeff[BURN]) + . = adjustHealth(amount * damage_coeff[BURN] * config.damage_multiplier) + +/mob/living/simple_animal/adjustOxyLoss(amount) + if(damage_coeff[OXY]) + . = adjustHealth(amount * damage_coeff[OXY] * config.damage_multiplier) + +/mob/living/simple_animal/adjustToxLoss(amount) + if(damage_coeff[TOX]) + . = adjustHealth(amount * damage_coeff[TOX] * config.damage_multiplier) + +/mob/living/simple_animal/adjustCloneLoss(amount) + if(damage_coeff[CLONE]) + . = adjustHealth(amount * damage_coeff[CLONE] * config.damage_multiplier) + +/mob/living/simple_animal/adjustStaminaLoss(amount) + return diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 0c40e06055e..40bda94fb41 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -147,14 +147,14 @@ switch(add_to) if("head") - place_on_head(usr.get_active_hand(),usr) + place_on_head(usr.get_active_held_item(),usr) if("back") if(inventory_back) usr << "It's already wearing something!" return else - var/obj/item/item_to_add = usr.get_active_hand() + var/obj/item/item_to_add = usr.get_active_held_item() if(!item_to_add) usr.visible_message("[usr] pets [src].","You rest your hand on [src]'s back for a moment.") diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index 3e10570986b..2d22e293753 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -144,19 +144,13 @@ /mob/living/simple_animal/drone/examine(mob/user) var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" - //Left hand items - if(l_hand && !(l_hand.flags&ABSTRACT)) - if(l_hand.blood_DNA) - msg += "It is holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in its left hand!\n" - else - msg += "It is holding \icon[l_hand] \a [l_hand] in its left hand.\n" - - //Right hand items - if(r_hand && !(r_hand.flags&ABSTRACT)) - if(r_hand.blood_DNA) - msg += "It is holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in its right hand!\n" - else - msg += "It is holding \icon[r_hand] \a [r_hand] in its right hand.\n" + //Hands + for(var/obj/item/I in held_items) + if(!(I.flags & ABSTRACT)) + if(I.blood_DNA) + msg += "It has \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n" + else + msg += "It has \icon[I] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n" //Internal storage if(internal_storage && !(internal_storage.flags&ABSTRACT)) @@ -244,7 +238,7 @@ /mob/living/simple_animal/drone/handle_temperature_damage() return -/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0) +/mob/living/simple_animal/drone/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0) if(affect_silicon) return ..() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index fba7b98f181..d3d99174436 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -6,65 +6,57 @@ //How the world interacts with drones -/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity) - A.attack_hand(src) +/mob/living/simple_animal/drone/attack_drone(mob/living/simple_animal/drone/D) + if(D != src && stat == DEAD) + var/d_input = alert(D,"Perform which action?","Drone Interaction","Reactivate","Cannibalize","Nothing") + if(d_input) + switch(d_input) + if("Reactivate") + var/mob/dead/observer/G = get_ghost() + if(!client && (!G || !G.client)) + var/list/faux_gadgets = list("hypertext inflator","failsafe directory","DRM switch","stack initializer",\ + "anti-freeze capacitor","data stream diode","TCP bottleneck","supercharged I/O bolt",\ + "tradewind stablizer","radiated XML cable","registry fluid tank","open-source debunker") + + var/list/faux_problems = list("won't be able to tune their bootstrap projector","will constantly remix their binary pool"+\ + " even though the BMX calibrator is working","will start leaking their XSS coolant",\ + "can't tell if their ethernet detour is moving or not", "won't be able to reseed enough"+\ + " kernels to function properly","can't start their neurotube console") + + D << "You can't seem to find the [pick(faux_gadgets)]! Without it, [src] [pick(faux_problems)]." + return + D.visible_message("[D] begins to reactivate [src].", "You begin to reactivate [src]...") + if(do_after(D,30, 1, target = src)) + revive(full_heal = 1) + D.visible_message("[D] reactivates [src]!", "You reactivate [src].") + alert_drones(DRONE_NET_CONNECT) + if(G) + G << "DRONE NETWORK: You were reactivated by [D]!" + else + D << "You need to remain still to reactivate [src]!" + + if("Cannibalize") + if(D.health < D.maxHealth) + D.visible_message("[D] begins to cannibalize parts from [src].", "You begin to cannibalize parts from [src]...") + if(do_after(D, 60, 0, target = src)) + D.visible_message("[D] repairs itself using [src]'s remains!", "You repair yourself using [src]'s remains.") + D.adjustBruteLoss(-src.maxHealth) + new /obj/effect/decal/cleanable/oil/streak(get_turf(src)) + qdel(src) + else + D << "You need to remain still to cannibalize [src]!" + else + D << "You're already in perfect condition!" + if("Nothing") + return /mob/living/simple_animal/drone/attack_hand(mob/user) - if(isdrone(user)) - var/mob/living/simple_animal/drone/D = user - if(D != src) - if(stat == DEAD) - var/d_input = alert(D,"Perform which action?","Drone Interaction","Reactivate","Cannibalize","Nothing") - if(d_input) - switch(d_input) - if("Reactivate") - var/mob/dead/observer/G = get_ghost() - if(!client && (!G || !G.client)) - var/list/faux_gadgets = list("hypertext inflator","failsafe directory","DRM switch","stack initializer",\ - "anti-freeze capacitor","data stream diode","TCP bottleneck","supercharged I/O bolt",\ - "tradewind stablizer","radiated XML cable","registry fluid tank","open-source debunker") - - var/list/faux_problems = list("won't be able to tune their bootstrap projector","will constantly remix their binary pool"+\ - " even though the BMX calibrator is working","will start leaking their XSS coolant",\ - "can't tell if their ethernet detour is moving or not", "won't be able to reseed enough"+\ - " kernels to function properly","can't start their neurotube console") - - D << "You can't seem to find the [pick(faux_gadgets)]! Without it, [src] [pick(faux_problems)]." - return - D.visible_message("[D] begins to reactivate [src].", "You begin to reactivate [src]...") - if(do_after(user,30, 1, target = src)) - revive(full_heal = 1) - D.visible_message("[D] reactivates [src]!", "You reactivate [src].") - alert_drones(DRONE_NET_CONNECT) - if(G) - G << "DRONE NETWORK: You were reactivated by [D]!" - else - D << "You need to remain still to reactivate [src]!" - - if("Cannibalize") - if(D.health < D.maxHealth) - D.visible_message("[D] begins to cannibalize parts from [src].", "You begin to cannibalize parts from [src]...") - if(do_after(D, 60, 0, target = src)) - D.visible_message("[D] repairs itself using [src]'s remains!", "You repair yourself using [src]'s remains.") - D.adjustBruteLoss(-src.maxHealth) - new /obj/effect/decal/cleanable/oil/streak(get_turf(src)) - qdel(src) - else - D << "You need to remain still to cannibalize [src]!" - else - D << "You're already in perfect condition!" - if("Nothing") - return - - return - - if(ishuman(user)) if(stat == DEAD || status_flags & GODMODE) ..() return - if(user.get_active_hand()) + if(user.get_active_held_item()) user << "Your hands are full!" return visible_message("[user] starts picking up [src].", \ @@ -77,16 +69,13 @@ user << "[src] is buckled to [buckled] and cannot be picked up!" return user << "You pick [src] up." - drop_l_hand() - drop_r_hand() + drop_all_held_items() var/obj/item/clothing/head/drone_holder/DH = new /obj/item/clothing/head/drone_holder(src) DH.updateVisualAppearence(src) DH.drone = src user.put_in_hands(DH) forceMove(DH) - return - ..() /mob/living/simple_animal/drone/attackby(obj/item/I, mob/user) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index 5fc07a58efe..44838adbe88 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -49,10 +49,9 @@ if(!istype(I)) return - if(I == l_hand) - l_hand = null - else if(I == r_hand) - r_hand = null + var/index = get_held_index_of_item(I) + if(index) + held_items[index] = null update_inv_hands() if(I.pulledby) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm index 6ebc4d8066c..ca5456e625c 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm @@ -18,10 +18,13 @@ drone_overlays[cache_index] = null -/mob/living/simple_animal/drone/proc/update_inv_hands() +/mob/living/simple_animal/drone/update_inv_hands() remove_overlay(DRONE_HANDS_LAYER) var/list/hands_overlays = list() + var/obj/item/l_hand = get_item_for_held_index(1) + var/obj/item/r_hand = get_item_for_held_index(2) + var/y_shift = getItemPixelShiftY() if(r_hand) @@ -38,7 +41,7 @@ if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) r_hand.layer = ABOVE_HUD_LAYER - r_hand.screen_loc = ui_rhand + r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand)) client.screen |= r_hand if(l_hand) @@ -55,7 +58,7 @@ if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) l_hand.layer = ABOVE_HUD_LAYER - l_hand.screen_loc = ui_lhand + l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand)) client.screen |= l_hand @@ -87,16 +90,6 @@ apply_overlay(DRONE_HEAD_LAYER) - -//These procs serve as redirection so that the drone updates as expected when other things call these procs -/mob/living/simple_animal/drone/update_inv_l_hand() - update_inv_hands() - - -/mob/living/simple_animal/drone/update_inv_r_hand() - update_inv_hands() - - /mob/living/simple_animal/drone/update_inv_wear_mask() update_inv_head() diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 96f074c5dcc..407076bbd4c 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -187,8 +187,7 @@ var/global/list/parasites = list() //all currently existing/living guardians return 1 /mob/living/simple_animal/hostile/guardian/death() - drop_l_hand() - drop_r_hand() + drop_all_held_items() ..() if(summoner) summoner << "Your [name] died somehow!" @@ -243,11 +242,10 @@ var/global/list/parasites = list() //all currently existing/living guardians return FALSE . = TRUE - if(I == l_hand) - l_hand = null - else if(I == r_hand) - r_hand = null - update_inv_hands() + var/index = get_held_index_of_item(I) + if(index) + held_items[index] = null + update_inv_hands() if(I.pulledby) I.pulledby.stop_pulling() @@ -267,9 +265,11 @@ var/global/list/parasites = list() //all currently existing/living guardians overlays -= guardian_overlays[cache_index] guardian_overlays[cache_index] = null -/mob/living/simple_animal/hostile/guardian/proc/update_inv_hands() +/mob/living/simple_animal/hostile/guardian/update_inv_hands() remove_overlay(GUARDIAN_HANDS_LAYER) var/list/hands_overlays = list() + var/obj/item/l_hand = get_item_for_held_index(1) + var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) var/r_state = r_hand.item_state @@ -282,7 +282,7 @@ var/global/list/parasites = list() //all currently existing/living guardians if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) r_hand.layer = ABOVE_HUD_LAYER - r_hand.screen_loc = ui_rhand + r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand)) client.screen |= r_hand if(l_hand) @@ -296,19 +296,13 @@ var/global/list/parasites = list() //all currently existing/living guardians if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) l_hand.layer = ABOVE_HUD_LAYER - l_hand.screen_loc = ui_lhand + l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand)) client.screen |= l_hand if(hands_overlays.len) guardian_overlays[GUARDIAN_HANDS_LAYER] = hands_overlays apply_overlay(GUARDIAN_HANDS_LAYER) -/mob/living/simple_animal/hostile/guardian/update_inv_l_hand() - update_inv_hands() - -/mob/living/simple_animal/hostile/guardian/update_inv_r_hand() - update_inv_hands() - /mob/living/simple_animal/hostile/guardian/regenerate_icons() update_inv_hands() diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 9e1848936ed..33743138b95 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -60,9 +60,7 @@ if(H.check_shields(90, "[name]", src, attack_type = THROWN_PROJECTILE_ATTACK)) blocked = 1 if(!blocked) - - L.drop_r_hand() - L.drop_l_hand() + L.drop_all_held_items() L.visible_message("[src] slams into [L]!", "[src] slams into you!") L.apply_damage(20, BRUTE) playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index 0d2387ef10b..e86c85e182b 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -28,17 +28,13 @@ if(dextrous) var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" msg += "[desc]\n" - if(l_hand && !(l_hand.flags&ABSTRACT)) - if(l_hand.blood_DNA) - msg += "It is holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in its left hand!\n" - else - msg += "It is holding \icon[l_hand] \a [l_hand] in its left hand.\n" - if(r_hand && !(r_hand.flags&ABSTRACT)) - if(r_hand.blood_DNA) - msg += "It is holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in its right hand!\n" - else - msg += "It is holding \icon[r_hand] \a [r_hand] in its right hand.\n" + for(var/obj/item/I in held_items) + if(!(I.flags & ABSTRACT)) + if(I.blood_DNA) + msg += "It has \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n" + else + msg += "It has \icon[I] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n" if(internal_storage && !(internal_storage.flags&ABSTRACT)) if(internal_storage.blood_DNA) @@ -53,14 +49,12 @@ /mob/living/simple_animal/hostile/guardian/dextrous/Recall() if(loc == summoner || cooldown > world.time) return 0 - drop_l_hand() - drop_r_hand() + drop_all_held_items() return ..() //lose items, then return /mob/living/simple_animal/hostile/guardian/dextrous/snapback() if(summoner && !(get_dist(get_turf(summoner),get_turf(src)) <= range)) - drop_l_hand() - drop_r_hand() + drop_all_held_items() ..() //lose items, then return //SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm index 889ab1803ca..a7a204af676 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/support.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm @@ -148,7 +148,7 @@ PoolOrNew(/obj/effect/overlay/temp/guardian/phase/out, T) if(isliving(A)) var/mob/living/L = A - L.flash_eyes() + L.flash_act() A.visible_message("[A] disappears in a flash of \ light!", "Your vision is obscured \ by a flash of light!") diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 013a77e81d1..2f75310ff25 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -256,12 +256,6 @@ else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one FindTarget() -/mob/living/simple_animal/hostile/UnarmedAttack(atom/A) - target = A - if(dextrous && !is_type_in_typecache(A, environment_target_typecache) && !ismob(A)) - ..() - else - AttackingTarget() /mob/living/simple_animal/hostile/proc/AttackingTarget() target.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index a8f7b491bc9..bedb33e3d4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -622,7 +622,7 @@ Difficulty: Very Hard if(isliving(target) && target != src) var/mob/living/L = target if(L.stat < DEAD) - L.heal_overall_damage(heal_power, heal_power, 1) + L.heal_overall_damage(heal_power, heal_power) PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(target), "#80F5FF")) /mob/living/simple_animal/hostile/lightgeist/Life() diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 23455487021..ebe6e335255 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -224,7 +224,7 @@ //Adding things to inventory else if(href_list["add_inv"]) var/add_to = href_list["add_inv"] - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr << "You have nothing in your hand to put on its [add_to]!" return switch(add_to) @@ -233,7 +233,7 @@ usr << "It's already wearing something!" return else - var/obj/item/item_to_add = usr.get_active_hand() + var/obj/item/item_to_add = usr.get_active_held_item() if(!item_to_add) return @@ -633,8 +633,10 @@ item = I else if(iscarbon(AM)) var/mob/living/carbon/C = AM - if((C.l_hand && C.l_hand.w_class <= 2) || (C.r_hand && C.r_hand.w_class <= 2)) - item = C + for(var/obj/item/I in C.held_items) + if(I.w_class <= 2) + item = I + break if(item) if(!AStar(src, get_turf(item), /turf/proc/Distance_cardinal)) item = null @@ -668,8 +670,9 @@ if(iscarbon(AM)) var/mob/living/carbon/C = AM - if(C.l_hand && C.l_hand.w_class <= 2 || C.r_hand && C.r_hand.w_class <= 2) - return C + for(var/obj/item/I in C.held_items) + if(I.w_class <= 2) + return C return null @@ -719,11 +722,10 @@ var/obj/item/stolen_item = null for(var/mob/living/carbon/C in view(1,src)) - if(C.l_hand && C.l_hand.w_class <= 2) - stolen_item = C.l_hand - - if(C.r_hand && C.r_hand.w_class <= 2) - stolen_item = C.r_hand + for(var/obj/item/I in C.held_items) + if(I.w_class <= 2) + stolen_item = I + break if(stolen_item) C.unEquip(stolen_item) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 342ed9d9946..edca0beac1d 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -101,10 +101,6 @@ client.screen += client.void ..() -/mob/living/simple_animal/updatehealth() - ..() - health = Clamp(health, 0, maxHealth) - /mob/living/simple_animal/Life() if(..()) //alive if(!ckey) @@ -113,6 +109,10 @@ handle_automated_speech() return 1 +/mob/living/simple_animal/updatehealth() + ..() + health = Clamp(health, 0, maxHealth) + /mob/living/simple_animal/update_stat() if(status_flags & GODMODE) return @@ -251,10 +251,6 @@ if(icon_gib) new /obj/effect/overlay/temp/gib_animation/animal(loc, icon_gib) -/mob/living/simple_animal/blob_act(obj/effect/blob/B) - adjustBruteLoss(20) - return - /mob/living/simple_animal/say_quote(input) var/ending = copytext(input, length(input)) if(speak_emote && speak_emote.len && ending != "?" && ending != "!") @@ -271,125 +267,7 @@ act = "me" ..(act, m_type, message) -/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) - if(..()) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - attack_threshold_check(damage,M.melee_damage_type) - return 1 -/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) - if(!Proj) - return - apply_damage(Proj.damage, Proj.damage_type) - Proj.on_hit(src) - return 0 - -/mob/living/simple_animal/proc/adjustHealth(amount) - if(status_flags & GODMODE) - return 0 - bruteloss = Clamp(bruteloss + amount, 0, maxHealth) - updatehealth() - return amount - -/mob/living/simple_animal/adjustBruteLoss(amount) - if(damage_coeff[BRUTE]) - . = adjustHealth(amount * damage_coeff[BRUTE] * config.damage_multiplier) - -/mob/living/simple_animal/adjustFireLoss(amount) - if(damage_coeff[BURN]) - . = adjustHealth(amount * damage_coeff[BURN] * config.damage_multiplier) - -/mob/living/simple_animal/adjustOxyLoss(amount) - if(damage_coeff[OXY]) - . = adjustHealth(amount * damage_coeff[OXY] * config.damage_multiplier) - -/mob/living/simple_animal/adjustToxLoss(amount) - if(damage_coeff[TOX]) - . = adjustHealth(amount * damage_coeff[TOX] * config.damage_multiplier) - -/mob/living/simple_animal/adjustCloneLoss(amount) - if(damage_coeff[CLONE]) - . = adjustHealth(amount * damage_coeff[CLONE] * config.damage_multiplier) - -/mob/living/simple_animal/adjustStaminaLoss(amount) - return - -/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) - ..() - switch(M.a_intent) - - if("help") - if (health > 0) - visible_message("[M] [response_help] [src].") - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - - if("grab") - grabbedby(M) - - if("harm", "disarm") - M.do_attack_animation(src) - visible_message("[M] [response_harm] [src]!") - playsound(loc, attacked_sound, 25, 1, -1) - attack_threshold_check(harm_intent_damage) - add_logs(M, src, "attacked") - updatehealth() - return 1 - -/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M) - if(..()) //successful monkey bite. - if(stat != DEAD) - var/damage = rand(1, 3) - attack_threshold_check(damage) - return 1 - if (M.a_intent == "help") - if (health > 0) - visible_message("[M.name] [response_help] [src].") - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - - return - -/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) - if(..()) //if harm or disarm intent. - if(M.a_intent == "disarm") - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - visible_message("[M] [response_disarm] [name]!", \ - "[M] [response_disarm] [name]!") - add_logs(M, src, "disarmed") - else - var/damage = rand(15, 30) - visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - attack_threshold_check(damage) - add_logs(M, src, "attacked") - return 1 - -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) - if(..()) //successful larva bite - var/damage = rand(5, 10) - if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - attack_threshold_check(damage) - return 1 - -/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M) - if(..()) //successful slime attack - var/damage = rand(15, 25) - if(M.is_adult) - damage = rand(20, 35) - attack_threshold_check(damage) - return 1 - -/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE) - if(!damage_coeff[damagetype]) - damage = 0 - else - damage *= damage_coeff[damagetype] - - if(damage >= 0 && damage <= force_threshold) - visible_message("[src] looks unharmed.") - else - adjustHealth(damage * config.damage_multiplier) /mob/living/simple_animal/movement_delay() . = ..() @@ -412,8 +290,7 @@ for(var/i in loot) new i(loc) if(dextrous) - unEquip(r_hand) - unEquip(l_hand) + drop_all_held_items() if(!gibbed) if(death_sound) playsound(get_turf(src),death_sound, 200, 1) @@ -423,6 +300,7 @@ visible_message("\The [src] stops moving...") if(del_on_death) ghostize() + stat = DEAD qdel(src) else health = 0 @@ -432,28 +310,6 @@ lying = 1 ..() -/mob/living/simple_animal/ex_act(severity, target) - ..() - var/bomb_armor = getarmor(null, "bomb") - switch (severity) - if (1) - if(prob(bomb_armor)) - adjustBruteLoss(500) - else - gib() - return - if (2) - var/bloss = 60 - if(prob(bomb_armor)) - bloss = bloss / 1.5 - adjustBruteLoss(bloss) - - if(3) - var/bloss = 30 - if(prob(bomb_armor)) - bloss = bloss / 1.5 - adjustBruteLoss(bloss) - /mob/living/simple_animal/proc/CanAttack(atom/the_target) if(see_invisible < the_target.invisibility) return 0 @@ -470,9 +326,6 @@ /mob/living/simple_animal/handle_fire() return -/mob/living/simple_animal/update_fire() - return - /mob/living/simple_animal/IgniteMob() return FALSE @@ -545,8 +398,7 @@ /mob/living/simple_animal/update_canmove() if(paralysis || stunned || weakened || stat || resting) - drop_r_hand() - drop_l_hand() + drop_all_held_items() canmove = 0 else if(buckled) canmove = 0 @@ -601,14 +453,6 @@ /mob/living/simple_animal/get_idcard() return access_card -//Dextrous simple mobs can use hands! -/mob/living/simple_animal/create_mob_hud() - if(client && !hud_used) - if(dextrous) - hud_used = new dextrous_hud_type(src, ui_style2icon(client.prefs.UI_style)) - else - ..() - /mob/living/simple_animal/OpenCraftingMenu() if(dextrous) handcrafting.ui_interact(src) @@ -622,54 +466,56 @@ /mob/living/simple_animal/activate_hand(selhand) if(!dextrous) return ..() + if(!selhand) + selhand = (active_hand_index % held_items.len)+1 if(istext(selhand)) selhand = lowertext(selhand) if(selhand == "right" || selhand == "r") - selhand = 0 + selhand = 2 if(selhand == "left" || selhand == "l") selhand = 1 - if(selhand != src.hand) - swap_hand() + if(selhand != active_hand_index) + swap_hand(selhand) else mode() -/mob/living/simple_animal/swap_hand() +/mob/living/simple_animal/swap_hand(hand_index) if(!dextrous) return ..() - var/obj/item/held_item = get_active_hand() + if(!hand_index) + hand_index = (active_hand_index % held_items.len)+1 + var/obj/item/held_item = get_active_held_item() if(held_item) if(istype(held_item, /obj/item/weapon/twohanded)) var/obj/item/weapon/twohanded/T = held_item if(T.wielded == 1) usr << "Your other hand is too busy holding the [T.name]." return - hand = !hand - if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand]) + var/oindex = active_hand_index + active_hand_index = hand_index + if(hud_used) var/obj/screen/inventory/hand/H - H = hud_used.inv_slots[slot_l_hand] - H.update_icon() - H = hud_used.inv_slots[slot_r_hand] - H.update_icon() - -/mob/living/simple_animal/UnarmedAttack(atom/A, proximity) - if(!dextrous) - return ..() - if(!ismob(A)) - A.attack_hand(src) - update_hand_icons() + H = hud_used.hand_slots["[hand_index]"] + if(H) + H.update_icon() + H = hud_used.hand_slots["[oindex]"] + if(H) + H.update_icon() /mob/living/simple_animal/put_in_hands(obj/item/I) ..() - update_hand_icons() + update_inv_hands() -/mob/living/simple_animal/proc/update_hand_icons() +/mob/living/simple_animal/update_inv_hands() if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) + var/obj/item/l_hand = get_item_for_held_index(1) + var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) r_hand.layer = ABOVE_HUD_LAYER - r_hand.screen_loc = ui_rhand + r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand)) client.screen |= r_hand if(l_hand) l_hand.layer = ABOVE_HUD_LAYER - l_hand.screen_loc = ui_lhand + l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand)) client.screen |= l_hand diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 44c96f7f216..0545bd03b00 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -14,4 +14,61 @@ if(damage >= 0) ear_damage = damage if(deaf >= 0) - ear_deaf = deaf \ No newline at end of file + ear_deaf = deaf + + +//////////////////////////////STUN //////////////////////////////////// + +/mob/living/proc/add_stun_absorption(key, duration, priority, message, self_message, examine_message) +//adds a stun absorption with a key, a duration in deciseconds, its priority, and the messages it makes when you're stunned/examined, if any + if(!islist(stun_absorption)) + stun_absorption = list() + if(stun_absorption[key]) + stun_absorption[key]["end_time"] = world.time + duration + stun_absorption[key]["priority"] = priority + stun_absorption[key]["stuns_absorbed"] = 0 + else + stun_absorption[key] = list("end_time" = world.time + duration, "priority" = priority, "stuns_absorbed" = 0, \ + "visible_message" = message, "self_message" = self_message, "examine_message" = examine_message) + +/mob/living/Stun(amount, updating = 1, ignore_canstun = 0) + if(!stat && islist(stun_absorption)) + var/priority_absorb_key + var/highest_priority + for(var/i in stun_absorption) + if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority)) + priority_absorb_key = stun_absorption[i] + highest_priority = stun_absorption[i]["priority"] + if(priority_absorb_key) + if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"]) + if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"]) + visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]") + else if(priority_absorb_key["visible_message"]) + visible_message("[src][priority_absorb_key["visible_message"]]") + else if(priority_absorb_key["self_message"]) + src << "[priority_absorb_key["self_message"]]" + priority_absorb_key["stuns_absorbed"] += amount + return 0 + ..() + +///////////////////////////////// WEAKEN ///////////////////////////////////// + +/mob/living/Weaken(amount, updating = 1, ignore_canweaken = 0) + if(!stat && islist(stun_absorption)) + var/priority_absorb_key + var/highest_priority + for(var/i in stun_absorption) + if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority)) + priority_absorb_key = stun_absorption[i] + highest_priority = priority_absorb_key["priority"] + if(priority_absorb_key) + if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"]) + if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"]) + visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]") + else if(priority_absorb_key["visible_message"]) + visible_message("[src][priority_absorb_key["visible_message"]]") + else if(priority_absorb_key["self_message"]) + src << "[priority_absorb_key["self_message"]]" + priority_absorb_key["stuns_absorbed"] += amount + return 0 + ..() \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 2a98cae186b..4744180d207 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -178,11 +178,6 @@ var/next_mob_id = 0 return /mob/proc/get_item_by_slot(slot_id) - switch(slot_id) - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand return null /mob/proc/restrained(ignore_grab) @@ -193,7 +188,7 @@ var/next_mob_id = 0 //This proc is called whenever someone clicks an inventory ui slot. /mob/proc/attack_ui(slot) - var/obj/item/W = get_active_hand() + var/obj/item/W = get_active_held_item() if(istype(W)) if(equip_to_slot_if_possible(W, slot,0,0,0)) @@ -399,16 +394,11 @@ var/next_mob_id = 0 if(incapacitated()) return - if(hand) - var/obj/item/W = l_hand - if (W) - W.attack_self(src) - update_inv_l_hand() - else - var/obj/item/W = r_hand - if (W) - W.attack_self(src) - update_inv_r_hand() + var/obj/item/I = get_active_held_item() + if(I) + I.attack_self(src) + update_inv_hands() + /* /mob/verb/dump_source() @@ -422,7 +412,7 @@ var/next_mob_id = 0 */ /mob/verb/memory() - set name = "Notes Memory" + set name = "Notes" set category = "IC" set desc = "View your character's notes memory." if(mind) @@ -539,8 +529,13 @@ var/next_mob_id = 0 if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) if(href_list["item"]) var/slot = text2num(href_list["item"]) - var/obj/item/what = get_item_by_slot(slot) - + var/hand_index = text2num(href_list["hand_index"]) + var/obj/item/what + if(hand_index) + what = get_item_for_held_index(hand_index) + slot = list(slot,hand_index) + else + what = get_item_by_slot(slot) if(what) usr.stripPanelUnequip(what,src,slot) else @@ -695,8 +690,7 @@ var/next_mob_id = 0 var/has_arms = get_num_arms() var/ignore_legs = get_leg_ignore() if(ko || resting || stunned || chokehold) - drop_r_hand() - drop_l_hand() + drop_all_held_items() unset_machine() if(pulling) stop_pulling() @@ -729,8 +723,7 @@ var/next_mob_id = 0 /mob/proc/fall(forced) - drop_l_hand() - drop_r_hand() + drop_all_held_items() /mob/verb/eastface() set hidden = 1 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index b361cf48130..ee73870dfd0 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -11,7 +11,6 @@ var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak - var/obj/screen/hands = null /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. The current method unnecessarily clusters up the variable list, especially for humans (although rearranging won't really clean it up a lot but the difference will be noticable for other mobs). @@ -38,7 +37,6 @@ var/next_move = null var/notransform = null //Carbon - var/hand = null var/eye_blind = 0 //Carbon var/eye_blurry = 0 //Carbon var/ear_deaf = 0 //Carbon @@ -62,7 +60,6 @@ var/timeofdeath = 0//Living var/cpr_time = 1//Carbon - var/bodytemperature = 310.055 //98.7 F var/drowsyness = 0//Carbon var/dizziness = 0//Carbon @@ -79,8 +76,12 @@ var/m_intent = "run"//Living var/lastKnownIP = null var/atom/movable/buckled = null//Living - var/obj/item/l_hand = null//Living - var/obj/item/r_hand = null//Living + + //Hands + var/active_hand_index = 1 + var/list/held_items = list(null, null) //len = number of hands, eg: 2 nulls is 2 empty hands, 1 item and 1 null is 1 full hand and 1 empty hand. + //held_items[active_hand_index] is the actively held item, but please use get_active_held_item() instead, because OOP + var/obj/item/weapon/storage/s_active = null//Carbon var/see_override = 0 //0 for no override, sets see_invisible = see_override in mob life process diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 3e734dee12f..40d23ea638d 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -273,8 +273,9 @@ It's fairly easy to fix if dealing with single letters but not so much with comp return 0 /mob/proc/abiotic(full_body = 0) - if(l_hand && !l_hand.flags&NODROP || r_hand && !r_hand.flags&NODROP) - return 1 + for(var/obj/item/I in held_items) + if(!(I.flags & NODROP)) + return 1 return 0 //converts intent-strings into numbers and back @@ -384,10 +385,6 @@ It's fairly easy to fix if dealing with single letters but not so much with comp return 1 return 0 -/proc/get_both_hands(mob/living/carbon/M) - var/list/hands = list(M.l_hand, M.r_hand) - return hands - /mob/proc/reagent_check(datum/reagent/R) // utilized in the species code return 1 @@ -416,14 +413,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp /proc/item_heal_robotic(mob/living/carbon/human/H, mob/user, brute_heal, burn_heal) var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - if(affecting && affecting.status == ORGAN_ROBOTIC) + if(affecting && affecting.status == BODYPART_ROBOTIC) var/dam //changes repair text based on how much brute/burn was supplied if(brute_heal > burn_heal) dam = 1 else dam = 0 if((brute_heal > 0 && affecting.brute_dam > 0) || (burn_heal > 0 && affecting.burn_dam > 0)) - affecting.heal_damage(brute_heal,burn_heal,1) + if(affecting.heal_damage(brute_heal, burn_heal, 1, 0)) + H.update_damage_overlays() user.visible_message("[user] has fixed some of the [dam ? "dents on" : "burnt wires in"] [H]'s [affecting].", "You fix some of the [dam ? "dents on" : "burnt wires in"] [H]'s [affecting].") return 1 //successful heal else diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 9cf04369356..919e995bca8 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -55,7 +55,7 @@ /client/Northwest() - if(!usr.get_active_hand()) + if(!usr.get_active_held_item()) usr << "You have nothing to drop in your hand!" return usr.drop_item() diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 649fe0462bb..dfbe6250533 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -245,7 +245,13 @@ return - +//////////////////////////////// HUSK DISABILITY ///////////////////////////: + +/mob/proc/cure_husk() + return + +/mob/proc/become_husk() + return diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index e1b2f760b4c..fcae203a523 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -7,19 +7,32 @@ var/list/implants = list() var/list/int_organs = list() + + if (tr_flags & TR_KEEPIMPLANTS) for(var/obj/item/weapon/implant/W in src) implants += W if (tr_flags & TR_KEEPORGANS) - for(var/obj/item/organ/I in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/I = X int_organs += I I.Remove(src, 1) + var/list/missing_bodyparts_zones = get_missing_limbs() + + var/obj/item/cavity_object + + var/obj/item/bodypart/chest/CH = get_bodypart("chest") + if(CH.cavity_item) + cavity_object = CH.cavity_item + CH.cavity_item = null + if(tr_flags & TR_KEEPITEMS) - for(var/obj/item/W in (src.contents-implants-int_organs)) + for(var/obj/item/W in (contents-implants-cavity_object)) unEquip(W) + //Make mob invisible and spawn animation notransform = 1 canmove = 0 @@ -82,17 +95,37 @@ //re-add organs to new mob if(tr_flags & TR_KEEPORGANS) - for(var/obj/item/organ/I in O.internal_organs) - qdel(I) + for(var/X in O.internal_organs) + qdel(X) - for(var/obj/item/organ/I in int_organs) + 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("chest") + if(cavity_object) + torso.cavity_item = cavity_object //cavity item is given to the new chest + cavity_object.loc = 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.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 mind and delete old mob if(mind) mind.transfer_to(O) if(O.mind.changeling) O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) + + if (tr_flags & TR_DEFAULTMSG) O << "You are now a monkey." @@ -121,13 +154,23 @@ implants += W if (tr_flags & TR_KEEPORGANS) - for(var/obj/item/organ/I in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/I = X int_organs += I I.Remove(src, 1) + var/list/missing_bodyparts_zones = get_missing_limbs() + + var/obj/item/cavity_object + + var/obj/item/bodypart/chest/CH = get_bodypart("chest") + if(CH.cavity_item) + cavity_object = CH.cavity_item + CH.cavity_item = null + //now the rest if (tr_flags & TR_KEEPITEMS) - for(var/obj/item/W in (src.contents-implants-int_organs)) + for(var/obj/item/W in (contents-implants-cavity_object)) unEquip(W) if (client) client.screen -= W @@ -136,6 +179,8 @@ W.dropped(src) W.layer = initial(W.layer) + + //Make mob invisible and spawn animation notransform = 1 canmove = 0 @@ -202,12 +247,31 @@ O.sec_hud_set_implants() if(tr_flags & TR_KEEPORGANS) - for(var/obj/item/organ/I in O.internal_organs) - qdel(I) + for(var/X in O.internal_organs) + qdel(X) - for(var/obj/item/organ/I in int_organs) + for(var/X in int_organs) + var/obj/item/organ/I = X I.Insert(O, 1) + + var/obj/item/bodypart/chest/torso = get_bodypart("chest") + if(cavity_object) + torso.cavity_item = cavity_object //cavity item is given to the new chest + cavity_object.loc = 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.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) + if(mind) mind.transfer_to(O) if(O.mind.changeling) diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index b14056f4186..6ed04dbbdd3 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -19,10 +19,7 @@ /mob/proc/update_inv_back() return -/mob/proc/update_inv_l_hand() - return - -/mob/proc/update_inv_r_hand() +/mob/proc/update_inv_hands() return /mob/proc/update_inv_wear_mask() @@ -40,9 +37,15 @@ /mob/proc/update_inv_head() return +/mob/proc/update_body() + return + /mob/proc/update_hair() return +/mob/proc/update_fire() + return + /mob/proc/update_inv_gloves() return @@ -62,4 +65,4 @@ return /mob/proc/update_inv_ears() - return + return \ No newline at end of file diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index 51c91a595ae..946a0c2fe52 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -55,12 +55,7 @@ if(!M.restrained() && !M.stat) if(!isturf(loc) || !Adjacent(M)) return - - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) /obj/item/device/modular_computer/laptop/attack_hand(mob/user) if(screen_on && isturf(loc)) diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index b8ec10694b8..8ddff02fb64 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -89,7 +89,7 @@ if(ishuman(user)) var/mob/living/carbon/human/h = user var/obj/item/weapon/card/id/I = h.get_idcard() - var/obj/item/weapon/card/id/C = h.get_active_hand() + var/obj/item/weapon/card/id/C = h.get_active_held_item() if(C) C = C.GetID() if(!(C && istype(C))) diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index 1e201da470b..780045d8b73 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -169,7 +169,7 @@ data_core.manifest_modify(id_card.registered_name, id_card.assignment) computer.proc_eject_id(user, 1) else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if (istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return @@ -185,7 +185,7 @@ minor = 0 computer.proc_eject_id(user, 2) else - var/obj/item/I = usr.get_active_hand() + var/obj/item/I = usr.get_active_held_item() if (istype(I, /obj/item/weapon/card/id)) if(!usr.drop_item()) return diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm index 1fa003fa76a..39e7f5c5701 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm @@ -9,11 +9,11 @@ if(!ninjacost(10)) var/mob/living/carbon/human/H = affecting - var/slot = H.hand ? slot_l_hand : slot_r_hand - - if(H.equip_to_slot_or_del(new /obj/item/weapon/throwing_star/ninja(H), slot)) + var/obj/item/weapon/throwing_star/ninja/N = new(H) + if(H.put_in_hands(N)) H << "A throwing star has been created in your hand!" - + else + qdel(N) H.throw_mode_on() //So they can quickly throw it. diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm index fb38a3fbdd7..8062c023bc1 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm @@ -32,9 +32,6 @@ if(energyKatana in C.stomach_contents) C.stomach_contents -= energyKatana - if(energyKatana in C.internal_organs) - C.internal_organs -= energyKatana - energyKatana.loc = get_turf(energyKatana) if(inview) //If we can see the katana, throw it towards ourselves, damaging people as we go. diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index b58b7d2bfec..f9e66b606ee 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -35,7 +35,7 @@ user << "You clip the paper onto \the [src]." update_icon() else if(toppaper) - toppaper.attackby(usr.get_active_hand(), usr) + toppaper.attackby(user.get_active_held_item(), user) update_icon() @@ -75,8 +75,9 @@ if(href_list["addpen"]) if(!haspen) - if(istype(usr.get_active_hand(), /obj/item/weapon/pen)) - var/obj/item/weapon/pen/W = usr.get_active_hand() + var/obj/item/held = usr.get_active_held_item() + if(istype(held, /obj/item/weapon/pen)) + var/obj/item/weapon/pen/W = held if(!usr.unEquip(W)) return W.loc = src @@ -86,8 +87,8 @@ if(href_list["write"]) var/obj/item/P = locate(href_list["write"]) if(istype(P) && P.loc == src) - if(usr.get_active_hand()) - P.attackby(usr.get_active_hand(), usr) + if(usr.get_active_held_item()) + P.attackby(usr.get_active_held_item(), usr) if(href_list["remove"]) var/obj/item/P = locate(href_list["remove"]) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index f6b887f1a2f..87b424efbfb 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -257,14 +257,14 @@ var/t = stripped_multiline_input("Enter what you want to write:", "Write") if(!t) return - var/obj/item/i = usr.get_active_hand() //Check to see if he still got that darn pen, also check if he's using a crayon or pen. + var/obj/item/i = usr.get_active_held_item() //Check to see if he still got that darn pen, also check if he's using a crayon or pen. var/iscrayon = 0 if(!istype(i, /obj/item/weapon/pen)) if(!istype(i, /obj/item/toy/crayon)) return iscrayon = 1 - if(!in_range(src, usr) && loc != usr && !istype(loc, /obj/item/weapon/clipboard) && loc.loc != usr && usr.get_active_hand() != i) //Some check to see if he's allowed to write + if(!in_range(src, usr) && loc != usr && !istype(loc, /obj/item/weapon/clipboard) && loc.loc != usr && usr.get_active_held_item() != i) //Some check to see if he's allowed to write return t = parsepencode(t, i, usr, iscrayon) // Encode everything from pencode to html diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm index 88d12fbd1c5..d147fb85a14 100644 --- a/code/modules/paperwork/paper_cutter.dm +++ b/code/modules/paperwork/paper_cutter.dm @@ -97,11 +97,7 @@ if(!remove_item_from_storage(M)) if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) add_fingerprint(M) diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 08f1f9bd76f..f559e5bde98 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -43,11 +43,7 @@ if(!remove_item_from_storage(M)) if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) add_fingerprint(M) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 52b39bc2737..4007929f9a9 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -245,17 +245,17 @@ else continue - var/holding = null + var/list/holding = list() if(istype(M, /mob/living)) var/mob/living/L = M - if(L.l_hand || L.r_hand) - if(L.l_hand) holding = "They are holding \a [L.l_hand]" - if(L.r_hand) - if(holding) - holding += " and \a [L.r_hand]" - else - holding = "They are holding \a [L.r_hand]" + + for(var/obj/item/I in L.held_items) + if(!holding) + holding += "They are holding \a [I]" + else + holding += " and \a [I]" + holding = holding.Join() if(!mob_detail) mob_detail = "You can see [L] on the photo[L.health < (L.maxHealth * 0.75) ? " - [L] looks hurt":""].[holding ? " [holding]":"."]. " diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm index 3f10566dde8..89d63ba3f06 100644 --- a/code/modules/power/antimatter/control.dm +++ b/code/modules/power/antimatter/control.dm @@ -170,12 +170,11 @@ if(fueljar) user << "There is already a [fueljar] inside!" return + + if(!user.unEquip(W)) + return fueljar = W - W.loc = src - if(user.client) - user.client.screen -= W - user.unEquip(W) - user.update_icons() + W.forceMove(src) user.visible_message("[user.name] loads an [W.name] into the [src.name].", \ "You load an [W.name].", \ "You hear a thunk.") diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index a5e754cd015..434a31157a4 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -517,7 +517,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \ return ..() var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - if(affecting && affecting.status == ORGAN_ROBOTIC) + if(affecting && affecting.status == BODYPART_ROBOTIC) user.visible_message("[user] starts to fix some of the wires in [H]'s [affecting.name].", "You start fixing some of the wires in [H]'s [affecting.name].") if(!do_mob(user, H, 50)) return diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 68c06b4cb51..41e77f5f886 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -439,10 +439,9 @@ else user << "You try to remove the light [fitting], but you burn your hand on it!" - var/obj/item/bodypart/affecting = H.get_bodypart("[user.hand ? "l" : "r" ]_arm") + var/obj/item/bodypart/affecting = H.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") if(affecting && affecting.take_damage( 0, 5 )) // 5 burn damage - H.update_damage_overlays(0) - H.updatehealth() + H.update_damage_overlays() return // if burned, don't remove the light else user << "You remove the light [fitting]." diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 107b9c68197..a3469c6b699 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -392,7 +392,7 @@ /obj/singularity/proc/mezzer() for(var/mob/living/carbon/M in oviewers(8, src)) - if(istype(M, /mob/living/carbon/brain)) //Ignore brains + if(istype(M, /mob/living/brain)) //Ignore brains continue if(M.stat == CONSCIOUS) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 03df590ca0a..b1ec4893a43 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -14,6 +14,7 @@ force = 5 origin_tech = "combat=1" needs_permit = 1 + unique_rename = 0 attack_verb = list("struck", "hit", "bashed") var/fire_sound = "gunshot" @@ -31,11 +32,8 @@ var/firing_burst = 0 //Prevent the weapon from firing again while already firing var/semicd = 0 //cooldown handler var/weapon_weight = WEAPON_LIGHT - var/spread = 0 //Spread induced by the gun itself. var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once. - - var/unique_rename = 0 //allows renaming with a pen var/unique_reskin = 0 //allows one-time reskinning var/current_skin = null //the skin choice if we had a reskin var/list/options = list() @@ -90,8 +88,6 @@ user << "It doesn't have a firing pin installed, and won't fire." if(unique_reskin && !current_skin) user << "Alt-click it to reskin it." - if(unique_rename) - user << "Use a pen on it to rename it." /obj/item/weapon/gun/proc/process_chamber() @@ -125,7 +121,7 @@ user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear a [istype(src, /obj/item/weapon/gun/energy) ? "laser blast" : "gunshot"]!") if(weapon_weight >= WEAPON_MEDIUM) - if(user.get_inactive_hand()) + if(user.get_inactive_held_item()) if(prob(15)) if(user.drop_item()) user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!") @@ -171,7 +167,7 @@ user.drop_item() return - if(weapon_weight == WEAPON_HEAVY && user.get_inactive_hand()) + if(weapon_weight == WEAPON_HEAVY && user.get_inactive_held_item()) user << "You need both hands free to fire \the [src]!" return @@ -207,7 +203,7 @@ obj/item/weapon/gun/proc/newshot() return if(weapon_weight) - if(user.get_inactive_hand()) + if(user.get_inactive_held_item()) recoil = 4 //one-handed kick else recoil = initial(recoil) @@ -218,7 +214,7 @@ obj/item/weapon/gun/proc/newshot() if(!user) break if(!issilicon(user)) - if( i>1 && !(src in get_both_hands(user))) //for burst firing + if( i>1 && !(user.is_holding(src))) //for burst firing break if(chambered) var/sprd = 0 @@ -261,10 +257,7 @@ obj/item/weapon/gun/proc/newshot() semicd = 0 if(user) - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() + user.update_inv_hands() feedback_add_details("gun_fired","[src.type]") /obj/item/weapon/gun/attack(mob/M as mob, mob/user) @@ -305,10 +298,7 @@ obj/item/weapon/gun/proc/newshot() for(var/datum/action/item_action/toggle_gunlight/TGL in actions) qdel(TGL) - if(unique_rename) - if(istype(I, /obj/item/weapon/pen)) - rename_gun(user) - ..() + /obj/item/weapon/gun/proc/toggle_gunlight() set name = "Toggle Gunlight" @@ -389,13 +379,6 @@ obj/item/weapon/gun/proc/newshot() update_icon() -/obj/item/weapon/gun/proc/rename_gun(mob/M) - var/input = stripped_input(M,"What do you want to name the gun?", ,"", MAX_NAME_LEN) - - if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove) - name = input - M << "You name the gun [input]. Say hello to your new friend." - return /obj/item/weapon/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 9001dd964d5..f729b9966cf 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -139,7 +139,7 @@ if (src.can_shoot()) user.visible_message("[user] is putting the barrel of the [src.name] in \his mouth. It looks like \he's trying to commit suicide.") sleep(25) - if(user.l_hand == src || user.r_hand == src) + if(user.is_holding(src)) user.visible_message("[user] melts \his face off with the [src.name]!") playsound(loc, fire_sound, 50, 1, -1) var/obj/item/ammo_casing/energy/shot = ammo_type[select] diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index cd5b9c737ab..9b50a1e4a98 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -98,7 +98,7 @@ if(loc == user) if(suppressed && can_unsuppress) var/obj/item/weapon/suppressor/S = suppressed - if(user.l_hand != src && user.r_hand != src) + if(!user.is_holding(src)) ..() return user << "You unscrew [suppressed] from [src]." @@ -145,7 +145,7 @@ if (src.chambered && src.chambered.BB && !src.chambered.BB.nodamage) user.visible_message("[user] is putting the barrel of the [src.name] in \his mouth. It looks like \he's trying to commit suicide.") sleep(25) - if(user.l_hand == src || user.r_hand == src) + if(user.is_holding(src)) process_fire(user, user, 0, zone_override = "head") user.visible_message("[user] blows \his brains out with the [src.name]!") return(BRUTELOSS) @@ -178,7 +178,7 @@ name = "sawn-off [src.name]" desc = sawn_desc w_class = 3 - item_state = "gun"//phil235 is it different with different skin? + item_state = "gun" slot_flags &= ~SLOT_BACK //you can't sling it on your back slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) sawn_state = SAWN_OFF diff --git a/code/modules/projectiles/guns/projectile/laser_gatling.dm b/code/modules/projectiles/guns/projectile/laser_gatling.dm index 35210e78702..43de02219f3 100644 --- a/code/modules/projectiles/guns/projectile/laser_gatling.dm +++ b/code/modules/projectiles/guns/projectile/laser_gatling.dm @@ -69,11 +69,7 @@ var/obj/screen/inventory/hand/H = over_object if(!M.unEquip(src)) return - switch(H.slot_id) - if(slot_r_hand) - M.put_in_r_hand(src) - if(slot_l_hand) - M.put_in_l_hand(src) + M.put_in_hand(src, H.held_index) /obj/item/weapon/minigunpack/update_icon() diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index a238c60623a..fdd8b765f67 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -37,7 +37,7 @@ if(unique_rename) if(istype(A, /obj/item/weapon/pen)) - rename_gun(user) + rename_weapon(user) /obj/item/weapon/gun/projectile/revolver/attack_self(mob/living/user) var/num_unloaded = 0 @@ -111,7 +111,7 @@ if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60 playsound(user, fire_sound, 50, 1) user << "[src] blows up in your face!" - user.take_organ_damage(0,20) + user.take_bodypart_damage(0,20) user.unEquip(src) return 0 ..() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 1c4616c90ed..910fe2cc89a 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -63,14 +63,26 @@ /obj/item/projectile/proc/on_range() //if we want there to be effects when they reach the end of their range qdel(src) -/obj/item/projectile/proc/on_hit(atom/target, blocked = 0, hit_zone) +//to get the correct limb (if any) for the projectile hit message +/mob/living/proc/check_limb_hit(hit_zone) + if(has_limbs) + return hit_zone + +/mob/living/carbon/check_limb_hit(hit_zone) + if(get_bodypart(hit_zone)) + return hit_zone + else //when a limb is missing the damage is actually passed to the chest + return "chest" + +/obj/item/projectile/proc/on_hit(atom/target, blocked = 0) if(!isliving(target)) return 0 var/mob/living/L = target if(blocked != 100) // not completely blocked var/organ_hit_text = "" - if(L.has_limbs) - organ_hit_text = " in \the [parse_zone(def_zone)]" + var/limb_hit = L.check_limb_hit(def_zone)//to get the correct message info. + if(limb_hit) + organ_hit_text = " in \the [parse_zone(limb_hit)]" if(suppressed) playsound(loc, hitsound, 5, 1, -1) L << "You're shot by \a [src][organ_hit_text]!" diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 59cd030b85f..0dc198bc33a 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -73,7 +73,7 @@ icon_state = "pulse1_bl" var/life = 20 -/obj/item/projectile/beam/pulse/heavy/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/beam/pulse/heavy/on_hit(atom/target, blocked = 0) life -= 10 if(life > 0) . = -1 diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index c1061c57293..4a3b66ba108 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -174,11 +174,11 @@ create_reagents(50) reagents.set_reacting(FALSE) -/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = 0) if(iscarbon(target)) var/mob/living/carbon/M = target if(blocked != 100) // not completely blocked - if(M.can_inject(null,0,hit_zone,piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body. + if(M.can_inject(null, 0, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body. ..() reagents.reaction(M, INJECT) reagents.trans_to(M, reagents.total_volume) @@ -188,7 +188,7 @@ target.visible_message("The [name] was deflected!", \ "You were protected against the [name]!") - ..(target, blocked, hit_zone) + ..(target, blocked) reagents.set_reacting(TRUE) reagents.handle_reactions() return 1 @@ -234,7 +234,7 @@ armour_penetration = 50 var/breakthings = TRUE -/obj/item/projectile/bullet/sniper/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/bullet/sniper/on_hit(atom/target, blocked = 0) if((blocked != 100) && (!ismob(target) && breakthings)) target.ex_act(rand(1,2)) return ..() @@ -248,7 +248,7 @@ weaken = 0 breakthings = FALSE -/obj/item/projectile/bullet/sniper/soporific/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/bullet/sniper/soporific/on_hit(atom/target, blocked = 0) if((blocked != 100) && istype(target, /mob/living)) var/mob/living/L = target L.Sleeping(20) @@ -263,7 +263,7 @@ weaken = 0 breakthings = FALSE -/obj/item/projectile/bullet/sniper/haemorrhage/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/bullet/sniper/haemorrhage/on_hit(atom/target, blocked = 0) if((blocked != 100) && iscarbon(target)) var/mob/living/carbon/C = target C.bleed(100) @@ -293,7 +293,7 @@ damage = 20 armour_penetration = 0 -/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = 0, hit_zone) +/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = 0) . = ..() if((blocked != 100) && iscarbon(target)) var/mob/living/carbon/C = target diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 0dadac9de80..d0f9d4bc511 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -98,8 +98,8 @@ if(iscarbon(target)) var/mob/living/carbon/C = target if(C.dna.species.id == "pod") - randmuti(C) - randmut(C) + C.randmuti() + C.randmut() C.updateappearance() C.domutcheck() diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index c70c022d467..1c78b5c6f8e 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -150,7 +150,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/bilk/on_mob_life(mob/living/M) if(M.getBruteLoss() && prob(10)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 return ..() || . @@ -681,7 +681,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/bananahonk/on_mob_life(mob/living/M) if( ( istype(M, /mob/living/carbon/human) && M.job in list("Clown") ) || istype(M, /mob/living/carbon/monkey) ) - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) . = 1 return ..() || . @@ -695,7 +695,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/silencer/on_mob_life(mob/living/M) if(istype(M, /mob/living/carbon/human) && M.job in list("Mime")) - M.heal_organ_damage(1,1) + M.heal_bodypart_damage(1,1) . = 1 return ..() || . diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 6e2d5c607e0..3055d8733e0 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -24,7 +24,7 @@ /datum/reagent/consumable/tomatojuice/on_mob_life(mob/living/M) if(M.getFireLoss() && prob(20)) - M.heal_organ_damage(0,1, 0) + M.heal_bodypart_damage(0,1, 0) . = 1 ..() @@ -95,7 +95,7 @@ /datum/reagent/consumable/banana/on_mob_life(mob/living/M) if( ( istype(M, /mob/living/carbon/human) && M.job in list("Clown") ) || istype(M, /mob/living/carbon/monkey) ) - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) . = 1 ..() @@ -106,7 +106,7 @@ /datum/reagent/consumable/nothing/on_mob_life(mob/living/M) if(istype(M, /mob/living/carbon/human) && M.job in list("Mime")) - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) . = 1 ..() @@ -155,13 +155,13 @@ /datum/reagent/consumable/milk/on_mob_life(mob/living/M) if(M.getBruteLoss() && prob(20)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 if(holder.has_reagent("capsaicin")) holder.remove_reagent("capsaicin", 2) var/datum/dna/Mdna = M.has_dna() if(Mdna && Mdna.species && (Mdna.species.id == "plasmaman" || Mdna.species.id == "skeleton")) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 ..() @@ -173,7 +173,7 @@ /datum/reagent/consumable/soymilk/on_mob_life(mob/living/M) if(M.getBruteLoss() && prob(20)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 ..() @@ -185,7 +185,7 @@ /datum/reagent/consumable/cream/on_mob_life(mob/living/M) if(M.getBruteLoss() && prob(20)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 ..() @@ -411,7 +411,7 @@ M.bodytemperature = min(310, M.bodytemperature + (5 * TEMPERATURE_DAMAGE_COEFFICIENT)) M.Jitter(5) if(M.getBruteLoss() && prob(20)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) ..() . = 1 @@ -429,7 +429,7 @@ M.bodytemperature = min(310, M.bodytemperature + (5 * TEMPERATURE_DAMAGE_COEFFICIENT)) M.Jitter(5) if(M.getBruteLoss() && prob(20)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 8e130dac8ce..939f77472cf 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -173,13 +173,13 @@ /datum/reagent/drug/methamphetamine/overdose_process(mob/living/M) if(M.canmove && !istype(M.loc, /atom/movable)) - for(var/i = 0, i < 4, i++) + for(var/i in 1 to 4) step(M, pick(cardinal)) if(prob(20)) M.emote("laugh") if(prob(33)) M.visible_message("[M]'s hands flip out and flail everywhere!") - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() ..() @@ -252,12 +252,12 @@ /datum/reagent/drug/bath_salts/overdose_process(mob/living/M) M.hallucination += 10 if(M.canmove && !istype(M.loc, /atom/movable)) - for(var/i = 0, i < 8, i++) + for(var/i in 1 to 8) step(M, pick(cardinal)) if(prob(20)) M.emote(pick("twitch","drool","moan")) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index c10c97cdaca..e65c395f7c7 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -27,7 +27,7 @@ /datum/reagent/consumable/nutriment/on_mob_life(mob/living/M) if(prob(50)) - M.heal_organ_damage(1,0, 0) + M.heal_bodypart_damage(1,0, 0) . = 1 if(iscarbon(M)) var/mob/living/carbon/C = M @@ -44,7 +44,7 @@ /datum/reagent/consumable/vitamin/on_mob_life(mob/living/M) if(prob(50)) - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) . = 1 if(M.satiety < 600) M.satiety += 30 @@ -325,7 +325,7 @@ /datum/reagent/consumable/sprinkles/on_mob_life(mob/living/M) if(istype(M, /mob/living/carbon/human) && M.job in list("Security Officer", "Head of Security", "Detective", "Warden")) - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) . = 1 ..() @@ -457,5 +457,5 @@ /datum/reagent/consumable/honey/on_mob_life(mob/living/M) M.reagents.add_reagent("sugar",3) if(prob(20)) - M.heal_organ_damage(3,1) + M.heal_bodypart_damage(3,1) ..() diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index b81330a3099..ce375b1d228 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -38,7 +38,7 @@ M.setCloneLoss(0, 0) M.setOxyLoss(0, 0) M.radiation = 0 - M.heal_organ_damage(5,5, 0) + M.heal_bodypart_damage(5,5, 0) M.adjustToxLoss(-5, 0) M.hallucination = 0 M.setBrainLoss(0) @@ -163,7 +163,7 @@ /datum/reagent/medicine/rezadone/on_mob_life(mob/living/M) M.setCloneLoss(0) //Rezadone is almost never used in favor of cryoxadone. Hopefully this will change that. - M.heal_organ_damage(1,1, 0) + M.heal_bodypart_damage(1,1, 0) M.status_flags &= ~DISFIGURED ..() . = 1 @@ -579,7 +579,7 @@ /datum/reagent/medicine/morphine/overdose_process(mob/living/M) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() M.Dizzy(2) @@ -588,7 +588,7 @@ /datum/reagent/medicine/morphine/addiction_act_stage1(mob/living/M) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() M.Dizzy(2) @@ -597,7 +597,7 @@ /datum/reagent/medicine/morphine/addiction_act_stage2(mob/living/M) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() M.adjustToxLoss(1*REM, 0) @@ -608,7 +608,7 @@ /datum/reagent/medicine/morphine/addiction_act_stage3(mob/living/M) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() M.adjustToxLoss(2*REM, 0) @@ -619,7 +619,7 @@ /datum/reagent/medicine/morphine/addiction_act_stage4(mob/living/M) if(prob(33)) - var/obj/item/I = M.get_active_hand() + var/obj/item/I = M.get_active_held_item() if(I) M.drop_item() M.adjustToxLoss(3*REM, 0) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 8b4dc3b73c1..7c311d980b3 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -537,7 +537,7 @@ color = "#808080" // rgb: 128, 128, 128 /datum/reagent/chlorine/on_mob_life(mob/living/M) - M.take_organ_damage(1*REM, 0, 0) + M.take_bodypart_damage(1*REM, 0, 0) . = 1 ..() @@ -748,10 +748,8 @@ if(H.lip_style) H.lip_style = null H.update_body() - if(C.r_hand) - C.r_hand.clean_blood() - if(C.l_hand) - C.l_hand.clean_blood() + for(var/obj/item/I in C.held_items) + I.clean_blood() if(C.wear_mask) if(C.wear_mask.clean_blood()) C.update_inv_wear_mask() diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index b3fb7d29526..7f6c1c4cbb4 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -34,11 +34,11 @@ if(!M.has_dna()) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if((method==VAPOR && prob(min(33, reac_volume))) || method==INGEST || method==PATCH || method==INJECT) - randmuti(M) + M.randmuti() if(prob(98)) - randmutb(M) + M.randmutb() else - randmutg(M) + M.randmutg() M.updateappearance() M.domutcheck() ..() @@ -118,7 +118,7 @@ M.adjustToxLoss(rand(20,60)*REM, 0) . = 1 else if(prob(40)) - M.heal_organ_damage(5*REM,0, 0) + M.heal_bodypart_damage(5*REM,0, 0) . = 1 ..() diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 5943577d59c..b475c752c67 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -50,7 +50,7 @@ var/list/chemical_mob_spawn_nicecritters = list() // and possible friendly mobs playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) for(var/mob/living/carbon/C in viewers(get_turf(holder.my_atom), null)) - C.flash_eyes() + C.flash_act() for(var/i = 1, i <= amount_to_spawn, i++) var/chosen if (reaction_name == "Friendly Gold Slime") diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 38e316be26b..6cb48f90552 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -218,7 +218,7 @@ s.set_up(2, 1, location) s.start() for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/3, location)) - if(C.flash_eyes()) + if(C.flash_act()) if(get_dist(C, location) < 4) C.Weaken(5) else @@ -237,7 +237,7 @@ s.set_up(2, 1, location) s.start() for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) - if(C.flash_eyes()) + if(C.flash_act()) if(get_dist(C, location) < 4) C.Weaken(5) else @@ -297,16 +297,7 @@ var/location = get_turf(holder.my_atom) playsound(location, 'sound/effects/bang.ogg', 25, 1) for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/3, location)) - if(C.check_ear_prot()) - continue - C.show_message("BANG", 2) - C.Stun(5) - C.Weaken(5) - C.setEarDamage(C.ear_damage + rand(0, 5), max(C.ear_deaf,15)) - if(C.ear_damage >= 15) - C << "Your ears start to ring badly!" - else if(C.ear_damage >= 5) - C << "Your ears start to ring!" + C.soundbang_act(1, 5, rand(0, 5)) /datum/chemical_reaction/sonic_powder_deafen name = "sonic_powder_deafen" @@ -318,17 +309,7 @@ var/location = get_turf(holder.my_atom) playsound(location, 'sound/effects/bang.ogg', 25, 1) for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) - if(C.check_ear_prot()) - continue - C.show_message("BANG", 2) - C.Stun(5) - C.Weaken(5) - C.setEarDamage(C.ear_damage + rand(0, 5), max(C.ear_deaf,15)) - if(C.ear_damage >= 15) - C << "Your ears start to ring badly!" - else if(C.ear_damage >= 5) - C << "Your ears start to ring!" - + C.soundbang_act(1, 5, rand(0, 5)) /datum/chemical_reaction/phlogiston name = "phlogiston" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index ca2b41ffbe7..fd73906d8bc 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -167,7 +167,7 @@ playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) for(var/mob/living/carbon/C in viewers(get_turf(holder.my_atom), null)) - C.flash_eyes() + C.flash_act() for(var/i = 1, i <= 4 + rand(1,2), i++) var/chosen = pick(borks) @@ -195,7 +195,7 @@ playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) for(var/mob/living/carbon/M in viewers(get_turf(holder.my_atom), null)) - M.flash_eyes() + M.flash_act() for(var/i = 1, i <= 4 + rand(1,2), i++) var/chosen = pick(borks) diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 08b12d92666..1ed89a74db8 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -78,7 +78,7 @@ var/t = stripped_input(user, "What would you like to label the blood pack?", name, null, 53) if(!user.canUseTopic(src)) return - if(user.get_active_hand() != I) + if(user.get_active_held_item() != I) return if(loc != user) return diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 6a1604a4c26..387e56aaf9c 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -3,7 +3,7 @@ name = "Cyborg Endoskeleton" id = "borg_suit" build_type = MECHFAB - build_path = /obj/item/robot_parts/robot_suit + build_path = /obj/item/robot_suit materials = list(MAT_METAL=15000) construction_time = 500 category = list("Cyborg") @@ -12,7 +12,7 @@ name = "Cyborg Torso" id = "borg_chest" build_type = MECHFAB - build_path = /obj/item/robot_parts/chest + build_path = /obj/item/bodypart/chest/robot materials = list(MAT_METAL=40000) construction_time = 350 category = list("Cyborg") @@ -21,7 +21,7 @@ name = "Cyborg Head" id = "borg_head" build_type = MECHFAB - build_path = /obj/item/robot_parts/head + build_path = /obj/item/bodypart/head/robot materials = list(MAT_METAL=5000) construction_time = 350 category = list("Cyborg") @@ -30,7 +30,7 @@ name = "Cyborg Left Arm" id = "borg_l_arm" build_type = MECHFAB - build_path = /obj/item/robot_parts/l_arm + build_path = /obj/item/bodypart/l_arm/robot materials = list(MAT_METAL=10000) construction_time = 200 category = list("Cyborg") @@ -39,7 +39,7 @@ name = "Cyborg Right Arm" id = "borg_r_arm" build_type = MECHFAB - build_path = /obj/item/robot_parts/r_arm + build_path = /obj/item/bodypart/r_arm/robot materials = list(MAT_METAL=10000) construction_time = 200 category = list("Cyborg") @@ -48,7 +48,7 @@ name = "Cyborg Left Leg" id = "borg_l_leg" build_type = MECHFAB - build_path = /obj/item/robot_parts/l_leg + build_path = /obj/item/bodypart/l_leg/robot materials = list(MAT_METAL=10000) construction_time = 200 category = list("Cyborg") @@ -57,7 +57,7 @@ name = "Cyborg Right Leg" id = "borg_r_leg" build_type = MECHFAB - build_path = /obj/item/robot_parts/r_leg + build_path = /obj/item/bodypart/r_leg/robot materials = list(MAT_METAL=10000) construction_time = 200 category = list("Cyborg") diff --git a/code/modules/spells/spell_types/barnyard.dm b/code/modules/spells/spell_types/barnyard.dm index e11115c64d3..a63d91c6437 100644 --- a/code/modules/spells/spell_types/barnyard.dm +++ b/code/modules/spells/spell_types/barnyard.dm @@ -47,4 +47,4 @@ target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1) playsound(get_turf(target), mSounds[randM], 50, 1) - target.flash_eyes() + target.flash_act() diff --git a/code/modules/spells/spell_types/charge.dm b/code/modules/spells/spell_types/charge.dm index 57088176cb2..ebd4933f58d 100644 --- a/code/modules/spells/spell_types/charge.dm +++ b/code/modules/spells/spell_types/charge.dm @@ -14,7 +14,7 @@ /obj/effect/proc_holder/spell/targeted/charge/cast(list/targets,mob/user = usr) for(var/mob/living/L in targets) - var/list/hand_items = list(L.get_active_hand(),L.get_inactive_hand()) + var/list/hand_items = list(L.get_active_held_item(),L.get_inactive_held_item()) var/charged_item = null var/burnt_out = 0 diff --git a/code/modules/spells/spell_types/infinite_guns.dm b/code/modules/spells/spell_types/infinite_guns.dm index 10b8612c858..d2cc1b32de3 100644 --- a/code/modules/spells/spell_types/infinite_guns.dm +++ b/code/modules/spells/spell_types/infinite_guns.dm @@ -20,3 +20,4 @@ C.drop_item() var/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/GUN = new C.put_in_hands(GUN) + C.swap_hand(C.get_held_index_of_item(GUN)) diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index 84db7d1efca..1cf58b7fd9b 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -43,7 +43,7 @@ for(var/mob/M in targets) var/list/hand_items = list() if(iscarbon(M)) - hand_items = list(M.get_active_hand(),M.get_inactive_hand()) + hand_items = list(M.get_active_held_item(),M.get_inactive_held_item()) if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry marked_item = null @@ -92,7 +92,8 @@ var/mob/living/carbon/C = old_body for(var/obj/item/W in C) C.unEquip(W) - for(var/obj/item/organ/I in C.internal_organs) + for(var/X in C.internal_organs) + var/obj/item/organ/I = X I.Remove(C) I.forceMove(body_turf) var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf)) diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm index e4b02f8b08b..4d6d1b5a3b3 100644 --- a/code/modules/spells/spell_types/summonitem.dm +++ b/code/modules/spells/spell_types/summonitem.dm @@ -17,8 +17,7 @@ /obj/effect/proc_holder/spell/targeted/summonitem/cast(list/targets,mob/user = usr) for(var/mob/living/L in targets) - var/list/hand_items = list(L.get_active_hand(),L.get_inactive_hand()) - var/butterfingers = 0 + var/list/hand_items = list(L.get_active_held_item(),L.get_inactive_held_item()) var/message if(!marked_item) //linking item to the spell @@ -93,17 +92,7 @@ if(item_to_retrive.loc) item_to_retrive.loc.visible_message("The [item_to_retrive.name] suddenly disappears!") - - - if(L.hand) //left active hand - if(!L.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1)) - if(!L.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1)) - butterfingers = 1 - else //right active hand - if(!L.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1)) - if(!L.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1)) - butterfingers = 1 - if(butterfingers) + if(!L.put_in_hands(item_to_retrive)) item_to_retrive.loc = L.loc item_to_retrive.loc.visible_message("The [item_to_retrive.name] suddenly appears!") playsound(get_turf(L),"sound/magic/SummonItems_generic.ogg",50,1) diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm index 51fa79bccc7..7cc593a1d0d 100644 --- a/code/modules/spells/spell_types/touch_attacks.dm +++ b/code/modules/spells/spell_types/touch_attacks.dm @@ -24,17 +24,8 @@ sleep(1) /obj/effect/proc_holder/spell/targeted/touch/proc/ChargeHand(mob/living/carbon/user) - var/hand_handled = 1 attached_hand = new hand_path(src) - if(user.hand) //left active hand - if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1)) - if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1)) - hand_handled = 0 - else //right active hand - if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1)) - if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1)) - hand_handled = 0 - if(!hand_handled) + if(!user.put_in_hands(attached_hand)) qdel(attached_hand) charge_counter = charge_max attached_hand = null diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index e040b43b643..fdc5247f4aa 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -7,7 +7,7 @@ /datum/station_goal/bluespace_cannon/get_report() return {"Our military presence is inadequate in your sector. - We need you to construct BSA-[rand(0-99)] Artillery position aboard your station. + We need you to construct BSA-[rand(1,99)] Artillery position aboard your station. Base parts should be availible for shipping by your cargo shuttle. -Nanotrasen Naval Command"} @@ -218,7 +218,7 @@ var/notice var/target use_power = 0 - circuit = /obj/machinery/computer/bsa_control + circuit = /obj/item/weapon/circuitboard/machine/computer/bsa_control icon = 'icons/obj/machines/particle_accelerator.dmi' icon_state = "control_boxp" var/area_aim = FALSE //should also show areas for targeting diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 6de3312238f..7f831986f2a 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -7,7 +7,7 @@ #define VAULT_NOBREATH "Lung Enhancement" #define VAULT_FIREPROOF "Thermal Regulation" #define VAULT_STUNTIME "Neural Repathing" -#define VAULT_ARMOUR "Bone Reinforcment" +#define VAULT_ARMOUR "Bone Reinforcement" /datum/station_goal/dna_vault name = "DNA Vault" @@ -20,7 +20,7 @@ animal_count = rand(15,20) //might be too few given ~15 roundstart stationside ones human_count = rand(round(0.75 * ticker.totalPlayersReady) , ticker.totalPlayersReady) // 75%+ roundstart population. var/non_standard_plants = non_standard_plants_count() - plant_count = rand(round(0.7 * non_standard_plants),round(0.9 * non_standard_plants)) + plant_count = rand(round(0.5 * non_standard_plants),round(0.7 * non_standard_plants)) /datum/station_goal/dna_vault/proc/non_standard_plants_count() . = 0 @@ -52,7 +52,7 @@ if(..()) return TRUE for(var/obj/machinery/dna_vault/V in machines) - if(V.animals.len >= animal_count && V.plants.len >= plant_count && V.dna >= human_count) + if(V.animals.len >= animal_count && V.plants.len >= plant_count && V.dna.len >= human_count) return TRUE return FALSE diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 1e13586eea8..2ebe45f2d31 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -2,8 +2,10 @@ /datum/surgery/amputation name = "amputation" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/sever_limb) - species = list(/mob/living/carbon/human) + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list("r_arm", "l_arm", "l_leg", "r_leg", "head") + requires_organic_bodypart = 0 + /datum/surgery_step/sever_limb name = "sever limb" @@ -16,7 +18,6 @@ /datum/surgery_step/sever_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) var/mob/living/carbon/human/L = target user.visible_message("[user] severs [L]'s [parse_zone(target_zone)]!", "You sever [L]'s [parse_zone(target_zone)].") - var/obj/item/bodypart/BP = L.get_bodypart(target_zone) - if(BP) - BP.drop_limb() + if(surgery.operated_bodypart) + surgery.operated_bodypart.drop_limb() return 1 \ No newline at end of file diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 42b001e1ddd..6e4ee1d069d 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -4,10 +4,11 @@ desc = "why is it detached..." force = 3 throwforce = 3 + icon = 'icons/mob/human_parts.dmi' icon_state = "" layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor - var/mob/living/carbon/human/owner = null - var/status = ORGAN_ORGANIC + var/mob/living/carbon/owner = null + var/status = BODYPART_ORGANIC var/body_zone //"chest", "l_arm", etc , used for def_zone var/body_part = null //bitflag used to check which clothes cover this bodypart var/brutestate = 0 @@ -16,6 +17,7 @@ var/burn_dam = 0 var/max_damage = 0 var/list/embedded_objects = list() + var/held_index = 0 //are we a hand? if so, which one! //Coloring and proper item icon update var/skin_tone = "" @@ -27,10 +29,14 @@ var/mutation_color = "" var/no_update = 0 + var/animal_origin = null //for nonhuman bodypart (e.g. monkey) + var/dismemberable = 1 //whether it can be dismembered with a weapon. + var/px_x = 0 var/px_y = 0 - var/state_flags + var/species_flags_list = list() + var/dmg_overlay_type //the type of damage overlay (if any) to use when this bodypart is bruised/burned. /obj/item/bodypart/examine(mob/user) ..() @@ -52,7 +58,7 @@ if(ishuman(C)) var/mob/living/carbon/human/H = C if(EASYLIMBATTACHMENT in H.dna.species.specflags) - if(!H.get_bodypart(body_zone)) + if(!H.get_bodypart(body_zone) && !animal_origin) if(H == user) H.visible_message("[H] jams [src] into \his empty socket!",\ "You force [src] into your empty socket, and it locks into place!") @@ -71,8 +77,8 @@ user << "There is nothing left inside [src]!" return playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1) - user.visible_message("[user] begins to cut through the bone in [src].",\ - "You begin to cut through the bone in [src]...") + user.visible_message("[user] begins to cut open [src].",\ + "You begin to cut open [src]...") if(do_after(user, 54, target = src)) drop_organs(user) else @@ -80,27 +86,30 @@ /obj/item/bodypart/throw_impact(atom/hit_atom) ..() - playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1) + if(status != BODYPART_ROBOTIC) + playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1) pixel_x = rand(-3, 3) pixel_y = rand(-3, 3) +//empties the bodypart from its organs and other things inside it /obj/item/bodypart/proc/drop_organs(mob/user) var/turf/T = get_turf(src) - playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) + if(status != BODYPART_ROBOTIC) + playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) for(var/obj/item/I in src) - I.loc = T + I.forceMove(T) //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. //Damage will not exceed max_damage using this proc //Cannot apply negative damage -/obj/item/bodypart/proc/take_damage(brute, burn) +/obj/item/bodypart/proc/take_damage(brute, burn, updating_health = 1) if(owner && (owner.status_flags & GODMODE)) return 0 //godmode brute = max(brute * config.damage_multiplier,0) burn = max(burn * config.damage_multiplier,0) - if(status == ORGAN_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger + if(status == BODYPART_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger brute = max(0, brute - 5) burn = max(0, burn - 4) @@ -125,7 +134,7 @@ burn_dam += can_inflict else return 0 - if(owner) + if(owner && updating_health) owner.updatehealth() return update_bodypart_damage_state() @@ -133,17 +142,17 @@ //Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all. //Damage cannot go below zero. //Cannot remove negative damage (i.e. apply damage) -/obj/item/bodypart/proc/heal_damage(brute, burn, robotic) +/obj/item/bodypart/proc/heal_damage(brute, burn, only_robotic = 0, only_organic = 1, updating_health = 1) - if(robotic && status != ORGAN_ROBOTIC) //This makes organic limbs not heal when the proc is in Robotic mode. + if(only_robotic && status != BODYPART_ROBOTIC) //This makes organic limbs not heal when the proc is in Robotic mode. return - if(!robotic && status == ORGAN_ROBOTIC) //This makes robolimbs not healable by chems. + if(only_organic && status != BODYPART_ORGANIC) //This makes robolimbs not healable by chems. return brute_dam = max(brute_dam - brute, 0) burn_dam = max(burn_dam - burn, 0) - if(owner) + if(owner && updating_health) owner.updatehealth() return update_bodypart_damage_state() @@ -156,14 +165,13 @@ //Updates an organ's brute/burn states for use by update_damage_overlays() //Returns 1 if we need to update overlays. 0 otherwise. /obj/item/bodypart/proc/update_bodypart_damage_state() - if(status == ORGAN_ORGANIC) //Robotic limbs show no damage - RR - var/tbrute = round( (brute_dam/max_damage)*3, 1 ) - var/tburn = round( (burn_dam/max_damage)*3, 1 ) - if((tbrute != brutestate) || (tburn != burnstate)) - brutestate = tbrute - burnstate = tburn - return 1 - return 0 + var/tbrute = round( (brute_dam/max_damage)*3, 1 ) + var/tburn = round( (burn_dam/max_damage)*3, 1 ) + if((tbrute != brutestate) || (tburn != burnstate)) + brutestate = tbrute + burnstate = tburn + return 1 + return 0 @@ -182,47 +190,57 @@ owner.update_damage_overlays() //we inform the bodypart of the changes that happened to the owner, or give it the informations from a source mob. -/obj/item/bodypart/proc/update_limb(dropping_limb, mob/living/carbon/human/source) - var/mob/living/carbon/human/H +/obj/item/bodypart/proc/update_limb(dropping_limb, mob/living/carbon/source) + var/mob/living/carbon/C if(source) - H = source + C = source else - H = owner - if(!istype(H)) - return + C = owner - should_draw_greyscale = FALSE + if(!animal_origin) + var/mob/living/carbon/human/H = C + should_draw_greyscale = FALSE - var/datum/species/S = H.dna.species - species_id = S.limbs_id + var/datum/species/S = H.dna.species + species_id = S.limbs_id + species_flags_list = H.dna.species.specflags - if(S.use_skintones) - skin_tone = H.skin_tone - should_draw_greyscale = TRUE - else - skin_tone = "" - - body_gender = H.gender - should_draw_gender = S.sexes - - if(MUTCOLORS in S.specflags) - if(S.fixed_mut_color) - species_color = S.fixed_mut_color + if(S.use_skintones) + skin_tone = H.skin_tone + should_draw_greyscale = TRUE else - species_color = H.dna.features["mcolor"] - should_draw_greyscale = TRUE - else - species_color = "" + skin_tone = "" - if(H.disabilities & HUSK) - species_id = "husk" + body_gender = H.gender + should_draw_gender = S.sexes + + if(MUTCOLORS in S.specflags) + if(S.fixed_mut_color) + species_color = S.fixed_mut_color + else + species_color = H.dna.features["mcolor"] + should_draw_greyscale = TRUE + else + species_color = "" + + if(!dropping_limb && H.dna.check_mutation(HULK)) + mutation_color = "00aa00" + else + mutation_color = "" + + dmg_overlay_type = S.damage_overlay_type + + else if(animal_origin == MONKEY_BODYPART) //currently monkeys are the only non human mob to have damage overlays. + dmg_overlay_type = animal_origin + + if(C.disabilities & HUSK) + species_id = "husk" //overrides species_id + dmg_overlay_type = "" //no damage overlay shown when husked should_draw_gender = FALSE should_draw_greyscale = FALSE - if(!dropping_limb && H.dna.check_mutation(HULK)) - mutation_color = "00aa00" - else - mutation_color = "" + if(status == BODYPART_ROBOTIC) + dmg_overlay_type = "robotic" if(dropping_limb) no_update = 1 //when attached, the limb won't be affected by the appearance changes of its mob owner. @@ -230,25 +248,49 @@ //to update the bodypart's icon when not attached to a mob /obj/item/bodypart/proc/update_icon_dropped() cut_overlays() - var/image/I = get_limb_icon(1) - if(I) + var/list/standing = get_limb_icon(1) + if(!standing.len) + icon_state = initial(icon_state)//no overlays found, we default back to initial icon. + return + for(var/image/I in standing) I.pixel_x = px_x I.pixel_y = px_y - add_overlay(I) + add_overlay(standing) //Gives you a proper icon appearance for the dismembered limb /obj/item/bodypart/proc/get_limb_icon(dropped) - var/image/I + icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone. + + var/list/standing = list() + + var/image_dir + if(dropped) + image_dir = SOUTH + if(dmg_overlay_type) + if(brutestate) + standing += image("icon"='icons/mob/dam_mob.dmi', "icon_state"="[dmg_overlay_type]_[body_zone]_[brutestate]0", "layer"=-DAMAGE_LAYER, "dir"=image_dir) + if(burnstate) + standing += image("icon"='icons/mob/dam_mob.dmi', "icon_state"="[dmg_overlay_type]_[body_zone]_0[burnstate]", "layer"=-DAMAGE_LAYER, "dir"=image_dir) + + + if(animal_origin) + if(status == BODYPART_ORGANIC) + if(species_id == "husk") + standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state"="[animal_origin]_husk_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) + else + standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state"="[animal_origin]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) + else + standing += image("icon"='icons/mob/augments.dmi', "icon_state"="[animal_origin]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) + return standing var/icon_gender = (body_gender == FEMALE) ? "f" : "m" //gender of the icon, if applicable if((body_zone != "head" && body_zone != "chest")) should_draw_gender = FALSE - var/image_dir - if(dropped) - image_dir = SOUTH - if(status == ORGAN_ORGANIC) + var/image/I + + if(status == BODYPART_ORGANIC) if(should_draw_greyscale) if(should_draw_gender) I = image("icon"='icons/mob/human_parts_greyscale.dmi', "icon_state"="[species_id]_[body_zone]_[icon_gender]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) @@ -264,11 +306,13 @@ I = image("icon"='icons/mob/augments.dmi', "icon_state"="[body_zone]_[icon_gender]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) else I = image("icon"='icons/mob/augments.dmi', "icon_state"="[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir) - return I + standing += I + return standing if(!should_draw_greyscale) - return I + standing += I + return standing //Greyscale Colouring var/draw_color @@ -283,14 +327,15 @@ if(draw_color) I.color = "#[draw_color]" //End Greyscale Colouring + standing += I - return I - + return standing /obj/item/bodypart/chest name = "chest" desc = "It's impolite to stare at a person's chest." + icon_state = "default_human_chest" max_damage = 200 body_zone = "chest" body_part = CHEST @@ -303,12 +348,43 @@ qdel(cavity_item) return ..() +/obj/item/bodypart/chest/drop_organs(mob/user) + if(cavity_item) + cavity_item.forceMove(user.loc) + cavity_item = null + ..() + +/obj/item/bodypart/chest/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_chest" + animal_origin = MONKEY_BODYPART + +/obj/item/bodypart/chest/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_chest_s" + dismemberable = 0 + max_damage = 500 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/chest/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/chest/larva + icon = 'icons/mob/animal_parts.dmi' + icon_state = "larva_chest_s" + dismemberable = 0 + max_damage = 50 + animal_origin = LARVA_BODYPART + /obj/item/bodypart/l_arm name = "left arm" desc = "Did you know that the word 'sinister' stems originally from the \ Latin 'sinestra' (left hand), because the left hand was supposed to \ be possessed by the devil? This arm appears to be possessed by no \ one though." + icon_state = "default_human_l_arm" attack_verb = list("slapped", "punched") max_damage = 50 body_zone ="l_arm" @@ -316,10 +392,32 @@ px_x = -6 px_y = 0 +/obj/item/bodypart/l_arm/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_l_arm" + animal_origin = MONKEY_BODYPART + px_x = -5 + px_y = -3 + +/obj/item/bodypart/l_arm/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_l_arm_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/l_arm/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + /obj/item/bodypart/r_arm name = "right arm" desc = "Over 87% of humans are right handed. That figure is much lower \ among humans missing their right arm." + icon_state = "default_human_r_arm" attack_verb = list("slapped", "punched") max_damage = 50 body_zone = "r_arm" @@ -327,10 +425,32 @@ px_x = 6 px_y = 0 +/obj/item/bodypart/r_arm/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_r_arm" + animal_origin = MONKEY_BODYPART + px_x = 5 + px_y = -3 + +/obj/item/bodypart/r_arm/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_r_arm_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/r_arm/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + /obj/item/bodypart/l_leg name = "left leg" desc = "Some athletes prefer to tie their left shoelaces first for good \ luck. In this instance, it probably would not have helped." + icon_state = "default_human_l_leg" attack_verb = list("kicked", "stomped") max_damage = 50 body_zone = "l_leg" @@ -338,12 +458,33 @@ px_x = -2 px_y = 12 +/obj/item/bodypart/l_leg/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_l_leg" + animal_origin = MONKEY_BODYPART + px_y = 4 + +/obj/item/bodypart/l_leg/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_l_leg_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/l_leg/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + /obj/item/bodypart/r_leg name = "right leg" desc = "You put your right leg in, your right leg out. In, out, in, out, \ shake it all about. And apparently then it detaches.\n\ The hokey pokey has certainly changed a lot since space colonisation." // alternative spellings of 'pokey' are availible + icon_state = "default_human_r_leg" attack_verb = list("kicked", "stomped") max_damage = 50 body_zone = "r_leg" @@ -351,6 +492,26 @@ px_x = 2 px_y = 12 +/obj/item/bodypart/r_leg/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_r_leg" + animal_origin = MONKEY_BODYPART + px_y = 4 + +/obj/item/bodypart/r_leg/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_r_leg_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/r_leg/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + ///////////////////////////////////////////////////////////////////////// diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 5d2e56971d7..b6218ceaea6 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -1,26 +1,33 @@ /obj/item/bodypart/proc/can_dismember(obj/item/I) - . = (get_damage() >= (max_damage - I.armour_penetration/2)) + if(dismemberable) + . = (get_damage() >= (max_damage - I.armour_penetration/2)) //Dismember a limb /obj/item/bodypart/proc/dismember(dam_type = BRUTE) - var/mob/living/carbon/human/H = owner - if(!istype(H) || (NODISMEMBER in H.dna.species.specflags)) // species don't allow dismemberment + if(!owner) return 0 + var/mob/living/carbon/C = owner + if(!dismemberable) + return 0 + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(NODISMEMBER in H.dna.species.specflags) // species don't allow dismemberment + return 0 - var/obj/item/bodypart/affecting = H.get_bodypart("chest") + var/obj/item/bodypart/affecting = C.get_bodypart("chest") affecting.take_damage(Clamp(brute_dam/2, 15, 50), Clamp(burn_dam/2, 0, 50)) //Damage the chest based on limb's existing damage - H.visible_message("[H]'s [src.name] has been violently dismembered!") - H.emote("scream") + C.visible_message("[C]'s [src.name] has been violently dismembered!") + C.emote("scream") drop_limb() if(dam_type == BURN) burn() return 1 - add_mob_blood(H) - var/turf/location = H.loc + add_mob_blood(C) + var/turf/location = C.loc if(istype(location)) - H.add_splatter_floor(location) + C.add_splatter_floor(location) var/direction = pick(cardinal) var/t_range = rand(2,max(throw_range/2, 2)) var/turf/target_turf = get_turf(src) @@ -34,88 +41,100 @@ /obj/item/bodypart/chest/dismember() - var/mob/living/carbon/human/H = owner - if(!istype(H) || (NODISMEMBER in H.dna.species.specflags)) //human's species don't allow dismemberment + if(!owner) return 0 + var/mob/living/carbon/C = owner + if(!dismemberable) + return 0 + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(NODISMEMBER in H.dna.species.specflags) // species don't allow dismemberment + return 0 var/organ_spilled = 0 - var/turf/T = get_turf(H) - H.add_splatter_floor(T) - playsound(get_turf(owner), 'sound/misc/splort.ogg', 80, 1) - for(var/X in owner.internal_organs) + var/turf/T = get_turf(C) + C.add_splatter_floor(T) + playsound(get_turf(C), 'sound/misc/splort.ogg', 80, 1) + for(var/X in C.internal_organs) var/obj/item/organ/O = X - if(O.zone != "chest") + var/org_zone = check_zone(O.zone) + if(org_zone != "chest") continue - O.Remove(owner) - O.loc = T + O.Remove(C) + O.forceMove(T) organ_spilled = 1 if(cavity_item) - cavity_item.loc = T + cavity_item.forceMove(T) cavity_item = null organ_spilled = 1 if(organ_spilled) - owner.visible_message("[owner]'s internal organs spill out onto the floor!") + C.visible_message("[C]'s internal organs spill out onto the floor!") return 1 //limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. /obj/item/bodypart/proc/drop_limb(special) - if(!ishuman(owner)) + if(!owner) return var/turf/T = get_turf(owner) - var/mob/living/carbon/human/H = owner + var/mob/living/carbon/C = owner if(!no_update) update_limb(1) - H.bodyparts -= src + C.bodyparts -= src + if(held_index) + C.unEquip(owner.get_item_for_held_index(held_index), 1) + C.hand_bodyparts[held_index] = null + owner = null - for(var/X in H.surgeries) //if we had an ongoing surgery on that limb, we stop it. + for(var/X in C.surgeries) //if we had an ongoing surgery on that limb, we stop it. var/datum/surgery/S = X - if(S.organ == src) - H.surgeries -= S + if(S.operated_bodypart == src) + C.surgeries -= S qdel(S) break for(var/obj/item/I in embedded_objects) embedded_objects -= I I.loc = src - if(!H.has_embedded_objects()) - H.clear_alert("embeddedobject") + if(!C.has_embedded_objects()) + C.clear_alert("embeddedobject") if(!special) - for(var/X in H.dna.mutations) //some mutations require having specific limbs to be kept. - var/datum/mutation/human/MT = X - if(MT.limb_req && MT.limb_req == body_zone) - MT.force_lose(H) + if(C.dna) + for(var/X in C.dna.mutations) //some mutations require having specific limbs to be kept. + var/datum/mutation/human/MT = X + if(MT.limb_req && MT.limb_req == body_zone) + MT.force_lose(C) - for(var/X in H.internal_organs) //internal organs inside the dismembered limb are dropped. + for(var/X in C.internal_organs) //internal organs inside the dismembered limb are dropped. var/obj/item/organ/O = X var/org_zone = check_zone(O.zone) if(org_zone != body_zone) continue - O.transfer_to_limb(src, H) + O.transfer_to_limb(src, C) update_icon_dropped() - src.loc = T - H.update_health_hud() //update the healthdoll - H.update_body() - H.update_hair() - H.update_canmove() + forceMove(T) + C.update_health_hud() //update the healthdoll + C.update_body() + C.update_hair() + C.update_canmove() //when a limb is dropped, the internal organs are removed from the mob and put into the limb -/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/human/H) - Remove(H) +/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C) + Remove(C) loc = LB -/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/H) - if(H.mind && H.mind.changeling) +/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C) + if(C.mind && C.mind.changeling) LB.brain = new //changeling doesn't lose its real brain organ, we drop a decoy. LB.brain.loc = LB else //if not a changeling, we put the brain organ inside the dropped head - Remove(H) //and put the player in control of the brainmob + Remove(C) //and put the player in control of the brainmob loc = LB LB.brain = src LB.brainmob = brainmob @@ -129,43 +148,39 @@ return /obj/item/bodypart/r_arm/drop_limb(special) - var/mob/living/carbon/human/H = owner + var/mob/living/carbon/C = owner ..() - if(istype(H) && !special) - if(H.handcuffed) - H.handcuffed.loc = H.loc - H.handcuffed.dropped(H) - H.handcuffed = null - H.update_handcuffed() - if(H.hud_used) - var/obj/screen/inventory/R = H.hud_used.inv_slots[slot_r_hand] + if(C && !special) + if(C.handcuffed) + C.handcuffed.loc = C.loc + C.handcuffed.dropped(C) + C.handcuffed = null + C.update_handcuffed() + if(C.hud_used) + var/obj/screen/inventory/hand/R = C.hud_used.hand_slots["[held_index]"] if(R) R.update_icon() - if(H.r_hand) - H.unEquip(H.r_hand, 1) - if(H.gloves) - H.unEquip(H.gloves, 1) - H.update_inv_gloves() //to remove the bloody hands overlay + if(C.gloves) + C.unEquip(C.gloves, 1) + C.update_inv_gloves() //to remove the bloody hands overlay /obj/item/bodypart/l_arm/drop_limb(special) - var/mob/living/carbon/human/H = owner + var/mob/living/carbon/C = owner ..() - if(istype(H) && !special) - if(H.handcuffed) - H.handcuffed.loc = H.loc - H.handcuffed.dropped(H) - H.handcuffed = null - H.update_handcuffed() - if(H.hud_used) - var/obj/screen/inventory/L = H.hud_used.inv_slots[slot_l_hand] + if(C && !special) + if(C.handcuffed) + C.handcuffed.loc = C.loc + C.handcuffed.dropped(C) + C.handcuffed = null + C.update_handcuffed() + if(C.hud_used) + var/obj/screen/inventory/hand/L = C.hud_used.hand_slots["[held_index]"] if(L) L.update_icon() - if(H.l_hand) - H.unEquip(H.l_hand, 1) - if(H.gloves) - H.unEquip(H.gloves, 1) - H.update_inv_gloves() //to remove the bloody hands overlay + if(C.gloves) + C.unEquip(C.gloves, 1) + C.update_inv_gloves() //to remove the bloody hands overlay /obj/item/bodypart/r_leg/drop_limb(special) @@ -176,10 +191,8 @@ owner.legcuffed.dropped(owner) owner.legcuffed = null owner.update_inv_legcuffed() - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - if(H.shoes) - H.unEquip(H.shoes, 1) + if(owner.shoes) + owner.unEquip(owner.shoes, 1) ..() /obj/item/bodypart/l_leg/drop_limb(special) //copypasta @@ -190,21 +203,17 @@ owner.legcuffed.dropped(owner) owner.legcuffed = null owner.update_inv_legcuffed() - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - if(H.shoes) - H.unEquip(H.shoes, 1) + if(owner.shoes) + owner.unEquip(owner.shoes, 1) ..() /obj/item/bodypart/head/drop_limb(special) - var/mob/living/carbon/human/H = owner - if(istype(H)) - if(!special) - //Drop all worn head items - for(var/X in list(H.glasses, H.ears, H.wear_mask, H.head)) - var/obj/item/I = X - H.unEquip(I, 1) - name = "[H]'s head" + if(!special) + //Drop all worn head items + for(var/X in list(owner.glasses, owner.ears, owner.wear_mask, owner.head)) + var/obj/item/I = X + owner.unEquip(I, 1) + name = "[owner]'s head" ..() @@ -213,81 +222,76 @@ //Attach a limb to a human and drop any existing limb of that type. -/obj/item/bodypart/proc/replace_limb(mob/living/carbon/human/H, special) - if(!istype(H)) +/obj/item/bodypart/proc/replace_limb(mob/living/carbon/C, special) + if(!istype(C)) return - var/obj/item/bodypart/O = locate(src.type) in H.bodyparts - + var/obj/item/bodypart/O = locate(src.type) in C.bodyparts if(O) O.drop_limb(1) - attach_limb(H, special) + attach_limb(C, special) -/obj/item/bodypart/head/replace_limb(mob/living/carbon/human/H, special) - if(!istype(H)) +/obj/item/bodypart/head/replace_limb(mob/living/carbon/C, special) + if(!istype(C)) return - var/obj/item/bodypart/head/O = locate(src.type) in H.bodyparts + var/obj/item/bodypart/head/O = locate(src.type) in C.bodyparts if(O) if(!special) return else O.drop_limb(1) - attach_limb(H, special) + attach_limb(C, special) -/obj/item/bodypart/proc/attach_limb(mob/living/carbon/human/H, special) +/obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special) loc = null - owner = H - H.bodyparts += src + owner = C + C.bodyparts += src + if(held_index) + C.hand_bodyparts += src + if(C.hud_used) + var/obj/screen/inventory/hand/hand = C.hud_used.hand_slots["[held_index]"] + if(hand) + hand.update_icon() + C.update_inv_gloves() if(special) //non conventional limb attachment - for(var/X in H.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it. + for(var/X in C.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it. var/datum/surgery/S = X var/surgery_zone = check_zone(S.location) if(surgery_zone == body_zone) - H.surgeries -= S + C.surgeries -= S qdel(S) break update_bodypart_damage_state() - H.updatehealth() - H.update_body() - H.update_hair() - H.update_damage_overlays() - H.update_canmove() + C.updatehealth() + C.update_body() + C.update_hair() + C.update_damage_overlays() + C.update_canmove() -/obj/item/bodypart/r_arm/attach_limb(mob/living/carbon/human/H, special) - ..() - if(H.hud_used) - var/obj/screen/inventory/R = H.hud_used.inv_slots[slot_r_hand] - if(R) - R.update_icon() -/obj/item/bodypart/l_arm/attach_limb(mob/living/carbon/human/H, special) - ..() - if(H.hud_used) - var/obj/screen/inventory/L = H.hud_used.inv_slots[slot_l_hand] - if(L) - L.update_icon() - -/obj/item/bodypart/head/attach_limb(mob/living/carbon/human/H, special) +/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special) //Transfer some head appearance vars over if(brain) brainmob.container = null //Reset brainmob head var. brainmob.loc = brain //Throw mob into brain. brain.brainmob = brainmob //Set the brain to use the brainmob brainmob = null //Set head brainmob var to null - brain.Insert(H) //Now insert the brain proper + brain.Insert(C) //Now insert the brain proper brain = null //No more brain in the head - H.hair_color = hair_color - H.hair_style = hair_style - H.facial_hair_color = facial_hair_color - H.facial_hair_style = facial_hair_style - H.eye_color = eye_color - H.lip_style = lip_style - H.lip_color = lip_color + if(ishuman(C)) + var/mob/living/carbon/human/H = C + H.hair_color = hair_color + H.hair_style = hair_style + H.facial_hair_color = facial_hair_color + H.facial_hair_style = facial_hair_style + H.eye_color = eye_color + H.lip_style = lip_style + H.lip_color = lip_color if(real_name) - H.real_name = real_name + C.real_name = real_name real_name = "" name = initial(name) ..() @@ -297,21 +301,22 @@ /mob/living/proc/regenerate_limbs(noheal, excluded_limbs) return 0 -/mob/living/carbon/human/regenerate_limbs(noheal, list/excluded_limbs) +/mob/living/carbon/regenerate_limbs(noheal, list/excluded_limbs) var/list/limb_list = list("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg") if(excluded_limbs) limb_list -= excluded_limbs for(var/Z in limb_list) . += regenerate_limb(Z, noheal) +/ /mob/living/proc/regenerate_limb(limb_zone, noheal) return -/mob/living/carbon/human/regenerate_limb(limb_zone, noheal) +/mob/living/carbon/regenerate_limb(limb_zone, noheal) var/obj/item/bodypart/L if(get_bodypart(limb_zone)) return 0 - L = newBodyPart(limb_zone, 0, 0, src) + L = newBodyPart(limb_zone, 0, 0) if(L) if(!noheal) L.brute_dam = 0 diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 16c742fc6fd..c3d86b5d4a2 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -1,6 +1,8 @@ /obj/item/bodypart/head name = "head" desc = "Didn't make sense not to live for fun, your brain gets smart but your head gets dumb." + icon = 'icons/mob/human_parts.dmi' + icon_state = "default_human_head" max_damage = 200 body_zone = "head" body_part = HEAD @@ -10,7 +12,7 @@ px_x = 0 px_y = -8 - var/mob/living/carbon/brain/brainmob = null //The current occupant. + var/mob/living/brain/brainmob = null //The current occupant. var/obj/item/organ/brain/brain = null //The brain organ //Limb appearance info: @@ -30,7 +32,8 @@ /obj/item/bodypart/head/drop_organs(mob/user) var/turf/T = get_turf(src) - playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) + if(status != BODYPART_ROBOTIC) + playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) for(var/obj/item/I in src) if(I == brain) if(user) @@ -46,67 +49,77 @@ else I.loc = T -/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/human/source) - var/mob/living/carbon/human/H +/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/source) + var/mob/living/carbon/C if(source) - H = source + C = source else - H = owner - if(!istype(H)) - return - var/datum/species/S = H.dna.species - //First of all, name. - real_name = H.real_name + C = owner - //Facial hair - if(H.facial_hair_style && (FACEHAIR in S.specflags)) - facial_hair_style = H.facial_hair_style - if(S.hair_color) - if(S.hair_color == "mutcolor") - facial_hair_color = H.dna.features["mcolor"] - else - facial_hair_color = S.hair_color - else - facial_hair_color = H.facial_hair_color - hair_alpha = S.hair_alpha - else - facial_hair_style = "Shaved" - facial_hair_color = "000" - hair_alpha = 255 - //Hair - if(H.hair_style && (HAIR in S.specflags)) - hair_style = H.hair_style - if(S.hair_color) - if(S.hair_color == "mutcolor") - hair_color = H.dna.features["mcolor"] - else - hair_color = S.hair_color - else - hair_color = H.hair_color - hair_alpha = S.hair_alpha - else + real_name = C.real_name + if(C.disabilities & HUSK) + real_name = "Unknown" hair_style = "Bald" - hair_color = "000" - hair_alpha = initial(hair_alpha) - // lipstick - if(H.lip_style && (LIPS in S.specflags)) - lip_style = H.lip_style - lip_color = H.lip_color - else - lip_style = null - lip_color = "white" - // eyes - if(EYECOLOR in S.specflags) - eyes = S.eyes - eye_color = H.eye_color - else + facial_hair_style = "Shaved" eyes = "eyes" eye_color = "" + lip_style = null + + else if(!animal_origin) + var/mob/living/carbon/human/H = C + var/datum/species/S = H.dna.species + + //Facial hair + if(H.facial_hair_style && (FACEHAIR in S.specflags)) + facial_hair_style = H.facial_hair_style + if(S.hair_color) + if(S.hair_color == "mutcolor") + facial_hair_color = H.dna.features["mcolor"] + else + facial_hair_color = S.hair_color + else + facial_hair_color = H.facial_hair_color + hair_alpha = S.hair_alpha + else + facial_hair_style = "Shaved" + facial_hair_color = "000" + hair_alpha = 255 + //Hair + if(H.hair_style && (HAIR in S.specflags)) + hair_style = H.hair_style + if(S.hair_color) + if(S.hair_color == "mutcolor") + hair_color = H.dna.features["mcolor"] + else + hair_color = S.hair_color + else + hair_color = H.hair_color + hair_alpha = S.hair_alpha + else + hair_style = "Bald" + hair_color = "000" + hair_alpha = initial(hair_alpha) + // lipstick + if(H.lip_style && (LIPS in S.specflags)) + lip_style = H.lip_style + lip_color = H.lip_color + else + lip_style = null + lip_color = "white" + // eyes + if(EYECOLOR in S.specflags) + eyes = S.eyes + eye_color = H.eye_color + else + eyes = "eyes" + eye_color = "" + ..() /obj/item/bodypart/head/update_icon_dropped() var/list/standing = get_limb_icon(1) - if(!standing) + if(!standing.len) + icon_state = initial(icon_state)//no overlays found, we default back to initial icon. return for(var/image/I in standing) I.pixel_x = px_x @@ -115,13 +128,11 @@ /obj/item/bodypart/head/get_limb_icon(dropped) cut_overlays() - var/image/I = ..() - var/list/standing = list() - standing += I + var/list/standing = ..() if(dropped) //certain overlays only appear when the limb is being detached from its owner. var/datum/sprite_accessory/S - if(status != ORGAN_ROBOTIC) //having a robotic head hides certain features. + if(status != BODYPART_ROBOTIC) //having a robotic head hides certain features. //facial hair if(facial_hair_style) S = facial_hair_styles_list[facial_hair_style] @@ -133,7 +144,12 @@ //Applies the debrained overlay if there is no brain if(!brain) - standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER, "dir"=SOUTH) + if(animal_origin == ALIEN_BODYPART) + standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state" = "debrained_alien_s", "layer" = -HAIR_LAYER, "dir"=SOUTH) + else if(animal_origin == LARVA_BODYPART) + standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state" = "debrained_larva_s", "layer" = -HAIR_LAYER, "dir"=SOUTH) + else if(!(NOBLOOD in species_flags_list)) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER, "dir"=SOUTH) else if(hair_style) S = hair_styles_list[hair_style] @@ -156,9 +172,36 @@ img_eyes_s.color = "#" + eye_color standing += img_eyes_s - if(standing.len) - return standing + return standing /obj/item/bodypart/head/burn() drop_organs() ..() + +/obj/item/bodypart/head/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_head" + animal_origin = MONKEY_BODYPART + +/obj/item/bodypart/head/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_head_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 500 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/head/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/head/larva + icon = 'icons/mob/animal_parts.dmi' + icon_state = "larva_head_s" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 50 + animal_origin = LARVA_BODYPART diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index f3e6fdbeabc..9f2c6ac37c1 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -10,55 +10,48 @@ if(L.body_zone == zone) return L -//Mob has their active hand -/mob/proc/has_active_hand() - return 1 +/mob/living/carbon/has_hand_for_held_index(i) + if(i) + var/obj/item/bodypart/L = hand_bodyparts[i] + if(L) + return L + return FALSE + + -/mob/living/carbon/human/has_active_hand() - var/obj/item/bodypart/L - if(hand) - L = get_bodypart("l_arm") - else - L = get_bodypart("r_arm") - if(!L) - return 0 - return 1 /mob/proc/has_left_hand() + return TRUE + +/mob/living/carbon/has_left_hand() + for(var/obj/item/bodypart/L in hand_bodyparts) + if(L.held_index % 2) + return TRUE + return FALSE + +/mob/living/carbon/alien/larva/has_left_hand() return 1 -/mob/living/carbon/human/has_left_hand() - var/obj/item/bodypart/L - L = get_bodypart("l_arm") - if(!L) - return 0 - return 1 /mob/proc/has_right_hand() + return TRUE + +/mob/living/carbon/has_right_hand() + for(var/obj/item/bodypart/L in hand_bodyparts) + if(!(L.held_index % 2)) + return TRUE + return FALSE + +/mob/living/carbon/alien/larva/has_right_hand() return 1 -/mob/living/carbon/human/has_right_hand() - var/obj/item/bodypart/L - L = get_bodypart("r_arm") - if(!L) - return 0 - return 1 //Limb numbers /mob/proc/get_num_arms() return 2 -/mob/proc/get_num_legs() - return 2 -/mob/proc/get_leg_ignore() - return 0 - -/mob/living/carbon/human/get_leg_ignore() - if(FLYING in dna.species.specflags) - return 1 - -/mob/living/carbon/human/get_num_arms() +/mob/living/carbon/get_num_arms() . = 0 for(var/X in bodyparts) var/obj/item/bodypart/affecting = X @@ -67,7 +60,19 @@ if(affecting.body_part == ARM_LEFT) .++ -/mob/living/carbon/human/get_num_legs() + +//sometimes we want to ignore that we don't have the required amount of arms. +/mob/proc/get_arm_ignore() + return 0 + +/mob/living/carbon/alien/larva/get_arm_ignore() + return 1 //so we can still handcuff larvas. + + +/mob/proc/get_num_legs() + return 2 + +/mob/living/carbon/get_num_legs() . = 0 for(var/X in bodyparts) var/obj/item/bodypart/affecting = X @@ -76,19 +81,36 @@ if(affecting.body_part == LEG_LEFT) .++ +//sometimes we want to ignore that we don't have the required amount of legs. +/mob/proc/get_leg_ignore() + return 0 + +/mob/living/carbon/alien/larva/get_leg_ignore() + return 1 + +/mob/living/carbon/human/get_leg_ignore() + if(FLYING in dna.species.specflags) + return 1 + /mob/living/proc/get_missing_limbs() return list() -/mob/living/carbon/human/get_missing_limbs() +/mob/living/carbon/get_missing_limbs() var/list/full = list("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg") for(var/zone in full) if(get_bodypart(zone)) full -= zone return full +/mob/living/carbon/alien/larva/get_missing_limbs() + var/list/full = list("head", "chest") + for(var/zone in full) + if(get_bodypart(zone)) + full -= zone + return full -//Remove all embedded objects from all limbs on the human mob -/mob/living/carbon/human/proc/remove_all_embedded_objects() +//Remove all embedded objects from all limbs on the carbon mob +/mob/living/carbon/proc/remove_all_embedded_objects() var/turf/T = get_turf(src) for(var/X in bodyparts) @@ -99,7 +121,7 @@ clear_alert("embeddedobject") -/mob/living/carbon/human/proc/has_embedded_objects() +/mob/living/carbon/proc/has_embedded_objects() . = 0 for(var/X in bodyparts) var/obj/item/bodypart/L = X @@ -108,7 +130,7 @@ //Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by -/proc/newBodyPart(zone, robotic, fixed_icon, mob/living/carbon/human/source) +/mob/living/carbon/proc/newBodyPart(zone, robotic, fixed_icon) var/obj/item/bodypart/L switch(zone) if("l_arm") @@ -124,13 +146,64 @@ if("chest") L = new /obj/item/bodypart/chest() if(L) - if(source) - L.update_limb(fixed_icon, source) - else if(fixed_icon) - L.no_update = 1//when attached, the limb won't be affected by the appearance changes of its mob owner. + L.update_limb(fixed_icon, src) if(robotic) - L.change_bodypart_status(ORGAN_ROBOTIC) + L.change_bodypart_status(BODYPART_ROBOTIC) + . = L +/mob/living/carbon/monkey/newBodyPart(zone, robotic, fixed_icon) + var/obj/item/bodypart/L + switch(zone) + if("l_arm") + L = new /obj/item/bodypart/l_arm/monkey() + if("r_arm") + L = new /obj/item/bodypart/r_arm/monkey() + if("head") + L = new /obj/item/bodypart/head/monkey() + if("l_leg") + L = new /obj/item/bodypart/l_leg/monkey() + if("r_leg") + L = new /obj/item/bodypart/r_leg/monkey() + if("chest") + L = new /obj/item/bodypart/chest/monkey() + if(L) + L.update_limb(fixed_icon, src) + if(robotic) + L.change_bodypart_status(BODYPART_ROBOTIC) + . = L + +/mob/living/carbon/alien/larva/newBodyPart(zone, robotic, fixed_icon) + var/obj/item/bodypart/L + switch(zone) + if("head") + L = new /obj/item/bodypart/head/larva() + if("chest") + L = new /obj/item/bodypart/chest/larva() + if(L) + L.update_limb(fixed_icon, src) + if(robotic) + L.change_bodypart_status(BODYPART_ROBOTIC) + . = L + +/mob/living/carbon/alien/humanoid/newBodyPart(zone, robotic, fixed_icon) + var/obj/item/bodypart/L + switch(zone) + if("l_arm") + L = new /obj/item/bodypart/l_arm/alien() + if("r_arm") + L = new /obj/item/bodypart/r_arm/alien() + if("head") + L = new /obj/item/bodypart/head/alien() + if("l_leg") + L = new /obj/item/bodypart/l_leg/alien() + if("r_leg") + L = new /obj/item/bodypart/r_leg/alien() + if("chest") + L = new /obj/item/bodypart/chest/alien() + if(L) + L.update_limb(fixed_icon, src) + if(robotic) + L.change_bodypart_status(BODYPART_ROBOTIC) . = L diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm new file mode 100644 index 00000000000..a5cefa1a0a7 --- /dev/null +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -0,0 +1,162 @@ + + +/obj/item/bodypart/l_arm/robot + name = "cyborg left arm" + desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." + attack_verb = list("slapped", "punched") + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "l_arm" + status = BODYPART_ROBOTIC + + +/obj/item/bodypart/r_arm/robot + name = "cyborg right arm" + desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." + attack_verb = list("slapped", "punched") + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "r_arm" + status = BODYPART_ROBOTIC + + +/obj/item/bodypart/l_leg/robot + name = "cyborg left leg" + desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." + attack_verb = list("kicked", "stomped") + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "l_leg" + status = BODYPART_ROBOTIC + + +/obj/item/bodypart/r_leg/robot + name = "cyborg right leg" + desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." + attack_verb = list("kicked", "stomped") + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "r_leg" + status = BODYPART_ROBOTIC + + +/obj/item/bodypart/chest/robot + name = "cyborg torso" + desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell." + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "chest" + status = BODYPART_ROBOTIC + var/wired = 0 + var/obj/item/weapon/stock_parts/cell/cell = null + +/obj/item/bodypart/chest/robot/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/weapon/stock_parts/cell)) + if(src.cell) + user << "You have already inserted a cell!" + return + else + if(!user.unEquip(W)) + return + W.loc = src + src.cell = W + user << "You insert the cell." + else if(istype(W, /obj/item/stack/cable_coil)) + if(src.wired) + user << "You have already inserted wire!" + return + var/obj/item/stack/cable_coil/coil = W + if (coil.use(1)) + src.wired = 1 + user << "You insert the wire." + else + user << "You need one length of coil to wire it!" + else + return ..() + +/obj/item/bodypart/chest/robot/Destroy() + if(cell) + qdel(cell) + cell = null + return ..() + + +/obj/item/bodypart/chest/robot/drop_organs(mob/user) + if(wired) + new /obj/item/stack/cable_coil(user.loc, 1) + if(cell) + cell.forceMove(user.loc) + cell = null + ..() + + +/obj/item/bodypart/head/robot + name = "cyborg head" + desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals." + item_state = "buildpipe" + icon = 'icons/obj/robot_parts.dmi' + flags = CONDUCT + icon_state = "head" + status = BODYPART_ROBOTIC + var/obj/item/device/assembly/flash/handheld/flash1 = null + var/obj/item/device/assembly/flash/handheld/flash2 = null + + + +/obj/item/bodypart/head/robot/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/device/assembly/flash/handheld)) + var/obj/item/device/assembly/flash/handheld/F = W + if(src.flash1 && src.flash2) + user << "You have already inserted the eyes!" + return + else if(F.crit_fail) + user << "You can't use a broken flash!" + return + else + if(!user.unEquip(W)) + return + F.loc = src + if(src.flash1) + src.flash2 = F + else + src.flash1 = F + user << "You insert the flash into the eye socket." + else if(istype(W, /obj/item/weapon/crowbar)) + if(flash1 || flash2) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + user << "You remove the flash from [src]." + if(flash1) + flash1.forceMove(user.loc) + flash1 = null + if(flash2) + flash2.forceMove(user.loc) + flash2 = null + else + user << "There are no flash to remove from [src]." + + else + return ..() + +/obj/item/bodypart/head/robot/Destroy() + if(flash1) + qdel(flash1) + flash1 = null + if(flash2) + qdel(flash2) + flash2 = null + return ..() + + +/obj/item/bodypart/head/robot/drop_organs(mob/user) + if(flash1) + flash1.forceMove(user.loc) + flash1 = null + if(flash2) + flash2.forceMove(user.loc) + flash2 = null + ..() diff --git a/code/modules/surgery/generic_steps.dm b/code/modules/surgery/generic_steps.dm index ee324e432b4..89b070f28cc 100644 --- a/code/modules/surgery/generic_steps.dm +++ b/code/modules/surgery/generic_steps.dm @@ -21,7 +21,7 @@ /datum/surgery_step/clamp_bleeders/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(locate(/datum/surgery_step/saw) in surgery.steps) - target.heal_organ_damage(20,0) + target.heal_bodypart_damage(20,0) return ..() @@ -69,7 +69,7 @@ /datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(locate(/datum/surgery_step/saw) in surgery.steps) - target.heal_organ_damage(45,0) + target.heal_bodypart_damage(45,0) return ..() @@ -84,9 +84,7 @@ user.visible_message("[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].", "You begin to saw through the bone in [target]'s [parse_zone(target_zone)]...") /datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(ishuman(target)) - var/mob/living/carbon/human/H = target - H.apply_damage(50,"brute","[target_zone]") + target.apply_damage(50,"brute","[target_zone]") user.visible_message("[user] saws [target]'s [parse_zone(target_zone)] open!", "You saw [target]'s [parse_zone(target_zone)] open.") return 1 diff --git a/code/modules/surgery/helpers.dm b/code/modules/surgery/helpers.dm index 79b641e3c06..32b294a7999 100644 --- a/code/modules/surgery/helpers.dm +++ b/code/modules/surgery/helpers.dm @@ -2,13 +2,13 @@ if(!istype(M)) return - var/mob/living/carbon/human/H + var/mob/living/carbon/C var/obj/item/bodypart/affecting var/selected_zone = user.zone_selected - if(istype(M, /mob/living/carbon/human)) - H = M - affecting = H.get_bodypart(check_zone(selected_zone)) + if(istype(M, /mob/living/carbon)) + C = M + affecting = C.get_bodypart(check_zone(selected_zone)) if(!M.lying && !isslime(M)) //if they're prone or a slime return @@ -29,9 +29,9 @@ if(affecting) if(!S.requires_bodypart) continue - if(S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC) + if(S.requires_organic_bodypart && affecting.status == BODYPART_ROBOTIC) continue - else if(H && S.requires_bodypart) //human with no limb in surgery zone when we need a limb + else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb continue if(!S.can_start(user, M)) continue @@ -49,14 +49,14 @@ return //during the input() another surgery was started at the same location. //we check that the surgery is still doable after the input() wait. - if(H) - affecting = H.get_bodypart(check_zone(selected_zone)) + if(C) + affecting = C.get_bodypart(check_zone(selected_zone)) if(affecting) if(!S.requires_bodypart) return - if(S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC) + if(S.requires_organic_bodypart && affecting.status == BODYPART_ROBOTIC) return - else if(H && S.requires_bodypart) + else if(C && S.requires_bodypart) return if(!S.can_start(user, M)) return @@ -76,7 +76,7 @@ user.visible_message("[user] removes the drapes from [M]'s [parse_zone(selected_zone)].", \ "You remove the drapes from [M]'s [parse_zone(selected_zone)].") qdel(current_surgery) - else if(istype(user.get_inactive_hand(), /obj/item/weapon/cautery) && current_surgery.can_cancel) + else if(istype(user.get_inactive_held_item(), /obj/item/weapon/cautery) && current_surgery.can_cancel) M.surgeries -= current_surgery user.visible_message("[user] mends the incision and removes the drapes from [M]'s [parse_zone(selected_zone)].", \ "You mend the incision and remove the drapes from [M]'s [parse_zone(selected_zone)].") diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index b3ab5a6379c..92704aa1356 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -26,14 +26,11 @@ I.removed(target) var/obj/item/weapon/implantcase/case - - if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase)) - case = user.get_item_by_slot(slot_l_hand) - else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase)) - case = user.get_item_by_slot(slot_r_hand) - else + for(var/obj/item/weapon/implantcase/ic in user.held_items) + case = ic + break + if(!case) case = locate(/obj/item/weapon/implantcase) in get_turf(target) - if(case && !case.imp) case.imp = I I.loc = case diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index f0a03ea7269..5e16b420f21 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -16,17 +16,17 @@ /datum/surgery_step/add_limb name = "replace limb" - implements = list(/obj/item/robot_parts = 100) + implements = list(/obj/item/bodypart = 100) time = 32 var/obj/item/bodypart/L = null // L because "limb" /datum/surgery_step/add_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/obj/item/robot_parts/aug = tool - if(istype(aug) && aug.body_zone != target_zone) + var/obj/item/bodypart/aug = tool + if(aug.status != BODYPART_ROBOTIC && aug.body_zone != target_zone) user << "[tool] isn't the right type for [parse_zone(target_zone)]." return -1 - L = surgery.organ + L = surgery.operated_bodypart if(L) user.visible_message("[user] begins to augment [target]'s [parse_zone(user.zone_selected)].", "You begin to augment [target]'s [parse_zone(user.zone_selected)]...") else @@ -45,15 +45,13 @@ /datum/surgery_step/add_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(L) - if(ishuman(target)) - var/mob/living/carbon/human/H = target - user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!", "You successfully augment [target]'s [parse_zone(target_zone)].") - L.change_bodypart_status(ORGAN_ROBOTIC, 1) - user.drop_item() - qdel(tool) - H.update_damage_overlays(0) - H.updatehealth() - add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]") + user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!", "You successfully augment [target]'s [parse_zone(target_zone)].") + L.change_bodypart_status(BODYPART_ROBOTIC, 1) + user.drop_item() + qdel(tool) + target.update_damage_overlays() + target.updatehealth() + add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]") else user << "[target] has no organic [parse_zone(target_zone)] there!" return 1 @@ -84,7 +82,7 @@ user.visible_message("[user] begins to install the chainsaw onto [target].", "You begin to install the chainsaw onto [target]...") /datum/surgery_step/chainsaw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(target.l_hand && target.r_hand) + if(!target.get_empty_held_indexes()) user << "You can't fit the chainsaw in while [target]'s hands are full!" return 0 else @@ -104,9 +102,7 @@ requires_organic_bodypart = 0 /datum/surgery/chainsaw_removal/can_start(mob/user, mob/living/carbon/target) - var/list/hands = get_both_hands(target) - var/M = locate(/obj/item/weapon/mounted_chainsaw) in hands - if(M) + if(target.is_holding_item_of_type(/obj/item/weapon/mounted_chainsaw)) return 1//can continue surgery else return 0//surgery will never be available @@ -120,8 +116,7 @@ user.visible_message("[user] begins sawing the chainsaw off of [target]'s arms.", "You begin removing [target]'s chainsaw...") /datum/surgery_step/chainsaw_removal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/list/hands = get_both_hands(target) - for(var/obj/item/weapon/mounted_chainsaw/V in hands) + for(var/obj/item/weapon/mounted_chainsaw/V in target.held_items) target.unEquip(V, 1) user.visible_message("[user] carefully saws [target]'s arm free of the chainsaw.", "You remove the chainsaw.") return 1 diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 8e8eccc4c8a..f2ccd41e270 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -77,7 +77,7 @@ organs[O.name] = O I = input("Remove which organ?", "Surgery", null, null) as null|anything in organs - if(I && user && target && user.Adjacent(target) && user.get_active_hand() == tool) + if(I && user && target && user.Adjacent(target) && user.get_active_held_item() == tool) I = organs[I] if(!I) return -1 user.visible_message("[user] begins to extract [I] from [target]'s [parse_zone(target_zone)].", diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 3cdf2328b19..76220ef9ddc 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -85,8 +85,7 @@ holder.w_class = 5 holder.materials = null - var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand) - var/obj/item/arm_item = owner.get_item_by_slot(arm_slot) + var/obj/item/arm_item = owner.get_active_held_item() if(arm_item) if(!owner.unEquip(arm_item)) @@ -95,13 +94,13 @@ else owner << "You drop [arm_item] to activate [src]!" - if(zone == "r_arm" ? !owner.put_in_r_hand(holder) : !owner.put_in_l_hand(holder)) + var/result = (zone == "r_arm" ? owner.put_in_r_hand(holder) : owner.put_in_l_hand(holder)) + if(!result) owner << "Your [src] fails to activate!" return // Activate the hand that now holds our item. - if(zone == "r_arm" ? owner.hand : !owner.hand) - owner.swap_hand() + owner.swap_hand(result)//... or the 1st hand if the index gets lost somehow owner.visible_message("[owner] extends [holder] from \his [zone == "r_arm" ? "right" : "left"] arm.", "You extend [holder] from your [zone == "r_arm" ? "right" : "left"] arm.", @@ -114,8 +113,7 @@ return // You can emag the arm-mounted implant by activating it while holding emag in it's hand. - var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand) - if(istype(owner.get_item_by_slot(arm_slot), /obj/item/weapon/card/emag) && emag_act()) + if(istype(owner.get_active_held_item(), /obj/item/weapon/card/emag) && emag_act()) return if(!holder || (holder in src)) diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 50c3875f258..eef8bf6dfd3 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -43,7 +43,7 @@ if(prob(10 * severity)) return owner << "Static obfuscates your vision!" - owner.flash_eyes(visual = 1) + owner.flash_act(visual = 1) /obj/item/organ/cyberimp/eyes/xray name = "X-ray implant" diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 55a3ff40153..3a5abcf647e 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -41,10 +41,7 @@ name = "anti-drop implant" desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle." var/active = 0 - var/l_hand_ignore = 0 - var/r_hand_ignore = 0 - var/obj/item/l_hand_obj = null - var/obj/item/r_hand_obj = null + var/list/stored_items = list() implant_color = "#DE7E00" slot = "brain_antidrop" origin_tech = "materials=4;programming=5;biotech=4" @@ -53,66 +50,41 @@ /obj/item/organ/cyberimp/brain/anti_drop/ui_action_click() active = !active if(active) - l_hand_obj = owner.l_hand - r_hand_obj = owner.r_hand - if(l_hand_obj) - if(owner.l_hand.flags & NODROP) - l_hand_ignore = 1 - else - owner.l_hand.flags |= NODROP - l_hand_ignore = 0 + for(var/obj/item/I in owner.held_items) + if(!(I.flags & NODROP)) + stored_items += I - if(r_hand_obj) - if(owner.r_hand.flags & NODROP) - r_hand_ignore = 1 - else - owner.r_hand.flags |= NODROP - r_hand_ignore = 0 - - if(!l_hand_obj && !r_hand_obj) + var/list/L = owner.get_empty_held_indexes() + if(L && L.len == owner.held_items.len) owner << "You are not holding any items, your hands relax..." active = 0 + stored_items = list() else - var/msg = 0 - msg += !l_hand_ignore && l_hand_obj ? 1 : 0 - msg += !r_hand_ignore && r_hand_obj ? 2 : 0 - switch(msg) - if(1) - owner << "Your left hand's grip tightens." - if(2) - owner << "Your right hand's grip tightens." - if(3) - owner << "Both of your hand's grips tighten." + for(var/obj/item/I in stored_items) + owner << "Your [owner.get_held_index_name(owner.get_held_index_of_item(I))]'s grip tightens." else release_items() owner << "Your hands relax..." - l_hand_obj = null - r_hand_obj = null + /obj/item/organ/cyberimp/brain/anti_drop/emp_act(severity) if(!owner) return var/range = severity ? 10 : 5 var/atom/A - var/obj/item/L_item = owner.l_hand - var/obj/item/R_item = owner.r_hand - release_items() ..() - if(L_item) + for(var/obj/item/I in stored_items) A = pick(oview(range)) - L_item.throw_at(A, range, 2) - owner << "Your left arm spasms and throws the [L_item.name]!" - if(R_item) - A = pick(oview(range)) - R_item.throw_at(A, range, 2) - owner << "Your right arm spasms and throws the [R_item.name]!" + I.throw_at(A, range, 2) + owner << "Your [owner.get_held_index_name(owner.get_held_index_of_item(I))] spasms and throws the [I.name]!" + stored_items = list() + /obj/item/organ/cyberimp/brain/anti_drop/proc/release_items() - if(!l_hand_ignore && l_hand_obj in owner.contents) - l_hand_obj.flags ^= NODROP - if(!r_hand_ignore && r_hand_obj in owner.contents) - r_hand_obj.flags ^= NODROP + for(var/obj/item/I in stored_items) + I.flags ^= NODROP + /obj/item/organ/cyberimp/brain/anti_drop/Remove(var/mob/living/carbon/M, special = 0) if(active) diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index f1ee5ec13f6..48915fd59bd 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -11,7 +11,7 @@ mob/proc/getorganslot(slot) mob/living/carbon/getorgan(typepath) return (locate(typepath) in internal_organs) -mob/living/carbon/getorganszone(zone, var/subzones = 0) +mob/living/carbon/getorganszone(zone, subzones = 0) var/list/returnorg = list() if(subzones) // Include subzones - groin for chest, eyes and mouth for head @@ -20,7 +20,8 @@ mob/living/carbon/getorganszone(zone, var/subzones = 0) if(zone == "chest") returnorg = getorganszone("groin") - for(var/obj/item/organ/O in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/O = X if(zone == O.zone) returnorg += O return returnorg diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index 7a0c9fa6718..5341c2bf09d 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -1,52 +1,50 @@ /datum/surgery/prosthetic_replacement name = "prosthetic replacement" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/add_prosthetic) - species = list(/mob/living/carbon/human) + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list("r_arm", "l_arm", "l_leg", "r_leg", "head") requires_bodypart = FALSE //need a missing limb /datum/surgery/prosthetic_replacement/can_start(mob/user, mob/living/carbon/target) - if(!ishuman(target)) + if(!iscarbon(target)) return 0 - var/mob/living/carbon/human/H = target - if(!H.get_bodypart(user.zone_selected)) //can only start if limb is missing + var/mob/living/carbon/C = target + if(!C.get_bodypart(user.zone_selected)) //can only start if limb is missing return 1 /datum/surgery_step/add_prosthetic name = "add prosthetic" - implements = list(/obj/item/robot_parts = 100, /obj/item/bodypart = 100) + implements = list(/obj/item/bodypart = 100) time = 32 var/organ_rejection_dam = 0 /datum/surgery_step/add_prosthetic/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/tool_body_zone - if(istype(tool, /obj/item/robot_parts)) - var/obj/item/robot_parts/RP = tool - tool_body_zone = RP.body_zone - else if(istype(tool, /obj/item/bodypart)) - var/obj/item/bodypart/L = tool - if(L.status != ORGAN_ROBOTIC) - organ_rejection_dam = 10 - if(target.dna.species.id != L.species_id) + var/obj/item/bodypart/BP = tool + if(ismonkey(target))// monkey patient only accept organic monkey limbs + if(BP.status == BODYPART_ROBOTIC || BP.animal_origin != MONKEY_BODYPART) + user << "[BP] doesn't match the patient's morphology." + return -1 + if(BP.status != BODYPART_ROBOTIC) + organ_rejection_dam = 10 + if(ishuman(target)) + if(BP.animal_origin) + user << "[BP] doesn't match the patient's morphology." + return -1 + var/mob/living/carbon/human/H = target + if(H.dna.species.id != BP.species_id) organ_rejection_dam = 30 - tool_body_zone = L.body_zone - if(target_zone == tool_body_zone) //so we can't replace a leg with an arm. + + if(target_zone == BP.body_zone) //so we can't replace a leg with an arm, or a human arm with a monkey arm. user.visible_message("[user] begins to replace [target]'s [parse_zone(target_zone)].", "You begin to replace [target]'s [parse_zone(target_zone)]...") else user << "[tool] isn't the right type for [parse_zone(target_zone)]." return -1 /datum/surgery_step/add_prosthetic/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/obj/item/bodypart/L - if(istype(tool, /obj/item/robot_parts)) - L = newBodyPart(target_zone, 1, 1) - user.drop_item() - qdel(tool) - else - L = tool - user.drop_item() + var/obj/item/bodypart/L = tool + user.drop_item() L.attach_limb(target) if(organ_rejection_dam) target.adjustToxLoss(organ_rejection_dam) diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm index 7117d276a76..fa9db1ae8ed 100644 --- a/code/modules/surgery/remove_embedded_object.dm +++ b/code/modules/surgery/remove_embedded_object.dm @@ -12,7 +12,7 @@ /datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - L = surgery.organ + L = surgery.operated_bodypart if(L) user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_selected)].", "You look for objects embedded in [target]'s [parse_zone(user.zone_selected)]...") else diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 1b8616c1fbb..26e57700ae5 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -10,26 +10,26 @@ var/list/possible_locs = list() //Multiple locations var/ignore_clothes = 0 //This surgery ignores clothes var/mob/living/carbon/target //Operation target mob - var/obj/item/organ/organ //Operable body part + var/obj/item/bodypart/operated_bodypart //Operable body part var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing. var/success_multiplier = 0 //Step success propability multiplier -/datum/surgery/New(surgery_target, surgery_location, surgery_organ) +/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart) ..() if(surgery_target) target = surgery_target target.surgeries += src if(surgery_location) location = surgery_location - if(surgery_organ) - organ = surgery_organ + if(surgery_bodypart) + operated_bodypart = surgery_bodypart /datum/surgery/Destroy() if(target) target.surgeries -= src target = null - organ = null + operated_bodypart = null return ..() @@ -45,7 +45,7 @@ var/datum/surgery_step/S = get_surgery_step() if(S) - if(S.try_op(user, target, user.zone_selected, user.get_active_hand(), src)) + if(S.try_op(user, target, user.zone_selected, user.get_active_held_item(), src)) return 1 return 0 diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm index e9394c806b2..1077931fcbf 100644 --- a/code/modules/telesci/bscrystal.dm +++ b/code/modules/telesci/bscrystal.dm @@ -62,7 +62,7 @@ return /obj/item/stack/sheet/bluespace_crystal/attack_hand(mob/user) - if (user.get_inactive_hand() == src) + if (user.get_inactive_held_item() == src) if(zero_amount()) // in this case, a sanity check return var/obj/item/weapon/ore/bluespace_crystal/BC = new(src) diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm index e3e110a2a83..a312bcecddf 100644 --- a/code/modules/tgui/states/hands.dm +++ b/code/modules/tgui/states/hands.dm @@ -15,7 +15,7 @@ return UI_CLOSE /mob/living/hands_can_use_topic(src_object) - if(src_object in get_both_hands(src)) + if(is_holding(src_object)) return UI_INTERACTIVE return UI_CLOSE diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm index 0df1bc9c0f1..75c136ea925 100644 --- a/code/modules/uplink/uplink_item.dm +++ b/code/modules/uplink/uplink_item.dm @@ -521,6 +521,7 @@ var/list/uplink_items = list() // Global list so we only initialize this once. deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry." item = /obj/item/weapon/sleeping_carp_scroll cost = 17 + surplus = 0 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang) /datum/uplink_item/stealthy_weapons/throwingweapons @@ -1111,7 +1112,7 @@ var/list/uplink_items = list() // Global list so we only initialize this once. exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang) /datum/uplink_item/badass/surplus/spawn_item(turf/loc, obj/item/device/uplink/U) - var/list/uplink_items = get_uplink_items() + var/list/uplink_items = get_uplink_items(ticker.mode) var/crate_value = 50 var/obj/structure/closet/crate/C = new(loc) @@ -1138,7 +1139,7 @@ var/list/uplink_items = list() // Global list so we only initialize this once. cost = 0 /datum/uplink_item/badass/random/spawn_item(turf/loc, obj/item/device/uplink/U) - var/list/uplink_items = get_uplink_items() + var/list/uplink_items = get_uplink_items(ticker.mode) var/list/possible_items = list() for(var/category in uplink_items) for(var/item in uplink_items[category]) diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 64223336da1..7e3cbf954ac 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -38,15 +38,18 @@ else buckled_mob.pixel_y = -4 +/obj/vehicle/scooter/buckle_mob(mob/living/M, force = 0) + if(!istype(M)) + return 0 + if(M.get_num_legs() < 2 && M.get_num_arms() <= 0) + M << "Your limbless body can't use [src]." + return 0 + . = ..() + /obj/vehicle/scooter/post_buckle_mob(mob/living/M) vehicle_move_delay = initial(vehicle_move_delay) - ..() if(M.get_num_legs() < 2) vehicle_move_delay ++ - if(M.get_num_arms() <= 0) - if(has_buckled_mobs())//to prevent the message displaying twice due to unbuckling - M << "Your limbless body flops off \the [src]." - unbuckle_mob(M) /obj/vehicle/scooter/skateboard name = "skateboard" diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index b6e29dc5844..f21275b6fce 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -52,7 +52,7 @@ //KEYS /obj/vehicle/proc/keycheck(mob/user) if(keytype) - if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype)) + if(user.is_holding_item_of_type(keytype)) return 1 else return 1 @@ -94,12 +94,14 @@ /obj/vehicle/relaymove(mob/user, direction) if(user.incapacitated()) unbuckle_mob(user) + return + if(world.time < next_vehicle_move) + return + next_vehicle_move = world.time + vehicle_move_delay if(keycheck(user)) - if(!Process_Spacemove(direction) || world.time < next_vehicle_move || !isturf(loc)) + if(!Process_Spacemove(direction) || !isturf(loc)) return - next_vehicle_move = world.time + vehicle_move_delay - step(src, direction) handle_vehicle_layer() diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 9057dff9547..c2aa26041cd 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -17,12 +17,12 @@ /obj/item/zombie_hand/equipped(mob/user, slot) . = ..() - switch(slot) - // Yes, these intentionally don't match - if(slot_l_hand) - icon_state = icon_right - if(slot_r_hand) - icon_state = icon_left + //these are intentionally inverted + var/i = user.get_held_index_of_item(src) + if(!(i % 2)) + icon_state = icon_left + else + icon_state = icon_right /obj/item/zombie_hand/afterattack(atom/target, mob/user, proximity_flag) . = ..() diff --git a/html/changelog.html b/html/changelog.html index e5ee7fea60f..9754c9fa064 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,40 @@ -->
+

12 September 2016

+

Joan updated:

+
    +
  • Cult structures can once again be constructed with runed metal.
  • +
  • Cult structures can now take damage and be destroyed. Artificers can repair them if they're damaged.
  • +
+

RemieRichards updated:

+
    +
  • Added the functionality for mobs to have multiple hands, this might have broken some things, so please report any weirdness
  • +
+

Shadowlight213 updated:

+
    +
  • The surplus crate and random item will now only contain items allowed by the gamemode
  • +
  • removes sleeping carp scroll from surplus crates
  • +
+

TheCarlSaganExpress updated:

+
    +
  • Crayons, lipstick, cigarettes, and penlights can now be inserted into PDAs.
  • +
+

phil235 updated:

+
    +
  • Monkeys can be dismembered.
  • +
  • Humans, monkeys and aliens can drop limbs when they are gibbed.
  • +
  • Roboticists can remove flashes, wires and power cells that they inserted in robot head or torso by using a crowbar on it.
  • +
  • visual wounds appear on a monkey's bodyparts when injured, exactly like humans.
  • +
  • Using a health analyzer on a monkey or alien shows the injuries to each bodypart.
  • +
  • Monkeys can become husks.
  • +
  • Human-monkey transformations now respect missing limbs. No more limb regrowth by becoming a monkey.
  • +
  • Changeling's regenerate ability also work while in monkey form.
  • +
  • Alien larva has its own gib and dust animation.
  • +
  • A bodypart that looks wounded still looks bloody when dismembered.
  • +
  • Amputation surgery now works on robotic limbs, and monkeys.
  • +
+

09 September 2016

Ergovisavi updated:

    @@ -1070,99 +1104,6 @@
    • Attacks will no longer miss missing limbs
    - -

    11 July 2016

    -

    Iamgoofball updated:

    -
      -
    • Fixes Nicotine's stun reduction
    • -
    -

    Joan updated:

    -
      -
    • The Function Call action that summons a Ratvarian Spear is no longer one-use; instead, it can be reused once every five minutes.
    • -
    • Clockwork Walls and Floors will appear as normal walls and plating to mesons, respectively.
    • -
    -

    coiax updated:

    -
      -
    • Syndicate bombs now use a more accurate timer.
    • -
    • Fixed a separate bug that caused bomb timers to take twice as long (ie. 60 seconds took 120 seconds)
    • -
    • The AI doomsday device timer is more accurate.
    • -
    • Fixes a bug where the doomsday device would take twice as long as it should.
    • -
    -

    optional name here updated:

    -
      -
    • The search function on security records consoles now works.
    • -
    - -

    09 July 2016

    -

    CoreOverload updated:

    -
      -
    • You can remove jetpack from a hardsuit by using screwdriver on it.
    • -
    -

    Crazylemon updated:

    -
      -
    • The map loader no longer resets when reading another map mid-load
    • -
    -

    Goofball Sanders updated:

    -
      -
    • Added a new plant to the game to encourage the Chef to be a more relevant job, alongside a recipe for a food related to it. Throw a cannabis leaf on a table and check the recipes list to find it.
    • -
    -

    Gun Hog updated:

    -
      -
    • Malf (Traitor) AI's Fireproof Core ability has been removed, as it was entirely obsolete.
    • -
    • Nanotrasen is proud to announce that conveyor belts can now be fabricated at your station's autolathes!
    • -
    -

    Iamgoofball updated:

    -
      -
    • Fixes the Atheist's Fedora's throw damage.
    • -
    -

    Joan updated:

    -
      -
    • Tips for Clock Cult may now show up.
    • -
    • The global component cache can only be accessed by clockwork slabs if there is at least one Tinkerer's Cache active.
    • -
    • Ratvarian Spears are now sharp and can be used to cut off limbs or butcher mobs.
    • -
    • Clock Cult silicons get an action button to communicate with other servants.
    • -
    • Clockwork Slabs now produce a component every 1 minute, 30 seconds, from every 1 minute.
    • -
    • The slab production time gain from each servant above 5 has been increased from 20 seconds to 30 seconds, and the maximum production time has been increased from 5 minutes to 6 minutes.
    • -
    • You can now transfer components between two clockwork slabs by attacking one slab, or a person holding a slab, with the other; this will transfer the attacking slab's components into the target slab.
    • -
    • Application scripture now requires 100 CV, from 75, Revenant scripture now requires 200 CV, from 150, and Judgment scripture now requires 300 CV, from 250.
    • -
    • However, converted windows, windoors, airlocks, and grilles will all provide some CV.
    • -
    -

    Lzimann & Keekenox updated:

    -
      -
    • You can now craft a baseball bat with 5 sheets of wood!
    • -
    -

    MrStonedOne updated:

    -
      -
    • Atmos on planets is now more realistic. There is an unseen upper atmosphere that gas changes get carried away into, causing planet turfs to revert back to their original gas mixture.
    • -
    • This should massively improve atmos run speed as all of lavaland won't be processing the moment somebody opens a door anymore
    • -
    -

    MrStonedOne, coiax updated:

    -
      -
    • View Variables can expand on associated lists with type keys. Only 90s admins will truely understand.
    • -
    -

    RemieRichards updated:

    -
      -
    • Added a Compact mode to the crafting tgui
    • -
    • Modified the back end of the crafting tgui so that it has well let's just say "a lot less" calls to certain functions, should lag a little less but don't expect miracles (you'd have to wait till we get a new version of ractive for those!)
    • -
    -

    coiax updated:

    -
      -
    • Podpeople (and venus human traps) are now no longer damaged, poisoned or obstructed by space vines. Explosive vines still damage them, because there's an actual explosion.
    • -
    • During a meteor shower, observers can automatically orbit threatening meteors via an action button and watch them hit the station.
    • -
    • Added Major Space Dust event, which is a meteor shower containing only space dust.
    • -
    • Fixes bug where meteors wouldn't move when spawned.
    • -
    • Meteor Shower split into three different events, Normal, Threatening and Catastrophic. They all have the same crew messages, but admins can tell the difference.
    • -
    • Damage to a shuttle while it is moving will now correctly make transit space turfs, rather than non-moving space.
    • -
    • AIs get a notification when hacking an APC, which can be clicked to jump your camera to the APC's location. AIs also get notification sounds when a hack has completed or failed.
    • -
    • Nuclear bombs now use a more accurate timer system, the same as gang dominators and shuttles.
    • -
    • Nuclear bombs now have a TGUI interface.
    • -
    • Fleshmend no longer regrows lost limbs.
    • -
    • Added free Regenerate power to changelings, which regrows all external limbs and internal organs (including the tongue if you lost your head). It costs 10 chemicals to use.
    • -
    • Fleshmend now costs 20 chemicals, down from 25.
    • -
    • Changeling revive power name changed from Regenerate to Revive.
    • -
    • When a player uses a communication console to ask for the codes to the self destruct, for better or for worse, the admins can set them with a single click. Whether the admins a) click the button b) actually give the random person the codes, is another thing entirely.
    • -
    • Servants of Ratvar get an alert if they have no tinkerer's caches constructed. Because it's important that they should.
    • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index b38c0a146bf..bfb5b9bc4fb 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -7005,3 +7005,34 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Shadowlight213: - tweak: Radiation storm direct tox loss removed - tweak: Radiation storms now cause a radiation alert to appear for the duration +2016-09-12: + Joan: + - rscadd: Cult structures can once again be constructed with runed metal. + - experiment: Cult structures can now take damage and be destroyed. Artificers can + repair them if they're damaged. + RemieRichards: + - rscadd: Added the functionality for mobs to have multiple hands, this might have + broken some things, so please report any weirdness + Shadowlight213: + - rscdel: The surplus crate and random item will now only contain items allowed + by the gamemode + - rscdel: removes sleeping carp scroll from surplus crates + TheCarlSaganExpress: + - rscadd: Crayons, lipstick, cigarettes, and penlights can now be inserted into + PDAs. + phil235: + - rscadd: Monkeys can be dismembered. + - rscadd: Humans, monkeys and aliens can drop limbs when they are gibbed. + - rscadd: Roboticists can remove flashes, wires and power cells that they inserted + in robot head or torso by using a crowbar on it. + - rscadd: visual wounds appear on a monkey's bodyparts when injured, exactly like + humans. + - rscadd: Using a health analyzer on a monkey or alien shows the injuries to each + bodypart. + - rscadd: Monkeys can become husks. + - bugfix: Human-monkey transformations now respect missing limbs. No more limb regrowth + by becoming a monkey. + - bugfix: Changeling's regenerate ability also work while in monkey form. + - bugfix: Alien larva has its own gib and dust animation. + - bugfix: A bodypart that looks wounded still looks bloody when dismembered. + - bugfix: Amputation surgery now works on robotic limbs, and monkeys. diff --git a/html/changelogs/AutoChangeLog-pr-20367.yml b/html/changelogs/AutoChangeLog-pr-20367.yml new file mode 100644 index 00000000000..18a3f33702d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-20367.yml @@ -0,0 +1,4 @@ +author: "Papa Bones" +delete-after: True +changes: + - tweak: "You can now rename the captain's sabre by using a pen on it." diff --git a/html/changelogs/AutoChangeLog-pr-20402.yml b/html/changelogs/AutoChangeLog-pr-20402.yml deleted file mode 100644 index e1cc68b7f55..00000000000 --- a/html/changelogs/AutoChangeLog-pr-20402.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Joan" -delete-after: True -changes: - - rscadd: "Cult structures can once again be constructed with runed metal." - - experiment: "Cult structures can now take damage and be destroyed. Artificers can repair them if they're damaged." diff --git a/html/changelogs/AutoChangeLog-pr-20412.yml b/html/changelogs/AutoChangeLog-pr-20412.yml new file mode 100644 index 00000000000..e45916006db --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-20412.yml @@ -0,0 +1,4 @@ +author: "PKPenguin321" +delete-after: True +changes: + - bugfix: "Tesla shocks from grilles will no longer do thousands and thousands of damage. They now properly deal burn damage that is equal to the current power in the powernet divided by 5000." diff --git a/html/changelogs/AutoChangeLog-pr-20436.yml b/html/changelogs/AutoChangeLog-pr-20436.yml new file mode 100644 index 00000000000..fc55c7f486b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-20436.yml @@ -0,0 +1,5 @@ +author: "Joan" +delete-after: True +changes: + - tweak: "The Recollection function of the clockwork slab is much more useful and easier to parse." + - wip: "Tweaked the Recital menus for scripture so the scripture are all in the proper order. This might fuck you up if you were used to the incorrect order, but you'll get used to it." diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 7eee4d7dc73..247d6a401f7 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index f073ff5b338..e915cb49e37 100644 Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ diff --git a/icons/mob/animal_parts.dmi b/icons/mob/animal_parts.dmi new file mode 100644 index 00000000000..b120e81d411 Binary files /dev/null and b/icons/mob/animal_parts.dmi differ diff --git a/icons/mob/augments.dmi b/icons/mob/augments.dmi index 8cbb3f03d5e..7ab1b3893d2 100644 Binary files a/icons/mob/augments.dmi and b/icons/mob/augments.dmi differ diff --git a/icons/mob/dam_human.dmi b/icons/mob/dam_human.dmi deleted file mode 100644 index d6d30c87f40..00000000000 Binary files a/icons/mob/dam_human.dmi and /dev/null differ diff --git a/icons/mob/dam_mob.dmi b/icons/mob/dam_mob.dmi new file mode 100644 index 00000000000..fe92746b43e Binary files /dev/null and b/icons/mob/dam_mob.dmi differ diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi index bddb6641c8a..58ba1d42168 100644 Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 9ec94d38800..413248185ef 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/mutant_bodyparts.dmi b/icons/mob/mutant_bodyparts.dmi index 518a57469e5..eafe937dc2c 100644 Binary files a/icons/mob/mutant_bodyparts.dmi and b/icons/mob/mutant_bodyparts.dmi differ diff --git a/icons/mob/wings.dmi b/icons/mob/wings.dmi index cd1a6d3b1cc..5f261b76fe3 100644 Binary files a/icons/mob/wings.dmi and b/icons/mob/wings.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index ffac4fc2f7e..29ab421834e 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/lavaland/ash_flora.dmi b/icons/obj/lavaland/ash_flora.dmi new file mode 100644 index 00000000000..d58541612d2 Binary files /dev/null and b/icons/obj/lavaland/ash_flora.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 455e2564fe0..14896210baf 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -558,7 +558,6 @@ #include "code\game\objects\effects\bump_teleporter.dm" #include "code\game\objects\effects\contraband.dm" #include "code\game\objects\effects\forcefields.dm" -#include "code\game\objects\effects\gibs.dm" #include "code\game\objects\effects\glowshroom.dm" #include "code\game\objects\effects\landmarks.dm" #include "code\game\objects\effects\manifest.dm" @@ -1276,6 +1275,7 @@ #include "code\modules\mining\laborcamp\laborminerals.dm" #include "code\modules\mining\laborcamp\laborshuttle.dm" #include "code\modules\mining\laborcamp\laborstacker.dm" +#include "code\modules\mining\lavaland\ash_flora.dm" #include "code\modules\mining\lavaland\lavaland_areas.dm" #include "code\modules\mining\lavaland\necropolis_chests.dm" #include "code\modules\mining\lavaland\ruins\gym.dm" @@ -1314,10 +1314,20 @@ #include "code\modules\mob\living\say.dm" #include "code\modules\mob\living\status_procs.dm" #include "code\modules\mob\living\ventcrawling.dm" +#include "code\modules\mob\living\brain\brain.dm" +#include "code\modules\mob\living\brain\brain_item.dm" +#include "code\modules\mob\living\brain\death.dm" +#include "code\modules\mob\living\brain\emote.dm" +#include "code\modules\mob\living\brain\life.dm" +#include "code\modules\mob\living\brain\MMI.dm" +#include "code\modules\mob\living\brain\posibrain.dm" +#include "code\modules\mob\living\brain\say.dm" +#include "code\modules\mob\living\brain\status_procs.dm" #include "code\modules\mob\living\carbon\carbon.dm" #include "code\modules\mob\living\carbon\carbon_defense.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" #include "code\modules\mob\living\carbon\carbon_movement.dm" +#include "code\modules\mob\living\carbon\damage_procs.dm" #include "code\modules\mob\living\carbon\death.dm" #include "code\modules\mob\living\carbon\emote.dm" #include "code\modules\mob\living\carbon\examine.dm" @@ -1328,6 +1338,7 @@ #include "code\modules\mob\living\carbon\update_icons.dm" #include "code\modules\mob\living\carbon\alien\alien.dm" #include "code\modules\mob\living\carbon\alien\alien_defense.dm" +#include "code\modules\mob\living\carbon\alien\damage_procs.dm" #include "code\modules\mob\living\carbon\alien\death.dm" #include "code\modules\mob\living\carbon\alien\life.dm" #include "code\modules\mob\living\carbon\alien\login.dm" @@ -1336,10 +1347,12 @@ #include "code\modules\mob\living\carbon\alien\say.dm" #include "code\modules\mob\living\carbon\alien\screen.dm" #include "code\modules\mob\living\carbon\alien\status_procs.dm" +#include "code\modules\mob\living\carbon\alien\update_icons.dm" #include "code\modules\mob\living\carbon\alien\humanoid\alien_powers.dm" #include "code\modules\mob\living\carbon\alien\humanoid\death.dm" #include "code\modules\mob\living\carbon\alien\humanoid\emote.dm" #include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm" +#include "code\modules\mob\living\carbon\alien\humanoid\humanoid_defense.dm" #include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm" #include "code\modules\mob\living\carbon\alien\humanoid\life.dm" #include "code\modules\mob\living\carbon\alien\humanoid\queen.dm" @@ -1352,28 +1365,17 @@ #include "code\modules\mob\living\carbon\alien\larva\emote.dm" #include "code\modules\mob\living\carbon\alien\larva\inventory.dm" #include "code\modules\mob\living\carbon\alien\larva\larva.dm" +#include "code\modules\mob\living\carbon\alien\larva\larva_defense.dm" #include "code\modules\mob\living\carbon\alien\larva\life.dm" #include "code\modules\mob\living\carbon\alien\larva\powers.dm" #include "code\modules\mob\living\carbon\alien\larva\update_icons.dm" #include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm" #include "code\modules\mob\living\carbon\alien\special\facehugger.dm" -#include "code\modules\mob\living\carbon\brain\brain.dm" -#include "code\modules\mob\living\carbon\brain\brain_item.dm" -#include "code\modules\mob\living\carbon\brain\death.dm" -#include "code\modules\mob\living\carbon\brain\emote.dm" -#include "code\modules\mob\living\carbon\brain\life.dm" -#include "code\modules\mob\living\carbon\brain\MMI.dm" -#include "code\modules\mob\living\carbon\brain\posibrain.dm" -#include "code\modules\mob\living\carbon\brain\say.dm" -#include "code\modules\mob\living\carbon\brain\status_procs.dm" +#include "code\modules\mob\living\carbon\human\damage_procs.dm" #include "code\modules\mob\living\carbon\human\death.dm" #include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" -#include "code\modules\mob\living\carbon\human\human_attackalien.dm" -#include "code\modules\mob\living\carbon\human\human_attackhand.dm" -#include "code\modules\mob\living\carbon\human\human_attackpaw.dm" -#include "code\modules\mob\living\carbon\human\human_damage.dm" #include "code\modules\mob\living\carbon\human\human_defense.dm" #include "code\modules\mob\living\carbon\human\human_defines.dm" #include "code\modules\mob\living\carbon\human\human_helpers.dm" @@ -1383,6 +1385,7 @@ #include "code\modules\mob\living\carbon\human\say.dm" #include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\species_types.dm" +#include "code\modules\mob\living\carbon\human\status_procs.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\whisper.dm" #include "code\modules\mob\living\carbon\monkey\death.dm" @@ -1390,16 +1393,20 @@ #include "code\modules\mob\living\carbon\monkey\inventory.dm" #include "code\modules\mob\living\carbon\monkey\life.dm" #include "code\modules\mob\living\carbon\monkey\monkey.dm" +#include "code\modules\mob\living\carbon\monkey\monkey_defense.dm" #include "code\modules\mob\living\carbon\monkey\punpun.dm" #include "code\modules\mob\living\carbon\monkey\update_icons.dm" +#include "code\modules\mob\living\silicon\damage_procs.dm" #include "code\modules\mob\living\silicon\death.dm" #include "code\modules\mob\living\silicon\examine.dm" #include "code\modules\mob\living\silicon\laws.dm" #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" #include "code\modules\mob\living\silicon\silicon.dm" +#include "code\modules\mob\living\silicon\silicon_defense.dm" #include "code\modules\mob\living\silicon\status_procs.dm" #include "code\modules\mob\living\silicon\ai\ai.dm" +#include "code\modules\mob\living\silicon\ai\ai_defense.dm" #include "code\modules\mob\living\silicon\ai\death.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" #include "code\modules\mob\living\silicon\ai\laws.dm" @@ -1416,6 +1423,7 @@ #include "code\modules\mob\living\silicon\pai\examine.dm" #include "code\modules\mob\living\silicon\pai\life.dm" #include "code\modules\mob\living\silicon\pai\pai.dm" +#include "code\modules\mob\living\silicon\pai\pai_defense.dm" #include "code\modules\mob\living\silicon\pai\personality.dm" #include "code\modules\mob\living\silicon\pai\say.dm" #include "code\modules\mob\living\silicon\pai\software.dm" @@ -1427,11 +1435,14 @@ #include "code\modules\mob\living\silicon\robot\life.dm" #include "code\modules\mob\living\silicon\robot\login.dm" #include "code\modules\mob\living\silicon\robot\robot.dm" +#include "code\modules\mob\living\silicon\robot\robot_defense.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" #include "code\modules\mob\living\silicon\robot\say.dm" +#include "code\modules\mob\living\simple_animal\animal_defense.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" +#include "code\modules\mob\living\simple_animal\damage_procs.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" #include "code\modules\mob\living\simple_animal\shade.dm" #include "code\modules\mob\living\simple_animal\simple_animal.dm" @@ -1852,6 +1863,7 @@ #include "code\modules\surgery\bodyparts\dismemberment.dm" #include "code\modules\surgery\bodyparts\head.dm" #include "code\modules\surgery\bodyparts\helpers.dm" +#include "code\modules\surgery\bodyparts\robot_bodyparts.dm" #include "code\modules\surgery\organs\augments_arms.dm" #include "code\modules\surgery\organs\augments_chest.dm" #include "code\modules\surgery\organs\augments_eyes.dm"