Merge remote-tracking branch 'upstream/dev-freeze' into dev

Conflicts:
	.travis.yml
	code/modules/mob/living/carbon/breathe.dm
	code/modules/mob/living/carbon/human/life.dm
	code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
	html/changelogs/.all_changelog.yml
This commit is contained in:
PsiOmegaDelta
2015-10-27 13:08:33 +01:00
11 changed files with 1527 additions and 1455 deletions

View File

@@ -558,7 +558,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/y = min(world.maxy, max(1, A.y + dy))
return locate(x,y,A.z)
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value.
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. Lower bound takes priority.
/proc/between(var/low, var/middle, var/high)
return max(min(middle, high), low)

View File

@@ -4,14 +4,76 @@
/obj/effect/effect/smoke/chem
icon = 'icons/effects/chemsmoke.dmi'
opacity = 0
layer = 6
time_to_live = 300
pass_flags = PASSTABLE | PASSGRILLE | PASSGLASS //PASSGLASS is fine here, it's just so the visual effect can "flow" around glass
var/splash_amount = 10 //atoms moving through a smoke cloud get splashed with up to 10 units of reagent
var/turf/destination
/obj/effect/effect/smoke/chem/New()
/obj/effect/effect/smoke/chem/New(var/newloc, smoke_duration, turf/dest_turf = null, icon/cached_icon = null)
time_to_live = smoke_duration
..()
create_reagents(500)
return
if(cached_icon)
icon = cached_icon
set_dir(pick(cardinal))
pixel_x = -32 + rand(-8, 8)
pixel_y = -32 + rand(-8, 8)
//switching opacity on after the smoke has spawned, and then turning it off before it is deleted results in cleaner
//lighting and view range updates (Is this still true with the new lighting system?)
opacity = 1
//float over to our destination, if we have one
destination = dest_turf
if(destination)
walk_to(src, destination)
/obj/effect/effect/smoke/chem/Destroy()
opacity = 0
fadeOut()
..()
/obj/effect/effect/smoke/chem/Move()
var/list/oldlocs = view(1, src)
. = ..()
if(.)
for(var/turf/T in view(1, src) - oldlocs)
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
if(loc == destination)
bound_width = 96
bound_height = 96
/obj/effect/effect/smoke/chem/Crossed(atom/movable/AM)
..()
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
/obj/effect/effect/smoke/chem/proc/initial_splash()
for(var/turf/T in view(1, src))
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
// Fades out the smoke smoothly using it's alpha variable.
/obj/effect/effect/smoke/chem/proc/fadeOut(var/frames = 16)
if(!alpha) return //already transparent
frames = max(frames, 1) //We will just assume that by 0 frames, the coder meant "during one frame".
var/alpha_step = round(alpha / frames)
while(alpha > 0)
alpha = max(0, alpha - alpha_step)
sleep(world.tick_lag)
/////////////////////////////////////////////
// Chem Smoke Effect System
/////////////////////////////////////////////
/datum/effect/effect/system/smoke_spread/chem
smoke_type = /obj/effect/effect/smoke/chem
var/obj/chemholder
@@ -115,13 +177,21 @@
else
I = icon('icons/effects/96x96.dmi', "smoke")
//Calculate smoke duration
var/smoke_duration = 150
var/pressure = 0
var/datum/gas_mixture/environment = location.return_air()
if(environment) pressure = environment.return_pressure()
smoke_duration = between(5, smoke_duration*pressure/(ONE_ATMOSPHERE/3), smoke_duration)
var/const/arcLength = 2.3559 //distance between each smoke cloud
for(var/i = 0, i < range, i++) //calculate positions for smoke coverage - then spawn smoke
var/radius = i * 1.5
if(!radius)
spawn(0)
spawnSmoke(location, I, 1)
spawnSmoke(location, I, 1, 1)
continue
var/offset = 0
@@ -146,43 +216,26 @@
// Randomizes and spawns the smoke effect.
// Also handles deleting the smoke once the effect is finished.
//------------------------------------------
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1, var/obj/effect/effect/smoke/chem/passed_smoke)
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/smoke_duration, var/dist = 1, var/splash_initial=0, var/obj/effect/effect/smoke/chem/passed_smoke)
var/obj/effect/effect/smoke/chem/smoke
if(passed_smoke)
smoke = passed_smoke
else
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location)
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, smoke_duration + rand(0, 20), T, I))
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
smoke.icon = I
smoke.layer = 6
smoke.set_dir(pick(cardinal))
smoke.pixel_x = -32 + rand(-8, 8)
smoke.pixel_y = -32 + rand(-8, 8)
walk_to(smoke, T)
smoke.opacity = 1 //switching opacity on after the smoke has spawned, and then
sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner
smoke.opacity = 0 // lighting and view range updates
fadeOut(smoke)
qdel(src)
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1)
//Kinda ugly, but needed unless the system is reworked
if(splash_initial)
smoke.initial_splash()
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/smoke_duration, var/icon/I, var/dist = 1)
var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location)
spores.name = "cloud of [seed.seed_name] [seed.seed_noun]"
..(T, I, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/fadeOut(var/atom/A, var/frames = 16) // Fades out the smoke smoothly using it's alpha variable.
if(A.alpha == 0) //Handle already transparent case
return
if(frames == 0)
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
var/step = A.alpha / frames
for(var/i = 0, i < frames, i++)
A.alpha -= step
sleep(world.tick_lag)
return
..(T, I, smoke_duration, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/smokeFlow() // Smoke pathfinder. Uses a flood fill method based on zones to quickly check what turfs the smoke (airflow) can actually reach.

View File

@@ -65,13 +65,15 @@
//Handle possble chem smoke effect
/mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment)
if(wear_mask && (wear_mask.item_flags & BLOCK_GAS_SMOKE_EFFECT))
if(species && environment.return_pressure() < species.breath_pressure/5)
return //pressure is too low to even breathe in.
if(wear_mask && (wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT))
return
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
if(smoke.reagents.total_volume)
smoke.reagents.trans_to_mob(src, 10, CHEM_INGEST, copy = 1)
//maybe check air pressure here or something to see if breathing in smoke is even possible.
smoke.reagents.trans_to_mob(src, 5, CHEM_INGEST, copy = 1)
smoke.reagents.trans_to_mob(src, 5, CHEM_BLOOD, copy = 1)
// I dunno, maybe the reagents enter the blood stream through the lungs?
break // If they breathe in the nasty stuff once, no need to continue checking

View File

@@ -382,7 +382,7 @@
oxygen_alert = max(oxygen_alert, 1)
return 0
var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa
var/safe_pressure_min = species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa
// Lung damage increases the minimum safe pressure.
if(species.has_organ["lungs"])
@@ -974,11 +974,11 @@
for(var/atom/a in hallucinations)
qdel(a)
if(halloss > 100)
src << "<span class='notice'>You're in too much pain to keep going...</span>"
src.visible_message("<B>[src]</B> slumps to the ground, too weak to continue fighting.")
Paralyse(10)
setHalLoss(99)
if(halloss > 100)
src << "<span class='warning'>[species.halloss_message_self]</span>"
src.visible_message("<B>[src]</B> [species.halloss_message].")
Paralyse(10)
setHalLoss(99)
if(paralysis || sleeping)
blinded = 1

View File

@@ -68,9 +68,12 @@
var/death_sound
var/death_message = "seizes up and falls limp, their eyes dead and lifeless..."
var/knockout_message = "has been knocked unconscious!"
var/halloss_message = "slumps to the ground, too weak to continue fighting."
var/halloss_message_self = "You're in too much pain to keep going..."
// Environment tolerance/life processes vars.
var/reagent_tag //Used for metabolizing reagents.
var/breath_pressure = 16 // Minimum partial pressure safe for breathing, kPa
var/breath_type = "oxygen" // Non-oxygen gas breathed, if any.
var/poison_type = "phoron" // Poisonous air.
var/exhale_type = "carbon_dioxide" // Exhaled gas type.

View File

@@ -281,6 +281,8 @@
show_ssd = "flashing a 'system offline' glyph on their monitor"
death_message = "gives one shrill beep before falling lifeless."
knockout_message = "encounters a hardware fault and suddenly reboots!"
halloss_message = "encounters a hardware fault and suddenly reboots."
halloss_message_self = "ERROR: Unrecoverable machine check exception.<BR>System halted, rebooting..."
warning_low_pressure = 50
hazard_low_pressure = 0

View File

@@ -304,7 +304,7 @@
trans_to(target, amount, multiplier, copy)
/datum/reagents/proc/trans_id_to(var/atom/target, var/id, var/amount = 1)
if (!target || !target.reagents)
if (!target || !target.reagents || !target.simulated)
return
amount = min(amount, get_reagent_amount(id))
@@ -333,7 +333,7 @@
return
/datum/reagents/proc/touch_mob(var/mob/target)
if(!target || !istype(target))
if(!target || !istype(target) || !target.simulated)
return
for(var/datum/reagent/current in reagent_list)
@@ -342,7 +342,7 @@
update_total()
/datum/reagents/proc/touch_turf(var/turf/target)
if(!target || !istype(target))
if(!target || !istype(target) || !target.simulated)
return
for(var/datum/reagent/current in reagent_list)
@@ -351,7 +351,7 @@
update_total()
/datum/reagents/proc/touch_obj(var/obj/target)
if(!target || !istype(target))
if(!target || !istype(target) || !target.simulated)
return
for(var/datum/reagent/current in reagent_list)
@@ -370,7 +370,7 @@
return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy)
/datum/reagents/proc/trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder...
if(!target || !istype(target))
if(!target || !istype(target) || !target.simulated)
return
if(iscarbon(target))
var/mob/living/carbon/C = target
@@ -389,7 +389,7 @@
R.touch_mob(target)
/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it.
if(!target)
if(!target || !target.simulated)
return
var/datum/reagents/R = new /datum/reagents(amount * multiplier)
@@ -398,7 +398,7 @@
return
/datum/reagents/proc/trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch.
if(!target)
if(!target || !target.simulated)
return
if(!target.reagents)

