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

This commit is contained in:
GinjaNinja32
2015-03-16 21:21:56 +00:00
263 changed files with 6218 additions and 5173 deletions

View File

@@ -31,6 +31,7 @@
#include "code\__HELPERS\turfs.dm"
#include "code\__HELPERS\type2type.dm"
#include "code\__HELPERS\unsorted.dm"
#include "code\__HELPERS\vector.dm"
#include "code\_onclick\adjacent.dm"
#include "code\_onclick\ai.dm"
#include "code\_onclick\click.dm"
@@ -782,6 +783,7 @@
#include "code\modules\admin\verbs\adminjump.dm"
#include "code\modules\admin\verbs\adminpm.dm"
#include "code\modules\admin\verbs\adminsay.dm"
#include "code\modules\admin\verbs\antag-ooc.dm"
#include "code\modules\admin\verbs\atmosdebug.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\buildmode.dm"
@@ -964,10 +966,12 @@
#include "code\modules\examine\examine.dm"
#include "code\modules\examine\descriptions\atmospherics.dm"
#include "code\modules\examine\descriptions\engineering.dm"
#include "code\modules\examine\descriptions\medical.dm"
#include "code\modules\examine\descriptions\mobs.dm"
#include "code\modules\examine\descriptions\stacks.dm"
#include "code\modules\examine\descriptions\structures.dm"
#include "code\modules\examine\descriptions\turfs.dm"
#include "code\modules\examine\descriptions\weapons.dm"
#include "code\modules\ext_scripts\irc.dm"
#include "code\modules\ext_scripts\python.dm"
#include "code\modules\flufftext\Dreaming.dm"
@@ -1060,6 +1064,7 @@
#include "code\modules\mob\living\logout.dm"
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\blob\blob.dm"
#include "code\modules\mob\living\carbon\breathe.dm"
#include "code\modules\mob\living\carbon\carbon.dm"
#include "code\modules\mob\living\carbon\carbon_defines.dm"
#include "code\modules\mob\living\carbon\carbon_powers.dm"
@@ -1095,6 +1100,7 @@
#include "code\modules\mob\living\carbon\brain\posibrain.dm"
#include "code\modules\mob\living\carbon\brain\robot.dm"
#include "code\modules\mob\living\carbon\brain\say.dm"
#include "code\modules\mob\living\carbon\human\appearance.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"
@@ -1256,6 +1262,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\modules\alarm_monitor.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\power_monitor.dm"
#include "code\modules\nano\modules\rcon.dm"
#include "code\modules\organs\blood.dm"
@@ -1345,6 +1352,7 @@
#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\effects.dm"
#include "code\modules\projectiles\gun.dm"
#include "code\modules\projectiles\projectile.dm"
#include "code\modules\projectiles\targeting.dm"

View File

@@ -2,17 +2,18 @@
Contains helper procs for airflow, handled in /connection_group.
*/
mob/var/tmp/last_airflow_stun = 0
mob/proc/airflow_stun()
if(stat == 2)
return 0
if(last_airflow_stun > world.time - vsc.airflow_stun_cooldown) return 0
if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN))
src << "\blue You stay upright as the air rushes past you."
src << "<span class='notice'>You stay upright as the air rushes past you.</span>"
return 0
if(weakened <= 0) src << "\red The sudden rush of air knocks you over!"
weakened = max(weakened,5)
if(!lying)
src << "<span class='warning'>The sudden rush of air knocks you over!</span>"
Weaken(5)
last_airflow_stun = world.time
mob/living/silicon/airflow_stun()
@@ -22,16 +23,9 @@ mob/living/carbon/metroid/airflow_stun()
return
mob/living/carbon/human/airflow_stun()
if(last_airflow_stun > world.time - vsc.airflow_stun_cooldown) return 0
if(buckled) return 0
if(shoes)
if(shoes.flags & NOSLIP) return 0
if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN))
src << "\blue You stay upright as the air rushes past you."
return 0
if(weakened <= 0) src << "\red The sudden rush of air knocks you over!"
weakened = max(weakened,rand(1,5))
last_airflow_stun = world.time
..()
atom/movable/proc/check_airflow_movable(n)
@@ -84,9 +78,7 @@ obj/item/check_airflow_movable(n)
if(istype(src, /mob/living/carbon/human))
if(src:buckled)
return
if(src:shoes)
if(istype(src:shoes, /obj/item/clothing/shoes/magboots))
if(src:shoes:magpulse)
if(src:shoes && src:shoes.flags & NOSLIP)
return
src << "\red You are sucked away by airflow!"
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
@@ -207,7 +199,8 @@ mob/airflow_hit(atom/A)
for(var/mob/M in hearers(src))
M.show_message("\red <B>\The [src] slams into \a [A]!</B>",1,"\red You hear a loud slam!",2)
playsound(src.loc, "smash.ogg", 25, 1, -1)
weakened = max(weakened, (istype(A,/obj/item) ? A:w_class : rand(1,5))) //Heheheh
var/weak_amt = istype(A,/obj/item) ? A:w_class : rand(1,5) //Heheheh
Weaken(weak_amt)
. = ..()
obj/airflow_hit(atom/A)
@@ -239,10 +232,10 @@ mob/living/carbon/human/airflow_hit(atom/A)
apply_damage(b_loss/3, BRUTE, "groin", blocked, 0, "Airflow")
if(airflow_speed > 10)
paralysis += round(airflow_speed * vsc.airflow_stun)
stunned = max(stunned,paralysis + 3)
Paralyse(round(airflow_speed * vsc.airflow_stun))
Stun(paralysis + 3)
else
stunned += round(airflow_speed * vsc.airflow_stun/2)
Stun(round(airflow_speed * vsc.airflow_stun/2))
. = ..()
zone/proc/movables()

View File

@@ -20,7 +20,7 @@ atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed
turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
/turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
if(fire_protection > world.time-300)
return 0
if(locate(/obj/fire) in src)
@@ -35,37 +35,35 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
if(air_contents.check_combustability(liquid))
igniting = 1
create_fire(1000)
create_fire(vsc.fire_firelevel_multiplier)
return igniting
/zone/proc/process_fire()
if(!air.check_combustability())
var/datum/gas_mixture/burn_gas = air.remove_ratio(vsc.fire_consuption_rate, fire_tiles.len)
var/firelevel = burn_gas.zburn(src, fire_tiles, force_burn = 1, no_check = 1)
//world << "[src]: firelevel [firelevel]"
air.merge(burn_gas)
if(firelevel)
for(var/turf/T in fire_tiles)
if(T.fire)
T.fire.firelevel = firelevel
else
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in T
fire_tiles -= T
fuel_objs -= fuel
else
for(var/turf/simulated/T in fire_tiles)
if(istype(T.fire))
T.fire.RemoveFire()
T.fire = null
fire_tiles.Cut()
fuel_objs.Cut()
if(!fire_tiles.len)
air_master.active_fire_zones.Remove(src)
return
var/datum/gas_mixture/burn_gas = air.remove_ratio(vsc.fire_consuption_rate, fire_tiles.len)
var/gm = burn_gas.group_multiplier
burn_gas.group_multiplier = 1
burn_gas.zburn(force_burn = 1, no_check = 1)
burn_gas.group_multiplier = gm
air.merge(burn_gas)
var/firelevel = air.calculate_firelevel()
for(var/turf/T in fire_tiles)
if(T.fire)
T.fire.firelevel = firelevel
else
fire_tiles -= T
/turf/proc/create_fire(fl)
return 0
@@ -79,8 +77,12 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
return 1
fire = new(src, fl)
zone.fire_tiles |= src
air_master.active_fire_zones |= zone
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in src
zone.fire_tiles |= src
if(fuel) zone.fuel_objs += fuel
return 0
/obj/fire
@@ -121,8 +123,8 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
SetLuminosity(3)
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
for(var/mob/living/carbon/human/M in loc)
M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the humans!
for(var/mob/living/L in loc)
L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs!
loc.fire_act(air_contents, air_contents.temperature, air_contents.volume)
for(var/atom/A in loc)
@@ -137,9 +139,10 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
if(!enemy_tile.zone || enemy_tile.fire)
continue
if(!enemy_tile.zone.fire_tiles.len)
//if(!enemy_tile.zone.fire_tiles.len) TODO - optimize
var/datum/gas_mixture/acs = enemy_tile.return_air()
if(!acs || !acs.check_combustability())
var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in enemy_tile
if(!acs || !acs.check_combustability(liquid))
continue
//If extinguisher mist passed over the turf it's trying to spread to, don't spread and
@@ -169,85 +172,122 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
/obj/fire/Del()
if (istype(loc, /turf/simulated))
SetLuminosity(0)
loc = null
air_master.active_hotspots.Remove(src)
RemoveFire()
..()
/obj/fire/proc/RemoveFire()
if (istype(loc, /turf))
SetLuminosity(0)
loc = null
air_master.active_hotspots.Remove(src)
turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
turf/proc/apply_fire_protection()
turf/simulated/apply_fire_protection()
/turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
/turf/proc/apply_fire_protection()
/turf/simulated/apply_fire_protection()
fire_protection = world.time
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, force_burn, no_check = 0)
//Returns the firelevel
/datum/gas_mixture/proc/zburn(zone/zone, force_burn, no_check = 0)
. = 0
if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check ||check_recombustability(liquid)))
if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check ||check_recombustability(zone? zone.fuel_objs : null)))
var/gas_fuel = 0 //in the case of mixed gas/liquid fires, the gas burns first.
var/liquid_fuel = 0
var/total_fuel = 0
var/total_oxidizers = 0
//*** Get the fuel and oxidizer amounts
for(var/g in gas)
if(gas_data.flags[g] & XGM_GAS_FUEL)
total_fuel += gas[g]
gas_fuel += gas[g]
if(gas_data.flags[g] & XGM_GAS_OXIDIZER)
total_oxidizers += gas[g]
gas_fuel *= group_multiplier
total_oxidizers *= group_multiplier
if(liquid)
//Liquid Fuel
if(liquid.amount <= 0.1)
del liquid
else
total_fuel += liquid.amount
if(zone)
for(var/obj/effect/decal/cleanable/liquid_fuel/fuel in zone.fuel_objs)
liquid_fuel += fuel.amount*LIQUIDFUEL_AMOUNT_TO_MOL
if(total_fuel == 0)
total_fuel = gas_fuel + liquid_fuel
if(total_fuel <= 0.005)
return 0
//Calculate the firelevel.
var/firelevel = calculate_firelevel(liquid, total_fuel, total_oxidizers, force = 1)
//*** Determine how fast the fire burns
//get the current inner energy of the gas mix
//calculate the firelevel.
var/firelevel = calculate_firelevel(zone? zone.fuel_objs : null, total_fuel, total_oxidizers, force = 1)
//get the current thermal energy of the gas mix
//this must be taken here to prevent the addition or deletion of energy by a changing heat capacity
var/starting_energy = temperature * heat_capacity()
//determine the amount of oxygen used
var/used_oxidizers = min(total_oxidizers, total_fuel / 2)
//determine how far the reaction can progress
var/reaction_limit = min(total_oxidizers*(FIRE_REACTION_FUEL_AMOUNT/FIRE_REACTION_OXIDIZER_AMOUNT), total_fuel) //stoichiometric limit
//determine the amount of fuel actually used
var/used_fuel_ratio = min(2 * total_oxidizers , total_fuel) / total_fuel
total_fuel = total_fuel * used_fuel_ratio
//determine the actual rate of reaction, as measured by the amount of fuel reacting
var/total_reactants = total_fuel + used_oxidizers
//vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).
var/gas_reaction_progress = max(0.2*group_multiplier, (firelevel/vsc.fire_firelevel_multiplier)*gas_fuel)*FIRE_GAS_BURNRATE_MULT
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning (which is sort of accounted for by firelevel). Having more fuel means a longer burn.
var/liquid_reaction_progress = (firelevel/vsc.fire_firelevel_multiplier)*FIRE_LIQUID_BURNRATE_MULT
//determine the amount of reactants actually reacting
var/used_reactants_ratio = min(max(total_reactants * firelevel / vsc.fire_firelevel_multiplier, 0.2), total_reactants) / total_reactants
//world << "liquid_reaction_progress = [liquid_reaction_progress]"
//world << "gas_reaction_progress = [gas_reaction_progress]"
var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress
var/used_fuel = min(total_reaction_progress, reaction_limit)
var/used_oxidizers = used_fuel*(FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT)
//world << "used_fuel = [used_fuel]; used_oxidizers = [used_oxidizers]; reaction_limit=[reaction_limit]"
//if the reaction is progressing too slow then it isn't self-sustaining anymore and burns out
if(zone && zone.fuel_objs.len)
if(used_fuel <= FIRE_LIQUD_MIN_BURNRATE)
return 0
else if(used_fuel <= FIRE_GAS_MIN_BURNRATE*group_multiplier) //purely gas fires have more stringent criteria
return 0
//*** Remove fuel and oxidizer, add carbon dioxide and heat
//remove and add gasses as calculated
remove_by_flag(XGM_GAS_OXIDIZER, used_oxidizers * used_reactants_ratio)
remove_by_flag(XGM_GAS_FUEL, total_fuel * used_reactants_ratio)
var/used_gas_fuel = min(used_fuel*(gas_reaction_progress/total_reaction_progress), gas_fuel) //remove in proportion to the relative reaction progress
var/used_liquid_fuel = between(0, used_fuel-used_gas_fuel, liquid_fuel)
adjust_gas("carbon_dioxide", max(total_fuel*used_reactants_ratio, 0))
//remove_by_flag() and adjust_gas() handle the group_multiplier for us.
remove_by_flag(XGM_GAS_OXIDIZER, used_oxidizers)
remove_by_flag(XGM_GAS_FUEL, used_gas_fuel)
adjust_gas("carbon_dioxide", used_oxidizers)
if(liquid)
liquid.amount -= (liquid.amount * used_fuel_ratio * used_reactants_ratio) * 5 // liquid fuel burns 5 times as quick
//As a simplification, we remove fuel equally from all fuel sources. It might be that some fuel sources have more fuel, some have less, but whatever.
if(zone && zone.fuel_objs.len)
var/fuel_to_remove = used_liquid_fuel/(zone.fuel_objs.len*LIQUIDFUEL_AMOUNT_TO_MOL) //convert back to liquid volume units
//world << "used gas fuel = [used_gas_fuel]; used other fuel = [used_fuel-used_gas_fuel]; fuel_to_remove = [fuel_to_remove]"
var/liquidonly = !check_combustability()
for(var/O in zone.fuel_objs)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = O
if(!istype(fuel))
zone.fuel_objs -= fuel
continue
if(liquid.amount <= 0) del liquid
fuel.amount -= fuel_to_remove
if(fuel.amount <= 0)
zone.fuel_objs -= fuel
if(liquidonly)
var/turf/T = fuel.loc
if(istype(T) && T.fire) del(T.fire)
del(fuel)
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity()
temperature = (starting_energy + vsc.fire_fuel_energy_release * used_fuel) / heat_capacity()
update_values()
. = total_reactants * used_reactants_ratio
return firelevel
datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
. = 0
for(var/g in gas)
if(gas_data.flags[g] & XGM_GAS_OXIDIZER && gas[g] >= 0.1)
@@ -257,7 +297,7 @@ datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_
if(!.)
return 0
if(liquid)
if(fuel_objs && fuel_objs.len)
return 1
. = 0
@@ -266,7 +306,7 @@ datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_
. = 1
break
datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
/datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid=null)
. = 0
for(var/g in gas)
if(gas_data.flags[g] & XGM_GAS_OXIDIZER && QUANTIZE(gas[g] * vsc.fire_consuption_rate) >= 0.1)
@@ -285,20 +325,12 @@ datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fu
. = 1
break
datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid, total_fuel = null, total_oxidizers = null, force = 0)
//Returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(list/fuel_objs, total_fuel, total_oxidizers, force = 0)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
var/firelevel = 0
if(force || check_recombustability(liquid))
if(isnull(total_fuel))
for(var/g in gas)
if(gas_data.flags[g] & XGM_GAS_FUEL)
total_fuel += gas[g]
if(gas_data.flags[g] & XGM_GAS_OXIDIZER)
total_oxidizers += gas[g]
if(liquid)
total_fuel += liquid.amount
if(force || check_recombustability(fuel_objs))
var/total_combustables = (total_fuel + total_oxidizers)
if(total_combustables > 0)

View File

@@ -44,6 +44,7 @@ Class Procs:
/zone/var/invalid = 0
/zone/var/list/contents = list()
/zone/var/list/fire_tiles = list()
/zone/var/list/fuel_objs = list()
/zone/var/needs_update = 0
@@ -72,8 +73,10 @@ Class Procs:
T.zone = src
contents.Add(T)
if(T.fire)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in T
fire_tiles.Add(T)
air_master.active_fire_zones.Add(src)
air_master.active_fire_zones |= src
if(fuel) fuel_objs += fuel
T.update_graphic(air.graphic)
/zone/proc/remove(turf/simulated/T)
@@ -85,6 +88,9 @@ Class Procs:
#endif
contents.Remove(T)
fire_tiles.Remove(T)
if(T.fire)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in T
fuel_objs -= fuel
T.zone = null
T.update_graphic(graphic_remove = air.graphic)
if(contents.len)
@@ -132,6 +138,11 @@ Class Procs:
air.group_multiplier = contents.len+1
/zone/proc/tick()
if(air.temperature >= PHORON_FLASHPOINT && !(src in air_master.active_fire_zones) && air.check_combustability() && contents.len)
var/turf/T = pick(contents)
if(istype(T))
T.create_fire(vsc.fire_firelevel_multiplier)
if(air.check_tile_graphic(graphic_add, graphic_remove))
for(var/turf/simulated/T in contents)
T.update_graphic(graphic_add, graphic_remove)

