diff --git a/code/modules/hydroponics/trays/tray_tools.dm b/code/modules/hydroponics/trays/tray_tools.dm
index 912d06b3d1..3548c390a1 100644
--- a/code/modules/hydroponics/trays/tray_tools.dm
+++ b/code/modules/hydroponics/trays/tray_tools.dm
@@ -169,7 +169,7 @@
switch(grown_seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
- dat += "
It is carniovorous and will eat tray pests for sustenance."
+ dat += "
It is carnivorous and will eat tray pests for sustenance."
if(2)
dat += "
It is carnivorous and poses a significant threat to living things around it."
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 4e9ef55280..5730474ab1 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -35,6 +35,7 @@
var/locked = 0
var/mob/living/carbon/brain/brainmob = null//The current occupant.
+ var/obj/item/organ/brain/brainobj = null //The current brain organ.
var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm.
attackby(var/obj/item/O as obj, var/mob/user as mob)
@@ -60,7 +61,8 @@
living_mob_list += brainmob
user.drop_item()
- qdel(O)
+ brainobj = O
+ brainobj.loc = src
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
@@ -91,7 +93,13 @@
user << "\red You upend the MMI, but the brain is clamped into place."
else
user << "\blue You upend the MMI, spilling the brain onto the floor."
- var/obj/item/organ/brain/brain = new(user.loc)
+ var/obj/item/organ/brain/brain
+ if (brainobj) //Pull brain organ out of MMI.
+ brainobj.loc = user.loc
+ brain = brainobj
+ brainobj = null
+ else //Or make a new one if empty.
+ brain = new(user.loc)
brainmob.container = null//Reset brainmob mmi var.
brainmob.loc = brain//Throw mob into brain.
living_mob_list -= brainmob//Get outta here
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 8fa15f6329..0d0bc2a226 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -52,12 +52,13 @@
/mob/visible_message(var/message, var/self_message, var/blind_message)
for(var/mob/M in viewers(src))
- if(M.see_invisible < invisibility)
- continue // Cannot view the invisible
- var/msg = message
if(self_message && M==src)
- msg = self_message
- M.show_message( msg, 1, blind_message, 2)
+ M.show_message(self_message, 1, blind_message, 2)
+ else if(M.see_invisible < invisibility) // Cannot view the invisible, but you can hear it.
+ if(blind_message)
+ M.show_message(blind_message, 2)
+ else
+ M.show_message(message, 1, blind_message, 2)
// Show a message to all mobs in sight of this atom
// Use for objects performing visible actions
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index 515d5596b6..52ca04e655 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -135,7 +135,7 @@
/obj/item/ammo_magazine/examine(mob/user)
..()
- user << "There [(stored_ammo.len > 1)? "are" : "is"] [stored_ammo.len] round\s left!"
+ user << "There [(stored_ammo.len == 1)? "is" : "are"] [stored_ammo.len] round\s left!"
//magazine icon state caching
/var/global/list/magazine_icondata_keys = list()
diff --git a/code/modules/projectiles/guns/launcher/crossbow.dm b/code/modules/projectiles/guns/launcher/crossbow.dm
index 4736fc0c7b..860776faec 100644
--- a/code/modules/projectiles/guns/launcher/crossbow.dm
+++ b/code/modules/projectiles/guns/launcher/crossbow.dm
@@ -68,14 +68,14 @@
/obj/item/weapon/gun/launcher/crossbow/consume_next_projectile(mob/user=null)
if(tension <= 0)
- user << "\red \The [src] is not drawn back!"
+ user << "\The [src] is not drawn back!"
return null
return bolt
/obj/item/weapon/gun/launcher/crossbow/handle_post_fire(mob/user, atom/target)
bolt = null
- icon_state = "crossbow"
tension = 0
+ update_icon()
..()
/obj/item/weapon/gun/launcher/crossbow/attack_self(mob/living/user as mob)
@@ -89,7 +89,7 @@
else
user.visible_message("[user] relaxes the tension on [src]'s string.","You relax the tension on [src]'s string.")
tension = 0
- icon_state = "crossbow"
+ update_icon()
else
draw(user)
@@ -106,15 +106,19 @@
user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].")
tension = 1
- while(bolt && tension && current_user == user)
+ while(bolt && tension && loc == current_user)
if(!do_after(user, 25)) //crossbow strings don't just magically pull back on their own.
user.visible_message("[usr] stops drawing and relaxes the string of [src].","You stop drawing back and relax the string of [src].")
tension = 0
- icon_state = "crossbow"
+ update_icon()
return
+ //double check that the user hasn't removed the bolt in the meantime
+ if(!(bolt && tension && loc == current_user))
+ return
+
tension++
- icon_state = "crossbow-drawn"
+ update_icon()
if(tension >= max_tension)
tension = max_tension
@@ -132,11 +136,10 @@
/obj/item/weapon/gun/launcher/crossbow/attackby(obj/item/W as obj, mob/user as mob)
if(!bolt)
if (istype(W,/obj/item/weapon/arrow))
- user.drop_item()
+ user.drop_from_inventory(W, src)
bolt = W
- bolt.loc = src
user.visible_message("[user] slides [bolt] into [src].","You slide [bolt] into [src].")
- icon_state = "crossbow-nocked"
+ update_icon()
return
else if(istype(W,/obj/item/stack/rods))
var/obj/item/stack/rods/R = W
@@ -144,7 +147,7 @@
bolt = new /obj/item/weapon/arrow/rod(src)
bolt.fingerprintslast = src.fingerprintslast
bolt.loc = src
- icon_state = "crossbow-nocked"
+ update_icon()
user.visible_message("[user] jams [bolt] into [src].","You jam [bolt] into [src].")
superheat_rod(user)
return
@@ -182,6 +185,14 @@
bolt.icon_state = "metal-rod-superheated"
cell.use(500)
+/obj/item/weapon/gun/launcher/crossbow/update_icon()
+ if(tension > 1)
+ icon_state = "crossbow-drawn"
+ else if(bolt)
+ icon_state = "crossbow-nocked"
+ else
+ icon_state = "crossbow"
+
// Crossbow construction.
/obj/item/weapon/crossbowframe
@@ -209,11 +220,11 @@
if(buildstate == 0)
var/obj/item/stack/rods/R = W
if(R.use(3))
- user << "\blue You assemble a backbone of rods around the wooden stock."
+ user << "You assemble a backbone of rods around the wooden stock."
buildstate++
update_icon()
else
- user << "\blue You need at least three rods to complete this task."
+ user << "You need at least three rods to complete this task."
return
else if(istype(W,/obj/item/weapon/weldingtool))
if(buildstate == 1)
@@ -221,7 +232,7 @@
if(T.remove_fuel(0,user))
if(!src || !T.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "\blue You weld the rods into place."
+ user << "You weld the rods into place."
buildstate++
update_icon()
return
@@ -229,33 +240,33 @@
var/obj/item/stack/cable_coil/C = W
if(buildstate == 2)
if(C.use(5))
- user << "\blue You wire a crude cell mount into the top of the crossbow."
+ user << "You wire a crude cell mount into the top of the crossbow."
buildstate++
update_icon()
else
- user << "\blue You need at least five segments of cable coil to complete this task."
+ user << "You need at least five segments of cable coil to complete this task."
return
else if(buildstate == 4)
if(C.use(5))
- user << "\blue You string a steel cable across the crossbow's lath."
+ user << "You string a steel cable across the crossbow's lath."
buildstate++
update_icon()
else
- user << "\blue You need at least five segments of cable coil to complete this task."
+ user << "You need at least five segments of cable coil to complete this task."
return
else if(istype(W,/obj/item/stack/sheet/mineral/plastic))
if(buildstate == 3)
var/obj/item/stack/sheet/mineral/plastic/P = W
if(P.use(3))
- user << "\blue You assemble and install a heavy plastic lath onto the crossbow."
+ user << "You assemble and install a heavy plastic lath onto the crossbow."
buildstate++
update_icon()
else
- user << "\blue You need at least three plastic sheets to complete this task."
+ user << "You need at least three plastic sheets to complete this task."
return
else if(istype(W,/obj/item/weapon/screwdriver))
if(buildstate == 5)
- user << "\blue You secure the crossbow's various parts."
+ user << "You secure the crossbow's various parts."
new /obj/item/weapon/gun/launcher/crossbow(get_turf(src))
qdel(src)
return
diff --git a/code/modules/projectiles/guns/launcher/pneumatic.dm b/code/modules/projectiles/guns/launcher/pneumatic.dm
index 863d3348e5..d26750a36e 100644
--- a/code/modules/projectiles/guns/launcher/pneumatic.dm
+++ b/code/modules/projectiles/guns/launcher/pneumatic.dm
@@ -14,17 +14,20 @@
var/max_w_class = 3 // Hopper intake size.
var/max_storage_space = 20 // Total internal storage size.
var/obj/item/weapon/tank/tank = null // Tank of gas for use in firing the cannon.
- var/obj/item/weapon/storage/tank_container // Something to hold the tank item so we don't accidentally fire it.
+
+ var/obj/item/weapon/storage/item_storage
var/pressure_setting = 10 // Percentage of the gas in the tank used to fire the projectile.
var/possible_pressure_amounts = list(5,10,20,25,50) // Possible pressure settings.
- var/minimum_tank_pressure = 10 // Minimum pressure to fire the gun.
var/force_divisor = 400 // Force equates to speed. Speed/5 equates to a damage multiplier for whoever you hit.
// For reference, a fully pressurized oxy tank at 50% gas release firing a health
// analyzer with a force_divisor of 10 hit with a damage multiplier of 3000+.
/obj/item/weapon/gun/launcher/pneumatic/New()
..()
- tank_container = new(src)
- tank_container.tag = "gas_tank_holder"
+ item_storage = new(src)
+ item_storage.name = "hopper"
+ item_storage.max_w_class = max_w_class
+ item_storage.max_storage_space = max_storage_space
+ item_storage.use_sound = null
/obj/item/weapon/gun/launcher/pneumatic/verb/set_pressure() //set amount of tank pressure.
set name = "Set Valve Pressure"
@@ -35,69 +38,65 @@
pressure_setting = N
usr << "You dial the pressure valve to [pressure_setting]%."
-/obj/item/weapon/gun/launcher/pneumatic/verb/eject_tank() //Remove the tank.
- set name = "Eject Tank"
- set category = "Object"
- set src in range(0)
-
- if(tank)
- usr << "You twist the valve and pop the tank out of [src]."
- tank.loc = usr.loc
- tank = null
- icon_state = "pneumatic"
- item_state = "pneumatic"
- if (ismob(src.loc))
- var/mob/M = src.loc
- M.update_icons()
- else
- usr << "There's no tank in [src]."
-
-/obj/item/weapon/gun/launcher/pneumatic/attackby(obj/item/W as obj, mob/user as mob)
- if(!tank && istype(W,/obj/item/weapon/tank))
- user.drop_item()
- tank = W
- tank.loc = src.tank_container
- user.visible_message("[user] jams [W] into [src]'s valve and twists it closed.","You jam [W] into [src]'s valve and twist it closed.")
- icon_state = "pneumatic-tank"
- item_state = "pneumatic-tank"
- user.update_icons()
- else if(istype(W) && W.w_class <= max_w_class)
- var/total_stored = 0
- for(var/obj/item/O in src.contents)
- total_stored += O.get_storage_cost()
- if(total_stored + W.get_storage_cost() <= max_storage_space)
- user.remove_from_mob(W)
- W.loc = src
- user << "You shove [W] into the hopper."
- else
- user << "That won't fit into the hopper - it's too full."
+/obj/item/weapon/gun/launcher/pneumatic/proc/eject_tank(mob/user) //Remove the tank.
+ if(!tank)
+ user << "There's no tank in [src]."
return
- else
- user << "That won't fit into the hopper."
-/obj/item/weapon/gun/launcher/pneumatic/attack_self(mob/user as mob)
- if(contents.len > 0)
- var/obj/item/removing = contents[contents.len]
- removing.loc = get_turf(src)
+ user << "You twist the valve and pop the tank out of [src]."
+ user.put_in_hands(tank)
+ tank = null
+ update_icon()
+
+/obj/item/weapon/gun/launcher/pneumatic/proc/unload_hopper(mob/user)
+ if(item_storage.contents.len > 0)
+ var/obj/item/removing = item_storage.contents[item_storage.contents.len]
+ item_storage.remove_from_storage(removing, src.loc)
user.put_in_hands(removing)
user << "You remove [removing] from the hopper."
else
user << "There is nothing to remove in \the [src]."
- return
+
+/obj/item/weapon/gun/launcher/pneumatic/attack_hand(mob/user as mob)
+ if(user.get_inactive_hand() == src)
+ unload_hopper(user)
+ else
+ return ..()
+
+/obj/item/weapon/gun/launcher/pneumatic/attackby(obj/item/W as obj, mob/user as mob)
+ if(!tank && istype(W,/obj/item/weapon/tank))
+ user.drop_from_inventory(W, src)
+ tank = W
+ user.visible_message("[user] jams [W] into [src]'s valve and twists it closed.","You jam [W] into [src]'s valve and twist it closed.")
+ update_icon()
+ else if(istype(W) && item_storage.can_be_inserted(W))
+ item_storage.handle_item_insertion(W)
+
+/obj/item/weapon/gun/launcher/pneumatic/attack_self(mob/user as mob)
+ eject_tank(user)
/obj/item/weapon/gun/launcher/pneumatic/consume_next_projectile(mob/user=null)
- if(!contents.len)
+ if(!item_storage.contents.len)
return null
if (!tank)
user << "There is no gas tank in [src]!"
return null
- var/fire_pressure = (tank.air_contents.return_pressure()/100)*pressure_setting
- if(fire_pressure < minimum_tank_pressure)
+ var/environment_pressure = 10
+ var/turf/T = get_turf(src)
+ if(T)
+ var/datum/gas_mixture/environment = T.return_air()
+ if(environment)
+ environment_pressure = environment.return_pressure()
+
+ fire_pressure = (tank.air_contents.return_pressure() - environment_pressure)*pressure_setting/100
+ if(fire_pressure < 10)
user << "There isn't enough gas in the tank to fire [src]."
return null
- return contents[1]
+ var/obj/item/launched = item_storage.contents[1]
+ item_storage.remove_from_storage(launched, src)
+ return launched
/obj/item/weapon/gun/launcher/pneumatic/examine(mob/user)
if(!..(user, 2))
@@ -119,11 +118,24 @@
if(tank)
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
-
+
var/turf/T = get_turf(src.loc)
if(T) T.assume_air(removed)
..()
+/obj/item/weapon/gun/launcher/pneumatic/update_icon()
+ if(tank)
+ icon_state = "pneumatic-tank"
+ item_state = "pneumatic-tank"
+ else
+ icon_state = "pneumatic"
+ item_state = "pneumatic"
+
+ if (ismob(src.loc))
+ var/mob/M = src.loc
+ M.update_inv_r_hand()
+ M.update_inv_l_hand()
+
//Constructable pneumatic cannon.
/obj/item/weapon/cannonframe
@@ -149,9 +161,9 @@
/obj/item/weapon/cannonframe/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/pipe))
if(buildstate == 0)
- user.drop_item()
+ user.drop_from_inventory(W)
qdel(W)
- user << "\blue You secure the piping inside the frame."
+ user << "You secure the piping inside the frame."
buildstate++
update_icon()
return
@@ -159,17 +171,17 @@
if(buildstate == 2)
var/obj/item/stack/sheet/metal/M = W
if(M.use(5))
- user << "\blue You assemble a chassis around the cannon frame."
+ user << "You assemble a chassis around the cannon frame."
buildstate++
update_icon()
else
- user << "\blue You need at least five metal sheets to complete this task."
+ user << "You need at least five metal sheets to complete this task."
return
else if(istype(W,/obj/item/device/transfer_valve))
if(buildstate == 4)
- user.drop_item()
+ user.drop_from_inventory(W)
qdel(W)
- user << "\blue You install the transfer valve and connect it to the piping."
+ user << "You install the transfer valve and connect it to the piping."
buildstate++
update_icon()
return
@@ -179,7 +191,7 @@
if(T.remove_fuel(0,user))
if(!src || !T.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "\blue You weld the pipe into place."
+ user << "You weld the pipe into place."
buildstate++
update_icon()
if(buildstate == 3)
@@ -187,7 +199,7 @@
if(T.remove_fuel(0,user))
if(!src || !T.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "\blue You weld the metal chassis together."
+ user << "You weld the metal chassis together."
buildstate++
update_icon()
if(buildstate == 5)
@@ -195,7 +207,7 @@
if(T.remove_fuel(0,user))
if(!src || !T.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "\blue You weld the valve into place."
+ user << "You weld the valve into place."
new /obj/item/weapon/gun/launcher/pneumatic(get_turf(src))
qdel(src)
return
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 2bd77f3442..d7c14829d9 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -182,15 +182,15 @@
//admin logs
if(!no_attack_log)
if(istype(firer, /mob))
- target_mob.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [target_mob]/[target_mob.ckey] with a [src.type]"
- firer.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [target_mob]/[target_mob.ckey] with a [src.type]"
- msg_admin_attack("[firer] ([firer.ckey]) shot [target_mob] ([target_mob.ckey]) with a [src] (JMP)") //BS12 EDIT ALG
- else if(firer)
- target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with a [src]"
- msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (JMP)") //BS12 EDIT ALG
+
+ var/attacker_message = "shot with \a [src.type]"
+ var/victim_message = "shot with \a [src.type]"
+ var/admin_message = "shot (\a [src.type])"
+
+ admin_attack_log(firer, target_mob, attacker_message, victim_message, admin_message)
else
- target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with a [src]"
- msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (JMP)") //BS12 EDIT ALG
+ target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]"
+ msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)")
//sometimes bullet_act() will want the projectile to continue flying
if (target_mob.bullet_act(src, def_zone) == -1)
diff --git a/html/changelog.html b/html/changelog.html
index 227e839d13..83d87d57b3 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,16 @@
-->