diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 1aea2fed5c6..451582bcf47 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -488,4 +488,5 @@ var/datum/subsystem/ticker/ticker //map rotate chance defaults to 75% of the length of the round (in minutes) if (!prob((world.time/600)*config.maprotatechancedelta)) return - maprotate() \ No newline at end of file + spawn(-1) //compiling a map can lock up the mc for 30 to 60 seconds if we don't spawn + maprotate() diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index fc8e01984f9..ca28400596e 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -125,6 +125,8 @@ var/mob/living/L = teleatom if(L.buckled) L.buckled.unbuckle_mob() + if(L.buckled_mob) + L.unbuckle_mob(force=1) destarea.Entered(teleatom) diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 9a360ea0bd3..d86dbcaf175 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -34,6 +34,9 @@ target.buckled.unbuckle_mob() if(target.pulledby) target.pulledby.stop_pulling() + target.stop_pulling() + if(target.buckled_mob) + target.unbuckle_mob(force=1) jaunt_disappear(animation, target) target.loc = holder target.notransform=0 //mob is safely inside holder now, no need for protection. diff --git a/code/datums/spells/turf_teleport.dm b/code/datums/spells/turf_teleport.dm index 7f8832ed436..1d2b47f11c0 100644 --- a/code/datums/spells/turf_teleport.dm +++ b/code/datums/spells/turf_teleport.dm @@ -36,5 +36,9 @@ return if(!target.Move(picked)) + if(target.buckled) + target.buckled.unbuckle_mob() + if(target.buckled_mob) + target.unbuckle_mob(force=1) target.loc = picked playsound(get_turf(usr), sound2, 50,1) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index a663a616313..4a677ab1d4b 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -1,6 +1,6 @@ var/list/uplink_items = list() -/proc/get_uplink_items() +/proc/get_uplink_items(var/gamemode_override=null) // If not already initialized.. if(!uplink_items.len) @@ -13,10 +13,6 @@ var/list/uplink_items = list() var/datum/uplink_item/I = new item() if(!I.item) continue - if(I.gamemodes.len && ticker && !(ticker.mode.type in I.gamemodes)) - continue - if(I.excludefrom.len && ticker && (ticker.mode.type in I.excludefrom)) - continue if(I.last) last += I continue @@ -33,7 +29,26 @@ var/list/uplink_items = list() uplink_items[I.category] += I - return uplink_items + //Filtered version + var/list/filtered_uplink_items = list() + + for(var/category in uplink_items) + for(var/datum/uplink_item/I in uplink_items[category]) + if(I.gamemodes.len) + if(!gamemode_override && ticker && !(ticker.mode.type in I.gamemodes)) + continue + if(gamemode_override && !(gamemode_override in I.gamemodes)) + continue + if(I.excludefrom.len) + if(!gamemode_override && ticker && (ticker.mode.type in I.excludefrom)) + continue + if(gamemode_override && (gamemode_override in I.excludefrom)) + continue + if(!filtered_uplink_items[I.category]) + filtered_uplink_items[I.category] = list() + filtered_uplink_items[category] += I + + return filtered_uplink_items // You can change the order of the list by putting datums before/after one another OR // you can use the last variable to make sure it appears last, well have the category appear last. diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a5351a80dc4..da6e6895049 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -104,6 +104,8 @@ throwing = 0 throw_impact(A) . = 1 + if(!A || qdeleted(A)) + return A.Bumped(src) diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index 92fc36842e4..c929eda6b68 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -26,8 +26,9 @@ /obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) var/obj/item/organ/internal/cyberimp/eyes/O = user.getorganslot("eye_ling") - O.Remove(user) - qdel(O) + if(O) + O.Remove(user) + qdel(O) diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm index f39505fa712..9a52ad85388 100644 --- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm +++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm @@ -10,7 +10,7 @@ /obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user) - var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 //phil235 so why is it needd? + var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 if(!istype(H)) // req_human could be done in can_sting stuff. return var/datum/mutation/human/HM = mutations_list[CHAMELEON] diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm index c581d3fb35e..04ccfbf429c 100644 --- a/code/game/gamemodes/changeling/powers/fleshmend.dm +++ b/code/game/gamemodes/changeling/powers/fleshmend.dm @@ -32,9 +32,10 @@ H.remove_all_embedded_objects() for(var/i = 0, i < 10, i++) //The healing itself - doesn't heal toxin damage (that's anatomic panacea) and effectiveness decreases with each use in a short timespan - user.adjustBruteLoss(-10 / recent_uses) - user.adjustOxyLoss(-10 / recent_uses) - user.adjustFireLoss(-10 / recent_uses) + if(user) + user.adjustBruteLoss(-10 / recent_uses) + user.adjustOxyLoss(-10 / recent_uses) + user.adjustFireLoss(-10 / recent_uses) sleep(10) feedback_add_details("changeling_powers","RR") diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 939cce46b06..91dc864f261 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -159,33 +159,7 @@ /datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob) - var/radio_freq = SYND_FREQ - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate/alt(synd_mob) - R.set_frequency(radio_freq) - R.freqlock = 1 - synd_mob.equip_to_slot_or_del(R, slot_ears) - - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(synd_mob), slot_gloves) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) - if(synd_mob.backbag == 1) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) - if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/pistol(synd_mob), slot_belt) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) - - var/obj/item/device/radio/uplink/U = new /obj/item/device/radio/uplink(synd_mob) - U.hidden_uplink.uplink_owner="[synd_mob.key]" - U.hidden_uplink.uses = 20 - synd_mob.equip_to_slot_or_del(U, slot_in_backpack) - - var/obj/item/weapon/implant/weapons_auth/W = new/obj/item/weapon/implant/weapons_auth(synd_mob) - W.implant(synd_mob) - var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob) - E.implant(synd_mob) - synd_mob.faction |= "syndicate" - synd_mob.update_icons() + synd_mob.equipOutfit(/datum/outfit/syndicate) return 1 @@ -313,4 +287,63 @@ var/mob/living/carbon/human/H = synd_mind.current synd_mind.name = H.dna.species.random_name(H.gender,0,lastname) synd_mind.current.real_name = synd_mind.name - return \ No newline at end of file + return + +/datum/outfit/syndicate + name = "Syndicate Operative - Basic" + + uniform = /obj/item/clothing/under/syndicate + shoes = /obj/item/clothing/shoes/combat + gloves = /obj/item/clothing/gloves/combat + back = /obj/item/weapon/storage/backpack + ears = /obj/item/device/radio/headset/syndicate/alt + id = /obj/item/weapon/card/id/syndicate + belt = /obj/item/weapon/gun/projectile/automatic/pistol + backpack_contents = list(/obj/item/weapon/storage/box/engineer=1) + + var/tc = 20 + +/datum/outfit/syndicate/post_equip(mob/living/carbon/human/H) + var/obj/item/device/radio/R = H.ears + R.set_frequency(SYND_FREQ) + R.freqlock = 1 + + var/obj/item/device/radio/uplink/U = new /obj/item/device/radio/uplink(H) + U.hidden_uplink.uplink_owner="[H.key]" + U.hidden_uplink.uses = tc + U.hidden_uplink.mode_override = /datum/game_mode/nuclear //Goodies + H.equip_to_slot_or_del(U, slot_in_backpack) + + var/obj/item/weapon/implant/weapons_auth/W = new/obj/item/weapon/implant/weapons_auth(H) + W.implant(H) + var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(H) + E.implant(H) + H.faction |= "syndicate" + H.update_icons() + +/datum/outfit/syndicate/full + name = "Syndicate Operative - Full Kit" + + glasses = /obj/item/clothing/glasses/night + mask = /obj/item/clothing/mask/gas/syndicate + suit = /obj/item/clothing/suit/space/hardsuit/syndi + l_pocket = /obj/item/weapon/tank/internals/emergency_oxygen/engi + r_pocket = /obj/item/weapon/gun/projectile/automatic/pistol + belt = /obj/item/weapon/storage/belt/military + r_hand = /obj/item/weapon/gun/projectile/automatic/shotgun/bulldog + backpack_contents = list(/obj/item/weapon/storage/box/engineer=1,\ + /obj/item/weapon/tank/jetpack/oxygen/harness=1,\ + /obj/item/weapon/pinpointer/nukeop=1) + + tc = 30 + +/datum/outfit/syndicate/full/post_equip(mob/living/carbon/human/H) + ..() + + + var/obj/item/clothing/suit/space/hardsuit/syndi/suit = H.wear_suit + suit.ToggleHelmet() + var/obj/item/clothing/head/helmet/space/hardsuit/syndi/helmet = H.head + helmet.attack_self(H) + + H.internal = H.l_store \ No newline at end of file diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 47ddaa84213..90eeaf2a609 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -380,6 +380,11 @@ explanation_text = "Destroy the station with a nuclear device." martyr_compatible = 1 +/datum/objective/nuclear/check_completion() + if(ticker && ticker.mode && ticker.mode.station_was_nuked) + return 1 + return 0 + var/global/list/possible_items = list() /datum/objective/steal diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 7472f7c6087..44624e57680 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -39,6 +39,7 @@ "Construction", "T-Comm", "Security", + "Machinery", "Medical", "Misc" ) @@ -373,7 +374,7 @@ if(hack) for(var/datum/design/D in files.possible_designs) - if((D.build_type & 4) && ("hacked" in D.category)) + if((D.build_type & AUTOLATHE) && ("hacked" in D.category)) files.known_designs += D else for(var/datum/design/D in files.known_designs) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 2cba9d67119..c74d6526b09 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -464,7 +464,7 @@ var/global/mulebot_count = 0 load= AM mode = BOT_IDLE -/obj/machinery/bot/mulebot/buckle_mob(mob/living/M) +/obj/machinery/bot/mulebot/buckle_mob(mob/living/M, force = 0) if(M.buckled) return 0 var/turf/T = get_turf(src) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 272e4f1a080..ae739499a1c 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -464,8 +464,7 @@ Auto Patrol: []"}, return build_step++ user << "You complete the Securitron! Beep boop." - var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot - S.loc = get_turf(src) + var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot(get_turf(src)) S.name = created_name qdel(I) qdel(src) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 8ed6035d818..c8e1c81efcb 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -239,35 +239,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ clear_holo(master) return ..() -/* -Holographic project of everything else. -/mob/verb/hologram_test() - set name = "Hologram Debug New" - set category = "CURRENT DEBUG" - - var/obj/effect/overlay/hologram = new(loc)//Spawn a blank effect at the location. - var/icon/flat_icon = icon(getFlatIcon(src,0))//Need to make sure it's a new icon so the old one is not reused. - flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. - flat_icon.ChangeOpacity(0.5)//Make it half transparent. - var/input = input("Select what icon state to use in effect.",,"") - if(input) - var/icon/alpha_mask = new('icons/effects/effects.dmi', "[input]") - flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. - hologram.icon = flat_icon - - world << "Your icon should appear now." - return -*/ - -/* - * Other Stuff: Is this even used? - */ -/obj/machinery/hologram/projector - name = "hologram projector" - desc = "It makes a hologram appear...with magnets or something..." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hologram0" #undef RANGE_BASED #undef AREA_BASED diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index d2116d4d5c2..7c6d2062ff5 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -179,17 +179,19 @@ Class Procs: density = 1 if(!target) for(var/mob/living/carbon/C in loc) - if(C.buckled) + if(C.buckled || C.buckled_mob) continue else target = C - if(target) + if(target && !target.buckled && !target.buckled_mob) if(target.client) target.client.perspective = EYE_PERSPECTIVE target.client.eye = src occupant = target target.loc = src target.stop_pulling() + if(target.pulledby) + target.pulledby.stop_pulling() updateUsrDialog() update_icon() diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 4870fb2d870..827a258508e 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -42,21 +42,12 @@ return if(!istype(target)) return - if(target.buckled) - occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled]!") + if(!patient_insertion_check(target)) return - if(patient) - occupant_message("The sleeper is already occupied!") - return - for(var/mob/living/simple_animal/slime/M in range(1,target)) - if(M.Victim == target) - occupant_message("[target] will not fit into the sleeper because they have a slime latched onto their head!") - return occupant_message("You start putting [target] into [src]...") chassis.visible_message("[chassis] starts putting [target] into \the [src].") if(do_after_cooldown(target)) - if(patient) - occupant_message("The sleeper is already occupied!") + if(!patient_insertion_check(target)) return target.forceMove(src) patient = target @@ -67,6 +58,18 @@ chassis.visible_message("[chassis] loads [target] into [src].") log_message("[target] loaded. Life support functions engaged.") +/obj/item/mecha_parts/mecha_equipment/sleeper/proc/patient_insertion_check(mob/living/carbon/target) + if(target.buckled) + occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled]!") + return + if(target.buckled_mob) + occupant_message("[target] will not fit into the sleeper because [target.buckled_mob] is attached to it!") + return + if(patient) + occupant_message("The sleeper is already occupied!") + return + return 1 + /obj/item/mecha_parts/mecha_equipment/sleeper/proc/go_out() if(!patient) return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 69a0cdfb492..cb2fdf03c96 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -668,10 +668,9 @@ user << "You are currently buckled and cannot move." log_append_to_last("Permission denied.") return - for(var/mob/living/simple_animal/slime/S in range(1,user)) - if(S.Victim == user) - user << "You're too busy getting your life sucked out of you!" - return + if(user.buckled_mob) //mob attached to us + user << "You can't enter the exosuit with [user.buckled_mob] attached to you!" + return visible_message("[user] starts to climb into [src.name].") @@ -681,7 +680,9 @@ else if(occupant) user << "[src.occupant] was faster! Try better next time, loser." else if(user.buckled) - user << "You have been buckled and cannot move." + user << "You can't enter the exosuit while buckled." + else if(user.buckled_mob) + user << "You can't enter the exosuit with [user.buckled_mob] attached to you." else moved_inside(user) else diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index df95b3e5e93..c643bf4a3d6 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -24,14 +24,13 @@ //Cleanup /atom/movable/Destroy() . = ..() - unbuckle_mob() + unbuckle_mob(force=1) //procs that handle the actual buckling and unbuckling -/atom/movable/proc/buckle_mob(mob/living/M) - if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.buckled_mob || (buckle_requires_restraints && !M.restrained()) || M == src) +/atom/movable/proc/buckle_mob(mob/living/M, force = 0) + if((!can_buckle && !force) || !istype(M) || (M.loc != loc) || M.buckled || M.buckled_mob || (buckle_requires_restraints && !M.restrained()) || M == src) return 0 - - if (isslime(M) || isAI(M)) + if(!M.can_buckle() && !force) if(M == usr) M << "You are unable to buckle yourself to the [src]!" else @@ -47,15 +46,15 @@ return 1 -/obj/buckle_mob(mob/living/M) +/obj/buckle_mob(mob/living/M, force = 0) . = ..() if(.) if(burn_state == 1) //Sets the mob on fire if you buckle them to a burning atom/movableect M.adjust_fire_stacks(1) M.IgniteMob() -/atom/movable/proc/unbuckle_mob() - if(buckled_mob && buckled_mob.buckled == src && buckled_mob.can_unbuckle(usr)) +/atom/movable/proc/unbuckle_mob(force=0) + if(buckled_mob && buckled_mob.buckled == src && (buckled_mob.can_unbuckle() || force)) . = buckled_mob buckled_mob.buckled = null buckled_mob.anchored = initial(buckled_mob.anchored) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index b0aa51e115d..66b97a5b5d1 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -188,7 +188,7 @@ if(iscarbon(target)) if(uses) playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) - var/mob/living/carbon/human/C = target + var/mob/living/carbon/C = target user.visible_message("[user] sprays [src] into the face of [target]!") target << "[user] sprays [src] into your face!" if(C.client) @@ -197,9 +197,11 @@ if(C.check_eye_prot() <= 0) // no eye protection? ARGH IT BURNS. C.confused = max(C.confused, 3) C.Weaken(3) - C.lip_style = "spray_face" - C.lip_color = colour - C.update_body() + if(ishuman(C)) + var/mob/living/carbon/human/H = C + H.lip_style = "spray_face" + H.lip_color = colour + H.update_body() uses = max(0,uses-10) ..() diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 29f78da5a5f..273e837e245 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -799,6 +799,9 @@ var/global/list/obj/item/device/pda/PDAs = list() var/datum/signal/signal = src.telecomms_process() + if(!P || qdeleted(P) || !U) //in case the PDA or mob gets destroyed during telecomms_process() + return + var/useTC = 0 if(signal) if(signal.data["done"]) diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index f1cb0adb9db..98bac0bac74 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -168,7 +168,7 @@ var/attachment = "no device" if(attached_device) if(istype(attached_device, /obj/item/device/assembly/signaler)) - attachment = "[attached_device]" + attachment = "[attached_device]" else attachment = attached_device diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index b0cc74e33d2..de4801caf63 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -19,6 +19,8 @@ var/list/world_uplinks = list() var/uplink_owner = null//text-only var/used_TC = 0 + var/mode_override = null + /obj/item/device/uplink/New() ..() world_uplinks+=src @@ -36,7 +38,7 @@ var/list/world_uplinks = list() dat += "Request item:
" dat += "Each item costs a number of tele-crystals as indicated by the number following their name.