File diff suppressed because it is too large Load Diff

View File

@@ -220,7 +220,7 @@
/datum/gas_mixture/proc/remove_ratio(ratio, out_group_multiplier = 1)
if(ratio <= 0)
return null
out_group_multiplier = max(1, min(group_multiplier, out_group_multiplier))
out_group_multiplier = between(1, out_group_multiplier, group_multiplier)
ratio = min(ratio, 1)
@@ -237,6 +237,11 @@
return removed
//Removes a volume of gas from the mixture and returns a gas_mixture containing the removed air with the given volume
/datum/gas_mixture/proc/remove_volume(removed_volume)
var/datum/gas_mixture/removed = remove_ratio(removed_volume/volume, 1)
removed.volume = removed_volume
return removed
//Removes moles from the gas mixture, limited by a given flag. Returns a gax_mixture containing the removed air.
/datum/gas_mixture/proc/remove_by_flag(flag, amount)
@@ -301,7 +306,7 @@
/datum/gas_mixture/proc/react(atom/dump_location)
zburn(null)
zburn(null, force_burn=0, no_check=0) //could probably just call zburn() here with no args but I like being explicit.
//Rechecks the gas_mixture and adjusts the graphic list if needed.

View File

@@ -45,7 +45,7 @@ var/global/list/skin_styles_female_list = list() //unused
var/global/list/underwear_m = list("White" = "m1", "Grey" = "m2", "Green" = "m3", "Blue" = "m4", "Black" = "m5", "Mankini" = "m6", "None") //Curse whoever made male/female underwear diffrent colours
var/global/list/underwear_f = list("Red" = "f1", "White" = "f2", "Yellow" = "f3", "Blue" = "f4", "Black" = "f5", "Thong" = "f6", "Black Sports" = "f7","White Sports" = "f8","None")
//undershirt
var/global/list/undershirt_t = list("Black Tank top" = "u1", "White Tank top" = "u2", "Black shirt" = "u3", "White shirt" = "u4", "None")
var/global/list/undershirt_t = list("White Tank top" = "u1", "Black Tank top" = "u2", "Black shirt" = "u3", "White shirt" = "u4", "None")
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")
var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg)

View File

@@ -36,7 +36,7 @@
//Removes a few problematic characters
/proc/sanitize_simple(var/t,var/list/repl_chars = list("\n"="#","\t"="#"))
for(var/char in repl_chars)
replacetext(t, char, repl_chars[char])
t = replacetext(t, char, repl_chars[char])
return t
/proc/readd_quotes(var/t)

View File

@@ -4,9 +4,11 @@
#define MINUTE *600
#define MINUTES *600
var/roundstart_hour = 0
//Returns the world time in english
proc/worldtime2text(time = world.time)
return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]"
if(!roundstart_hour) roundstart_hour = pick(2,7,12,17)
return "[round(time / 36000)+roundstart_hour]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]"
proc/time_stamp()
return time2text(world.timeofday, "hh:mm:ss")

View File

@@ -374,7 +374,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/mob/living/silicon/ai/selected
var/list/active = active_ais()
for(var/mob/living/silicon/ai/A in active)
if(!selected || (selected.connected_robots > A.connected_robots))
if(!selected || (selected.connected_robots.len > A.connected_robots.len))
selected = A
return selected

141
code/__HELPERS/vector.dm Normal file
View File

@@ -0,0 +1,141 @@
/*
plot_vector is a helper datum for plotting a path in a straight line towards a target turf.
This datum converts from world space (turf.x and turf.y) to pixel space, which the datum keeps track of itself. This
should work with any size turfs (i.e. 32x32, 64x64) as it references world.icon_size (note: not actually tested with
anything other than 32x32 turfs).
setup()
This should be called after creating a new instance of a plot_vector datum.
This does the initial setup and calculations. Since we are travelling in a straight line we only need to calculate
the vector and x/y steps once. x/y steps are capped to 1 full turf, whichever is further. If we are travelling along
the y axis each step will be +/- 1 y, and the x movement reduced based on the angle (tangent calculation). After
this every subsequent step will be incremented based on these calculations.
Inputs:
source - the turf the object is starting from
target - the target turf the object is travelling towards
xo - starting pixel_x offset, typically won't be needed, but included in case someone has a need for it later
yo - same as xo, but for the y_pixel offset
increment()
Adds the offset to the current location - incrementing it by one step along the vector.
return_angle()
Returns the direction (angle in degrees) the object is travelling in.
(N)
90<39>
^
|
(W) 180<38> <--+--> 0<> (E)
|
v
-90<39>
(S)
return_hypotenuse()
Returns the distance of travel for each step of the vector, relative to each full step of movement. 1 is a full turf
length. Currently used as a multiplier for scaling effects that should be contiguous, like laser beams.
return_location()
Returns a vector_loc datum containing the current location data of the object (see /datum/vector_loc). This includes
the turf it currently should be at, as well as the pixel offset from the centre of that turf. Typically increment()
would be called before this if you are going to move an object based on it's vector data.
*/
/datum/plot_vector
var/turf/source
var/turf/target
var/angle = 0 // direction of travel in degrees
var/loc_x = 0 // in pixels from the left edge of the map
var/loc_y = 0 // in pixels from the bottom edge of the map
var/loc_z = 0 // loc z is in world space coordinates (i.e. z level) - we don't care about measuring pixels for this
var/offset_x = 0 // distance to increment each step
var/offset_y = 0
/datum/plot_vector/proc/setup(var/turf/S, var/turf/T, var/xo = 0, var/yo = 0)
source = S
target = T
if(!istype(source))
source = get_turf(source)
if(!istype(target))
target = get_turf(target)
if(!istype(source) || !istype(target))
return
// convert coordinates to pixel space (default is 32px/turf, 8160px across for a size 255 map)
loc_x = source.x * world.icon_size + xo
loc_y = source.y * world.icon_size + yo
loc_z = source.z
// calculate initial x and y difference
var/dx = target.x - source.x
var/dy = target.y - source.y
// if we aren't moving anywhere; quit now
if(dx == 0 && dy == 0)
return
// calculate the angle
angle = Atan2(dx, dy)
// and some rounding to stop the increments jumping whole turfs - because byond favours certain angles
if(angle > -135 && angle < 45)
angle = Ceiling(angle)
else
angle = Floor(angle)
// calculate the offset per increment step
if(abs(angle) in list(0, 45, 90, 135, 180)) // check if the angle is a cardinal
if(abs(angle) in list(0, 45, 135, 180)) // if so we can skip the trigonometry and set these to absolutes as
offset_x = sign(dx) // they will always be a full step in one or more directions
if(abs(angle) in list(45, 90, 135))
offset_y = sign(dy)
else if(abs(dy) > abs(dx))
offset_x = Cot(abs(angle)) // otherwise set the offsets
offset_y = sign(dy)
else
offset_x = sign(dx)
offset_y = Tan(angle)
if(dx < 0)
offset_y = -offset_y
// multiply the offset by the turf pixel size
offset_x *= world.icon_size
offset_y *= world.icon_size
/datum/plot_vector/proc/increment()
loc_x += offset_x
loc_y += offset_y
/datum/plot_vector/proc/return_angle()
return angle
/datum/plot_vector/proc/return_hypotenuse()
return sqrt(((offset_x / 32) ** 2) + ((offset_y / 32) ** 2))
/datum/plot_vector/proc/return_location(var/datum/vector_loc/data)
if(!data)
data = new()
data.loc = locate(round(loc_x / world.icon_size), round(loc_y / world.icon_size), loc_z)
if(!data.loc)
return
data.pixel_x = loc_x - (data.loc.x * world.icon_size)
data.pixel_y = loc_y - (data.loc.y * world.icon_size)
return data
/*
vector_loc is a helper datum for returning precise location data from plot_vector. It includes the turf the object is in
as well as the pixel offsets.
return_turf()
Returns the turf the object should be currently located in.
*/
/datum/vector_loc
var/turf/loc
var/pixel_x
var/pixel_y
/datum/vector_loc/proc/return_turf()
return loc

View File

@@ -36,6 +36,9 @@
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -101,14 +104,22 @@
I have no idea why it was in atoms.dm instead of respective files.
*/
/atom/proc/AICtrlShiftClick()
return
/obj/machinery/door/airlock/AICtrlShiftClick()
if(emagged)
return
return
/atom/proc/AIShiftClick()
return
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors!
if(density)
Topic(src, list("src"= "\ref[src]", "aiEnable"="7"), 1) // 1 meaning no window (consistency!)
Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "1"), 1) // 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "aiDisable"="7"), 1)
Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "0"), 1)
return
/atom/proc/AICtrlClick()
@@ -116,9 +127,9 @@
/obj/machinery/door/airlock/AICtrlClick() // Bolts doors
if(locked)
Topic(src, list("src"= "\ref[src]", "aiEnable"="4"), 1)// 1 meaning no window (consistency!)
Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "0"), 1)// 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "aiDisable"="4"), 1)
Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "1"), 1)
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
Topic(src, list("src"= "\ref[src]", "breaker"="1"), 1) // 1 meaning no window (consistency!)
@@ -130,12 +141,12 @@
AltClick(A)
/obj/machinery/door/airlock/AIAltClick() // Electrifies doors.
if(!secondsElectrified)
if(!electrified_until)
// permanent shock
Topic(src, list("src"= "\ref[src]", "aiEnable"="6"), 1) // 1 meaning no window (consistency!)
Topic(src, list("src"= "\ref[src]", "command"="electrify_permanently", "activate" = "1"), 1) // 1 meaning no window (consistency!)
else
// disable/6 is not in Topic; disable/5 disables both temporary and permanent shock
Topic(src, list("src"= "\ref[src]", "aiDisable"="5"), 1)
Topic(src, list("src"= "\ref[src]", "command"="electrify_permanently", "activate" = "0"), 1)
return
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
@@ -146,9 +157,9 @@
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
if(!src.lights)
Topic(src, list("src"= "\ref[src]", "aiEnable"="10"), 1) // 1 meaning no window (consistency!)
Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "1"), 1) // 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "aiDisable"="10"), 1)
Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "0"), 1)
return
//

View File

