diff --git a/code/datums/components/disabilities/pollen.dm b/code/datums/components/disabilities/pollen.dm index e51b3c872e6..1c71405b7e9 100644 --- a/code/datums/components/disabilities/pollen.dm +++ b/code/datums/components/disabilities/pollen.dm @@ -59,7 +59,9 @@ if(locate(/obj/effect/plant) in things) trigger_allergy() return - if(locate(/obj/item/toy/bouquet) in things) + for(var/obj/item/toy/bouquet/flowers in things) + if(istype(flowers, /obj/item/toy/bouquet/fake)) //Plastic doesn't trigger pollen. + continue trigger_allergy() return for(var/obj/machinery/portable_atmospherics/hydroponics/irritant_tray in things) diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index e00e495ae37..c1bb487425e 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -86,7 +86,9 @@ stop() return if(!chance || prob(chance)) - play(get_sound(starttime)) + var/soundfile = get_sound(starttime) + if(soundfile) + play(soundfile) if(!timerid) timerid = addtimer(CALLBACK(src, PROC_REF(sound_loop), world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP) diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index dd7581a4724..499f64682c5 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -280,6 +280,23 @@ SSmotiontracker.ping(src,100) qdel(src) +/obj/effect/mine/stripping + mineitemtype = /obj/item/mine/stripping + +/obj/effect/mine/stripping/explode(var/mob/living/M) + if(triggered) // Prevents circular mine explosions from two mines detonating eachother + return + triggered = TRUE + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, src) + s.start() + if(istype(M)) + for(var/obj/item/content_item in M) + M.drop_from_inventory(content_item) + visible_message("\The [src.name] explodes, stripping [M]!") + SSmotiontracker.ping(src,100) + qdel(src) + /obj/effect/mine/gadget mineitemtype = /obj/item/mine/gadget @@ -415,6 +432,11 @@ desc = "A small explosive mine with a fire symbol on the side." minetype = /obj/effect/mine/incendiary +/obj/item/mine/stripping + name = "strip mine" + desc = "A small bluespace mine with a symbol of clothing with a slash through it.." + minetype = /obj/effect/mine/stripping + /obj/item/mine/gadget name = "gadget mine" desc = "A small pressure-triggered device. If no component is added, the internal release bolts will detonate in unison when triggered." diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index c6adf33e37d..4c1dd8d8146 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -35,6 +35,7 @@ var/power_usage = 1 var/power_use = 1 var/flickering = FALSE + var/single_use = FALSE pickup_sound = 'sound/items/pickup/device.ogg' drop_sound = 'sound/items/drop/device.ogg' @@ -96,6 +97,8 @@ . = ..(user) if(.) return TRUE + if(single_use && on) + return FALSE if(special_handling) return FALSE if(flickering) @@ -409,16 +412,17 @@ icon_state = "flare" item_state = "flare" actions_types = list() //just pull it manually, neckbeard. - var/fuel = 0 + var/fuel = 800 var/on_damage = 7 var/produce_heat = 1500 power_use = 0 drop_sound = 'sound/items/drop/gloves.ogg' pickup_sound = 'sound/items/pickup/gloves.ogg' light_system = MOVABLE_LIGHT + single_use = TRUE /obj/item/flashlight/flare/Initialize(mapload) - fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds. + fuel += rand(0, 200) . = ..() /obj/item/flashlight/flare/process() @@ -443,11 +447,9 @@ if(.) return TRUE // Usual checks - if(!fuel) + if(!fuel || on) to_chat(user, span_notice("It's out of fuel.")) return - if(on) - return // All good, turn it on. if(. == CAN_USE) user.visible_message(span_notice("[user] activates the flare."), span_notice("You pull the cord on the flare, activating it!")) @@ -477,11 +479,12 @@ light_color = "#49F37C" icon_state = "glowstick_green" item_state = "glowstick_green" - var/fuel = 0 - power_use = 0 + var/fuel = 1600 + power_use = FALSE + single_use = TRUE /obj/item/flashlight/glowstick/Initialize(mapload) - fuel = rand(1600, 2000) + fuel += rand(0, 400) . = ..() /obj/item/flashlight/glowstick/process() @@ -493,18 +496,16 @@ STOP_PROCESSING(SSobj, src) /obj/item/flashlight/glowstick/proc/turn_off() - on = 0 + on = FALSE update_brightness() /obj/item/flashlight/glowstick/attack_self(mob/user) . = ..(user) if(.) return TRUE - if(!fuel) + if(!fuel || on) to_chat(user, span_notice("The glowstick has already been turned on.")) return - if(on) - return if(. == CAN_USE) user.visible_message(span_notice("[user] cracks and shakes \the [name]."), span_notice("You crack and shake \the [src], turning it on!")) diff --git a/code/game/objects/items/devices/vacpack.dm b/code/game/objects/items/devices/vacpack.dm index 96b1f203271..f65e915baac 100644 --- a/code/game/objects/items/devices/vacpack.dm +++ b/code/game/objects/items/devices/vacpack.dm @@ -90,6 +90,10 @@ var/atom/movable/output_atom = output_dest?.resolve() if(!output_atom) return + var/mob/living/attachment_holder //If we have someone holding the vac_attachment, so we don't suck them up by mistake. + if(vac_owner) //If we have a vac owner, treat the vac owner as the user. + attachment_holder = user + user = vac_owner if(istype(output_atom, /obj/item/storage/bag/trash)) if(get_turf(output_atom) != get_turf(user)) vac_power = 0 @@ -141,7 +145,7 @@ I.singularity_pull(target, STAGE_THREE) suckables += I for(var/mob/living/L in oview(pull_range, target)) - if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey) + if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey || L == attachment_holder) continue L.singularity_pull(target, STAGE_THREE) suckables += L @@ -154,7 +158,7 @@ continue suckables += I for(var/mob/living/L in target) - if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey) + if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey || L == attachment_holder) continue if(L.size_multiplier < 0.5 || vac_power >= 6) suckables += L @@ -266,8 +270,14 @@ /obj/item/vac_attachment/proc/prepare_sucking(atom/movable/target, mob/user, turf/target_turf) var/atom/movable/output_atom = output_dest?.resolve() - if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_atom) //Cancel if moved/unpowered/dropped + + if(vac_owner) //Embedded vacs have special handling. + var/turf/item_turf = get_turf(src) + if(vac_power < 2 || !output_atom || (!target.Adjacent(user) && !item_turf.Adjacent(target))) //Swoopie vacs check to see if you're adjacent to the person holding the vac OR the swoopie itself. + return + else if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_atom) //Cancel if moved/unpowered/dropped return + if(!is_allowed_suck(target, user, output_atom)) //cancel if you're not allowed return target.SpinAnimation(5,1) @@ -277,8 +287,14 @@ if(target_turf && target.loc != target_turf) return var/atom/movable/output_atom = output_dest?.resolve() - if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_atom) //Cancel if moved/unpowered/dropped + + if(vac_owner) + var/turf/item_turf = get_turf(src) + if(vac_power < 2 || !output_atom || (!target.Adjacent(user) && !item_turf.Adjacent(target))) //Swoopie vacs check to see if you're adjacent to the person holding the vac OR the swoopie itself. + return + else if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_atom) //Cancel if moved/unpowered/dropped return + if(!is_allowed_suck(target, user, output_atom)) //Does it obey restrictions on what the target could otherwise consume? return if(isitem(target)) diff --git a/code/game/objects/items/leash.dm b/code/game/objects/items/leash.dm index ca765b7f420..5f72e8e869a 100644 --- a/code/game/objects/items/leash.dm +++ b/code/game/objects/items/leash.dm @@ -43,6 +43,9 @@ var/mob/living/carbon/human/leash_master = leash_master_ref?.resolve() if(!leash_pet) return + if(leash_pet.absorbed) //Glrk'd + clear_leash() + return if(!is_wearing_collar(leash_pet)) //The pet has slipped their collar and is not the pet anymore. leash_pet.visible_message( span_warning("[leash_pet] has slipped out of [leash_pet.p_their()] collar!"), @@ -109,6 +112,9 @@ var/mob/living/carbon/human/leash_master = leash_master_ref?.resolve() if(!leash_pet || leash_master) //No pet, no tug. return + if(leash_pet.absorbed) //Glrk'd. + clear_leash() + return //Yank the pet. Yank em in close. apply_tug_mob_to_mob(leash_pet, leash_master, 1) @@ -119,6 +125,9 @@ //Make sure the dom still has a pet if(!leash_master || !leash_pet) return + if(leash_pet.absorbed) + clear_leash() + return addtimer(CALLBACK(src, PROC_REF(after_master_move)), 0.2 SECONDS) /obj/item/leash/proc/after_master_move() @@ -132,7 +141,7 @@ //Knock the pet over if they get further behind. Shouldn't happen too often. sleep(3) //This way running normally won't just yank the pet to the ground. - if(!leash_master || !leash_pet) //Just to stop error messages. Break the loop early if something removed the master + if(!leash_master || !leash_pet || leash_pet.absorbed) //Just to stop error messages. Break the loop early if something removed the master clear_leash() return if(get_dist(leash_pet, leash_master) > 3 && !leash_pet.stunned) @@ -144,7 +153,7 @@ //This code is to check if the pet has gotten too far away, and then break the leash. sleep(3) //Wait to snap the leash - if(!leash_master || !leash_pet) //Just to stop error messages + if(!leash_master || !leash_pet || leash_pet.absorbed) //Just to stop error messages clear_leash() return if(get_dist(leash_pet, leash_master) > 5) @@ -171,7 +180,7 @@ /obj/item/leash/proc/after_pet_move() var/mob/living/carbon/human/leash_pet = leash_pet_ref?.resolve() var/mob/living/carbon/human/leash_master = leash_master_ref?.resolve() - if(!leash_master || !leash_pet) + if(!leash_master || !leash_pet || leash_pet.absorbed) return for(var/i in 3 to get_dist(leash_pet, leash_master)) // Move the pet to a minimum of 2 tiles away from the master, so the pet trails behind them. step_towards(leash_pet, leash_master) @@ -181,7 +190,7 @@ . = ..() var/mob/living/carbon/human/leash_pet = leash_pet_ref?.resolve() var/mob/living/carbon/human/leash_master = leash_master_ref?.resolve() - if(!leash_pet || !leash_master) //There is no pet. Stop this silliness + if(!leash_pet || !leash_master || leash_pet.absorbed) //There is no pet. Stop this silliness clear_leash() return //Dropping procs any time the leash changes slots. So, we will wait a tick and see if the leash was actually dropped @@ -216,6 +225,9 @@ /obj/item/leash/proc/struggle_leash() var/mob/living/carbon/human/leash_pet = leash_pet_ref?.resolve() var/mob/living/carbon/human/leash_master = leash_master_ref?.resolve() + if(leash_pet && leash_pet.absorbed) + clear_leash() + return leash_pet.visible_message(span_danger("\The [leash_pet] is attempting to unhook [leash_pet.p_their()] leash!"), span_danger("You attempt to unhook your leash")) add_attack_logs(leash_master,leash_pet,"Self-unleash (attempt)") diff --git a/code/game/objects/items/weapons/inducer_vr.dm b/code/game/objects/items/weapons/inducer_vr.dm index 3bcfa5c4db7..5f8e772750b 100644 --- a/code/game/objects/items/weapons/inducer_vr.dm +++ b/code/game/objects/items/weapons/inducer_vr.dm @@ -252,6 +252,7 @@ charge = 100 maxcharge = 100 + item_flags = ABSTRACT var/mob/living/carbon/human/hume diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 092a1b37842..ea063490d13 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1,7 +1,7 @@ GLOBAL_VAR_INIT(global_vantag_hud, 0) ADMIN_VERB(drop_everything, R_ADMIN, "Drop Everything", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/dropee in GLOB.mob_list) - var/confirm = tgui_alert(src, "Make [dropee] drop everything?", "Message", list("Yes", "No")) + var/confirm = tgui_alert(user, "Make [dropee] drop everything?", "Message", list("Yes", "No")) if(confirm != "Yes") return diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 3fdf3bc8359..1ba636280ca 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -768,6 +768,8 @@ /obj/item/clothing/shoes/wash() . = ..() + blood_color = null + track_blood = 0 update_icon() /obj/item/clothing/shoes/proc/handle_movement(var/turf/walking, var/running, var/mob/living/carbon/human/pred) diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 40465e126db..8326c2b6be4 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -225,6 +225,8 @@ /obj/item/rig/get_worn_icon_file(var/body_type,var/slot_name,var/default_icon,var/inhands) if(!inhands && (slot_name == slot_back_str || slot_name == slot_belt_str)) + if(body_type == SPECIES_TESHARI || body_type == SPECIES_WEREBEAST) //Until teshari get proper sprites for rigs, they can default to not having the sprite. + return null //All other species are 'humanoid enough' to wear the default rig sprite. if(icon_override) return icon_override else if(mob_icon) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index e6d91ff80e2..ae88763243d 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -86,7 +86,7 @@ // src = THE PERSON BEING ATTACKED // has_hands = Local variable. If the attacker has hands or not. if(I_HELP) - attack_hand_help_intent(H, M, M, has_hands) + attack_hand_help_intent(H, M, has_hands) if(I_GRAB) attack_hand_grab_intent(H, M, has_hands) @@ -115,7 +115,7 @@ return FALSE; //todo: make this whole CPR check into it's own individual proc instead of hogging up attack_hand_help_intent - if((istype(H) && (health < get_crit_point()) || stat == DEAD) && !on_fire) //Only humans can do CPR. + if((istype(H) && (health < get_crit_point()) || stat == DEAD) && !on_fire && H != src) //Only humans can do CPR. if(!H.check_has_mouth()) to_chat(H, span_danger("You don't have a mouth, you cannot perform CPR!")) return FALSE diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index c286436c6eb..cbdfdfa2bae 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -366,6 +366,9 @@ return ..() +/mob/living/silicon/robot/drop_from_inventory(var/obj/item/W, var/atom/target = null) + return FALSE //Dropping things from robots break everything. + // CONTINUE CODING HERE /* /mob/living/silicon/robot/proc/set_module_sprites(var/list/new_sprites) diff --git a/code/modules/mob/living/silicon/robot/robot_simple_items.dm b/code/modules/mob/living/silicon/robot/robot_simple_items.dm index ba749096726..848fa489818 100644 --- a/code/modules/mob/living/silicon/robot/robot_simple_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_simple_items.dm @@ -345,23 +345,26 @@ /obj/item/material/minihoe/cyborg icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_cultivator" + applies_material_colour = FALSE /obj/item/material/knife/machete/hatchet/cyborg icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_hatchet" + applies_material_colour = FALSE /obj/item/analyzer/plant_analyzer/cyborg icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_secateur" - /obj/item/material/knife/cyborg icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_knife" + applies_material_colour = FALSE /obj/item/material/kitchen/rollingpin/cyborg icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_rolling_pin" + applies_material_colour = FALSE /obj/item/robotic_multibelt/syndicate name = "Syndicate Robotic multitool" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/swoopie.dm b/code/modules/mob/living/simple_mob/subtypes/vore/swoopie.dm index 668211205a3..03a8e7e22a4 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/swoopie.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/swoopie.dm @@ -321,7 +321,7 @@ to_chat(usr, "You press a button on \the [src], [ai.swoop_pests ? "" : "de"]activating it's pest seeking routines!") if("Swoop Trash") ai.swoop_trash = !ai.swoop_trash // invert the option - to_chat(usr, "you press a button on \the [src], [ai.swoop_trash ? "" : "de"]activating it's pest seeking routines!") + to_chat(usr, "you press a button on \the [src], [ai.swoop_trash ? "" : "de"]activating it's trash seeking routines!") /mob/living/simple_mob/vore/aggressive/corrupthound/swoopie/Login() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 203d5a682d0..3fafd1ea39a 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -162,7 +162,7 @@ next_move_dir_sub = 0 // I'm not really sure why next_move_dir_sub even exists. return else //We are anything BUT an observer. - if(!my_mob.canmove)//If you want to be very restrictive, add my_mob.restrained() and it'll stop people cuffed/straight jacketed. For now, that's too restrictive for a bugfix PR. + if(!my_mob.canmove || my_mob.paralysis || my_mob.stunned)//If you want to be very restrictive, add my_mob.restrained() and it'll stop people cuffed/straight jacketed. For now, that's too restrictive for a bugfix PR. return else //Proceed like normal. Process_Incorpmove(direct) diff --git a/code/modules/refinery/core/industrial_reagent_waste.dm b/code/modules/refinery/core/industrial_reagent_waste.dm index 042d9bf31a6..df2bed9a250 100644 --- a/code/modules/refinery/core/industrial_reagent_waste.dm +++ b/code/modules/refinery/core/industrial_reagent_waste.dm @@ -16,6 +16,7 @@ // Can't be set on these src.verbs -= /obj/machinery/reagent_refinery/verb/set_APTFT AddElement(/datum/element/climbable) + flags |= NOREACT /obj/machinery/reagent_refinery/waste_processor/process() if(!anchored) diff --git a/code/modules/xenoarcheaology/finds/find_spawning.dm b/code/modules/xenoarcheaology/finds/find_spawning.dm index 6f48554f6d6..12f23707698 100644 --- a/code/modules/xenoarcheaology/finds/find_spawning.dm +++ b/code/modules/xenoarcheaology/finds/find_spawning.dm @@ -1,8 +1,10 @@ /obj/item/archaeological_find name = "object" + desc = "The existence of this object is reality defying and immersion breaking. Looking at it simply makes you unable to comprehend how it even exists. You should follow the command below." icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "ano01" var/find_type = 0 + item_flags = ABSTRACT /// Find spawning debug tool. Can be called on any /mob to spawn it at their location. /mob/proc/artifact_spawn_debug_tool() @@ -84,7 +86,7 @@ additional_desc = "There appear to be [pick("dark","faintly glowing","pungent","bright")] [pick("red","purple","green","blue")] stains inside." if(ARCHAEO_URN) item_type = "urn" - new_item = new /obj/item/reagent_containers/glass/beaker(src.loc) + new_item = new /obj/item/reagent_containers/glass/replenishing(src.loc) new_item.icon = 'icons/obj/xenoarchaeology.dmi' new_item.icon_state = "urn[rand(1,2)]" apply_image_decorations = TRUE @@ -119,6 +121,7 @@ item_type = "[pick("bladed knife","serrated blade","sharp cutting implement")]" var/possible_object_paths = list(/obj/item/material/knife) //As far as I can tell, this is more 'random' than using typesof, as it just picks a random one vs going down the list with a prob (as seen below) possible_object_paths += subtypesof(/obj/item/material/knife) + possible_object_paths -= list(/obj/item/material/knife/cyborg, /obj/item/material/knife/machete/hatchet/cyborg) var/obj/item/material/knife/new_knife = pick(possible_object_paths) new_item = new new_knife(src.loc) additional_desc = "[pick("It doesn't look safe.",\ @@ -192,7 +195,7 @@ item_type = "tool" var/possible_object_paths = list() possible_object_paths += subtypesof(/obj/item/tool) - possible_object_paths -= /obj/item/tool/screwdriver/test_driver + possible_object_paths -= list(/obj/item/tool/screwdriver/test_driver, /obj/item/tool/screwdriver/cyborg, /obj/item/tool/wrench/cyborg, /obj/item/tool/crowbar/cyborg, /obj/item/tool/crowbar/cyborg/jaws, /obj/item/tool/wirecutters/cyborg) var/new_tool = pick(possible_object_paths) new_item = new new_tool(src.loc) new_item.color = rgb(rand(0,255),rand(0,255),rand(0,255)) @@ -450,6 +453,7 @@ var/obj/item/organ/internal/new_organ = pick(possible_object_paths) new_item = new new_organ(src.loc) + additional_desc = "This organ reminds you of a [new_organ.name]" //Code to prevent rejection. new_organ = new_item @@ -582,10 +586,8 @@ apply_image_decorations = TRUE if(prob(25)) apply_material_decorations = FALSE - new_item = new /obj/item/telecube/randomized(src.loc) - secondary_item = new /obj/item/telecube/randomized(src.loc) + new_item = new /obj/item/telecube/mated(src.loc) item_type = new_item.name - secondary_item_type = secondary_item.name if(ARCHAEO_BATTERY) // Battery!