Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n"
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
dat += "Gender identity: [active2.fields["id_gender"]] "
diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm
index e8fe96ae6c8..3d0235fab95 100644
--- a/code/game/machinery/computer/prisoner.dm
+++ b/code/game/machinery/computer/prisoner.dm
@@ -2,7 +2,6 @@
/obj/machinery/computer/prisoner
name = "prisoner management console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "security_key"
icon_screen = "explosive"
light_color = "#a91515"
diff --git a/code/game/machinery/computer/prisonshuttle.dm b/code/game/machinery/computer/prisonshuttle.dm
index 1c54fb0f4ce..8c435f58459 100644
--- a/code/game/machinery/computer/prisonshuttle.dm
+++ b/code/game/machinery/computer/prisonshuttle.dm
@@ -12,7 +12,6 @@ var/prison_shuttle_timeleft = 0
/obj/machinery/computer/prison_shuttle
name = "prison shuttle control console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "security_key"
icon_screen = "syndishuttle"
light_color = "#00ffff"
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index ca56ce168df..4d29a56b89a 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -1,7 +1,6 @@
/obj/machinery/computer/robotics
name = "robotics control console"
desc = "Used to remotely lockdown or detonate linked cyborgs."
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "tech_key"
icon_screen = "robot"
light_color = "#a97faa"
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 54c94d86848..465884b2caa 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -127,6 +127,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
@@ -612,5 +613,4 @@ What a mess.*/
..(severity)
/obj/machinery/computer/secure_data/detective_computer
- icon = 'icons/obj/computer.dmi'
icon_state = "messyfiles"
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 1a67778fdf6..bd9c66dbaed 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -93,6 +93,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm
index cb0f8a5552a..0a337f4df8f 100644
--- a/code/game/machinery/computer/specops_shuttle.dm
+++ b/code/game/machinery/computer/specops_shuttle.dm
@@ -13,7 +13,6 @@ var/specops_shuttle_timeleft = 0
/obj/machinery/computer/specops_shuttle
name = "special operations shuttle control console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "security_key"
icon_screen = "syndishuttle"
light_color = "#00ffff"
diff --git a/code/game/machinery/computer/supply.dm b/code/game/machinery/computer/supply.dm
index d390a7f1633..4bcc43bbecf 100644
--- a/code/game/machinery/computer/supply.dm
+++ b/code/game/machinery/computer/supply.dm
@@ -1,6 +1,5 @@
/obj/machinery/computer/supplycomp
name = "supply control console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "tech_key"
icon_screen = "supply"
light_color = "#b88b2e"
@@ -13,7 +12,6 @@
/obj/machinery/computer/ordercomp
name = "supply ordering console"
- icon = 'icons/obj/computer.dmi'
icon_screen = "request"
circuit = /obj/item/weapon/circuitboard/ordercomp
var/temp = null
diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm
index d36f03b5252..ba7193b69bb 100644
--- a/code/game/machinery/computer/syndicate_specops_shuttle.dm
+++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm
@@ -12,7 +12,6 @@ var/syndicate_elite_shuttle_timeleft = 0
/obj/machinery/computer/syndicate_elite_shuttle
name = "elite syndicate squad shuttle control console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "syndie_key"
icon_screen = "syndishuttle"
light_color = "#00ffff"
diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm
index 57a662db46f..bb4228397dd 100644
--- a/code/game/machinery/computer3/computers/medical.dm
+++ b/code/game/machinery/computer3/computers/medical.dm
@@ -95,6 +95,7 @@
dat += "Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Fingerprint: [active1.fields["fingerprint"]] \n \
diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm
index a314bed2736..6b77a274bf5 100644
--- a/code/game/machinery/computer3/computers/security.dm
+++ b/code/game/machinery/computer3/computers/security.dm
@@ -134,6 +134,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index d1ab11e7067..5d0f707ae88 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -96,7 +96,7 @@
occupantData["name"] = occupant.name
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
- occupantData["maxHealth"] = occupant.maxHealth
+ occupantData["maxHealth"] = occupant.getMaxHealth()
occupantData["minHealth"] = config.health_threshold_dead
occupantData["bruteLoss"] = occupant.getBruteLoss()
occupantData["oxyLoss"] = occupant.getOxyLoss()
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 6441a5e72ae..672a6a425b7 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -534,7 +534,7 @@
time_entered = world.time
if(ishuman(M) && applies_stasis)
var/mob/living/carbon/human/H = M
- H.in_stasis = 1
+ H.Stasis(1000)
// Book keeping!
var/turf/location = get_turf(src)
@@ -602,7 +602,7 @@
set_occupant(usr)
if(ishuman(usr) && applies_stasis)
var/mob/living/carbon/human/H = occupant
- H.in_stasis = 1
+ H.Stasis(1000)
icon_state = occupied_icon_state
@@ -638,7 +638,7 @@
occupant.forceMove(get_turf(src))
if(ishuman(occupant) && applies_stasis)
var/mob/living/carbon/human/H = occupant
- H.in_stasis = 0
+ H.Stasis(0)
set_occupant(null)
icon_state = base_icon_state
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 6aeecfc8e5d..e78cba35688 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -777,7 +777,7 @@ About the new airlock wires panel:
src.welded = 1
else
src.welded = null
- playsound(src, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src, 'sound/items/Welder.ogg', 75, 1)
src.update_icon()
return
else
@@ -802,7 +802,7 @@ About the new airlock wires panel:
cable.plugin(src, user)
else if(!repairing && istype(C, /obj/item/weapon/crowbar))
if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) )
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 75, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.")
if(do_after(user,40))
to_chat(user,"You removed the airlock electronics!")
@@ -895,9 +895,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
- playsound(src.loc, open_sound_powered, 100, 1)
+ playsound(src.loc, open_sound_powered, 75, 1)
else
- playsound(src.loc, open_sound_unpowered, 100, 1)
+ playsound(src.loc, open_sound_unpowered, 75, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -992,9 +992,9 @@ About the new airlock wires panel:
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0
if(arePowerSystemsOn())
- playsound(src.loc, open_sound_powered, 100, 1)
+ playsound(src.loc, open_sound_powered, 75, 1)
else
- playsound(src.loc, open_sound_unpowered, 100, 1)
+ playsound(src.loc, open_sound_unpowered, 75, 1)
for(var/turf/turf in locs)
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis)
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 209e3bb228f..3d899377cca 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -12,6 +12,7 @@
desc = "That looks like it doesn't open easily."
icon = 'icons/obj/doors/rapid_pdoor.dmi'
icon_state = null
+ min_force = 20 //minimum amount of force needed to damage the door with a melee weapon
// Icon states for different shutter types. Simply change this instead of rewriting the update_icon proc.
var/icon_state_open = null
@@ -78,7 +79,10 @@
// Proc: force_toggle()
// Parameters: None
// Description: Opens or closes the door, depending on current state. No checks are done inside this proc.
-/obj/machinery/door/blast/proc/force_toggle()
+/obj/machinery/door/blast/proc/force_toggle(var/forced = 0, mob/user as mob)
+ if (forced)
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+
if(src.density)
src.force_open()
else
@@ -91,7 +95,7 @@
/obj/machinery/door/blast/attackby(obj/item/weapon/C as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(C, /obj/item/weapon)) // For reasons unknown, sometimes C is actually not what it is advertised as, like a mob.
- if(C.pry == 1) // Can we pry it open with something, like a crowbar/fireaxe/lingblade?
+ if(C.pry == 1 && (user.a_intent != I_HURT || (stat & BROKEN))) // Can we pry it open with something, like a crowbar/fireaxe/lingblade?
if(istype(C,/obj/item/weapon/material/twohanded/fireaxe)) // Fireaxes need to be in both hands to pry.
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(!F.wielded)
@@ -100,7 +104,8 @@
// If we're at this point, it's a fireaxe in both hands or something else that doesn't care for twohanding.
if(((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating ))
- force_toggle()
+ force_toggle(1, user)
+
else
usr << "[src]'s motors resist your effort."
return
@@ -123,15 +128,33 @@
usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
+ else if(src.density)
+ var/obj/item/weapon/W = C
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(W.damtype == BRUTE || W.damtype == BURN)
+ user.do_attack_animation(src)
+ if(W.force < min_force)
+ user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
+ else
+ user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
+ playsound(src.loc, hitsound, 100, 1)
+ take_damage(W.force*0.35) //it's a blast door, it should take a while. -Luke
+ return
+
// Proc: open()
// Parameters: None
// Description: Opens the door. Does necessary checks. Automatically closes if autoclose is true
-/obj/machinery/door/blast/open()
- if (src.operating || (stat & BROKEN || stat & NOPOWER))
- return
- force_open()
- if(autoclose)
+/obj/machinery/door/blast/open(var/forced = 0)
+ if(forced)
+ force_open()
+ return 1
+ else
+ if (src.operating || (stat & BROKEN || stat & NOPOWER))
+ return 1
+ force_open()
+
+ if(autoclose && src.operating && !(stat & BROKEN || stat & NOPOWER))
spawn(150)
close()
return 1
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 185de7f06db..cd38f9f1ceb 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -312,6 +312,8 @@
/obj/machinery/door/examine(mob/user)
. = ..()
+ if(src.health <= 0)
+ user << "\The [src] is broken!"
if(src.health < src.maxhealth / 4)
user << "\The [src] looks like it's about to break!"
else if(src.health < src.maxhealth / 2)
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index ae48142b4d2..a18edbc5fa5 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -78,7 +78,7 @@
C.traits = new()
C.nameVar = "grey"
I.add_product(C)
-
+
/obj/machinery/smartfridge/secure/medbay
name = "\improper Refrigerated Medicine Storage"
@@ -139,6 +139,7 @@
icon_state = "drying_rack"
icon_on = "drying_rack_on"
icon_off = "drying_rack"
+ icon_panel = "drying_rack-panel"
/obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj)
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/))
@@ -260,7 +261,7 @@
locked = -1
user << "You short out the product lock on [src]."
return 1
-
+
/obj/machinery/smartfridge/proc/stock(obj/item/O)
var/hasRecord = FALSE //Check to see if this passes or not.
for(var/datum/stored_item/I in item_records)
@@ -273,7 +274,7 @@
item.add_product(O)
item_records.Add(item)
nanomanager.update_uis(src)
-
+
/obj/machinery/smartfridge/proc/vend(datum/stored_item/I)
I.get_product(get_turf(src))
nanomanager.update_uis(src)
@@ -357,7 +358,7 @@
if (!throw_item)
continue
break
-
+
if(!throw_item)
return 0
spawn(0)
diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm
index ffe30bf3fd8..1e10e03f4f8 100644
--- a/code/game/mecha/equipment/tools/medical_tools.dm
+++ b/code/game/mecha/equipment/tools/medical_tools.dm
@@ -7,7 +7,7 @@
energy_drain = 20
range = MELEE
equip_cooldown = 50
- var/mob/living/carbon/occupant = null
+ var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 10
required_type = /obj/mecha/medical
@@ -28,7 +28,7 @@
Exit(atom/movable/O)
return 0
- action(var/mob/living/carbon/target)
+ action(var/mob/living/carbon/human/target)
if(!action_checks(target))
return
if(!istype(target))
@@ -56,6 +56,7 @@
target.forceMove(src)
occupant = target
target.reset_view(src)
+ occupant.Stasis(3)
/*
if(target.client)
target.client.perspective = EYE_PERSPECTIVE
@@ -80,6 +81,7 @@
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
*/
+ occupant.Stasis(0)
occupant = null
pr_mech_sleeper.stop()
set_ready_state(1)
diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm
index a6da9bfa000..00a0654cc12 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/game/mecha/mecha_control_console.dm
@@ -1,6 +1,5 @@
/obj/machinery/computer/mecha
name = "Exosuit Control"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "rd_key"
icon_screen = "mecha"
light_color = "#a97faa"
diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm
index 967c03252f3..6aec830c899 100644
--- a/code/game/mecha/medical/odysseus.dm
+++ b/code/game/mecha/medical/odysseus.dm
@@ -95,7 +95,7 @@
holder.icon_state = "hudhealth-100"
C.images += holder
else
- holder.icon_state = RoundHealth((patient.health-config.health_threshold_crit)/(patient.maxHealth-config.health_threshold_crit)*100)
+ holder.icon_state = RoundHealth((patient.health-config.health_threshold_crit)/(patient.getMaxHealth()-config.health_threshold_crit)*100)
C.images += holder
holder = patient.hud_list[STATUS_HUD]
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 7950200137d..f456a95d734 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -74,7 +74,12 @@
add_fingerprint(user)
unbuckle_mob()
- if(buckle_mob(M))
+ //can't buckle unless you share locs so try to move M to the obj.
+ if(M.loc != src.loc)
+ step_towards(M, src)
+
+ . = buckle_mob(M)
+ if(.)
if(M == user)
M.visible_message(\
"[M.name] buckles themselves to [src].",\
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index 1450fa94ce5..4d77da4ae93 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -77,14 +77,20 @@
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
..()
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
- if(!ishuman(usr)) return
+ if(!ishuman(usr)) return 0
if(opened) return 0
if(contents.len) return 0
visible_message("[usr] folds up the [src.name]")
- new item_path(get_turf(src))
+ var/folded = new item_path(get_turf(src))
spawn(0)
qdel(src)
- return
+ return folded
+
+/obj/structure/closet/body_bag/relaymove(mob/user,direction)
+ if(src.loc != get_turf(src))
+ src.loc.relaymove(user,direction)
+ else
+ ..()
/obj/structure/closet/body_bag/proc/get_occupants()
var/list/occupants = list()
@@ -109,34 +115,43 @@
/obj/item/bodybag/cryobag
name = "stasis bag"
- desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant, especially useful if short on time or in \
- a hostile enviroment."
+ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
+ especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi'
icon_state = "bodybag_folded"
item_state = "bodybag_cryo_folded"
origin_tech = list(TECH_BIO = 4)
+ var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/item/bodybag/cryobag/attack_self(mob/user)
var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
R.add_fingerprint(user)
+ if(syringe)
+ R.syringe = syringe
+ syringe = null
qdel(src)
/obj/structure/closet/body_bag/cryobag
name = "stasis bag"
- desc = "A non-reusable plastic bag designed to prevent additional damage to an occupant, especially useful if short on time or in \
- a hostile enviroment."
+ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
+ especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi'
item_path = /obj/item/bodybag/cryobag
store_misc = 0
store_items = 0
var/used = 0
var/obj/item/weapon/tank/tank = null
+ var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
+ var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/structure/closet/body_bag/cryobag/New()
tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened.
..()
/obj/structure/closet/body_bag/cryobag/Destroy()
+ if(syringe)
+ qdel(syringe)
+ syringe = null
qdel(tank)
tank = null
..()
@@ -151,11 +166,19 @@
O.desc = "Pretty useless now.."
qdel(src)
+/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
+ . = ..()
+ if(. && syringe)
+ var/obj/item/bodybag/cryobag/folded = .
+ folded.syringe = syringe
+ syringe = null
+
/obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
- H.in_stasis = 1
+ H.Stasis(stasis_level)
src.used = 1
+ inject_occupant(H)
if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM
@@ -167,7 +190,7 @@
/obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
- H.in_stasis = 0
+ H.Stasis(0)
if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM
@@ -181,10 +204,19 @@
return tank.air_contents
..()
+/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H)
+ if(!syringe)
+ return
+
+ if(H.reagents)
+ syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD)
+
/obj/structure/closet/body_bag/cryobag/examine(mob/user)
..()
if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
user << "You peer into \the [src]."
+ if(syringe)
+ user << "It has a syringe added to it."
for(var/mob/living/L in contents)
L.examine(user)
@@ -196,5 +228,28 @@
var/obj/item/device/healthanalyzer/analyzer = W
for(var/mob/living/L in contents)
analyzer.attack(L,user)
+
+ else if(istype(W,/obj/item/weapon/reagent_containers/syringe))
+ if(syringe)
+ to_chat(user,"\The [src] already has an injector! Remove it first.")
+ else
+ var/obj/item/weapon/reagent_containers/syringe/syringe = W
+ to_chat(user,"You insert \the [syringe] into \the [src], and it locks into place.")
+ user.unEquip(syringe)
+ src.syringe = syringe
+ syringe.loc = null
+ for(var/mob/living/carbon/human/H in contents)
+ inject_occupant(H)
+ break
+
+ else if(istype(W,/obj/item/weapon/screwdriver))
+ if(syringe)
+ if(used)
+ to_chat(user,"The injector cannot be removed now that the stasis bag has been used!")
+ else
+ syringe.forceMove(src.loc)
+ to_chat(user,"You pry \the [syringe] out of \the [src].")
+ syringe = null
+
else
..()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 674e746c28b..667adfc712f 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -1105,6 +1105,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(M.stat == DEAD && M.client && (M.is_preference_enabled(/datum/client_preference/ghost_ears))) // src.client is so that ghosts don't have to listen to mice
if(istype(M, /mob/new_player))
continue
+ if(M.forbid_seeing_deadchat)
+ continue
M.show_message("PDA Message - [owner] -> [P.owner]: [t]")
if(!conversations.Find("\ref[P]"))
diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm
index 8bfe2dffca2..42c8e4949b7 100644
--- a/code/game/objects/items/devices/communicator/communicator.dm
+++ b/code/game/objects/items/devices/communicator/communicator.dm
@@ -212,6 +212,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
alert_called = 0
update_icon()
ui_interact(user)
+ if(video_source)
+ watch_video(user)
// Proc: MouseDrop()
//Same thing PDAs do
@@ -1032,7 +1034,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(!Adjacent(user) || !video_source) return
user.set_machine(video_source)
user.reset_view(video_source)
- user << "Now viewing video session. To leave camera view: OOC -> Cancel Camera View"
+ to_chat(user,"Now viewing video session. To leave camera view, close the communicator window OR: OOC -> Cancel Camera View")
+ to_chat(user,"To return to an active video session, use the communicator in your hand.")
spawn(0)
while(user.machine == video_source && Adjacent(user))
var/turf/T = get_turf(video_source)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index b553f4416ce..62d7e7b311c 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -92,8 +92,8 @@
flash_strength *= H.species.flash_mod
if(flash_strength > 0)
- H.confused = max(H.confused, flash_strength + 5)
- H.eye_blind = max(H.eye_blind, flash_strength)
+ H.Confuse(flash_strength + 5)
+ H.Blind(flash_strength)
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
H.flash_eyes()
H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun.
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 1bd7f9349ad..74d9a4b8ed2 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -65,10 +65,12 @@ var/global/list/default_medbay_channels = list(
..()
wires = new(src)
internal_channels = default_internal_channels.Copy()
+ listening_objects += src
/obj/item/device/radio/Destroy()
qdel(wires)
wires = null
+ listening_objects -= src
if(radio_controller)
radio_controller.remove_object(src, frequency)
for (var/ch_name in channels)
@@ -474,7 +476,6 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null)
-
if (broadcasting)
if(get_dist(src, M) <= canhear_range)
talk_into(M, msg,null,verb,speaking)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 243d301289b..5d883784aa0 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -69,7 +69,7 @@ REAGENT SCANNER
user.show_message("Analyzing Results for [M]:")
user.show_message("Overall Status: dead")
else
- user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.maxHealth)*100) ]% healthy"]")
+ user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]")
user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message(" Damage Specifics: [OX] - [TX] - [BU] - [BR]")
user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
diff --git a/code/game/objects/items/devices/translator.dm b/code/game/objects/items/devices/translator.dm
index 90fb43724ed..5de1ba13961 100644
--- a/code/game/objects/items/devices/translator.dm
+++ b/code/game/objects/items/devices/translator.dm
@@ -47,6 +47,9 @@
var/mob/living/L = loc
+ if(!language)
+ return //Borgs were causing runtimes when passing language=null
+
if (language && (language.flags & NONVERBAL))
return //Not gonna translate sign language
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 15f33103225..db4e890d604 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -155,7 +155,7 @@
singular_name = "advanced trauma kit"
desc = "An advanced trauma kit for severe injuries."
icon_state = "traumakit"
- heal_brute = 0
+ heal_brute = 5
origin_tech = list(TECH_BIO = 1)
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -213,7 +213,7 @@
singular_name = "advanced burn kit"
desc = "An advanced treatment kit for severe burns."
icon_state = "burnkit"
- heal_burn = 0
+ heal_burn = 5
origin_tech = list(TECH_BIO = 1)
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index 10a847b4695..d404b5cd445 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -39,7 +39,7 @@ RSF
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
if (mode == 1)
mode = 2
- user << "Changed dispensing mode to 'Drinking Glass'"
+ user << "Changed dispensing mode to 'Drinking Glass:Pint'"
return
if (mode == 2)
mode = 3
@@ -82,7 +82,7 @@ RSF
product = new /obj/item/clothing/mask/smokable/cigarette()
used_energy = 10
if(2)
- product = new /obj/item/weapon/reagent_containers/food/drinks/glass2()
+ product = new /obj/item/weapon/reagent_containers/food/drinks/glass2/pint()
used_energy = 50
if(3)
product = new /obj/item/weapon/paper()
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index 76c4f9e7688..ee2d2f2c57a 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -399,21 +399,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
..()
name = "empty [initial(name)]"
-/obj/item/clothing/mask/smokable/pipe/light(var/flavor_text = "[usr] lights the [name].")
- if(!src.lit && src.smoketime)
- src.lit = 1
- damtype = "fire"
- icon_state = icon_on
- item_state = icon_on
- var/turf/T = get_turf(src)
- T.visible_message(flavor_text)
- processing_objects.Add(src)
- if(ismob(loc))
- var/mob/living/M = loc
- M.update_inv_wear_mask(0)
- M.update_inv_l_hand(0)
- M.update_inv_r_hand(1)
-
/obj/item/clothing/mask/smokable/pipe/attack_self(mob/user as mob)
if(lit == 1)
if(user.a_intent == I_HURT)
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 1190d7f8120..62941c24f08 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -41,6 +41,8 @@
user << "You need to have a firm grip on [C] before you can put \the [src] on!"
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
+ if(user == target)
+ return 1
if(istype(user, /mob/living/silicon/robot))
if(user.Adjacent(target))
return 1
diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm
index cf55cbd7067..db24be3c0af 100644
--- a/code/game/objects/items/weapons/implants/implantcircuits.dm
+++ b/code/game/objects/items/weapons/implants/implantcircuits.dm
@@ -38,7 +38,10 @@
IC.examine(user)
/obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user)
- if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) )
+ if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) || istype(O, /obj/item/weapon/cell/device) )
IC.attackby(O, user)
else
- ..()
\ No newline at end of file
+ ..()
+
+/obj/item/weapon/implant/integrated_circuit/attack_self(mob/user)
+ IC.attack_self(user)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm
index b13b5e6ac22..87b635ce50e 100644
--- a/code/game/objects/items/weapons/material/kitchen.dm
+++ b/code/game/objects/items/weapons/material/kitchen.dm
@@ -7,7 +7,7 @@
/obj/item/weapon/material/kitchen/utensil
w_class = ITEMSIZE_TINY
thrown_force_divisor = 1
- origin_tech = "materials=1"
+ origin_tech = list(TECH_MATERIAL = 1)
attack_verb = list("attacked", "stabbed", "poked")
sharp = 1
edge = 1
diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm
index 593b1d92376..9545504f84e 100644
--- a/code/game/objects/items/weapons/material/knives.dm
+++ b/code/game/objects/items/weapons/material/knives.dm
@@ -64,7 +64,7 @@
edge = 1
force_divisor = 0.15 // 9 when wielded with hardness 60 (steel)
matter = list(DEFAULT_WALL_MATERIAL = 12000)
- origin_tech = "materials=1"
+ origin_tech = list(TECH_MATERIAL = 1)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/weapon/material/knife/suicide_act(mob/user)
diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm
new file mode 100644
index 00000000000..1041fb5d1fd
--- /dev/null
+++ b/code/game/objects/items/weapons/material/material_armor.dm
@@ -0,0 +1,263 @@
+#define MATERIAL_ARMOR_COEFFICENT 0.05
+/*
+SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
+This class of armor takes armor and appearance data from a material "datum".
+They are also fragile based on material data and many can break/smash apart when hit.
+
+Materials has a var called protectiveness which plays a major factor in how good it is for armor.
+With the coefficent being 0.05, this is how strong different levels of protectiveness are (for melee)
+For bullets and lasers, material hardness and reflectivity also play a major role, respectively.
+
+
+Protectiveness | Armor %
+ 0 = 0%
+ 5 = 20%
+ 10 = 33%
+ 15 = 42%
+ 20 = 50%
+ 25 = 55%
+ 30 = 60%
+ 40 = 66%
+ 50 = 71%
+ 60 = 75%
+ 70 = 77%
+ 80 = 80%
+*/
+
+
+// Putting these at /clothing/ level saves a lot of code duplication in armor/helmets/gauntlets/etc
+/obj/item/clothing
+ var/material/material = null // Why isn't this a datum?
+ var/applies_material_color = TRUE
+ var/unbreakable = FALSE
+ var/default_material = null // Set this to something else if you want material attributes on init.
+ var/material_armor_modifer = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor)
+
+/obj/item/clothing/New(var/newloc, var/material_key)
+ ..(newloc)
+ if(!material_key)
+ material_key = default_material
+ if(material_key) // May still be null if a material was not specified as a default.
+ set_material(material_key)
+
+/obj/item/clothing/Destroy()
+ processing_objects -= src
+ ..()
+
+/obj/item/clothing/get_material()
+ return material
+
+// Debating if this should be made an /obj/item/ proc.
+/obj/item/clothing/proc/set_material(var/new_material)
+ material = get_material_by_name(new_material)
+ if(!material)
+ qdel(src)
+ else
+ name = "[material.display_name] [initial(name)]"
+ health = round(material.integrity/10)
+ if(applies_material_color)
+ color = material.icon_colour
+ if(material.products_need_process())
+ processing_objects |= src
+ update_armor()
+
+// This is called when someone wearing the object gets hit in some form (melee, bullet_act(), etc).
+// Note that this cannot change if someone gets hurt, as it merely reacts to being hit.
+/obj/item/clothing/proc/clothing_impact(var/obj/source, var/damage)
+ if(material && damage)
+ material_impact(source, damage)
+
+/obj/item/clothing/proc/material_impact(var/obj/source, var/damage)
+ if(!material || unbreakable)
+ return
+
+ if(istype(source, /obj/item/projectile))
+ var/obj/item/projectile/P = source
+ if(P.pass_flags & PASSGLASS)
+ if(material.opacity - 0.3 <= 0)
+ return // Lasers ignore 'fully' transparent material.
+
+ if(material.is_brittle())
+ health = 0
+ else if(!prob(material.hardness))
+ health--
+
+ if(health <= 0)
+ shatter()
+
+/obj/item/clothing/proc/shatter()
+ if(!material)
+ return
+ var/turf/T = get_turf(src)
+ T.visible_message("\The [src] [material.destruction_desc]!")
+ if(istype(loc, /mob/living))
+ var/mob/living/M = loc
+ M.drop_from_inventory(src)
+ if(material.shard_type == SHARD_SHARD) // Wearing glass armor is a bad idea.
+ var/obj/item/weapon/material/shard/S = material.place_shard(T)
+ M.embed(S)
+
+ playsound(src, "shatter", 70, 1)
+ qdel(src)
+
+// Might be best to make ablative vests a material armor using a new material to cut down on this copypaste.
+/obj/item/clothing/suit/armor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(!material) // No point checking for reflection.
+ return ..()
+
+ if(material.reflectivity)
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
+ var/reflectchance = (40 * material.reflectivity) - round(damage/3)
+ reflectchance *= material_armor_modifer
+ if(!(def_zone in list(BP_TORSO, BP_GROIN)))
+ reflectchance /= 2
+ if(P.starting && prob(reflectchance))
+ visible_message("\The [user]'s [src.name] reflects [attack_text]!")
+
+ // Find a turf near or on the original location to bounce to
+ var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/turf/curloc = get_turf(user)
+
+ // redirect the projectile
+ P.redirect(new_x, new_y, curloc, user)
+ P.reflected = 1
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+
+/proc/calculate_material_armor(amount)
+ var/result = 1 - MATERIAL_ARMOR_COEFFICENT * amount / (1 + MATERIAL_ARMOR_COEFFICENT * abs(amount))
+ result = result * 100
+ result = abs(result - 100)
+ return round(result)
+
+
+/obj/item/clothing/proc/update_armor()
+ if(material)
+ var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0
+
+ melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer)
+
+ bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifer) * 0.7)
+
+ laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifer) * 0.7)
+ if(material.opacity != 1)
+ laser_armor *= max(material.opacity - 0.3, 0) // Glass and such has an opacity of 0.3, but lasers should go through glass armor entirely.
+
+ energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.4)
+
+ bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5)
+
+ // Makes sure the numbers stay capped.
+ for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor))
+ number = between(0, number, 100)
+
+ armor["melee"] = melee_armor
+ armor["bullet"] = bullet_armor
+ armor["laser"] = laser_armor
+ armor["energy"] = energy_armor
+ armor["bomb"] = bomb_armor
+
+ if(!isnull(material.conductivity))
+ siemens_coefficient = between(0, material.conductivity / 10, 10)
+ slowdown = between(0, round(material.weight / 10, 0.1), 6)
+
+/obj/item/clothing/suit/armor/material
+ name = "armor"
+ default_material = DEFAULT_WALL_MATERIAL
+
+/obj/item/clothing/suit/armor/material/makeshift
+ name = "sheet armor"
+ desc = "This appears to be two 'sheets' of a material held together by cable. If the sheets are strong, this could be rather protective."
+ icon_state = "material_armor_makeshift"
+
+/obj/item/clothing/suit/armor/material/makeshift/durasteel
+ default_material = "durasteel"
+
+/obj/item/clothing/suit/armor/material/makeshift/glass
+ default_material = "glass"
+
+// Used to craft sheet armor, and possibly other things in the Future(tm).
+/obj/item/weapon/material/armor_plating
+ name = "armor plating"
+ desc = "A sheet designed to protect something."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "armor_plate"
+ unbreakable = TRUE
+ force_divisor = 0.05 // Really bad as a weapon.
+ thrown_force_divisor = 0.2
+ var/wired = FALSE
+
+/obj/item/weapon/material/armor_plating/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/S = O
+ if(wired)
+ to_chat(user, "This already has enough wires on it.")
+ return
+ if(S.use(20))
+ to_chat(user, "You attach several wires to \the [src]. Now it needs another plate.")
+ wired = TRUE
+ icon_state = "[initial(icon_state)]_wired"
+ return
+ else
+ to_chat(user, "You need more wire for that.")
+ return
+ if(istype(O, /obj/item/weapon/material/armor_plating))
+ var/obj/item/weapon/material/armor_plating/second_plate = O
+ if(!wired && !second_plate.wired)
+ to_chat(user, "You need something to hold the two pieces of plating together.")
+ return
+ if(second_plate.material != src.material)
+ to_chat(user, "Both plates need to be the same type of material.")
+ return
+ user.drop_from_inventory(src)
+ user.drop_from_inventory(second_plate)
+ var/obj/item/clothing/suit/armor/material/makeshift/new_armor = new(null, src.material.name)
+ user.put_in_hands(new_armor)
+ qdel(second_plate)
+ qdel(src)
+ else
+ ..()
+
+
+// Used to craft the makeshift helmet
+/obj/item/clothing/head/helmet/bucket
+ name = "bucket"
+ desc = "It's a bucket with a large hole cut into it. You could wear it on your head and look really stupid."
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ icon_state = "bucket"
+ armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/head/helmet/bucket/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/material))
+ var/obj/item/stack/material/S = O
+ if(S.use(2))
+ to_chat(user, "You apply some [S.material.use_name] to \the [src]. Hopefully it'll make the makeshift helmet stronger.")
+ var/obj/item/clothing/head/helmet/material/makeshift/helmet = new(null, S.material.name)
+ user.put_in_hands(helmet)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+ else
+ to_chat(user, "You don't have enough material to build a helmet!")
+ else
+ ..()
+
+/obj/item/clothing/head/helmet/material
+ name = "helmet"
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ default_material = DEFAULT_WALL_MATERIAL
+
+/obj/item/clothing/head/helmet/material/makeshift
+ name = "bucket"
+ desc = "A bucket with plating applied to the outside. Very crude, but could potentially be rather protective, if \
+ it was plated with something strong."
+ icon_state = "material_armor_makeshift"
+
+/obj/item/clothing/head/helmet/material/makeshift/durasteel
+ default_material = "durasteel"
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index 5edd1c77b57..2d85bc0a663 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -29,7 +29,7 @@
w_class = ITEMSIZE_SMALL
sharp = 1
edge = 1
- origin_tech = "materials=2;combat=1"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
attack_verb = list("chopped", "torn", "cut")
applies_material_colour = 0
@@ -99,5 +99,5 @@
throw_range = 3
w_class = ITEMSIZE_LARGE
slot_flags = SLOT_BACK
- origin_tech = "materials=2;combat=2"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 2)
attack_verb = list("chopped", "sliced", "cut", "reaped")
diff --git a/code/game/objects/items/weapons/permits.dm b/code/game/objects/items/weapons/permits.dm
index bb0ebfdd0c2..8008959460a 100644
--- a/code/game/objects/items/weapons/permits.dm
+++ b/code/game/objects/items/weapons/permits.dm
@@ -32,4 +32,9 @@
/obj/item/weapon/permit/gun/bar
name = "bar shotgun permit"
- desc = "A card indicating that the owner is allowed to carry a shotgun in the bar."
\ No newline at end of file
+ desc = "A card indicating that the owner is allowed to carry a shotgun in the bar."
+
+/obj/item/weapon/permit/drone
+ name = "drone identification card"
+ desc = "A card issued by the EIO, indicating that the owner is a Drone Intelligence. Drones are mandated to carry this card within SolGov space, by law."
+ icon_state = "drone"
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index a9f2a15deaf..9b4cb3ca9bc 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -2,12 +2,12 @@
/obj/item/taperoll
name = "tape roll"
icon = 'icons/policetape.dmi'
- icon_state = "rollstart"
+ icon_state = "tape"
w_class = ITEMSIZE_SMALL
var/turf/start
var/turf/end
var/tape_type = /obj/item/tape
- var/icon_base
+ var/icon_base = "tape"
var/apply_tape = FALSE
@@ -33,7 +33,7 @@ var/list/tape_roll_applications = list()
var/lifted = 0
var/crumpled = 0
var/tape_dir = 0
- var/icon_base
+ var/icon_base = "tape"
/obj/item/tape/update_icon()
//Possible directional bitflags: 0 (AIRLOCK), 1 (NORTH), 2 (SOUTH), 4 (EAST), 8 (WEST), 3 (VERTICAL), 12 (HORIZONTAL)
@@ -60,22 +60,20 @@ var/list/tape_roll_applications = list()
/obj/item/taperoll/police
name = "police tape"
desc = "A roll of police tape used to block off crime scenes from the public."
- icon_state = "police"
tape_type = /obj/item/tape/police
- icon_base = "police"
+ color = COLOR_RED_LIGHT
/obj/item/tape/police
name = "police tape"
desc = "A length of police tape. Do not cross."
req_access = list(access_security)
- icon_base = "police"
+ color = COLOR_RED_LIGHT
/obj/item/taperoll/engineering
name = "engineering tape"
desc = "A roll of engineering tape used to block off working areas from the public."
- icon_state = "engineering"
tape_type = /obj/item/tape/engineering
- icon_base = "engineering"
+ color = COLOR_YELLOW
/obj/item/taperoll/engineering/applied
apply_tape = TRUE
@@ -84,28 +82,31 @@ var/list/tape_roll_applications = list()
name = "engineering tape"
desc = "A length of engineering tape. Better not cross it."
req_one_access = list(access_engine,access_atmospherics)
- icon_base = "engineering"
+ color = COLOR_YELLOW
/obj/item/taperoll/atmos
name = "atmospherics tape"
desc = "A roll of atmospherics tape used to block off working areas from the public."
- icon_state = "atmos"
tape_type = /obj/item/tape/atmos
- icon_base = "atmos"
+ color = COLOR_DEEP_SKY_BLUE
/obj/item/tape/atmos
name = "atmospherics tape"
desc = "A length of atmospherics tape. Better not cross it."
req_one_access = list(access_engine,access_atmospherics)
- icon_base = "atmos"
+ color = COLOR_DEEP_SKY_BLUE
/obj/item/taperoll/update_icon()
overlays.Cut()
+ var/image/overlay = image(icon = src.icon)
+ overlay.appearance_flags = RESET_COLOR
if(ismob(loc))
if(!start)
- overlays += "start"
+ overlay.icon_state = "start"
else
- overlays += "stop"
+ overlay.icon_state = "stop"
+ overlays += overlay
+
/obj/item/taperoll/dropped(mob/user)
update_icon()
diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm
index b6fc2f42511..04e5aa909bf 100644
--- a/code/game/objects/items/weapons/tape.dm
+++ b/code/game/objects/items/weapons/tape.dm
@@ -163,6 +163,15 @@
overlays = null
qdel(src)
+/obj/item/weapon/ducttape/attackby(var/obj/item/I, var/mob/user)
+ if(!(istype(src, /obj/item/weapon/handcuffs/cable/tape) || istype(src, /obj/item/clothing/mask/muzzle/tape)))
+ return ..()
+ else
+ user.drop_from_inventory(I)
+ I.loc = src
+ qdel(I)
+ to_chat(user, "You place \the [I] back into \the [src].")
+
/obj/item/weapon/ducttape/afterattack(var/A, mob/user, flag, params)
if(!in_range(user, A) || istype(A, /obj/machinery/door) || !stuck)
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 1080e1b8fbe..8c4067187fe 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -401,7 +401,7 @@
user.sdisabilities |= BLIND
else if (E.damage >= E.min_bruised_damage)
user << "You go blind!"
- user.eye_blind = 5
+ user.Blind(5)
user.eye_blurry = 5
user.disabilities |= NEARSIGHTED
spawn(100)
diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm
index cd11af34000..e6abdcb366e 100644
--- a/code/game/objects/items/weapons/traps.dm
+++ b/code/game/objects/items/weapons/traps.dm
@@ -8,7 +8,7 @@
desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off."
throwforce = 0
w_class = ITEMSIZE_NORMAL
- origin_tech = "materials=1"
+ origin_tech = list(TECH_MATERIAL = 1)
matter = list(DEFAULT_WALL_MATERIAL = 18750)
var/deployed = 0
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index bd280787827..42ee6af2e3e 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -77,34 +77,44 @@
return
return
+
/obj/structure/morgue/attack_hand(mob/user as mob)
if (src.connected)
- for(var/atom/movable/A as mob|obj in src.connected.loc)
- if (!( A.anchored ))
- A.forceMove(src)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- qdel(src.connected)
- src.connected = null
+ close()
else
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- src.connected = new /obj/structure/m_tray( src.loc )
- step(src.connected, src.dir)
- src.connected.layer = OBJ_LAYER
- var/turf/T = get_step(src, src.dir)
- if (T.contents.Find(src.connected))
- src.connected.connected = src
- src.icon_state = "morgue0"
- for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.connected.loc)
- src.connected.icon_state = "morguet"
- src.connected.set_dir(src.dir)
- else
- qdel(src.connected)
- src.connected = null
+ open()
src.add_fingerprint(user)
update()
return
+
+/obj/structure/morgue/proc/close()
+ for(var/atom/movable/A as mob|obj in src.connected.loc)
+ if (!( A.anchored ))
+ A.forceMove(src)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ qdel(src.connected)
+ src.connected = null
+
+
+/obj/structure/morgue/proc/open()
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ src.connected = new /obj/structure/m_tray( src.loc )
+ step(src.connected, src.dir)
+ src.connected.layer = OBJ_LAYER
+ var/turf/T = get_step(src, src.dir)
+ if (T.contents.Find(src.connected))
+ src.connected.connected = src
+ src.icon_state = "morgue0"
+ for(var/atom/movable/A as mob|obj in src)
+ A.forceMove(src.connected.loc)
+ src.connected.icon_state = "morguet"
+ src.connected.set_dir(src.dir)
+ else
+ qdel(src.connected)
+ src.connected = null
+
+
/obj/structure/morgue/attackby(P as obj, mob/user as mob)
if (istype(P, /obj/item/weapon/pen))
var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text
@@ -123,21 +133,8 @@
/obj/structure/morgue/relaymove(mob/user as mob)
if (user.stat)
return
- src.connected = new /obj/structure/m_tray( src.loc )
- step(src.connected, EAST)
- src.connected.layer = OBJ_LAYER
- var/turf/T = get_step(src, EAST)
- if (T.contents.Find(src.connected))
- src.connected.connected = src
- src.icon_state = "morgue0"
- for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.connected.loc)
- src.connected.icon_state = "morguet"
- else
- qdel(src.connected)
- src.connected = null
- return
-
+ if (user in src.occupants)
+ open()
/*
* Morgue tray
diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm
index 779f76fc933..2170ea30194 100644
--- a/code/game/turfs/flooring/flooring.dm
+++ b/code/game/turfs/flooring/flooring.dm
@@ -37,6 +37,7 @@ var/list/flooring_types
var/descriptor = "tiles"
var/flags
var/can_paint
+ var/list/footstep_sounds = list() // key=species name, value = list of soundss
/decl/flooring/grass
name = "grass"
@@ -90,6 +91,12 @@ var/list/flooring_types
build_type = /obj/item/stack/tile/carpet
damage_temperature = T0C+200
flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_CROWBAR | TURF_CAN_BURN
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/carpet1.ogg',
+ 'sound/effects/footstep/carpet2.ogg',
+ 'sound/effects/footstep/carpet3.ogg',
+ 'sound/effects/footstep/carpet4.ogg',
+ 'sound/effects/footstep/carpet5.ogg'))
/decl/flooring/carpet/blue
name = "carpet"
@@ -107,6 +114,12 @@ var/list/flooring_types
flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK | TURF_CAN_BURN
build_type = /obj/item/stack/tile/floor
can_paint = 1
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/floor1.ogg',
+ 'sound/effects/footstep/floor2.ogg',
+ 'sound/effects/footstep/floor3.ogg',
+ 'sound/effects/footstep/floor4.ogg',
+ 'sound/effects/footstep/floor5.ogg'))
/decl/flooring/linoleum
name = "linoleum"
@@ -193,6 +206,12 @@ var/list/flooring_types
descriptor = "planks"
build_type = /obj/item/stack/tile/wood
flags = TURF_CAN_BREAK | TURF_IS_FRAGILE | TURF_REMOVE_SCREWDRIVER
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/wood1.ogg',
+ 'sound/effects/footstep/wood2.ogg',
+ 'sound/effects/footstep/wood3.ogg',
+ 'sound/effects/footstep/wood4.ogg',
+ 'sound/effects/footstep/wood5.ogg'))
/decl/flooring/reinforced
name = "reinforced floor"
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 3a7c1afdf0d..336a34b2fe3 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -13,6 +13,12 @@
var/base_desc = "The naked hull."
var/base_icon = 'icons/turf/flooring/plating.dmi'
var/base_icon_state = "plating"
+ var/static/list/base_footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/plating1.ogg',
+ 'sound/effects/footstep/plating2.ogg',
+ 'sound/effects/footstep/plating3.ogg',
+ 'sound/effects/footstep/plating4.ogg',
+ 'sound/effects/footstep/plating5.ogg'))
// Flooring data.
var/flooring_override
@@ -33,10 +39,13 @@
floortype = initial_flooring
if(floortype)
set_flooring(get_flooring_data(floortype))
+ else
+ footstep_sounds = base_footstep_sounds
/turf/simulated/floor/proc/set_flooring(var/decl/flooring/newflooring)
make_plating(defer_icon_update = 1)
flooring = newflooring
+ footstep_sounds = newflooring.footstep_sounds
update_icon(1)
levelupdate()
@@ -53,6 +62,7 @@
desc = base_desc
icon = base_icon
icon_state = base_icon_state
+ footstep_sounds = base_footstep_sounds
if(flooring)
if(flooring.build_type && place_product)
diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm
index da694061571..75c7e680835 100644
--- a/code/game/turfs/simulated/outdoors/outdoors.dm
+++ b/code/game/turfs/simulated/outdoors/outdoors.dm
@@ -31,17 +31,19 @@ var/list/outdoor_turfs = list()
/turf/simulated/floor/Destroy()
if(outdoors)
- outdoor_turfs.Remove(src)
+ planet_controller.unallocateTurf(src)
..()
-/turf/simulated/floor/proc/update_icon_edge()
+/turf/simulated/proc/update_icon_edge()
if(edge_blending_priority)
for(var/checkdir in cardinal)
var/turf/simulated/T = get_step(src, checkdir)
if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state)
var/cache_key = "[T.get_edge_icon_state()]-[checkdir]"
if(!turf_edge_cache[cache_key])
- turf_edge_cache[cache_key] = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir)
+ var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir)
+ I.plane = 0
+ turf_edge_cache[cache_key] = I
overlays += turf_edge_cache[cache_key]
/turf/simulated/proc/get_edge_icon_state()
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index 77eb419ed13..781ddeeb7f7 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -35,7 +35,16 @@
water_breath.temperature = above_air.temperature
return water_breath
else
- return null // Lying down means they're submerged, which means no air.
+ var/gasid = "carbon_dioxide"
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ if(H.species && H.species.exhale_type)
+ gasid = H.species.exhale_type
+ var/datum/gas_mixture/water_breath = new()
+ var/datum/gas_mixture/above_air = return_air()
+ water_breath.adjust_gas(gasid, BREATH_MOLES) // They have no oxygen, but non-zero moles and temp
+ water_breath.temperature = above_air.temperature
+ return water_breath
return return_air() // Otherwise their head is above the water, so get the air from the atmosphere instead.
/turf/simulated/floor/water/Entered(atom/movable/AM, atom/oldloc)
@@ -94,7 +103,7 @@
return
/mob/living/water_act(amount)
- adjust_fire_stacks(amount * 5)
+ adjust_fire_stacks(-amount * 5)
for(var/atom/movable/AM in contents)
AM.water_act(amount)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index c13b4606d36..3f2e0064f22 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -26,6 +26,8 @@
var/movement_cost = 0 // How much the turf slows down movement, if any.
+ var/list/footstep_sounds = null
+
/turf/New()
..()
for(var/atom/movable/AM as mob|obj in src)
@@ -145,6 +147,9 @@ var/const/enterloopsanity = 100
else if(!is_space())
M.inertia_dir = 0
M.make_floating(0)
+ if(isliving(M))
+ var/mob/living/L = M
+ L.handle_footstep(src)
..()
var/objects = 0
if(A && (A.flags & PROXMOVE))
@@ -243,3 +248,11 @@ var/const/enterloopsanity = 100
/turf/proc/update_blood_overlays()
return
+// Called when turf is hit by a thrown object
+/turf/hitby(atom/movable/AM as mob|obj, var/speed)
+ if(src.density)
+ spawn(2)
+ step(AM, turn(AM.last_move, 180))
+ if(isliving(AM))
+ var/mob/living/M = AM
+ M.turf_collision(src, speed)
diff --git a/code/game/turfs/unsimulated/planetary.dm b/code/game/turfs/unsimulated/planetary.dm
index ce4ffa44c0f..7d9159d04a1 100644
--- a/code/game/turfs/unsimulated/planetary.dm
+++ b/code/game/turfs/unsimulated/planetary.dm
@@ -27,6 +27,15 @@ var/list/planetary_walls = list()
planetary_walls.Remove(src)
..()
+/turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature)
+ if(new_temperature == temperature)
+ return
+ temperature = new_temperature
+ // Force ZAS to reconsider our connections because our temperature has changed
+ if(connections)
+ connections.erase_all()
+ air_master.mark_for_update(src)
+
// Normal station/earth air.
/turf/unsimulated/wall/planetary/normal
oxygen = MOLES_O2STANDARD
@@ -55,3 +64,4 @@ var/list/planetary_walls = list()
oxygen = MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD
temperature = 310.92 // About 37.7C / 100F
+
diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm
index ec84ee42329..6e23d74bbb6 100644
--- a/code/game/verbs/suicide.dm
+++ b/code/game/verbs/suicide.dm
@@ -127,7 +127,7 @@
suiciding = 1
viewers(src) << "[src] is powering down. It looks like \he's trying to commit suicide."
//put em at -175
- adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
+ adjustOxyLoss(max(getMaxHealth() * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
updatehealth()
/mob/living/silicon/robot/verb/suicide()
@@ -147,7 +147,7 @@
suiciding = 1
viewers(src) << "[src] is powering down. It looks like \he's trying to commit suicide."
//put em at -175
- adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
+ adjustOxyLoss(max(getMaxHealth() * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
updatehealth()
/mob/living/silicon/pai/verb/suicide()
diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm
index affa55ce107..439e1f1b7f2 100644
--- a/code/modules/busy_space/organizations.dm
+++ b/code/modules/busy_space/organizations.dm
@@ -249,7 +249,11 @@
"Anything Legal Considered",
"New Toy",
"Me, I'm Always Counting",
- "Just Five More Minutes"
+ "Just Five More Minutes",
+ "Are You Feeling It",
+ "Great White Snark",
+ "No Shirt No Shoes",
+ "Callsign"
)
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index ffea7b7fab7..099aa439787 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -408,6 +408,7 @@
projectile_type = /obj/item/projectile/chameleon
charge_meter = 0
charge_cost = 48 //uses next to no power, since it's just holograms
+ battery_lock = 1
var/obj/item/projectile/copy_projectile
var/global/list/gun_choices
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 497b145190b..e3d781df297 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -347,7 +347,9 @@
body_parts_covered = FACE|EYES
sprite_sheets = list(
"Teshari" = 'icons/mob/species/seromi/masks.dmi',
- "Vox" = 'icons/mob/species/vox/masks.dmi'
+ "Vox" = 'icons/mob/species/vox/masks.dmi',
+ "Tajara" = 'icons/mob/species/tajaran/mask.dmi',
+ "Unathi" = 'icons/mob/species/unathi/mask.dmi'
)
var/voicechange = 0
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 137cab1a01d..4fb748f73ae 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -132,7 +132,7 @@ BLIND // can't see anything
eye = !eye
if(eye)
- icon_state = "[icon_state]_r"
+ icon_state = "[icon_state]_1"
else
icon_state = initial(icon_state)
update_clothing_icon()
@@ -395,14 +395,15 @@ BLIND // can't see anything
toggleable = 1
action_button_name = "Toggle Goggles"
vision_flags = SEE_MOBS
- see_invisible = INVISIBILITY_LEVEL_TWO
+ see_invisible = SEE_INVISIBLE_NOLIGHTING
+
emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/M = src.loc
M << "\red The Optical Thermal Scanner overloads and blinds you!"
if(M.glasses == src)
- M.eye_blind = 3
+ M.Blind(3)
M.eye_blurry = 5
// Don't cure being nearsighted
if(!(M.disabilities & NEARSIGHTED))
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index 978a5c13e60..5a311c51724 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -6,10 +6,6 @@
flags_inv = HIDEFACE|BLOCKHAIR
body_parts_covered = FACE|HEAD
w_class = ITEMSIZE_SMALL
- sprite_sheets = list(
- "Tajara" = 'icons/mob/species/tajaran/mask.dmi',
- "Unathi" = 'icons/mob/species/unathi/mask.dmi',
- )
/obj/item/clothing/mask/balaclava/tactical
name = "green balaclava"
@@ -18,10 +14,6 @@
item_state_slots = list(slot_r_hand_str = "bandgreen", slot_l_hand_str = "bandgreen")
flags_inv = HIDEFACE|BLOCKHAIR
w_class = ITEMSIZE_SMALL
- sprite_sheets = list(
- "Tajara" = 'icons/mob/species/tajaran/mask.dmi',
- "Unathi" = 'icons/mob/species/unathi/mask.dmi',
- )
/obj/item/clothing/mask/luchador
name = "Luchador Mask"
diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm
index ff0f8ae0776..e23c3c0c264 100644
--- a/code/modules/clothing/spacesuits/alien.dm
+++ b/code/modules/clothing/spacesuits/alien.dm
@@ -34,7 +34,7 @@
item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | PHORONGUARD
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank)
phoronproof = 1
- slowdown = 2
+ slowdown = 0.5
armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 100, rad = 50)
siemens_coefficient = 0.2
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index d08726371a9..f0903123205 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -80,6 +80,9 @@
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
reflectchance /= 2
diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm
index d9dc2f2e540..5d734c9d95a 100644
--- a/code/modules/clothing/under/accessories/holster.dm
+++ b/code/modules/clothing/under/accessories/holster.dm
@@ -76,10 +76,12 @@
/obj/item/clothing/accessory/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
..()
- has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
+ if(has_suit)
+ has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
/obj/item/clothing/accessory/holster/on_removed(mob/user as mob)
- has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
+ if(has_suit)
+ has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
..()
//For the holster hotkey
@@ -105,7 +107,7 @@
if(!H.holstered)
var/obj/item/W = usr.get_active_hand()
if(!istype(W, /obj/item))
- usr << "You need your gun equiped to holster it."
+ usr << "You need your gun equipped to holster it."
return
H.holster(W, usr)
else
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index e09c062ab01..d0f9a8165cb 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -41,9 +41,11 @@
i++
/datum/event/carp_migration/end()
- for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp)
- if(!C.stat)
- var/turf/T = get_turf(C)
- if(istype(T, /turf/space))
- if(!prob(25))
- qdel(C)
\ No newline at end of file
+ spawn(0)
+ for(var/mob/living/simple_animal/hostile/C in spawned_carp)
+ if(!C.stat)
+ var/turf/T = get_turf(C)
+ if(istype(T, /turf/space))
+ if(prob(75))
+ qdel(C)
+ sleep(1)
\ No newline at end of file
diff --git a/code/modules/genetics/side_effects.dm b/code/modules/genetics/side_effects.dm
index dcb5b4e4990..f3a9efb6d2b 100644
--- a/code/modules/genetics/side_effects.dm
+++ b/code/modules/genetics/side_effects.dm
@@ -72,7 +72,7 @@
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
- H.confused += 100
+ H.Confuse(100)
proc/trigger_side_effect(mob/living/carbon/human/H)
spawn
diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm
index eb18581551b..ff0b95f3653 100644
--- a/code/modules/holodeck/HolodeckControl.dm
+++ b/code/modules/holodeck/HolodeckControl.dm
@@ -18,23 +18,57 @@
var/mob/last_to_emag = null
var/last_change = 0
var/last_gravity_change = 0
- var/list/supported_programs = list( \
- "Empty Court" = "emptycourt", \
- "Basketball Court" = "basketball", \
- "Thunderdome Court" = "thunderdomecourt", \
- "Boxing Ring"="boxingcourt", \
- "Beach" = "beach", \
- "Desert" = "desert", \
- "Space" = "space", \
- "Picnic Area" = "picnicarea", \
- "Snow Field" = "snowfield", \
- "Theatre" = "theatre", \
- "Meeting Hall" = "meetinghall", \
- "Courtroom" = "courtroom", \
- "Turn Off" = "turnoff" \
+
+ var/area/projection_area = /area/holodeck/alphadeck
+ var/current_program
+ var/powerdown_program = "Turn Off"
+ var/default_program = "Empty Court"
+
+ var/list/supported_programs = list(
+ "Empty Court" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')),
+ "Boxing Ring" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')),
+ "Basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')),
+ "Thunderdome" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')),
+ "Beach" = new/datum/holodeck_program(/area/holodeck/source_beach),
+ "Desert" = new/datum/holodeck_program(/area/holodeck/source_desert,
+ list(
+ 'sound/effects/wind/wind_2_1.ogg',
+ 'sound/effects/wind/wind_2_2.ogg',
+ 'sound/effects/wind/wind_3_1.ogg',
+ 'sound/effects/wind/wind_4_1.ogg',
+ 'sound/effects/wind/wind_4_2.ogg',
+ 'sound/effects/wind/wind_5_1.ogg'
+ )
+ ),
+ "Snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield,
+ list(
+ 'sound/effects/wind/wind_2_1.ogg',
+ 'sound/effects/wind/wind_2_2.ogg',
+ 'sound/effects/wind/wind_3_1.ogg',
+ 'sound/effects/wind/wind_4_1.ogg',
+ 'sound/effects/wind/wind_4_2.ogg',
+ 'sound/effects/wind/wind_5_1.ogg'
+ )
+ ),
+ "Space" = new/datum/holodeck_program(/area/holodeck/source_space,
+ list(
+ 'sound/ambience/ambispace.ogg',
+ 'sound/music/main.ogg',
+ 'sound/music/space.ogg',
+ 'sound/music/traitor.ogg',
+ )
+ ),
+ "Picnic Area" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')),
+ "Theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre),
+ "Meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall),
+ "Courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')),
+ "Turn Off" = new/datum/holodeck_program(/area/holodeck/source_plating, list())
+ )
+
+ var/list/restricted_programs = list(
+ "Burnoff Test Simulation" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()),
+ "Wildlife Simulation" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list())
)
- var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp")
- var/current_program = "turnoff"
/obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
@@ -59,10 +93,10 @@
var/restricted_program_list[0]
for(var/P in supported_programs)
- program_list[++program_list.len] = list("name" = P, "program" = supported_programs[P])
+ program_list[++program_list.len] = P
for(var/P in restricted_programs)
- restricted_program_list[++restricted_program_list.len] = list("name" = P, "program" = restricted_programs[P])
+ restricted_program_list[++restricted_program_list.len] = P
data["supportedPrograms"] = program_list
data["restrictedPrograms"] = restricted_program_list
@@ -93,9 +127,9 @@
if(href_list["program"])
var/prog = href_list["program"]
- if(prog in holodeck_programs)
- loadProgram(holodeck_programs[prog])
- current_program = href_list["program"]
+ if(prog in (supported_programs + restricted_programs))
+ loadProgram(prog)
+ current_program = prog
else if(href_list["AIoverride"])
if(!issilicon(usr))
@@ -150,7 +184,10 @@
/obj/machinery/computer/HolodeckControl/New()
..()
- linkedholodeck = locate(/area/holodeck/alphadeck)
+ current_program = powerdown_program
+ linkedholodeck = locate(projection_area)
+ if(!linkedholodeck)
+ world << "Holodeck computer at [x],[y],[z] failed to locate projection area."
//This could all be done better, but it works for now.
/obj/machinery/computer/HolodeckControl/Destroy()
@@ -185,7 +222,7 @@
if(!checkInteg(linkedholodeck))
damaged = 1
- loadProgram(holodeck_programs["turnoff"], 0)
+ loadProgram(powerdown_program, 0)
active = 0
use_power = 1
for(var/mob/M in range(10,src))
@@ -227,9 +264,9 @@
//Why is it called toggle if it doesn't toggle?
/obj/machinery/computer/HolodeckControl/proc/togglePower(var/toggleOn = 0)
if(toggleOn)
- loadProgram(holodeck_programs["emptycourt"], 0)
+ loadProgram(default_program, 0)
else
- loadProgram(holodeck_programs["turnoff"], 0)
+ loadProgram(powerdown_program, 0)
if(!linkedholodeck.has_gravity)
linkedholodeck.gravitychange(1,linkedholodeck)
@@ -238,9 +275,18 @@
use_power = 1
-/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/datum/holodeck_program/HP, var/check_delay = 1)
+/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/prog, var/check_delay = 1)
+ if(!prog)
+ return
+
+ var/datum/holodeck_program/HP
+ if(prog in supported_programs)
+ HP = supported_programs[prog]
+ else if(prog in restricted_programs)
+ HP = restricted_programs[prog]
if(!HP)
return
+
var/area/A = locate(HP.target)
if(!A)
return
@@ -324,7 +370,7 @@
/obj/machinery/computer/HolodeckControl/proc/emergencyShutdown()
//Turn it back to the regular non-holographic room
- loadProgram(holodeck_programs["turnoff"], 0)
+ loadProgram(powerdown_program, 0)
if(!linkedholodeck.has_gravity)
linkedholodeck.gravitychange(1,linkedholodeck)
diff --git a/code/modules/holodeck/HolodeckPrograms.dm b/code/modules/holodeck/HolodeckPrograms.dm
index 9cb77f2a4bd..4ae4361a21c 100644
--- a/code/modules/holodeck/HolodeckPrograms.dm
+++ b/code/modules/holodeck/HolodeckPrograms.dm
@@ -1,46 +1,3 @@
-var/global/list/holodeck_programs = list(
- "emptycourt" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')),
- "boxingcourt" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')),
- "basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')),
- "thunderdomecourt" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')),
- "beach" = new/datum/holodeck_program(/area/holodeck/source_beach),
- "desert" = new/datum/holodeck_program(/area/holodeck/source_desert,
- list(
- 'sound/effects/wind/wind_2_1.ogg',
- 'sound/effects/wind/wind_2_2.ogg',
- 'sound/effects/wind/wind_3_1.ogg',
- 'sound/effects/wind/wind_4_1.ogg',
- 'sound/effects/wind/wind_4_2.ogg',
- 'sound/effects/wind/wind_5_1.ogg'
- )
- ),
- "snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield,
- list(
- 'sound/effects/wind/wind_2_1.ogg',
- 'sound/effects/wind/wind_2_2.ogg',
- 'sound/effects/wind/wind_3_1.ogg',
- 'sound/effects/wind/wind_4_1.ogg',
- 'sound/effects/wind/wind_4_2.ogg',
- 'sound/effects/wind/wind_5_1.ogg'
- )
- ),
- "space" = new/datum/holodeck_program(/area/holodeck/source_space,
- list(
- 'sound/ambience/ambispace.ogg',
- 'sound/music/main.ogg',
- 'sound/music/space.ogg',
- 'sound/music/traitor.ogg',
- )
- ),
- "picnicarea" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')),
- "theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre),
- "meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall),
- "courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')),
- "burntest" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()),
- "wildlifecarp" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()),
- "turnoff" = new/datum/holodeck_program(/area/holodeck/source_plating, list())
- )
-
/datum/holodeck_program
var/target
var/list/ambience = null
diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm
index c404f615812..7089c19d515 100644
--- a/code/modules/integrated_electronics/_defines.dm
+++ b/code/modules/integrated_electronics/_defines.dm
@@ -8,7 +8,7 @@
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD.
-#define IC_FORMAT_STRING "\"
+#define IC_FORMAT_STRING "\"
#define IC_FORMAT_NUMBER "\"
#define IC_FORMAT_REF "\["
#define IC_FORMAT_LIST "\]"
diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm
index 88b804f80a3..5c49e1817c7 100644
--- a/code/modules/integrated_electronics/core/assemblies.dm
+++ b/code/modules/integrated_electronics/core/assemblies.dm
@@ -107,6 +107,7 @@
for(var/obj/item/integrated_circuit/circuit in contents)
HTML += "[circuit.name] | "
HTML += "\[Rename\] | "
+ HTML += "\[Scan with Debugger\] | "
if(circuit.removable)
HTML += "\[Remove\]"
HTML += " "
@@ -223,9 +224,10 @@
if(proximity)
var/scanned = FALSE
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
- S.set_pin_data(IC_OUTPUT, 1, weakref(target))
- S.check_then_do_work()
- scanned = TRUE
+// S.set_pin_data(IC_OUTPUT, 1, weakref(target))
+// S.check_then_do_work()
+ if(S.scan(target))
+ scanned = TRUE
if(scanned)
visible_message("\The [user] waves \the [src] around [target].")
diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm
index 87bb4cd182f..1593297734d 100644
--- a/code/modules/integrated_electronics/core/integrated_circuit.dm
+++ b/code/modules/integrated_electronics/core/integrated_circuit.dm
@@ -6,6 +6,7 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/examine(mob/user)
. = ..()
external_examine(user)
+ interact(user)
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
@@ -86,16 +87,14 @@ a creative player the means to solve many problems. Circuits are held inside an
var/HTML = list()
HTML += "[src.name]"
HTML += ""
- HTML += " "
+ HTML += ""
HTML += " \[Refresh\] | "
HTML += "\[Rename\] | "
+ HTML += "\[Scan with Debugger\] | "
HTML += "\[Remove\] "
HTML += ""
- //HTML += ""
- //HTML += ""
- //HTML += ""
HTML += ""
HTML += ""
HTML += ""
@@ -212,6 +211,16 @@ a creative player the means to solve many problems. Circuits are held inside an
if(href_list["rename"])
rename_component(usr)
+ if(href_list["scan"])
+ if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
+ var/obj/item/device/integrated_electronics/debugger/D = held_item
+ if(D.accepting_refs)
+ D.afterattack(src, usr, TRUE)
+ else
+ to_chat(usr, "The Debugger's 'ref scanner' needs to be on.")
+ else
+ to_chat(usr, "You need a Debugger set to 'ref' mode to do that.")
+
if(href_list["autopulse"])
if(autopulse != -1)
autopulse = !autopulse
@@ -260,10 +269,10 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE // Battery has enough.
return FALSE // Not enough power.
-/obj/item/integrated_circuit/proc/check_then_do_work()
+/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
- if(power_draw_per_use)
+ if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm
index 8220162be72..a8759174411 100644
--- a/code/modules/integrated_electronics/core/tools.dm
+++ b/code/modules/integrated_electronics/core/tools.dm
@@ -160,7 +160,7 @@
data_to_show = A.name
to_chat(user, "You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].")
else if(io.io_type == PULSE_CHANNEL)
- io.holder.check_then_do_work()
+ io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "You pulse \the [io.holder]'s [io].")
io.holder.interact(user) // This is to update the UI.
diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm
index c6134f9bd1d..059c699e502 100644
--- a/code/modules/integrated_electronics/subtypes/arithmetic.dm
+++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm
@@ -1,9 +1,18 @@
//These circuits do simple math.
/obj/item/integrated_circuit/arithmetic
complexity = 1
- inputs = list("A","B","C","D","E","F","G","H")
- outputs = list("result")
- activators = list("compute")
+ inputs = list(
+ "\ A",
+ "\ B",
+ "\ C",
+ "\ D",
+ "\ E",
+ "\ F",
+ "\ G",
+ "\ H"
+ )
+ outputs = list("\ result")
+ activators = list("\ compute", "\ on computed")
category_text = "Arithmetic"
autopulse = 1
power_draw_per_use = 5 // Math is pretty cheap.
@@ -30,9 +39,9 @@
if(isnum(I.data))
result = result + I.data
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// -Subtracting- //
@@ -58,9 +67,9 @@
if(isnum(I.data))
result = result - I.data
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// *Multiply* //
@@ -86,9 +95,9 @@
if(isnum(I.data))
result = result * I.data
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// /Division/ //
@@ -114,9 +123,9 @@
if(isnum(I.data) && I.data != 0) //No runtimes here.
result = result / I.data
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
//^ Exponent ^//
@@ -134,9 +143,9 @@
if(isnum(A.data) && isnum(B.data))
result = A.data ** B.data
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// +-Sign-+ //
@@ -159,9 +168,9 @@
else
result = 0
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Round //
@@ -183,9 +192,9 @@
else
result = round(A.data)
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Absolute //
@@ -204,9 +213,9 @@
if(isnum(I.data))
result = abs(I.data)
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Averaging //
@@ -229,9 +238,9 @@
if(inputs_used)
result = result / inputs_used
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Pi, because why the hell not? //
/obj/item/integrated_circuit/arithmetic/pi
@@ -242,9 +251,9 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/pi/do_work()
- var/datum/integrated_io/output/O = outputs[1]
- O.data = 3.14159
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, 3.14159)
+ push_data()
+ activate_pin(2)
// Random //
/obj/item/integrated_circuit/arithmetic/random
@@ -253,20 +262,20 @@
extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \
for outputs of 1, 2, or 3. H being the higher number is not strictly required."
icon_state = "random"
- inputs = list("L","H")
+ inputs = list("\ L","\ H")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/random/do_work()
var/result = 0
- var/datum/integrated_io/L = inputs[1]
- var/datum/integrated_io/H = inputs[2]
+ var/L = get_pin_data(IC_INPUT, 1)
+ var/H = get_pin_data(IC_INPUT, 2)
- if(isnum(L.data) && isnum(H.data))
- result = rand(L.data, H.data)
+ if(isnum(L) && isnum(H))
+ result = rand(L, H)
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Square Root //
@@ -274,7 +283,7 @@
name = "square root circuit"
desc = "This outputs the square root of a number you put in."
icon_state = "square_root"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
@@ -284,9 +293,9 @@
if(isnum(I.data))
result = sqrt(I.data)
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// % Modulo % //
@@ -294,17 +303,17 @@
name = "modulo circuit"
desc = "Gets the remainder of A / B."
icon_state = "modulo"
- inputs = list("A", "B")
+ inputs = list("\ A", "\ B")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/modulo/do_work()
var/result = 0
- var/datum/integrated_io/input/A = inputs[1]
- var/datum/integrated_io/input/B = inputs[2]
- if(isnum(A.data) && isnum(B.data) && B.data != 0)
- result = A.data % B.data
+ var/A = get_pin_data(IC_INPUT, 1)
+ var/B = get_pin_data(IC_INPUT, 2)
+ if(isnum(A) && isnum(B) && B != 0)
+ result = A % B
- for(var/datum/integrated_io/output/O in outputs)
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm
index 9e04e24db51..431faa241f9 100644
--- a/code/modules/integrated_electronics/subtypes/converters.dm
+++ b/code/modules/integrated_electronics/subtypes/converters.dm
@@ -3,7 +3,7 @@
complexity = 2
inputs = list("input")
outputs = list("output")
- activators = list("convert")
+ activators = list("\ convert", "\ on convert")
category_text = "Converter"
autopulse = 1
power_draw_per_use = 10
@@ -16,89 +16,113 @@
name = "number to string"
desc = "This circuit can convert a number variable into a string."
icon_state = "num-string"
+ inputs = list("\ input")
+ outputs = list("\ output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/num2text/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- if(incoming.data && isnum(incoming.data))
- result = num2text(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && isnum(incoming))
+ result = num2text(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/text2num
name = "string to number"
desc = "This circuit can convert a string variable into a number."
icon_state = "string-num"
+ inputs = list("\ input")
+ outputs = list("\ output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/text2num/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- if(incoming.data && istext(incoming.data))
- result = text2num(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && istext(incoming))
+ result = text2num(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/ref2text
name = "reference to string"
desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference."
icon_state = "ref-string"
+ inputs = list("\[ input")
+ outputs = list("\ output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/ref2text/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- var/atom/A = incoming.data_as_type(/atom)
- result = A && A.name
+ pull_data()
+ var/atom/A = get_pin_data(IC_INPUT, 1)
+ if(A && istype(A))
+ result = A.name
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/lowercase
name = "lowercase string converter"
desc = "this will cause a string to come out in all lowercase."
icon_state = "lowercase"
+ inputs = list("\ input")
+ outputs = list("\ output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/lowercase/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- if(incoming.data && istext(incoming.data))
- result = lowertext(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && istext(incoming))
+ result = lowertext(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/uppercase
name = "uppercase string converter"
desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
icon_state = "uppercase"
+ inputs = list("\ input")
+ outputs = list("\ output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/uppercase/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- if(incoming.data && istext(incoming.data))
- result = uppertext(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && istext(incoming))
+ result = uppertext(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/concatenatior
name = "concatenatior"
- desc = "This joins many strings together to get one big string."
+ desc = "This joins many strings or numbers together to get one big string."
complexity = 4
- inputs = list("A","B","C","D","E","F","G","H")
- outputs = list("result")
- activators = list("concatenate")
+ inputs = list(
+ "\ A",
+ "\ B",
+ "\ C",
+ "\ D",
+ "\ E",
+ "\ F",
+ "\ G",
+ "\ H"
+ )
+ outputs = list("\ result")
+ activators = list("\ concatenate", "\ on concatenated")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/concatenatior/do_work()
@@ -107,70 +131,70 @@
I.pull_data()
if(istext(I.data))
result = result + I.data
+ else if(!isnull(I.data) && num2text(I.data))
+ result = result + num2text(I.data)
var/datum/integrated_io/outgoing = outputs[1]
outgoing.data = result
outgoing.push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/radians2degrees
name = "radians to degrees converter"
desc = "Converts radians to degrees."
- inputs = list("radian")
- outputs = list("degrees")
+ inputs = list("\ radian")
+ outputs = list("\ degrees")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/radians2degrees/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- incoming.pull_data()
- if(incoming.data && isnum(incoming.data))
- result = ToDegrees(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && isnum(incoming))
+ result = ToDegrees(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/degrees2radians
name = "degrees to radians converter"
desc = "Converts degrees to radians."
- inputs = list("degrees")
- outputs = list("radians")
+ inputs = list("\ degrees")
+ outputs = list("\ radians")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/degrees2radians/do_work()
var/result = null
- var/datum/integrated_io/incoming = inputs[1]
- var/datum/integrated_io/outgoing = outputs[1]
- incoming.pull_data()
- if(incoming.data && isnum(incoming.data))
- result = ToRadians(incoming.data)
+ pull_data()
+ var/incoming = get_pin_data(IC_INPUT, 1)
+ if(incoming && isnum(incoming))
+ result = ToRadians(incoming)
- outgoing.data = result
- outgoing.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/converter/abs_to_rel_coords
name = "abs to rel coordinate converter"
desc = "Easily convert absolute coordinates to relative coordinates with this."
complexity = 4
- inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)")
- outputs = list("X (rel)", "Y (rel)")
- activators = list("compute rel coordinates")
+ inputs = list("\ X1", "\ Y1", "\ X2", "\ Y2")
+ outputs = list("\ X", "\ Y")
+ activators = list("\ compute rel coordinates", "\ on convert")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
- var/datum/integrated_io/x1 = inputs[1]
- var/datum/integrated_io/y1 = inputs[2]
+ var/x1 = get_pin_data(IC_INPUT, 1)
+ var/y1 = get_pin_data(IC_INPUT, 2)
- var/datum/integrated_io/x2 = inputs[3]
- var/datum/integrated_io/y2 = inputs[4]
+ var/x2 = get_pin_data(IC_INPUT, 3)
+ var/y2 = get_pin_data(IC_INPUT, 4)
- var/datum/integrated_io/result_x = outputs[1]
- var/datum/integrated_io/result_y = outputs[2]
+ if(x1 && y1 && x2 && y2)
+ set_pin_data(IC_OUTPUT, 1, x1 - x2)
+ set_pin_data(IC_OUTPUT, 2, y1 - y2)
- if(x1.data && y1.data && x2.data && y2.data)
- result_x.data = x1.data - x2.data
- result_y.data = y1.data - y2.data
-
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
\ No newline at end of file
+ push_data()
+ activate_pin(2)
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/subtypes/input_output.dm b/code/modules/integrated_electronics/subtypes/input_output.dm
index baa5738d4ea..456fae889f2 100644
--- a/code/modules/integrated_electronics/subtypes/input_output.dm
+++ b/code/modules/integrated_electronics/subtypes/input_output.dm
@@ -14,28 +14,27 @@
can_be_asked_input = 1
inputs = list()
outputs = list()
- activators = list("on pressed")
+ activators = list("\ on pressed")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
- var/datum/integrated_io/A = activators[1]
- if(A.linked.len)
- for(var/datum/integrated_io/activate/target in A.linked)
- target.holder.check_then_do_work()
to_chat(user, "You press the button labeled '[src.name]'.")
+ activate_pin(1)
/obj/item/integrated_circuit/input/toggle_button
name = "toggle button"
desc = "It toggles on, off, on, off..."
icon_state = "toggle_button"
complexity = 1
+ can_be_asked_input = 1
inputs = list()
- outputs = list("on" = 0)
- activators = list("on toggle")
+ outputs = list("\ on" = 0)
+ activators = list("\ on toggle")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto.
set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1))
+ push_data()
activate_pin(1)
to_chat(user, "You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].")
@@ -46,19 +45,17 @@
complexity = 2
can_be_asked_input = 1
inputs = list()
- outputs = list("number entered")
- activators = list("on entered")
+ outputs = list("\ number entered")
+ activators = list("\ on entered")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter a number, please.","Number pad") as null|num
if(isnum(new_input) && CanInteract(user, physical_state))
- var/datum/integrated_io/O = outputs[1]
- O.data = new_input
- O.push_data()
- var/datum/integrated_io/A = activators[1]
- A.push_data()
+ set_pin_data(IC_OUTPUT, 1, new_input)
+ push_data()
+ activate_pin(1)
/obj/item/integrated_circuit/input/textpad
name = "text pad"
@@ -67,49 +64,43 @@
complexity = 2
can_be_asked_input = 1
inputs = list()
- outputs = list("string entered")
- activators = list("on entered")
+ outputs = list("\ string entered")
+ activators = list("\ on entered")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter some words, please.","Number pad") as null|text
if(istext(new_input) && CanInteract(user, physical_state))
- var/datum/integrated_io/O = outputs[1]
- O.data = new_input
- O.push_data()
- var/datum/integrated_io/A = activators[1]
- A.push_data()
+ set_pin_data(IC_OUTPUT, 1, new_input)
+ push_data()
+ activate_pin(1)
/obj/item/integrated_circuit/input/med_scanner
name = "integrated medical analyser"
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is."
icon_state = "medscan"
complexity = 4
- inputs = list("target ref")
- outputs = list("total health %", "total missing health")
- activators = list("scan")
+ inputs = list("\][ target")
+ outputs = list("\ total health %", "\ total missing health")
+ activators = list("\ scan", "\ on scanned")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
power_draw_per_use = 40
/obj/item/integrated_circuit/input/med_scanner/do_work()
- var/datum/integrated_io/I = inputs[1]
- var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human)
+ var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
- var/total_health = round(H.health/H.maxHealth, 0.1)*100
- var/missing_health = H.maxHealth - H.health
+ var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100
+ var/missing_health = H.getMaxHealth() - H.health
- var/datum/integrated_io/total = outputs[1]
- var/datum/integrated_io/missing = outputs[2]
+ set_pin_data(IC_OUTPUT, 1, total_health)
+ set_pin_data(IC_OUTPUT, 2, missing_health)
- total.data = total_health
- missing.data = missing_health
-
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/input/adv_med_scanner
name = "integrated advanced medical analyser"
@@ -117,48 +108,39 @@
This type is much more precise, allowing the machine to know much more about the target than a normal analyzer."
icon_state = "medscan_adv"
complexity = 12
- inputs = list("target ref")
+ inputs = list("\][ target")
outputs = list(
- "total health %",
- "total missing health",
- "brute damage",
- "burn damage",
- "tox damage",
- "oxy damage",
- "clone damage"
+ "\ total health %",
+ "\ total missing health",
+ "\ brute damage",
+ "\ burn damage",
+ "\ tox damage",
+ "\ oxy damage",
+ "\ clone damage"
)
- activators = list("scan")
+ activators = list("\ scan", "\ on scanned")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 80
/obj/item/integrated_circuit/input/adv_med_scanner/do_work()
- var/datum/integrated_io/I = inputs[1]
- var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human)
+ var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
- var/total_health = round(H.health/H.maxHealth, 0.1)*100
- var/missing_health = H.maxHealth - H.health
+ var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100
+ var/missing_health = H.getMaxHealth() - H.health
- var/datum/integrated_io/total = outputs[1]
- var/datum/integrated_io/missing = outputs[2]
- var/datum/integrated_io/brute = outputs[3]
- var/datum/integrated_io/burn = outputs[4]
- var/datum/integrated_io/tox = outputs[5]
- var/datum/integrated_io/oxy = outputs[6]
- var/datum/integrated_io/clone = outputs[7]
+ set_pin_data(IC_OUTPUT, 1, total_health)
+ set_pin_data(IC_OUTPUT, 2, missing_health)
+ set_pin_data(IC_OUTPUT, 3, H.getBruteLoss())
+ set_pin_data(IC_OUTPUT, 4, H.getFireLoss())
+ set_pin_data(IC_OUTPUT, 5, H.getToxLoss())
+ set_pin_data(IC_OUTPUT, 6, H.getOxyLoss())
+ set_pin_data(IC_OUTPUT, 7, H.getCloneLoss())
- total.data = total_health
- missing.data = missing_health
- brute.data = H.getBruteLoss()
- burn.data = H.getFireLoss()
- tox.data = H.getToxLoss()
- oxy.data = H.getOxyLoss()
- clone.data = H.getCloneLoss()
-
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/input/local_locator
name = "local locator"
@@ -222,9 +204,9 @@
Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin."
icon_state = "signal"
complexity = 4
- inputs = list("frequency","code")
+ inputs = list("\ frequency","\ code")
outputs = list()
- activators = list("send signal","on signal received")
+ activators = list("\ send signal","\ on signal sent", "\ on signal received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
power_draw_idle = 5
@@ -237,11 +219,9 @@
/obj/item/integrated_circuit/input/signaler/initialize()
..()
set_frequency(frequency)
- var/datum/integrated_io/new_freq = inputs[1]
- var/datum/integrated_io/new_code = inputs[2]
// Set the pins so when someone sees them, they won't show as null
- new_freq.data = frequency
- new_code.data = code
+ set_pin_data(IC_INPUT, 1, frequency)
+ set_pin_data(IC_INPUT, 2, code)
/obj/item/integrated_circuit/input/signaler/Destroy()
if(radio_controller)
@@ -250,12 +230,12 @@
. = ..()
/obj/item/integrated_circuit/input/signaler/on_data_written()
- var/datum/integrated_io/new_freq = inputs[1]
- var/datum/integrated_io/new_code = inputs[2]
- if(isnum(new_freq.data) && new_freq.data > 0)
- set_frequency(new_freq.data)
- if(isnum(new_code.data))
- code = new_code.data
+ var/new_freq = get_pin_data(IC_INPUT, 1)
+ var/new_code = get_pin_data(IC_INPUT, 2)
+ if(isnum(new_freq) && new_freq > 0)
+ set_frequency(new_freq)
+ if(isnum(new_code))
+ code = new_code
/obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal.
@@ -267,6 +247,7 @@
signal.encryption = code
signal.data["message"] = "ACTIVATE"
radio_connection.post_signal(src, signal)
+ activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
@@ -280,11 +261,11 @@
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
- var/datum/integrated_io/new_code = inputs[2]
+ var/new_code = get_pin_data(IC_INPUT, 2)
var/code = 0
- if(isnum(new_code.data))
- code = new_code.data
+ if(isnum(new_code))
+ code = new_code
if(!signal)
return 0
if(signal.encryption != code)
@@ -292,8 +273,7 @@
if(signal.source == src) // Don't trigger ourselves.
return 0
- var/datum/integrated_io/A = activators[2]
- A.push_data()
+ activate_pin(3)
for(var/mob/O in hearers(1, get_turf(src)))
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
@@ -306,9 +286,9 @@
will pulse whatever's connected to it. Pulsing the first activation pin will send a message."
icon_state = "signal"
complexity = 4
- inputs = list("target EPv2 address", "data to send", "secondary text")
- outputs = list("address received", "data received", "secondary text received")
- activators = list("send data", "on data received")
+ inputs = list("\ target EPv2 address", "\ data to send", "\ secondary text")
+ outputs = list("\ address received", "\ data received", "\ secondary text received")
+ activators = list("\ send data", "\ on data received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2)
power_draw_per_use = 50
@@ -318,7 +298,7 @@
..()
exonet = new(src)
exonet.make_address("EPv2_circuit-\ref[src]")
- desc += "] This circuit's EPv2 address is: [exonet.address]."
+ desc += " This circuit's EPv2 address is: [exonet.address]"
/obj/item/integrated_circuit/input/EPv2/Destroy()
if(exonet)
@@ -327,64 +307,60 @@
..()
/obj/item/integrated_circuit/input/EPv2/do_work()
- var/datum/integrated_io/target_address = inputs[1]
- var/datum/integrated_io/message = inputs[2]
- var/datum/integrated_io/text = inputs[3]
- if(istext(target_address.data))
- exonet.send_message(target_address.data, message.data, text.data)
+ var/target_address = get_pin_data(IC_INPUT, 1)
+ var/message = get_pin_data(IC_INPUT, 2)
+ var/text = get_pin_data(IC_INPUT, 3)
+
+ if(target_address && istext(target_address))
+ exonet.send_message(target_address, message, text)
/obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
- var/datum/integrated_io/message_received = outputs[1]
- var/datum/integrated_io/data_received = outputs[2]
- var/datum/integrated_io/text_received = outputs[3]
+ set_pin_data(IC_OUTPUT, 1, origin_address)
+ set_pin_data(IC_OUTPUT, 2, message)
+ set_pin_data(IC_OUTPUT, 3, text)
- var/datum/integrated_io/A = activators[2]
- A.push_data()
-
- message_received.write_data_to_pin(origin_address)
- data_received.write_data_to_pin(message)
- text_received.write_data_to_pin(text)
-
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
+ push_data()
+ activate_pin(2)
//This circuit gives information on where the machine is.
/obj/item/integrated_circuit/input/gps
name = "global positioning system"
desc = "This allows you to easily know the position of a machine containing this device."
+ extended_desc = "The GPS's coordinates it gives is absolute, not relative."
icon_state = "gps"
complexity = 4
inputs = list()
- outputs = list("X (abs)", "Y (abs)")
- activators = list("get coordinates")
+ outputs = list("\ X", "\ Y")
+ activators = list("\ get coordinates", "\ on get coordinates")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/gps/do_work()
var/turf/T = get_turf(src)
- var/datum/integrated_io/result_x = outputs[1]
- var/datum/integrated_io/result_y = outputs[2]
- result_x.data = null
- result_y.data = null
+ set_pin_data(IC_OUTPUT, 1, null)
+ set_pin_data(IC_OUTPUT, 2, null)
if(!T)
return
- result_x.data = T.x
- result_y.data = T.y
+ set_pin_data(IC_OUTPUT, 1, T.x)
+ set_pin_data(IC_OUTPUT, 2, T.y)
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
+ push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/input/microphone
name = "microphone"
desc = "Useful for spying on people or for voice activated machines."
+ extended_desc = "This will automatically translate most languages it hears to Galactic Common. \
+ The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
+ is only triggered if it hears someone speaking a language other than Galactic Common."
icon_state = "recorder"
complexity = 8
inputs = list()
- outputs = list("speaker \", "message \")
- activators = list("on message received")
+ outputs = list("\ speaker", "\ message")
+ activators = list("\ on message received", "\ on translation")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
@@ -397,42 +373,45 @@
..()
/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
- var/datum/integrated_io/V = outputs[1]
- var/datum/integrated_io/O = outputs[2]
- var/datum/integrated_io/A = activators[1]
+ var/translated = FALSE
if(M && msg)
if(speaking)
if(!speaking.machine_understands)
msg = speaking.scramble(msg)
- V.data = M.GetVoice()
- O.data = msg
- A.push_data()
+ if(!istype(speaking, /datum/language/common))
+ translated = TRUE
+ set_pin_data(IC_OUTPUT, 1, M.GetVoice())
+ set_pin_data(IC_OUTPUT, 2, msg)
- for(var/datum/integrated_io/output/out in outputs)
- out.push_data()
-
- A.push_data()
+ push_data()
+ activate_pin(1)
+ if(translated)
+ activate_pin(2)
/obj/item/integrated_circuit/input/sensor
name = "sensor"
desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face."
+ extended_desc = "If 'ignore storage' pin is set to 1, the sensor will disregard scanning various storage containers such as backpacks."
icon_state = "recorder"
complexity = 12
- inputs = list()
- outputs = list("scanned ref \[")
- activators = list("on scanned")
+ inputs = list("\ ignore storage" = 1)
+ outputs = list("\][ scanned")
+ activators = list("\ on scanned")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
-/obj/item/integrated_circuit/input/sensor/do_work()
- // Because this gets called by attack(), all this needs to do is pulse the activator.
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
- var/datum/integrated_io/activate/A = activators[1]
- A.push_data()
+/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
+ var/ignore_bags = get_pin_data(IC_INPUT, 1)
+ if(ignore_bags)
+ if(istype(A, /obj/item/weapon/storage))
+ return FALSE
+ set_pin_data(IC_OUTPUT, 1, weakref(A))
+ push_data()
+ activate_pin(1)
+ return TRUE
/obj/item/integrated_circuit/output
category_text = "Output"
@@ -441,9 +420,9 @@
name = "small screen"
desc = "This small screen can display a single piece of data, when the machine is examined closely."
icon_state = "screen"
- inputs = list("displayed data")
+ inputs = list("\ displayed data")
outputs = list()
- activators = list("load data")
+ activators = list("\ load data")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 10
autopulse = 1
@@ -497,7 +476,7 @@
complexity = 4
inputs = list()
outputs = list()
- activators = list("toggle light")
+ activators = list("\ toggle light")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/light_toggled = 0
var/light_brightness = 3
@@ -519,18 +498,18 @@
power_draw_idle = light_toggled ? light_brightness * 2 : 0
/obj/item/integrated_circuit/output/light/advanced/update_lighting()
- var/datum/integrated_io/R = inputs[1]
- var/datum/integrated_io/G = inputs[2]
- var/datum/integrated_io/B = inputs[3]
- var/datum/integrated_io/brightness = inputs[4]
+ var/R = get_pin_data(IC_INPUT, 1)
+ var/G = get_pin_data(IC_INPUT, 2)
+ var/B = get_pin_data(IC_INPUT, 3)
+ var/brightness = get_pin_data(IC_INPUT, 4)
- if(isnum(R.data) && isnum(G.data) && isnum(B.data) && isnum(brightness.data))
- R.data = Clamp(R.data, 0, 255)
- G.data = Clamp(G.data, 0, 255)
- B.data = Clamp(B.data, 0, 255)
- brightness.data = Clamp(brightness.data, 0, 6)
- light_rgb = rgb(R.data, G.data, B.data)
- light_brightness = brightness.data
+ if(isnum(R) && isnum(G) && isnum(B) && isnum(brightness))
+ R = Clamp(R, 0, 255)
+ G = Clamp(G, 0, 255)
+ B = Clamp(B, 0, 255)
+ brightness = Clamp(brightness, 0, 6)
+ light_rgb = rgb(R, G, B)
+ light_brightness = brightness
..()
@@ -544,10 +523,10 @@
icon_state = "light_adv"
complexity = 8
inputs = list(
- "R",
- "G",
- "B",
- "Brightness"
+ "\ R",
+ "\ G",
+ "\ B",
+ "\ Brightness"
)
outputs = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
@@ -563,9 +542,9 @@
complexity = 8
cooldown_per_use = 4 SECONDS
inputs = list(
- "sound ID",
- "volume",
- "frequency"
+ "\ sound ID",
+ "\ volume",
+ "\ frequency"
)
outputs = list()
activators = list("play sound")
diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm
index beb44bf5354..759b1586eb4 100644
--- a/code/modules/integrated_electronics/subtypes/logic.dm
+++ b/code/modules/integrated_electronics/subtypes/logic.dm
@@ -4,7 +4,7 @@
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
complexity = 3
outputs = list("result")
- activators = list("compare", "on true result", "on false result")
+ activators = list("\ compare", "\ on true result", "\ on false result")
category_text = "Logic"
autopulse = 1
power_draw_per_use = 1
@@ -14,19 +14,17 @@
check_then_do_work()
/obj/item/integrated_circuit/logic/do_work()
- var/datum/integrated_io/O = outputs[1]
- var/datum/integrated_io/T = activators[2]
- var/datum/integrated_io/F = activators[3]
- O.push_data()
- if(O.data)
- T.push_data()
+ push_data()
+ if(get_pin_data(IC_INPUT, 1))
+ activate_pin(1)
else
- F.push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/logic/binary
- inputs = list("A","B")
+ inputs = list("\ A","\ B")
/obj/item/integrated_circuit/logic/binary/do_work()
+ pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
@@ -37,9 +35,10 @@
return FALSE
/obj/item/integrated_circuit/logic/unary
- inputs = list("A")
+ inputs = list("\ A")
/obj/item/integrated_circuit/logic/unary/do_work()
+ pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = do_check(A) ? TRUE : FALSE
diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm
index 65bae751e00..4ee51451790 100644
--- a/code/modules/integrated_electronics/subtypes/manipulation.dm
+++ b/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -11,12 +11,12 @@
complexity = 20
w_class = ITEMSIZE_NORMAL
inputs = list(
- "target X rel",
- "target Y rel"
+ "\ target X rel",
+ "\ target Y rel"
)
outputs = list()
activators = list(
- "fire"
+ "\ fire"
)
var/obj/item/weapon/gun/installed_gun = null
spawn_flags = IC_SPAWN_RESEARCH
diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm
index 7b3256e06b9..3480a83a4a4 100644
--- a/code/modules/integrated_electronics/subtypes/power.dm
+++ b/code/modules/integrated_electronics/subtypes/power.dm
@@ -11,9 +11,9 @@
some power is lost due to ineffiency."
w_class = ITEMSIZE_SMALL
complexity = 16
- inputs = list("target ref")
- outputs = list("target cell charge", "target cell max charge", "target cell percentage")
- activators = list("transmit")
+ inputs = list("\][ target")
+ outputs = list("\ target cell charge", "\ target cell max charge", "\ target cell percentage")
+ activators = list("\ transmit")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 500 // Inefficency has to come from somewhere.
diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm
index d0c26baf663..e3b69d31cd4 100644
--- a/code/modules/integrated_electronics/subtypes/reagents.dm
+++ b/code/modules/integrated_electronics/subtypes/reagents.dm
@@ -43,39 +43,39 @@
flags = OPENCONTAINER
complexity = 20
cooldown_per_use = 6 SECONDS
- inputs = list("target ref", "injection amount" = 5)
+ inputs = list("\][ target", "\ injection amount" = 5)
outputs = list()
- activators = list("inject")
+ activators = list("\ inject")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
volume = 30
power_draw_per_use = 15
/obj/item/integrated_circuit/reagent/injector/proc/inject_amount()
- var/datum/integrated_io/amount = inputs[2]
- if(isnum(amount.data))
- return Clamp(amount.data, 0, 30)
+ var/amount = get_pin_data(IC_INPUT, 2)
+ if(isnum(amount))
+ return Clamp(amount, 0, 30)
/obj/item/integrated_circuit/reagent/injector/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
- var/datum/integrated_io/target = inputs[1]
- var/atom/movable/AM = target.data_as_type(/atom/movable)
+ var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!istype(AM)) //Invalid input
return
if(!reagents.total_volume) // Empty
return
if(AM.can_be_injected_by(src))
if(isliving(AM))
+ var/mob/living/L = AM
var/turf/T = get_turf(AM)
- T.visible_message("[src] is trying to inject [AM]!")
+ T.visible_message("[src] is trying to inject [L]!")
sleep(3 SECONDS)
- if(!AM.can_be_injected_by(src))
+ if(!L.can_be_injected_by(src))
return
var/contained = reagents.get_reagents()
- var/trans = reagents.trans_to_mob(target, inject_amount(), CHEM_BLOOD)
- message_admins("[src] injected \the [AM] with [trans]u of [contained].")
+ var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD)
+ message_admins("[src] injected \the [L] with [trans]u of [contained].")
to_chat(AM, "You feel a tiny prick!")
- visible_message("[src] injects [AM]!")
+ visible_message("[src] injects [L]!")
else
reagents.trans_to(AM, inject_amount())
@@ -88,9 +88,9 @@
outside the machine if it is next to the machine. Note that this cannot be used on entities."
flags = OPENCONTAINER
complexity = 8
- inputs = list("source ref", "target ref", "injection amount" = 10)
+ inputs = list("\][ source", "\][ target", "\ injection amount" = 10)
outputs = list()
- activators = list("transfer reagents")
+ activators = list("\ transfer reagents", "\ on transfer")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
@@ -103,10 +103,9 @@
transfer_amount = amount.data
/obj/item/integrated_circuit/reagent/pump/do_work()
- var/datum/integrated_io/A = inputs[1]
- var/datum/integrated_io/B = inputs[2]
- var/atom/movable/source = A.data_as_type(/atom/movable)
- var/atom/movable/target = B.data_as_type(/atom/movable)
+ var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
+ var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
+
if(!istype(source) || !istype(target)) //Invalid input
return
var/turf/T = get_turf(src)
@@ -117,10 +116,11 @@
return
if(!source.is_open_container() || !target.is_open_container())
return
- if(!source.reagents.get_free_space() || !target.reagents.get_free_space())
+ if(!target.reagents.get_free_space())
return
source.reagents.trans_to(target, transfer_amount)
+ activate_pin(2)
/obj/item/integrated_circuit/reagent/storage
name = "reagent storage"
diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm
index c159522e974..a90a3f57a36 100644
--- a/code/modules/integrated_electronics/subtypes/smart.dm
+++ b/code/modules/integrated_electronics/subtypes/smart.dm
@@ -8,17 +8,16 @@
cannot see the target, it will not be able to calculate the correct direction."
icon_state = "numberpad"
complexity = 25
- inputs = list("target ref")
- outputs = list("dir")
- activators = list("calculate dir")
+ inputs = list("\][ target")
+ outputs = list("\ dir")
+ activators = list("\ calculate dir", "\ on calculated")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
power_draw_per_use = 40
/obj/item/integrated_circuit/smart/basic_pathfinder/do_work()
var/datum/integrated_io/I = inputs[1]
- var/datum/integrated_io/O = outputs[1]
- O.data = null
+ set_pin_data(IC_OUTPUT, 1, null)
if(!isweakref(I.data))
return
@@ -28,6 +27,6 @@
if(!(A in view(get_turf(src))))
return // Can't see the target.
var/desired_dir = get_dir(get_turf(src), A)
- if(desired_dir)
- O.data = desired_dir
- O.push_data()
\ No newline at end of file
+
+ set_pin_data(IC_OUTPUT, 1, desired_dir)
+ push_data()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm
index 72766c0c48c..322ee2f9e09 100644
--- a/code/modules/integrated_electronics/subtypes/time.dm
+++ b/code/modules/integrated_electronics/subtypes/time.dm
@@ -12,16 +12,15 @@
This circuit is set to send a pulse after a delay of two seconds."
icon_state = "delay-20"
var/delay = 2 SECONDS
- activators = list("incoming pulse","outgoing pulse")
+ activators = list("\ incoming","\ outgoing")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/delay/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor. It'll delay the entire thing
- var/datum/integrated_io/out_pulse = activators[2]
sleep(delay)
- out_pulse.push_data()
+ activate_pin(2)
/obj/item/integrated_circuit/time/delay/five_sec
name = "five-sec delay circuit"
@@ -60,14 +59,13 @@
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse."
icon_state = "delay"
- inputs = list("delay time")
+ inputs = list("\ delay time")
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom/do_work()
- var/datum/integrated_io/delay_input = inputs[1]
- if(delay_input.data && isnum(delay_input.data) )
- var/new_delay = min(delay_input.data, 1)
- new_delay = max(new_delay, 36000) //An hour.
+ var/delay_input = get_pin_data(IC_INPUT, 1)
+ if(delay_input && isnum(delay_input) )
+ var/new_delay = between(1, delay_input, 36000) //An hour.
delay = new_delay
..()
@@ -80,8 +78,8 @@
var/ticks_to_pulse = 4
var/ticks_completed = 0
var/is_running = FALSE
- inputs = list("enable ticking")
- activators = list("outgoing pulse")
+ inputs = list("\ enable ticking" = 0)
+ activators = list("\ outgoing pulse")
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 4
@@ -91,8 +89,8 @@
. = ..()
/obj/item/integrated_circuit/time/ticker/on_data_written()
- var/datum/integrated_io/do_tick = inputs[1]
- if(do_tick.data && !is_running)
+ var/do_tick = get_pin_data(IC_INPUT, 1)
+ if(do_tick && !is_running)
is_running = TRUE
processing_objects |= src
else if(is_running)
@@ -108,8 +106,7 @@
ticks_completed -= ticks_to_pulse
else
ticks_completed = 0
- var/datum/integrated_io/pulser = activators[1]
- pulser.push_data()
+ activate_pin(1)
/obj/item/integrated_circuit/time/ticker/fast
name = "fast ticker"
@@ -134,20 +131,16 @@
desc = "Tells you what the local time is, specific to your station or planet."
icon_state = "clock"
inputs = list()
- outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)")
+ outputs = list("\ time", "\ hours", "\ minutes", "\ seconds")
+ activators = list("\ get time","\ on time got")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
- var/datum/integrated_io/time = outputs[1]
- var/datum/integrated_io/hour = outputs[2]
- var/datum/integrated_io/min = outputs[3]
- var/datum/integrated_io/sec = outputs[4]
+ set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
+ set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
+ set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
+ set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
- time.data = time2text(station_time_in_ticks, "hh:mm:ss")
- hour.data = text2num(time2text(station_time_in_ticks, "hh"))
- min.data = text2num(time2text(station_time_in_ticks, "mm"))
- sec.data = text2num(time2text(station_time_in_ticks, "ss"))
-
- for(var/datum/integrated_io/output/O in outputs)
- O.push_data()
\ No newline at end of file
+ push_data()
+ activate_pin(2)
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/subtypes/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm
index b1a19f4a406..72d779b6218 100644
--- a/code/modules/integrated_electronics/subtypes/trig.dm
+++ b/code/modules/integrated_electronics/subtypes/trig.dm
@@ -1,9 +1,18 @@
//These circuits do not-so-simple math.
/obj/item/integrated_circuit/trig
complexity = 1
- inputs = list("A","B","C","D","E","F","G","H")
- outputs = list("result")
- activators = list("compute")
+ inputs = list(
+ "\ A",
+ "\ B",
+ "\ C",
+ "\ D",
+ "\ E",
+ "\ F",
+ "\ G",
+ "\ H"
+ )
+ outputs = list("\ result")
+ activators = list("\ compute", "\ on computed")
category_text = "Trig"
extended_desc = "Input and output are in degrees."
autopulse = 1
@@ -19,19 +28,19 @@
name = "sin circuit"
desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A."
icon_state = "sine"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/sine/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = sin(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = sin(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Cosine //
@@ -39,19 +48,19 @@
name = "cos circuit"
desc = "Outputs the cosine of A."
icon_state = "cosine"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosine/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = cos(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = cos(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Tangent //
@@ -59,19 +68,19 @@
name = "tan circuit"
desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance."
icon_state = "tangent"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/tangent/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = Tan(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = Tan(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Cosecant //
@@ -79,19 +88,19 @@
name = "csc circuit"
desc = "Outputs the cosecant of A."
icon_state = "cosecant"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosecant/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = Csc(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = Csc(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Secant //
@@ -100,19 +109,19 @@
name = "sec circuit"
desc = "Outputs the secant of A. Has nothing to do with the security department."
icon_state = "secant"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/secant/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = Sec(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = Sec(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
// Cotangent //
@@ -121,16 +130,16 @@
name = "cot circuit"
desc = "Outputs the cotangent of A."
icon_state = "cotangent"
- inputs = list("A")
+ inputs = list("\ A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cotangent/do_work()
+ pull_data()
var/result = null
- var/datum/integrated_io/input/A = inputs[1]
- A.pull_data()
- if(isnum(A.data))
- result = Cot(A.data)
+ var/A = get_pin_data(IC_INPUT, 1)
+ if(isnum(A))
+ result = Cot(A)
- var/datum/integrated_io/output/O = outputs[1]
- O.data = result
- O.push_data()
\ No newline at end of file
+ set_pin_data(IC_OUTPUT, 1, result)
+ push_data()
+ activate_pin(2)
\ No newline at end of file
diff --git a/code/modules/lore_codex/lore_data/species.dm b/code/modules/lore_codex/lore_data/species.dm
index fa8c6d96152..54d72e07182 100644
--- a/code/modules/lore_codex/lore_data/species.dm
+++ b/code/modules/lore_codex/lore_data/species.dm
@@ -38,16 +38,11 @@
/datum/lore/codex/page/unathi
name = "Unathi"
- data = "The author wishes to apologize to the reader, as they currently lack enough knowledge of the Unathi to write about them, as they are \
- rather rare inside Vir." // Replace this when Anewbe finishes the lizard rewrite.
- /*
- data = "Raging in from Moghes, the Unathi are a race of tall, reptilian humanoids that possess both crocodile-like and serpent-like features. \
- They are a proud, warlike species that favors honor and strength, their home, Moghes, is a desert planet but was once believed to be full of life. \
- Of all the currently known sentient species, the Unathi are the most unequal in gender with females tending to be property of the males. Most Unathi \
- outside of Moghes tend to be exiles however, and with influence of other species the gender difference is not nearly as pronounced. Unathi were \
- humanity's second contact, and despite their aggressive nature, seem to get along well enough with humanity, though are often considered to be \
- 'second-class' citizens and are rarely seen in jobs other than where muscle is needed." // This probably needs to be updated.
- */
+ data = "The Unathi are a race of tall, reptilian humanoids that possess a blend of serpentine features reminiscent of crocodiles. \
+ They are a proud, religious species that favors honor and strength, and originate from the desert planet of Moghes. \
+ The Unathi follow a religious code known as the Unity, and they carry this with them on their travels. \
+ Unathi once fought a serious war against SolGov, and as a result are often considered to be second-class citizens, \
+ rarely seen in jobs that don't require a little muscle."
/datum/lore/codex/page/tajaran
name = "Tajaran"
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
index 11f6021c75b..68fb129108e 100644
--- a/code/modules/materials/material_recipes.dm
+++ b/code/modules/materials/material_recipes.dm
@@ -10,6 +10,7 @@
recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/weapon/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]")
+ recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]")
if(integrity>=50)
recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm
index 4610b4e00fe..921b28d733e 100644
--- a/code/modules/materials/materials.dm
+++ b/code/modules/materials/materials.dm
@@ -90,10 +90,12 @@ var/list/name_to_material
var/ignition_point // K, point at which the material catches on fire.
var/melting_point = 1800 // K, walls will take damage if they're next to a fire hotter than this
var/integrity = 150 // General-use HP value for products.
+ var/protectiveness = 10 // How well this material works as armor. Higher numbers are better, diminishing returns applies.
var/opacity = 1 // Is the material transparent? 0.5< makes transparent walls/doors.
- var/reflectivity = 0 // How reflective to light is the material? Currently used for laser defense.
+ var/reflectivity = 0 // How reflective to light is the material? Currently used for laser reflection and defense.
var/explosion_resistance = 5 // Only used by walls currently.
var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn.
+ var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10.
var/list/composite_material // If set, object matter var will be a list containing these values.
// Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
@@ -103,7 +105,7 @@ var/list/name_to_material
var/list/window_options = list()
// Damage values.
- var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons.
+ var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. Also used for bullet protection in armor.
var/weight = 20 // Determines blunt damage/throwforce for weapons.
// Noise when someone is faceplanted onto a table made of this material.
@@ -236,6 +238,7 @@ var/list/name_to_material
icon_colour = "#00FFE1"
opacity = 0.4
reflectivity = 0.6
+ conductivity = 1
shard_type = SHARD_SHARD
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 100
@@ -247,6 +250,7 @@ var/list/name_to_material
icon_colour = "#EDD12F"
weight = 24
hardness = 40
+ conductivity = 41
stack_origin_tech = list(TECH_MATERIAL = 4)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -261,6 +265,7 @@ var/list/name_to_material
icon_colour = "#D1E6E3"
weight = 22
hardness = 50
+ conductivity = 63
stack_origin_tech = list(TECH_MATERIAL = 3)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -304,6 +309,8 @@ var/list/name_to_material
shard_type = SHARD_STONE_PIECE
weight = 22
hardness = 55
+ protectiveness = 5 // 20%
+ conductivity = 5
door_icon_base = "stone"
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
@@ -320,6 +327,8 @@ var/list/name_to_material
name = DEFAULT_WALL_MATERIAL
stack_type = /obj/item/stack/material/steel
integrity = 150
+ conductivity = 11 // Assuming this is carbon steel, it would actually be slightly less conductive than iron, but lets ignore that.
+ protectiveness = 10 // 33%
icon_base = "solid"
icon_reinf = "reinf_over"
icon_colour = "#666666"
@@ -355,6 +364,8 @@ var/list/name_to_material
explosion_resistance = 25
hardness = 80
weight = 23
+ protectiveness = 20 // 50%
+ conductivity = 13 // For the purposes of balance.
stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo
@@ -370,6 +381,7 @@ var/list/name_to_material
explosion_resistance = 75
hardness = 100
weight = 28
+ protectiveness = 60 // 75%
reflectivity = 0.7 // Not a perfect mirror, but close.
stack_origin_tech = list(TECH_MATERIAL = 8)
composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug
@@ -377,6 +389,7 @@ var/list/name_to_material
/material/plasteel/titanium
name = "titanium"
stack_type = null
+ conductivity = 2.38
icon_base = "metal"
door_icon_base = "metal"
icon_colour = "#D1E6E3"
@@ -393,6 +406,8 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 30
weight = 15
+ protectiveness = 0 // 0%
+ conductivity = 1 // Glass shards don't conduct.
door_icon_base = "stone"
destruction_desc = "shatters"
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
@@ -483,7 +498,7 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 40
weight = 30
- stack_origin_tech = "materials=2"
+ stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 2, "glass" = SHEET_MATERIAL_AMOUNT)
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
created_window = /obj/structure/window/reinforced
@@ -526,6 +541,8 @@ var/list/name_to_material
icon_colour = "#CCCCCC"
hardness = 10
weight = 12
+ protectiveness = 5 // 20%
+ conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator.
melting_point = T0C+371 //assuming heat resistant plastic
stack_origin_tech = list(TECH_MATERIAL = 3)
@@ -556,12 +573,14 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/mhydrogen
icon_colour = "#E6C5DE"
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
+ conductivity = 100
/material/platinum
name = "platinum"
stack_type = /obj/item/stack/material/platinum
icon_colour = "#9999FF"
weight = 27
+ conductivity = 9.43
stack_origin_tech = list(TECH_MATERIAL = 2)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -571,6 +590,7 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/iron
icon_colour = "#5C5454"
weight = 22
+ conductivity = 10
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -585,6 +605,7 @@ var/list/name_to_material
explosion_resistance = 200 // Hull plating.
hardness = 500
weight = 500
+ protectiveness = 80 // 80%
// Likewise.
/material/alienalloy/elevatorium
@@ -603,6 +624,8 @@ var/list/name_to_material
shard_can_repair = 0 // you can't weld splinters back into planks
hardness = 15
weight = 18
+ protectiveness = 8 // 28%
+ conductivity = 1
melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
ignition_point = T0C+288
stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
@@ -634,6 +657,7 @@ var/list/name_to_material
icon_colour = "#AAAAAA"
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
stack_origin_tech = list(TECH_MATERIAL = 1)
@@ -650,6 +674,7 @@ var/list/name_to_material
integrity = 1
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
stack_origin_tech = list(TECH_MATERIAL = 1)
melting_point = T0C+1
destruction_desc = "crumples"
@@ -662,6 +687,7 @@ var/list/name_to_material
door_icon_base = "wood"
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
flags = MATERIAL_PADDING
/material/cult
@@ -695,6 +721,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+300
melting_point = T0C+300
+ protectiveness = 3 // 13%
/material/carpet
name = "carpet"
@@ -706,6 +733,7 @@ var/list/name_to_material
melting_point = T0C+300
sheet_singular_name = "tile"
sheet_plural_name = "tiles"
+ protectiveness = 1 // 4%
/material/cotton
name = "cotton"
@@ -714,7 +742,9 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
+// This all needs to be OOP'd and use inheritence if its ever used in the future.
/material/cloth_teal
name = "teal"
display_name ="teal"
@@ -723,6 +753,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_black
name = "black"
@@ -732,6 +763,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_green
name = "green"
@@ -741,6 +773,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_puple
name = "purple"
@@ -750,6 +783,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_blue
name = "blue"
@@ -759,6 +793,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_beige
name = "beige"
@@ -768,6 +803,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_lime
name = "lime"
@@ -777,6 +813,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/toy_foam
name = "foam"
@@ -787,4 +824,5 @@ var/list/name_to_material
melting_point = T0C+300
icon_colour = "#ff9900"
hardness = 1
- weight = 1
\ No newline at end of file
+ weight = 1
+ protectiveness = 0 // 0%
\ No newline at end of file
diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ore.dm
index 128dc173328..e531e5208f3 100644
--- a/code/modules/mining/ore.dm
+++ b/code/modules/mining/ore.dm
@@ -37,7 +37,7 @@
var/mob/living/carbon/human/H = hit_atom
if(istype(H) && H.has_eyes() && prob(85))
H << "Some of \the [src] gets in your eyes!"
- H.eye_blind += 5
+ H.Blind(5)
H.eye_blurry += 10
spawn(1)
if(istype(loc, /turf/)) qdel(src)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 07562ad190d..4384151cbd4 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -212,7 +212,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
- if(stat == DEAD)
+ if(stat == DEAD && !forbid_seeing_deadchat)
announce_ghost_joinleave(ghostize(1))
else
var/response
@@ -223,7 +223,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
src.client.admin_ghost()
else
- response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body")
+ response = alert(src, "Are you -sure- you want to ghost?\n(You are alive, or otherwise have the potential to become alive. If you ghost, you won't be able to play this round until you respawn as a new character! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body")
if(response != "Ghost")
return
resting = 1
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index fdb0b012ef8..3a451bff448 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -101,7 +101,7 @@
/mob/living/silicon/ai/special_mentions()
return list("AI") // AI door!
-// Converts specific characters, like *, |, and _ to formatted output.
+// Converts specific characters, like +, |, and _ to formatted output.
/mob/proc/say_emphasis(var/message)
message = encode_html_emphasis(message, "|", "i")
message = encode_html_emphasis(message, "+", "b")
diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm
index 85942fcb4e9..44e0d002808 100644
--- a/code/modules/mob/language/station.dm
+++ b/code/modules/mob/language/station.dm
@@ -24,7 +24,7 @@
/datum/language/unathi
name = LANGUAGE_UNATHI
- desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi."
+ desc = "The common language of the Moghes Hegemony, composed of sibilant hisses and rattles. Spoken natively by Unathi."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "roars"
@@ -60,7 +60,7 @@
flags = WHITELISTED
syllables = list("mrr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr",
"mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r",
- "ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah",
+ "ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah",
"hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra")
/datum/language/tajaran/get_random_name(var/gender)
diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm
index 8c61b68a3ea..873934c0c70 100644
--- a/code/modules/mob/living/bot/bot.dm
+++ b/code/modules/mob/living/bot/bot.dm
@@ -70,10 +70,10 @@
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
- health = maxHealth
+ health = getMaxHealth()
stat = CONSCIOUS
else
- health = maxHealth - getFireLoss() - getBruteLoss()
+ health = getMaxHealth() - getFireLoss() - getBruteLoss()
oxyloss = 0
toxloss = 0
cloneloss = 0
@@ -104,9 +104,9 @@
user << "You need to unlock the controls first."
return
else if(istype(O, /obj/item/weapon/weldingtool))
- if(health < maxHealth)
+ if(health < getMaxHealth())
if(open)
- health = min(maxHealth, health + 10)
+ health = min(getMaxHealth(), health + 10)
user.visible_message("[user] repairs [src].","You repair [src].")
else
user << "Unable to repair with the maintenance panel closed."
@@ -224,7 +224,7 @@
/mob/living/bot/proc/getPatrolTurf()
var/minDist = INFINITY
var/obj/machinery/navbeacon/targ = locate() in get_turf(src)
-
+
if(!targ)
for(var/obj/machinery/navbeacon/N in navbeacons)
if(!N.codes["patrol"])
diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm
index a7764d3d1dc..fd48b912a0d 100644
--- a/code/modules/mob/living/carbon/alien/life.dm
+++ b/code/modules/mob/living/carbon/alien/life.dm
@@ -73,11 +73,11 @@
// Eyes and blindness.
if(!has_eyes())
- eye_blind = 1
+ SetBlinded(1)
blinded = 1
eye_blurry = 1
else if(eye_blind)
- eye_blind = max(eye_blind-1,0)
+ AdjustBlinded(-1)
blinded = 1
else if(eye_blurry)
eye_blurry = max(eye_blurry-1, 0)
diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm
index 3f41f21ce55..bac50b1e626 100644
--- a/code/modules/mob/living/carbon/brain/life.dm
+++ b/code/modules/mob/living/carbon/brain/life.dm
@@ -76,7 +76,7 @@
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
- confused = max(0, confused - 1)
+ AdjustConfused(-1)
// decrement dizziness counter, clamped to 0
if(resting)
dizziness = max(0, dizziness - 5)
@@ -110,7 +110,7 @@
if(31 to INFINITY)
emp_damage = 30//Let's not overdo it
if(21 to 30)//High level of EMP damage, unable to see, hear, or speak
- eye_blind = 1
+ SetBlinded(1)
blinded = 1
ear_deaf = 1
silent = 1
@@ -123,7 +123,7 @@
if(20)
alert = 0
blinded = 0
- eye_blind = 0
+ SetBlinded(0)
ear_deaf = 0
silent = 0
emp_damage -= 1
diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm
index 14c8efbbadd..6b07140211f 100644
--- a/code/modules/mob/living/carbon/give.dm
+++ b/code/modules/mob/living/carbon/give.dm
@@ -1,11 +1,11 @@
-/mob/living/carbon/human/verb/give(var/mob/living/target in view(1)-usr)
+/mob/living/carbon/human/verb/give(var/mob/living/carbon/target in view(1)-usr)
set category = "IC"
set name = "Give"
// TODO : Change to incapacitated() on merge.
- if(src.stat || src.lying || src.resting || src.buckled)
+ if(src.stat || src.lying || src.resting || src.handcuffed)
return
- if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null)
+ if(!istype(target) || target.stat || target.lying || target.resting || target.handcuffed || target.client == null)
return
var/obj/item/I = src.get_active_hand()
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index ee0c867ffb6..b4a47d2e47f 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -41,6 +41,13 @@
species.handle_death(src)
animate_tail_stop()
+ //Handle snowflake ling stuff.
+ if(mind && mind.changeling)
+ // If the ling is capable of revival, don't allow them to see deadchat.
+ if(mind.changeling.chem_charges >= CHANGELING_STASIS_COST)
+ if(mind.changeling.max_geneticpoints >= 0) // Absorbed lings don't count, as they can't revive.
+ forbid_seeing_deadchat = TRUE
+
//Handle brain slugs.
var/obj/item/organ/external/Hd = get_organ(BP_HEAD)
var/mob/living/simple_animal/borer/B
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 1c4f4e841e3..66abc50cabe 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -88,6 +88,7 @@
if(mind.changeling)
stat("Chemical Storage", mind.changeling.chem_charges)
stat("Genetic Damage Time", mind.changeling.geneticdamage)
+ stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]")
/mob/living/carbon/human/ex_act(severity)
if(!blinded)
@@ -1496,3 +1497,11 @@
/mob/living/carbon/human/is_muzzled()
return (wear_mask && (istype(wear_mask, /obj/item/clothing/mask/muzzle) || istype(src.wear_mask, /obj/item/weapon/grenade)))
+// Called by job_controller. Makes drones start with a permit, might be useful for other people later too.
+/mob/living/carbon/human/equip_post_job()
+ var/braintype = get_FBP_type()
+ if(braintype == FBP_DRONE)
+ var/turf/T = get_turf(src)
+ var/obj/item/weapon/permit/drone/permit = new(T)
+ permit.set_name(real_name)
+ equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor.
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index fa3d19ebabe..30ee7c64d6e 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -2,7 +2,7 @@
/mob/living/carbon/human/updatehealth()
if(status_flags & GODMODE)
- health = maxHealth
+ health = getMaxHealth()
stat = CONSCIOUS
return
@@ -14,10 +14,10 @@
total_brute += O.brute_dam
total_burn += O.burn_dam
- health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
+ health = getMaxHealth() - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
- if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD)
+ if( ((getMaxHealth() - total_burn) < config.health_threshold_dead) && stat == DEAD)
ChangeToHusk()
return
@@ -42,7 +42,7 @@
if(should_have_organ("brain"))
var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
- sponge.damage = min(max(amount, 0),(maxHealth*2))
+ sponge.damage = min(max(amount, 0),(getMaxHealth()*2))
brainloss = sponge.damage
else
brainloss = 200
@@ -56,7 +56,7 @@
if(should_have_organ("brain"))
var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
- brainloss = min(sponge.damage,maxHealth*2)
+ brainloss = min(sponge.damage,getMaxHealth()*2)
else
brainloss = 200
else
@@ -99,16 +99,32 @@
/mob/living/carbon/human/adjustBruteLoss(var/amount)
amount = amount*species.brute_mod
if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_brute_damage_percent))
+ amount *= M.incoming_brute_damage_percent
take_overall_damage(amount, 0)
else
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
heal_overall_damage(-amount, 0)
BITSET(hud_updateflag, HEALTH_HUD)
/mob/living/carbon/human/adjustFireLoss(var/amount)
amount = amount*species.burn_mod
if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_fire_damage_percent))
+ amount *= M.incoming_fire_damage_percent
take_overall_damage(0, amount)
else
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
heal_overall_damage(0, -amount)
BITSET(hud_updateflag, HEALTH_HUD)
@@ -118,8 +134,16 @@
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_brute_damage_percent))
+ amount *= M.incoming_brute_damage_percent
O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(-amount, 0, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
@@ -131,8 +155,16 @@
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_fire_damage_percent))
+ amount *= M.incoming_fire_damage_percent
O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(0, -amount, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
@@ -153,6 +185,26 @@
wearing_rig.notify_ai("Warning: user consciousness failure. Mobility control passed to integrated intelligence system.")
..()
+/mob/living/carbon/human/proc/Stasis(amount)
+ if((species.flags & NO_SCAN) || isSynthetic())
+ in_stasis = 0
+ else
+ in_stasis = amount
+
+/mob/living/carbon/human/proc/getStasis()
+ if((species.flags & NO_SCAN) || isSynthetic())
+ return 0
+
+ return in_stasis
+
+//This determines if, RIGHT NOW, the life() tick is being skipped due to stasis
+/mob/living/carbon/human/proc/inStasisNow()
+ var/stasisValue = getStasis()
+ if(stasisValue && (life_tick % stasisValue))
+ return 1
+
+ return 0
+
/mob/living/carbon/human/getCloneLoss()
if((species.flags & NO_SCAN) || isSynthetic())
cloneloss = 0
@@ -400,11 +452,25 @@ This function restores all organs.
if(BRUTE)
damageoverlaytemp = 20
damage = damage*species.brute_mod
+
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ damage *= M.incoming_damage_percent
+ if(!isnull(M.incoming_brute_damage_percent))
+ damage *= M.incoming_brute_damage_percent
+
if(organ.take_damage(damage, 0, sharp, edge, used_weapon))
UpdateDamageIcon()
if(BURN)
damageoverlaytemp = 20
damage = damage*species.burn_mod
+
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ damage *= M.incoming_damage_percent
+ if(!isnull(M.incoming_brute_damage_percent))
+ damage *= M.incoming_fire_damage_percent
+
if(organ.take_damage(0, damage, sharp, edge, used_weapon))
UpdateDamageIcon()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 86bbdebc15e..61b13316b84 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -27,6 +27,11 @@ emp_act
if(!P.nodamage)
organ.add_autopsy_data("[P.name]", P.damage)
+ // Tell clothing we're wearing that it got hit by a bullet/laser/etc
+ var/list/clothing = get_clothing_list_organ(organ)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(P, P.damage)
+
//Shrapnel
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
@@ -130,6 +135,15 @@ emp_act
return siemens_coefficient
+// Returns a list of clothing that is currently covering def_zone.
+/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
+ var/list/results = list()
+ var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
+ for(var/obj/item/clothing/C in clothing_items)
+ if(istype(C) && (C.body_parts_covered & def_zone.body_part))
+ results.Add(C)
+ return results
+
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
if(!type || !def_zone) return 0
@@ -231,10 +245,6 @@ emp_act
var/soaked = get_armor_soak(hit_zone, "melee", I.armor_penetration)
- if(soaked >= effective_force)
- src << "Your armor absorbs the force of [I.name]!"
- return
-
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
@@ -246,9 +256,14 @@ emp_act
if(!affecting)
return 0
- if(soaked >= effective_force)
- return 0
+ // Allow clothing to respond to being hit.
+ // This is done up here so that clothing damage occurs even if fully blocked.
+ var/list/clothing = get_clothing_list_organ(affecting)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(I, effective_force)
+ if(soaked >= round(effective_force*0.8))
+ effective_force -= round(effective_force*0.8)
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force *= 0.5 //reduced effective force...
@@ -309,12 +324,15 @@ emp_act
return 1
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked, var/soaked)
- if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100 || soaked > effective_force)
+ if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
return 0
if(W.damtype != BRUTE)
return 0
+ if(soaked >= round(effective_force*0.8))
+ effective_force -= round(effective_force*0.8)
+
//want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb
var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100
if(prob(dislocate_chance * (100 - blocked)/100))
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 0a1817e6b2d..636d6af7920 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -93,3 +93,5 @@
mob_swap_flags = ~HEAVY
var/identifying_gender // In case the human identifies as another gender than it's biological
+
+ var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 7682f675b08..cb49001d3c9 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -90,6 +90,24 @@
return 0
+// Returns a string based on what kind of brain the FBP has.
+/mob/living/carbon/human/proc/get_FBP_type()
+ if(!isSynthetic())
+ return FBP_NONE
+ var/obj/item/organ/internal/brain/B
+ B = internal_organs_by_name[O_BRAIN]
+ if(B) // Incase we lost our brain for some reason, like if we got decapped.
+ if(istype(B, /obj/item/organ/internal/mmi_holder))
+ var/obj/item/organ/internal/mmi_holder/mmi_holder = B
+ if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/posibrain))
+ return FBP_POSI
+ else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/robot))
+ return FBP_DRONE
+ else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi)) // This needs to come last because inheritence.
+ return FBP_CYBORG
+
+ return FBP_NONE
+
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 2ffec342883..98f8f81d9c7 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -13,9 +13,15 @@
handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
if(force_max_speed)
- return -3 // Returning -1 will actually result in a slowdown for Teshari.
+ return -3
- var/health_deficiency = (maxHealth - health)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.haste) && M.haste == TRUE)
+ return -3 // Returning -1 will actually result in a slowdown for Teshari.
+ if(!isnull(M.slowdown))
+ tally += M.slowdown
+
+ var/health_deficiency = (getMaxHealth() - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
if(can_feel_pain())
@@ -80,9 +86,7 @@
if(T && T.movement_cost)
tally += T.movement_cost
- if(species.item_slowdown_halved)
- if(item_tally > 0)
- item_tally *= 0.5
+ item_tally *= species.item_slowdown_mod
tally += item_tally
@@ -140,3 +144,36 @@
prob_slip = round(prob_slip)
return(prob_slip)
+
+// Handle footstep sounds
+/mob/living/carbon/human/handle_footstep(var/turf/T)
+ if(!config.footstep_volume || !T.footstep_sounds || !T.footstep_sounds.len)
+ return
+ // Future Upgrades - Multi species support
+ var/list/footstep_sounds = T.footstep_sounds["human"]
+ if(!footstep_sounds)
+ return
+
+ var/S = pick(footstep_sounds)
+ if(!S) return
+
+ // Only play every other step while running
+ if(m_intent == "run" && step_count++ % 2 == 0)
+ return
+
+ var/volume = config.footstep_volume
+ // Reduce volume while walking or barefoot
+ if(!shoes || m_intent != "run")
+ volume *= 0.5
+
+ if(!has_organ(BP_L_FOOT) && !has_organ(BP_R_FOOT))
+ return // no feet = no footsteps
+
+ if(buckled || lying || throwing)
+ return // people flying, lying down or sitting do not step
+
+ if(!has_gravity(src) && prob(75))
+ return // Far less likely to make noise in no gravity
+
+ playsound(T, S, volume, FALSE)
+ return
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index e6563a28a1b..2738686c38a 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -62,8 +62,12 @@
voice = GetVoice()
+ var/stasis = inStasisNow()
+ if(getStasis() > 2)
+ Sleeping(20)
+
//No need to update all of these procs if the guy is dead.
- if(stat != DEAD && !in_stasis)
+ if(stat != DEAD && !stasis)
//Updates the number of stored chemicals for powers
handle_changeling()
@@ -82,7 +86,6 @@
if(!client)
species.handle_npc(src)
-
if(!handle_some_updates())
return //We go ahead and process them 5 times for HUD images and other stuff though.
@@ -97,7 +100,7 @@
return 1
/mob/living/carbon/human/breathe()
- if(!in_stasis)
+ if(!inStasisNow())
..()
// Calculate how vulnerable the human is to under- and overpressure.
@@ -207,7 +210,7 @@
/mob/living/carbon/human/handle_mutations_and_radiation()
- if(in_stasis)
+ if(inStasisNow())
return
if(getFireLoss())
@@ -789,7 +792,7 @@
/mob/living/carbon/human/handle_chemicals_in_body()
- if(in_stasis)
+ if(inStasisNow())
return
if(reagents)
@@ -971,18 +974,18 @@
vision = internal_organs_by_name[species.vision_organ]
if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
- eye_blind = 0
+ SetBlinded(0)
blinded = 0
eye_blurry = 0
else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind.
- eye_blind = 1
+ SetBlinded(1)
blinded = 1
eye_blurry = 1
else //You have the requisite organs
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
blinded = 1
else if(eye_blind) // Blindness, heals slowly over time
- eye_blind = max(eye_blind-1,0)
+ AdjustBlinded(-1)
blinded = 1
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
eye_blurry = max(eye_blurry-3, 0)
@@ -1339,7 +1342,7 @@
if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING
/mob/living/carbon/human/handle_random_events()
- if(in_stasis)
+ if(inStasisNow())
return
// Puke if toxloss is too high
@@ -1536,7 +1539,7 @@
if(stat == DEAD)
holder.icon_state = "-100" // X_X
else
- holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(maxHealth-config.health_threshold_crit)*100)
+ holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(getMaxHealth()-config.health_threshold_crit)*100)
hud_list[HEALTH_HUD] = holder
if (BITTEST(hud_updateflag, LIFE_HUD))
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 8a8650aa9ba..f547cba9fcb 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -133,7 +133,7 @@
var/appearance_flags = 0 // Appearance/display related features.
var/spawn_flags = 0 // Flags that specify who can spawn as this species
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
- var/item_slowdown_halved = 0 // If this is on, they're not as affected by item weights for slowdown
+ var/item_slowdown_mod = 1 // How affected by item slowdown the species is.
var/primitive_form // Lesser form, if any (ie. monkey for humans)
var/greater_form // Greater form, if any, ie. human for monkeys.
var/holder_type
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index 5015e19940d..e49236af940 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -34,19 +34,21 @@
ambiguous_genders = TRUE
gluttonous = 1
slowdown = 0.5
- brute_mod = 0.9
- burn_mod = 0.9
+ brute_mod = 0.85
+ burn_mod = 0.85
+ metabolic_rate = 0.85
+ item_slowdown_mod = 0.5
num_alternate_languages = 3
secondary_langs = list(LANGUAGE_UNATHI)
name_language = LANGUAGE_UNATHI
health_hud_intensity = 2.5
- min_age = 18
- max_age = 60
+ min_age = 32
+ max_age = 260
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
- Uuosa-Eso system, which roughly translates to 'burning mother'.]
Coming from a harsh, radioactive \
- desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \
+ Uuosa-Eso system, which roughly translates to 'burning mother'.
Coming from a harsh, inhospitable \
+ planet, they mostly hold ideals of honesty, virtue, proficiency and bravery above all \
else, frequently even their own lives. They prefer warmer temperatures than most species and \
their native tongue is a heavy hissing laungage called Sinta'Unathi."
@@ -62,9 +64,34 @@
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
flesh_color = "#34AF10"
+ blood_color = "#b3cbc3"
+ base_color = "#066000"
reagent_tag = IS_UNATHI
- base_color = "#066000"
+
+ has_limbs = list(
+ BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi),
+ BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi),
+ BP_HEAD = list("path" = /obj/item/organ/external/head/unathi),
+ BP_L_ARM = list("path" = /obj/item/organ/external/arm),
+ BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
+ BP_L_LEG = list("path" = /obj/item/organ/external/leg),
+ BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
+ BP_L_HAND = list("path" = /obj/item/organ/external/hand),
+ BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
+ BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
+ BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
+ )
+
+ //No kidneys or appendix
+ has_organ = list(
+ O_HEART = /obj/item/organ/internal/heart/unathi,
+ O_LUNGS = /obj/item/organ/internal/lungs/unathi,
+ O_LIVER = /obj/item/organ/internal/liver/unathi,
+ O_BRAIN = /obj/item/organ/internal/brain/unathi,
+ O_EYES = /obj/item/organ/internal/eyes,
+ )
+
heat_discomfort_level = 295
heat_discomfort_strings = list(
@@ -229,6 +256,7 @@
secondary_langs = list(LANGUAGE_ROOTGLOBAL)
name_language = LANGUAGE_ROOTLOCAL
health_hud_intensity = 2.5
+ item_slowdown_mod = 0.25
min_age = 1
max_age = 300
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index a84a2889dc5..1924bd5e78f 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -131,10 +131,11 @@ Please contact me on #coderbus IRC. ~Carn x
#define LEGCUFF_LAYER 23
#define L_HAND_LAYER 24
#define R_HAND_LAYER 25
-#define FIRE_LAYER 26 //If you're on fire
-#define WATER_LAYER 27 //If you're submerged in water.
-#define TARGETED_LAYER 28 //BS12: Layer for the target overlay from weapon targeting system
-#define TOTAL_LAYERS 29
+#define MODIFIER_EFFECTS_LAYER 26
+#define FIRE_LAYER 27 //If you're on fire
+#define WATER_LAYER 28 //If you're submerged in water.
+#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system
+#define TOTAL_LAYERS 30
//////////////////////////////////
/mob/living/carbon/human
@@ -1118,6 +1119,18 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
+/mob/living/carbon/human/update_modifier_visuals(var/update_icons=1)
+ overlays_standing[MODIFIER_EFFECTS_LAYER] = null
+ var/image/effects = new()
+ for(var/datum/modifier/M in modifiers)
+ if(M.mob_overlay_state)
+ var/image/I = image("icon" = 'icons/mob/modifier_effects.dmi', "icon_state" = M.mob_overlay_state)
+ effects.overlays += I
+
+ overlays_standing[MODIFIER_EFFECTS_LAYER] = effects
+
+ if(update_icons)
+ update_icons()
/mob/living/carbon/human/update_fire(var/update_icons=1)
overlays_standing[FIRE_LAYER] = null
diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm
index 7bbc4110dde..0f393a9417d 100644
--- a/code/modules/mob/living/carbon/metroid/life.dm
+++ b/code/modules/mob/living/carbon/metroid/life.dm
@@ -80,7 +80,7 @@
src.blinded = null
- health = maxHealth - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
+ health = getMaxHealth() - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
if(health < 0 && stat != DEAD)
death()
@@ -118,7 +118,7 @@
if (src.stuttering) src.stuttering = 0
if (src.eye_blind)
- src.eye_blind = 0
+ SetBlinded(0)
src.blinded = 1
if (src.ear_deaf > 0) src.ear_deaf = 0
diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm
index 3c0bfbdbadd..5fdea4a0e6f 100644
--- a/code/modules/mob/living/carbon/metroid/metroid.dm
+++ b/code/modules/mob/living/carbon/metroid/metroid.dm
@@ -81,7 +81,7 @@
var/tally = 0
- var/health_deficiency = (maxHealth - health)
+ var/health_deficiency = (getMaxHealth() - health)
if(health_deficiency >= 30) tally += (health_deficiency / 25)
if (bodytemperature < 183.222)
@@ -146,7 +146,7 @@
..()
statpanel("Status")
- stat(null, "Health: [round((health / maxHealth) * 100)]%")
+ stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
stat(null, "Intent: [a_intent]")
if (client.statpanel == "Status")
diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm
index 933596ef5e2..9e20d49a442 100644
--- a/code/modules/mob/living/carbon/metroid/powers.dm
+++ b/code/modules/mob/living/carbon/metroid/powers.dm
@@ -21,7 +21,7 @@
return "I cannot feed on other slimes..."
if (!Adjacent(M))
return "This subject is too far away..."
- if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
+ if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.getMaxHealth() * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
return "This subject does not have an edible life energy..."
for(var/mob/living/carbon/slime/met in view())
if(met.Victim == M && met != src)
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 552319e6fe4..0fa139c36f1 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -11,10 +11,13 @@
/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/used_weapon = null, var/sharp = 0, var/edge = 0)
if(Debug2)
world.log << "## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]."
- if(!damage || (blocked >= 100) || soaked >= damage)
+ if(!damage || (blocked >= 100))
return 0
if(soaked)
- damage -= soaked
+ if(soaked >= round(damage*0.8))
+ damage -= round(damage*0.8)
+ else
+ damage -= soaked
blocked = (100-blocked)/100
switch(damagetype)
if(BRUTE)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 9271167d40d..2209c630084 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -10,6 +10,8 @@
return
var/datum/gas_mixture/environment = loc.return_air()
+ handle_modifiers() // Do this early since it might affect other things later.
+
if(stat != DEAD)
//Breathing, if applicable
handle_breathing()
@@ -148,9 +150,9 @@
/mob/living/proc/handle_disabilities()
//Eyes
if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own
- eye_blind = max(eye_blind, 1)
+ SetBlinded(1)
else if(eye_blind) //blindness, heals slowly over time
- eye_blind = max(eye_blind-1,0)
+ AdjustBlinded(-1)
else if(eye_blurry) //blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index ab55807be8d..0b47ba7870f 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -150,9 +150,9 @@ default behaviour is:
/mob/living/verb/succumb()
set hidden = 1
- if ((src.health < 0 && src.health > (5-src.maxHealth))) // Health below Zero but above 5-away-from-death, as before, but variable
- src.adjustOxyLoss(src.health + src.maxHealth * 2) // Deal 2x health in OxyLoss damage, as before but variable.
- src.health = src.maxHealth - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss()
+ if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable
+ src.adjustOxyLoss(src.health + src.getMaxHealth() * 2) // Deal 2x health in OxyLoss damage, as before but variable.
+ src.health = src.getMaxHealth() - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss()
src << "\blue You have given up life and succumbed to death."
@@ -161,7 +161,7 @@ default behaviour is:
health = 100
stat = CONSCIOUS
else
- health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss
+ health = getMaxHealth() - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
@@ -223,14 +223,38 @@ default behaviour is:
/mob/living/proc/adjustBruteLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- bruteloss = min(max(bruteloss + amount, 0),(maxHealth*2))
+
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_brute_damage_percent))
+ amount *= M.incoming_brute_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+
+ bruteloss = min(max(bruteloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/getOxyLoss()
return oxyloss
/mob/living/proc/adjustOxyLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- oxyloss = min(max(oxyloss + amount, 0),(maxHealth*2))
+
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_oxy_damage_percent))
+ amount *= M.incoming_oxy_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+
+ oxyloss = min(max(oxyloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setOxyLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -241,7 +265,19 @@ default behaviour is:
/mob/living/proc/adjustToxLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- toxloss = min(max(toxloss + amount, 0),(maxHealth*2))
+
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_tox_damage_percent))
+ amount *= M.incoming_tox_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+
+ toxloss = min(max(toxloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setToxLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -255,14 +291,37 @@ default behaviour is:
/mob/living/proc/adjustFireLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- fireloss = min(max(fireloss + amount, 0),(maxHealth*2))
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_fire_damage_percent))
+ amount *= M.incoming_fire_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+
+ fireloss = min(max(fireloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/getCloneLoss()
return cloneloss
/mob/living/proc/adjustCloneLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- cloneloss = min(max(cloneloss + amount, 0),(maxHealth*2))
+
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_clone_damage_percent))
+ amount *= M.incoming_clone_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+
+ cloneloss = min(max(cloneloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setCloneLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -273,7 +332,7 @@ default behaviour is:
/mob/living/proc/adjustBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- brainloss = min(max(brainloss + amount, 0),(maxHealth*2))
+ brainloss = min(max(brainloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -284,18 +343,117 @@ default behaviour is:
/mob/living/proc/adjustHalLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
- halloss = min(max(halloss + amount, 0),(maxHealth*2))
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_damage_percent))
+ amount *= M.incoming_damage_percent
+ if(!isnull(M.incoming_hal_damage_percent))
+ amount *= M.incoming_hal_damage_percent
+ if(!isnull(M.disable_duration_percent))
+ amount *= M.incoming_hal_damage_percent
+ else if(amount < 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.incoming_healing_percent))
+ amount *= M.incoming_healing_percent
+ halloss = min(max(halloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setHalLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
halloss = amount
+// Use this to get a mob's max health whenever possible. Reading maxHealth directly will give inaccurate results if any modifiers exist.
/mob/living/proc/getMaxHealth()
- return maxHealth
+ var/result = maxHealth
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.max_health_flat))
+ result += M.max_health_flat
+ // Second loop is so we can get all the flat adjustments first before multiplying, otherwise the result will be different.
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.max_health_percent))
+ result *= M.max_health_percent
+ return result
/mob/living/proc/setMaxHealth(var/newMaxHealth)
maxHealth = newMaxHealth
+/mob/living/Stun(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustStunned(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/Weaken(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustWeakened(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/Paralyse(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustParalysis(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/Sleeping(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustSleeping(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/Confuse(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustConfused(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/Blind(amount)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
+/mob/living/AdjustBlinded(amount)
+ if(amount > 0)
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.disable_duration_percent))
+ amount = round(amount * M.disable_duration_percent)
+ ..(amount)
+
// ++++ROCKDTBEN++++ MOB PROCS //END
/mob/proc/get_contents()
@@ -433,7 +591,7 @@ default behaviour is:
// fix blindness and deafness
blinded = 0
- eye_blind = 0
+ SetBlinded(0)
eye_blurry = 0
ear_deaf = 0
ear_damage = 0
@@ -570,6 +728,9 @@ default behaviour is:
for(var/mob/living/carbon/slime/M in view(1,src))
M.UpdateFeed(src)
+/mob/living/proc/handle_footstep(turf/T)
+ return FALSE
+
/mob/living/verb/resist()
set name = "Resist"
set category = "IC"
@@ -797,6 +958,11 @@ default behaviour is:
update_icons()
return canmove
+// Adds overlays for specific modifiers.
+// You'll have to add your own implementation for non-humans currently, just override this proc.
+/mob/living/proc/update_modifier_visuals()
+ return
+
/mob/living/proc/update_water() // Involves overlays for humans. Maybe we'll get submerged sprites for borgs in the future?
return
@@ -804,3 +970,7 @@ default behaviour is:
if(isSynthetic())
return FALSE
return TRUE
+
+// Called by job_controller.
+/mob/living/proc/equip_post_job()
+ return
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 8a49ed8922b..66e1278e225 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -107,6 +107,11 @@
var/absorb = run_armor_check(def_zone, P.check_armour, P.armor_penetration)
var/proj_sharp = is_sharp(P)
var/proj_edge = has_edge(P)
+
+ if ((proj_sharp || proj_edge) && (soaked >= round(P.damage*0.8)))
+ proj_sharp = 0
+ proj_edge = 0
+
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour)))
proj_sharp = 0
proj_edge = 0
@@ -167,13 +172,11 @@
var/soaked = get_armor_soak(hit_zone, "melee")
var/blocked = run_armor_check(hit_zone, "melee")
- //If the armor absorbs all of the damage, skip the damage calculation and the blood
- if(!(soaked > effective_force))
- standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
+ standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
- if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
- var/turf/simulated/location = get_turf(src)
- if(istype(location)) location.add_blood_floor(src)
+ if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
+ var/turf/simulated/location = get_turf(src)
+ if(istype(location)) location.add_blood_floor(src)
return blocked
@@ -186,13 +189,14 @@
if(HULK in user.mutations)
effective_force *= 2
- //Armor soak
- if(soaked >= effective_force)
- return 0
-
//Apply weapon damage
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
+
+ if(getsoak(hit_zone, "melee",) - (I.armor_penetration/5) > round(effective_force*0.8)) //soaking a hit turns sharp attacks into blunt ones
+ weapon_sharp = 0
+ weapon_edge = 0
+
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
weapon_sharp = 0
weapon_edge = 0
@@ -251,7 +255,7 @@
if(!O || !src) return
if(O.sharp) //Projectile is suitable for pinning.
- if(soaked >= throw_damage) //Don't embed if it didn't actually damage
+ if(soaked >= round(throw_damage*0.8))
return
//Handles embedding for non-humans and simple_animals.
@@ -435,3 +439,11 @@
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
client.screen += hud_used.hide_actions_toggle
+
+// Returns a number to determine if something is harder or easier to hit than normal.
+/mob/living/proc/get_evasion()
+ var/result = evasion // First we get the 'base' evasion. Generally this is zero.
+ for(var/datum/modifier/M in modifiers)
+ if(!isnull(M.evasion))
+ result += M.evasion
+ return result
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index e6b7f2979df..d8913e7b5b8 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -2,7 +2,7 @@
see_invisible = SEE_INVISIBLE_LIVING
//Health and life related vars
- var/maxHealth = 100 //Maximum health that should be possible.
+ var/maxHealth = 100 //Maximum health that should be possible. Avoid adjusting this if you can, and instead use modifiers datums.
var/health = 100 //A mob's health
var/hud_updateflag = 0
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 1aef4eca81e..80c0dbc505a 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -141,7 +141,7 @@ proc/get_radio_key_from_channel(var/channel)
//Redirect to say_dead if talker is dead
if(stat)
- if(stat == DEAD)
+ if(stat == DEAD && !forbid_seeing_deadchat)
return say_dead(message)
return
@@ -308,7 +308,7 @@ proc/get_radio_key_from_channel(var/channel)
if(M && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(M),get_turf(src))
- if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc)
+ if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
index 349f27114b0..8c12226e3d3 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
@@ -1,7 +1,6 @@
/obj/machinery/computer/drone_control
name = "Maintenance Drone Control"
desc = "Used to monitor the station's drone population and the assembler that services them."
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "power_key"
icon_screen = "power"
req_access = list(access_engine_equip)
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 9dacf9924c4..a9464c595e8 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -98,7 +98,7 @@
else //Not stunned.
src.stat = 0
- confused = max(0, confused - 1)
+ AdjustConfused(-1)
else //Dead.
src.blinded = 1
@@ -107,7 +107,7 @@
if (src.stuttering) src.stuttering--
if (src.eye_blind)
- src.eye_blind--
+ src.AdjustBlinded(-1)
src.blinded = 1
if (src.ear_deaf > 0) src.ear_deaf--
diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm
index 1b051e029f4..58a81ca7a7d 100644
--- a/code/modules/mob/living/silicon/robot/robot_damage.dm
+++ b/code/modules/mob/living/silicon/robot/robot_damage.dm
@@ -1,9 +1,9 @@
/mob/living/silicon/robot/updatehealth()
if(status_flags & GODMODE)
- health = maxHealth
+ health = getMaxHealth()
stat = CONSCIOUS
return
- health = maxHealth - (getBruteLoss() + getFireLoss())
+ health = getMaxHealth() - (getBruteLoss() + getFireLoss())
return
/mob/living/silicon/robot/getBruteLoss()
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 738e9969676..40b18525282 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -63,16 +63,16 @@
switch(severity)
if(1)
src.take_organ_damage(0,20,emp=1)
- confused = (min(confused + 5, 30))
+ Confuse(5)
if(2)
src.take_organ_damage(0,15,emp=1)
- confused = (min(confused + 4, 30))
+ Confuse(4)
if(3)
src.take_organ_damage(0,10,emp=1)
- confused = (min(confused + 3, 30))
+ Confuse(3)
if(4)
src.take_organ_damage(0,5,emp=1)
- confused = (min(confused + 2, 30))
+ Confuse(2)
flash_eyes(affect_silicon = 1)
src << "*BZZZT*"
src << "Warning: Electromagnetic pulse detected."
@@ -148,7 +148,7 @@
// this function shows the health of the AI in the Status panel
/mob/living/silicon/proc/show_system_integrity()
if(!src.stat)
- stat(null, text("System integrity: [round((health/maxHealth)*100)]%"))
+ stat(null, text("System integrity: [round((health/getMaxHealth())*100)]%"))
else
stat(null, text("Systems nonfunctional"))
diff --git a/code/modules/mob/living/simple_animal/aliens/drone.dm b/code/modules/mob/living/simple_animal/aliens/drone.dm
index 3d1ae1bd02d..06de6b4d141 100644
--- a/code/modules/mob/living/simple_animal/aliens/drone.dm
+++ b/code/modules/mob/living/simple_animal/aliens/drone.dm
@@ -17,7 +17,7 @@
response_help = "pokes"
response_disarm = "gently pushes aside"
response_harm = "hits"
-
+
a_intent = I_HURT
ranged = 1
rapid = 1
@@ -99,16 +99,16 @@
src.visible_message("\red \icon[src] [src] suddenly lights up, and additional targetting vanes slide into place.")
hostile = 1
- if(health / maxHealth > 0.9)
+ if(health / getMaxHealth() > 0.9)
icon_state = "drone3"
explode_chance = 0
- else if(health / maxHealth > 0.7)
+ else if(health / getMaxHealth() > 0.7)
icon_state = "drone2"
explode_chance = 0
- else if(health / maxHealth > 0.5)
+ else if(health / getMaxHealth() > 0.5)
icon_state = "drone1"
explode_chance = 0.5
- else if(health / maxHealth > 0.3)
+ else if(health / getMaxHealth() > 0.3)
icon_state = "drone0"
explode_chance = 5
else if(health > 0)
diff --git a/code/modules/mob/living/simple_animal/animals/spiderbot.dm b/code/modules/mob/living/simple_animal/animals/spiderbot.dm
index 1bb202d1a03..95b7e81a177 100644
--- a/code/modules/mob/living/simple_animal/animals/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/animals/spiderbot.dm
@@ -95,10 +95,10 @@
if (istype(O, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = O
if (WT.remove_fuel(0))
- if(health < maxHealth)
+ if(health < getMaxHealth())
health += pick(1,1,1,2,2,3)
- if(health > maxHealth)
- health = maxHealth
+ if(health > getMaxHealth())
+ health = getMaxHealth()
add_fingerprint(user)
src.visible_message("\The [user] has spot-welded some of the damage to \the [src]!")
else
diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm
index c24100476cc..1cc1a85108b 100644
--- a/code/modules/mob/living/simple_animal/constructs/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm
@@ -57,7 +57,7 @@
/mob/living/simple_animal/construct/attack_generic(var/mob/user)
if(istype(user, /mob/living/simple_animal/construct/builder))
- if(health < maxHealth)
+ if(health < getMaxHealth())
adjustBruteLoss(-5)
user.visible_message("\The [user] mends some of \the [src]'s wounds.")
else
@@ -68,9 +68,9 @@
/mob/living/simple_animal/construct/examine(mob/user)
..(user)
var/msg = "*---------*\nThis is \icon[src] \a [src]!\n"
- if (src.health < src.maxHealth)
+ if (src.health < src.getMaxHealth())
msg += ""
- if (src.health >= src.maxHealth/2)
+ if (src.health >= src.getMaxHealth()/2)
msg += "It looks slightly dented.\n"
else
msg += "It looks severely dented!\n"
diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm
index 05087c40368..7b5e77f5c39 100644
--- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm
+++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm
@@ -170,7 +170,7 @@
T.forceMove(src) //put shade in stone
T.status_flags |= GODMODE
T.canmove = 0
- T.health = T.maxHealth
+ T.health = T.getMaxHealth()
src.icon_state = "soulstone2"
T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form"
diff --git a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm
index 79f389821e7..ae700d60b76 100644
--- a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm
+++ b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm
@@ -75,7 +75,7 @@
/mob/living/simple_animal/hostile/mecha/Life()
. = ..()
if(!.) return
- if((health < maxHealth*0.3) && prob(10))
+ if((health < getMaxHealth()*0.3) && prob(10))
sparks.start()
/mob/living/simple_animal/hostile/mecha/bullet_act()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index af20f042019..3ad6260813a 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -234,8 +234,8 @@
density = 1
//Overhealth
- else if(health > maxHealth)
- health = maxHealth
+ else if(health > getMaxHealth())
+ health = getMaxHealth()
/mob/living/simple_animal/update_icon()
..()
@@ -534,7 +534,7 @@
if(istype(O, /obj/item/stack/medical))
if(stat != DEAD)
var/obj/item/stack/medical/MED = O
- if(health < maxHealth)
+ if(health < getMaxHealth())
if(MED.amount >= 1)
adjustBruteLoss(-MED.heal_brute)
MED.amount -= 1
@@ -602,7 +602,7 @@
..()
if(statpanel("Status") && show_stat_health)
- stat(null, "Health: [round((health / maxHealth) * 100)]%")
+ stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
/mob/living/simple_animal/lay_down()
..()
@@ -645,10 +645,10 @@
adjustBruteLoss(30)
/mob/living/simple_animal/adjustBruteLoss(damage)
- health = Clamp(health - damage, 0, maxHealth)
+ health = Clamp(health - damage, 0, getMaxHealth())
/mob/living/simple_animal/adjustFireLoss(damage)
- health = Clamp(health - damage, 0, maxHealth)
+ health = Clamp(health - damage, 0, getMaxHealth())
// Check target_mob if worthy of attack (i.e. check if they are dead or empty mecha)
/mob/living/simple_animal/proc/SA_attackable(target_mob)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 714bde7096a..f16af92a740 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -804,6 +804,30 @@
sleeping = max(sleeping + amount,0)
return
+/mob/proc/Confuse(amount)
+ confused = max(max(confused,amount),0)
+ return
+
+/mob/proc/SetConfused(amount)
+ confused = max(amount,0)
+ return
+
+/mob/proc/AdjustConfused(amount)
+ confused = max(confused + amount,0)
+ return
+
+/mob/proc/Blind(amount)
+ eye_blind = max(max(eye_blind,amount),0)
+ return
+
+/mob/proc/SetBlinded(amount)
+ eye_blind = max(amount,0)
+ return
+
+/mob/proc/AdjustBlinded(amount)
+ eye_blind = max(eye_blind + amount,0)
+ return
+
/mob/proc/Resting(amount)
facing_dir = null
resting = max(max(resting,amount),0)
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 1901902c80d..a63590acf8b 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -207,3 +207,4 @@
var/list/active_genes=list()
var/mob_size = MOB_MEDIUM
+ var/forbid_seeing_deadchat = FALSE // Used for lings to not see deadchat, and to have ghosting behave as if they were not really dead.
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index f3cd084ffac..80f68b979d5 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -170,7 +170,7 @@
if(announce)
assailant.visible_message("[assailant] covers [affecting]'s eyes!")
if(affecting.eye_blind < 3)
- affecting.eye_blind = 3
+ affecting.Blind(3)
/obj/item/weapon/grab/attack_self()
return s_click(hud)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 4327840a478..ba5b24dbe70 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -390,10 +390,16 @@ proc/is_blind(A)
else
name = realname
+ if(subject && subject.forbid_seeing_deadchat && !subject.client.holder)
+ return // Can't talk in deadchat if you can't see it.
+
for(var/mob/M in player_list)
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_mentor(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay))
var/follow
var/lname
+ if(M.forbid_seeing_deadchat && !M.client.holder)
+ continue
+
if(subject)
if(M.is_key_ignored(subject.client.key)) // If we're ignored, do nothing.
continue
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 476a8b68105..a553d4309ca 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -199,7 +199,7 @@
if(S.victim == mob)
return
- if(mob.stat==DEAD && isliving(mob))
+ if(mob.stat==DEAD && isliving(mob) && !mob.forbid_seeing_deadchat)
mob.ghostize()
return
diff --git a/code/modules/mob/modifiers.dm b/code/modules/mob/modifiers.dm
new file mode 100644
index 00000000000..8e1f9e2f6fe
--- /dev/null
+++ b/code/modules/mob/modifiers.dm
@@ -0,0 +1,131 @@
+// This is a datum that tells the mob that something is affecting them.
+// The advantage of using this datum verses just setting a variable on the mob directly, is that there is no risk of two different procs overwriting
+// each other, or other weirdness. An excellent example is adjusting max health.
+
+/datum/modifier
+ var/name = null // Mostly used to organize, might show up on the UI in the Future(tm)
+ var/desc = null // Ditto.
+ var/icon_state = null // See above.
+ var/mob/living/holder = null // The mob that this datum is affecting.
+ var/expire_at = null // world.time when holder's Life() will remove the datum. If null, it lasts forever or until it gets deleted by something else.
+ var/on_created_text = null // Text to show to holder upon being created.
+ var/on_expired_text = null // Text to show to holder when it expires.
+ var/hidden = FALSE // If true, it will not show up on the HUD in the Future(tm)
+ var/stacks = MODIFIER_STACK_FORBID // If true, attempts to add a second instance of this type will refresh expire_at instead.
+ var/flags = 0 // Flags for the modifier, see mobs.dm defines for more details.
+
+ var/light_color = null // If set, the mob possessing the modifier will glow in this color. Not implemented yet.
+ var/light_range = null // How far the light for the above var goes. Not implemented yet.
+ var/light_intensity = null // Ditto. Not implemented yet.
+ var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented.
+
+ // Now for all the different effects.
+ // Percentage modifiers are expressed as a multipler. (e.g. +25% damage should be written as 1.25)
+ var/max_health_flat // Adjusts max health by a flat (e.g. +20) amount. Note this is added to base health.
+ var/max_health_percent // Adjusts max health by a percentage (e.g. -30%).
+ var/disable_duration_percent // Adjusts duration of 'disables' (stun, weaken, paralyze, confusion, sleep, halloss, etc) Setting to 0 will grant immunity.
+ var/incoming_damage_percent // Adjusts all incoming damage.
+ var/incoming_brute_damage_percent // Only affects bruteloss.
+ var/incoming_fire_damage_percent // Only affects fireloss.
+ var/incoming_tox_damage_percent // Only affects toxloss.
+ var/incoming_oxy_damage_percent // Only affects oxyloss.
+ var/incoming_clone_damage_percent // Only affects cloneloss.
+ var/incoming_hal_damage_percent // Only affects halloss.
+ var/incoming_healing_percent // Adjusts amount of healing received.
+ var/outgoing_melee_damage_percent // Adjusts melee damage inflicted by holder by a percentage. Affects attacks by melee weapons and hand-to-hand.
+ var/slowdown // Negative numbers speed up, positive numbers slow down movement.
+ var/haste // If set to 1, the mob will be 'hasted', which makes it ignore slowdown and go really fast.
+ var/evasion // Positive numbers reduce the odds of being hit by 15% each. Negative numbers increase the odds.
+
+/datum/modifier/New(var/new_holder)
+ holder = new_holder
+ ..()
+
+// Checks to see if this datum should continue existing.
+/datum/modifier/proc/check_if_valid()
+ if(expire_at && expire_at < world.time) // Is our time up?
+ src.expire()
+
+/datum/modifier/proc/expire(var/silent = FALSE)
+ if(on_expired_text && !silent)
+ to_chat(holder, on_expired_text)
+ on_expire()
+ holder.modifiers.Remove(src)
+ if(mob_overlay_state) // We do this after removing ourselves from the list so that the overlay won't remain.
+ holder.update_modifier_visuals()
+ qdel(src)
+
+// Override this for special effects when it gets removed.
+/datum/modifier/proc/on_expire()
+ return
+
+// Called every Life() tick. Override for special behaviour.
+/datum/modifier/proc/tick()
+ return
+
+/mob/living
+ var/list/modifiers = list() // A list of modifier datums, which can adjust certain mob numbers.
+
+/mob/living/Destroy()
+ remove_all_modifiers(TRUE)
+ ..()
+
+// Called by Life().
+/mob/living/proc/handle_modifiers()
+ if(!modifiers.len) // No work to do.
+ return
+ // Get rid of anything we shouldn't have.
+ for(var/datum/modifier/M in modifiers)
+ M.check_if_valid()
+ // Remaining modifiers will now receive a tick(). This is in a second loop for safety in order to not tick() an expired modifier.
+ for(var/datum/modifier/M in modifiers)
+ M.tick()
+
+// Call this to add a modifier to a mob. First argument is the modifier type you want, second is how long it should last, in ticks.
+// The SECONDS/MINUTES macro is very helpful for this. E.g. M.add_modifier(/datum/modifier/example, 5 MINUTES)
+/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null)
+ // First, check if the mob already has this modifier.
+ for(var/datum/modifier/M in modifiers)
+ if(istype(modifier_type, M))
+ switch(M.stacks)
+ if(MODIFIER_STACK_FORBID)
+ return // Stop here.
+ if(MODIFIER_STACK_ALLOWED)
+ break // No point checking anymore.
+ if(MODIFIER_STACK_EXTEND)
+ // Not allow to add a second instance, but we can try to prolong the first instance.
+ if(expire_at && world.time + expire_at > M.expire_at)
+ M.expire_at = world.time + expire_at
+ return
+
+ // If we're at this point, the mob doesn't already have it, or it does but stacking is allowed.
+ var/datum/modifier/mod = new modifier_type(src)
+ if(expire_at)
+ mod.expire_at = world.time + expire_at
+ if(mod.on_created_text)
+ to_chat(src, mod.on_created_text)
+ modifiers.Add(mod)
+ if(mod.mob_overlay_state)
+ update_modifier_visuals()
+
+// Removes a specific instance of modifier
+/mob/living/proc/remove_specific_modifier(var/datum/modifier/M, var/silent = FALSE)
+ M.expire(silent)
+
+// Removes all modifiers of a type
+/mob/living/proc/remove_modifiers_of_type(var/modifier_type, var/silent = FALSE)
+ for(var/datum/modifier/M in modifiers)
+ if(istype(M, modifier_type))
+ M.expire(silent)
+
+// Removes all modifiers, useful if the mob's being deleted
+/mob/living/proc/remove_all_modifiers(var/silent = FALSE)
+ for(var/datum/modifier/M in modifiers)
+ M.expire(silent)
+
+// Checks if the mob has a modifier type.
+/mob/living/proc/has_modifier_of_type(var/modifier_type)
+ for(var/datum/modifier/M in modifiers)
+ if(istype(M, modifier_type))
+ return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm
index e76c6516aa7..0ed4e5364a5 100644
--- a/code/modules/multiz/basic.dm
+++ b/code/modules/multiz/basic.dm
@@ -11,25 +11,43 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S
qdel(src)
// The storage of connections between adjacent levels means some bitwise magic is needed.
-proc/HasAbove(var/z)
+/proc/HasAbove(var/z)
if(z >= world.maxz || z > 16 || z < 1)
return 0
return z_levels & (1 << (z - 1))
-proc/HasBelow(var/z)
+/proc/HasBelow(var/z)
if(z > world.maxz || z > 17 || z < 2)
return 0
return z_levels & (1 << (z - 2))
// Thankfully, no bitwise magic is needed here.
-proc/GetAbove(var/atom/atom)
+/proc/GetAbove(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasAbove(turf.z) ? get_step(turf, UP) : null
-proc/GetBelow(var/atom/atom)
+/proc/GetBelow(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasBelow(turf.z) ? get_step(turf, DOWN) : null
+
+/proc/GetConnectedZlevels(z)
+ . = list(z)
+ for(var/level = z, HasBelow(level), level--)
+ . |= level-1
+ for(var/level = z, HasAbove(level), level++)
+ . |= level+1
+
+proc/AreConnectedZLevels(var/zA, var/zB)
+ return zA == zB || (zB in GetConnectedZlevels(zA))
+
+/proc/get_zstep(ref, dir)
+ if(dir == UP)
+ . = GetAbove(ref)
+ else if (dir == DOWN)
+ . = GetBelow(ref)
+ else
+ . = get_step(ref, dir)
\ No newline at end of file
diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm
index 586b6242602..122e1aa4cda 100644
--- a/code/modules/multiz/movement.dm
+++ b/code/modules/multiz/movement.dm
@@ -3,34 +3,38 @@
set category = "IC"
if(zMove(UP))
- to_chat(usr, "You move upwards.")
+ to_chat(src, "You move upwards.")
/mob/verb/down()
set name = "Move Down"
set category = "IC"
if(zMove(DOWN))
- to_chat(usr, "You move down.")
+ to_chat(src, "You move down.")
/mob/proc/zMove(direction)
if(eyeobj)
return eyeobj.zMove(direction)
if(!can_ztravel())
- to_chat(usr, "You lack means of travel in that direction.")
+ to_chat(src, "You lack means of travel in that direction.")
return
+ var/turf/start = loc
+ if(!istype(start))
+ to_chat(src, "You are unable to move from here.")
+ return 0
+
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
-
if(!destination)
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
+ return 0
+
+ if(!start.CanZPass(src, direction))
+ to_chat(src, "\The [start] is in the way.")
return 0
- var/turf/start = get_turf(src)
- if(!start.CanZPass(src, direction))
- to_chat(usr, "\The [start] is in the way.")
- return 0
if(!destination.CanZPass(src, direction))
- to_chat(usr, "\The [destination] blocks your way.")
+ to_chat(src, "\The [destination] blocks your way.")
return 0
var/area/area = get_area(src)
@@ -46,12 +50,12 @@
to_chat(src, "You gave up on pulling yourself up.")
return 0
else
- to_chat(usr, "Gravity stops you from moving upward.")
+ to_chat(src, "Gravity stops you from moving upward.")
return 0
for(var/atom/A in destination)
if(!A.CanPass(src, start, 1.5, 0))
- to_chat(usr, "\The [A] blocks you.")
+ to_chat(src, "\The [A] blocks you.")
return 0
Move(destination)
return 1
@@ -61,14 +65,14 @@
if(destination)
forceMove(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/observer/eye/zMove(direction)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
setLoc(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/proc/can_ztravel()
return 0
diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm
index 1cb5b9b4da7..7c1fee0525e 100644
--- a/code/modules/multiz/pipes.dm
+++ b/code/modules/multiz/pipes.dm
@@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe
dir = SOUTH
initialize_directions = SOUTH
+ // node1 is the connection on the same Z
+ // node2 is the connection on the other Z
+
var/minimum_temperature_difference = 300
var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
@@ -48,7 +51,7 @@ obj/machinery/atmospherics/pipe/zpipe/New()
invisibility = i ? 101 : 0
update_icon()
-obj/machinery/atmospherics/pipe/up/process()
+obj/machinery/atmospherics/pipe/zpipe/process()
if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
..()
else
@@ -78,10 +81,10 @@ obj/machinery/atmospherics/pipe/zpipe/proc/burst()
qdel(src) // NOT qdel.
obj/machinery/atmospherics/pipe/zpipe/proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
+ if(dir == (NORTH|SOUTH))
+ set_dir(NORTH)
+ else if(dir == (EAST|WEST))
+ set_dir(EAST)
obj/machinery/atmospherics/pipe/zpipe/Destroy()
if(node1)
@@ -94,6 +97,7 @@ obj/machinery/atmospherics/pipe/zpipe/pipeline_expansion()
return list(node1, node2)
obj/machinery/atmospherics/pipe/zpipe/update_icon()
+ color = pipe_color
return
obj/machinery/atmospherics/pipe/zpipe/disconnect(obj/machinery/atmospherics/reference)
diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm
index 57278082764..18bb91a9e46 100644
--- a/code/modules/multiz/structures.dm
+++ b/code/modules/multiz/structures.dm
@@ -122,10 +122,6 @@
allowed_directions = UP|DOWN
icon_state = "ladder11"
-
-
-
-
/obj/structure/stairs
name = "Stairs"
desc = "Stairs leading to another deck. Not too useful if the gravity goes out."
diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm
index 8389df7112b..b6845d076f1 100644
--- a/code/modules/multiz/turf.dm
+++ b/code/modules/multiz/turf.dm
@@ -36,6 +36,11 @@
..()
mover.fall()
+// Called when thrown object lands on this turf.
+/turf/simulated/open/hitby(var/atom/movable/AM, var/speed)
+ . = ..()
+ AM.fall()
+
/turf/simulated/open/proc/update()
below = GetBelow(src)
turf_changed_event.register(below, src, /turf/simulated/open/update_icon)
@@ -82,7 +87,7 @@
return
var/obj/item/stack/rods/R = C
if (R.use(1))
- user << "Constructing support lattice ..."
+ to_chat(user, "Constructing support lattice ...")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
@@ -99,7 +104,7 @@
ChangeTurf(/turf/simulated/floor/airless)
return
else
- user << "The plating is going to need some support."
+ to_chat(user, "The plating is going to need some support.")
//To lay cable.
if(istype(C, /obj/item/stack/cable_coil))
diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm
index 0f5ea190f26..c6670d2a30e 100644
--- a/code/modules/organs/blood.dm
+++ b/code/modules/organs/blood.dm
@@ -37,7 +37,7 @@ var/const/CE_STABLE_THRESHOLD = 0.5
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
- if(in_stasis)
+ if(inStasisNow())
return
if(!should_have_organ(O_HEART))
diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm
index 6514092dfc0..1390c89b291 100644
--- a/code/modules/organs/internal/brain.dm
+++ b/code/modules/organs/internal/brain.dm
@@ -35,7 +35,7 @@
if (. >= 2)
if(prob(1))
owner.custom_pain("Your feel very dizzy for a moment!",0)
- owner.confused = max(owner.confused, 2)
+ owner.Confuse(2)
/obj/item/organ/internal/brain/proc/replace_self_with(replace_path)
var/mob/living/carbon/human/tmp_owner = owner
diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm
index 2a2b8305d3c..4febf8f4790 100644
--- a/code/modules/organs/internal/eyes.dm
+++ b/code/modules/organs/internal/eyes.dm
@@ -72,7 +72,7 @@
if(is_bruised())
owner.eye_blurry = 20
if(is_broken())
- owner.eye_blind = 20
+ owner.Blind(20)
/obj/item/organ/internal/eyes/handle_germ_effects()
. = ..() //Up should return an infection level as an integer
diff --git a/code/modules/organs/internal/liver.dm b/code/modules/organs/internal/liver.dm
index daa0a88f76c..6b7459500b6 100644
--- a/code/modules/organs/internal/liver.dm
+++ b/code/modules/organs/internal/liver.dm
@@ -53,6 +53,6 @@
if(prob(1))
owner.custom_pain("There's a sharp pain in your upper-right abdomen!",1)
if (. >= 2)
- if(prob(1) && owner.getToxLoss() < owner.maxHealth*0.3)
+ if(prob(1) && owner.getToxLoss() < owner.getMaxHealth()*0.3)
//owner << "" //Toxins provide their own messages for pain
owner.adjustToxLoss(5) //Not realistic to PA but there are basically no 'real' liver infections
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 63c6da64098..20390a35553 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -492,7 +492,7 @@ This function completely restores a damaged organ to perfect condition.
//Burn damage can cause fluid loss due to blistering and cook-off
if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT))
- var/fluid_loss = 0.75 * (damage/(owner.maxHealth - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100)
+ var/fluid_loss = 0.75 * (damage/(owner.getMaxHealth() - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100)
owner.remove_blood(fluid_loss)
// first check whether we can widen an existing wound
@@ -882,7 +882,7 @@ Note that amputating the affected organ does in fact remove the infection from t
if(!clean)
// Throw limb around.
if(src && istype(loc,/turf))
- throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+ throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
dir = 2
if(DROPLIMB_BURN)
new /obj/effect/decal/cleanable/ash(get_turf(victim))
@@ -901,19 +901,19 @@ Note that amputating the affected organ does in fact remove the infection from t
gore.basecolor = use_blood_colour
gore.update_icon()
- gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+ gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
for(var/obj/item/organ/I in internal_organs)
I.removed()
if(istype(loc,/turf))
- I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+ I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
for(var/obj/item/I in src)
if(I.w_class <= ITEMSIZE_SMALL)
qdel(I)
continue
I.loc = get_turf(src)
- I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+ I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
qdel(src)
diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm
index 244c0b79719..cfc0910901c 100644
--- a/code/modules/organs/organ_internal.dm
+++ b/code/modules/organs/organ_internal.dm
@@ -165,7 +165,7 @@
if(is_bruised())
owner.eye_blurry = 20
if(is_broken())
- owner.eye_blind = 20
+ owner.Blind(20)
/obj/item/organ/internal/liver
name = "liver"
diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm
index 25db1953d67..69d14c1dd16 100644
--- a/code/modules/organs/robolimbs.dm
+++ b/code/modules/organs/robolimbs.dm
@@ -44,6 +44,14 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
var/parts = BP_ALL //Defines what parts said brand can replace on a body.
var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator.
+/datum/robolimb/unbranded_monitor
+ company = "Unbranded Monitor"
+ desc = "A generic unbranded interpretation of a popular prosthetic head model. It looks rudimentary and cheaply constructed."
+ icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi'
+ parts = list(BP_HEAD)
+ monitor_styles = standard_monitor_styles
+ unavailable_to_build = 1
+
/datum/robolimb/nanotrasen
company = "NanoTrasen"
desc = "A simple but efficient robotic limb, created by NanoTrasen."
diff --git a/code/modules/organs/subtypes/unathi.dm b/code/modules/organs/subtypes/unathi.dm
new file mode 100644
index 00000000000..212330577ce
--- /dev/null
+++ b/code/modules/organs/subtypes/unathi.dm
@@ -0,0 +1,50 @@
+/obj/item/organ/external/chest/unathi
+ max_damage = 100
+ min_broken_damage = 40
+ encased = "upper ribplates"
+
+/obj/item/organ/external/groin/unathi
+ max_damage = 100
+ min_broken_damage = 40
+ encased = "lower ribplates"
+
+/obj/item/organ/external/head/unathi
+ max_damage = 75
+ min_broken_damage = 35
+ eye_icon = "eyes_s"
+ force = 5
+ throwforce = 10
+
+
+/obj/item/organ/internal/heart/unathi
+ icon_state = "unathi_heart-on"
+ dead_icon = "unath_heart-off"
+
+/obj/item/organ/internal/lungs/unathi
+ color = "#b3cbc3"
+
+/obj/item/organ/internal/liver/unathi
+ name = "filtration organ"
+ icon_state = "unathi_liver"
+
+//Unathi liver acts as kidneys, too.
+/obj/item/organ/internal/liver/unathi/process()
+ ..()
+ if(!owner) return
+
+ var/datum/reagent/coffee = locate(/datum/reagent/drink/coffee) in owner.reagents.reagent_list
+ if(coffee)
+ if(is_bruised())
+ owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
+ else if(is_broken())
+ owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
+
+ var/datum/reagent/sugar = locate(/datum/reagent/sugar) in owner.reagents.reagent_list
+ if(sugar)
+ if(is_bruised())
+ owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
+ else if(is_broken())
+ owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
+
+/obj/item/organ/internal/brain/unathi
+ color = "#b3cbc3"
\ No newline at end of file
diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm
index 53a07f228bf..4c308ca9306 100644
--- a/code/modules/planet/planet.dm
+++ b/code/modules/planet/planet.dm
@@ -12,8 +12,17 @@
var/datum/weather_holder/weather_holder
var/sun_position = 0 // 0 means midnight, 1 means noon.
+ var/list/sun = list("range","brightness","color")
var/expected_z_levels = list()
+ var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary
+
+ var/turf/simulated/floor/planet_floors = list()
+ var/turf/unsimulated/wall/planetary/planet_walls = list()
+
+
+ var/needs_work = 0 // Bitflags to signal to the planet controller these need (properly deferrable) work. Flags defined in controller.
+
/datum/planet/New()
..()
weather_holder = new(src)
@@ -31,17 +40,13 @@
/datum/planet/proc/update_sun()
sun_last_process = world.time
-
/datum/planet/proc/update_weather()
if(weather_holder)
weather_holder.process()
/datum/planet/proc/update_sun_deferred(var/new_range, var/new_brightness, var/new_color)
- set background = 1
- set waitfor = 0
- var/i = 0
- for(var/turf/simulated/floor/T in outdoor_turfs)
- T.set_light(new_range, new_brightness, new_color)
- i++
- if(i % 30 == 0)
- sleep(1)
+ sun["range"] = new_range
+ sun["brightness"] = new_brightness
+ sun["color"] = new_color
+ needs_work |= PLANET_PROCESS_SUN
+
diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm
index 303d05f5091..e35646ce7fc 100644
--- a/code/modules/planet/sif.dm
+++ b/code/modules/planet/sif.dm
@@ -10,6 +10,7 @@ var/datum/planet/sif/planet_sif = null
Its center of government is the equatorial city and site of first settlement, New Reykjavik." // Ripped straight from the wiki.
current_time = new /datum/time/sif() // 32 hour clocks are nice.
expected_z_levels = list(1) // To be changed when real map is finished.
+ planetary_wall_type = /turf/unsimulated/wall/planetary/sif
/datum/planet/sif/New()
..()
@@ -104,3 +105,197 @@ var/datum/planet/sif/planet_sif = null
/proc/get_sif_time()
if(planet_sif)
return planet_sif.current_time
+
+//Weather definitions
+/datum/weather_holder/sif
+ temperature = T0C
+ allowed_weather_types = list(
+ WEATHER_CLEAR = new /datum/weather/sif/clear(),
+ WEATHER_OVERCAST = new /datum/weather/sif/overcast(),
+ WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(),
+ WEATHER_SNOW = new /datum/weather/sif/snow(),
+ WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(),
+ WEATHER_RAIN = new /datum/weather/sif/rain(),
+ WEATHER_STORM = new /datum/weather/sif/storm(),
+ WEATHER_HAIL = new /datum/weather/sif/hail(),
+ WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon()
+ )
+ roundstart_weather_chances = list(
+ WEATHER_CLEAR = 30,
+ WEATHER_OVERCAST = 30,
+ WEATHER_LIGHT_SNOW = 20,
+ WEATHER_SNOW = 5,
+ WEATHER_BLIZZARD = 5,
+ WEATHER_RAIN = 5,
+ WEATHER_STORM = 2.5,
+ WEATHER_HAIL = 2.5
+ )
+
+datum/weather/sif
+ name = "sif base"
+ temp_high = 243.15 // -20c
+ temp_low = 233.15 // -30c
+
+/datum/weather/sif/clear
+ name = "clear"
+ transition_chances = list(
+ WEATHER_CLEAR = 60,
+ WEATHER_OVERCAST = 40
+ )
+
+/datum/weather/sif/overcast
+ name = "overcast"
+ light_modifier = 0.8
+ transition_chances = list(
+ WEATHER_CLEAR = 25,
+ WEATHER_OVERCAST = 50,
+ WEATHER_LIGHT_SNOW = 10,
+ WEATHER_SNOW = 5,
+ WEATHER_RAIN = 5,
+ WEATHER_HAIL = 5
+ )
+
+/datum/weather/sif/light_snow
+ name = "light snow"
+ icon_state = "snowfall_light"
+ temp_high = 238.15 // -25c
+ temp_low = 228.15 // -35c
+ light_modifier = 0.7
+ transition_chances = list(
+ WEATHER_OVERCAST = 20,
+ WEATHER_LIGHT_SNOW = 50,
+ WEATHER_SNOW = 25,
+ WEATHER_HAIL = 5
+ )
+
+/datum/weather/sif/snow
+ name = "moderate snow"
+ icon_state = "snowfall_med"
+ temp_high = 233.15 // -30c
+ temp_low = 223.15 // -40c
+ light_modifier = 0.5
+ transition_chances = list(
+ WEATHER_LIGHT_SNOW = 20,
+ WEATHER_SNOW = 50,
+ WEATHER_BLIZZARD = 20,
+ WEATHER_HAIL = 5,
+ WEATHER_OVERCAST = 5
+ )
+
+/datum/weather/sif/snow/process_effects()
+ for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
+ if(S.z in holder.our_planet.expected_z_levels)
+ for(var/dir_checked in cardinal)
+ var/turf/simulated/floor/T = get_step(S, dir_checked)
+ if(istype(T))
+ if(istype(T, /turf/simulated/floor/outdoors) && prob(33))
+ T.chill()
+
+/datum/weather/sif/blizzard
+ name = "blizzard"
+ icon_state = "snowfall_heavy"
+ temp_high = 223.15 // -40c
+ temp_low = 203.15 // -60c
+ light_modifier = 0.3
+ transition_chances = list(
+ WEATHER_SNOW = 45,
+ WEATHER_BLIZZARD = 40,
+ WEATHER_HAIL = 10,
+ WEATHER_OVERCAST = 5
+ )
+
+/datum/weather/sif/blizzard/process_effects()
+ for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
+ if(S.z in holder.our_planet.expected_z_levels)
+ for(var/dir_checked in cardinal)
+ var/turf/simulated/floor/T = get_step(S, dir_checked)
+ if(istype(T))
+ if(istype(T, /turf/simulated/floor/outdoors) && prob(50))
+ T.chill()
+
+/datum/weather/sif/rain
+ name = "rain"
+ icon_state = "rain"
+ light_modifier = 0.5
+ transition_chances = list(
+ WEATHER_OVERCAST = 25,
+ WEATHER_LIGHT_SNOW = 10,
+ WEATHER_RAIN = 50,
+ WEATHER_STORM = 10,
+ WEATHER_HAIL = 5
+ )
+
+/datum/weather/sif/rain/process_effects()
+ for(var/mob/living/L in living_mob_list)
+ if(L.z in holder.our_planet.expected_z_levels)
+ var/turf/T = get_turf(L)
+ if(!T.outdoors)
+ return // They're indoors, so no need to rain on them.
+
+ L.adjust_fire_stacks(-5)
+ to_chat(L, "Rain falls on you.")
+
+/datum/weather/sif/storm
+ name = "storm"
+ icon_state = "storm"
+ temp_high = 233.15 // -30c
+ temp_low = 213.15 // -50c
+ light_modifier = 0.3
+ transition_chances = list(
+ WEATHER_RAIN = 45,
+ WEATHER_STORM = 40,
+ WEATHER_HAIL = 10,
+ WEATHER_OVERCAST = 5
+ )
+
+/datum/weather/sif/rain/process_effects()
+ for(var/mob/living/L in living_mob_list)
+ if(L.z in holder.our_planet.expected_z_levels)
+ var/turf/T = get_turf(L)
+ if(!T.outdoors)
+ return // They're indoors, so no need to rain on them.
+
+ L.adjust_fire_stacks(-10)
+ to_chat(L, "Rain falls on you, drenching you in water.")
+
+/datum/weather/sif/hail
+ name = "hail"
+ icon_state = "hail"
+ temp_high = 233.15 // -30c
+ temp_low = 213.15 // -50c
+ light_modifier = 0.3
+ transition_chances = list(
+ WEATHER_RAIN = 45,
+ WEATHER_STORM = 10,
+ WEATHER_HAIL = 40,
+ WEATHER_OVERCAST = 5
+ )
+
+/datum/weather/sif/hail/process_effects()
+ for(var/mob/living/L in living_mob_list)
+ if(L.z in holder.our_planet.expected_z_levels)
+ var/turf/T = get_turf(L)
+ if(!T.outdoors)
+ return // They're indoors, so no need to pelt them with ice.
+
+ var/target_zone = pick(BP_ALL)
+ var/amount_blocked = L.run_armor_check(target_zone, "melee")
+ var/amount_soaked = L.get_armor_soak(target_zone, "melee")
+
+ if(amount_blocked >= 100)
+ return // No need to apply damage.
+
+ if(amount_soaked >= 10)
+ return // No need to apply damage.
+
+ L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
+ to_chat(L, "The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!")
+
+/datum/weather/sif/blood_moon
+ name = "blood moon"
+ light_modifier = 0.5
+ light_color = "#FF0000"
+ transition_chances = list(
+ WEATHER_BLOODMOON = 100
+ )
+
diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm
index c98383a2425..5e392be7969 100644
--- a/code/modules/planet/weather.dm
+++ b/code/modules/planet/weather.dm
@@ -1,15 +1,3 @@
-#define WEATHER_CLEAR "clear"
-#define WEATHER_OVERCAST "overcast"
-#define WEATHER_LIGHT_SNOW "light snow"
-#define WEATHER_SNOW "snow"
-#define WEATHER_BLIZZARD "blizzard"
-#define WEATHER_RAIN "rain"
-#define WEATHER_STORM "storm"
-#define WEATHER_HAIL "hail"
-#define WEATHER_WINDY "windy"
-#define WEATHER_HOT "hot"
-#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on.
-
/datum/weather_holder
var/datum/planet/our_planet = null
var/datum/weather/current_weather = null
@@ -19,7 +7,6 @@
var/list/allowed_weather_types = list()
var/list/roundstart_weather_chances = list()
var/next_weather_shift = null
- var/planetary_wall_type = null // Which walls to look for when updating temperature.
/datum/weather_holder/New(var/source)
..()
@@ -54,55 +41,15 @@
current_weather.process_effects()
/datum/weather_holder/proc/update_icon_effects()
- set background = 1
- set waitfor = 0
- if(current_weather)
- for(var/turf/simulated/floor/T in outdoor_turfs)
- if(T.z in our_planet.expected_z_levels)
- T.overlays -= T.weather_overlay
- T.weather_overlay = image(icon = current_weather.icon, icon_state = current_weather.icon_state, layer = LIGHTING_LAYER - 1)
- T.overlays += T.weather_overlay
+ our_planet.needs_work |= PLANET_PROCESS_WEATHER
/datum/weather_holder/proc/update_temperature()
temperature = Interpolate(current_weather.temp_low, current_weather.temp_high, weight = our_planet.sun_position)
-
- for(var/turf/unsimulated/wall/planetary/wall in planetary_walls)
- if(ispath(wall.type, planetary_wall_type))
- wall.temperature = temperature
- for(var/dir in cardinal)
- var/turf/simulated/T = get_step(wall, dir)
- if(istype(T))
- if(T.zone)
- T.zone.rebuild()
-
+ our_planet.needs_work |= PLANET_PROCESS_TEMP
/datum/weather_holder/proc/get_weather_datum(desired_type)
return allowed_weather_types[desired_type]
-/datum/weather_holder/sif
- temperature = T0C
- allowed_weather_types = list(
- WEATHER_CLEAR = new /datum/weather/sif/clear(),
- WEATHER_OVERCAST = new /datum/weather/sif/overcast(),
- WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(),
- WEATHER_SNOW = new /datum/weather/sif/snow(),
- WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(),
- WEATHER_RAIN = new /datum/weather/sif/rain(),
- WEATHER_STORM = new /datum/weather/sif/storm(),
- WEATHER_HAIL = new /datum/weather/sif/hail(),
- WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon()
- )
- planetary_wall_type = /turf/unsimulated/wall/planetary/sif
- roundstart_weather_chances = list(
- WEATHER_CLEAR = 30,
- WEATHER_OVERCAST = 30,
- WEATHER_LIGHT_SNOW = 20,
- WEATHER_SNOW = 5,
- WEATHER_BLIZZARD = 5,
- WEATHER_RAIN = 5,
- WEATHER_STORM = 2.5,
- WEATHER_HAIL = 2.5
- )
/datum/weather
var/name = "weather base"
@@ -117,169 +64,3 @@
/datum/weather/proc/process_effects()
return
-
-/datum/weather/sif
- name = "sif base"
- temp_high = 243.15 // -20c
- temp_low = 233.15 // -30c
-
-/datum/weather/sif/clear
- name = "clear"
- transition_chances = list(
- WEATHER_CLEAR = 60,
- WEATHER_OVERCAST = 40
- )
-
-/datum/weather/sif/overcast
- name = "overcast"
- light_modifier = 0.8
- transition_chances = list(
- WEATHER_CLEAR = 25,
- WEATHER_OVERCAST = 50,
- WEATHER_LIGHT_SNOW = 10,
- WEATHER_SNOW = 5,
- WEATHER_RAIN = 5,
- WEATHER_HAIL = 5
- )
-
-/datum/weather/sif/light_snow
- name = "light snow"
- icon_state = "snowfall_light"
- temp_high = 238.15 // -25c
- temp_low = 228.15 // -35c
- light_modifier = 0.7
- transition_chances = list(
- WEATHER_OVERCAST = 20,
- WEATHER_LIGHT_SNOW = 50,
- WEATHER_SNOW = 25,
- WEATHER_HAIL = 5
- )
-
-/datum/weather/sif/snow
- name = "moderate snow"
- icon_state = "snowfall_med"
- temp_high = 233.15 // -30c
- temp_low = 223.15 // -40c
- light_modifier = 0.5
- transition_chances = list(
- WEATHER_LIGHT_SNOW = 20,
- WEATHER_SNOW = 50,
- WEATHER_BLIZZARD = 20,
- WEATHER_HAIL = 5,
- WEATHER_OVERCAST = 5
- )
-
-/datum/weather/sif/snow/process_effects()
- for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
- for(var/dir_checked in cardinal)
- var/turf/simulated/floor/T = get_step(S, dir_checked)
- if(istype(T))
- if(istype(T, /turf/simulated/floor/outdoors) && prob(33))
- T.chill()
-
-/datum/weather/sif/blizzard
- name = "blizzard"
- icon_state = "snowfall_heavy"
- temp_high = 223.15 // -40c
- temp_low = 203.15 // -60c
- light_modifier = 0.3
- transition_chances = list(
- WEATHER_SNOW = 45,
- WEATHER_BLIZZARD = 40,
- WEATHER_HAIL = 10,
- WEATHER_OVERCAST = 5
- )
-
-/datum/weather/sif/blizzard/process_effects()
- for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
- for(var/dir_checked in cardinal)
- var/turf/simulated/floor/T = get_step(S, dir_checked)
- if(istype(T))
- if(istype(T, /turf/simulated/floor/outdoors) && prob(50))
- T.chill()
-
-/datum/weather/sif/rain
- name = "rain"
- icon_state = "rain"
- light_modifier = 0.5
- transition_chances = list(
- WEATHER_OVERCAST = 25,
- WEATHER_LIGHT_SNOW = 10,
- WEATHER_RAIN = 50,
- WEATHER_STORM = 10,
- WEATHER_HAIL = 5
- )
-
-/datum/weather/sif/rain/process_effects()
- for(var/mob/living/L in living_mob_list)
- if(L.z in holder.our_planet.expected_z_levels)
- var/turf/T = get_turf(L)
- if(!T.outdoors)
- return // They're indoors, so no need to rain on them.
-
- L.adjust_fire_stacks(-5)
- to_chat(L, "Rain falls on you.")
-
-/datum/weather/sif/storm
- name = "storm"
- icon_state = "storm"
- temp_high = 233.15 // -30c
- temp_low = 213.15 // -50c
- light_modifier = 0.3
- transition_chances = list(
- WEATHER_RAIN = 45,
- WEATHER_STORM = 40,
- WEATHER_HAIL = 10,
- WEATHER_OVERCAST = 5
- )
-
-/datum/weather/sif/rain/process_effects()
- for(var/mob/living/L in living_mob_list)
- if(L.z in holder.our_planet.expected_z_levels)
- var/turf/T = get_turf(L)
- if(!T.outdoors)
- return // They're indoors, so no need to rain on them.
-
- L.adjust_fire_stacks(-10)
- to_chat(L, "Rain falls on you, drenching you in water.")
-
-/datum/weather/sif/hail
- name = "hail"
- icon_state = "hail"
- temp_high = 233.15 // -30c
- temp_low = 213.15 // -50c
- light_modifier = 0.3
- transition_chances = list(
- WEATHER_RAIN = 45,
- WEATHER_STORM = 10,
- WEATHER_HAIL = 40,
- WEATHER_OVERCAST = 5
- )
-
-/datum/weather/sif/hail/process_effects()
- for(var/mob/living/L in living_mob_list)
- if(L.z in holder.our_planet.expected_z_levels)
- var/turf/T = get_turf(L)
- if(!T.outdoors)
- return // They're indoors, so no need to pelt them with ice.
-
- var/target_zone = pick(BP_ALL)
- var/amount_blocked = L.run_armor_check(target_zone, "melee")
- var/amount_soaked = L.get_armor_soak(target_zone, "melee")
-
- if(amount_blocked >= 100)
- return // No need to apply damage.
-
- if(amount_soaked >= 10)
- return // No need to apply damage.
-
- L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
- to_chat(L, "The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!")
-
-/datum/weather/sif/blood_moon
- name = "blood moon"
- light_modifier = 0.5
- light_color = "#FF0000"
- transition_chances = list(
- WEATHER_BLOODMOON = 100
- )
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 671d57e04ef..27bf4c0ab7c 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -48,7 +48,7 @@ var/list/possible_cable_coil_colours = list(
anchored =1
var/datum/powernet/powernet
name = "power cable"
- desc = "A flexible superconducting cable for heavy-duty power transfer"
+ desc = "A flexible superconducting cable for heavy-duty power transfer."
icon = 'icons/obj/power_cond_white.dmi'
icon_state = "0-1"
var/d1 = 0
@@ -116,9 +116,9 @@ var/list/possible_cable_coil_colours = list(
user.examinate(src)
// following code taken from attackby (multitool)
if(powernet && (powernet.avail > 0))
- user << "[powernet.avail]W in power network."
+ to_chat(user, "[powernet.avail]W in power network.")
else
- user << "The cable is not powered."
+ to_chat(user, "The cable is not powered.")
return
///////////////////////////////////
@@ -159,12 +159,12 @@ var/list/possible_cable_coil_colours = list(
return
if(istype(W, /obj/item/weapon/wirecutters))
- if(d1 == 12 || d2 == 12)
- user << "You must cut this cable from above."
+ if(d1 == UP || d2 == UP)
+ to_chat(user, "You must cut this cable from above.")
return
if(breaker_box)
- user << "\red This cable is connected to nearby breaker box. Use breaker box to interact with it."
+ to_chat(user, "This cable is connected to nearby breaker box. Use breaker box to interact with it.")
return
if (shock(user, 50))
@@ -178,11 +178,11 @@ var/list/possible_cable_coil_colours = list(
for(var/mob/O in viewers(src, null))
O.show_message("[user] cuts the cable.", 1)
- if(d1 == 11 || d2 == 11)
+ if(d1 == DOWN || d2 == DOWN)
var/turf/turf = GetBelow(src)
if(turf)
for(var/obj/structure/cable/c in turf)
- if(c.d1 == 12 || c.d2 == 12)
+ if(c.d1 == UP || c.d2 == UP)
qdel(c)
investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires")
@@ -194,17 +194,17 @@ var/list/possible_cable_coil_colours = list(
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if (coil.get_amount() < 1)
- user << "Not enough cable"
+ to_chat(user, "Not enough cable")
return
coil.cable_join(src, user)
else if(istype(W, /obj/item/device/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
- user << "[powernet.avail]W in power network."
+ to_chat(user, "[powernet.avail]W in power network.")
else
- user << "The cable is not powered."
+ to_chat(user, "The cable is not powered.")
shock(user, 5, 0.2)
@@ -300,12 +300,12 @@ obj/structure/cable/proc/cableColor(var/colorC)
// merge with the powernets of power objects in the given direction
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
- var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf
+ var/fdir = direction ? reverse_dir[direction] : 0 //flip the direction, to match with the source position on its turf
if(!(d1 == direction || d2 == direction)) //if the cable is not pointed in this direction, do nothing
return
- var/turf/TB = get_step(src, direction)
+ var/turf/TB = get_zstep(src, direction)
for(var/obj/structure/cable/C in TB)
@@ -376,25 +376,15 @@ obj/structure/cable/proc/cableColor(var/colorC)
. = list() // this will be a list of all connected power objects
var/turf/T
- // Handle up/down cables
- if(d1 == 11 || d2 == 11)
- T = GetBelow(src)
- if(T)
- . += power_list(T, src, 12, 1)
- if(d1 == 12 || d1 == 12)
- T = GetAbove(src)
- if(T)
- . += power_list(T, src, 11, 1)
-
// Handle standard cables in adjacent turfs
for(var/cable_dir in list(d1, d2))
- if(cable_dir == 11 || cable_dir == 12 || cable_dir == 0)
+ if(cable_dir == 0)
continue
var/reverse = reverse_dir[cable_dir]
- T = get_step(src, cable_dir)
+ T = get_zstep(src, cable_dir)
if(T)
for(var/obj/structure/cable/C in T)
- if((C.d1 && C.d1 == reverse) || (C.d2 && C.d2 == reverse))
+ if(C.d1 == reverse || C.d2 == reverse)
. += C
if(cable_dir & (cable_dir - 1)) // Diagonal, check for /\/\/\ style cables along cardinal directions
for(var/pair in list(NORTH|SOUTH, EAST|WEST))
@@ -402,7 +392,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
if(T)
var/req_dir = cable_dir ^ pair
for(var/obj/structure/cable/C in T)
- if((C.d1 && C.d1 == req_dir) || (C.d2 && C.d2 == req_dir))
+ if(C.d1 == req_dir || C.d2 == req_dir)
. += C
// Handle cables on the same turf as us
@@ -566,7 +556,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
final_color = possible_cable_coil_colours["Red"]
selected_color = "red"
color = final_color
- user << "You change \the [src]'s color to [lowertext(selected_color)]."
+ to_chat(user, "You change \the [src]'s color to [lowertext(selected_color)].")
/obj/item/stack/cable_coil/proc/update_wclass()
if(amount == 1)
@@ -579,11 +569,11 @@ obj/structure/cable/proc/cableColor(var/colorC)
return
if(get_amount() == 1)
- user << "A short piece of power cable."
+ to_chat(user, "A short piece of power cable.")
else if(get_amount() == 2)
- user << "A piece of power cable."
+ to_chat(user, "A piece of power cable.")
else
- user << "A coil of power cable. There are [get_amount()] lengths of cable in the coil."
+ to_chat(user, "A coil of power cable. There are [get_amount()] lengths of cable in the coil.")
/obj/item/stack/cable_coil/verb/make_restraint()
@@ -594,14 +584,14 @@ obj/structure/cable/proc/cableColor(var/colorC)
if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned)
if(!istype(usr.loc,/turf)) return
if(src.amount <= 14)
- usr << "\red You need at least 15 lengths to make restraints!"
+ to_chat(usr, "You need at least 15 lengths to make restraints!")
return
var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc)
B.color = color
- usr << "You wind some cable together to make some restraints."
+ to_chat(usr, "You wind some cable together to make some restraints.")
src.use(15)
else
- usr << "\blue You cannot do that."
+ to_chat(usr, "You cannot do that.")
..()
/obj/item/stack/cable_coil/cyborg/verb/set_colour()
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index fe51b4152e1..d6ae824fd1e 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -3,7 +3,6 @@
/obj/machinery/computer/gravity_control_computer
name = "Gravity Generator Control"
desc = "A computer to control a local gravity generator. Qualified personnel only."
- icon = 'icons/obj/computer.dmi'
icon_state = "airtunnel0e"
anchored = 1
density = 1
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index 7697fdf6a45..13213c2e7e3 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -209,16 +209,8 @@
// if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0)
. = list()
- var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
-///// Z-Level Stuff
- var/Zdir
- if(d==11)
- Zdir = 11
- else if (d==12)
- Zdir = 12
- else
- Zdir = 999
-///// Z-Level Stuff
+
+ var/reverse = d ? reverse_dir[d] : 0
for(var/AM in T)
if(AM == source) continue //we don't want to return source
@@ -234,11 +226,7 @@
var/obj/structure/cable/C = AM
if(!unmarked || !C.powernet)
-///// Z-Level Stuff
- if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir)
-///// Z-Level Stuff
- . += C
- else if(C.d1 == d || C.d2 == d)
+ if(C.d1 == d || C.d2 == d || C.d1 == reverse || C.d2 == reverse )
. += C
return .
diff --git a/code/modules/power/sensors/sensor_monitoring.dm b/code/modules/power/sensors/sensor_monitoring.dm
index 597ced19db1..21aecc59ea1 100644
--- a/code/modules/power/sensors/sensor_monitoring.dm
+++ b/code/modules/power/sensors/sensor_monitoring.dm
@@ -6,7 +6,6 @@
/obj/machinery/computer/power_monitor
name = "Power Monitoring Console"
desc = "Computer designed to remotely monitor power levels around the station"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "power_key"
icon_screen = "power:0"
light_color = "#ffcc33"
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index 8786930e2f8..88c4ca34ac2 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -28,7 +28,6 @@
/obj/machinery/computer/turbine_computer
name = "Gas turbine control computer"
desc = "A computer to remotely control a gas turbine"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "tech_key"
icon_screen = "turbinecomp"
circuit = /obj/item/weapon/circuitboard/turbine_control
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 75d574ed632..9cb7292baf8 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -182,7 +182,11 @@
if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot)
handle_suicide(user)
else if(user.a_intent == I_HURT) //point blank shooting
- Fire(A, user, pointblank=1)
+ if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A && A != user)
+ PreFire(A,user) //They're using the new gun system, locate what they're aiming at.
+ return
+ else
+ Fire(A, user, pointblank=1)
else
return ..() //Pistolwhippin'
@@ -326,6 +330,8 @@
user.setMoveCooldown(move_delay)
next_fire_time = world.time + fire_delay
+ accuracy = initial(accuracy) //Reset the gun's accuracy
+
if(muzzle_flash)
set_light(0)
@@ -396,6 +402,8 @@
//update timing
next_fire_time = world.time + fire_delay
+ accuracy = initial(accuracy) //Reset the gun's accuracy
+
if(muzzle_flash)
set_light(0)
@@ -425,21 +433,21 @@
/obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
if(silenced)
playsound(user, fire_sound, 10, 1)
+ to_chat(user, "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]")
+ for(var/mob/living/L in oview(2,user))
+ if(L.stat)
+ continue
+ if(L.blinded)
+ to_chat(L, "You hear a [fire_sound_text]!")
+ continue
+ to_chat(L, "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]")
else
playsound(user, fire_sound, 50, 1)
-
- if(reflex)
- user.visible_message(
- "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""] by reflex!",
- "You fire \the [src] by reflex!",
- "You hear a [fire_sound_text]!"
- )
- else
- user.visible_message(
- "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""]!",
- "You fire \the [src]!",
- "You hear a [fire_sound_text]!"
- )
+ user.visible_message(
+ "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]",
+ "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]",
+ "You hear a [fire_sound_text]!"
+ )
if(muzzle_flash)
set_light(muzzle_flash)
@@ -482,11 +490,11 @@
// Certain statuses make it harder to aim, blindness especially. Same chances as melee, however guns accuracy uses multiples of 15.
if(user.eye_blind)
- accuracy -= 5
+ P.accuracy -= 5
if(user.eye_blurry)
- accuracy -= 2
+ P.accuracy -= 2
if(user.confused)
- accuracy -= 3
+ P.accuracy -= 3
//accuracy bonus from aiming
if (aim_targets && (target in aim_targets))
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index 6fd294f9284..604c936172b 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -28,6 +28,7 @@
name = "practice laser carbine"
desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice."
projectile_type = /obj/item/projectile/beam/practice
+ charge_cost = 48
cell_type = /obj/item/weapon/cell/device
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index faafd2e8c95..8fbfc0e6579 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -21,7 +21,7 @@
item_state = null
w_class = ITEMSIZE_NORMAL
force = 5
- slot_flags = SLOT_BELT
+ slot_flags = SLOT_BELT|SLOT_HOLSTER
charge_cost = 480
projectile_type = /obj/item/projectile/ion
diff --git a/code/modules/projectiles/guns/projectile/boltaction.dm b/code/modules/projectiles/guns/projectile/boltaction.dm
index f96dfd22eae..e07c45294cd 100644
--- a/code/modules/projectiles/guns/projectile/boltaction.dm
+++ b/code/modules/projectiles/guns/projectile/boltaction.dm
@@ -49,4 +49,19 @@
desc = "The firepower of a Mosin, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds."
user << "You shorten the barrel and stock of \the [src]!"
else
- ..()
\ No newline at end of file
+ ..()
+
+
+//Lever actions are the same thing, but bigger.
+/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever
+ name = "lever-action rifle"
+ desc = "A reproduction of an almost ancient weapon design from the 19th century. This one uses a lever-action to move new rounds into the chamber. Uses 5.56mm rounds."
+ item_state = "leveraction"
+ icon_state = "leveraction"
+ fire_sound = 'sound/weapons/rifleshot.ogg'
+ max_shells = 5
+ caliber = "a556"
+ origin_tech = list(TECH_COMBAT = 1)// Old as shit rifle doesn't have very good tech.
+ ammo_type = /obj/item/ammo_casing/a556
+ load_method = SINGLE_CASING|SPEEDLOADER
+ action_sound = 'sound/weapons/riflebolt.ogg'
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 750164a2602..f5a7460cc32 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -173,7 +173,7 @@
return
//roll to-hit
- miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.evasion), 0)
+ miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.get_evasion()), 0)
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss
var/result = PROJECTILE_FORCE_MISS
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index 54a2d301c7f..033b4065102 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -29,8 +29,8 @@
flash_strength *= H.species.flash_mod
if(flash_strength > 0)
- H.confused = max(H.confused, flash_strength + 5)
- H.eye_blind = max(H.eye_blind, flash_strength)
+ H.Confuse(flash_strength + 5)
+ H.Blind(flash_strength)
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
H.adjustHalLoss(22 * (flash_strength / 5)) // Five flashes to stun. Bit weaker than melee flashes due to being ranged.
@@ -146,9 +146,9 @@
var/ear_safety = 0
ear_safety = M.get_ear_protection()
if(ear_safety == 1)
- M.confused += 150
+ M.Confuse(150)
else if (ear_safety > 1)
- M.confused += 30
+ M.Confuse(30)
else if (!ear_safety)
M.Stun(10)
M.Weaken(2)
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index b507afc3167..dd81d713fe3 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -150,7 +150,7 @@
on_hit(var/atom/target, var/blocked = 0)
if(ishuman(target))
var/mob/living/carbon/human/M = target
- M.confused += rand(5,8)
+ M.Confuse(rand(5,8))
/obj/item/projectile/chameleon
name = "bullet"
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
index 091842663d2..d0be0469c10 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
@@ -95,7 +95,9 @@
if(alien == IS_SKRELL)
strength_mod *= 5
if(alien == IS_TAJARA)
- strength_mod *= 1.75
+ strength_mod *= 1.25
+ if(alien == IS_UNATHI)
+ strength_mod *= 0.75
if(alien == IS_DIONA)
strength_mod = 0
@@ -106,7 +108,7 @@
if(dose * strength_mod >= strength * 2) // Slurring
M.slurring = max(M.slurring, 30)
if(dose * strength_mod >= strength * 3) // Confusion - walking in random directions
- M.confused = max(M.confused, 20)
+ M.Confuse(20)
if(dose * strength_mod >= strength * 4) // Blurry vision
M.eye_blurry = max(M.eye_blurry, 10)
if(dose * strength_mod >= strength * 5) // Drowsyness - periodically falling asleep
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
index 95f661d7a54..a5469149307 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -376,7 +376,7 @@
else if(eyes_covered)
M << "Your [safe_thing] protect you from most of the pepperspray!"
M.eye_blurry = max(M.eye_blurry, effective_strength * 3)
- M.eye_blind = max(M.eye_blind, effective_strength)
+ M.Blind(effective_strength)
M.Stun(5)
M.Weaken(5)
return
@@ -387,7 +387,7 @@
else // Oh dear :D
M << "You're sprayed directly in the eyes with pepperspray!"
M.eye_blurry = max(M.eye_blurry, effective_strength * 5)
- M.eye_blind = max(M.eye_blind, effective_strength * 2)
+ M.Blind(effective_strength * 2)
M.Stun(5)
M.Weaken(5)
return
@@ -1166,7 +1166,7 @@
if(M.dizziness)
M.dizziness = max(0, M.dizziness - 15)
if(M.confused)
- M.confused = max(0, M.confused - 5)
+ M.Confuse(-5)
/datum/reagent/drink/dry_ramen
name = "Dry Ramen"
@@ -1799,6 +1799,7 @@
reagent_state = LIQUID
color = "#7F00FF"
strength = 10
+ druggy = 15
glass_name = "Pan-Galactic Gargle Blaster"
glass_desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy."
@@ -2232,3 +2233,26 @@
glass_name = "special blend whiskey"
glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
+/datum/reagent/ethanol/unathiliquor
+ name = "Redeemer's Brew"
+ id = "unathiliquor"
+ description = "This barely qualifies as a drink, and could give jetfuel a run for its money. Also known to cause feelings of euphoria and numbness."
+ taste_description = "spiced numbness"
+ color = "#242424"
+ strength = 5
+
+ glass_name = "unathi liquor"
+ glass_desc = "This barely qualifies as a drink, and may cause euphoria and numbness. Imbimber beware!"
+
+/datum/reagent/ethanol/unathiliquor/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
+ ..()
+ if(alien == IS_DIONA)
+ return
+
+ var/drug_strength = 10
+ if(alien == IS_SKRELL)
+ drug_strength = drug_strength * 0.8
+
+ M.druggy = max(M.druggy, drug_strength)
+ if(prob(10) && isturf(M.loc) && !istype(M.loc, /turf/space) && M.canmove && !M.restrained())
+ step(M, pick(cardinal))
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
index e0307e07cc3..ef6d8bb4287 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
@@ -258,7 +258,7 @@
/datum/reagent/oxycodone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.add_chemical_effect(CE_PAINKILLER, 200)
M.eye_blurry += 10
- M.confused += 5
+ M.Confuse(5)
/datum/reagent/oxycodone/overdose(var/mob/living/carbon/M, var/alien)
..()
@@ -319,7 +319,7 @@
/datum/reagent/imidazoline/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.eye_blurry = max(M.eye_blurry - 5, 0)
- M.eye_blind = max(M.eye_blind - 5, 0)
+ M.AdjustBlinded(-5)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
@@ -349,7 +349,7 @@
continue
if(I.damage > 0) //Peridaxon heals only non-robotic organs
I.damage = max(I.damage - removed, 0)
- H.confused += 5
+ H.Confuse(5)
if(I.damage <= 5 && I.organ_tag == O_EYES)
H.eye_blurry += 10 //Eyes need to reset, or something
H.sdisabilities &= ~BLIND
@@ -441,7 +441,7 @@
M.dizziness = 0
M.drowsyness = 0
M.stuttering = 0
- M.confused = 0
+ M.SetConfused(0)
if(M.ingested)
for(var/datum/reagent/R in M.ingested.reagent_list)
if(istype(R, /datum/reagent/ethanol))
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
index 4f8e17cb1e6..0a7c78f9527 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
@@ -133,7 +133,7 @@
M.disabilities = 0
M.sdisabilities = 0
M.eye_blurry = 0
- M.eye_blind = 0
+ M.SetBlinded(0)
M.SetWeakened(0)
M.SetStunned(0)
M.SetParalysis(0)
@@ -141,7 +141,7 @@
M.dizziness = 0
M.drowsyness = 0
M.stuttering = 0
- M.confused = 0
+ M.SetConfused(0)
M.sleeping = 0
M.jitteriness = 0
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
index 6e34257e4a4..12540c2d049 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
@@ -403,7 +403,7 @@
effective_dose *= 2
if(effective_dose == metabolism)
- M.confused += 2
+ M.Confuse(2)
M.drowsyness += 2
else if(effective_dose < 2 * threshold)
M.Weaken(30)
@@ -429,6 +429,7 @@
glass_name = "beer"
glass_desc = "A freezing pint of beer"
+
/* Drugs */
/datum/reagent/space_drugs
@@ -490,7 +491,7 @@
if(alien == IS_SKRELL)
drug_strength = drug_strength * 0.8
M.make_dizzy(drug_strength)
- M.confused = max(M.confused, drug_strength * 5)
+ M.Confuse(drug_strength * 5)
/datum/reagent/impedrezene
name = "Impedrezene"
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 41ad4cb5c6c..e20ee9459f7 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -384,7 +384,7 @@
name = "Stimm"
id = "stimm"
result = "stimm"
- required_reagents = list("sugar" = 1, "fuel" = 1)
+ required_reagents = list("left4zed" = 1, "fuel" = 1)
catalysts = list("fuel" = 5)
result_amount = 2
diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm
index ce377c87091..16a1cb3b265 100644
--- a/code/modules/reagents/reagent_containers/borghydro.dm
+++ b/code/modules/reagents/reagent_containers/borghydro.dm
@@ -121,7 +121,7 @@
recharge_time = 3
volume = 60
possible_transfer_amounts = list(5, 10, 20, 30)
- reagent_ids = list("beer", "kahlua", "whiskey", "specialwhiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice")
+ reagent_ids = list("ale", "beer", "berryjuice", "coffee", "cognac", "cola", "dr_gibb", "egg", "gin", "hot_coco", "ice", "icetea", "kahlua", "lemonjuice", "lemon_lime", "limejuice", "mead", "milk", "mint", "orangejuice", "rum", "sodawater", "soymilk", "space_up", "spacemountainwind", "specialwhiskey", "sugar", "tea", "tequilla", "tomatojuice", "tonic", "vermouth", "vodka", "water", "watermelonjuice", "whiskey", "wine")
/obj/item/weapon/reagent_containers/borghypo/service/attack(var/mob/M, var/mob/user)
return
diff --git a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
index 3300eb91d6e..2dcdd126057 100644
--- a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
@@ -407,6 +407,16 @@
..()
reagents.add_reagent("pwine", 100)
+/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew
+ name = "Redeemer's Brew"
+ desc = "Just opening the top of this bottle makes you feel a bit tipsy. Not for the faint of heart."
+ icon_state = "redeemersbrew"
+ center_of_mass = list("x"=16, "y"=3)
+
+/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew/New()
+ ..()
+ reagents.add_reagent("unathiliquor", 100)
+
//////////////////////////JUICES AND STUFF ///////////////////////
/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index ed27e1a259b..bd670cc8bce 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -243,6 +243,12 @@
user.drop_from_inventory(src)
qdel(src)
return
+ else if(istype(D, /obj/item/weapon/wirecutters))
+ to_chat(user, "You cut a big hole in \the [src] with \the [D]. It's kinda useless as a bucket now.")
+ user.put_in_hands(new /obj/item/clothing/head/helmet/bucket)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
else if(istype(D, /obj/item/weapon/mop))
if(reagents.total_volume < 1)
user << "\The [src] is empty!"
diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm
index f7bc1d1c803..48721314294 100644
--- a/code/modules/shieldgen/emergency_shield.dm
+++ b/code/modules/shieldgen/emergency_shield.dm
@@ -290,7 +290,7 @@
else if(istype(W, /obj/item/stack/cable_coil) && malfunction && is_open)
var/obj/item/stack/cable_coil/coil = W
user << "You begin to replace the wires."
- //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage
+ //if(do_after(user, min(60, round( ((getMaxHealth()/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage
if(do_after(user, 30))
if (coil.use(1))
health = max_health
diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm
index b6857a3f823..980053bd5d9 100644
--- a/code/modules/shuttles/shuttle_console.dm
+++ b/code/modules/shuttles/shuttle_console.dm
@@ -1,6 +1,5 @@
/obj/machinery/computer/shuttle_control
name = "shuttle control console"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "atmos_key"
icon_screen = "shuttle"
circuit = null
diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm
index a28f03e8feb..515453f6a35 100644
--- a/code/modules/spells/spellbook.dm
+++ b/code/modules/spells/spellbook.dm
@@ -322,7 +322,7 @@
/obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob)
..()
user <<"You go blind!"
- user.eye_blind = 10
+ user.Blind(10)
/obj/item/weapon/spellbook/oneuse/mindswap
spell = /spell/targeted/mind_transfer
diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm
index 498d363408e..d9d581e0504 100644
--- a/code/modules/spells/targeted/targeted.dm
+++ b/code/modules/spells/targeted/targeted.dm
@@ -138,8 +138,8 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp
if(amt_weakened || amt_paralysis || amt_stunned)
if(target.buckled)
target.buckled = null
- target.eye_blind += amt_eye_blind
+ target.Blind(amt_eye_blind)
target.eye_blurry += amt_eye_blurry
target.dizziness += amt_dizziness
- target.confused += amt_confused
+ target.Confuse(amt_confused)
target.stuttering += amt_stuttering
\ No newline at end of file
diff --git a/code/modules/turbolift/turbolift.dm b/code/modules/turbolift/turbolift.dm
index 7d2f3c11a83..90273250cb5 100644
--- a/code/modules/turbolift/turbolift.dm
+++ b/code/modules/turbolift/turbolift.dm
@@ -108,7 +108,7 @@
current_floor = next_floor
control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.")
- return 1
+ return (next_floor.delay_time || move_delay || 30)
/datum/turbolift/proc/queue_move_to(var/datum/turbolift_floor/floor)
if(!floor || !(floor in floors) || (floor in queued_floors))
diff --git a/code/modules/turbolift/turbolift_areas.dm b/code/modules/turbolift/turbolift_areas.dm
index dbf568aec2e..f9d69cc16f7 100644
--- a/code/modules/turbolift/turbolift_areas.dm
+++ b/code/modules/turbolift/turbolift_areas.dm
@@ -9,3 +9,4 @@
var/lift_floor_name = null
var/lift_announce_str = "Ding!"
var/arrival_sound = 'sound/machines/ding.ogg'
+ var/delay_time
diff --git a/code/modules/turbolift/turbolift_console.dm b/code/modules/turbolift/turbolift_console.dm
index 4cbee6a7737..f6619516816 100644
--- a/code/modules/turbolift/turbolift_console.dm
+++ b/code/modules/turbolift/turbolift_console.dm
@@ -123,7 +123,7 @@
dat += "Emergency Stop"
dat += " "
- var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 230, 260)
+ var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 250, 320)
popup.set_content(jointext(dat, null))
popup.open()
return
diff --git a/code/modules/turbolift/turbolift_floor.dm b/code/modules/turbolift/turbolift_floor.dm
index 7761f092843..46e4dfa0f48 100644
--- a/code/modules/turbolift/turbolift_floor.dm
+++ b/code/modules/turbolift/turbolift_floor.dm
@@ -5,6 +5,7 @@
var/name
var/announce_str
var/arrival_sound
+ var/delay_time
var/list/doors = list()
var/obj/structure/lift/button/ext_panel
@@ -20,6 +21,7 @@
name = A.lift_floor_name ? A.lift_floor_name : A.name
announce_str = A.lift_announce_str
arrival_sound = A.arrival_sound
+ delay_time = A.delay_time
//called when a lift has queued this floor as a destination
/datum/turbolift_floor/proc/pending_move(var/datum/turbolift/lift)
diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm
index 2e2498f88db..8930bf34d62 100644
--- a/code/modules/turbolift/turbolift_map.dm
+++ b/code/modules/turbolift/turbolift_map.dm
@@ -221,7 +221,7 @@
var/turf/T = locate(int_panel_x, int_panel_y, uz)
lift.control_panel_interior = new(T, lift)
lift.control_panel_interior.set_dir(udir)
- lift.current_floor = lift.floors[uz]
+ lift.current_floor = lift.floors[1]
lift.open_doors()
diff --git a/code/modules/turbolift/turbolift_process.dm b/code/modules/turbolift/turbolift_process.dm
index 83ce1b9faf0..124049d42e4 100644
--- a/code/modules/turbolift/turbolift_process.dm
+++ b/code/modules/turbolift/turbolift_process.dm
@@ -20,16 +20,17 @@ var/datum/controller/process/turbolift/turbolift_controller
continue
spawn(0)
lift.busy = 1
- if(!lift.do_move())
+ var/floor_delay
+ if(!(floor_delay = lift.do_move()))
moving_lifts[liftref] = null
moving_lifts -= liftref
if(lift.target_floor)
lift.target_floor.ext_panel.reset()
lift.target_floor = null
else
- lift_is_moving(lift)
+ lift_is_moving(lift,floor_delay)
lift.busy = 0
SCHECK
-/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift)
- moving_lifts["\ref[lift]"] = world.time + lift.move_delay
+/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift,var/floor_delay)
+ moving_lifts["\ref[lift]"] = world.time + floor_delay
diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm
index 5c2db9f3deb..1ece0248335 100644
--- a/code/modules/ventcrawl/ventcrawl.dm
+++ b/code/modules/ventcrawl/ventcrawl.dm
@@ -44,10 +44,15 @@ var/list/ventcrawl_machinery = list(
/mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item)
if(carried_item == ability_master)
return 1
+
+ var/list/allowed = list()
for(var/type in can_enter_vent_with)
- if(istype(carried_item, can_enter_vent_with))
- return get_inventory_slot(carried_item) == 0
- return 0
+ var/list/types = typesof(type)
+ allowed += types
+
+ if(carried_item.type in allowed)
+ if(get_inventory_slot(carried_item) == 0)
+ return 1
/mob/living/carbon/is_allowed_vent_crawl_item(var/obj/item/carried_item)
if(carried_item in internal_organs)
diff --git a/code/modules/virus2/curer.dm b/code/modules/virus2/curer.dm
index d6c5189f191..c297643e2a9 100644
--- a/code/modules/virus2/curer.dm
+++ b/code/modules/virus2/curer.dm
@@ -1,6 +1,5 @@
/obj/machinery/computer/curer
name = "cure research machine"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "med_key"
icon_screen = "dna"
circuit = /obj/item/weapon/circuitboard/curefab
diff --git a/code/modules/virus2/diseasesplicer.dm b/code/modules/virus2/diseasesplicer.dm
index 8d88639db3c..298dc49f27e 100644
--- a/code/modules/virus2/diseasesplicer.dm
+++ b/code/modules/virus2/diseasesplicer.dm
@@ -1,6 +1,5 @@
/obj/machinery/computer/diseasesplicer
name = "disease splicer"
- icon = 'icons/obj/computer.dmi'
icon_keyboard = "med_key"
icon_screen = "crew"
diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm
index 5243bae35f6..310f2231593 100644
--- a/code/modules/virus2/effect.dm
+++ b/code/modules/virus2/effect.dm
@@ -264,7 +264,7 @@
stage = 3
activate(var/mob/living/carbon/mob,var/multiplier)
mob << "You have trouble telling right and left apart all of a sudden."
- mob.confused += 10
+ mob.Confuse(10)
/datum/disease2/effect/mutation
name = "DNA Degradation"
diff --git a/code/modules/xenobio2/machinery/injector_computer.dm b/code/modules/xenobio2/machinery/injector_computer.dm
index 2f0144d37b3..6189a385e22 100644
--- a/code/modules/xenobio2/machinery/injector_computer.dm
+++ b/code/modules/xenobio2/machinery/injector_computer.dm
@@ -76,7 +76,7 @@
if(injector.occupant)
data["occupantHealth"] = injector.occupant.health
- data["occupantHealthMax"] = injector.occupant.maxHealth
+ data["occupantHealthMax"] = injector.occupant.getMaxHealth()
else
data["occupantHealth"] = null
data["occupantHealthMax"] = null
diff --git a/config/example/game_options.txt b/config/example/game_options.txt
index 035431b8bad..9e122db4238 100644
--- a/config/example/game_options.txt
+++ b/config/example/game_options.txt
@@ -57,6 +57,8 @@ ALIEN_DELAY 0
METROID_DELAY 0
ANIMAL_DELAY 0
+## Volume of footstep sound effects. Range: 1-100, Set to 0 to disable footstep sounds.
+FOOTSTEP_VOLUME 60
### Miscellaneous ###
diff --git a/html/changelog.html b/html/changelog.html
index 79d28487748..b3ff3223e11 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -53,6 +53,88 @@
-->
+ 25 April 2017
+ Anewbe updated:
+
+ - Cultist armor now has better protection from strange energies.
+ - Adds the ion pistol to the uplink.
+ - The ion pistol can now be holstered.
+ - Sprites on the smoking pipes should be fixed.
+
+ Atermonera updated:
+
+ - Brain type (Organic, cyborg, posi, or drone) is now displayed in all records.
+
+ Belsima updated:
+
+ - Changes relaymove() code in bodybags.
+ - Above tweak used to allow exiting bodybag while in closed morgue tray.
+
+ Leshana updated:
+
+ - Implements footstep sound system and adds sounds to various floor types including plating, tiles, wood, and carpet.
+
+ LorenLuke updated:
+
+ - Allows people who are bucked to give/receive items.
+ - Can click-drag people onto chairs/beds from 1 tile away to buckle them.
+ - Allows you to place tape masks/restraints back on the roll (roll is still infinite).
+ - Fixes ventcrawling for spiderbots/implants/etc.
+
+ Neerti updated:
+
+ - Drones will now spawn with an EIO-mandated ID card alongside their NT ID.
+ - Fabricate Clothing for Changelings costs one point instead of two, and is fabricated twice as fast.
+ - Dead changelings can no longer hear deadchat or freely ghost.
+ - Shrieks now share a 10 second cooldown.
+ - Lings cannot transform or shriek inside containers such as closets and pipes.
+ - Regen. Stasis timer adjusted to be between 2 to 4 minutes.
+ - Visible Camo. should end if the user is stunned.
+ - Visible Camo. now blocks AI tracking when active.
+ - Recursive Visible Camo. no longer gives true invis.
+ - Recursive Visible Camo. will allow the changeling to run while cloaked instead.
+ - Ling chemical meter on HUD now has a blinking exclaimation mark if below 20 chemicals, to warn that they cannot revive if they should die while still below 20.
+
+ Yoshax updated:
+
+ - Tape color is different now. Security tape is red rather than yellow, Engineering tape remains yellow and Atmos tape is a lighter cyan rather than blue.
+
+
+ 19 April 2017
+ Anewbe updated:
+
+ - Unathi ribcages now reach down to their lower torso.
+ - Unathi no longer have appendices or kidneys, the function of the kidneys is now a function of their liver.
+ - Unathi are more slightly more difficult to damage.
+ - Unathi now process medicine 15% slower. Additionally, it's harder for them to get drunk.
+ - Unathi age range is now 32 to 260.
+ - Unathi are not as slowed by heavy items.
+
+ Atermonera updated:
+
+ - Translators no longer try to translate null languages.
+
+ LorenLuke updated:
+
+ - Allows Blast doors to be attacked and broken like regular airlocks.
+ - Changelings can bank up to a maximum of 3 respecs at one time.
+ - Changelings begin with 2 respecs.
+ - Firing a silenced weapon gives a message in text to the user.
+
+ MagmaRam updated:
+
+ - Added instructions on how to use the changelog updating scripts.
+ - Updated in-game EVA manual.
+
+ Neerti updated:
+
+ - Adds makeshift armor for the head and chest regions. How protective they are depends on the material used to craft it. The helmet is made by using wirecutters on a bucket, then using a stack of material. The chestpiece is made by crafting two armor plate, using wires on one of them, then hiting one with the other.
+
+ Yoshax updated:
+
+ - Water such as the pool will no longer apply fire stacks when you enter, meaning you will no longer be flammable from swimming.
+
+
16 April 2017
Anewbe updated:
- Reagents
+ Blood Reagents
{{if data.occupant.reagents}}
{{for data.occupant.reagents}}
@@ -105,7 +105,20 @@ Used In File(s): \code\game\machinery\adv_med.dm
{{/for}}
{{else}}
- No reagents detected.
+ No blood reagents detected.
+ {{/if}}
+ Stomach Reagents
+ {{if data.occupant.ingested}}
+
+ {{for data.occupant.ingested}}
+
+ | {{:value.name}}: |
+ {{:value.amount}} |
+
+ {{/for}}
+
+ {{else}}
+ No stomach reagents detected.
{{/if}}
External Organs
diff --git a/nano/templates/holodeck.tmpl b/nano/templates/holodeck.tmpl
index 71d4ad56056..a91d5a60e51 100644
--- a/nano/templates/holodeck.tmpl
+++ b/nano/templates/holodeck.tmpl
@@ -5,7 +5,7 @@
Current Loaded Programs:
{{for data.supportedPrograms}}
- {{:helper.link(value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+ {{:helper.link(value, data.currentProgram == value ? 'check' : 'close', {'program' : value}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.
{{if data.isSilicon}}
@@ -22,7 +22,7 @@
{{if data.safetyDisabled}}
{{for data.restrictedPrograms}}
- {{:helper.link('Begin ' + value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+ {{:helper.link('Begin ' + value, data.currentProgram == value ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Ensure the holodeck is empty before testing.
Safety Protocols are DISABLED
diff --git a/nano/templates/pai_medrecords.tmpl b/nano/templates/pai_medrecords.tmpl
index 89926d3915b..24e00e949f1 100644
--- a/nano/templates/pai_medrecords.tmpl
+++ b/nano/templates/pai_medrecords.tmpl
@@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+ Entity Classification
+ {{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pai_secrecords.tmpl b/nano/templates/pai_secrecords.tmpl
index 51cb45dee2e..5ba1e4d90dc 100644
--- a/nano/templates/pai_secrecords.tmpl
+++ b/nano/templates/pai_secrecords.tmpl
@@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+ Entity Classification
+ {{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl
index 6cd3004654e..77f026a3495 100644
--- a/nano/templates/pda.tmpl
+++ b/nano/templates/pda.tmpl
@@ -568,6 +568,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm
{{if data.records.general_exists == 1}}
Name: {{:data.records.general.name}}
+ Entity Class: {{:data.records.general.brain_type}}
Sex: {{:data.records.general.sex}}
Species: {{:data.records.general.species}}
Age: {{:data.records.general.age}}
diff --git a/nano/templates/sleeper.tmpl b/nano/templates/sleeper.tmpl
index 49fb0ae8d75..7ee370e890f 100644
--- a/nano/templates/sleeper.tmpl
+++ b/nano/templates/sleeper.tmpl
@@ -88,4 +88,12 @@
{{/if}}
+
+
+ Stasis Level:
+
+
+ {{:helper.link(data.stasis, null, {'change_stasis' : 1})}}
+
+
{{/if}}
diff --git a/polaris.dme b/polaris.dme
index 28d9de7f22a..1df561601b3 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -32,6 +32,7 @@
#include "code\__defines\math_physics.dm"
#include "code\__defines\misc.dm"
#include "code\__defines\mobs.dm"
+#include "code\__defines\planets.dm"
#include "code\__defines\process_scheduler.dm"
#include "code\__defines\research.dm"
#include "code\__defines\species_languages.dm"
@@ -470,8 +471,6 @@
#include "code\game\gamemodes\technomancer\spells\aura\frost_aura.dm"
#include "code\game\gamemodes\technomancer\spells\aura\shock_aura.dm"
#include "code\game\gamemodes\technomancer\spells\aura\unstable_aura.dm"
-#include "code\game\gamemodes\technomancer\spells\insert\corona.dm"
-#include "code\game\gamemodes\technomancer\spells\insert\haste.dm"
#include "code\game\gamemodes\technomancer\spells\insert\insert.dm"
#include "code\game\gamemodes\technomancer\spells\insert\mend_burns.dm"
#include "code\game\gamemodes\technomancer\spells\insert\mend_metal.dm"
@@ -479,7 +478,10 @@
#include "code\game\gamemodes\technomancer\spells\insert\mend_wires.dm"
#include "code\game\gamemodes\technomancer\spells\insert\mend_wounds.dm"
#include "code\game\gamemodes\technomancer\spells\insert\purify.dm"
-#include "code\game\gamemodes\technomancer\spells\insert\repel_missiles.dm"
+#include "code\game\gamemodes\technomancer\spells\modifier\corona.dm"
+#include "code\game\gamemodes\technomancer\spells\modifier\haste.dm"
+#include "code\game\gamemodes\technomancer\spells\modifier\modifier.dm"
+#include "code\game\gamemodes\technomancer\spells\modifier\repel_missiles.dm"
#include "code\game\gamemodes\technomancer\spells\projectile\beam.dm"
#include "code\game\gamemodes\technomancer\spells\projectile\chain_lightning.dm"
#include "code\game\gamemodes\technomancer\spells\projectile\force_missile.dm"
@@ -898,6 +900,7 @@
#include "code\game\objects\items\weapons\material\foam.dm"
#include "code\game\objects\items\weapons\material\kitchen.dm"
#include "code\game\objects\items\weapons\material\knives.dm"
+#include "code\game\objects\items\weapons\material\material_armor.dm"
#include "code\game\objects\items\weapons\material\material_weapons.dm"
#include "code\game\objects\items\weapons\material\misc.dm"
#include "code\game\objects\items\weapons\material\shards.dm"
@@ -1506,6 +1509,7 @@
#include "code\modules\mob\mob_helpers.dm"
#include "code\modules\mob\mob_movement.dm"
#include "code\modules\mob\mob_transformation_simple.dm"
+#include "code\modules\mob\modifiers.dm"
#include "code\modules\mob\say.dm"
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\typing_indicator.dm"
@@ -1792,6 +1796,7 @@
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\seromi.dm"
#include "code\modules\organs\subtypes\standard.dm"
+#include "code\modules\organs\subtypes\unathi.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
#include "code\modules\organs\subtypes\vox.dm"
#include "code\modules\overmap\_defines.dm"
diff --git a/sound/effects/footstep/carpet1.ogg b/sound/effects/footstep/carpet1.ogg
new file mode 100644
index 00000000000..2735a9bf3dc
Binary files /dev/null and b/sound/effects/footstep/carpet1.ogg differ
diff --git a/sound/effects/footstep/carpet2.ogg b/sound/effects/footstep/carpet2.ogg
new file mode 100644
index 00000000000..07e5f2320aa
Binary files /dev/null and b/sound/effects/footstep/carpet2.ogg differ
diff --git a/sound/effects/footstep/carpet3.ogg b/sound/effects/footstep/carpet3.ogg
new file mode 100644
index 00000000000..edb0193f6e2
Binary files /dev/null and b/sound/effects/footstep/carpet3.ogg differ
diff --git a/sound/effects/footstep/carpet4.ogg b/sound/effects/footstep/carpet4.ogg
new file mode 100644
index 00000000000..c9598e2b736
Binary files /dev/null and b/sound/effects/footstep/carpet4.ogg differ
diff --git a/sound/effects/footstep/carpet5.ogg b/sound/effects/footstep/carpet5.ogg
new file mode 100644
index 00000000000..076818323ae
Binary files /dev/null and b/sound/effects/footstep/carpet5.ogg differ
diff --git a/sound/effects/footstep/floor1.ogg b/sound/effects/footstep/floor1.ogg
new file mode 100644
index 00000000000..1e3e1558399
Binary files /dev/null and b/sound/effects/footstep/floor1.ogg differ
diff --git a/sound/effects/footstep/floor2.ogg b/sound/effects/footstep/floor2.ogg
new file mode 100644
index 00000000000..cce5a25d829
Binary files /dev/null and b/sound/effects/footstep/floor2.ogg differ
diff --git a/sound/effects/footstep/floor3.ogg b/sound/effects/footstep/floor3.ogg
new file mode 100644
index 00000000000..16ab67f729c
Binary files /dev/null and b/sound/effects/footstep/floor3.ogg differ
diff --git a/sound/effects/footstep/floor4.ogg b/sound/effects/footstep/floor4.ogg
new file mode 100644
index 00000000000..9ef15430ff8
Binary files /dev/null and b/sound/effects/footstep/floor4.ogg differ
diff --git a/sound/effects/footstep/floor5.ogg b/sound/effects/footstep/floor5.ogg
new file mode 100644
index 00000000000..0f6a66057de
Binary files /dev/null and b/sound/effects/footstep/floor5.ogg differ
diff --git a/sound/effects/footstep/hull1.ogg b/sound/effects/footstep/hull1.ogg
new file mode 100644
index 00000000000..615df6c5502
Binary files /dev/null and b/sound/effects/footstep/hull1.ogg differ
diff --git a/sound/effects/footstep/hull2.ogg b/sound/effects/footstep/hull2.ogg
new file mode 100644
index 00000000000..3aecb743f70
Binary files /dev/null and b/sound/effects/footstep/hull2.ogg differ
diff --git a/sound/effects/footstep/hull3.ogg b/sound/effects/footstep/hull3.ogg
new file mode 100644
index 00000000000..03339131f63
Binary files /dev/null and b/sound/effects/footstep/hull3.ogg differ
diff --git a/sound/effects/footstep/hull4.ogg b/sound/effects/footstep/hull4.ogg
new file mode 100644
index 00000000000..2fba89d3185
Binary files /dev/null and b/sound/effects/footstep/hull4.ogg differ
diff --git a/sound/effects/footstep/hull5.ogg b/sound/effects/footstep/hull5.ogg
new file mode 100644
index 00000000000..10c5912b97a
Binary files /dev/null and b/sound/effects/footstep/hull5.ogg differ
diff --git a/sound/effects/footstep/plating1.ogg b/sound/effects/footstep/plating1.ogg
new file mode 100644
index 00000000000..0df770e6638
Binary files /dev/null and b/sound/effects/footstep/plating1.ogg differ
diff --git a/sound/effects/footstep/plating2.ogg b/sound/effects/footstep/plating2.ogg
new file mode 100644
index 00000000000..314b9133d25
Binary files /dev/null and b/sound/effects/footstep/plating2.ogg differ
diff --git a/sound/effects/footstep/plating3.ogg b/sound/effects/footstep/plating3.ogg
new file mode 100644
index 00000000000..5c571d77eb6
Binary files /dev/null and b/sound/effects/footstep/plating3.ogg differ
diff --git a/sound/effects/footstep/plating4.ogg b/sound/effects/footstep/plating4.ogg
new file mode 100644
index 00000000000..5953262764b
Binary files /dev/null and b/sound/effects/footstep/plating4.ogg differ
diff --git a/sound/effects/footstep/plating5.ogg b/sound/effects/footstep/plating5.ogg
new file mode 100644
index 00000000000..4676a637a6d
Binary files /dev/null and b/sound/effects/footstep/plating5.ogg differ
diff --git a/sound/effects/footstep/wood1.ogg b/sound/effects/footstep/wood1.ogg
new file mode 100644
index 00000000000..c76fc423fc2
Binary files /dev/null and b/sound/effects/footstep/wood1.ogg differ
diff --git a/sound/effects/footstep/wood2.ogg b/sound/effects/footstep/wood2.ogg
new file mode 100644
index 00000000000..71dc1aa9679
Binary files /dev/null and b/sound/effects/footstep/wood2.ogg differ
diff --git a/sound/effects/footstep/wood3.ogg b/sound/effects/footstep/wood3.ogg
new file mode 100644
index 00000000000..bf86889006e
Binary files /dev/null and b/sound/effects/footstep/wood3.ogg differ
diff --git a/sound/effects/footstep/wood4.ogg b/sound/effects/footstep/wood4.ogg
new file mode 100644
index 00000000000..44734425ce6
Binary files /dev/null and b/sound/effects/footstep/wood4.ogg differ
diff --git a/sound/effects/footstep/wood5.ogg b/sound/effects/footstep/wood5.ogg
new file mode 100644
index 00000000000..5ad4fa81e77
Binary files /dev/null and b/sound/effects/footstep/wood5.ogg differ
|
|
|
|
|