@@ -45,6 +45,9 @@
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -292,6 +295,17 @@
/mob/proc/TurfAdjacent(var/turf/T)
return T.AdjacentQuick(src)
/*
Control+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(var/atom/A)
A.CtrlShiftClick(src)
return
/atom/proc/CtrlShiftClick(var/mob/user)
return
/*
Misc helpers

View File

@@ -16,6 +16,9 @@
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -109,6 +112,55 @@
cycle_modules()
return
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
// for non-doors/apcs
/mob/living/silicon/robot/CtrlShiftClickOn(var/atom/A)
A.BorgCtrlShiftClick(src)
/mob/living/silicon/robot/ShiftClickOn(var/atom/A)
A.BorgShiftClick(src)
/mob/living/silicon/robot/CtrlClickOn(var/atom/A)
A.BorgCtrlClick(src)
/mob/living/silicon/robot/AltClickOn(var/atom/A)
A.BorgAltClick(src)
/atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick()
AICtrlShiftClick()
/atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code.
AIShiftClick()
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick() // Bolts doors. Forwards to AI code.
AICtrlClick()
/obj/machinery/power/apc/BorgCtrlClick() // turns off/on APCs. Forwards to AI code.
AICtrlClick()
/obj/machinery/turretid/BorgCtrlClick() //turret control on/off. Forwards to AI code.
AICtrlClick()
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
AltClick(user)
return
/obj/machinery/door/airlock/BorgAltClick() // Eletrifies doors. Forwards to AI code.
AIAltClick()
/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code.
AIAltClick()
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.

View File

@@ -184,6 +184,8 @@
var/starlight = 0 // Whether space turfs have ambient light or not
var/list/ert_species = list("Human")
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -609,6 +611,10 @@
value = text2num(value)
config.starlight = value >= 0 ? value : 0
if("ert_species")
config.ert_species = text2list(value, ";")
if(!config.ert_species.len)
config.ert_species += "Human"
else
log_misc("Unknown setting in configuration: '[name]'")

View File

@@ -72,10 +72,10 @@ datum/mind
current.remove_changeling_powers()
current.verbs -= /datum/changeling/proc/EvolutionMenu
current.mind = null
if(new_character.mind) //remove any mind currently in our new body's mind variable
new_character.mind.current = null
nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user
if(new_character.mind) //remove any mind currently in our new body's mind variable
new_character.mind.current = null
current = new_character //link ourself to our new body
new_character.mind = src //and link our new body to ourself

View File

@@ -14,6 +14,7 @@
for(var/obj/machinery/door/door in T.contents)
spawn(1)
if(istype(door,/obj/machinery/door/airlock))
door:unlock(1) //forced because it's magic!
var/obj/machinery/door/airlock/A = door
A.unlock(1) //forced because it's magic!
door.open()
return

View File

@@ -696,20 +696,31 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
name = "Weapons crate"
contains = list(/obj/item/weapon/melee/baton,
/obj/item/weapon/melee/baton,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/gun,
/obj/item/weapon/gun/energy/gun,
/obj/item/weapon/gun/energy/taser,
/obj/item/weapon/gun/energy/taser,
/obj/item/weapon/gun/projectile/sec,
/obj/item/weapon/gun/projectile/sec,
/obj/item/weapon/storage/box/flashbangs,
/obj/item/weapon/storage/box/flashbangs)
cost = 30
cost = 40
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Weapons crate"
access = access_security
group = "Security"
/datum/supply_packs/flareguns
name = "Flare guns crate"
contains = list(/obj/item/weapon/gun/projectile/sec/flash,
/obj/item/ammo_magazine/c45m/flash,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/flare,
/obj/item/weapon/storage/box/flashshells)
cost = 25
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Flare gun crate"
access = access_security
group = "Security"
/datum/supply_packs/eweapons
name = "Experimental weapons crate"
@@ -777,7 +788,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
name = "Energy weapons crate"
contains = list(/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/gun)
/obj/item/weapon/gun/energy/laser)
cost = 50
containertype = /obj/structure/closet/crate/secure
containername = "energy weapons crate"
@@ -789,9 +800,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
contains = list(/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/weapon/storage/box/shotgunammo,
/obj/item/weapon/gun/projectile/shotgun/pump,
/obj/item/weapon/storage/box/shotgunshells,
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
/obj/item/weapon/gun/projectile/shotgun/pump/combat)
cost = 50
cost = 65
containertype = /obj/structure/closet/crate/secure
containername = "Shotgun crate"
access = access_armory

View File

@@ -59,7 +59,6 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
A.loseMainPower()
A.shock(usr, 50)
else
if((!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER2)))
A.regainMainPower()
A.shock(usr, 50)
@@ -70,7 +69,6 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
A.loseBackupPower()
A.shock(usr, 50)
else
if((!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER2)))
A.regainBackupPower()
A.shock(usr, 50)
@@ -78,8 +76,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
if(!mended)
//Cutting this wire also drops the door bolts, and mending it does not raise them. (This is what happens now, except there are a lot more wires going to door bolts at present)
if(A.locked!=1)
A.locked = 1
A.lock(1)
A.update_icon()
if(AIRLOCK_WIRE_AI_CONTROL)
@@ -98,16 +95,11 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
A.aiControlDisabled = -1
if(AIRLOCK_WIRE_ELECTRIFY)
if(!mended)
//Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted.
if(A.secondsElectrified != -1)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified", admin=0, addition="at [A.x],[A.y],[A.z]")
A.secondsElectrified = -1
A.electrify(-1)
else
if(A.secondsElectrified == -1)
A.secondsElectrified = 0
A.electrify(0)
return // Don't update the dialog.
if (AIRLOCK_WIRE_SAFETY)
@@ -139,13 +131,9 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
//one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not),
//raises them if they are down (only if power's on)
if(!A.locked)
A.locked = 1
A.audible_message("You hear a click from the bottom of the door.", null, 1)
A.lock()
else
if(A.arePowerSystemsOn()) //only can raise bolts if power's on
A.locked = 0
A.audible_message("You hear a click from the bottom of the door.", null, 1)
A.update_icon()
A.unlock()
if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2)
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
@@ -165,19 +153,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
if(AIRLOCK_WIRE_ELECTRIFY)
//one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds.
if(A.secondsElectrified==0)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified", admin=0, addition="at [A.x],[A.y],[A.z]")
A.secondsElectrified = 30
spawn(10)
if(A)
//TODO: Move this into process() and make pulsing reset secondsElectrified to 30
while (A.secondsElectrified>0)
A.secondsElectrified-=1
if(A.secondsElectrified<0)
A.secondsElectrified = 0
sleep(10)
return
A.electrify(30)
if(AIRLOCK_WIRE_OPEN_DOOR)
//tries to open the door without ID
//will succeed only if the ID wire is cut or the door requires no access and it's not emagged

View File

@@ -34,8 +34,7 @@ var/const/BORG_WIRE_CAMERA = 16
if (BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
if(!mended)
if (R.connected_ai)
R.connected_ai = null
R.disconnect_from_ai()
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && !R.scrambledcodes)
@@ -56,12 +55,8 @@ var/const/BORG_WIRE_CAMERA = 16
if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!R.emagged)
var/mob/living/silicon/ai/new_ai = select_active_ai(R)
if(new_ai && (new_ai != R.connected_ai))
R.connected_ai.connected_robots -= src
R.connected_ai = new_ai
new_ai.connected_robots += src
R.notify_ai(1)
R.sync()
R.connect_to_ai(new_ai)
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
R.camera.kick_viewers() // Kick anyone watching the Cyborg's camera

View File

@@ -437,7 +437,7 @@
collection_mode = 1
display_contents_with_number = 1
max_w_class = 3
max_combined_w_class = 100
max_storage_space = 100
/obj/item/weapon/stock_parts
name = "stock part"

View File

@@ -12,12 +12,15 @@ proc/process_med_hud(var/mob/M, var/local_scanner, var/mob/Alt)
if(P.Mob.see_invisible < patient.invisibility)
continue
if(!(local_scanner || hassensorlevel(patient, SUIT_SENSOR_VITAL)))
continue
P.Client.images += patient.hud_list[HEALTH_HUD]
if(local_scanner)
P.Client.images += patient.hud_list[HEALTH_HUD]
P.Client.images += patient.hud_list[STATUS_HUD]
else
var/sensor_level = getsensorlevel(patient)
if(sensor_level >= SUIT_SENSOR_VITAL)
P.Client.images += patient.hud_list[HEALTH_HUD]
if(sensor_level >= SUIT_SENSOR_BINARY)
P.Client.images += patient.hud_list[LIFE_HUD]
//Security HUDs. Pass a value for the second argument to enable implant viewing or other special features.
proc/process_sec_hud(var/mob/M, var/advanced_mode, var/mob/Alt)

View File

@@ -47,9 +47,8 @@ proc/sql_report_death(var/mob/living/carbon/human/H)
if(!H.key || !H.mind)
return
var/turf/T = H.loc
var/area/placeofdeath = get_area(T.loc)
var/podname = placeofdeath.name
var/area/placeofdeath = get_area(H)
var/podname = placeofdeath ? placeofdeath.name : "Unknown area"
var/sqlname = sanitizeSQL(H.real_name)
var/sqlkey = sanitizeSQL(H.key)
@@ -82,9 +81,8 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
if(!H.key || !H.mind)
return
var/turf/T = H.loc
var/area/placeofdeath = get_area(T.loc)
var/podname = placeofdeath.name
var/area/placeofdeath = get_area(H)
var/podname = placeofdeath ? placeofdeath.name : "Unknown area"
var/sqlname = sanitizeSQL(H.real_name)
var/sqlkey = sanitizeSQL(H.key)

View File

@@ -38,6 +38,11 @@
return cameras
/area/proc/atmosalert(danger_level, var/alarm_source)
if (danger_level == 0)
atmosphere_alarm.clearAlarm(master, alarm_source)
else
atmosphere_alarm.triggerAlarm(master, alarm_source, severity = danger_level)
//Check all the alarms before lowering atmosalm. Raising is perfectly fine.
for (var/area/RA in related)
for (var/obj/machinery/alarm/AA in RA)
@@ -51,11 +56,6 @@
else if (danger_level >= 2 && atmosalm < 2)
air_doors_close()
if (danger_level == 0)
atmosphere_alarm.clearAlarm(master, alarm_source)
else
atmosphere_alarm.triggerAlarm(master, alarm_source, severity = danger_level)
atmosalm = danger_level
for(var/area/RA in related)
for (var/obj/machinery/alarm/AA in RA)

View File

@@ -34,6 +34,12 @@
else
return null
//Currently used only for cryo cells, because they are also pipes and so overriding their return_air() would break their pipe-behaviour.
//If cryo cells are ever rewritten so that the part that contains the human is separate from the pipe part --
//such as rewriting them so that they are a machine that contains a pipe segment (or a pipe that contains a machine that contains the human?) -- then this can be removed.
/atom/proc/return_air_for_internal_lifeform()
return return_air()
/atom/proc/check_eye(user as mob)
if (istype(user, /mob/living/silicon/ai)) // WHYYYY
return 1
@@ -201,6 +207,7 @@ its easier to just keep the beam vertical.
f_name += "oil-stained [name][infix]."
user << "\icon[src] That's [f_name] [suffix]"
user << desc
return distance == -1 || (get_dist(src, user) <= distance)

View File

@@ -32,6 +32,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
var/word1
var/word2
var/word3
var/list/converting = list()
// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere.
// travel self [word] - Teleport to random [rune with word destination matching]

View File

@@ -1,6 +1,7 @@
var/list/sacrificed = list()
/obj/effect/rune
/////////////////////////////////////////FIRST RUNE
proc
teleport(var/key)
@@ -98,50 +99,82 @@ var/list/sacrificed = list()
/////////////////////////////////////////THIRD RUNE
convert()
var/mob/living/carbon/target = null
for(var/mob/living/carbon/M in src.loc)
if(iscultist(M))
continue
if(M.stat==2)
continue
if(!iscultist(M) && M.stat < DEAD && !(M in converting))
target = M
break
if(!target) //didn't find any new targets
if(!converting.len)
fizzle()
else
usr << "<span class='danger'>You sense that the power of the dark one is already working away at them.</span>"
return
usr.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!")
if (M.species && (M.species.flags & NO_PAIN))
M.visible_message("\red The markings below [M] glow a bloody red.")
else
M.visible_message("\red [M] writhes in pain as the markings below \him glow a bloody red.", \
"\red AAAAAAHHHH!", \
"\red You hear an anguished scream.")
if(is_convertable_to_cult(M.mind) && !jobban_isbanned(M, "cultist"))//putting jobban check here because is_convertable uses mind as argument
converting |= target
var/list/waiting_for_input = list(target = 0) //need to box this up in order to be able to reset it again from inside spawn, apparently
var/initial_message = 0
while(target in converting)
if(target.loc != src.loc || target.stat == DEAD)
converting -= target
if(target.getFireLoss() < 100)
target.hallucination = min(target.hallucination, 500)
return 0
// Mostly for the benefit of those who resist, but it makes sense for even those who join to have some.. effect.
M.take_overall_damage(0, 10)
var/choice = alert(M,"Do you want to join the cult?","Submit to Nar'Sie","Resist","Submit")
if(choice == "Submit")
ticker.mode.add_cultist(M.mind)
M.mind.special_role = "Cultist"
M << "<font color=\"purple\"><b><i>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root.</b></i></font>"
M << "<font color=\"purple\"><b><i>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.</b></i></font>"
return 1
else if(choice == "Resist")
M.take_overall_damage(0, rand(5, 10)) // You dirty resister cannot handle the damage to your mind. Easily.
target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects
// Resist messages go!
var/BurnLoss = M.getFireLoss()
if (BurnLoss < 25) M << "<font color=\"red\"><b>Your blood boils as you force yourself to resist the corruption invading every corner of your mind."
else if (BurnLoss < 45) M << "<font color=\"red\"><b>Your blood boils and your body burns as the corruption further forces itself into your body and mind."
else if (BurnLoss < 75) M << "<font color=\"red\"><b>You begin to hallucinate images of a dark and incomprehensible being and your entire body feels like its engulfed in flame as your mental defenses crumble."
else if (BurnLoss < 100) M << "<font color=\"red\"><b>Your mind turns to ash as the burning flames engulf your very soul and images of Nar'Sie begin to bombard the last remnants of mental resistance."
else M << "<font color=\"red\"><b>Your entire broken soul and being is engulfed in corruption and flames as your mind shatters away into nothing."
return 0
if(initial_message) //don't do this stuff right away, only if they resist or hesitate.
switch(target.getFireLoss())
if(0 to 25)
target << "<span class='danger'>Your blood boils as you force yourself to resist the corruption invading every corner of your mind.</span>"
if(25 to 45)
target << "<span class='danger'>Your blood boils and your body burns as the corruption further forces itself into your body and mind.</span>"
if(45 to 75)
target << "<span class='danger'>You begin to hallucinate images of a dark and incomprehensible being and your entire body feels like its engulfed in flame as your mental defenses crumble.</span>"
target.apply_effect(rand(1,10), STUTTER)
if(75 to 100)
target << "<span class='cult'>Your mind turns to ash as the burning flames engulf your very soul and images of an unspeakable horror begin to bombard the last remnants of mental resistance.</span>"
//broken mind - 5000 may seem like a lot I wanted the effect to really stand out for maxiumum losing-your-mind-spooky
//hallucination is reduced when the step off as well, provided they haven't hit the last stage...
target.hallucination += 5000
target.apply_effect(10, STUTTER)
target.adjustBrainLoss(1)
if(100 to INFINITY)
target << "<span class='cult'>Your entire broken soul and being is engulfed in corruption and flames as your mind shatters away into nothing.</span>"
target.hallucination += 5000
target.apply_effect(15, STUTTER)
target.adjustBrainLoss(rand(1,5))
initial_message = 1
if (target.species && (target.species.flags & NO_PAIN))
target.visible_message("<span class='warning'>The markings below [target] glow a bloody red.</span>")
else
M << "<font color=\"purple\"><b><i>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root.</b></i></font>"
M << "<font color=\"red\"><b>And you were able to force it out of your mind. You now know the truth, there's something horrible out there, stop it and its minions at all costs.</b></font>"
return 0
return fizzle()
target.visible_message("<span class='warning'>[target] writhes in pain as the markings below \him glow a bloody red.</span>", "<span class='danger'>AAAAAAHHHH!</span>", "<span class='warning'>You hear an anguished scream.</span>")
if(!waiting_for_input[target]) //so we don't spam them with dialogs if they hesitate
waiting_for_input[target] = 1
if(!is_convertable_to_cult(target.mind) || jobban_isbanned(target, "cultist"))//putting jobban check here because is_convertable uses mind as argument
//waiting_for_input ensures this is only shown once, so they basically auto-resist from here on out. They still need to find a way to get off the freaking rune if they don't want to burn to death, though.
target << "<span class='cult'>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root.</span>"
target << "<span class='danger'>And you were able to force it out of your mind. You now know the truth, there's something horrible out there, stop it and its minions at all costs.</span>"
else spawn()
var/choice = alert(target,"Do you want to join the cult?","Submit to Nar'Sie","Resist","Submit")
waiting_for_input[target] = 0
if(choice == "Submit") //choosing 'Resist' does nothing of course.
ticker.mode.add_cultist(target.mind)
target.mind.special_role = "Cultist"
target << "<span class='cult'>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root.</span>"
target << "<span class='cult'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.</span>"
converting -= target
target.hallucination = 0 //sudden clarity
sleep(100) //proc once every 10 seconds
return 1
/////////////////////////////////////////FOURTH RUNE

View File

@@ -32,14 +32,14 @@
if(L.name == "carpspawn")
ninjastart.Add(L)
if(ninjastart.len)
return 1
if(ninjastart.len == 0 && latejoin.len > 0)
ninja.current << "<B>\red No spawneable locations could be found. Defaulting to latejoin.</B>"
ninja.current << "<B>\red No spawn locations could be found. Defaulting to late-join locations.</B>"
return 1
else
ninja.current << "<B>\red No spawneable locations could be found. Aborting.</B>"
return 0
return 1
ninja.current << "<B>\red No spawn locations could be found. Aborting.</B>"
return 0
/datum/game_mode/ninja/pre_setup()
for(var/datum/mind/ninja in ninjas)

View File

@@ -104,7 +104,7 @@
if(C.imprinted != "empty")
U << "\red <b>Capture failed!</b>: \black The soul stone has already been imprinted with [C.imprinted]'s mind!"
else
if (T.stat == 0)
if ((T.health + T.halloss) > config.health_threshold_crit)
U << "\red <b>Capture failed!</b>: \black Kill or maim the victim first!"
else
if(T.client == null)
@@ -129,6 +129,11 @@
S.canmove = 0//Can't move out of the soul stone
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
S.icon = T.icon
S.icon_state = T.icon_state
S.overlays = T.overlays
S.color = rgb(254,0,0)
S.alpha = 127
if (T.client)
T.client.mob = S
S.cancel_camera()

View File

@@ -85,10 +85,8 @@
//MONEY
/var/const/access_crate_cash = 200
/obj/var/list/req_access = null
/obj/var/req_access_txt = "0"
/obj/var/list/req_one_access = null
/obj/var/req_one_access_txt = "0"
/obj/var/list/req_access = list()
/obj/var/list/req_one_access = list()
//returns 1 if this mob has sufficient access to use this object
/obj/proc/allowed(mob/M)
@@ -117,37 +115,14 @@
return null
/obj/proc/check_access(obj/item/I)
//These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system.
if(!src.req_access)
src.req_access = list()
if(src.req_access_txt)
var/list/req_access_str = text2list(req_access_txt,";")
for(var/x in req_access_str)
var/n = text2num(x)
if(n)
req_access += n
if(!src.req_one_access)
src.req_one_access = list()
if(src.req_one_access_txt)
var/list/req_one_access_str = text2list(req_one_access_txt,";")
for(var/x in req_one_access_str)
var/n = text2num(x)
if(n)
req_one_access += n
if(!istype(src.req_access, /list)) //something's very wrong
return 1
var/list/L = src.req_access
if(!L.len && (!src.req_one_access || !src.req_one_access.len)) //no requirements
if(!src.req_access.len && !src.req_one_access.len) //no requirements
return 1
if(!I)
return 0
for(var/req in src.req_access)
if(!(req in I.GetAccess())) //doesn't have this access
return 0
if(src.req_one_access && src.req_one_access.len)
if(src.req_one_access.len)
for(var/req in src.req_one_access)
if(req in I.GetAccess()) //has an access from the single access list
return 1
@@ -156,15 +131,13 @@
/obj/proc/check_access_list(var/list/L)
if(!src.req_access && !src.req_one_access) return 1
if(!istype(src.req_access, /list)) return 1
if(!src.req_access.len && (!src.req_one_access || !src.req_one_access.len)) return 1
if(!src.req_access.len && !src.req_one_access.len) return 1
if(!L) return 0
if(!istype(L, /list)) return 0
for(var/req in src.req_access)
if(!(req in L)) //doesn't have this access
return 0
if(src.req_one_access && src.req_one_access.len)
if(src.req_one_access.len)
for(var/req in src.req_one_access)
if(req in L) //has an access from the single access list
return 1

View File

@@ -72,7 +72,8 @@ var/list/medical_positions = list(
"Medical Doctor",
"Geneticist",
"Psychiatrist",
"Chemist"
"Chemist",
"Paramedic"
)

View File

@@ -4,6 +4,8 @@
icon_state = "motion0"
layer = 3
anchored = 1.0
use_power = 1
idle_power_usage = 10
var/uses = 20
var/disabled = 1
var/lethal = 0
@@ -13,6 +15,7 @@
var/cooldown_on = 0
req_access = list(access_ai_upload)
/obj/machinery/ai_slipper/New()
..()
update_icon()

View File

@@ -80,6 +80,9 @@
var/report_danger_level = 1
/obj/machinery/alarm/nobreach
breach_detection = 0
/obj/machinery/alarm/monitor
report_danger_level = 0
breach_detection = 0
@@ -488,7 +491,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 625, 625, master_ui = master_ui, custom_state = custom_state)
ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 325, 625, master_ui = master_ui, custom_state = custom_state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)

View File

@@ -214,9 +214,7 @@ update_flag
else
can_label = 0
if(air_contents.temperature > PHORON_FLASHPOINT)
air_contents.zburn()
return
air_contents.react() //cooking up air cans - add phoron and oxygen, then heat above PHORON_MINIMUM_BURN_TEMPERATURE
/obj/machinery/portable_atmospherics/canister/return_air()
return air_contents

View File

@@ -6,7 +6,7 @@
anchored = 1
use_power = 1
idle_power_usage = 10
active_power_usage = 100
active_power_usage = 2000
var/list/machine_recipes
var/list/stored_material = list("metal" = 0, "glass" = 0)
@@ -23,6 +23,7 @@
var/datum/wires/autolathe/wires = null
/obj/machinery/autolathe/New()
..()
@@ -233,8 +234,7 @@
return
busy = 1
//This needs some work.
use_power(max(2000, (making.power_use*multiplier)))
update_use_power(2)
//Check if we still have the materials.
for(var/material in making.resources)
@@ -253,6 +253,7 @@
sleep(build_time)
busy = 0
update_use_power(1)
//Sanity check.
if(!making || !src) return

View File

@@ -14,6 +14,7 @@
var/build_eff = 1
var/eat_eff = 1
/obj/machinery/biogenerator/New()
..()
var/datum/reagents/R = new/datum/reagents(1000)

View File

@@ -1,12 +1,14 @@
//These machines are mostly just here for debugging/spawning. Skeletons of the feature to come.
/obj/machinery/bioprinter
name = "bioprinter"
name = "organ bioprinter"
desc = "It's a machine that grows replacement organs."
icon = 'icons/obj/surgery.dmi'
anchored = 1
density = 1
use_power = 1
idle_power_usage = 40
icon_state = "bioprinter"
@@ -41,33 +43,45 @@
if(prints_prosthetics)
O.robotic = 2
else if(loaded_dna)
visible_message("The printer would be using the DNA sample if it was coded.")
//TODO: Copy DNA hash or donor reference over to new organ.
visible_message("<span class='notice'>The printer injects stored DNA in used biomass.</span>.")
var/datum/organ/internal/I = new O.organ_type
I.transplant_data = list()
var/mob/living/carbon/C = loaded_dna["donor"]
I.transplant_data["species"] = C.species.name
I.transplant_data["blood_type"] = loaded_dna["blood_type"]
I.transplant_data["blood_DNA"] = loaded_dna["blood_DNA"]
O.organ_data = I
I.organ_holder = O
visible_message("The bioprinter spits out a new organ.")
visible_message("<span class='info'>The bioprinter spits out a new organ.")
else
user << "There is not enough matter in the printer."
user << "<span class='warning'>There is not enough matter in the printer.</span>"
/obj/machinery/bioprinter/attackby(obj/item/weapon/W, mob/user)
// DNA sample from syringe.
if(!prints_prosthetics && istype(W,/obj/item/weapon/reagent_containers/syringe))
user << "You inject the blood sample into the bioprinter, but it isn't coded yet."
var/obj/item/weapon/reagent_containers/syringe/S = W
var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood
if(injected && injected.data)
loaded_dna = injected.data
user << "<span class='info'>You inject the blood sample into the bioprinter.</span>"
return
// Meat for biomass.
else if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
user << "\blue \The [src] processes \the [W]."
stored_matter += 50
user.drop_item()
user << "<span class='info'>\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]</span>"
del(W)
return
// Steel for matter.
else if(prints_prosthetics && istype(W, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = W
user << "\blue \The [src] processes \the [W]."
stored_matter += M.amount * 10
user.drop_item()
user << "<span class='info'>\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]</span>"
del(W)
return
else

View File

@@ -265,13 +265,19 @@ Auto Patrol: []"},
src.mode = 0
walk_to(src,0)
if(target) // make sure target exists
// We re-assess human targets, before bashing their head in, in case their credentials change
if(target && istype(target, /mob/living/carbon/human))
if(istype(target, /mob/living/carbon/human))
var/threat = src.assess_perp(target, idcheck, check_records, check_arrest)
if(threat < 4)
target = null
frustration = 8
return
// The target must remain in view to complete the desire to bash its head in
if(!(target in view(search_range,src)))
frustration++
return
if(target) // make sure target exists
if(!lasercolor && Adjacent(target)) // If right next to perp. Lasertag bots do not arrest anyone, just patrol and shoot and whatnot
if(istype(src.target,/mob/living/carbon))
playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
@@ -349,7 +355,12 @@ Auto Patrol: []"},
if(istype(src.target,/mob/living/carbon))
var/mob/living/carbon/C = target
if(!C.handcuffed && !src.arrest_type)
var/wearing_hardsuit
if(istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
if(istype(H.back, /obj/item/weapon/rig) && istype(H.gloves,/obj/item/clothing/gloves/rig))
wearing_hardsuit = 1
if(!wearing_hardsuit && !C.handcuffed && !src.arrest_type)
playsound(src.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
mode = SECBOT_ARREST
visible_message("\red <B>[src] is trying to put handcuffs on [src.target]!</B>")

View File

@@ -10,6 +10,7 @@
idle_power_usage = 2
active_power_usage = 4
/obj/machinery/button/attack_ai(mob/user as mob)
return src.attack_hand(user)

View File

@@ -31,13 +31,13 @@
var/alarm_on = 0
var/busy = 0
var/on_open_network = 0
/obj/machinery/camera/New()
wires = new(src)
assembly = new(src)
assembly.state = 4
invalidateCameraCache()
/* // Use this to look for cameras that have the same c_tag.
for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
@@ -56,18 +56,18 @@
/obj/machinery/camera/emp_act(severity)
if(!isEmpProof())
if(prob(100/severity))
invalidateCameraCache()
stat |= EMPED
SetLuminosity(0)
kick_viewers()
triggerCameraAlarm(10 * severity)
triggerCameraAlarm(30 / severity)
update_icon()
update_coverage()
spawn(900)
stat &= ~EMPED
cancelCameraAlarm()
update_icon()
invalidateCameraCache()
update_coverage()
..()
/obj/machinery/camera/bullet_act(var/obj/item/projectile/P)
@@ -114,7 +114,7 @@
destroy()
/obj/machinery/camera/attackby(obj/W as obj, mob/living/user as mob)
invalidateCameraCache()
update_coverage()
// DECONSTRUCTION
if(isscrewdriver(W))
//user << "<span class='notice'>You start to [panel_open ? "close" : "open"] the camera's panel.</span>"
@@ -158,7 +158,7 @@
for(var/mob/living/silicon/ai/O in living_mob_list)
if(!O.client) continue
if(U.name == "Unknown") O << "<b>[U]</b> holds \a [itemname] up to one of your cameras ..."
else O << "<b><a href='byond://?src=\ref[O];track2=\ref[O];track=\ref[U]'>[U]</a></b> holds \a [itemname] up to one of your cameras ..."
else O << "<b><a href='byond://?src=\ref[O];track2=\ref[O];track=\ref[U];trackname=[U.name]'>[U]</a></b> holds \a [itemname] up to one of your cameras ..."
O << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", itemname, info), text("window=[]", itemname))
for(var/mob/O in player_list)
if (istype(O.machine, /obj/machinery/computer/security))
@@ -195,7 +195,7 @@
//legacy support, if choice is != 1 then just kick viewers without changing status
kick_viewers()
else
invalidateCameraCache()
update_coverage()
set_status( !src.status )
if (!(src.status))
visible_message("\red [user] has deactivated [src]!")
@@ -215,11 +215,11 @@
//Used when someone breaks a camera
/obj/machinery/camera/proc/destroy()
invalidateCameraCache()
stat |= BROKEN
kick_viewers()
triggerCameraAlarm()
update_icon()
update_coverage()
//sparks
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
@@ -364,7 +364,7 @@
network_added = 1
if(network_added)
invalidateCameraCache()
update_coverage(1)
/obj/machinery/camera/proc/remove_networks(var/list/networks)
var/network_removed
@@ -375,24 +375,24 @@
network_removed = 1
if(network_removed)
invalidateCameraCache()
update_coverage(1)
/obj/machinery/camera/proc/replace_networks(var/list/networks)
if(networks.len != network.len)
network = networks
invalidateCameraCache()
update_coverage(1)
return
for(var/new_network in networks)
if(!(new_network in network))
network = networks
invalidateCameraCache()
update_coverage(1)
return
/obj/machinery/camera/proc/clear_all_networks()
if(network.len)
network.Cut()
invalidateCameraCache()
update_coverage(1)
/obj/machinery/camera/proc/nano_structure()
var/cam[0]
@@ -403,3 +403,17 @@
cam["y"] = y
cam["z"] = z
return cam
/obj/machinery/camera/proc/update_coverage(var/network_change = 0)
if(network_change)
var/list/open_networks = difflist(network, restricted_camera_networks)
// Add or remove camera from the camera net as necessary
if(on_open_network && !open_networks.len)
cameranet.removeCamera(src)
else if(!on_open_network && open_networks.len)
on_open_network = 1
cameranet.addCamera(src)
else
cameranet.updateVisibility(src, 0)
invalidateCameraCache()

View File

@@ -78,7 +78,7 @@
if(isscrewdriver(W))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13"))
var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13"))
if(!input)
usr << "No input found please hang up and try your call again."
return
@@ -100,9 +100,6 @@
C.auto_turn()
C.replace_networks(uniquelist(tempnetwork))
tempnetwork = difflist(C.network,restricted_camera_networks)
if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility.
cameranet.removeCamera(C)
C.c_tag = input

View File

@@ -93,6 +93,6 @@
/datum/topic_state/air_alarm/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = user && (atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO))
extra_href["remote_access"] = user && (user.isAI() || atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO))
return extra_href

View File

@@ -8,9 +8,9 @@
var/obj/nano_module/alarm_monitor/engineering/alarm_monitor
/obj/machinery/computer/station_alert/New()
..()
alarm_monitor = new(src)
alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon)
..()
/obj/machinery/computer/station_alert/Del()
alarm_monitor.unregister(src)
@@ -38,7 +38,7 @@
if(stat & (BROKEN|NOPOWER))
return
var/list/alarms = alarm_monitor.active_alarms()
var/list/alarms = alarm_monitor.major_alarms()
if(alarms.len)
icon_state = "alert:2"
else

View File

@@ -86,12 +86,13 @@
if(3.0)
dat += text("<B>Records Maintenance</B><HR>\n<A href='?src=\ref[];back=1'>Backup To Disk</A><BR>\n<A href='?src=\ref[];u_load=1'>Upload From disk</A><BR>\n<A href='?src=\ref[];del_all=1'>Delete All Records</A><BR>\n<BR>\n<A href='?src=\ref[];screen=1'>Back</A>", src, src, src, src)
if(4.0)
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
var/icon/front = active1.fields["photo_front"]
var/icon/side = active1.fields["photo_side"]
usr << browse_rsc(front, "front.png")
usr << browse_rsc(side, "side.png")
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
dat += "<table><tr><td>Name: [active1.fields["name"]] \
ID: [active1.fields["id"]]<BR>\n \
Sex: <A href='?src=\ref[src];field=sex'>[active1.fields["sex"]]</A><BR>\n \

View File

@@ -3,7 +3,7 @@
/obj/machinery/atmospherics/unary/cryo_cell
name = "cryo cell"
icon = 'icons/obj/cryogenics.dmi'
icon_state = "cell-off"
icon_state = "pod0"
density = 1
anchored = 1.0
layer = 2.8
@@ -24,6 +24,11 @@
..()
initialize_directions = dir
/obj/machinery/atmospherics/unary/cryo_cell/Del()
if(occupant)
occupant.loc = loc
..()
/obj/machinery/atmospherics/unary/cryo_cell/initialize()
if(node) return
var/node_connect = dir
@@ -37,7 +42,6 @@
if(!node)
return
if(!on)
updateUsrDialog()
return
if(occupant)
@@ -52,7 +56,6 @@
if(abs(temperature_archived-air_contents.temperature) > 1)
network.update = 1
updateUsrDialog()
return 1
@@ -188,17 +191,17 @@
var/mob/M = G:affecting
if(put_mob(M))
del(G)
updateUsrDialog()
return
/obj/machinery/atmospherics/unary/cryo_cell/update_icon()
if(on)
overlays.Cut()
icon_state = "pod[on]"
if(occupant)
icon_state = "cell-occupied"
return
icon_state = "cell-on"
return
icon_state = "cell-off"
var/image/pickle = image(occupant.icon, occupant.icon_state)
pickle.overlays = occupant.overlays
pickle.pixel_y = 20
overlays += pickle
overlays += "lid[on]"
/obj/machinery/atmospherics/unary/cryo_cell/proc/process_occupant()
if(air_contents.total_moles < 10)
@@ -331,7 +334,13 @@
put_mob(usr)
return
/obj/machinery/atmospherics/unary/cryo_cell/return_air_for_internal_lifeform()
//assume that the cryo cell has some kind of breath mask or something that
//draws from the cryo tube's environment, instead of the cold internal air.
if(loc)
return loc.return_air()
else
return null
/datum/data/function/proc/reset()
return

View File

@@ -234,6 +234,12 @@
..()
/obj/machinery/cryopod/Del()
if(occupant)
occupant.loc = loc
occupant.resting = 1
..()
/obj/machinery/cryopod/initialize()
..()

View File

@@ -182,7 +182,8 @@ for reference:
else if (istype(W, /obj/item/weapon/card/emag))
if (src.emagged == 0)
src.emagged = 1
src.req_access = null
src.req_access.Cut()
src.req_one_access.Cut()
user << "You break the ID authentication lock on \the [src]."
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)

View File

@@ -34,6 +34,7 @@
idle_power_usage = 2
active_power_usage = 4
/obj/machinery/door_control/attack_ai(mob/user as mob)
if(wires & 2)
return src.attack_hand(user)
@@ -81,17 +82,16 @@
if(specialfunctions & BOLTS)
D.lock()
if(specialfunctions & SHOCK)
D.secondsElectrified = -1
D.electrify(-1)
if(specialfunctions & SAFE)
D.safe = 0
else
if(specialfunctions & IDSCAN)
D.aiDisabledIdScanner = 0
if(specialfunctions & BOLTS)
if(!D.isWireCut(4) && D.arePowerSystemsOn())
D.unlock()
if(specialfunctions & SHOCK)
D.secondsElectrified = 0
D.electrify(0)
if(specialfunctions & SAFE)
D.safe = 1

View File

@@ -7,13 +7,14 @@
explosion_resistance = 15
var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
var/hackProof = 0 // if 1, this door can't be hacked by the AI
var/secondsMainPowerLost = 0 //The number of seconds until power is restored.
var/secondsBackupPowerLost = 0 //The number of seconds until power is restored.
var/electrified_until = 0 //World time when the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
var/main_power_lost_until = 0 //World time when main power is restored.
var/backup_power_lost_until = -1 //World time when backup power is restored.
var/next_beep_at = 0 //World time when we may next beep due to doors being blocked by mobs
var/spawnPowerRestoreRunning = 0
var/welded = null
var/locked = 0
var/lights = 1 // bolt lights show by default
secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
var/aiDisabledIdScanner = 0
var/aiHacking = 0
var/obj/machinery/door/airlock/closeOther = null
@@ -217,6 +218,19 @@
mineral = "uranium"
var/last_event = 0
/obj/machinery/door/airlock/process()
// Deliberate no call to parent.
if(main_power_lost_until > 0 && world.time >= main_power_lost_until)
regainMainPower()
if(backup_power_lost_until > 0 && world.time >= backup_power_lost_until)
regainBackupPower()
else if(electrified_until > 0 && world.time >= electrified_until)
electrify(0)
..()
/obj/machinery/door/airlock/uranium/process()
if(world.time > last_event+20)
if(prob(50))
@@ -319,7 +333,7 @@ About the new airlock wires panel:
..(user)
/obj/machinery/door/airlock/proc/isElectrified()
if(src.secondsElectrified != 0)
if(src.electrified_until != 0)
return 1
return 0
@@ -336,7 +350,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/arePowerSystemsOn()
if (stat & (NOPOWER|BROKEN))
return 0
return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0)
return (src.main_power_lost_until==0 || src.backup_power_lost_until==0)
/obj/machinery/door/airlock/requiresID()
return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner)
@@ -344,48 +358,68 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/isAllPowerLoss()
if(stat & (NOPOWER|BROKEN))
return 1
if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))
if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))
if(mainPowerCablesCut() && backupPowerCablesCut())
return 1
return 0
/obj/machinery/door/airlock/proc/regainMainPower()
if(src.secondsMainPowerLost > 0)
src.secondsMainPowerLost = 0
/obj/machinery/door/airlock/proc/mainPowerCablesCut()
return src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)
/obj/machinery/door/airlock/proc/backupPowerCablesCut()
return src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)
/obj/machinery/door/airlock/proc/loseMainPower()
if(src.secondsMainPowerLost <= 0)
src.secondsMainPowerLost = 60
if(src.secondsBackupPowerLost < 10)
src.secondsBackupPowerLost = 10
if(!src.spawnPowerRestoreRunning)
src.spawnPowerRestoreRunning = 1
spawn(0)
var/cont = 1
while (cont)
sleep(10)
cont = 0
if(src.secondsMainPowerLost>0)
if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)))
src.secondsMainPowerLost -= 1
src.updateDialog()
cont = 1
main_power_lost_until = mainPowerCablesCut() ? -1 : world.time + SecondsToTicks(60)
if(src.secondsBackupPowerLost>0)
if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)))
src.secondsBackupPowerLost -= 1
src.updateDialog()
cont = 1
src.spawnPowerRestoreRunning = 0
src.updateDialog()
// If backup power is permanently disabled then activate in 10 seconds if possible, otherwise it's already enabled or a timer is already running
if(backup_power_lost_until == -1 && !backupPowerCablesCut())
backup_power_lost_until = world.time + SecondsToTicks(10)
// Disable electricity if required
if(electrified_until && isAllPowerLoss())
electrify(0)
/obj/machinery/door/airlock/proc/loseBackupPower()
if(src.secondsBackupPowerLost < 60)
src.secondsBackupPowerLost = 60
backup_power_lost_until = backupPowerCablesCut() ? -1 : world.time + SecondsToTicks(60)
// Disable electricity if required
if(electrified_until && isAllPowerLoss())
electrify(0)
/obj/machinery/door/airlock/proc/regainMainPower()
if(!mainPowerCablesCut())
main_power_lost_until = 0
// If backup power is currently active then disable, otherwise let it count down and disable itself later
if(!backup_power_lost_until)
backup_power_lost_until = -1
/obj/machinery/door/airlock/proc/regainBackupPower()
if(src.secondsBackupPowerLost > 0)
src.secondsBackupPowerLost = 0
if(!backupPowerCablesCut())
// Restore backup power only if main power is offline, otherwise permanently disable
backup_power_lost_until = main_power_lost_until == 0 ? -1 : 0
/obj/machinery/door/airlock/proc/electrify(var/duration, var/feedback = 0)
var/message = ""
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY) && arePowerSystemsOn())
message = text("The electrification wire is cut - Door permanently electrified.")
src.electrified_until = -1
else if(duration && !arePowerSystemsOn())
message = text("The door is unpowered - Cannot electrify the door.")
src.electrified_until = 0
else if(!duration && electrified_until != 0)
message = "The door is now un-electrified."
src.electrified_until = 0
else if(duration) //electrify door for the given duration seconds
if(usr)
shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])")
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Electrified the [name] at [x] [y] [z]</font>")
else
shockedby += text("\[[time_stamp()]\] - EMP)")
message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]."
src.electrified_until = duration == -1 ? -1 : world.time + SecondsToTicks(duration)
if(feedback && message)
usr << message
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
@@ -407,7 +441,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/update_icon()
if(overlays) overlays.Cut()
if(density)
if(locked && lights)
if(locked && lights && src.arePowerSystemsOn())
icon_state = "door_locked"
else
icon_state = "door_closed"
@@ -428,7 +462,6 @@ About the new airlock wires panel:
icon_state = "door_open"
if((stat & BROKEN) && !(stat & NOPOWER))
overlays += image(icon, "sparks_open")
return
/obj/machinery/door/airlock/do_animate(animation)
@@ -457,114 +490,36 @@ About the new airlock wires panel:
if("deny")
if(density && src.arePowerSystemsOn())
flick("door_deny", src)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
return
/obj/machinery/door/airlock/attack_ai(mob/user as mob)
if (!check_synth_access(user))
return
ui_interact(user)
//Separate interface for the AI.
user.set_machine(src)
var/t1 = text("<B>Airlock Control</B><br>\n")
if(src.secondsMainPowerLost > 0)
if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)))
t1 += text("Main power is offline for [] seconds.<br>\n", src.secondsMainPowerLost)
else
t1 += text("Main power is offline indefinitely.<br>\n")
else
t1 += text("Main power is online.")
/obj/machinery/door/airlock/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
if(src.secondsBackupPowerLost > 0)
if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)))
t1 += text("Backup power is offline for [] seconds.<br>\n", src.secondsBackupPowerLost)
else
t1 += text("Backup power is offline indefinitely.<br>\n")
else if(src.secondsMainPowerLost > 0)
t1 += text("Backup power is online.")
else
t1 += text("Backup power is offline, but will turn on if main power fails.")
t1 += "<br>\n"
data["main_power_loss"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1)
data["backup_power_loss"] = round(backup_power_lost_until > 0 ? max(backup_power_lost_until - world.time, 0) / 10 : backup_power_lost_until, 1)
data["electrified"] = round(electrified_until > 0 ? max(electrified_until - world.time, 0) / 10 : electrified_until, 1)
data["open"] = !density
if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
t1 += text("IdScan wire is cut.<br>\n")
else if(src.aiDisabledIdScanner)
t1 += text("IdScan disabled. <A href='?src=\ref[];aiEnable=1'>Enable?</a><br>\n", src)
else
t1 += text("IdScan enabled. <A href='?src=\ref[];aiDisable=1'>Disable?</a><br>\n", src)
var/commands[0]
commands[++commands.len] = list("name" = "IdScan", "command"= "idscan", "active" = !aiDisabledIdScanner, "enabled" = "Enabled", "disabled" = "Disable", "danger" = 0, "act" = 1)
commands[++commands.len] = list("name" = "Bolts", "command"= "bolts", "active" = !locked, "enabled" = "Raised ", "disabled" = "Dropped", "danger" = 0, "act" = 0)
commands[++commands.len] = list("name" = "Bolt Lights", "command"= "lights", "active" = lights, "enabled" = "Enabled", "disabled" = "Disable", "danger" = 0, "act" = 1)
commands[++commands.len] = list("name" = "Safeties", "command"= "safeties", "active" = safe, "enabled" = "Nominal", "disabled" = "Overridden", "danger" = 1, "act" = 0)
commands[++commands.len] = list("name" = "Timing", "command"= "timing", "active" = normalspeed, "enabled" = "Nominal", "disabled" = "Overridden", "danger" = 1, "act" = 0)
commands[++commands.len] = list("name" = "Door State", "command"= "open", "active" = density, "enabled" = "Closed", "disabled" = "Opened", "danger" = 0, "act" = 0)
if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1))
t1 += text("Main Power Input wire is cut.<br>\n")
if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))
t1 += text("Main Power Output wire is cut.<br>\n")
if(src.secondsMainPowerLost == 0)
t1 += text("<A href='?src=\ref[];aiDisable=2'>Temporarily disrupt main power?</a>.<br>\n", src)
if(src.secondsBackupPowerLost == 0)
t1 += text("<A href='?src=\ref[];aiDisable=3'>Temporarily disrupt backup power?</a>.<br>\n", src)
if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1))
t1 += text("Backup Power Input wire is cut.<br>\n")
if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))
t1 += text("Backup Power Output wire is cut.<br>\n")
if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
t1 += text("Door bolt control wire is cut.<br>\n")
else if(!src.locked)
t1 += text("Door bolts are up. <A href='?src=\ref[];aiDisable=4'>Drop them?</a><br>\n", src)
else
t1 += text("Door bolts are down.")
if(src.arePowerSystemsOn())
t1 += text(" <A href='?src=\ref[];aiEnable=4'>Raise?</a><br>\n", src)
else
t1 += text(" Cannot raise door bolts due to power failure.<br>\n")
if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
t1 += text("Door bolt lights wire is cut.<br>\n")
else if(!src.lights)
t1 += text("Door lights are off. <A href='?src=\ref[];aiEnable=10'>Enable?</a><br>\n", src)
else
t1 += text("Door lights are on. <A href='?src=\ref[];aiDisable=10'>Disable?</a><br>\n", src)
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
t1 += text("Electrification wire is cut.<br>\n")
if(src.secondsElectrified==-1)
t1 += text("Door is electrified indefinitely. <A href='?src=\ref[];aiDisable=5'>Un-electrify it?</a><br>\n", src)
else if(src.secondsElectrified>0)
t1 += text("Door is electrified temporarily ([] seconds). <A href='?src=\ref[];aiDisable=5'>Un-electrify it?</a><br>\n", src.secondsElectrified, src)
else
t1 += text("Door is not electrified. <A href='?src=\ref[];aiEnable=5'>Electrify it for 30 seconds?</a> Or, <A href='?src=\ref[];aiEnable=6'>Electrify it indefinitely until someone cancels the electrification?</a><br>\n", src, src)
if(src.isWireCut(AIRLOCK_WIRE_SAFETY))
t1 += text("Door force sensors not responding.</a><br>\n")
else if(src.safe)
t1 += text("Door safeties operating normally. <A href='?src=\ref[];aiDisable=8'> Override?</a><br>\n",src)
else
t1 += text("Danger. Door safeties disabled. <A href='?src=\ref[];aiEnable=8'> Restore?</a><br>\n",src)
if(src.isWireCut(AIRLOCK_WIRE_SPEED))
t1 += text("Door timing circuitry not responding.</a><br>\n")
else if(src.normalspeed)
t1 += text("Door timing circuitry operating normally. <A href='?src=\ref[];aiDisable=9'> Override?</a><br>\n",src)
else
t1 += text("Warning. Door timing circuitry operating abnormally. <A href='?src=\ref[];aiEnable=9'> Restore?</a><br>\n",src)
if(src.welded)
t1 += text("Door appears to have been welded shut.<br>\n")
else if(!src.locked)
if(src.density)
t1 += text("<A href='?src=\ref[];aiEnable=7'>Open door</a><br>\n", src)
else
t1 += text("<A href='?src=\ref[];aiDisable=7'>Close door</a><br>\n", src)
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
user << browse(t1, "window=airlock")
onclose(user, "airlock")
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door
data["commands"] = commands
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "door_control.tmpl", "Door Controls", 450, 350)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/door/airlock/proc/hack(mob/user as mob)
if(src.aiHacking==0)
@@ -655,10 +610,13 @@ About the new airlock wires panel:
..(user)
return
/obj/machinery/door/airlock/proc/check_synth_access(mob/user as mob)
/obj/machinery/door/airlock/CanUseTopic(var/mob/user, href_list)
if(!user.isSilicon())
return STATUS_CLOSE
if(operating < 0) //emagged
user << "<span class='warning'>Unable to interface: Internal error.</span>"
return 0
return STATUS_CLOSE
if(!src.canAIControl())
if(src.canAIHack(user))
src.hack(user)
@@ -667,201 +625,80 @@ About the new airlock wires panel:
user << "<span class='warning'>Unable to interface: Connection timed out.</span>"
else
user << "<span class='warning'>Unable to interface: Connection refused.</span>"
return 0
return 1
return STATUS_CLOSE
return STATUS_INTERACTIVE
/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
if(..())
return 1
if(href_list["close"])
usr << browse(null, "window=airlock")
if(usr.machine==src)
usr.unset_machine()
return 1
if((in_range(src, usr) && istype(src.loc, /turf)) && src.p_open)
usr.set_machine(src)
if(istype(usr, /mob/living/silicon))
if (!check_synth_access(usr))
return 1
//AI
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed
if(href_list["aiDisable"])
var/code = text2num(href_list["aiDisable"])
switch (code)
if(1)
//disable idscan
var/activate = text2num(href_list["activate"])
switch (href_list["command"])
if("idscan")
if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
usr << "The IdScan wire has been cut - The IdScan feature is already disabled."
else if(src.aiDisabledIdScanner)
usr << "The IdScan feature is already disabled."
else
usr << "The IdScan feature has been disabled."
usr << "The IdScan wire has been cut - IdScan feature permanently disabled."
else if(activate && src.aiDisabledIdScanner)
src.aiDisabledIdScanner = 0
usr << "IdScan feature has been enabled."
else if(!activate && !src.aiDisabledIdScanner)
src.aiDisabledIdScanner = 1
if(2)
//disrupt main power
if(src.secondsMainPowerLost == 0)
usr << "IdScan feature has been disabled."
if("main_power")
if(!main_power_lost_until)
src.loseMainPower()
else
usr << "Main power is already offline."
if(3)
//disrupt backup power
if(src.secondsBackupPowerLost == 0)
if("backup_power")
if(!backup_power_lost_until)
src.loseBackupPower()
else
usr << "Backup power is already offline."
if(4)
//drop door bolts
if("bolts")
if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
usr << "The door bolt control wire has been cut - The door bolts are already dropped."
else if(src.locked)
usr << "The door bolts are already dropped."
else
if(src.lock())
usr << "The door bolt control wire has been cut - Door bolts permanently dropped."
else if(activate && src.lock())
usr << "The door bolts have been dropped."
if(5)
//un-electrify door
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
usr << text("The electrification wire is cut - Cannot un-electrify the door.")
else if(secondsElectrified != 0)
usr << "The door is now un-electrified."
src.secondsElectrified = 0
if(7)
//close door
else if(!activate && src.unlock())
usr << "The door bolts have been raised."
if("electrify_temporary")
electrify(30 * activate, 1)
if("electrify_permanently")
electrify(-1 * activate, 1)
if("open")
if(src.welded)
usr << text("The airlock has been welded shut!")
else if(src.locked)
usr << text("The door bolts are down!")
else if(!src.density)
close()
else
else if(activate && density)
open()
if(8)
else if(!activate && !density)
close()
if("safeties")
// Safeties! We don't need no stinking safeties!
if (src.isWireCut(AIRLOCK_WIRE_SAFETY))
usr << text("Control to door sensors is disabled.")
else if (src.safe)
usr << text("The safety wire is cut - Cannot secure the door.")
else if (activate && src.safe)
safe = 0
else
usr << text("Firmware reports safeties already overridden.")
if(9)
else if (!activate && !src.safe)
safe = 1
if("timing")
// Door speed control
if(src.isWireCut(AIRLOCK_WIRE_SPEED))
usr << text("Control to door timing circuitry has been severed.")
else if (src.normalspeed)
usr << text("The timing wire is cut - Cannot alter timing.")
else if (activate && src.normalspeed)
normalspeed = 0
else
usr << text("Door timing circuity already accelerated.")
if(10)
else if (!activate && !src.normalspeed)
normalspeed = 1
if("lights")
// Bolt lights
if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
usr << "The bolt lights wire has been cut - The door bolt lights are already disabled."
else if (src.lights)
usr << "The bolt lights wire has been cut - The door bolt lights are permanently disabled."
else if (!activate && src.lights)
lights = 0
usr << "The door bolt lights have been disabled."
else
usr << "The door bolt lights are already disabled!"
else if(href_list["aiEnable"])
var/code = text2num(href_list["aiEnable"])
switch (code)
if(1)
//enable idscan
if(src.isWireCut(AIRLOCK_WIRE_IDSCAN))
usr << "The IdScan wire has been cut - The IdScan feature cannot be enabled."
else if(src.aiDisabledIdScanner)
usr << "The IdScan feature has been enabled."
src.aiDisabledIdScanner = 0
else
usr << "The IdScan feature is already enabled."
if(4)
//raise door bolts
if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
usr << "The door bolt control wire has been cut - The door bolts cannot be raised."
else if(!src.locked)
usr << "The door bolts are already raised."
else
if(src.unlock())
usr << "The door bolts have been raised."
else
usr << "Unable to raise door bolts."
if(5)
//electrify door for 30 seconds
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
usr << text("The electrification wire has been cut.<br>\n")
else if(src.secondsElectrified==-1)
usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.<br>\n")
else if(src.secondsElectrified!=0)
usr << text("The door is already electrified. Cannot re-electrify it while it's already electrified.<br>\n")
else
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Electrified the [name] at [x] [y] [z]</font>")
usr << "The door is now electrified for thirty seconds."
src.secondsElectrified = 30
spawn(10)
while (src.secondsElectrified>0)
src.secondsElectrified-=1
if(src.secondsElectrified<0)
src.secondsElectrified = 0
sleep(10)
if(6)
//electrify door indefinitely
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
usr << text("The electrification wire has been cut.<br>\n")
else if(src.secondsElectrified==-1)
usr << text("The door is already indefinitely electrified.<br>\n")
else if(src.secondsElectrified!=0)
usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.<br>\n")
else
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Electrified the [name] at [x] [y] [z]</font>")
usr << "The door is now electrified."
src.secondsElectrified = -1
if(7)
//open door
if(src.welded)
usr << text("The airlock has been welded shut!")
else if(src.locked)
usr << text("The door bolts are down!")
else if(src.density)
open()
else
close()
if (8)
// Safeties! Maybe we do need some stinking safeties!
if (src.isWireCut(AIRLOCK_WIRE_SAFETY))
usr << text("Control to door sensors is disabled.")
else if (!src.safe)
safe = 1
else
usr << text("Firmware reports safeties already in place.")
if(9)
// Door speed control
if(src.isWireCut(AIRLOCK_WIRE_SPEED))
usr << text("Control to door timing circuitry has been severed.")
else if (!src.normalspeed)
normalspeed = 1
else
usr << text("Door timing circuity currently operating normally.")
if(10)
// Bolt lights
if(src.isWireCut(AIRLOCK_WIRE_LIGHT))
usr << "The bolt lights wire has been cut - The door bolt lights cannot be enabled."
else if (!src.lights)
else if (activate && !src.lights)
lights = 1
usr << "The door bolt lights have been enabled"
else
usr << "The door bolt lights are already enabled!"
usr << "The door bolt lights have been enabled."
add_fingerprint(usr)
update_icon()
if(!nowindow)
updateUsrDialog()
return 0
return 1
/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob)
//world << text("airlock attackby src [] obj [] mob []", src, C, user)
@@ -988,7 +825,7 @@ About the new airlock wires panel:
return
/obj/machinery/door/airlock/open(var/forced=0)
if( operating || welded || locked )
if(!can_open())
return 0
if(!forced)
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
@@ -1002,20 +839,32 @@ About the new airlock wires panel:
src.closeOther.close()
return ..()
/obj/machinery/door/airlock/close(var/forced=0)
if(operating || welded || locked)
return
/obj/machinery/door/airlock/can_open()
if(locked || welded)
return 0
return ..()
/obj/machinery/door/airlock/can_close(var/forced)
if(locked || welded)
return 0
if(!forced)
//despite the name, this wire is for general door control.
//Bolts are already covered by the check for locked, above
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return 0
return ..()
/obj/machinery/door/airlock/close(var/forced=0)
if(!can_close(forced))
return
if(safe)
for(var/turf/turf in locs)
if(locate(/mob/living) in turf)
// playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) //THE BUZZING IT NEVER STOPS -Pete
spawn (60)
close()
if(world.time > next_beep_at)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
next_beep_at = world.time + SecondsToTicks(10)
close_door_at = world.time + 6
return
for(var/turf/turf in locs)
@@ -1053,7 +902,10 @@ About the new airlock wires panel:
return
/obj/machinery/door/airlock/proc/lock(var/forced=0)
if (operating || src.locked) return 0
if(locked)
return 0
if (operating && !forced) return 0
src.locked = 1
for(var/mob/M in range(1,src))
@@ -1062,21 +914,23 @@ About the new airlock wires panel:
return 1
/obj/machinery/door/airlock/proc/unlock(var/forced=0)
if (operating || !src.locked) return
if(!src.locked)
return
if (!forced)
if(operating || !src.arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) return
if (forced || (src.arePowerSystemsOn())) //only can raise bolts if power's on
src.locked = 0
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
update_icon()
return 1
return 0
/obj/machinery/door/airlock/New(var/newloc, var/obj/structure/door_assembly/assembly=null)
..()
//if assembly is given, create the new door from the assembly
if (assembly)
if (assembly && istype(assembly))
assembly_type = assembly.type
electronics = assembly.electronics
@@ -1085,9 +939,10 @@ About the new airlock wires panel:
//update the door's access to match the electronics'
secured_wires = electronics.secure
if(electronics.one_access)
req_access = null
req_access.Cut()
req_one_access = src.electronics.conf_access
else
req_one_access.Cut()
req_access = src.electronics.conf_access
//get the name from the assembly
@@ -1128,8 +983,19 @@ About the new airlock wires panel:
electronics.conf_access = src.req_one_access
electronics.one_access = 1
/obj/machinery/door/airlock/emp_act(var/severity)
if(prob(40/severity))
var/duration = world.time + SecondsToTicks(30 / severity)
if(duration > electrified_until)
electrify(duration)
..()
/obj/machinery/door/airlock/power_change() //putting this is obj/machinery/door itself makes non-airlock doors turn invisible for some reason
..()
if(stat & NOPOWER)
// If we lost power, disable electrification
// Keeping door lights on, runs on internal battery or something.
electrified_until = 0
update_icon()
/obj/machinery/door/airlock/proc/prison_open()

View File

@@ -16,7 +16,6 @@
var/open_layer = DOOR_OPEN_LAYER
var/closed_layer = DOOR_CLOSED_LAYER
var/secondsElectrified = 0
var/visible = 1
var/p_open = 0
var/operating = 0
@@ -32,6 +31,7 @@
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
var/obj/item/stack/sheet/metal/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/close_door_at = 0 //When to automatically close the door, if possible
//Multi-tile doors
dir = EAST
@@ -75,8 +75,23 @@
..()
return
//process()
//return
/obj/machinery/door/process()
if(close_door_at && world.time >= close_door_at)
if(autoclose)
close_door_at = next_close_time()
close()
else
close_door_at = 0
/obj/machinery/door/proc/can_open()
if(!density || operating || !ticker)
return 0
return 1
/obj/machinery/door/proc/can_close(var/forced = 0)
if(!density && !operating && !(!forced && (stat & (BROKEN|NOPOWER))))
return 1
return 0
/obj/machinery/door/Bumped(atom/AM)
if(p_open || operating) return
@@ -101,7 +116,7 @@
if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
open()
else
flick("door_deny", src)
do_animate("deny")
return
if(istype(AM, /obj/structure/bed/chair/wheelchair))
var/obj/structure/bed/chair/wheelchair/wheel = AM
@@ -109,7 +124,7 @@
if(wheel.pulling && (src.allowed(wheel.pulling)))
open()
else
flick("door_deny", src)
do_animate("deny")
return
return
@@ -126,12 +141,9 @@
if(user.last_airflow > world.time - vsc.airflow_delay) //Fakkit
return
src.add_fingerprint(user)
if(!src.requiresID())
user = null
if(density)
if(allowed(user)) open()
else flick("door_deny", src)
else do_animate("deny")
return
/obj/machinery/door/meteorhit(obj/M as obj)
@@ -193,10 +205,6 @@
return
if(src.operating > 0 || isrobot(user)) return //borgs can't attack doors open because it conflicts with their AI-like interaction with them.
src.add_fingerprint(user)
if(!Adjacent(user))
user = null
if(!src.requiresID())
user = null
if(istype(I, /obj/item/stack/sheet/metal))
if(stat & BROKEN)
@@ -268,7 +276,7 @@
if(src.operating) return
if(src.density && (operable() && istype(I, /obj/item/weapon/card/emag)))
flick("door_spark", src)
do_animate("spark")
sleep(6)
open()
operating = -1
@@ -281,8 +289,8 @@
close()
return
if(src.density && !(stat & (NOPOWER|BROKEN)))
flick("door_deny", src)
if(src.density)
do_animate("deny")
return
/obj/machinery/door/proc/take_damage(var/damage)
@@ -317,11 +325,6 @@
/obj/machinery/door/emp_act(severity)
if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) )
open()
if(prob(40/severity))
if(secondsElectrified == 0)
secondsElectrified = -1
spawn(300)
secondsElectrified = 0
..()
@@ -364,23 +367,27 @@
flick("o_doorc1", src)
else
flick("doorc1", src)
if("spark")
if(density)
flick("door_spark", src)
if("deny")
if(density && !(stat & (NOPOWER|BROKEN)))
flick("door_deny", src)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
return
/obj/machinery/door/proc/open()
if(!density) return 1
if(operating > 0) return
if(!ticker) return 0
if(!can_open()) return
if(!operating) operating = 1
do_animate("opening")
icon_state = "door0"
src.SetOpacity(0)
sleep(10)
src.layer = open_layer
sleep(3)
src.density = 0
sleep(7)
src.layer = open_layer
explosion_resistance = 0
update_icon()
SetOpacity(0)
@@ -388,26 +395,26 @@
if(operating) operating = 0
if(autoclose && normalspeed)
spawn(150)
autoclose()
if(autoclose && !normalspeed)
spawn(5)
autoclose()
if(autoclose)
close_door_at = next_close_time()
return 1
/obj/machinery/door/proc/next_close_time()
return world.time + (normalspeed ? 150 : 5)
/obj/machinery/door/proc/close()
if(density) return 1
if(operating > 0) return
if(!can_close())
return
operating = 1
close_door_at = 0
do_animate("closing")
sleep(3)
src.density = 1
explosion_resistance = initial(explosion_resistance)
src.layer = closed_layer
do_animate("closing")
sleep(10)
sleep(7)
update_icon()
if(visible && !glass)
SetOpacity(1) //caaaaarn!
@@ -423,6 +430,11 @@
/obj/machinery/door/proc/requiresID()
return 1
/obj/machinery/door/allowed(mob/M)
if(!requiresID())
return ..(null) //don't care who they are or what they have, act as if they're NOTHING
return ..(M)
/obj/machinery/door/update_nearby_tiles(need_rebuild)
if(!air_master)
return 0
@@ -440,12 +452,6 @@
else
source.thermal_conductivity = initial(source.thermal_conductivity)
/obj/machinery/door/proc/autoclose()
var/obj/machinery/door/airlock/A = src
if(!A.density && !A.operating && !A.locked && !A.welded && !(A.stat & (BROKEN|NOPOWER)) && A.autoclose)
close()
return
/obj/machinery/door/Move(new_loc, new_dir)
//update_nearby_tiles()
. = ..()

View File

@@ -234,9 +234,6 @@
src.add_fingerprint(user)
if (!src.requiresID())
//don't care who they are or what they have, act as if they're NOTHING
user = null
if (src.allowed(user))
if (src.density)

View File

@@ -13,9 +13,6 @@ var/list/doppler_arrays = list()
doppler_arrays -= src
..()
/obj/machinery/doppler_array/process()
return PROCESS_KILL
/obj/machinery/doppler_array/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range,var/took)
if(stat & NOPOWER) return
if(z != z0) return

View File

@@ -12,6 +12,8 @@
var/strength = 10 //How weakened targets are when flashed.
var/base_state = "mflash"
anchored = 1
use_power = 1
idle_power_usage = 2
/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored
name = "portable flasher"
@@ -133,7 +135,7 @@
active = 1
icon_state = "launcheract"
for(var/obj/machinery/flasher/M in world)
for(var/obj/machinery/flasher/M in machines)
if(M.id == src.id)
spawn()
M.flash()

View File

@@ -5,25 +5,30 @@
icon = 'icons/obj/holosign.dmi'
icon_state = "sign_off"
layer = 4
use_power = 1
idle_power_usage = 2
active_power_usage = 4
var/lit = 0
var/id = null
var/on_icon = "sign_on"
proc/toggle()
/obj/machinery/holosign/proc/toggle()
if (stat & (BROKEN|NOPOWER))
return
lit = !lit
use_power = lit ? 2 : 1
update_icon()
update_icon()
/obj/machinery/holosign/update_icon()
if (!lit)
icon_state = "sign_off"
else
icon_state = on_icon
power_change()
/obj/machinery/holosign/power_change()
if (stat & NOPOWER)
lit = 0
use_power = 0
update_icon()
/obj/machinery/holosign/surgery

View File

@@ -53,6 +53,10 @@
var/last_spark = 0
var/base_state = "migniter"
anchored = 1
use_power = 1
idle_power_usage = 2
active_power_usage = 4
/obj/machinery/sparker/New()
..()
@@ -129,12 +133,12 @@
active = 1
icon_state = "launcheract"
for(var/obj/machinery/sparker/M in world)
for(var/obj/machinery/sparker/M in machines)
if (M.id == src.id)
spawn( 0 )
M.ignite()
for(var/obj/machinery/igniter/M in world)
for(var/obj/machinery/igniter/M in machines)
if(M.id == src.id)
use_power(50)
M.on = !( M.on )

View File

@@ -16,6 +16,9 @@ datum/track/New(var/title_name, var/audio)
anchored = 1
density = 1
power_channel = EQUIP
use_power = 1
idle_power_usage = 10
active_power_usage = 100
var/playing = 0
@@ -32,6 +35,7 @@ datum/track/New(var/title_name, var/audio)
new/datum/track("Trai`Tor", 'sound/music/traitor.ogg'),
)
/obj/machinery/media/jukebox/Del()
StopPlaying()
..()
@@ -190,6 +194,7 @@ datum/track/New(var/title_name, var/audio)
related_area.forced_ambience = null
playing = 0
update_use_power(1)
update_icon()
@@ -207,4 +212,5 @@ datum/track/New(var/title_name, var/audio)
related_area.play_ambience(related_area)
playing = 1
update_use_power(2)
update_icon()

View File

@@ -58,7 +58,7 @@
/obj/machinery/smartfridge/secure/extract
name = "\improper Slime Extract Storage"
desc = "A refrigerated storage unit for slime extracts"
req_access_txt = "47"
req_access = list(access_research)
/obj/machinery/smartfridge/secure/extract/accept_check(var/obj/item/O as obj)
if(istype(O,/obj/item/slime_extract))
@@ -70,7 +70,7 @@
desc = "A refrigerated storage unit for storing medicine and chemicals."
icon_state = "smartfridge" //To fix the icon in the map editor.
icon_on = "smartfridge_chem"
req_one_access_txt = "5;33"
req_one_access = list(access_medical,access_chemistry)
/obj/machinery/smartfridge/secure/medbay/accept_check(var/obj/item/O as obj)
if(istype(O,/obj/item/weapon/reagent_containers/glass/))
@@ -84,7 +84,7 @@
/obj/machinery/smartfridge/secure/virology
name = "\improper Refrigerated Virus Storage"
desc = "A refrigerated storage unit for storing viral material."
req_access_txt = "39"
req_access = list(access_virology)
icon_state = "smartfridge_virology"
icon_on = "smartfridge_virology"
icon_off = "smartfridge_virology-off"

View File

@@ -126,8 +126,11 @@ Class Procs:
..()
/obj/machinery/process()//If you dont use process or power why are you here
if(!(use_power || idle_power_usage || active_power_usage))
return PROCESS_KILL
return
/obj/machinery/emp_act(severity)
if(use_power && stat == 0)
use_power(7500/severity)

View File

@@ -16,7 +16,7 @@
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
proc/drive(amount)
/obj/machinery/mass_driver/proc/drive(amount)
if(stat & (BROKEN|NOPOWER))
return
use_power(500)
@@ -35,7 +35,7 @@
flick("mass_driver1", src)
return
emp_act(severity)
/obj/machinery/mass_driver/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
return
drive()

View File

@@ -56,6 +56,7 @@
var/datum/effect/effect/system/spark_spread/spark_system //the spark system, used for generating... sparks?
var/wrenching = 0
var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range
/obj/machinery/porta_turret/stationary
lethal = 1
@@ -502,6 +503,9 @@
return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee
/obj/machinery/porta_turret/proc/tryToShootAt(var/list/mob/living/targets)
if(targets.len && last_target && (last_target in targets) && target(last_target))
return 1
while(targets.len > 0)
var/mob/living/M = pick(targets)
targets -= M
@@ -527,6 +531,7 @@
update_icon()
/obj/machinery/porta_turret/proc/popDown() //pops the turret down
last_target = null
if(disabled)
return
if(raising || !raised)
@@ -555,7 +560,8 @@
/obj/machinery/porta_turret/proc/target(var/mob/living/target)
if(disabled)
return
if(target && (target.stat != DEAD) && (!(target.lying) || emagged))
if(target)
last_target = target
spawn()
popUp() //pop the turret up if it's not already up.
set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
@@ -566,7 +572,7 @@
/obj/machinery/porta_turret/proc/shootAt(var/mob/living/target)
//any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power!
if(!(emagged || lethal)) //if it hasn't been emagged, it has to obey a cooldown rate
if(!emagged) //if it hasn't been emagged, it has to obey a cooldown rate
if(last_fired || !raised) //prevents rapid-fire shooting, unless it's been emagged
return
last_fired = 1
@@ -592,12 +598,14 @@
A = new projectile(loc)
playsound(loc, shot_sound, 75, 1)
A.original = target
if(!(emagged || lethal))
use_power(reqpower)
else
use_power(reqpower * 2)
// Lethal/emagged turrets use twice the power due to higher energy beams
// Emagged turrets again use twice as much power due to higher firing rates
use_power(reqpower * (2 * (emagged || lethal)) * (2 * emagged))
//Shooting Code:
A.current = T
A.starting = T
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn(1)

View File

@@ -617,6 +617,7 @@
/obj/machinery/suit_cycler/Del()
del(wires) // qdel
wires = null
..()
/obj/machinery/suit_cycler/engineering
name = "Engineering suit cycler"

View File

@@ -175,6 +175,7 @@
active_power_usage = 2000
var/obj/machinery/computer/teleporter/com
/obj/machinery/teleport/hub/New()
..()
underlays.Cut()
@@ -335,6 +336,8 @@
if (com)
com.icon_state = "tele1"
use_power(5000)
update_use_power(2)
com.update_use_power(2)
for(var/mob/O in hearers(src, null))
O.show_message("\blue Teleporter engaged!", 2)
src.add_fingerprint(usr)
@@ -348,6 +351,8 @@
if (com)
com.icon_state = "tele0"
com.accurate = 0
com.update_use_power(1)
update_use_power(1)
for(var/mob/O in hearers(src, null))
O.show_message("\blue Teleporter disengaged!", 2)
src.add_fingerprint(usr)

View File

@@ -38,7 +38,6 @@
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
if(robot)
robot.SetLockDown(0)
robot.notify_ai(1)
/obj/machinery/transformer/conveyor/New()
..()

View File

@@ -265,6 +265,7 @@
A = new /obj/item/projectile/energy/electrode( loc )
use_power(200)
A.current = T
A.starting = T
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn( 0 )

View File

@@ -700,7 +700,7 @@
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?"
product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
req_access_txt = "25"
req_access = list(access_bar)
/obj/machinery/vending/assist
products = list( /obj/item/device/assembly/prox_sensor = 5,/obj/item/device/assembly/igniter = 3,/obj/item/device/assembly/signaler = 4,
@@ -788,7 +788,7 @@
icon_state = "med"
icon_deny = "med-deny"
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
req_access_txt = "5"
req_access = list(access_medical)
products = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4,
/obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12,
@@ -812,7 +812,7 @@
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
icon_deny = "wallmed-deny"
req_access_txt = "5"
req_access = list(access_medical)
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/weapon/reagent_containers/hypospray/autoinjector = 4,/obj/item/device/healthanalyzer = 1)
contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/pill/tox = 1)
@@ -822,7 +822,7 @@
desc = "Wall-mounted Medical Equipment dispenser."
icon_state = "wallmed"
icon_deny = "wallmed-deny"
req_access_txt = "5"
req_access = list(access_medical)
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 5,/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,/obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment =3,/obj/item/device/healthanalyzer = 3)
@@ -834,10 +834,10 @@
product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?"
icon_state = "sec"
icon_deny = "sec-deny"
req_access_txt = "1"
req_access = list(access_security)
products = list(/obj/item/weapon/handcuffs = 8,/obj/item/weapon/grenade/flashbang = 4,/obj/item/device/flash = 5,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12,/obj/item/weapon/storage/box/evidence = 6)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/donut_box = 2)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/box/donut = 2)
/obj/machinery/vending/hydronutrients
name = "NutriMax"
@@ -927,7 +927,7 @@
desc = "Tools for tools."
icon_state = "tool"
icon_deny = "tool-deny"
//req_access_txt = "12" //Maintenance access
//req_access = list(access_maint_tunnels) //Maintenance access
products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/weapon/crowbar = 5,/obj/item/weapon/weldingtool = 3,/obj/item/weapon/wirecutters = 5,
/obj/item/weapon/wrench = 5,/obj/item/device/analyzer = 5,/obj/item/device/t_scanner = 5,/obj/item/weapon/screwdriver = 5)
contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2)
@@ -938,7 +938,7 @@
desc = "Spare tool vending. What? Did you expect some witty description?"
icon_state = "engivend"
icon_deny = "engivend-deny"
req_access_txt = "11" //Engineering Equipment access
req_access = list(access_engine_equip) //Engineering Equipment access
products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,/obj/item/weapon/airalarm_electronics = 10,/obj/item/weapon/cell/high = 10)
contraband = list(/obj/item/weapon/cell/potato = 3)
premium = list(/obj/item/weapon/storage/belt/utility = 3)
@@ -949,7 +949,7 @@
desc = "Everything you need for do-it-yourself station repair."
icon_state = "engi"
icon_deny = "engi-deny"
req_access_txt = "11"
req_access = list(access_engine_equip)
products = list(/obj/item/clothing/under/rank/chief_engineer = 4,/obj/item/clothing/under/rank/engineer = 4,/obj/item/clothing/shoes/orange = 4,/obj/item/clothing/head/hardhat = 4,
/obj/item/weapon/storage/belt/utility = 4,/obj/item/clothing/glasses/meson = 4,/obj/item/clothing/gloves/yellow = 4, /obj/item/weapon/screwdriver = 12,
/obj/item/weapon/crowbar = 12,/obj/item/weapon/wirecutters = 12,/obj/item/device/multitool = 12,/obj/item/weapon/wrench = 12,/obj/item/device/t_scanner = 12,
@@ -966,7 +966,7 @@
desc = "All the tools you need to create your own robot army."
icon_state = "robotics"
icon_deny = "robotics-deny"
req_access_txt = "29"
req_access = list(access_robotics)
products = list(/obj/item/clothing/suit/storage/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash = 4,
/obj/item/weapon/cell/high = 12, /obj/item/device/assembly/prox_sensor = 3,/obj/item/device/assembly/signaler = 3,/obj/item/device/healthanalyzer = 3,
/obj/item/weapon/scalpel = 2,/obj/item/weapon/circular_saw = 2,/obj/item/weapon/tank/anesthetic = 2,/obj/item/clothing/mask/breath/medical = 5,

View File

@@ -760,6 +760,18 @@
user << "You screw the cell in place"
return
else if(istype(W, /obj/item/device/multitool))
if(state>=3 && src.occupant)
user << "You attempt to eject the pilot using the maintenance controls."
if(src.occupant.stat)
src.go_out()
src.log_message("[src.occupant] was ejected using the maintenance controls.")
else
user << "<span class='warning'>Your attempt is rejected.</span>"
src.occupant_message("<span class='warning'>An attempt to eject you was made using the maintenance controls.</span>")
src.log_message("Eject attempt made using maintenance controls - rejected.")
return
else if(istype(W, /obj/item/weapon/cell))
if(state==4)
if(!src.cell)

View File

@@ -24,6 +24,7 @@
return 0
M.buckled = src
M.facing_dir = null
M.set_dir(dir)
M.update_canmove()
buckled_mob = M

View File

@@ -1,10 +1,10 @@
obj/effect/decal/cleanable/liquid_fuel
/obj/effect/decal/cleanable/liquid_fuel
//Liquid fuel is used for things that used to rely on volatile fuels or phoron being contained to a couple tiles.
icon = 'icons/effects/effects.dmi'
icon_state = "fuel"
layer = TURF_LAYER+0.2
anchored = 1
var/amount = 1 //Basically moles.
var/amount = 1
New(turf/newLoc,amt=1,nologs=0)
if(!nologs)
@@ -12,30 +12,41 @@ obj/effect/decal/cleanable/liquid_fuel
log_game("Liquid fuel has spilled in [newLoc.loc.name] ([newLoc.x],[newLoc.y],[newLoc.z])")
src.amount = amt
var/has_spread = 0
//Be absorbed by any other liquid fuel in the tile.
for(var/obj/effect/decal/cleanable/liquid_fuel/other in newLoc)
if(other != src)
other.amount += src.amount
spawn other.Spread()
del src
other.Spread()
has_spread = 1
break
Spread()
. = ..()
if(!has_spread)
Spread()
else
del(src)
proc/Spread()
proc/Spread(exclude=list())
//Allows liquid fuels to sometimes flow into other tiles.
if(amount < 5.0) return
if(amount < 15) return //lets suppose welder fuel is fairly thick and sticky. For something like water, 5 or less would be more appropriate.
var/turf/simulated/S = loc
if(!istype(S)) return
for(var/d in cardinal)
if(rand(25))
var/turf/simulated/target = get_step(src,d)
var/turf/simulated/origin = get_turf(src)
if(origin.CanPass(null, target, 0, 0) && target.CanPass(null, origin, 0, 0))
if(!locate(/obj/effect/decal/cleanable/liquid_fuel) in target)
var/obj/effect/decal/cleanable/liquid_fuel/other_fuel = locate() in target
if(other_fuel)
other_fuel.amount += amount*0.25
if(!(other_fuel in exclude))
exclude += src
other_fuel.Spread(exclude)
else
new/obj/effect/decal/cleanable/liquid_fuel(target, amount*0.25,1)
amount *= 0.75
flamethrower_fuel
icon_state = "mustard"
anchored = 0

View File

@@ -247,4 +247,44 @@
/datum/poster/bay_50
icon_state="bsposter50"
name = "Pinup Girl Cindy Kate"
desc = "This particular one is of Cindy Kate, a seductive performer well known among less savoury circles." //idk
desc = "This particular one is of Cindy Kate, a seductive performer well known among less savoury circles."
/datum/poster/bay_51
icon_state="bsposter51"
name = "space appreciation poster"
desc = "This is a poster produced by the Generic Space Company, as a part of a series of commemorative posters on the wonders of space. One of three."
/datum/poster/bay_52
icon_state="bsposter52"
name = "fire safety poster"
desc = "This is a poster reminding you of what you should do if you are on fire, or if you are at a dance party."
/datum/poster/bay_53
icon_state="bsposter53"
name = "fire extinguisher poster"
desc = "This is a poster reminding you of what you should use to put out a fire."
/datum/poster/bay_54
icon_state="bsposter54"
name = "firefighter poster"
desc = "This is a poster of a particularly stern looking firefighter. The caption reads, \"Only you can prevent space fires.\""
/datum/poster/bay_55
icon_state="bsposter55"
name = "Earth appreciation poster"
desc = "This is a poster produced by the Generic Space Company, as a part of a series of commemorative posters on the wonders of space. Two of three."
/datum/poster/bay_56
icon_state="bsposter56"
name = "Mars appreciation poster"
desc = "This is a poster produced by the Generic Space Company, as a part of a series of commemorative posters on the wonders of space. Three of three."
/datum/poster/bay_57
icon_state="bsposter57"
name = "space carp warning poster"
desc = "This poster tells of the dangers of space carp infestations."
/datum/poster/bay_58
icon_state="bsposter58"
name = "space carp information poster"
desc = "This poster showcases an old spacer saying on the dangers of migrant space carp."

View File

@@ -117,7 +117,7 @@
/obj/effect/landmark/start/ninja/New()
..()
ninjastart += loc
ninjastart += src
//Costume spawner landmarks

View File

@@ -1067,6 +1067,17 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_message = 1
update_icon()
/obj/item/device/pda/ai/new_message(var/atom/movable/sending_unit, var/sender, var/sender_job, var/message)
var/track = ""
if(ismob(sending_unit.loc) && isAI(loc))
track = "(<a href='byond://?src=\ref[loc];track=\ref[sending_unit.loc];trackname=[html_encode(sender)]'>Follow</a>)"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=1;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
new_info(message_silent, newstone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
new_message = 1
/obj/item/device/pda/verb/verb_remove_id()
set category = "Object"
set name = "Remove id"

View File

@@ -140,7 +140,6 @@
..()
name = "DV-136ZB #[rand(1000,9999)]"
c_tag = name
cameranet.removeCamera(src) // Sorry, no AI spying.
/obj/machinery/camera/spy/check_eye(var/mob/user as mob)
return 1

View File

@@ -226,7 +226,6 @@
feedback_inc("cyborg_birth",1)
callHook("borgify", list(O))
O.notify_ai(1)
O.Namepick()
del(src)

View File

@@ -36,12 +36,12 @@
icon = 'icons/mob/custom-synthetic.dmi'
R.icon_state = "[R.ckey]-Standard"
del(R.module)
R.notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, R.module.name)
R.module = null
R.camera.remove_networks(list("Engineering","Medical","MINE"))
R.updatename("Default")
R.status_flags |= CANPUSH
R.updateicon()
R.notify_ai(2)
return 1
@@ -57,7 +57,7 @@
/obj/item/borg/upgrade/rename/action(var/mob/living/silicon/robot/R)
if(..()) return 0
R.notify_ai(3, R.name, heldname)
R.notify_ai(ROBOT_NOTIFICATION_NEW_NAME, R.name, heldname)
R.name = heldname
R.custom_name = heldname
R.real_name = heldname
@@ -84,7 +84,7 @@
R.stat = CONSCIOUS
dead_mob_list -= R
living_mob_list |= R
R.notify_ai(1)
R.notify_ai(ROBOT_NOTIFICATION_NEW_UNIT)
return 1

View File

@@ -187,7 +187,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
*/
var/global/list/datum/stack_recipe/cardboard_recipes = list ( \
new/datum/stack_recipe("box", /obj/item/weapon/storage/box), \
new/datum/stack_recipe("donut box", /obj/item/weapon/storage/donut_box/empty), \
new/datum/stack_recipe("donut box", /obj/item/weapon/storage/box/donut/empty), \
new/datum/stack_recipe("egg box", /obj/item/weapon/storage/fancy/egg_box), \
new/datum/stack_recipe("light tubes", /obj/item/weapon/storage/box/lights/tubes), \
new/datum/stack_recipe("light bulbs", /obj/item/weapon/storage/box/lights/bulbs), \

View File

@@ -43,7 +43,11 @@
var/mob/living/carbon/human/H = target
if (!H.has_organ_for_slot(slot_handcuffed))
user << "\red \The [H] needs at least two wrists before you can cuff them together!"
user << "<span class='danger'>\The [H] needs at least two wrists before you can cuff them together!</span>"
return
if(istype(H.gloves,/obj/item/clothing/gloves/rig)) // Can't cuff someone who's in a deployed hardsuit.
user << "<span class='danger'>The cuffs won't fit around \the [H.gloves]!</span>"
return
H.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been handcuffed (attempt) by [user.name] ([user.ckey])</font>")

View File

@@ -8,10 +8,10 @@
desc = "You wear this on your back and put items into it."
icon_state = "backpack"
item_state = "backpack"
w_class = 4.0
slot_flags = SLOT_BACK //ERROOOOO
w_class = 4
slot_flags = SLOT_BACK
max_w_class = 3
max_combined_w_class = 21
max_storage_space = 28
/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (src.use_sound)
@@ -40,7 +40,7 @@
origin_tech = "bluespace=4"
icon_state = "holdingpack"
max_w_class = 4
max_combined_w_class = 28
max_storage_space = 56
New()
..()
@@ -68,6 +68,12 @@
*/
..()
//Please don't clutter the parent storage item with stupid hacks.
can_be_inserted(obj/item/W as obj, stop_messages = 0)
if(istype(W, /obj/item/weapon/storage/backpack/holding))
return 1
return ..()
proc/failcheck(mob/user as mob)
if (prob(src.reliability)) return 1 //No failure
if (prob(src.reliability))
@@ -88,7 +94,7 @@
w_class = 4.0
storage_slots = 20
max_w_class = 3
max_combined_w_class = 400 // can store a ton of shit!
max_storage_space = 400 // can store a ton of shit!
/obj/item/weapon/storage/backpack/cultpack
name = "trophy rack"

View File

@@ -77,7 +77,7 @@
slot_flags = SLOT_BELT | SLOT_POCKET
w_class = 3
storage_slots = 50
max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
max_w_class = 3
can_hold = list(/obj/item/weapon/ore)
@@ -91,7 +91,7 @@
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "plantbag"
storage_slots = 50; //the number of plant pieces it can carry.
max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
max_w_class = 3
w_class = 2
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/grown,/obj/item/seeds,/obj/item/weapon/grown)
@@ -249,7 +249,7 @@
icon_state = "cashbag"
desc = "A bag for carrying lots of cash. It's got a big dollar sign printed on the front."
storage_slots = 50; //the number of cash pieces it can carry.
max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * cash.w_class
max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * cash.w_class
max_w_class = 3
w_class = 2
can_hold = list(/obj/item/weapon/coin,/obj/item/weapon/spacecash)