View File

@@ -226,6 +226,10 @@
description = "This is what makes chilis hot."
reagent_state = LIQUID
color = "#B31008"
var/agony_dose = 5
var/agony_amount = 2
var/discomfort_message = "<span class='danger'>Your insides feel uncomfortably hot!</span>"
var/slime_temp_adj = 10
/datum/reagent/capsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
@@ -239,82 +243,82 @@
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & (NO_PAIN)))
return
if(dose < 5 && (dose == metabolism || prob(5)))
M << "<span class='danger'>Your insides feel uncomfortably hot!</span>"
if(dose >= 5)
M.apply_effect(2, AGONY, 0)
if(dose < agony_dose)
if(prob(5) || dose == metabolism) //dose == metabolism is a very hacky way of forcing the message the first time this procs
M << discomfort_message
else
M.apply_effect(agony_amount, AGONY, 0)
if(prob(5))
M.visible_message("<span class='warning'>[M] [pick("dry heaves!","coughs!","splutters!")]</span>", "<span class='danger'>You feel like your insides are burning!</span>")
M.custom_emote(2, "[pick("dry heaves!","coughs!","splutters!")]")
M << "<span class='danger'>You feel like your insides are burning!</span>"
if(istype(M, /mob/living/carbon/slime))
M.bodytemperature += rand(10, 25)
M.bodytemperature += rand(0, 15) + slime_temp_adj
holder.remove_reagent("frostoil", 5)
/datum/reagent/condensedcapsaicin
/datum/reagent/capsaicin/condensed
name = "Condensed Capsaicin"
id = "condensedcapsaicin"
description = "A chemical agent used for self-defense and in police work."
reagent_state = LIQUID
touch_met = 50 // Get rid of it quickly
color = "#B31008"
agony_dose = 0.5
agony_amount = 4
discomfort_message = "<span class='danger'>You feel like your insides are burning!</span>"
slime_temp_adj = 15
/datum/reagent/condensedcapsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
return
M.adjustToxLoss(0.5 * removed)
/datum/reagent/condensedcapsaicin/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
/datum/reagent/capsaicin/condensed/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
var/eyes_covered = 0
var/mouth_covered = 0
var/obj/item/safe_thing = null
var/no_pain = 0
var/obj/item/eye_protection = null
var/obj/item/face_protection = null
var/list/protection
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
protection = list(H.head, H.glasses, H.wear_mask)
if(H.species && (H.species.flags & NO_PAIN))
return
if(H.head)
if(H.head.body_parts_covered & EYES)
no_pain = 1 //TODO: living-level can_feel_pain() proc
else
protection = list(M.wear_mask)
for(var/obj/item/I in protection)
if(I)
if(I.flags & MASKCOVERSEYES)
eyes_covered = 1
safe_thing = H.head
if((H.head.body_parts_covered & FACE) && !(H.head.item_flags & FLEXIBLEMATERIAL))
eye_protection = I.name
if(I.flags & MASKCOVERSMOUTH)
mouth_covered = 1
safe_thing = H.head
if(H.wear_mask)
if(!eyes_covered && H.wear_mask.body_parts_covered & EYES)
eyes_covered = 1
safe_thing = H.wear_mask
if(!mouth_covered && (H.wear_mask.body_parts_covered & FACE) && !(H.wear_mask.item_flags & FLEXIBLEMATERIAL))
mouth_covered = 1
safe_thing = H.wear_mask
if(H.glasses && H.glasses.body_parts_covered & EYES)
if(!eyes_covered)
eyes_covered = 1
if(!safe_thing)
safe_thing = H.glasses
if(eyes_covered && mouth_covered)
M << "<span class='warning'>Your [safe_thing] protects you from the pepperspray!</span>"
return
else if(eyes_covered)
M << "<span class='warning'>Your [safe_thing] protect you from most of the pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 15)
M.eye_blind = max(M.eye_blind, 5)
face_protection = I.name
var/message = null
if(eyes_covered)
if(!mouth_covered)
message = "<span class='warning'>Your [eye_protection] protects your eyes from the pepperspray!</span>"
else
message = "<span class='warning'>The pepperspray gets in your eyes!</span>"
if(mouth_covered)
M.eye_blurry = max(M.eye_blurry, 15)
M.eye_blind = max(M.eye_blind, 5)
else
M.eye_blurry = max(M.eye_blurry, 25)
M.eye_blind = max(M.eye_blind, 10)
if(mouth_covered)
if(!message)
message = "<span class='warning'>Your [face_protection] protects you from the pepperspray!</span>"
else if(!no_pain)
message = "<span class='danger'>Your face and throat burn!</span>"
if(prob(25))
M.custom_emote(2, "[pick("coughs!","coughs hysterically!","splutters!")]")
M.Stun(5)
M.Weaken(5)
return
else if (mouth_covered) // Mouth cover is better than eye cover
M << "<span class='warning'>Your [safe_thing] protects your face from the pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 5)
return
else // Oh dear :D
M << "<span class='warning'>You're sprayed directly in the eyes with pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 25)
M.eye_blind = max(M.eye_blind, 10)
M.Stun(5)
M.Weaken(5)
return
/datum/reagent/condensedcapsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & (NO_PAIN)))
if(H.species && (H.species.flags & NO_PAIN))
return
if(dose == metabolism)
M << "<span class='danger'>You feel like your insides are burning!</span>"

View File

@@ -62,6 +62,10 @@
<li class="tweak">Bruise packs are now applied per wound, not per limb.</li>
<li class="tweak">Bruise packs now use a delay depending on wound severity for applying.</li>
<li class="rscdel">Removed instant healing ability from advanced bruise packs and ointment.</li>
<h2 class="date">27 October 2015</h2>
<h3 class="author">HarpyEagle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">When affected by pepperspray, eye protection now prevents blindness and face protection now prevents stun, instead of face protection doing both.</li>
</ul>
<h2 class="date">14 October 2015</h2>

View File

@@ -2352,3 +2352,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- tweak: Bruise packs are now applied per wound, not per limb.
- tweak: Bruise packs now use a delay depending on wound severity for applying.
- rscdel: Removed instant healing ability from advanced bruise packs and ointment.
2015-10-27:
HarpyEagle:
- bugfix: When affected by pepperspray, eye protection now prevents blindness and
face protection now prevents stun, instead of face protection doing both.

File diff suppressed because it is too large Load Diff