mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge remote-tracking branch 'upstream/dev' into reagent_dispenser
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
184
code/ZAS/Fire.dm
184
code/ZAS/Fire.dm
@@ -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)
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
141
code/__HELPERS/vector.dm
Normal 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
|
||||
@@ -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
|
||||
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]'")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -72,7 +72,8 @@ var/list/medical_positions = list(
|
||||
"Medical Doctor",
|
||||
"Geneticist",
|
||||
"Psychiatrist",
|
||||
"Chemist"
|
||||
"Chemist",
|
||||
"Paramedic"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var/build_eff = 1
|
||||
var/eat_eff = 1
|
||||
|
||||
|
||||
/obj/machinery/biogenerator/New()
|
||||
..()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -234,6 +234,12 @@
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/cryopod/Del()
|
||||
if(occupant)
|
||||
occupant.loc = loc
|
||||
occupant.resting = 1
|
||||
..()
|
||||
|
||||
/obj/machinery/cryopod/initialize()
|
||||
..()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -617,6 +617,7 @@
|
||||
/obj/machinery/suit_cycler/Del()
|
||||
del(wires) // qdel
|
||||
wires = null
|
||||
..()
|
||||
|
||||
/obj/machinery/suit_cycler/engineering
|
||||
name = "Engineering suit cycler"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
return 0
|
||||
|
||||
M.buckled = src
|
||||
M.facing_dir = null
|
||||
M.set_dir(dir)
|
||||
M.update_canmove()
|
||||
buckled_mob = M
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
@@ -117,7 +117,7 @@
|
||||
|
||||
/obj/effect/landmark/start/ninja/New()
|
||||
..()
|
||||
ninjastart += loc
|
||||
ninjastart += src
|
||||
|
||||
//Costume spawner landmarks
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -226,7 +226,6 @@
|
||||
|
||||
feedback_inc("cyborg_birth",1)
|
||||
callHook("borgify", list(O))
|
||||
O.notify_ai(1)
|
||||
O.Namepick()
|
||||
|
||||
del(src)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,...
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user