View File

@@ -32,7 +32,12 @@
/obj/item/device/t_scanner,
/obj/item/device/analyzer,
/obj/item/taperoll/engineering,
/obj/item/device/robotanalyzer)
/obj/item/device/robotanalyzer,
/obj/item/weapon/minihoe,
/obj/item/weapon/hatchet,
/obj/item/device/analyzer/plant_analyzer,
/obj/item/weapon/extinguisher/mini
)
/obj/item/weapon/storage/belt/utility/full/New()
@@ -75,8 +80,13 @@
/obj/item/stack/medical,
/obj/item/device/flashlight/pen,
/obj/item/clothing/mask/surgical,
/obj/item/clothing/head/surgery,
/obj/item/clothing/gloves/latex,
/obj/item/weapon/reagent_containers/hypospray
/obj/item/weapon/reagent_containers/hypospray,
/obj/item/clothing/glasses/hud/health,
/obj/item/weapon/crowbar,
/obj/item/device/flashlight,
/obj/item/weapon/extinguisher/mini
)
/obj/item/weapon/storage/belt/medical/emt
@@ -87,6 +97,7 @@
item_state = "emsbelt"
/obj/item/weapon/storage/belt/security
name = "security belt"
desc = "Can hold security gear like handcuffs and flashes."
@@ -94,7 +105,7 @@
item_state = "security"
storage_slots = 7
max_w_class = 3
max_combined_w_class = 21
max_storage_space = 28
can_hold = list(
/obj/item/weapon/grenade,
/obj/item/weapon/reagent_containers/spray/pepper,
@@ -103,15 +114,16 @@
/obj/item/clothing/glasses,
/obj/item/ammo_casing/shotgun,
/obj/item/ammo_magazine,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal,
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly,
/obj/item/weapon/reagent_containers/food/snacks/donut/,
/obj/item/weapon/melee/baton,
/obj/item/weapon/gun/energy/taser,
/obj/item/weapon/flame/lighter/zippo,
/obj/item/weapon/flame/lighter,
/obj/item/clothing/glasses/hud/security,
/obj/item/device/flashlight,
/obj/item/device/pda,
/obj/item/device/radio/headset,
/obj/item/device/hailer,
/obj/item/device/megaphone,
/obj/item/weapon/melee,
/obj/item/weapon/gun/projectile/sec,
/obj/item/taperoll/police
@@ -154,4 +166,4 @@
item_state = "swatbelt"
storage_slots = 9
max_w_class = 3
max_combined_w_class = 21
max_storage_space = 28

View File

@@ -24,7 +24,31 @@
desc = "It's just an ordinary box."
icon_state = "box"
item_state = "syringe_kit"
foldable = /obj/item/stack/sheet/cardboard //BubbleWrap
var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
// BubbleWrap - A box can be folded up to make card
/obj/item/weapon/storage/box/attack_self(mob/user as mob)
if(..()) return
//try to fold it.
if ( contents.len )
return
if ( !ispath(src.foldable) )
return
var/found = 0
// Close any open UI windows first
for(var/mob/M in range(1))
if (M.s_active == src)
src.close(M)
if ( M == user )
found = 1
if ( !found ) // User is too far away
return
// Now make the cardboard
user << "<span class='notice'>You fold [src] flat.</span>"
new src.foldable(get_turf(src))
del(src)
/obj/item/weapon/storage/box/survival/
New()
@@ -564,7 +588,7 @@
foldable = /obj/item/stack/sheet/cardboard //BubbleWrap
storage_slots=21
can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb)
max_combined_w_class = 42 //holds 21 items of w_class 2
max_storage_space = 42 //holds 21 items of w_class 2
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
/obj/item/weapon/storage/box/lights/bulbs/New()