" - var/list/buyable_items = get_uplink_items() + var/list/buyable_items = get_uplink_items(mode_override) // Loop through categories var/index = 0 @@ -100,7 +102,7 @@ var/list/world_uplinks = list() var/category = split[1] var/number = text2num(split[2]) - var/list/buyable_items = get_uplink_items() + var/list/buyable_items = get_uplink_items(mode_override) var/list/uplink = buyable_items[category] if(uplink && uplink.len >= number) diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index f60b7d58c09..519acd53d55 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -496,12 +496,12 @@ RCD /obj/item/weapon/rcd/borg/useResource(amount, mob/user) if(!isrobot(user)) return 0 - return user:cell:use(amount * 160) + return user:cell:use(amount * 72) //borgs get 1.3x the use of their RCDs /obj/item/weapon/rcd/borg/checkResource(amount, mob/user) if(!isrobot(user)) return 0 - return user:cell:charge >= (amount * 160) + return user:cell:charge >= (amount * 72) /obj/item/weapon/rcd/borg/New() ..() diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 5b36e5337ae..891ab95aa35 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -73,15 +73,15 @@ return -/obj/machinery/implantchair/attackby(obj/item/weapon/G, mob/user, params) - if(istype(G, /obj/item/weapon/grab)) - if(!ismob(G:affecting)) +/obj/machinery/implantchair/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = W + if(!ismob(G.affecting)) + return + var/mob/M = G.affecting + if(M.buckled_mob) + usr << "[M] will not fit into [src] because they have a slime latched onto their head." return - for(var/mob/living/simple_animal/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - usr << "[G:affecting:name] will not fit into the [src.name] because they have a slime latched onto their head." - return - var/mob/M = G:affecting if(put_mob(M)) qdel(G) src.updateUsrDialog() diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 839ad1b8a48..6eded14811b 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -336,7 +336,8 @@ M.client.screen -= W if(ismob(loc)) - W.dropped(usr) + var/mob/M = loc + W.dropped(M) W.layer = initial(W.layer) W.loc = new_location diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 34b888def5d..361c29ba0cb 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -122,7 +122,7 @@ if(istype(AM, /mob/living)) var/mob/living/L = AM - if(L.buckled || L.mob_size > max_mob_size) //buckled mobs and mobs too big for the container don't get inside closets. + if(L.buckled || L.buckled_mob || L.mob_size > max_mob_size) //buckled mobs, mobs with another mob attached, and mobs too big for the container don't get inside closets. return 0 if(L.mob_size > MOB_SIZE_TINY) //decently sized mobs take more space than objects. var/mobs_stored = 0 @@ -133,6 +133,7 @@ if(L.client) L.client.perspective = EYE_PERSPECTIVE L.client.eye = src + L.stop_pulling() else if(!istype(AM, /obj/item) && !istype(AM, /obj/effect/dummy/chameleon)) return 0 else if(AM.density || AM.anchored) @@ -140,6 +141,8 @@ else if(AM.flags & NODROP) return 0 AM.loc = src + if(AM.pulledby) + AM.pulledby.stop_pulling() return 1 /obj/structure/closet/proc/close() diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index 1f0a3386f4e..4ac722a6719 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -188,9 +188,6 @@ new /obj/item/clothing/shoes/sneakers/black(src) new /obj/item/clothing/shoes/sneakers/black(src) new /obj/item/clothing/shoes/sneakers/black(src) - new /obj/item/clothing/head/hardhat/atmos(src) - new /obj/item/clothing/head/hardhat/atmos(src) - new /obj/item/clothing/head/hardhat/atmos(src) return /obj/structure/closet/wardrobe/engineering_yellow diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index c03090a5119..a37b474470c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -89,4 +89,5 @@ new /obj/item/tapeproj/engineering(src) new /obj/item/weapon/watertank/atmos(src) new /obj/item/clothing/suit/fire/atmos(src) + new /obj/item/clothing/head/hardhat/atmos(src) new /obj/item/clothing/glasses/meson/engine/tray(src) \ No newline at end of file diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index b5a65b25ddf..4f7d765d7c0 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -130,7 +130,7 @@ user << "You [open ? "close":"open"] the [src]" open = !open update_icon() - else if(open) + else if(open && !showpiece) if(user.unEquip(W)) W.loc = src showpiece = W @@ -195,7 +195,7 @@ if(istype(I, /obj/item/weapon/electronics/airlock)) user << "You start installing the electronics into [src]..." playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(user.unEquip(I) && do_after(user, 30, target = src)) + if(user.unEquip(I) && do_after(user, 30, target = src)) I.loc = src electronics = I user << "You install the airlock electronics." diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 78cd7e11221..aa6b7d59ecf 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -252,7 +252,7 @@ ..() update_mob() -/obj/structure/bed/chair/janicart/unbuckle_mob() +/obj/structure/bed/chair/janicart/unbuckle_mob(force = 0) if(buckled_mob) buckled_mob.pixel_x = 0 buckled_mob.pixel_y = 0 diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 027541007f5..d8c04a9bbd6 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -83,7 +83,7 @@ body += "SM - " body += "FLW
" if(antagonist > 0) - body += "Antagonist"; + body += "Antagonist"; body += ""; diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1507cf81ff7..49a46309629 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -276,7 +276,7 @@ message_admins("[key_name_admin(usr)] called the Emergency Shuttle to the station") - href_list["secretsadmin"] = "check_antagonist" + href_list["secrets"] = "check_antagonist" else if(href_list["edit_shuttle_time"]) if(!check_rights(R_SERVER)) return @@ -286,7 +286,7 @@ log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds") minor_announce("The emergency shuttle will reach its destination in [round(SSshuttle.emergency.timeLeft(600))] minutes.") message_admins("[key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds") - href_list["secretsadmin"] = "check_antagonist" + href_list["secrets"] = "check_antagonist" else if(href_list["toggle_continuous"]) if(!check_rights(R_ADMIN)) return @@ -347,7 +347,7 @@ ticker.delay_end = !ticker.delay_end log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - href_list["secretsadmin"] = "check_antagonist" + href_list["secrets"] = "check_antagonist" else if(href_list["end_round"]) if(!check_rights(R_ADMIN)) return @@ -1595,7 +1595,7 @@ src.owner << "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];" src.owner << "Location = [location_description];" src.owner << "[special_role_description]" - src.owner << "(PM) (PP) (VV) (SM) (FLW) (CA)" + src.owner << "(PM) (PP) (VV) (SM) (FLW) (CA)" else if(href_list["addjobslot"]) if(!check_rights(R_ADMIN)) return @@ -1673,7 +1673,7 @@ else if(href_list["BlueSpaceArtillery"]) var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) - M.client.bluespace_artillery(M) + usr.client.bluespace_artillery(M) else if(href_list["CentcommReply"]) var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 6b3040a1677..a1c4cce58f7 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -149,6 +149,10 @@ message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]") /proc/admin_forcemove(mob/mover, atom/newloc) + if(mover.buckled) + mover.buckled.unbuckle_mob() + if(mover.buckled_mob) + mover.unbuckle_mob(force=1) mover.loc = newloc mover.on_forcemove(newloc) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 16d33da43c8..ef82c5ce6be 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -73,7 +73,7 @@ item_color = "atmos" name = "atmospheric technician's firefighting helmet" desc = "A firefighter's helmet, able to keep the user cool in any situation." - flags = STOPSPRESSUREDMAGE + flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 5f6e75ad7d9..99940b9a6ad 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -231,7 +231,9 @@ if(!F) return - var/mob/living/carbon/human/user = usr + var/mob/user = usr + if(user.incapacitated()) + return if(!isturf(user.loc)) user << "You cannot turn the light on while in this [user.loc]!" F.on = !F.on diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 5380c3a54c7..0fe9492913c 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -226,7 +226,6 @@ Contains: item_state = "space" desc = "A lightweight space helmet with the basic ability to protect the wearer from the vacuum of space during emergencies." flash_protect = 0 - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) /obj/item/clothing/head/helmet/space/freedom diff --git a/code/modules/events/operative.dm b/code/modules/events/operative.dm new file mode 100644 index 00000000000..f11961388b7 --- /dev/null +++ b/code/modules/events/operative.dm @@ -0,0 +1,80 @@ +/datum/round_event_control/operative + name = "Lone Operative" + typepath = /datum/round_event/operative + weight = 0 //Admin only + max_occurrences = 1 + +/datum/round_event/operative + var/key_of_operative + +/datum/round_event/operative/proc/get_operative(end_if_fail = 0) + key_of_operative = null + if(!key_of_operative) + var/list/candidates = get_candidates(BE_OPERATIVE) + if(!candidates.len) + if(end_if_fail) + return 0 + return find_operative() + var/client/C = pick(candidates) + key_of_operative = C.key + if(!key_of_operative) + if(end_if_fail) + return 0 + return find_operative() + var/datum/mind/player_mind = new /datum/mind(key_of_operative) + player_mind.active = 1 + var/list/spawn_locs = list() + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name in list("ninjaspawn","carpspawn")) + spawn_locs += L.loc + if(!spawn_locs.len) + return kill() + + var/mob/living/carbon/human/operative = new(pick(spawn_locs)) + var/datum/preferences/A = new + A.copy_to(operative) + operative.dna.update_dna_identity() + + operative.equipOutfit(/datum/outfit/syndicate/full) + + var/datum/mind/Mind = new /datum/mind(key_of_operative) + Mind.assigned_role = "Lone Operative" + Mind.special_role = "Lone Operative" + ticker.mode.traitors |= Mind + Mind.active = 1 + + var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in machines + if(nuke) + var/nuke_code + if(!nuke.r_code || nuke.r_code == "ADMIN") + nuke_code = "[rand(10000, 99999)]" + nuke.r_code = nuke_code + else + nuke_code = nuke.r_code + + Mind.store_memory("Station Self-Destruct Device Code: [nuke_code]", 0, 0) + Mind.current << "The nuclear authorization code is: [nuke_code]" + + var/datum/objective/nuclear/O = new() + O.owner = Mind + Mind.objectives += O + + Mind.transfer_to(operative) + + message_admins("[key_of_operative] has been made into lone operative by an event.") + log_game("[key_of_operative] was spawned as a lone operative by an event.") + return 1 + +/datum/round_event/operative/start() + get_operative() + + +/datum/round_event/operative/proc/find_operative() + message_admins("Attempted to spawn a operative but there was no players available. Will try again momentarily.") + spawn(50) + if(get_operative(1)) + message_admins("Situation has been resolved, [key_of_operative] has been spawned as a operative.") + log_game("[key_of_operative] was spawned as a operative by an event.") + return 0 + message_admins("Unfortunately, no candidates were available for becoming a operative. Shutting down.") + return kill() \ No newline at end of file diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 73c1234680d..8ddc528a2c8 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -477,7 +477,7 @@ if(prob(20)) SV.grow() else //If tile is fully grown - SV.buckle_mob() + SV.entangle_mob() //if(prob(25)) SV.spread() @@ -501,14 +501,14 @@ for(var/datum/spacevine_mutation/SM in mutations) SM.on_grow(src) -/obj/effect/spacevine/buckle_mob() +/obj/effect/spacevine/proc/entangle_mob() if(!buckled_mob && prob(25)) for(var/mob/living/carbon/V in src.loc) for(var/datum/spacevine_mutation/SM in mutations) SM.on_buckle(src, V) if((V.stat != DEAD) && (V.buckled != src)) //not dead or captured V << "The vines [pick("wind", "tangle", "tighten")] around you!" - ..(V) + buckle_mob(V) break //only capture one mob at a time /obj/effect/spacevine/proc/spread() diff --git a/code/modules/lighting/lighting_system.dm b/code/modules/lighting/lighting_system.dm index 9a97bc52b5b..a8fe3cc34d8 100644 --- a/code/modules/lighting/lighting_system.dm +++ b/code/modules/lighting/lighting_system.dm @@ -58,6 +58,8 @@ remove_effect() owner.light = null owner = null + if(changed) + SSlighting.changed_lights -= src return ..() //Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index 286ee10a07d..e7f9fc57901 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/alien/larva/emote(var/act) +/mob/living/carbon/alien/larva/emote(act,m_type=1,message = null) var/param = null if (findtext(act, "-", 1, null)) @@ -7,8 +7,6 @@ act = copytext(act, 1, t1) var/muzzled = is_muzzled() - var/m_type = 1 - var/message switch(act) //Alphabetically sorted please. if ("burp","burps") @@ -26,6 +24,9 @@ if (!src.restrained()) message = "[src] dances around happily." m_type = 1 + if ("deathgasp","deathgasps") + message = "[src] lets out a sickly hiss of air and falls limply to the floor..." + m_type = 2 if ("drool","drools") message = "[src] drools." m_type = 1 @@ -42,6 +43,9 @@ if ("jump","jumps") message = "[src] jumps!" m_type = 1 + if ("me") + ..() + return if ("moan","moans") message = "[src] moans!" m_type = 2 @@ -95,7 +99,7 @@ m_type = 2 if ("help") //"The exception" - src << "Help for larva emotes. You can use these emotes with say \"*emote\":\n\nburp, choke, collapse, dance, drool, gasp, gnarl, hiss, jump, moan, nod, roll, roar, scratch, screech, shake, shiver, sign-#, sulk, sway, tail, twitch, whimper" + src << "Help for larva emotes. You can use these emotes with say \"*emote\":\n\nburp, choke, collapse, dance, deathgasp, drool, gasp, gnarl, hiss, jump, me, moan, nod, roll, roar, scratch, screech, shake, shiver, sign-#, sulk, sway, tail, twitch, whimper" else src << "Unusable emote '[act]'. Say *help for a list." @@ -106,4 +110,4 @@ visible_message(message) else audible_message(message) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index d11d0e389e2..e2f100405f0 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -60,7 +60,7 @@ emp_act return -1 // complete projectile permutation - if(check_shields(P.damage, "the [P.name]", P)) + if(check_shields(P.damage, "the [P.name]", P, 0, P.armour_penetration)) P.on_hit(src, 100, def_zone) return 2 return (..(P , def_zone)) @@ -80,8 +80,9 @@ emp_act //End Here -/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, thrown_proj = 0) +/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, thrown_proj = 0, armour_penetration = 0) var/block_chance = 50 + 30*thrown_proj - round(damage / 3) //thrown things are easier to block + block_chance -= armour_penetration if(AM) if(AM.flags & NOSHIELD) //weapon ignores shields altogether return 0 @@ -295,12 +296,12 @@ emp_act /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]")) + if(check_shields(damage, "the [M.name]", "", "", M.armour_penetration)) return 0 var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone)) var/armor = run_armor_check(affecting, "melee") - apply_damage(damage, M.melee_damage_type, affecting, armor) + apply_damage(damage, M.melee_damage_type, affecting, armor, "", "", M.armour_penetration) updatehealth() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 5968b88647e..ce5bf0c35ab 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -85,12 +85,56 @@ return null +//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() +/mob/living/carbon/human/equip_to_slot(obj/item/I, slot) + if(!..()) //a check failed or the item has already found its slot + return + switch(slot) + if(slot_belt) + belt = I + update_inv_belt() + if(slot_wear_id) + wear_id = I + sec_hud_set_ID() + update_inv_wear_id() + if(slot_ears) + ears = I + update_inv_ears() + if(slot_glasses) + glasses = I + update_inv_glasses() + if(slot_gloves) + gloves = I + update_inv_gloves() + if(slot_shoes) + shoes = I + update_inv_shoes() + if(slot_wear_suit) + wear_suit = I + if(I.flags_inv & HIDEJUMPSUIT) + update_inv_w_uniform() + update_inv_wear_suit() + if(slot_w_uniform) + w_uniform = I + update_suit_sensors() + update_inv_w_uniform() + if(slot_l_store) + l_store = I + update_inv_pockets() + if(slot_r_store) + r_store = I + update_inv_pockets() + if(slot_s_store) + s_store = I + update_inv_s_store() + else + src << "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!" + /mob/living/carbon/human/unEquip(obj/item/I) . = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should. if(!. || !I) return - if(I == wear_suit) if(s_store) unEquip(s_store, 1) //It makes no sense for your suit storage to stay on you if you drop your suit. @@ -125,16 +169,6 @@ else if(I == belt) belt = null update_inv_belt() - else if(I == wear_mask) - wear_mask = null - if(I.flags & BLOCKHAIR) - update_hair() //rebuild hair - if(internal) - if(internals) - internals.icon_state = "internal0" - internal = null - sec_hud_set_ID() - update_inv_wear_mask() else if(I == wear_id) wear_id = null sec_hud_set_ID() @@ -149,95 +183,27 @@ s_store = null update_inv_s_store() -//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() -//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. -/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1) - if(!slot) return - if(!istype(I)) return +/mob/living/carbon/human/wear_mask_update(obj/item/I, unequip = 1) + if(I.flags & BLOCKHAIR) + update_hair() + if(unequip && internal) + if(internals) + internals.icon_state = "internal0" + internal = null + sec_hud_set_ID() + ..() + +/mob/living/carbon/human/head_update(obj/item/I) + if(I.flags & BLOCKHAIR) + update_hair() + if(I.flags_inv & HIDEEYES) + update_inv_glasses() + if(I.flags_inv & HIDEEARS) + update_body() + ..() - if(I == l_hand) - l_hand = null - else if(I == r_hand) - r_hand = null - I.screen_loc = null // will get moved if inventory is visible - I.loc = src - I.equipped(src, slot) - I.layer = 20 - switch(slot) - if(slot_back) - back = I - update_inv_back(redraw_mob) - if(slot_wear_mask) - wear_mask = I - if(wear_mask.flags & BLOCKHAIR) - update_hair(redraw_mob) //rebuild hair - sec_hud_set_ID() - update_inv_wear_mask(redraw_mob) - if(slot_handcuffed) - handcuffed = I - update_inv_handcuffed(redraw_mob) - if(slot_legcuffed) - legcuffed = I - update_inv_legcuffed(redraw_mob) - if(slot_l_hand) - l_hand = I - update_inv_l_hand(redraw_mob) - if(slot_r_hand) - r_hand = I - update_inv_r_hand(redraw_mob) - if(slot_belt) - belt = I - update_inv_belt(redraw_mob) - if(slot_wear_id) - wear_id = I - sec_hud_set_ID() - update_inv_wear_id(redraw_mob) - if(slot_ears) - ears = I - update_inv_ears(redraw_mob) - if(slot_glasses) - glasses = I - update_inv_glasses(redraw_mob) - if(slot_gloves) - gloves = I - update_inv_gloves(redraw_mob) - if(slot_head) - head = I - if(head.flags & BLOCKHAIR) - update_hair(redraw_mob) //rebuild hair - if(head.flags_inv & HIDEEARS) - update_body(redraw_mob) - update_inv_head(redraw_mob) - if(slot_shoes) - shoes = I - update_inv_shoes(redraw_mob) - if(slot_wear_suit) - wear_suit = I - if(I.flags_inv & HIDEJUMPSUIT) - update_inv_w_uniform() - update_inv_wear_suit(redraw_mob) - if(slot_w_uniform) - w_uniform = I - update_suit_sensors() - update_inv_w_uniform(redraw_mob) - if(slot_l_store) - l_store = I - update_inv_pockets(redraw_mob) - if(slot_r_store) - r_store = I - update_inv_pockets(redraw_mob) - if(slot_s_store) - s_store = I - update_inv_s_store(redraw_mob) - if(slot_in_backpack) - if(get_active_hand() == I) - unEquip(I) - I.loc = back - else - src << "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!" - return //Cycles through all clothing slots and tests them for destruction /mob/living/carbon/human/proc/shred_clothing(bomb,shock) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index f9973ea991d..940f0329542 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -308,7 +308,7 @@ 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)) + if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE))) bodyparts_to_add -= "snout" if("frills" in mutant_bodyparts) @@ -998,7 +998,7 @@ // 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)) + if(H.check_shields(I.force, "the [I.name]", I, 0, I.armour_penetration)) return 0 if(I.attack_verb && I.attack_verb.len) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 1b3da71d25d..b2230ae11eb 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -275,19 +275,20 @@ Please contact me on #coderbus IRC. ~Carnie x glasses.screen_loc = ui_glasses //...draw the item in the inventory screen client.screen += glasses //Either way, add the item to the HUD - var/layer2use - if(glasses.alternate_worn_layer) - layer2use = glasses.alternate_worn_layer - if(!layer2use) - layer2use = GLASSES_LAYER + if(!(head && (head.flags_inv & HIDEEYES))) + var/layer2use + if(glasses.alternate_worn_layer) + layer2use = glasses.alternate_worn_layer + if(!layer2use) + layer2use = GLASSES_LAYER - var/image/standing - if(glasses.alternate_worn_icon) - standing = image("icon"=glasses.alternate_worn_icon, "icon_state"="[glasses.icon_state]","layer"=-layer2use) - if(!standing) - standing = image("icon"='icons/mob/eyes.dmi', "icon_state"="[glasses.icon_state]", "layer"=-layer2use) + var/image/standing + if(glasses.alternate_worn_icon) + standing = image("icon"=glasses.alternate_worn_icon, "icon_state"="[glasses.icon_state]","layer"=-layer2use) + if(!standing) + standing = image("icon"='icons/mob/eyes.dmi', "icon_state"="[glasses.icon_state]", "layer"=-layer2use) - overlays_standing[GLASSES_LAYER] = standing + overlays_standing[GLASSES_LAYER] = standing apply_overlay(GLASSES_LAYER) diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 44ba92c73f2..d397a7af712 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -17,24 +17,67 @@ return null -/mob/living/carbon/unEquip(obj/item/I) //THIS PROC DID NOT CALL ..() AND THAT COST ME AN ENTIRE DAY OF DEBUGGING. +//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() +/mob/living/carbon/equip_to_slot(obj/item/I, slot) + if(!slot) + return + if(!istype(I)) + return + + if(I == l_hand) + l_hand = null + else if(I == r_hand) + r_hand = null + + I.screen_loc = null // will get moved if inventory is visible + I.loc = src + I.equipped(src, slot) + I.layer = 20 + + switch(slot) + if(slot_back) + back = I + update_inv_back() + if(slot_wear_mask) + wear_mask = I + wear_mask_update(I, unequip=0) + if(slot_head) + head = I + head_update(I) + if(slot_handcuffed) + handcuffed = I + update_inv_handcuffed() + 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_in_backpack) + if(I == get_active_hand()) + unEquip(I) + I.loc = back + else + return 1 + + +/mob/living/carbon/unEquip(obj/item/I) . = ..() //Sets the default return value to what the parent returns. if(!. || !I) //We don't want to set anything to null if the parent returned 0. return if(I == head) head = null - if(I.flags & BLOCKHAIR) - update_hair() - update_inv_head() + head_update(I) else if(I == back) back = null update_inv_back() else if(I == wear_mask) - if(istype(src, /mob/living/carbon/human)) //If we don't do this hair won't be properly rebuilt. - return wear_mask = null - update_inv_wear_mask() + wear_mask_update(I, unequip=1) else if(I == handcuffed) handcuffed = null if(buckled && buckled.buckle_requires_restraints) @@ -44,3 +87,12 @@ legcuffed = null update_inv_legcuffed() +//handle stuff to update when a mob equips/unequips a mask. +/mob/living/carbon/proc/wear_mask_update(obj/item/I, unequip = 1) + update_inv_wear_mask() + +//handle stuff to update when a mob equips/unequips a headgear. +/mob/living/carbon/proc/head_update(obj/item/I) + if(I.flags_inv & HIDEMASK) + update_inv_wear_mask() + update_inv_head() diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index c0ae3e21920..0d7378a729c 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -29,57 +29,4 @@ return 0 //Unsupported slot -//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() -//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. -/mob/living/carbon/monkey/equip_to_slot(obj/item/I, slot, redraw_mob = 1) - if(!slot) return - if(!istype(I)) return - - if(I == l_hand) - l_hand = null - else if(I == r_hand) - r_hand = null - - switch(slot) - if(slot_back) - back = I - I.equipped(src, slot) - update_inv_back(redraw_mob) - if(slot_wear_mask) - wear_mask = I - I.equipped(src, slot) - update_inv_wear_mask(redraw_mob) - if(slot_head) - head = I - I.equipped(src, slot) - update_inv_head(redraw_mob) - if(slot_handcuffed) - handcuffed = I - update_inv_handcuffed(redraw_mob) - if(slot_legcuffed) - legcuffed = I - I.equipped(src, slot) - update_inv_legcuffed(redraw_mob) - if(slot_l_hand) - l_hand = I - I.equipped(src, slot) - update_inv_l_hand(redraw_mob) - if(slot_r_hand) - r_hand = I - I.equipped(src, slot) - update_inv_r_hand(redraw_mob) - if(slot_in_backpack) - if(I == get_active_hand()) - unEquip(I) - I.loc = back - return - else - usr << "You are trying to equip this item to an unsupported inventory slot. Report this to a coder." - return - - I.loc = src - I.equipped(src, slot) - I.layer = 20 - - diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index b0563bb2d38..7c6c62f0fb0 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -101,24 +101,26 @@ /mob/living/carbon/update_inv_wear_mask() remove_overlay(FACEMASK_LAYER) + if(istype(wear_mask, /obj/item/clothing/mask)) - var/layer2use - if(wear_mask.alternate_worn_layer) - layer2use = wear_mask.alternate_worn_layer - if(!layer2use) - layer2use = FACEMASK_LAYER + if(!(head && (head.flags_inv & HIDEMASK))) + var/layer2use + if(wear_mask.alternate_worn_layer) + layer2use = wear_mask.alternate_worn_layer + if(!layer2use) + layer2use = FACEMASK_LAYER - var/image/standing - if(wear_mask.alternate_worn_icon) - standing = image("icon"=wear_mask.alternate_worn_icon, "icon_state"="[wear_mask.icon_state]", "layer"=-layer2use) - if(!standing) - standing = image("icon"='icons/mob/mask.dmi', "icon_state"="[wear_mask.icon_state]", "layer"=-layer2use) + var/image/standing + if(wear_mask.alternate_worn_icon) + standing = image("icon"=wear_mask.alternate_worn_icon, "icon_state"="[wear_mask.icon_state]", "layer"=-layer2use) + if(!standing) + standing = image("icon"='icons/mob/mask.dmi', "icon_state"="[wear_mask.icon_state]", "layer"=-layer2use) - overlays_standing[FACEMASK_LAYER] = standing + overlays_standing[FACEMASK_LAYER] = standing - if(wear_mask.blood_DNA && (wear_mask.body_parts_covered & HEAD)) - standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood") + if(wear_mask.blood_DNA && (wear_mask.body_parts_covered & HEAD)) + standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood") return wear_mask /mob/living/carbon/update_inv_back() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 77c21506462..4fa4a958c9a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -577,9 +577,6 @@ Sorry Giacom. Please don't be mad :( // It's ugly. But everything related to inventory/storage is. -- c0 s_active.close(src) - for(var/mob/living/simple_animal/slime/M in oview(1,src)) - M.UpdateFeed(src) - /mob/living/proc/makeTrail(turf/T, mob/living/M) if(!has_gravity(M)) return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index a63a44b5a03..41300c018c0 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -199,7 +199,9 @@ M << "You cannot attack people before the game has started." return - if(M.Victim) + if(M.buckled) + if(M == buckled_mob) + M.Feedstop() return // can't attack while eating! if (stat != DEAD) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 627e4fdca89..d62e69f357d 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -840,3 +840,6 @@ var/list/ai_list = list() 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 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index f04ded89b18..9f7c26e5fbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -100,7 +100,7 @@ projectilesound = 'sound/weapons/Gunshot_smg.ogg' projectiletype = /obj/item/projectile/bullet/midbullet2 - weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r + weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r/unrestricted /mob/living/simple_animal/hostile/syndicate/ranged/space icon_state = "syndicaterangedpsace" @@ -140,4 +140,4 @@ ..(gibbed) visible_message("[src] is smashed into pieces!") qdel(src) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/simple_animal/morph/morph.dm b/code/modules/mob/living/simple_animal/morph/morph.dm index d511e5f2004..dd6e4f36fa2 100644 --- a/code/modules/mob/living/simple_animal/morph/morph.dm +++ b/code/modules/mob/living/simple_animal/morph/morph.dm @@ -57,6 +57,8 @@ return 0 if(istype(A,/obj/singularity)) return 0 + if(istype(A,/mob/living/simple_animal/hostile/morph)) + return 0 return 1 /mob/living/simple_animal/hostile/morph/ShiftClickOn(atom/movable/A) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 76d8c13e570..bb93b464481 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -181,7 +181,7 @@ /mob/living/simple_animal/parrot/Topic(href, href_list) //Can the usr physically do this? - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + if(usr.incapacitated() || !usr.Adjacent(loc)) return //Is the usr's mob type able to do this? (lolaliens) @@ -480,7 +480,7 @@ parrot_state = PARROT_SWOOP | PARROT_RETURN return - if(in_range(src, parrot_interest)) + if(Adjacent(parrot_interest)) if(isliving(parrot_interest)) steal_from_mob() @@ -508,7 +508,7 @@ parrot_state = PARROT_WANDER return - if(in_range(src, parrot_perch)) + if(Adjacent(parrot_perch)) src.loc = parrot_perch.loc drop_held_item() parrot_state = PARROT_PERCH @@ -548,7 +548,7 @@ a_intent = "harm" //If the mob is close enough to interact with - if(in_range(src, parrot_interest)) + if(Adjacent(parrot_interest)) //If the mob we've been chasing/attacking dies or falls into crit, check for loot! if(L.stat) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index e61c9b0d78c..3a41421b8da 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -43,6 +43,7 @@ //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly var/melee_damage_lower = 0 var/melee_damage_upper = 0 + var/armour_penetration = 0 //How much armour they ignore, as a flat reduction from the targets armour value var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage. var/list/ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 0, CLONE = 0, STAMINA = 1, OXY = 0) //Set 0 to receive that damage type, 1 to ignore var/attacktext = "attacks" diff --git a/code/modules/mob/living/simple_animal/slime/death.dm b/code/modules/mob/living/simple_animal/slime/death.dm index 81493941d34..549a4e2c728 100644 --- a/code/modules/mob/living/simple_animal/slime/death.dm +++ b/code/modules/mob/living/simple_animal/slime/death.dm @@ -15,6 +15,9 @@ name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])" return + if(buckled) + Feedstop(silent=1) //releases ourselves from the mob we fed on. + stat = DEAD overlays.len = 0 diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index c0756da1c8b..f65100a6d64 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -14,6 +14,8 @@ if (notransform) return if(..()) + if(buckled) + handle_feeding() handle_nutrition() handle_targets() if (!ckey) @@ -32,8 +34,8 @@ AIproc = 1 - while(AIproc && stat != DEAD && (attacked || hungry || rabid || Victim)) - if(Victim) // can't eat AND have this little process at the same time + while(AIproc && stat != DEAD && (attacked || hungry || rabid || buckled)) + if(buckled) // can't eat AND have this little process at the same time break if(!Target || client) @@ -45,11 +47,10 @@ break if(Target) - for(var/mob/living/simple_animal/slime/M in view(1,Target)) - if(M.Victim == Target) - Target = null - AIproc = 0 - break + if(isslime(Target.buckled_mob)) + Target = null + AIproc = 0 + break if(!AIproc) break @@ -148,11 +149,65 @@ return temp_change /mob/living/simple_animal/slime/handle_regular_status_updates() - if(..()) if(prob(30)) adjustBruteLoss(-1) +/mob/living/simple_animal/slime/proc/handle_feeding() + if(!ismob(buckled)) + return + var/mob/M = buckled + + if(M.stat == DEAD) // our victim died + if(!client) + if(!rabid && !attacked) + if(M.LAssailant && M.LAssailant != M) + if(prob(50)) + if(!(M.LAssailant in Friends)) + Friends[M.LAssailant] = 1 + else + ++Friends[M.LAssailant] + else + src << "This subject does not have a strong enough life energy anymore..." + + if(M.client && ishuman(M)) + if(prob(85)) + rabid = 1 //we go rabid after finishing to feed on a human with a client. + + Feedstop() + return + + if(iscarbon(M)) + var/mob/living/carbon/C = M + C.adjustCloneLoss(rand(2,4)) + C.adjustToxLoss(rand(1,2)) + + if(prob(10) && C.client) + C << "[pick("You can feel your body becoming weak!", \ + "You feel like you're about to die!", \ + "You feel every part of your body screaming in agony!", \ + "A low, rolling pain passes through your body!", \ + "Your body feels as if it's falling apart!", \ + "You feel extremely weak!", \ + "A sharp, deep pain bathes every inch of your body!")]" + + else if(isanimal(M)) + var/mob/living/simple_animal/SA = M + SA.adjustBruteLoss(is_adult ? rand(4, 7) : rand(3, 4)) + + else + src << "[pick("This subject is incompatible", \ + "This subject does not have a life energy", "This subject is empty", \ + "I am not satisified", "I can not feed from this subject", \ + "I do not feel nourished", "This subject is not food")]!" + Feedstop() + return + + add_nutrition(rand(7,15)) + + //Heal yourself. + adjustBruteLoss(-3) + /mob/living/simple_animal/slime/proc/handle_nutrition() if(docile) //God as my witness, I will never go hungry again @@ -171,27 +226,29 @@ nutrition -= 20 amount_grown++ - if(amount_grown >= 10 && !Victim && !Target && !ckey) + if(amount_grown >= 10 && !buckled && !Target && !ckey) if(is_adult) Reproduce() else Evolve() -/mob/living/simple_animal/slime/proc/add_nutrition(nutrition_to_add = 0, lastnut = 0) +/mob/living/simple_animal/slime/proc/add_nutrition(nutrition_to_add = 0) nutrition = min((nutrition + nutrition_to_add), get_max_nutrition()) - if(nutrition >= (lastnut + 50)) - if(prob(80)) - lastnut = nutrition - powerlevel++ - if(powerlevel > 10) - powerlevel = 10 - adjustBruteLoss(-10) + if(nutrition >= get_grow_nutrition()) + if(powerlevel<10) + if(prob(30-powerlevel*2)) + powerlevel++ + else if(nutrition >= get_hunger_nutrition() + 100) //can't get power levels unless you're a bit above hunger level. + if(powerlevel<5) + if(prob(25-powerlevel*5)) + powerlevel++ + /mob/living/simple_animal/slime/proc/handle_targets() if(Tempstun) - if(!Victim) // not while they're eating! + if(!buckled) // not while they're eating! canmove = 0 else canmove = 1 @@ -212,7 +269,7 @@ if(!client) if(!canmove) return - if(Victim) return // if it's eating someone already, continue eating! + if(buckled) return // if it's eating someone already, continue eating! if(Target) --target_patience @@ -254,13 +311,8 @@ if(src.type in H.dna.species.ignored_by) continue - if(!L.canmove) // Only one slime can latch on at a time. - var/notarget = 0 - for(var/mob/living/simple_animal/slime/M in view(1,L)) - if(M.Victim == L) - notarget = 1 - if(notarget) - continue + if(isslime(L.buckled_mob)) // Only one slime can latch on at a time. + continue targets += L // Possible target found! @@ -361,9 +413,9 @@ else // Not friendly enough to_say = pick("No...", "I won't follow...") else if (findtext(phrase, "stop")) - if (Victim) // We are asked to stop feeding + if (buckled) // We are asked to stop feeding if (Friends[who] > 4) - Victim = null + Feedstop() Target = null if (Friends[who] < 7) --Friends[who] @@ -457,7 +509,7 @@ if (bodytemperature < T0C - 50) phrases += "..." phrases += "C... c..." - if (Victim) + if (buckled) phrases += "Nom..." phrases += "Tasty..." if (powerlevel > 3) phrases += "Bzzz..." diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index d41d71cbbea..cd900cf3776 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -20,129 +20,44 @@ if(!Adjacent(M)) return 0 - if(Victim) + if(buckled) Feedstop() return 0 if(isslime(M)) - src << "I can't latch onto another slime..." + src << "I can't latch onto another slime..." return 0 if(docile) - src << "I'm not hungry anymore..." + src << "I'm not hungry anymore..." return 0 if(stat) - src << "I must be conscious to do this..." + src << "I must be conscious to do this..." return 0 if(M.stat == DEAD) - src << "This subject does not have a strong enough life energy..." + src << "This subject does not have a strong enough life energy..." return 0 - for(var/mob/living/simple_animal/slime/met in view()) - if(met.Victim == M && met != src) - src << "The [met.name] is already feeding on this subject..." - return 0 + if(isslime(M.buckled_mob)) + src << "Another slime is already feeding on this subject..." + return 0 return 1 /mob/living/simple_animal/slime/proc/Feedon(mob/living/M) + if(M.buckle_mob(src, force=1)) + M.visible_message("The [name] has latched onto [M]!", \ + "The [name] has latched onto [M]!") + else + src << "I have failed to latch onto the subject" - src << "I have latched onto the subject and begun feeding..." - M << "The [name] has latched onto [M.name]!" - - Victim = M - src.loc = M.loc - canmove = 0 - anchored = 1 - var/lastnut = nutrition - var/fed_succesfully = 0 - - while(Victim && Victim == M && Victim.stat != DEAD && stat != DEAD) - canmove = 0 - - if(Adjacent(Victim)) - loc = M.loc - - if(iscarbon(Victim)) - Victim.adjustCloneLoss(rand(5,6)) - Victim.adjustToxLoss(rand(1,2)) - if(Victim.health <= 0) - Victim.adjustToxLoss(rand(2,4)) - - if(prob(15) && Victim.client) - Victim << "[pick("You can feel your body becoming weak!", \ - "You feel like you're about to die!", \ - "You feel every part of your body screaming in agony!", \ - "A low, rolling pain passes through your body!", \ - "Your body feels as if it's falling apart!", \ - "You feel extremely weak!", \ - "A sharp, deep pain bathes every inch of your body!")]" - - fed_succesfully = 1 - - else if(isanimal(Victim)) //we already know it's a simple_animal from above - Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12)) - fed_succesfully = 1 - - else - src << "[pick("This subject is incompatible", \ - "This subject does not have a life energy", "This subject is empty", \ - "I am not satisified", "I can not feed from this subject", \ - "I do not feel nourished", "This subject is not food")]!" - - if(fed_succesfully) - add_nutrition(rand(15,30), lastnut) - - //Heal yourself. - adjustBruteLoss(-10) - - updatehealth() - if(Victim) - Victim.updatehealth() - - sleep(rand(15,45)) - - else - break - - canmove = 1 - anchored = 0 - - - if(M && M.stat == DEAD) - if(!client) - if(Victim && !rabid && !attacked) - if(Victim.LAssailant && Victim.LAssailant != Victim) - if(prob(50)) - if(!(Victim.LAssailant in Friends)) - Friends[Victim.LAssailant] = 1 - else - ++Friends[Victim.LAssailant] - - if(M.client && ishuman(M)) - if(prob(85)) - rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU - - if(client) - src << "This subject does not have a strong enough life energy anymore..." - - else if(client) - src << "I have stopped feeding..." - - Victim = null - -/mob/living/simple_animal/slime/proc/Feedstop() - if(Victim) - if(Victim.client) - Victim << "[src] has let go of your head!" - Victim = null - -/mob/living/simple_animal/slime/proc/UpdateFeed(mob/M) - if(Victim) - if(Victim == M) - loc = M.loc // simple "attach to head" effect! - +/mob/living/simple_animal/slime/proc/Feedstop(silent=0) + if(buckled) + if(!silent) + visible_message("[src] has let go of [buckled]!", \ + "I stopped feeding.") + buckled.unbuckle_mob(force=1) /mob/living/simple_animal/slime/verb/Evolve() set category = "Slime" diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 045b5c31410..cadcdb2db31 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -48,7 +48,6 @@ var/number = 0 // Used to understand when someone is talking to it - var/mob/living/Victim = null // the person the slime is currently feeding on var/mob/living/Target = null // AI variable - tells the slime to hunt this down var/mob/living/Leader = null // AI variable - tells the slime to follow this person @@ -178,7 +177,7 @@ ..() /mob/living/simple_animal/slime/MouseDrop(atom/movable/A as mob|obj) - if(isliving(A) && A != src) + if(isliving(A) && A != src && usr == src) var/mob/living/Food = A if(CanFeedon(Food)) Feedon(Food) @@ -197,8 +196,8 @@ if(..()) //successful slime attack if(M == src) return - if(Victim) - Victim = null + if(buckled) + Feedstop(silent=1) visible_message("[M] pulls [src] off!") return attacked += 5 @@ -229,8 +228,8 @@ /mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M) - if(Victim) - if(Victim == M) + if(buckled) + if(buckled == M) if(prob(60)) visible_message("[M] attempts to wrestle \the [name] off!") playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) @@ -244,11 +243,11 @@ else M.do_attack_animation(src) if(prob(30)) - visible_message("[M] attempts to wrestle \the [name] off of [Victim]!") + visible_message("[M] attempts to wrestle \the [name] off of [buckled]!") playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) else - visible_message("[M] manages to wrestle \the [name] off of [Victim]!") + visible_message("[M] manages to wrestle \the [name] off of [buckled]!") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) discipline_slime(M) @@ -357,10 +356,10 @@ if(Discipline == 1) attacked = 0 - if(Victim || Target) - Victim = null + if(Target) Target = null - anchored = 0 + if(buckled) + Feedstop(silent=1) //we unbuckle the slime from the mob it latched onto. spawn(0) SStun = 1 @@ -378,3 +377,13 @@ /mob/living/simple_animal/slime/pet docile = 1 + +/mob/living/simple_animal/slime/can_unbuckle() + return 0 + +/mob/living/simple_animal/slime/can_buckle() + return 0 + +/mob/living/simple_animal/slime/get_mob_buckling_height(mob/seat) + if(..()) + return 3 \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 4adc20626e2..ca0948b56c5 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -981,7 +981,7 @@ var/list/slot_equipment_priority = list( \ dir = angle2dir(rotation+dir2angle(dir)) //You can buckle on mobs if you're next to them since most are dense -/mob/buckle_mob(mob/living/M) +/mob/buckle_mob(mob/living/M, force = 0) if(M.buckled) return 0 var/turf/T = get_turf(src) @@ -997,12 +997,26 @@ var/list/slot_equipment_priority = list( \ //Default buckling shift visual for mobs /mob/post_buckle_mob(mob/living/M) if(M == buckled_mob) //post buckling - M.pixel_y = initial(M.pixel_y) + 9 + var/height = M.get_mob_buckling_height(src) + M.pixel_y = initial(M.pixel_y) + height if(M.layer < layer) M.layer = layer + 0.1 else //post unbuckling M.layer = initial(M.layer) M.pixel_y = initial(M.pixel_y) -/mob/proc/can_unbuckle(mob/user) +//returns the height in pixel the mob should have when buckled to another mob. +/mob/proc/get_mob_buckling_height(mob/seat) + if(isliving(seat)) + var/mob/living/L = seat + if(L.mob_size <= MOB_SIZE_SMALL) //being on top of a small mob doesn't put you very high. + return 0 + return 9 + +//can the mob be buckled to something by default? +/mob/proc/can_buckle() + return 1 + +//can the mob be unbuckled from something by default? +/mob/proc/can_unbuckle() return 1 \ No newline at end of file diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index f991cfc8478..a5d25a81c71 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -25,7 +25,7 @@ /obj/singularity/narsie/large/New() ..() world << "NAR-SIE HAS RISEN" - world << 'sound/effects/narsie.ogg' + world << pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg') var/area/A = get_area(src) if(A) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 2c4d8e15eda..423f7523d67 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -203,6 +203,8 @@ if(burst_size > 1) for(var/i = 1 to burst_size) + if(!user) + break if(!issilicon(user)) if( i>1 && !(src in get_both_hands(user))) //for burst firing break @@ -240,10 +242,11 @@ spawn(fire_delay) semicd = 0 - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() + if(user) + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() feedback_add_details("gun_fired","[src.type]") /obj/item/weapon/gun/attack(mob/M as mob, mob/user) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index dd63e9c86d9..4d68d5f00d7 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -16,7 +16,7 @@ set name = "Set transfer amount" set category = "Object" set src in range(0) - if(usr.stat || !usr.canmove || usr.restrained()) + if(usr.incapacitated()) return var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts if (N) diff --git a/code/modules/recycling/disposal-unit.dm b/code/modules/recycling/disposal-unit.dm index b76334d1680..cfcde5ffc32 100644 --- a/code/modules/recycling/disposal-unit.dm +++ b/code/modules/recycling/disposal-unit.dm @@ -106,7 +106,7 @@ /obj/machinery/disposal/proc/stuff_mob_in(mob/living/target, mob/living/user) if(!iscarbon(user) && !user.ventcrawler) //only carbon and ventcrawlers can climb into disposal by themselves. return - if(target.buckled) + if(target.buckled || target.buckled_mob) return if(target.mob_size > MOB_SIZE_HUMAN) user << "[target] doesn't fit inside [src]!" diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm index a7df6bb115f..0719aafb9e8 100644 --- a/code/modules/research/designs/power_designs.dm +++ b/code/modules/research/designs/power_designs.dm @@ -11,7 +11,7 @@ materials = list(MAT_METAL = 700, MAT_GLASS = 50) construction_time=100 build_path = /obj/item/weapon/stock_parts/cell - category = list("Misc","Power Designs") + category = list("Misc","Power Designs","Machinery","initial") /datum/design/high_cell name = "High-Capacity Power Cell" diff --git a/code/modules/research/designs/stock_parts_designs.dm b/code/modules/research/designs/stock_parts_designs.dm index e9d2511b8bb..3f10842e91f 100644 --- a/code/modules/research/designs/stock_parts_designs.dm +++ b/code/modules/research/designs/stock_parts_designs.dm @@ -32,7 +32,7 @@ build_type = PROTOLATHE | AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) build_path = /obj/item/weapon/stock_parts/capacitor - category = list("Stock Parts") + category = list("Stock Parts","Machinery","initial") /datum/design/adv_capacitor name = "Advanced Capacitor" @@ -75,7 +75,7 @@ build_type = PROTOLATHE | AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/scanning_module - category = list("Stock Parts") + category = list("Stock Parts","Machinery","initial") /datum/design/adv_scanning name = "Advanced Scanning Module" @@ -118,7 +118,7 @@ build_type = PROTOLATHE | AUTOLATHE materials = list(MAT_METAL = 30) build_path = /obj/item/weapon/stock_parts/manipulator - category = list("Stock Parts") + category = list("Stock Parts","Machinery","initial") /datum/design/nano_mani name = "Nano Manipulator" @@ -161,7 +161,7 @@ build_type = PROTOLATHE | AUTOLATHE materials = list(MAT_METAL = 10, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/micro_laser - category = list("Stock Parts") + category = list("Stock Parts","Machinery","initial") /datum/design/high_micro_laser name = "High-Power Micro-Laser" @@ -203,7 +203,7 @@ build_type = PROTOLATHE | AUTOLATHE materials = list(MAT_METAL = 80) build_path = /obj/item/weapon/stock_parts/matter_bin - category = list("Stock Parts") + category = list("Stock Parts","Machinery","initial") /datum/design/adv_matter_bin name = "Advanced Matter Bin" @@ -306,4 +306,4 @@ build_type = PROTOLATHE materials = list(MAT_GLASS = 100, MAT_SILVER = 10, MAT_URANIUM = 15) build_path = /obj/item/weapon/stock_parts/subspace/transmitter - category = list("Stock Parts") \ No newline at end of file + category = list("Stock Parts") diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 6cf59f10915..366876ec57c 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -457,27 +457,23 @@ visible_message("[src]'s crusher goes way too many levels too high, crushing right through space-time!") playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 1, -3) investigate_log("Experimentor has triggered the 'throw things' reaction.", "experimentor") - var/list/throwAt = list() - for(var/i in oview(7,src)) - if(istype(i,/obj/item) || istype(i,/mob/living)) - throwAt.Add(i) - var/counter - for(counter = 1, counter < throwAt.len, ++counter) - var/cast = throwAt[counter] - cast:throw_at(src,10,1) + spawn(0) + for(var/atom/movable/AM in oview(7,src)) + if(!AM.anchored) + AM.throw_at(src,10,1) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src]'s crusher goes one level too high, crushing right into space-time!") playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 1, -3) investigate_log("Experimentor has triggered the 'minor throw things' reaction.", "experimentor") - var/list/oViewStuff = oview(7,src) var/list/throwAt = list() - for(var/i in oViewStuff) - if(istype(i,/obj/item) || istype(i,/mob/living)) - throwAt.Add(i) - var/counter - for(counter = 1, counter < throwAt.len, ++counter) - var/cast = throwAt[counter] - cast:throw_at(pick(throwAt),10,1) + for(var/atom/movable/AM in oview(7,src)) + if(!AM.anchored) + throwAt.Add(AM) + spawn(0) + for(var/counter = 1, counter < throwAt.len, ++counter) + var/atom/movable/cast = throwAt[counter] + cast.throw_at(pick(throwAt),10,1) ejectItem(TRUE) //////////////////////////////////////////////////////////////////////////////////////////////// if(exp == FAIL) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 63c047a4a09..84cfae486a5 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -608,7 +608,7 @@ return cooldown = 1 usr << "Your request has been recieved by Centcom." - admins << "FERRY: [key_name_admin(usr)] (?) (FLW) (Move Ferry) is requesting to move the transport ferry to Centcom." + admins << "FERRY: [key_name_admin(usr)] (?) (FLW) (Move Ferry) is requesting to move the transport ferry to Centcom." spawn(600) //One minute cooldown cooldown = 0 diff --git a/html/changelog.html b/html/changelog.html index 32a059e7ef9..8c0e1cc1025 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -62,6 +62,8 @@
  • Add airlock electronics to open it with id later, otherwise you'll have to use crowbar
  • Broken display cases can be fixed with glass sheets or removed using crowbar
  • Added start_showpiece_type variable for mappers to create custom displays
  • +
  • Syndicate Lone Operatives spotted near the nanotrasen stations! Keep the disk safe!
  • +
  • Admin spawned nuclear operatives will now have access to nukeop equipment
  • Gun Hog updated: