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 @@