View File

@@ -7,9 +7,9 @@
force = 8.0
throw_speed = 1
throw_range = 4
w_class = 4.0
w_class = 4
max_w_class = 3
max_combined_w_class = 16
max_storage_space = 16
/obj/item/weapon/storage/briefcase/New()
..()

View File

@@ -47,7 +47,7 @@
icon_type = "egg"
name = "egg box"
storage_slots = 12
max_combined_w_class = 24
max_storage_space = 24
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/egg)
/obj/item/weapon/storage/fancy/egg_box/New()
@@ -254,9 +254,9 @@
icon = 'icons/obj/vialbox.dmi'
icon_state = "vialbox0"
item_state = "syringe_kit"
max_w_class = 3
max_w_class = 2
can_hold = list(/obj/item/weapon/reagent_containers/glass/beaker/vial)
max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item.
max_storage_space = 12 //The sum of the w_classes of all the items in this storage item.
storage_slots = 6
req_access = list(access_virology)

View File

@@ -7,7 +7,7 @@
item_state = "syringe_kit"
w_class = 4
max_w_class = 3
max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item.
max_storage_space = 14 //The sum of the w_classes of all the items in this storage item.
storage_slots = 4
req_access = list(access_armory)
var/locked = 1

View File

@@ -11,7 +11,7 @@
* Donut Box
*/
/obj/item/weapon/storage/donut_box
/obj/item/weapon/storage/box/donut
icon = 'icons/obj/food.dmi'
icon_state = "donutbox"
name = "donut box"
@@ -20,14 +20,14 @@
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/donut)
foldable = /obj/item/stack/sheet/cardboard
/obj/item/weapon/storage/donut_box/New()
/obj/item/weapon/storage/box/donut/New()
..()
for(var/i=1; i <= startswith; i++)
new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src)
update_icon()
return
/obj/item/weapon/storage/donut_box/update_icon()
/obj/item/weapon/storage/box/donut/update_icon()
overlays.Cut()
var/i = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/donut/D in contents)
@@ -36,6 +36,6 @@
overlays += img
i++
/obj/item/weapon/storage/donut_box/empty
/obj/item/weapon/storage/box/donut/empty
icon_state = "donutbox0"
startswith = 0

