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 e8fe96ae6c..3d0235fab9 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 1c54fb0f4c..8c435f5845 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 ca56ce168d..4d29a56b89 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 54c94d8684..465884b2ca 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 1a67778fdf..bd9c66dbae 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 cb0f8a5552..0a337f4df8 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 d390a7f163..4bcc43bbec 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 d36f03b525..ba7193b69b 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 57a662db46..bb4228397d 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 a314bed273..6b77a274bf 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 d1ab11e706..5d0f707ae8 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 6441a5e72a..672a6a425b 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 6aeecfc8e5..e78cba3568 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 209e3bb228..3d899377cc 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 185de7f06d..cd38f9f1ce 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 ae48142b4d..a18edbc5fa 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 ffe30bf3fd..1e10e03f4f 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 a6da9bfa00..00a0654cc1 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 967c03252f..6aec830c89 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 7950200137..f456a95d73 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 1450fa94ce..4d77da4ae9 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 674e746c28..667adfc712 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 8bfe2dffca..42c8e4949b 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 b553f4416c..62d7e7b311 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 1bd7f9349a..74d9a4b8ed 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 243d301289..5d883784aa 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 90fb43724e..5de1ba1396 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 15f3310322..db4e890d60 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 10a847b469..d404b5cd44 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 76c4f9e768..ee2d2f2c57 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 1190d7f812..62941c24f0 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 cf55cbd706..db24be3c0a 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 b13b5e6ac2..87b635ce50 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 593b1d9237..9545504f84 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 0000000000..1041fb5d1f
--- /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 5edd1c77b5..2d85bc0a66 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 bb0ebfdd0c..8008959460 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 a9f2a15dea..9b4cb3ca9b 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 b6fc2f4251..04e5aa909b 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 1080e1b8fb..8c4067187f 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 cd11af3400..e6abdcb366 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 bd28078782..42ee6af2e3 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 779f76fc93..2170ea3019 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 3a7c1afdf0..336a34b2fe 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 da69406157..75c7e68083 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 77eb419ed1..781ddeeb7f 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 c13b4606d3..3f2e0064f2 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 ce4ffa44c0..7d9159d04a 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 ec84ee4232..6e23d74bbb 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 affa55ce10..439e1f1b7f 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 ffea7b7fab..099aa43978 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 497b145190..e3d781df29 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 137cab1a01..4fb748f73a 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 978a5c13e6..5a311c5172 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 ff0f8ae077..e23c3c0c26 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 d08726371a..f090312320 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 d9dc2f2e54..5d734c9d95 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 e09c062ab0..d0f9a8165c 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 dcb5b4e499..f3a9efb6d2 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 eb18581551..ff0b95f365 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 9cb77f2a4b..4ae4361a21 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 c404f61581..7089c19d51 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 88b804f80a..5c49e1817c 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 87bb4cd182..1593297734 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 8220162be7..a875917441 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 c6134f9bd1..059c699e50 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 9e04e24db5..431faa241f 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 baa5738d4e..456fae889f 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 beb44bf535..759b1586eb 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 65bae751e0..4ee5145179 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 7b3256e06b..3480a83a4a 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 d0c26baf66..e3b69d31cd 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 c159522e97..a90a3f57a3 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 72766c0c48..322ee2f9e0 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 b1a19f4a40..72d779b621 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 fa8c6d9615..54d72e0718 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 11f6021c75..68fb129108 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 4610b4e00f..921b28d733 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 128dc17332..e531e5208f 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 07562ad190..4384151cbd 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 fdb0b012ef..3a451bff44 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 85942fcb4e..44e0d00280 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 8c61b68a3e..873934c0c7 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 a7764d3d1d..fd48b912a0 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 3f41f21ce5..bac50b1e62 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 14c8efbbad..6b07140211 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 ee0c867ffb..b4a47d2e47 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 1c4f4e841e..66abc50cab 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 fa3d19ebab..30ee7c64d6 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 86bbdebc15..61b13316b8 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 0a1817e6b2..636d6af792 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 7682f675b0..cb49001d3c 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 2ffec34288..98f8f81d9c 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 e6563a28a1..2738686c38 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 8a8650aa9b..f547cba9fc 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 5015e19940..e49236af94 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 a84a2889dc..1924bd5e78 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 7bbc4110dd..0f393a9417 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 3c0bfbdbad..5fdea4a0e6 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 933596ef5e..9e20d49a44 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 552319e6fe..0fa139c36f 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 9271167d40..2209c63008 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 ab55807be8..0b47ba7870 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 8a49ed8922..66e1278e22 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 e6b7f2979d..d8913e7b5b 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 1aef4eca81..80c0dbc505 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 349f27114b..8c12226e3d 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 9dacf9924c..a9464c595e 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 1b051e029f..58a81ca7a7 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 738e996967..40b1852528 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 3d1ae1bd02..06de6b4d14 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 1bb202d1a0..95b7e81a17 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 c24100476c..1cc1a85108 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 05087c4036..7b5e77f5c3 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 79f389821e..ae700d60b7 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 af20f04201..3ad6260813 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 714bde7096..f16af92a74 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 1901902c80..a63590acf8 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 f3cd084ffa..80f68b979d 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 4327840a47..ba5b24dbe7 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 476a8b6810..a553d4309c 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 0000000000..8e1f9e2f6f
--- /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 e76c6516aa..0ed4e5364a 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 586b624260..122e1aa4cd 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 1cb5b9b4da..7c1fee0525 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 5727808276..18bb91a9e4 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 8389df7112..b6845d076f 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 0f5ea190f2..c6670d2a30 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 6514092dfc..1390c89b29 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 2a2b8305d3..4febf8f479 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 daa0a88f76..6b7459500b 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 63c6da6409..20390a3555 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 244c0b7971..cfc0910901 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 25db1953d6..69d14c1dd1 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 0000000000..212330577c
--- /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 53a07f228b..4c308ca930 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 303d05f509..e35646ce7f 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 c98383a242..5e392be796 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 671d57e04e..27bf4c0ab7 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 fe51b4152e..d6ae824fd1 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 7697fdf6a4..13213c2e7e 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 597ced19db..21aecc59ea 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 8786930e2f..88c4ca34ac 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 75d574ed63..9cb7292baf 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 6fd294f928..604c936172 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 faafd2e8c9..8fbfc0e657 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 f96dfd22ea..e07c45294c 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 750164a260..f5a7460cc3 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 54a2d301c7..033b406510 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 b507afc316..dd81d713fe 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 091842663d..d0be0469c1 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 95f661d7a5..a546914930 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 e0307e07cc..ef6d8bb428 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 4f8e17cb1e..0a7c78f952 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 6e34257e4a..12540c2d04 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 41ad4cb5c6..e20ee9459f 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 ce377c8709..16a1cb3b26 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 3300eb91d6..2dcdd12605 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 ed27e1a259..bd670cc8bc 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 f7bc1d1c80..4872131429 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 b6857a3f82..980053bd5d 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 a28f03e8fe..515453f6a3 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 498d363408..d9d581e050 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 7d2f3c11a8..90273250cb 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 dbf568aec2..f9d69cc16f 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 4cbee6a773..f661951681 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 7761f09284..46e4dfa0f4 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 2e2498f88d..8930bf34d6 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 83ce1b9faf..124049d42e 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 5c2db9f3de..1ece024833 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 d6c5189f19..c297643e2a 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 8d88639db3..298dc49f27 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 5243bae35f..310f223159 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 2f0144d37b..6189a385e2 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 035431b8ba..9e122db423 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 79d2848774..b3ff3223e1 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 71d4ad5605..a91d5a60e5 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 89926d3915..24e00e949f 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 51cb45dee2..5ba1e4d90d 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 6cd3004654..77f026a349 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 49fb0ae8d7..7ee370e890 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 28d9de7f22..1df561601b 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 0000000000..2735a9bf3d
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 0000000000..07e5f2320a
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 0000000000..edb0193f6e
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 0000000000..c9598e2b73
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 0000000000..076818323a
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 0000000000..1e3e155839
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 0000000000..cce5a25d82
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 0000000000..16ab67f729
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 0000000000..9ef15430ff
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 0000000000..0f6a66057d
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 0000000000..615df6c550
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 0000000000..3aecb743f7
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 0000000000..03339131f6
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 0000000000..2fba89d318
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 0000000000..10c5912b97
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 0000000000..0df770e663
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 0000000000..314b9133d2
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 0000000000..5c571d77eb
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 0000000000..5953262764
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 0000000000..4676a637a6
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 0000000000..c76fc423fc
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 0000000000..71dc1aa967
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 0000000000..bf86889006
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 0000000000..44734425ce
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 0000000000..5ad4fa81e7
Binary files /dev/null and b/sound/effects/footstep/wood5.ogg differ
|
|
|
|
|