View File

@@ -23,9 +23,9 @@
var/l_hacking = 0
var/emagged = 0
var/open = 0
w_class = 3.0
w_class = 3
max_w_class = 2
max_combined_w_class = 14
max_storage_space = 14
examine(mob/user)
if(..(user, 1))

View File

@@ -8,11 +8,11 @@
/obj/item/weapon/storage
name = "storage"
icon = 'icons/obj/storage.dmi'
w_class = 3.0
w_class = 3
var/list/can_hold = new/list() //List of objects which this item can store (if set, it can't store anything else)
var/list/cant_hold = new/list() //List of objects which this item can't store (in effect only if can_hold isn't set)
var/max_w_class = 2 //Max size of objects that this object can store (in effect only if can_hold isn't set)
var/max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item.
var/max_storage_space = 14 //The sum of the storage costs of all the items in this storage item.
var/storage_slots = 7 //The number of storage slots in this container.
var/obj/screen/storage/boxes = null
var/obj/screen/close/closer = null
@@ -21,7 +21,6 @@
var/allow_quick_empty //Set this variable to allow the object to have the 'empty' verb, which dumps all the contents on the floor.
var/allow_quick_gather //Set this variable to allow the object to have the 'toggle mode' verb, which quickly collects all items from a tile.
var/collection_mode = 1; //0 = pick one at a time, 1 = pick all on tile
var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
var/use_sound = "rustle" //sound played when used. null for no sound.
/obj/item/weapon/storage/MouseDrop(obj/over_object as obj)
@@ -226,17 +225,16 @@
usr << "<span class='notice'>[W] is too big for this [src].</span>"
return 0
var/sum_w_class = W.w_class
var/total_storage_space = W.get_storage_cost()
for(var/obj/item/I in contents)
sum_w_class += I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it.
total_storage_space += I.get_storage_cost() //Adds up the combined w_classes which will be in the storage item if the item is added to it.
if(sum_w_class > max_combined_w_class)
if(total_storage_space > max_storage_space)
if(!stop_messages)
usr << "<span class='notice'>[src] is full, make some space.</span>"
return 0
if(W.w_class >= src.w_class && (istype(W, /obj/item/weapon/storage)))
if(!istype(src, /obj/item/weapon/storage/backpack/holding)) //bohs should be able to hold backpacks again. The override for putting a boh in a boh is in backpack.dm.
if(!stop_messages)
usr << "<span class='notice'>[src] cannot hold [W] as it's a storage item of the same size.</span>"
return 0 //To prevent the stacking of same sized storage items.
@@ -259,13 +257,13 @@
W.dropped(usr)
add_fingerprint(usr)
if(!prevent_warning && !istype(W, /obj/item/weapon/gun/energy/crossbow))
if(!prevent_warning)
for(var/mob/M in viewers(usr, null))
if (M == usr)
usr << "<span class='notice'>You put \the [W] into [src].</span>"
else if (M in range(1)) //If someone is standing close enough, they can tell what it is...
M.show_message("<span class='notice'>[usr] puts [W] into [src].</span>")
else if (W && W.w_class >= 3.0) //Otherwise they can only see large or normal items from a distance...
else if (W && W.w_class >= 3) //Otherwise they can only see large or normal items from a distance...
M.show_message("<span class='notice'>[usr] puts [W] into [src].</span>")
src.orient2hud(usr)
@@ -415,35 +413,12 @@
O.emp_act(severity)
..()
// BubbleWrap - A box can be folded up to make card
/obj/item/weapon/storage/attack_self(mob/user as mob)
//Clicking on itself will empty it, if it has the verb to do that.
if(user.get_active_hand() == src)
if(src.verbs.Find(/obj/item/weapon/storage/verb/quick_empty))
src.quick_empty()
return
//Otherwise we'll try to fold it.
if ( contents.len )
return
if ( !ispath(src.foldable) )
return
var/found = 0
// Close any open UI windows first
for(var/mob/M in range(1))
if (M.s_active == src)
src.close(M)
if ( M == user )
found = 1
if ( !found ) // User is too far away
return
// Now make the cardboard
user << "<span class='notice'>You fold [src] flat.</span>"
new src.foldable(get_turf(src))
del(src)
//BubbleWrap END
return 1
/obj/item/weapon/storage/hear_talk(mob/M as mob, text, verb, datum/language/speaking)
for (var/atom/A in src)
@@ -486,3 +461,6 @@
return -1 //inside something with a null loc.
return depth
/obj/item/proc/get_storage_cost()
return 2**(w_class-1) //1,2,4,8,16,...

View File

@@ -5,20 +5,16 @@
icon_state = "red"
item_state = "toolbox_red"
flags = CONDUCT
force = 5.0
throwforce = 10.0
force = 5
throwforce = 10
throw_speed = 1
throw_range = 7
w_class = 4.0
w_class = 4
max_w_class = 3
max_storage_space = 14 //can hold 7 w_class-2 items or up to 3 w_class-3 items (with 1 w_class-2 item as change).
origin_tech = "combat=1"
attack_verb = list("robusted")
New()
..()
if (src.type == /obj/item/weapon/storage/toolbox)
world << "BAD: [src] ([src.type]) spawned at [src.x] [src.y] [src.z]"
del(src)
/obj/item/weapon/storage/toolbox/emergency
name = "emergency toolbox"
icon_state = "red"

View File

@@ -246,7 +246,7 @@
/obj/item/weapon/tank/process()
//Allow for reactions
air_contents.react()
air_contents.react() //cooking up air tanks - add phoron and oxygen, then heat above PHORON_MINIMUM_BURN_TEMPERATURE
check_status()

View File

@@ -62,16 +62,6 @@
else
return null
/obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request)
//Return: (NONSTANDARD)
// null if object handles breathing logic for lifeform
// datum/air_group to tell lifeform to process using that breath return
//DEFAULT: Take air from turf to give to have mob process
if(breath_request>0)
return remove_air(breath_request)
else
return null
/atom/movable/proc/initialize()
return

View File

@@ -177,8 +177,8 @@
icon_state = "energykill100"
item_to_spawn()
return pick(prob(2);/obj/item/weapon/gun/energy/laser,\
prob(1);/obj/item/weapon/gun/energy/gun,\
prob(2);/obj/item/weapon/gun/energy/stunrevolver)
prob(2);/obj/item/weapon/gun/energy/gun,\
prob(1);/obj/item/weapon/gun/energy/stunrevolver)
/obj/random/projectile
name = "Random Projectile Weapon"
@@ -188,10 +188,17 @@
item_to_spawn()
return pick(prob(3);/obj/item/weapon/gun/projectile/shotgun/pump,\
prob(2);/obj/item/weapon/gun/projectile/automatic/wt550,\
prob(3);/obj/item/weapon/gun/projectile/sec,\
prob(2);/obj/item/weapon/gun/projectile/sec/wood,\
prob(1);/obj/item/weapon/gun/projectile/shotgun/pump/combat)
/obj/random/handgun
name = "Random Handgun"
desc = "This is a random security sidearm."
icon = 'icons/obj/gun.dmi'
icon_state = "secgundark"
item_to_spawn()
return pick(prob(3);/obj/item/weapon/gun/projectile/sec,\
prob(1);/obj/item/weapon/gun/projectile/sec/wood)
/obj/random/ammo
name = "Random Ammunition"
@@ -199,15 +206,15 @@
icon = 'icons/obj/ammo.dmi'
icon_state = "45-10"
item_to_spawn()
return pick(prob(3);/obj/item/weapon/storage/box/beanbags,\
prob(1);/obj/item/weapon/storage/box/shotgunammo,\
prob(2);/obj/item/weapon/storage/box/shotgunshells,\
prob(2);/obj/item/weapon/storage/box/stunshells,\
prob(1);/obj/item/ammo_magazine/c45m,\
prob(2);/obj/item/ammo_magazine/c45m/rubber,\
prob(2);/obj/item/ammo_magazine/c45m/flash,\
prob(1);/obj/item/ammo_magazine/mc9mmt,\
prob(3);/obj/item/ammo_magazine/mc9mmt/rubber)
return pick(prob(6);/obj/item/weapon/storage/box/beanbags,\
prob(2);/obj/item/weapon/storage/box/shotgunammo,\
prob(4);/obj/item/weapon/storage/box/shotgunshells,\
prob(1);/obj/item/weapon/storage/box/stunshells,\
prob(2);/obj/item/ammo_magazine/c45m,\
prob(4);/obj/item/ammo_magazine/c45m/rubber,\
prob(4);/obj/item/ammo_magazine/c45m/flash,\
prob(2);/obj/item/ammo_magazine/mc9mmt,\
prob(6);/obj/item/ammo_magazine/mc9mmt/rubber)
/obj/random/action_figure

View File

@@ -52,7 +52,7 @@
/obj/structure/closet/secure_closet/medical3
name = "medical doctor's locker"
req_access = list(access_surgery)
req_access = list(access_medical)
icon_state = "securemed1"
icon_closed = "securemed"
icon_locked = "securemed1"

View File

@@ -196,7 +196,7 @@
new /obj/item/clothing/head/soft/sec/corp(src)
new /obj/item/clothing/under/rank/security/corp(src)
new /obj/item/ammo_magazine/c45m/rubber(src)
new /obj/item/weapon/gun/projectile/sec(src)
new /obj/item/weapon/gun/energy/taser(src)
return

View File

@@ -248,6 +248,10 @@
glass = 1
else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype)
var/M = S.sheettype
// Ugly hack, will suffice for now. Need to fix it upstream as well, may rewrite mineral walls. ~Z
if(M in list("mhydrogen","osmium","tritium","platinum","iron"))
user << "You cannot make an airlock out of that material."
return
if(S.get_amount() >= 2)
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")

View File

@@ -144,6 +144,10 @@
if(S.sheettype)
var/M = S.sheettype
// Ugly hack, will suffice for now. Need to fix it upstream as well, may rewrite mineral walls. ~Z
if(M in list("mhydrogen","osmium","tritium","platinum","iron"))
user << "You cannot plate the girder in that material."
return
if(!anchored)
if(S.amount < 2) return
S.use(2)

View File

@@ -3,7 +3,7 @@
desc = "A folded membrane which rapidly expands into a large cubical shape on activation."
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_wall"
w_class = 3.0
w_class = 3
attack_self(mob/user)
playsound(loc, 'sound/items/zip.ogg', 75, 1)
@@ -252,7 +252,7 @@
desc = "Contains inflatable walls and doors."
icon_state = "inf_box"
item_state = "syringe_kit"
max_combined_w_class = 21
max_storage_space = 28
can_hold = list(/obj/item/inflatable)
New()

View File

@@ -7,59 +7,19 @@
density = 0
anchored = 1
var/shattered = 0
var/list/ui_users = list()
/obj/structure/mirror/attack_hand(mob/user as mob)
if(shattered) return
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.a_intent == "hurt")
if(prob(30) || H.species.can_shred(H))
attack_generic(user,1)
else
attack_generic(user)
return
var/userloc = H.loc
//see code/modules/mob/new_player/preferences.dm at approx line 545 for comments!
//this is largely copypasted from there.
//handle facial hair (if necessary)
if(H.gender == MALE)
var/list/species_facial_hair = list()
if(H.species)
for(var/i in facial_hair_styles_list)
var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i]
if(H.species.name in tmp_facial.species_allowed)
species_facial_hair += i
else
species_facial_hair = facial_hair_styles_list
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair
if(userloc != H.loc) return //no tele-grooming
if(new_style)
H.f_style = new_style
//handle normal hair
var/list/species_hair = list()
if(H.species)
for(var/i in hair_styles_list)
var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i]
if(H.species.name in tmp_hair.species_allowed)
species_hair += i
else
species_hair = hair_styles_list
var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair
if(userloc != H.loc) return //no tele-grooming
if(new_style)
H.h_style = new_style
H.update_hair()
var/obj/nano_module/appearance_changer/AC = ui_users[user]
if(!AC)
AC = new(src, user)
AC.name = "SalonPro Nano-Mirror(TM)"
ui_users[user] = AC
AC.ui_interact(user)
/obj/structure/mirror/proc/shatter()
if(shattered) return

View File

@@ -138,8 +138,8 @@
density = 1
icon_state = "up"
else
buckled_mob.pixel_y = 0
buckled_mob.old_y = 0
M.pixel_y = 0
M.old_y = 0
density = 0
icon_state = "down"

View File

@@ -353,53 +353,24 @@ obj/structure/ex_act(severity)
moving = 0
// Should I return a copy here? If the caller edits or del()s the returned
// datum, there might be problems if I don't...
/obj/structure/transit_tube_pod/return_air()
var/datum/gas_mixture/GM = new()
GM.copy_from(air_contents)
return GM
return air_contents
// For now, copying what I found in an unused FEA file (and almost identical in a
// used ZAS file). Means that assume_air and remove_air don't actually alter the
// air contents.
/obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver)
return air_contents.merge(giver)
/obj/structure/transit_tube_pod/remove_air(amount)
return air_contents.remove(amount)
// Called when a pod arrives at, and before a pod departs from a station,
// giving it a chance to mix its internal air supply with the turf it is
// currently on.
/obj/structure/transit_tube_pod/proc/mix_air()
var/datum/gas_mixture/environment = loc.return_air()
var/env_pressure = environment.return_pressure()
var/int_pressure = air_contents.return_pressure()
var/total_pressure = env_pressure + int_pressure
if(total_pressure == 0)
return
// Math here: Completely made up, not based on realistic equasions.
// Goal is to balance towards equal pressure, but ensure some gas
// transfer in both directions regardless.
// Feel free to rip this out and replace it with something better,
// I don't really know muhch about how gas transfer rates work in
// SS13.
var/transfer_in = max(0.1, 0.5 * (env_pressure - int_pressure) / total_pressure)
var/transfer_out = max(0.1, 0.3 * (int_pressure - env_pressure) / total_pressure)
var/datum/gas_mixture/from_env = loc.remove_air(environment.total_moles * transfer_in)
var/datum/gas_mixture/from_int = air_contents.remove(air_contents.total_moles * transfer_out)
loc.assume_air(from_int)
air_contents.merge(from_env)
//note that share_ratio assumes both gas mixes have the same volume,
//so if the volume is changed this may need to be changed as well.
air_contents.share_ratio(environment, 1)
// When the player moves, check if the pos is currently stopped at a station.
// if it is, check the direction. If the direction matches the direction of

View File

@@ -3,7 +3,7 @@
desc = "Holds item of clothing you shouldn't be showing off in the hallways."
icon = 'icons/obj/closet.dmi'
icon_state = "cabinet_closed"
density = 1
/obj/structure/undies_wardrobe/attack_hand(mob/user as mob)
src.add_fingerprint(user)

View File

@@ -65,6 +65,7 @@ client/verb/JoinResponseTeam()
var/leader_selected = isemptylist(response_team_members)
var/mob/living/carbon/human/new_commando = create_response_team(L.loc, leader_selected, new_name)
del(L)
//Creates mind stuff.
new_commando.mind.key = usr.key
new_commando.key = usr.key
@@ -74,6 +75,10 @@ client/verb/JoinResponseTeam()
new_commando << "<b>As member of the Emergency Response Team, you answer only to your leader and CentComm officials.</b>"
else
new_commando << "<b>As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
// By setting an explicit location the mob cannot wander off and decide change appearance elsewhere
new_commando.change_appearance(APPEARANCE_ALL, new_commando.loc, new_commando, species_whitelist = config.ert_species)
return
else
@@ -167,105 +172,13 @@ proc/trigger_armed_response_team(var/force = 0)
var/mob/living/carbon/human/M = new(null)
response_team_members |= M
//todo: god damn this.
//make it a panel, like in character creation
var/new_facial = input("Please select facial hair color.", "Character Generation") as color
if(new_facial)
M.r_facial = hex2num(copytext(new_facial, 2, 4))
M.g_facial = hex2num(copytext(new_facial, 4, 6))
M.b_facial = hex2num(copytext(new_facial, 6, 8))
var/new_hair = input("Please select hair color.", "Character Generation") as color
if(new_facial)
M.r_hair = hex2num(copytext(new_hair, 2, 4))
M.g_hair = hex2num(copytext(new_hair, 4, 6))
M.b_hair = hex2num(copytext(new_hair, 6, 8))
var/new_eyes = input("Please select eye color.", "Character Generation") as color
if(new_eyes)
M.r_eyes = hex2num(copytext(new_eyes, 2, 4))
M.g_eyes = hex2num(copytext(new_eyes, 4, 6))
M.b_eyes = hex2num(copytext(new_eyes, 6, 8))
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
if (!new_tone)
new_tone = 35
M.s_tone = max(min(round(text2num(new_tone)), 220), 1)
M.s_tone = -M.s_tone + 35
// hair
var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
var/list/hairs = list()
// loop through potential hairs
for(var/x in all_hairs)
var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x
hairs.Add(H.name) // add hair name to hairs
del(H) // delete the hair after it's all done
// var/new_style = input("Please select hair style", "Character Generation") as null|anything in hairs
//hair
var/new_hstyle = input(usr, "Select a hair style", "Grooming") as null|anything in hair_styles_list
if(new_hstyle)
M.h_style = new_hstyle
// facial hair
var/new_fstyle = input(usr, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list
if(new_fstyle)
M.f_style = new_fstyle
// if new style selected (not cancel)
/* if (new_style)
M.h_style = new_style
for(var/x in all_hairs) // loop through all_hairs again. Might be slightly CPU expensive, but not significantly.
var/datum/sprite_accessory/hair/H = new x // create new hair datum
if(H.name == new_style)
M.h_style = H // assign the hair_style variable a new hair datum
break
else
del(H) // if hair H not used, delete. BYOND can garbage collect, but better safe than sorry
// facial hair
var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
var/list/fhairs = list()
for(var/x in all_fhairs)
var/datum/sprite_accessory/facial_hair/H = new x
fhairs.Add(H.name)
del(H)
new_style = input("Please select facial style", "Character Generation") as null|anything in fhairs
if(new_style)
M.f_style = new_style
for(var/x in all_fhairs)
var/datum/sprite_accessory/facial_hair/H = new x
if(H.name == new_style)
M.f_style = H
break
else
del(H)
*/
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
if (new_gender)
if(new_gender == "Male")
M.gender = MALE
else
M.gender = FEMALE
//M.rebuild_appearance()
M.update_hair()
M.update_body()
M.check_dna(M)
M.real_name = commando_name
M.name = commando_name
M.age = !leader_selected ? rand(23,35) : rand(35,45)
M.check_dna(M)
M.dna.ready_dna(M)//Creates DNA.
//Creates mind stuff.
M.mind = new
M.mind.current = M
M.mind.original = M
@@ -275,6 +188,7 @@ proc/trigger_armed_response_team(var/force = 0)
ticker.minds += M.mind//Adds them to regular mind list.
M.loc = spawn_location
M.equip_strike_team(leader_selected)
return M
/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0)

Some files were not shown because too many files have changed in this diff Show More