Merge branch 'dev' of https://github.com/Baystation12/Baystation12 into 6/5/2015_bay_merge

Conflicts:
	.travis.yml
	code/controllers/configuration.dm
	code/datums/supplypacks.dm
	code/game/machinery/bluespacerelay.dm
	code/game/machinery/hologram.dm
	code/game/objects/items/weapons/RCD.dm
	code/game/objects/items/weapons/circuitboards/machinery/commsantenna.dm
	code/game/turfs/simulated/floor.dm
	code/game/turfs/simulated/floor_types.dm
	code/game/turfs/simulated/walls.dm
	code/global.dm
	code/modules/clothing/spacesuits/rig/suits/ert.dm
	code/modules/mob/living/silicon/ai/ai.dm
	code/modules/research/designs.dm
	config/example/config.txt
	icons/mob/feet.dmi
	icons/mob/head.dmi
	icons/mob/suit.dmi
	icons/obj/clothing/hats.dmi
	icons/obj/clothing/shoes.dmi
	icons/obj/clothing/suits.dmi
	icons/obj/rig_modules.dmi
	interface/interface.dm
	maps/exodus-3.dmm
	polaris.dme
This commit is contained in:
Neerti
2015-06-05 22:11:15 -04:00
1080 changed files with 29305 additions and 32788 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@
*.lk
*.backup
data/
cfg/

View File

@@ -130,7 +130,7 @@
var/total_specific_power = 0 //the power required to remove one mole of filterable gas
for (var/g in filtering)
var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas
total_specific_power = specific_power_gas[g]*ratio
total_specific_power += specific_power_gas[g]*ratio
//Figure out how much of each gas to filter
if (isnull(total_transfer_moles))
@@ -427,10 +427,19 @@
//If set, sink_volume_mod adjusts the effective output volume used in the calculation. This is useful when the output gas_mixture is
//part of a pipenetwork, and so it's volume isn't representative of the actual volume since the gas will be shared across the pipenetwork when it processes.
/proc/calculate_transfer_moles(datum/gas_mixture/source, datum/gas_mixture/sink, var/pressure_delta, var/sink_volume_mod=0)
//Make the approximation that the sink temperature is unchanged after transferring gas
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
var/output_volume = (sink.volume * sink.group_multiplier) + sink_volume_mod
if(source.temperature == 0 || source.total_moles == 0) return 0
var/output_volume = (sink.volume * sink.group_multiplier) + sink_volume_mod
var/source_total_moles = source.total_moles * source.group_multiplier
var/air_temperature = source.temperature
if(sink.total_moles > 0 && sink.temperature > 0)
//estimate the final temperature of the sink after transfer
var/estimate_moles = pressure_delta*output_volume/(sink.temperature * R_IDEAL_GAS_EQUATION)
var/sink_heat_capacity = sink.heat_capacity()
var/transfer_heat_capacity = source.heat_capacity()*estimate_moles/source_total_moles
air_temperature = (sink.temperature*sink_heat_capacity + source.temperature*transfer_heat_capacity) / (sink_heat_capacity + transfer_heat_capacity)
//get the number of moles that would have to be transfered to bring sink to the target pressure
return pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)

View File

@@ -85,6 +85,9 @@ obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/a
return node.pipe_color
/obj/machinery/atmospherics/process()
last_flow_rate = 0
last_power_draw = 0
build_network()
/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)

View File

@@ -168,7 +168,7 @@
return
src.add_fingerprint(usr)
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
usr.set_machine(src)
ui_interact(user)
@@ -242,20 +242,20 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (unlocked)
user << "\red You cannot unwrench this [src], turn it off first."
user << "<span class='warning'>You cannot unwrench \the [src], turn it off first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -91,7 +91,7 @@
attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/wrench))
anchored = !anchored
user << "\blue You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor."
user << "<span class='notice'>You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor.</span>"
if(anchored)
if(dir & (NORTH|SOUTH))
@@ -263,7 +263,7 @@
if(istype(W, /obj/item/weapon/wrench))
anchored = !anchored
turbine = null
user << "\blue You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor."
user << "<span class='notice'>You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor.</span>"
updateConnection()
else
..()
@@ -286,4 +286,4 @@
if (usr.stat || usr.restrained() || anchored)
return
src.set_dir(turn(src.dir, 90))
src.set_dir(turn(src.dir, 90))

View File

@@ -183,7 +183,7 @@ Thus, the two variables affect pump operation are set in New():
return
src.add_fingerprint(usr)
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
usr.set_machine(src)
ui_interact(user)
@@ -219,20 +219,20 @@ Thus, the two variables affect pump operation are set in New():
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (!(stat & NOPOWER) && use_power)
user << "\red You cannot unwrench this [src], turn it off first."
user << "<span class='warning'>You cannot unwrench this [src], turn it off first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench this [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -87,15 +87,15 @@
int_pressure += P.air.return_pressure()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_pressure - env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "<span class='warning'>You cannot unwrench [src], it is too exerted due to internal pressure.</span>"
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)
@@ -299,4 +299,4 @@
update_ports()
return null
return null

View File

@@ -134,22 +134,22 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (connected_device)
user << "\red You cannot unwrench this [src], dettach [connected_device] first."
user << "<span class='warning'>You cannot unwrench \the [src], dettach \the [connected_device] first.</span>"
return 1
if (locate(/obj/machinery/portable_atmospherics, src.loc))
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -134,16 +134,16 @@
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)
@@ -153,7 +153,7 @@
return
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
var/dat

View File

@@ -109,15 +109,15 @@
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)
@@ -127,7 +127,7 @@
return
src.add_fingerprint(usr)
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
usr.set_machine(src)
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[use_power?"On":"Off"]</a><br>

View File

@@ -308,7 +308,7 @@
if(!powered())
return
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
..()
@@ -350,21 +350,21 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (istype(src, /obj/machinery/atmospherics/tvalve/digital))
user << "\red You cannot unwrench this [src], it's too complicated."
user << "<span class='warning'>You cannot unwrench \the [src], it's too complicated.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warnng'>You cannot unwrench \the [src], it too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)
@@ -448,7 +448,7 @@
if(!powered())
return
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
..()
@@ -482,4 +482,4 @@
if(state)
go_straight()
else
go_to_side()
go_to_side()

View File

@@ -70,20 +70,20 @@
return ..()
var/turf/T = src.loc
if (level==1 && isturf(T) && T.intact)
user << "\red You must remove the plating first."
user << "<span class='warning'>You must remove the plating first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)
qdel(src)

View File

@@ -61,19 +61,31 @@
use_power = 1
icon_state = "map_vent_in"
/obj/machinery/atmospherics/unary/vent_pump/siphon/on/atmos
use_power = 1
icon_state = "map_vent_in"
external_pressure_bound = 0
external_pressure_bound_default = 0
internal_pressure_bound = 2000
internal_pressure_bound_default = 2000
pressure_checks = 2
pressure_checks_default = 2
/obj/machinery/atmospherics/unary/vent_pump/New()
..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP
icon = null
initial_loc = get_area(loc)
if (initial_loc.master)
initial_loc = initial_loc.master
area_uid = initial_loc.uid
if (!id_tag)
assign_uid()
id_tag = num2text(uid)
/obj/machinery/atmospherics/unary/vent_pump/Destroy()
unregister_radio(src, frequency)
..()
/obj/machinery/atmospherics/unary/vent_pump/high_volume
name = "Large Air Vent"
power_channel = EQUIP
@@ -211,14 +223,6 @@
return pressure_delta
//Radio remote control
/obj/machinery/atmospherics/unary/vent_pump/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency,radio_filter_in)
/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status()
if(!radio_connection)
return 0
@@ -260,7 +264,7 @@
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
radio_connection = register_radio(src, frequency, frequency, radio_filter_in)
src.broadcast_status()
/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
@@ -354,22 +358,22 @@
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if (WT.remove_fuel(0,user))
user << "\blue Now welding the vent."
user << "<span class='notice'>Now welding the vent.</span>"
if(do_after(user, 20))
if(!src || !WT.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
if(!welded)
user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.")
user.visible_message("<span class='notice'>\The [user] welds the vent shut.</span>", "<span class='notice'>You weld the vent shut.</span>", "You hear welding.")
welded = 1
update_icon()
else
user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.")
user.visible_message("<span class='notice'>[user] unwelds the vent.</span>", "<span class='notice'>You unweld the vent.</span>", "You hear welding.")
welded = 0
update_icon()
else
user << "\blue The welding tool needs to be on to start this task."
user << "<span class='notice'>The welding tool needs to be on to start this task.</span>"
else
user << "\blue You need more welding fuel to complete this task."
user << "<span class='warning'>You need more welding fuel to complete this task.</span>"
return 1
else
..()
@@ -392,25 +396,25 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (!(stat & NOPOWER) && use_power)
user << "\red You cannot unwrench this [src], turn it off first."
user << "<span class='warning'>You cannot unwrench \the [src], turn it off first.</span>"
return 1
var/turf/T = src.loc
if (node && node.level==1 && isturf(T) && T.intact)
user << "\red You must remove the plating first."
user << "<span class='warning'>You must remove the plating first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -17,6 +17,7 @@
var/frequency = 1439
var/datum/radio_frequency/radio_connection
var/hibernate = 0 //Do we even process?
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
var/list/scrubbing_gas = list("carbon_dioxide")
@@ -36,13 +37,16 @@
icon = null
initial_loc = get_area(loc)
if (initial_loc.master)
initial_loc = initial_loc.master
area_uid = initial_loc.uid
if (!id_tag)
assign_uid()
id_tag = num2text(uid)
/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
unregister_radio(src, frequency)
..()
/obj/machinery/atmospherics/unary/vent_scrubber/update_icon(var/safety = 0)
if(!check_icon_cache())
return
@@ -123,8 +127,8 @@
/obj/machinery/atmospherics/unary/vent_scrubber/process()
..()
last_power_draw = 0
last_flow_rate = 0
if (hibernate)
return 1
if (!node)
use_power = 0
@@ -146,6 +150,12 @@
power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
if(scrubbing && power_draw < 0 && controller_iteration > 10) //99% of all scrubbers
//Fucking hibernate because you ain't doing shit.
hibernate = 1
spawn(rand(100,200)) //hibernate for 10 or 20 seconds randomly
hibernate = 0
if (power_draw >= 0)
last_power_draw = power_draw
use_power(power_draw)
@@ -248,25 +258,25 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (!(stat & NOPOWER) && use_power)
user << "\red You cannot unwrench this [src], turn it off first."
user << "<span class='warning'>You cannot unwrench \the [src], turn it off first.</span>"
return 1
var/turf/T = src.loc
if (node && node.level==1 && isturf(T) && T.intact)
user << "\red You must remove the plating first."
user << "<span class='warning'>You must remove the plating first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -241,7 +241,7 @@
if(!powered())
return
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
..()
@@ -294,21 +294,21 @@
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (istype(src, /obj/machinery/atmospherics/valve/digital))
user << "\red You cannot unwrench this [src], it's too complicated."
user << "<span class='warning'>You cannot unwrench \the [src], it's too complicated.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
qdel(src)

View File

@@ -649,7 +649,7 @@ obj/machinery/atmospherics/mains_pipe/valve
attack_hand(mob/user as mob)
if(!src.allowed(user))
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
..()
@@ -704,4 +704,4 @@ obj/machinery/atmospherics/mains_pipe/valve
close()
else
open()
*/
*/

View File

@@ -82,21 +82,21 @@
return ..()
var/turf/T = src.loc
if (level==1 && isturf(T) && T.intact)
user << "\red You must remove the plating first."
user << "<span class='warning'>You must remove the plating first.</span>"
return 1
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
user << "<span class='warning'>You cannot unwrench [src], it is too exerted due to internal pressure.</span>"
user << "<span class='warning'>You cannot unwrench \the [src], it is too exerted due to internal pressure.</span>"
add_fingerprint(user)
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src]..."
user << "<span class='notice>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src].", \
"You hear ratchet.")
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear a ratchet.")
new /obj/item/pipe(loc, make_from=src)
for (var/obj/machinery/meter/meter in T)
if (meter.target == src)
@@ -214,7 +214,7 @@
else return 1
/obj/machinery/atmospherics/pipe/simple/proc/burst()
src.visible_message("\red \bold [src] bursts!");
src.visible_message("<span class='danger'>\The [src] bursts!</span>");
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
var/datum/effect/effect/system/smoke_spread/smoke = new
smoke.set_up(1,0, src.loc, 0)
@@ -1121,19 +1121,19 @@
if(istype(W, /obj/item/device/analyzer) && in_range(user, src))
for (var/mob/O in viewers(user, null))
O << "\red [user] has used the analyzer on \icon[icon]"
O << "<span class='notice'>\The [user] has used \the [W] on \the [src] \icon[src]</span>"
var/pressure = parent.air.return_pressure()
var/total_moles = parent.air.total_moles
user << "\blue Results of analysis of \icon[icon]"
user << "<span class='notice'>Results of analysis of \the [src] \icon[src]</span>"
if (total_moles>0)
user << "\blue Pressure: [round(pressure,0.1)] kPa"
user << "<span class='notice'>Pressure: [round(pressure,0.1)] kPa</span>"
for(var/g in parent.air.gas)
user << "\blue [gas_data.name[g]]: [round((parent.air.gas[g] / total_moles) * 100)]%"
user << "\blue Temperature: [round(parent.air.temperature-T0C)]&deg;C"
user << "<span class='notice'>[gas_data.name[g]]: [round((parent.air.gas[g] / total_moles) * 100)]%</span>"
user << "<span class='notice'>Temperature: [round(parent.air.temperature-T0C)]&deg;C</span>"
else
user << "\blue Tank is empty!"
user << "<span class='notice'>Tank is empty!</span>"
/obj/machinery/atmospherics/pipe/tank/air
name = "Pressure Tank (Air)"

View File

@@ -48,7 +48,7 @@ obj/item/weapon/tank
adjust_mixture(temperature as num, target_toxin_pressure as num, target_oxygen_pressure as num)
set src in world
if(!air_contents)
usr << "\red ERROR: no gas_mixture associated with this tank"
usr << "<span class='warning'>ERROR: no gas_mixture associated with this tank</span>"
return null
air_contents.temperature = temperature
@@ -74,7 +74,7 @@ turf/simulated/floor
else
usr << "Space Borders: None"
else
usr << "\blue [x],[y] has no parent air group."
usr << "<span class='notice'>[x],[y] has no parent air group.</span>"
verb
create_wall()
@@ -329,7 +329,7 @@ obj/machinery/atmospherics
set src in world
set category = "Minor"
world << "\blue [x],[y]"
world << "<span class='notice'>[x],[y]</span>"
world << "network 1: [network_node1.normal_members.len], [network_node1.line_members.len]"
for(var/obj/O in network_node1.normal_members)
world << "member: [O.x], [O.y]"
@@ -406,7 +406,7 @@ turf/simulated
set src in world
set category = "Minor"
var/datum/gas_mixture/GM = return_air()
usr << "\blue @[x],[y] ([GM.group_multiplier]): O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(active_hotspot)?("\red BURNING"):(null)]"
usr << "<span class='notice'>@[x],[y] ([GM.group_multiplier]): O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(active_hotspot)?("<span class='danger'>BURNING</span>"):(null)]</span>""
for(var/datum/gas/trace_gas in GM.trace_gases)
usr << "[trace_gas.type]: [trace_gas.moles]"
@@ -515,7 +515,7 @@ mob
fire_report()
set category = "Debug"
usr << "\b \red Fire Report"
usr << "<span class='danger'>Fire Report</span>"
for(var/obj/effect/hotspot/flame in world)
usr << "[flame.x],[flame.y]: [flame.temperature]K, [flame.volume] L - [flame.loc:air:temperature]"

View File

@@ -146,7 +146,7 @@ datum
setup()
set background = 1
world << "\red \b Processing Geometry..."
world << "<span class='danger'>Processing Geometry...</span>"
sleep(1)
var/start_time = world.timeofday
@@ -156,7 +156,7 @@ datum
assemble_group_turf(S)
S.update_air_properties()
world << "\red \b Geometry processed in [(world.timeofday-start_time)/10] seconds!"
world << "<span class='danger'>Geometry processed in [(world.timeofday-start_time)/10] seconds!</span>"
assemble_group_turf(turf/simulated/base)

View File

@@ -13,13 +13,13 @@
for(var/atom/A in T.contents)
if(A.density)
blocked = 1
usr << "\red You bump into [A.name]."
usr << "<span class='warning'>You bump into \the [A].</span>"
break
if(!blocked)
usr.Move(T)
usr << "You move upwards."
else
usr << "\red There is something in your way."
usr << "<span class='warning'>There is something in your way.</span>"
if (legal == 0)
usr << "There is nothing of interest in this direction."
return 1
@@ -40,13 +40,13 @@
for(var/atom/A in T.contents)
if(A.density)
blocked = 1
usr << "\red You bump into [A.name]."
usr << "<span class='warning'>You bump into \the [A].</span>"
break
if(!blocked)
usr.Move(T)
usr << "You move downwards."
else
usr << "\red You cant move through the floor."
usr << "<span class='warning'>You cant move through the floor.</span>"
if (legal == 0)
usr << "There is nothing of interest in this direction."
return 1

View File

@@ -73,7 +73,7 @@ obj/machinery/atmospherics/pipe/zpipe/check_pressure(pressure)
else return 1
obj/machinery/atmospherics/pipe/zpipe/proc/burst()
src.visible_message("\red \bold [src] bursts!");
src.visible_message("<span class='warning'>\The [src] bursts!</span>");
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
var/datum/effect/effect/system/smoke_spread/smoke = new
smoke.set_up(1,0, src.loc, 0)

View File

@@ -114,7 +114,7 @@
sleep(60)
if(!user || !WT || !WT.isOn()) return
var/obj/item/stack/sheet/metal/S = new /obj/item/stack/sheet/metal( src )
var/obj/item/stack/material/steel/S = new /obj/item/stack/material/steel( src )
S.amount = 2
user << "<span class='notice'>You remove the ladder and close the hole.</span>"
qdel(src)
@@ -141,7 +141,7 @@
if(blocked || istype(T, /turf/simulated/wall))
M << "Something is blocking the ladder."
else
M.visible_message("\blue \The [M] climbs [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You climb [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You hear some grunting, and clanging of a metal ladder being used.")
M.visible_message("<span class='notice'>\The [M] climbs [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!</span>", "You climb [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You hear some grunting, and clanging of a metal ladder being used.")
M.Move(target.loc)
/* hatch
@@ -188,7 +188,7 @@
qdel(src)
if(M.z == z && get_dist(src,M) <= 1)
var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
M.visible_message("\blue \The [M] scurries [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You scramble [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You hear some grunting, and a hatch sealing.")
M.visible_message("<span class='notice'>\The [M] scurries [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!</span>", "You scramble [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You hear some grunting, and a hatch sealing.")
M.Move(target.loc)
flick(top_icon_state_close,top_hatch)
bottom_hatch.overlays -= green_overlay
@@ -271,4 +271,4 @@
var/turf/above2 = locate(bottom.x, bottom.y, controller.up_target)
if(istype(above2, /turf/space) || istype(above,/turf/simulated/floor/open))
top.target2 = above2
return
return

View File

@@ -71,7 +71,7 @@
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
// check if there is something to draw below
if(!controller.down)
src.ChangeTurf(/turf/space)
src.ChangeTurf(get_base_turf(src.z))
return 0
else
floorbelow = locate(src.x, src.y, controller.down_target)
@@ -109,7 +109,7 @@
return
var/obj/item/stack/rods/R = C
if (R.use(1))
user << "\blue Constructing support lattice ..."
user << "<span class='notice'>Constructing support lattice...</span>"
playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
@@ -126,5 +126,5 @@
S.use(1)
return
else
user << "\red The plating is going to need some support."
user << "<span class='warning'>The plating is going to need some support.</span>"
return

View File

@@ -92,16 +92,6 @@
turf += src
c.add(turf,3,1)
/turf/space/New()
..()
var/turf/controller = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/c in controller)
if(c.initialized)
var/list/turf = list()
turf += src
c.add(turf,3,1)
atom/movable/Move() //Hackish
. = ..()
@@ -176,70 +166,6 @@ atom/movable/Move() //Hackish
T.overlays -= below.z_overlays
T.z_overlays -= below.z_overlays
// this is sadly impossible to use right now
// the overlay is always opaque to mouseclicks and thus prevents interactions with everything except the turf
/*if(up)
var/turf/above = locate(T.x, T.y, up_target)
if(above)
var/eligeable = 0
for(var/d in cardinal)
var/turf/mT = get_step(above,d)
if(istype(mT, /turf/space) || istype(mT, /turf/simulated/floor/open))
eligeable = 1
/*if(mT.opacity == 0)
for(var/f in cardinal)
var/turf/nT = get_step(mT,f)
if(istype(nT, /turf/space) || istype(nT, /turf/simulated/floor/open))
eligeable = 1*/
if(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)) eligeable = 1
if(eligeable == 1)
if(!(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)))
var/image/t_img = list()
if(new_list < 1) new_list = 1
above.overlays -= above.z_overlays
var/image/temp = image(above, dir=above.dir, layer = 5 + 0.04)
above.overlays += above.z_overlays
temp.alpha = 100
temp.overlays += above.overlays
temp.overlays -= above.z_overlays
t_img += temp
T.overlays += t_img
T.z_overlays += t_img
// get objects
var/image/o_img = list()
for(var/obj/o in above)
// ingore objects that have any form of invisibility
if(o.invisibility) continue
if(new_list < 2) new_list = 2
var/image/temp2 = image(o, dir=o.dir, layer = 5+0.05*o.layer)
temp2.alpha = 100
temp2.overlays += o.overlays
o_img += temp2
// you need to add a list to .overlays or it will not display any because space
T.overlays += o_img
T.z_overlays += o_img
// get mobs
var/image/m_img = list()
for(var/mob/m in above)
// ingore mobs that have any form of invisibility
if(m.invisibility) continue
// only add this tile to fastprocessing if there is a living mob, not a dead one
if(istype(m, /mob/living) && new_list < 3) new_list = 3
var/image/temp2 = image(m, dir=m.dir, layer = 5+0.05*m.layer)
temp2.alpha = 100
temp2.overlays += m.overlays
m_img += temp2
// you need to add a list to .overlays or it will not display any because space
T.overlays += m_img
T.z_overlays += m_img
T.overlays -= above.z_overlays
T.z_overlays -= above.z_overlays*/
L -= T
if(new_list == 1)

View File

@@ -80,7 +80,7 @@ obj/item/check_airflow_movable(n)
return
if(src:shoes && src:shoes.flags & NOSLIP)
return
src << "\red You are sucked away by airflow!"
src << "<span class='danger'>You are sucked away by airflow!</span>"
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
if(airflow_falloff < 1)
airflow_dest = null
@@ -144,7 +144,7 @@ obj/item/check_airflow_movable(n)
if(istype(src:shoes, /obj/item/clothing/shoes/magboots))
if(src:shoes.flags & NOSLIP)
return
src << "\red You are pushed away by airflow!"
src << "<span clas='danger'>You are pushed away by airflow!</span>"
last_airflow = world.time
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
if(airflow_falloff < 1)
@@ -197,7 +197,7 @@ atom/movable/proc/airflow_hit(atom/A)
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)
M.show_message("<span class='danger'>\The [src] slams into \a [A]!</span>",1,"<span class='danger'>You hear a loud slam!</span>",2)
playsound(src.loc, "smash.ogg", 25, 1, -1)
var/weak_amt = istype(A,/obj/item) ? A:w_class : rand(1,5) //Heheheh
Weaken(weak_amt)
@@ -205,7 +205,7 @@ mob/airflow_hit(atom/A)
obj/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)
M.show_message("<span class='danger'>\The [src] slams into \a [A]!</span>",1,"<span class='danger'>You hear a loud slam!</span>",2)
playsound(src.loc, "smash.ogg", 25, 1, -1)
. = ..()
@@ -215,7 +215,7 @@ obj/item/airflow_hit(atom/A)
mob/living/carbon/human/airflow_hit(atom/A)
// for(var/mob/M in hearers(src))
// M.show_message("\red <B>[src] slams into [A]!</B>",1,"\red You hear a loud slam!",2)
// M.show_message("<span class='danger'>[src] slams into [A]!</span>",1,"<span class='danger'>You hear a loud slam!</span>",2)
playsound(src.loc, "punch", 25, 1, -1)
if (prob(33))
loc:add_blood(src)
@@ -244,4 +244,4 @@ zone/proc/movables()
for(var/atom/A in T)
if(istype(A, /obj/effect) || istype(A, /mob/aiEye))
continue
. += A
. += A

View File

@@ -187,7 +187,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
#ifdef ZASDBG
if(updated != updating.len)
tick_progress = "[updating.len - updated] tiles left unupdated."
world << "\red [tick_progress]"
world << "<span class='danger'>[tick_progress]</span>"
. = 0
#endif
@@ -371,4 +371,4 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
/datum/controller/air_system/proc/remove_edge(connection_edge/E)
edges.Remove(E)
if(!E.sleeping) active_edges.Remove(E)
if(!E.sleeping) active_edges.Remove(E)

View File

@@ -84,154 +84,7 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
else
mob << "both turfs can merge."
/*zone/proc/DebugDisplay(client/client)
if(!istype(client))
return
if(!dbg_output)
dbg_output = 1 //Don't want to be spammed when someone investigates a zone...
if(!client.zone_debug_images)
client.zone_debug_images = list()
var/list/current_zone_images = list()
for(var/turf/T in contents)
current_zone_images += image('icons/misc/debug_group.dmi', T, null, TURF_LAYER)
for(var/turf/space/S in unsimulated_tiles)
current_zone_images += image('icons/misc/debug_space.dmi', S, null, TURF_LAYER)
client << "<u>Zone Air Contents</u>"
client << "Oxygen: [air.oxygen]"
client << "Nitrogen: [air.nitrogen]"
client << "Phoron: [air.phoron]"
client << "Carbon Dioxide: [air.carbon_dioxide]"
client << "Temperature: [air.temperature] K"
client << "Heat Energy: [air.temperature * air.heat_capacity()] J"
client << "Pressure: [air.return_pressure()] KPa"
client << ""
client << "Space Tiles: [length(unsimulated_tiles)]"
client << "Movable Objects: [length(movables())]"
client << "<u>Connections: [length(connections)]</u>"
for(var/connection/C in connections)
client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]"
current_zone_images += image('icons/misc/debug_connect.dmi', C.A, null, TURF_LAYER)
current_zone_images += image('icons/misc/debug_connect.dmi', C.B, null, TURF_LAYER)
client << "Connected Zones:"
for(var/zone/zone in connected_zones)
client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)"
for(var/zone/zone in closed_connection_zones)
client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)"
for(var/C in connections)
if(!istype(C,/connection))
client << "[C] (Not Connection!)"
if(!client.zone_debug_images)
client.zone_debug_images = list()
client.zone_debug_images[src] = current_zone_images
client.images += client.zone_debug_images[src]
else
dbg_output = 0
client.images -= client.zone_debug_images[src]
client.zone_debug_images.Remove(src)
if(air_master)
for(var/zone/Z in air_master.zones)
if(Z.air == air && Z != src)
var/turf/zloc = pick(Z.contents)
client << "\red Illegal air datum shared by: [zloc.loc.name]"*/
/*client/proc/TestZASRebuild()
set category = "Debug"
// var/turf/turf = get_turf(mob)
var/zone/current_zone = mob.loc:zone
if(!current_zone)
src << "There is no zone there!"
return
var/list/current_adjacents = list()
var/list/overlays = list()
var/adjacent_id
var/lowest_id
var/list/identical_ids = list()
var/list/turfs = current_zone.contents.Copy()
var/current_identifier = 1
for(var/turf/simulated/current in turfs)
lowest_id = null
current_adjacents = list()
for(var/direction in cardinal)
var/turf/simulated/adjacent = get_step(current, direction)
if(!current.ZCanPass(adjacent))
continue
if(turfs.Find(adjacent))
current_adjacents += adjacent
adjacent_id = turfs[adjacent]
if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
lowest_id = adjacent_id
if(!lowest_id)
lowest_id = current_identifier++
identical_ids += lowest_id
overlays += image('icons/misc/debug_rebuild.dmi',, "[lowest_id]")
for(var/turf/simulated/adjacent in current_adjacents)
adjacent_id = turfs[adjacent]
if(adjacent_id != lowest_id)
if(adjacent_id)
adjacent.overlays -= overlays[adjacent_id]
identical_ids[adjacent_id] = lowest_id
turfs[adjacent] = lowest_id
adjacent.overlays += overlays[lowest_id]
sleep(5)
if(turfs[current])
current.overlays -= overlays[turfs[current]]
turfs[current] = lowest_id
current.overlays += overlays[lowest_id]
sleep(5)
var/list/final_arrangement = list()
for(var/turf/simulated/current in turfs)
current_identifier = identical_ids[turfs[current]]
current.overlays -= overlays[turfs[current]]
current.overlays += overlays[current_identifier]
sleep(5)
if( current_identifier > final_arrangement.len )
final_arrangement.len = current_identifier
final_arrangement[current_identifier] = list(current)
else
final_arrangement[current_identifier] += current
//lazy but fast
final_arrangement.Remove(null)
src << "There are [final_arrangement.len] unique segments."
for(var/turf/current in turfs)
current.overlays -= overlays
return final_arrangement*/
client/proc/ZASSettings()
set category = "Debug"
vsc.SetDefault(mob)
vsc.SetDefault(mob)

View File

@@ -10,6 +10,8 @@ Attach to transfer valve and open. BOOM.
*/
//#define FIREDBG
/turf/var/obj/fire/fire = null
//Some legacy definitions so fires can be started.
@@ -35,14 +37,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(air_contents.check_combustability(liquid))
igniting = 1
create_fire(vsc.fire_firelevel_multiplier)
create_fire(exposed_temperature)
return igniting
/zone/proc/process_fire()
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)
@@ -65,6 +66,29 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(!fire_tiles.len)
air_master.active_fire_zones.Remove(src)
/zone/proc/remove_liquidfuel(var/used_liquid_fuel, var/remove_fire=0)
if(!fuel_objs.len)
return
//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. It will mean that sometimes we will remove a tiny bit less fuel then we intended to.
var/fuel_to_remove = used_liquid_fuel/(fuel_objs.len*LIQUIDFUEL_AMOUNT_TO_MOL) //convert back to liquid volume units
for(var/O in fuel_objs)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = O
if(!istype(fuel))
fuel_objs -= fuel
continue
fuel.amount -= fuel_to_remove
if(fuel.amount <= 0)
fuel_objs -= fuel
if(remove_fire)
var/turf/T = fuel.loc
if(istype(T) && T.fire) qdel(T.fire)
qdel(fuel)
/turf/proc/create_fire(fl)
return 0
@@ -91,14 +115,14 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
anchored = 1
mouse_opacity = 0
//luminosity = 3
blend_mode = BLEND_ADD
icon = 'icons/effects/fire.dmi'
icon_state = "1"
l_color = "#ED9200"
light_color = "#ED9200"
layer = TURF_LAYER
var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
var/firelevel = 1 //Calculated by gas_mixture.calculate_firelevel()
/obj/fire/process()
. = 1
@@ -114,15 +138,14 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(firelevel > 6)
icon_state = "3"
SetLuminosity(7)
set_light(7, 3)
else if(firelevel > 2.5)
icon_state = "2"
SetLuminosity(5)
set_light(5, 2)
else
icon_state = "1"
SetLuminosity(3)
set_light(3, 1)
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
for(var/mob/living/L in loc)
L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs!
@@ -158,28 +181,40 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
else
enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.volume)
animate(src, color = fire_color(air_contents.temperature), 5)
set_light(l_color = color)
/obj/fire/New(newLoc,fl)
..()
if(!istype(loc, /turf))
qdel(src)
return
set_dir(pick(cardinal))
SetLuminosity(3)
var/datum/gas_mixture/air_contents = loc.return_air()
color = fire_color(air_contents.temperature)
set_light(3, 1, color)
firelevel = fl
air_master.active_hotspots.Add(src)
/obj/fire/proc/fire_color(var/env_temperature)
var/temperature = max(4000*sqrt(firelevel/vsc.fire_firelevel_multiplier), env_temperature)
return heat2color(temperature)
/obj/fire/Destroy()
if (istype(loc, /turf/simulated))
RemoveFire()
RemoveFire()
..()
/obj/fire/proc/RemoveFire()
if (istype(loc, /turf))
SetLuminosity(0)
var/turf/T = loc
if (istype(T))
set_light(0)
T.fire = null
loc = null
air_master.active_hotspots.Remove(src)
@@ -191,6 +226,11 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//Returns the firelevel
/datum/gas_mixture/proc/zburn(zone/zone, force_burn, no_check = 0)
#ifdef FIREDBG
log_debug("***************** FIREDBG *****************")
if(zone) log_debug("Burning [zone.name]!")
#endif
. = 0
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.
@@ -208,9 +248,11 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
total_oxidizers *= group_multiplier
//Liquid Fuel
var/fuel_area = 0
if(zone)
for(var/obj/effect/decal/cleanable/liquid_fuel/fuel in zone.fuel_objs)
liquid_fuel += fuel.amount*LIQUIDFUEL_AMOUNT_TO_MOL
fuel_area++
total_fuel = gas_fuel + liquid_fuel
if(total_fuel <= 0.005)
@@ -218,9 +260,6 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//*** Determine how fast the fire burns
//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()
@@ -228,61 +267,54 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//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 actual rate of reaction, as measured by the amount of fuel reacting
//calculate the firelevel.
var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
//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
var/gas_reaction_progress = min(0.2, (firelevel/vsc.fire_firelevel_multiplier))*gas_fuel*FIRE_GAS_BURNRATE_MULT
//world << "liquid_reaction_progress = [liquid_reaction_progress]"
//world << "gas_reaction_progress = [gas_reaction_progress]"
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning. Limit the burn rate to a certain amount per area.
var/liquid_reaction_progress = ((firelevel/vsc.fire_firelevel_multiplier)*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT
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]"
#ifdef FIREDBG
log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]")
log_debug("liquid_reaction_progress = [liquid_reaction_progress]")
log_debug("gas_reaction_progress = [gas_reaction_progress]")
log_debug("used_fuel = [used_fuel]; used_oxidizers = [used_oxidizers]; reaction_limit=[reaction_limit]")
#endif
//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)
if(zone) //be less restrictive with canister and tank reactions
if((!liquid_fuel || used_fuel <= FIRE_LIQUD_MIN_BURNRATE) && (!gas_fuel || used_fuel <= FIRE_GAS_MIN_BURNRATE*group_multiplier))
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
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)
var/used_gas_fuel = between(0.25, used_fuel*(gas_reaction_progress/total_reaction_progress), gas_fuel) //remove in proportion to the relative reaction progress
var/used_liquid_fuel = between(0.25, used_fuel-used_gas_fuel, liquid_fuel)
//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)
//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
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) qdel(T.fire)
qdel(fuel)
if(zone)
zone.remove_liquidfuel(used_liquid_fuel, !check_combustability())
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * used_fuel) / heat_capacity()
#ifdef FIREDBG
log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_gas_fuel+used_liquid_fuel]")
log_debug("new temperature = [temperature]")
#endif
update_values()
return firelevel
@@ -325,21 +357,28 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
. = 1
break
//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)
//returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
//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(fuel_objs))
var/total_combustables = (total_fuel + total_oxidizers)
var/total_combustables = (total_fuel + total_oxidizers)
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = total_combustables / total_moles
//calculates how close the mixture of the reactants is to the optimum
var/mix_multiplier = 1 / (1 + (5 * ((total_oxidizers / total_combustables) ** 2)))
//toss everything together
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = min(1, reaction_limit / (total_moles/group_multiplier))
//calculates how close the mixture of the reactants is to the optimum
//fires burn better when there is more oxidizer -- too much fuel will choke them out a bit, reducing firelevel.
var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
#ifdef FIREDBG
ASSERT(dampening_multiplier <= 1)
ASSERT(mix_multiplier <= 1)
#endif
//toss everything together -- should produce a value between 0 and fire_firelevel_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
return max( 0, firelevel)

View File

@@ -88,7 +88,7 @@ obj/var/contaminated = 0
if(vsc.plc.SKIN_BURNS)
if(!pl_head_protected() || !pl_suit_protected())
burn_skin(0.75)
if(prob(20)) src << "\red Your skin burns!"
if(prob(20)) src << "<span class='danger'>Your skin burns!</span>"
updatehealth()
//Burn eyes if exposed.
@@ -111,7 +111,7 @@ obj/var/contaminated = 0
if(vsc.plc.GENETIC_CORRUPTION)
if(rand(1,10000) < vsc.plc.GENETIC_CORRUPTION)
randmutb(src)
src << "\red High levels of toxins cause you to spontaneously mutate."
src << "<span class='danger'>High levels of toxins cause you to spontaneously mutate!</span>"
domutcheck(src,null)
@@ -122,11 +122,11 @@ obj/var/contaminated = 0
var/obj/item/organ/eyes/E = internal_organs_by_name["eyes"]
if(E)
if(prob(20)) src << "\red Your eyes burn!"
if(prob(20)) src << "<span class='danger'>Your eyes burn!</span>"
E.damage += 2.5
eye_blurry = min(eye_blurry+1.5,50)
if (prob(max(0,E.damage - 15) + 1) &&!eye_blind)
src << "\red You are blinded!"
src << "<span class='danger'>You are blinded!</span>"
eye_blind += 20
/mob/living/carbon/human/proc/pl_head_protected()

View File

@@ -45,6 +45,45 @@
air_master.connect(sim, src)
/*
Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
This implementation may produce false negatives but it (hopefully) will not produce any false postiives.
*/
/turf/simulated/proc/can_safely_remove_from_zone()
#ifdef ZLEVELS
return 0 //TODO generalize this to multiz.
#else
if(!zone) return 1
var/check_dirs = get_zone_neighbours(src)
var/unconnected_dirs = check_dirs
for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST))
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
if((dir & check_dirs) == dir)
//check that they are connected by the corner turf
var/connected_dirs = get_zone_neighbours(get_step(src, dir))
if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir)
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
return !unconnected_dirs
#endif
//helper for can_safely_remove_from_zone()
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
. = 0
if(istype(T) && T.zone)
for(var/dir in cardinal)
var/turf/simulated/other = get_step(T, dir)
if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
. |= dir
/turf/simulated/update_air_properties()
if(zone && zone.invalid)
@@ -60,7 +99,7 @@
if(zone)
var/zone/z = zone
if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time
if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
z.remove(src)
else
z.rebuild()

View File

@@ -168,7 +168,7 @@ var/global/vs_control/vsc = new
vars[ch] = vw
if(how == "Toggle")
newvar = (newvar?"ON":"OFF")
world << "\blue <b>[key_name(user)] changed the setting [display_description] to [newvar].</b>"
world << "<span class='notice'><b>[key_name(user)] changed the setting [display_description] to [newvar].</b></span>"
if(ch in plc.settings)
ChangeSettingsDialog(user,plc.settings)
else
@@ -321,7 +321,7 @@ var/global/vs_control/vsc = new
plc.N2O_HALLUCINATION = initial(plc.N2O_HALLUCINATION)
world << "\blue <b>[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"</b>"
world << "<span class='notice'><b>[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"</b></span>"
/pl_control/var/list/settings = list()

42
code/__defines/admin.dm Normal file
View File

@@ -0,0 +1,42 @@
// A set of constants used to determine which type of mute an admin wishes to apply.
// Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO, etc. = (MUTE_IC << 1)
// Therefore there needs to be a gap between the flags for the automute flags.
#define MUTE_IC 1
#define MUTE_OOC 2
#define MUTE_PRAY 4
#define MUTE_ADMINHELP 8
#define MUTE_DEADCHAT 16
#define MUTE_ALL 31
// Number of identical messages required to get the spam-prevention auto-mute thing to trigger warnings and automutes.
#define SPAM_TRIGGER_WARNING 5
#define SPAM_TRIGGER_AUTOMUTE 10
// Some constants for DB_Ban
#define BANTYPE_PERMA 1
#define BANTYPE_TEMP 2
#define BANTYPE_JOB_PERMA 3
#define BANTYPE_JOB_TEMP 4
#define BANTYPE_ANY_FULLBAN 5 // Used to locate stuff to unban.
#define ROUNDSTART_LOGOUT_REPORT_TIME 6000 // Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued.
// Admin permissions. Please don't edit these values without speaking to Errorage first. ~Carn
#define R_BUILDMODE 1
#define R_ADMIN 2
#define R_BAN 4
#define R_FUN 8
#define R_SERVER 16
#define R_DEBUG 32
#define R_POSSESS 64
#define R_PERMISSIONS 128
#define R_STEALTH 256
#define R_REJUVINATE 512
#define R_VAREDIT 1024
#define R_SOUNDS 2048
#define R_SPAWN 4096
#define R_MOD 8192
#define R_MENTOR 16384
#define R_HOST 32768
#define R_MAXPERMISSION 32768 // This holds the maximum value for a permission. It is used in iteration, so keep it updated.

86
code/__defines/atmos.dm Normal file
View File

@@ -0,0 +1,86 @@
#define CELL_VOLUME 2500 // Liters in a cell.
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) // Moles in a 2.5 m^3 cell at 101.325 kPa and 20 C.
#define O2STANDARD 0.21 // Percentage.
#define N2STANDARD 0.79
#define MOLES_PHORON_VISIBLE 0.7 // Moles in a standard cell after which phoron is visible.
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD * O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD * N2STANDARD) // N2 standard value (79%)
// These are for when a mob breathes poisonous air.
#define MIN_TOXIN_DAMAGE 1
#define MAX_TOXIN_DAMAGE 10
#define BREATH_VOLUME 0.5 // Liters in a normal breath.
#define BREATH_MOLES (ONE_ATMOSPHERE * BREATH_VOLUME / (T20C * R_IDEAL_GAS_EQUATION)) // Amount of air to take a from a tile
#define BREATH_PERCENTAGE (BREATH_VOLUME / CELL_VOLUME) // Amount of air needed before pass out/suffocation commences.
#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD * BREATH_PERCENTAGE * 0.16)
#define SOUND_MINIMUM_PRESSURE 10
#define PRESSURE_DAMAGE_COEFFICIENT 4 // The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE.
#define MAX_HIGH_PRESSURE_DAMAGE 4 // This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
#define LOW_PRESSURE_DAMAGE 2 // The amount of damage someone takes when in a low pressure area. (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.05 // Minimum ratio of air that must move to/from a tile to suspend group processing
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Either this must be active
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C + 100) // or this (or both, obviously)
#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012 // Minimum temperature difference before group processing is suspended.
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4
#define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5 // Minimum temperature difference before the gas temperatures are just set to be equal.
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION (T20C + 10)
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C + 200)
// Must be between 0 and 1. Values closer to 1 equalize temperature faster. Should not exceed 0.4, else strange heat flow occurs.
#define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4
#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
#define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0
#define SPACE_HEAT_TRANSFER_COEFFICIENT 0.2 // A hack to partly simulate radiative heat.
#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 // A hack for now.
// Fire damage.
#define CARBON_LIFEFORM_FIRE_RESISTANCE (T0C + 200)
#define CARBON_LIFEFORM_FIRE_DAMAGE 4
// Phoron fire properties.
#define PHORON_MINIMUM_BURN_TEMPERATURE (T0C + 126) //400 K - autoignite temperature in tanks and canisters - enclosed environments I guess
#define PHORON_FLASHPOINT (T0C + 246) //519 K - autoignite temperature in air if that ever gets implemented.
//These control the mole ratio of oxidizer and fuel used in the combustion reaction
#define FIRE_REACTION_OXIDIZER_AMOUNT 3 //should be greater than the fuel amount if fires are going to spread much
#define FIRE_REACTION_FUEL_AMOUNT 2
//These control the speed at which fire burns
#define FIRE_GAS_BURNRATE_MULT 1
#define FIRE_LIQUID_BURNRATE_MULT 1
//If the fire is burning slower than this rate then the reaction is going too slow to be self sustaining and the fire burns itself out.
//This ensures that fires don't grind to a near-halt while still remaining active forever.
#define FIRE_GAS_MIN_BURNRATE 0.01
#define FIRE_LIQUD_MIN_BURNRATE 0.01
//How many moles of fuel are contained within one solid/liquid fuel volume unit
#define LIQUIDFUEL_AMOUNT_TO_MOL 1 //mol/volume unit
// XGM gas flags.
#define XGM_GAS_FUEL 1
#define XGM_GAS_OXIDIZER 2
#define XGM_GAS_CONTAMINANT 4
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) // Tank starts leaking.
#define TANK_RUPTURE_PRESSURE (40.*ONE_ATMOSPHERE) // Tank spills all contents into atmosphere.
#define TANK_FRAGMENT_PRESSURE (50.*ONE_ATMOSPHERE) // Boom 3x3 base explosion.
#define TANK_FRAGMENT_SCALE (10.*ONE_ATMOSPHERE) // +1 for each SCALE kPa above threshold. Was 2 atm.
#define NORMPIPERATE 30 // Pipe-insulation rate divisor.
#define HEATPIPERATE 8 // Heat-exchange pipe insulation.
#define FLOWFRAC 0.99 // Fraction of gas transfered per process.
//Flags for zone sleeping
#define ZONE_ACTIVE 1
#define ZONE_SLEEPING 0

View File

@@ -0,0 +1,39 @@
#define HUNGER_FACTOR 0.05 // Factor of how fast mob nutrition decreases
#define REM 0.2 // Means 'Reagent Effect Multiplier'. This is how many units of reagent are consumed per tick
#define CHEM_TOUCH 1
#define CHEM_INGEST 2
#define CHEM_BLOOD 3
#define MINIMUM_CHEMICAL_VOLUME 0.01
#define SOLID 1
#define LIQUID 2
#define GAS 3
#define REAGENTS_OVERDOSE 30
#define CHEM_SYNTH_ENERGY 500 // How much energy does it take to synthesize 1 unit of chemical, in Joules.
// Some on_mob_life() procs check for alien races.
#define IS_DIONA 1
#define IS_VOX 2
#define IS_SKRELL 3
#define IS_UNATHI 4
#define IS_XENOS 5
#define IS_MACHINE 6
#define CE_STABLE "stable" // Inaprovaline
#define CE_ANTIBIOTIC "antibiotic" // Spaceacilin
#define CE_BLOODRESTORE "bloodrestore" // Iron/nutriment
#define CE_PAINKILLER "painkiller"
#define CE_ALCOHOL "alcohol" // Liver filtering
#define CE_ALCOHOL_TOXIC "alcotoxic" // Liver damage
#define CE_SPEEDBOOST "gofast" // Hyperzine
// Chemistry lists.
var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglycerin", "thirteenloko", "nicotine") // Increase heart rate.
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
var/list/heartstopper = list("potassium_phorochloride", "zombie_powder") // This stops the heart.
var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional

View File

@@ -0,0 +1,56 @@
// Damage things. TODO: Merge these down to reduce on defines.
// Way to waste perfectly good damage-type names (BRUTE) on this... If you were really worried about case sensitivity, you could have just used lowertext(damagetype) in the proc.
#define BRUTE "brute"
#define BURN "fire"
#define TOX "tox"
#define OXY "oxy"
#define CLONE "clone"
#define HALLOSS "halloss"
#define CUT "cut"
#define BRUISE "bruise"
#define STUN "stun"
#define WEAKEN "weaken"
#define PARALYZE "paralize"
#define IRRADIATE "irradiate"
#define AGONY "agony" // Added in PAIN!
#define SLUR "slur"
#define STUTTER "stutter"
#define EYE_BLUR "eye_blur"
#define DROWSY "drowsy"
// I hate adding defines like this but I'd much rather deal with bitflags than lists and string searches.
#define BRUTELOSS 1
#define FIRELOSS 2
#define TOXLOSS 4
#define OXYLOSS 8
#define FIRE_DAMAGE_MODIFIER 0.0215 // Higher values result in more external fire damage to the skin. (default 0.0215)
#define AIR_DAMAGE_MODIFIER 2.025 // More means less damage from hot air scalding lungs, less = more damage. (default 2.025)
// Organ defines.
#define ORGAN_CUT_AWAY 1<<0
#define ORGAN_BLEEDING 1<<1
#define ORGAN_BROKEN 1<<2
#define ORGAN_DESTROYED 1<<3
#define ORGAN_ROBOT 1<<4
#define ORGAN_SPLINTED 1<<5
#define ORGAN_DEAD 1<<6
#define ORGAN_MUTATED 1<<7
#define ORGAN_ASSISTED 1<<8
#define DROPLIMB_EDGE 0
#define DROPLIMB_BLUNT 1
#define DROPLIMB_BURN 2
// Damage above this value must be repaired with surgery.
#define ROBOLIMB_SELF_REPAIR_CAP 30
//Germs and infections.
#define GERM_LEVEL_AMBIENT 110 // Maximum germ level you can reach by standing still.
#define GERM_LEVEL_MOVE_CAP 200 // Maximum germ level you can reach by running around.
#define INFECTION_LEVEL_ONE 100
#define INFECTION_LEVEL_TWO 500
#define INFECTION_LEVEL_THREE 1000

76
code/__defines/dna.dm Normal file
View File

@@ -0,0 +1,76 @@
// Bitflags for mutations.
#define STRUCDNASIZE 27
#define UNIDNASIZE 13
// Generic mutations:
#define TK 1
#define COLD_RESISTANCE 2
#define XRAY 3
#define HULK 4
#define CLUMSY 5
#define FAT 6
#define HUSK 7
#define NOCLONE 8
#define LASER 9 // Harm intent - click anywhere to shoot lasers from eyes.
#define HEAL 10 // Healing people with hands.
#define SKELETON 29
#define PLANT 30
// Other Mutations:
#define mNobreath 100 // No need to breathe.
#define mRemote 101 // Remote viewing.
#define mRegen 102 // Health regeneration.
#define mRun 103 // No slowdown.
#define mRemotetalk 104 // Remote talking.
#define mMorph 105 // Hanging appearance.
#define mBlend 106 // Nothing. (seriously nothing)
#define mHallucination 107 // Hallucinations.
#define mFingerprints 108 // No fingerprints.
#define mShock 109 // Insulated hands.
#define mSmallsize 110 // Table climbing.
// disabilities
#define NEARSIGHTED 1
#define EPILEPSY 2
#define COUGHING 4
#define TOURETTES 8
#define NERVOUS 16
// sdisabilities
#define BLIND 1
#define MUTE 2
#define DEAF 4
// The way blocks are handled badly needs a rewrite, this is horrible.
// Too much of a project to handle at the moment, TODO for later.
var/BLINDBLOCK = 0
var/DEAFBLOCK = 0
var/HULKBLOCK = 0
var/TELEBLOCK = 0
var/FIREBLOCK = 0
var/XRAYBLOCK = 0
var/CLUMSYBLOCK = 0
var/FAKEBLOCK = 0
var/COUGHBLOCK = 0
var/GLASSESBLOCK = 0
var/EPILEPSYBLOCK = 0
var/TWITCHBLOCK = 0
var/NERVOUSBLOCK = 0
var/MONKEYBLOCK = STRUCDNASIZE
var/BLOCKADD = 0
var/DIFFMUT = 0
var/HEADACHEBLOCK = 0
var/NOBREATHBLOCK = 0
var/REMOTEVIEWBLOCK = 0
var/REGENERATEBLOCK = 0
var/INCREASERUNBLOCK = 0
var/REMOTETALKBLOCK = 0
var/MORPHBLOCK = 0
var/BLENDBLOCK = 0
var/HALLUCINATIONBLOCK = 0
var/NOPRINTSBLOCK = 0
var/SHOCKIMMUNITYBLOCK = 0
var/SMALLSIZEBLOCK = 0

119
code/__defines/gamemode.dm Normal file
View File

@@ -0,0 +1,119 @@
#define GAME_STATE_PREGAME 1
#define GAME_STATE_SETTING_UP 2
#define GAME_STATE_PLAYING 3
#define GAME_STATE_FINISHED 4
// Security levels.
#define SEC_LEVEL_GREEN 0
#define SEC_LEVEL_BLUE 1
#define SEC_LEVEL_RED 2
#define SEC_LEVEL_DELTA 3
#define BE_TRAITOR 1
#define BE_OPERATIVE 2
#define BE_CHANGELING 4
#define BE_WIZARD 8
#define BE_MALF 16
#define BE_REV 32
#define BE_ALIEN 64
#define BE_AI 128
#define BE_CULTIST 256
#define BE_MONKEY 512
#define BE_NINJA 1024
#define BE_RAIDER 2048
#define BE_PLANT 4096
#define BE_MUTINEER 8192
#define BE_PAI 16384
var/list/be_special_flags = list(
"Traitor" = BE_TRAITOR,
"Operative" = BE_OPERATIVE,
"Changeling" = BE_CHANGELING,
"Wizard" = BE_WIZARD,
"Malf AI" = BE_MALF,
"Revolutionary" = BE_REV,
"Xenomorph" = BE_ALIEN,
"Positronic Brain" = BE_AI,
"Cultist" = BE_CULTIST,
"Monkey" = BE_MONKEY,
"Ninja" = BE_NINJA,
"Raider" = BE_RAIDER,
"Diona" = BE_PLANT,
"Mutineer" = BE_MUTINEER,
"pAI" = BE_PAI
)
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
// Antagonist datum flags.
#define ANTAG_OVERRIDE_JOB 1 // Assigned job is set to MODE when spawning.
#define ANTAG_OVERRIDE_MOB 2 // Mob is recreated from datum mob_type var when spawning.
#define ANTAG_CLEAR_EQUIPMENT 4 // All preexisting equipment is purged.
#define ANTAG_CHOOSE_NAME 8 // Antagonists are prompted to enter a name.
#define ANTAG_IMPLANT_IMMUNE 16 // Cannot be loyalty implanted.
#define ANTAG_SUSPICIOUS 32 // Shows up on roundstart report.
#define ANTAG_HAS_LEADER 64 // Generates a leader antagonist.
#define ANTAG_HAS_NUKE 128 // Will spawn a nuke at supplied location.
#define ANTAG_RANDSPAWN 256 // Potentially randomly spawns due to events.
#define ANTAG_VOTABLE 512 // Can be voted as an additional antagonist before roundstart.
#define ANTAG_SET_APPEARANCE 1024 // Causes antagonists to use an appearance modifier on spawn.
// Mode/antag template macros.
#define MODE_BORER "borer"
#define MODE_XENOMORPH "xeno"
#define MODE_LOYALIST "loyalist"
#define MODE_MUTINEER "mutineer"
#define MODE_COMMANDO "commando"
#define MODE_DEATHSQUAD "deathsquad"
#define MODE_ERT "ert"
#define MODE_MERCENARY "mercenary"
#define MODE_NINJA "ninja"
#define MODE_RAIDER "raider"
#define MODE_WIZARD "wizard"
#define MODE_CHANGELING "changeling"
#define MODE_CULTIST "cultist"
#define MODE_HIGHLANDER "highlander"
#define MODE_MONKEY "monkey"
#define MODE_RENEGADE "renegade"
#define MODE_REVOLUTIONARY "revolutionary"
#define MODE_MALFUNCTION "malf"
#define MODE_TRAITOR "traitor"
/////////////////
////WIZARD //////
/////////////////
/* WIZARD SPELL FLAGS */
#define GHOSTCAST 1 //can a ghost cast it?
#define NEEDSCLOTHES 2 //does it need the wizard garb to cast? Nonwizard spells should not have this
#define NEEDSHUMAN 4 //does it require the caster to be human?
#define Z2NOCAST 8 //if this is added, the spell can't be cast at centcomm
#define STATALLOWED 16 //if set, the user doesn't have to be conscious to cast. Required for ghost spells
#define IGNOREPREV 32 //if set, each new target does not overlap with the previous one
//The following flags only affect different types of spell, and therefore overlap
//Targeted spells
#define INCLUDEUSER 64 //does the spell include the caster in its target selection?
#define SELECTABLE 128 //can you select each target for the spell?
//AOE spells
#define IGNOREDENSE 64 //are dense turfs ignored in selection?
#define IGNORESPACE 128 //are space turfs ignored in selection?
//End split flags
#define CONSTRUCT_CHECK 256 //used by construct spells - checks for nullrods
#define NO_BUTTON 512 //spell won't show up in the HUD with this
//invocation
#define SpI_SHOUT "shout"
#define SpI_WHISPER "whisper"
#define SpI_EMOTE "emote"
#define SpI_NONE "none"
//upgrading
#define Sp_SPEED "speed"
#define Sp_POWER "power"
#define Sp_TOTAL "total"
//casting costs
#define Sp_RECHARGE "recharge"
#define Sp_CHARGES "charges"
#define Sp_HOLDVAR "holdervar"

View File

@@ -0,0 +1,185 @@
#define HUMAN_STRIP_DELAY 40 // Takes 40ds = 4s to strip someone.
#define SHOES_SLOWDOWN -1.0 // How much shoes slow you down by default. Negative values speed you up.
#define CANDLE_LUM 3 // For how bright candles are.
// Item inventory slot bitmasks.
#define SLOT_OCLOTHING 1
#define SLOT_ICLOTHING 2
#define SLOT_GLOVES 4
#define SLOT_EYES 8
#define SLOT_EARS 16
#define SLOT_MASK 32
#define SLOT_HEAD 64
#define SLOT_FEET 128
#define SLOT_ID 256
#define SLOT_BELT 512
#define SLOT_BACK 1024
#define SLOT_POCKET 2048 // This is to allow items with a w_class of 3 or 4 to fit in pockets.
#define SLOT_DENYPOCKET 4096 // This is to deny items with a w_class of 2 or 1 from fitting in pockets.
#define SLOT_TWOEARS 8192
#define SLOT_TIE 16384
#define SLOT_HOLSTER 32768 //16th bit
// Flags bitmasks.
#define STOPPRESSUREDAMAGE 1 // This flag is used on the flags variable for SUIT and HEAD items which stop pressure damage. Note that the flag 1 was previous used as ONBACK, so it is possible for some code to use (flags & 1) when checking if something can be put on your back. Replace this code with (inv_flags & SLOT_BACK) if you see it anywhere
// To successfully stop you taking all pressure damage you must have both a suit and head item with this flag.
#define NOBLUDGEON 2 // When an item has this it produces no "X has been hit by Y with Z" message with the default handler.
#define AIRTIGHT 4 // Functions with internals.
#define USEDELAY 8 // 1 second extra delay on use. (Can be used once every 2s)
#define NOSHIELD 16 // Weapon not affected by shield.
#define CONDUCT 32 // Conducts electricity. (metal etc.)
#define ON_BORDER 64 // Item has priority to check when entering or leaving.
#define NOBLOODY 512 // Used for items if they don't want to get a blood overlay.
#define NODELAY 8192 // 1 second attack-by delay skipped (Can be used once every 0.2s). Most objects have a 1s attack-by delay, which doesn't require a flag.
//Use these flags to indicate if an item obscures the specified slots from view, whereas body_parts_covered seems to be used to indicate what body parts the item protects.
#define GLASSESCOVERSEYES 256
#define MASKCOVERSEYES 256 // Get rid of some of the other retardation in these flags.
#define HEADCOVERSEYES 256 // Feel free to reallocate these numbers for other purposes.
#define MASKCOVERSMOUTH 512 // On other items, these are just for mask/head.
#define HEADCOVERSMOUTH 512
#define THICKMATERIAL 256 // From /tg/station: prevents syringes, parapens and hyposprays if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body. (NOTE: flag shared with NOSLIP for shoes)
#define NOSLIP 256 // Prevents from slipping on wet floors, in space, etc.
#define OPENCONTAINER 1024 // Is an open container for chemistry purposes.
#define BLOCK_GAS_SMOKE_EFFECT 2048 // Blocks the effect that chemical clouds would have on a mob -- glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL)
#define ONESIZEFITSALL 2048
#define PHORONGUARD 4096 // Does not get contaminated by phoron.
#define NOREACT 4096 // Reagents don't react inside this container.
#define BLOCKHEADHAIR 4 // Temporarily removes the user's hair overlay. Leaves facial hair.
#define BLOCKHAIR 8192 // Temporarily removes the user's hair, facial and otherwise.
// Flags for pass_flags.
#define PASSTABLE 1
#define PASSGLASS 2
#define PASSGRILLE 4
#define PASSBLOB 8
// Bitmasks for the flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
// WARNING: The following flags apply only to the external suit!
#define HIDEGLOVES 1
#define HIDESUITSTORAGE 2
#define HIDEJUMPSUIT 4
#define HIDESHOES 8
#define HIDETAIL 16
// WARNING: The following flags apply only to the helmets and masks!
#define HIDEMASK 1
#define HIDEEARS 2 // Headsets and such.
#define HIDEEYES 4 // Glasses.
#define HIDEFACE 8 // Dictates whether we appear as "Unknown".
// Slots.
#define slot_back 1
#define slot_wear_mask 2
#define slot_handcuffed 3
#define slot_l_hand 4
#define slot_r_hand 5
#define slot_belt 6
#define slot_wear_id 7
#define slot_l_ear 8
#define slot_glasses 9
#define slot_gloves 10
#define slot_head 11
#define slot_shoes 12
#define slot_wear_suit 13
#define slot_w_uniform 14
#define slot_l_store 15
#define slot_r_store 16
#define slot_s_store 17
#define slot_in_backpack 18
#define slot_legcuffed 19
#define slot_r_ear 20
#define slot_legs 21
#define slot_tie 22
// Inventory slot strings.
// since numbers cannot be used as associative list keys.
#define slot_back_str "back"
#define slot_l_hand_str "slot_l_hand"
#define slot_r_hand_str "slot_r_hand"
#define slot_w_uniform_str "w_uniform"
// Bitflags for clothing parts.
#define HEAD 1
#define FACE 2
#define EYES 4
#define UPPER_TORSO 8
#define LOWER_TORSO 16
#define LEG_LEFT 32
#define LEG_RIGHT 64
#define LEGS 96 // LEG_LEFT | LEG_RIGHT
#define FOOT_LEFT 128
#define FOOT_RIGHT 256
#define FEET 384 // FOOT_LEFT | FOOT_RIGHT
#define ARM_LEFT 512
#define ARM_RIGHT 1024
#define ARMS 1536 // ARM_LEFT | ARM_RIGHT
#define HAND_LEFT 2048
#define HAND_RIGHT 4096
#define HANDS 6144 // HAND_LEFT | HAND_RIGHT
#define FULL_BODY 8191
// Bitflags for the percentual amount of protection a piece of clothing which covers the body part offers.
// Used with human/proc/get_heat_protection() and human/proc/get_cold_protection().
// The values here should add up to 1, e.g., the head has 30% protection.
#define THERMAL_PROTECTION_HEAD 0.3
#define THERMAL_PROTECTION_UPPER_TORSO 0.15
#define THERMAL_PROTECTION_LOWER_TORSO 0.15
#define THERMAL_PROTECTION_LEG_LEFT 0.075
#define THERMAL_PROTECTION_LEG_RIGHT 0.075
#define THERMAL_PROTECTION_FOOT_LEFT 0.025
#define THERMAL_PROTECTION_FOOT_RIGHT 0.025
#define THERMAL_PROTECTION_ARM_LEFT 0.075
#define THERMAL_PROTECTION_ARM_RIGHT 0.075
#define THERMAL_PROTECTION_HAND_LEFT 0.025
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
// Pressure limits.
#define HAZARD_HIGH_PRESSURE 550 // This determines at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
#define WARNING_HIGH_PRESSURE 325 // This determines when the orange pressure icon is displayed (it is 0.7 * HAZARD_HIGH_PRESSURE)
#define WARNING_LOW_PRESSURE 50 // This is when the gray low pressure icon is displayed. (it is 2.5 * HAZARD_LOW_PRESSURE)
#define HAZARD_LOW_PRESSURE 20 // This is when the black ultra-low pressure icon is displayed. (This one is set as a constant)
#define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 // This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount.
#define BODYTEMP_AUTORECOVERY_DIVISOR 12 // This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive.
#define BODYTEMP_AUTORECOVERY_MINIMUM 1 // Minimum amount of kelvin moved toward 310.15K per tick. So long as abs(310.15 - bodytemp) is more than 50.
#define BODYTEMP_COLD_DIVISOR 6 // Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is lower than their body temperature. Make it lower to lose bodytemp faster.
#define BODYTEMP_HEAT_DIVISOR 6 // Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is higher than their body temperature. Make it lower to gain bodytemp faster.
#define BODYTEMP_COOLING_MAX -30 // The maximum number of degrees that your body can cool down in 1 tick, when in a cold area.
#define BODYTEMP_HEATING_MAX 30 // The maximum number of degrees that your body can heat up in 1 tick, when in a hot area.
#define BODYTEMP_HEAT_DAMAGE_LIMIT 360.15 // The limit the human body can take before it starts taking damage from heat.
#define BODYTEMP_COLD_DAMAGE_LIMIT 260.15 // The limit the human body can take before it starts taking damage from coldness.
#define SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // What min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0.
#define SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // What min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0.
#define HELMET_MIN_COLD_PROTECTION_TEMPERATURE 160 // For normal helmets.
#define ARMOR_MIN_COLD_PROTECTION_TEMPERATURE 160 // For armor.
#define GLOVES_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // For some gloves.
#define SHOE_MIN_COLD_PROTECTION_TEMPERATURE 2.0 // For shoes.
#define SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE 5000 // These need better heat protect, but not as good heat protect as firesuits.
#define FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // What max_heat_protection_temperature is set to for firesuit quality headwear. MUST NOT BE 0.
#define FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 30000 // For fire-helmet quality items. (Red and white hardhats)
#define HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For normal helmets.
#define ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE 600 // For armor.
#define GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For some gloves.
#define SHOE_MAX_HEAT_PROTECTION_TEMPERATURE 1500 // For shoes.
// Fire.
#define FIRE_MIN_STACKS -20
#define FIRE_MAX_STACKS 25
#define FIRE_MAX_FIRESUIT_STACKS 20 // If the number of stacks goes above this firesuits won't protect you anymore. If not, you can walk around while on fire like a badass.
#define THROWFORCE_SPEED_DIVISOR 5 // The throwing speed value at which the throwforce multiplier is exactly 1.
#define THROWNOBJ_KNOCKBACK_SPEED 15 // The minumum speed of a w_class 2 thrown object that will cause living mobs it hits to be knocked back. Heavier objects can cause knockback at lower speeds.
#define THROWNOBJ_KNOCKBACK_DIVISOR 2 // Affects how much speed the mob is knocked back with.
// Suit sensor levels
#define SUIT_SENSOR_OFF 0
#define SUIT_SENSOR_BINARY 1
#define SUIT_SENSOR_VITAL 2
#define SUIT_SENSOR_TRACKING 3

View File

@@ -0,0 +1,99 @@
var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called manually after an event.
var/CELLRATE = 0.002 // Multiplier for watts per tick <> cell storage (e.g., 0.02 means if there is a load of 1000 watts, 20 units will be taken from a cell per second)
// It's a conversion constant. power_used*CELLRATE = charge_provided, or charge_used/CELLRATE = power_provided
var/CHARGELEVEL = 0.0005 // Cap for how fast cells charge, as a percentage-per-tick (0.01 means cellcharge is capped to 1% per second)
// Doors!
#define DOOR_CRUSH_DAMAGE 10
#define ALIEN_SELECT_AFK_BUFFER 1 // How many minutes that a person can be AFK before not being allowed to be an alien.
// Channel numbers for power.
#define EQUIP 1
#define LIGHT 2
#define ENVIRON 3
#define TOTAL 4 // For total power used only.
// Bitflags for machine stat variable.
#define BROKEN 1
#define NOPOWER 2
#define POWEROFF 4 // TBD.
#define MAINT 8 // Under maintenance.
#define EMPED 16 // Temporary broken by EMP pulse.
// Bitmasks for door switches.
#define OPEN 1
#define IDSCAN 2
#define BOLTS 4
#define SHOCK 8
#define SAFE 16
#define AI_CAMERA_LUMINOSITY 6
// Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them.
var/list/restricted_camera_networks = list("thunder","ERT","NUKE","Secret")
// Camera networks
#define NETWORK_CRESCENT "Crescent"
#define NETWORK_CIVILIAN_EAST "Civilian East"
#define NETWORK_CIVILIAN_WEST "Civilian West"
#define NETWORK_COMMAND "Command"
#define NETWORK_ENGINE "Engine"
#define NETWORK_ENGINEERING "Engineering"
#define NETWORK_ENGINEERING_OUTPOST "Engineering Outpost"
#define NETWORK_ERT "ERT"
#define NETWORK_EXODUS "Exodus"
#define NETWORK_MEDICAL "Medical"
#define NETWORK_MINE "MINE"
#define NETWORK_RESEARCH "Research"
#define NETWORK_RESEARCH_OUTPOST "Research Outpost"
#define NETWORK_PRISON "Prison"
#define NETWORK_SECURITY "Security"
#define NETWORK_TELECOM "Tcomsat"
#define NETWORK_THUNDER "thunder"
//singularity defines
#define STAGE_ONE 1
#define STAGE_TWO 3
#define STAGE_THREE 5
#define STAGE_FOUR 7
#define STAGE_FIVE 9
#define STAGE_SUPER 11
// computer3 error codes, move lower in the file when it passes dev -Sayu
#define PROG_CRASH 1 // Generic crash.
#define MISSING_PERIPHERAL 2 // Missing hardware.
#define BUSTED_ASS_COMPUTER 4 // Self-perpetuating error. BAC will continue to crash forever.
#define MISSING_PROGRAM 8 // Some files try to automatically launch a program. This is that failing.
#define FILE_DRM 16 // Some files want to not be copied/moved. This is them complaining that you tried.
#define NETWORK_FAILURE 32
// NanoUI flags
#define STATUS_INTERACTIVE 2 // GREEN Visability
#define STATUS_UPDATE 1 // ORANGE Visability
#define STATUS_DISABLED 0 // RED Visability
#define STATUS_CLOSE -1 // Close the interface
/*
* Atmospherics Machinery.
*/
#define MAX_SIPHON_FLOWRATE 2500 // L/s. This can be used to balance how fast a room is siphoned. Anything higher than CELL_VOLUME has no effect.
#define MAX_SCRUBBER_FLOWRATE 200 // L/s. Max flow rate when scrubbing from a turf.
// These balance how easy or hard it is to create huge pressure gradients with pumps and filters.
// Lower values means it takes longer to create large pressures differences.
// Has no effect on pumping gasses from high pressure to low, only from low to high.
#define ATMOS_PUMP_EFFICIENCY 2.5
#define ATMOS_FILTER_EFFICIENCY 2.5
// Will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance.
#define MINIMUM_MOLES_TO_PUMP 0.01
#define MINIMUM_MOLES_TO_FILTER 0.1
// The flow rate/effectiveness of various atmos devices is limited by their internal volume,
// so for many atmos devices these will control maximum flow rates in L/s.
#define ATMOS_DEFAULT_VOLUME_PUMP 200 // Liters.
#define ATMOS_DEFAULT_VOLUME_FILTER 200 // L.
#define ATMOS_DEFAULT_VOLUME_MIXER 200 // L.
#define ATMOS_DEFAULT_VOLUME_PIPE 70 // L.

View File

@@ -0,0 +1,27 @@
// Math constants.
#define M_PI 3.14159265
#define R_IDEAL_GAS_EQUATION 8.31 // kPa*L/(K*mol).
#define ONE_ATMOSPHERE 101.325 // kPa.
#define IDEAL_GAS_ENTROPY_CONSTANT 1164 // (mol^3 * s^3) / (kg^3 * L).
// Radiation constants.
#define STEFAN_BOLTZMANN_CONSTANT 5.6704e-8 // W/(m^2*K^4).
#define COSMIC_RADIATION_TEMPERATURE 3.15 // K.
#define AVERAGE_SOLAR_RADIATION 200 // W/m^2. Kind of arbitrary. Really this should depend on the sun position much like solars.
#define RADIATOR_OPTIMUM_PRESSURE 3771 // kPa at 20 C. This should be higher as gases aren't great conductors until they are dense. Used the critical pressure for air.
#define GAS_CRITICAL_TEMPERATURE 132.65 // K. The critical point temperature for air.
#define RADIATOR_EXPOSED_SURFACE_AREA_RATIO 0.04 // (3 cm + 100 cm * sin(3deg))/(2*(3+100 cm)). Unitless ratio.
#define T0C 273.15 // 0.0 degrees celcius
#define T20C 293.15 // 20.0 degrees celcius
#define TCMB 2.7 // -270.3 degrees celcius
#define CLAMP01(x) max(0, min(1, x))
#define QUANTIZE(variable) (round(variable,0.0001))
#define INFINITY 1.#INF
#define TICKS_IN_DAY 24*60*60*10
#define TICKS_IN_SECOND 10

150
code/__defines/misc.dm Normal file
View File

@@ -0,0 +1,150 @@
#define DEBUG
// Turf-only flags.
#define NOJAUNT 1 // This is used in literally one place, turf.dm, to block ethereal jaunt.
#define TRANSITIONEDGE 7 // Distance from edge to move to another z-level.
// Invisibility constants.
#define INVISIBILITY_LIGHTING 20
#define INVISIBILITY_LEVEL_ONE 35
#define INVISIBILITY_LEVEL_TWO 45
#define INVISIBILITY_OBSERVER 60
#define INVISIBILITY_EYE 61
#define SEE_INVISIBLE_LIVING 25
#define SEE_INVISIBLE_OBSERVER_NOLIGHTING 15
#define SEE_INVISIBLE_LEVEL_ONE 35
#define SEE_INVISIBLE_LEVEL_TWO 45
#define SEE_INVISIBLE_CULT 60
#define SEE_INVISIBLE_OBSERVER 61
#define SEE_INVISIBLE_MINIMUM 5
#define INVISIBILITY_MAXIMUM 100
// Some arbitrary defines to be used by self-pruning global lists. (see master_controller)
#define PROCESS_KILL 26 // Used to trigger removal from a processing list.
// Age limits on a character.
#define AGE_MIN 17
#define AGE_MAX 85
#define MAX_GEAR_COST 5 // Used in chargen for accessory loadout limit.
// Preference toggles.
#define SOUND_ADMINHELP 1
#define SOUND_MIDI 2
#define SOUND_AMBIENCE 4
#define SOUND_LOBBY 8
#define CHAT_OOC 16
#define CHAT_DEAD 32
#define CHAT_GHOSTEARS 64
#define CHAT_GHOSTSIGHT 128
#define CHAT_PRAYER 256
#define CHAT_RADIO 512
#define CHAT_ATTACKLOGS 1024
#define CHAT_DEBUGLOGS 2048
#define CHAT_LOOC 4096
#define CHAT_GHOSTRADIO 8192
#define SHOW_TYPING 16384
#define CHAT_NOICONS 32768
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
#define HEALTH_HUD 1 // A simple line rounding the mob's number health.
#define STATUS_HUD 2 // Alive, dead, diseased, etc.
#define ID_HUD 3 // The job asigned to your ID.
#define WANTED_HUD 4 // Wanted, released, paroled, security status.
#define IMPLOYAL_HUD 5 // Loyality implant.
#define IMPCHEM_HUD 6 // Chemical implant.
#define IMPTRACK_HUD 7 // Tracking implant.
#define SPECIALROLE_HUD 8 // AntagHUD image.
#define STATUS_HUD_OOC 9 // STATUS_HUD without virus DB check for someone being ill.
#define LIFE_HUD 10 // STATUS_HUD that only reports dead or alive
//some colors
#define COLOR_RED "#FF0000"
#define COLOR_GREEN "#00FF00"
#define COLOR_BLUE "#0000FF"
#define COLOR_CYAN "#00FFFF"
#define COLOR_PINK "#FF00FF"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_ORANGE "#FF9900"
#define COLOR_WHITE "#FFFFFF"
#define COLOR_BLACK "#000000"
// Shuttles.
// These define the time taken for the shuttle to get to the space station, and the time before it leaves again.
#define SHUTTLE_PREPTIME 300 // 5 minutes = 300 seconds - after this time, the shuttle departs centcom and cannot be recalled.
#define SHUTTLE_LEAVETIME 180 // 3 minutes = 180 seconds - the duration for which the shuttle will wait at the station after arriving.
#define SHUTTLE_TRANSIT_DURATION 300 // 5 minutes = 300 seconds - how long it takes for the shuttle to get to the station.
#define SHUTTLE_TRANSIT_DURATION_RETURN 120 // 2 minutes = 120 seconds - for some reason it takes less time to come back, go figure.
// Shuttle moving status.
#define SHUTTLE_IDLE 0
#define SHUTTLE_WARMUP 1
#define SHUTTLE_INTRANSIT 2
// Ferry shuttle processing status.
#define IDLE_STATE 0
#define WAIT_LAUNCH 1
#define FORCE_LAUNCH 2
#define WAIT_ARRIVE 3
#define WAIT_FINISH 4
// Setting this much higher than 1024 could allow spammers to DOS the server easily.
#define MAX_MESSAGE_LEN 1024
#define MAX_PAPER_MESSAGE_LEN 3072
#define MAX_BOOK_MESSAGE_LEN 9216
#define MAX_LNAME_LEN 64
#define MAX_NAME_LEN 26
// Event defines.
#define EVENT_LEVEL_MUNDANE 1
#define EVENT_LEVEL_MODERATE 2
#define EVENT_LEVEL_MAJOR 3
//General-purpose life speed define for plants.
#define HYDRO_SPEED_MULTIPLIER 1
#define DEFAULT_JOB_TYPE /datum/job/assistant
//Area flags, possibly more to come
#define RAD_SHIELDED 1 //shielded from radiation, clearly
// Custom layer definitions, supplementing the default TURF_LAYER, MOB_LAYER, etc.
#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
#define DOOR_CLOSED_LAYER 3.1 //Above most items if closed
#define LIGHTING_LAYER 11
#define OBFUSCATION_LAYER 14 //Where images covering the view for eyes are put
#define SCREEN_LAYER 17 //Mob HUD/effects layer
// Convoluted setup so defines can be supplied by Bay12 main server compile script.
// Should still work fine for people jamming the icons into their repo.
#ifndef CUSTOM_ITEM_OBJ
#define CUSTOM_ITEM_OBJ 'icons/obj/custom_items_obj.dmi'
#endif
#ifndef CUSTOM_ITEM_MOB
#define CUSTOM_ITEM_MOB 'icons/mob/custom_items_mob.dmi'
#endif
#ifndef CUSTOM_ITEM_SYNTH
#define CUSTOM_ITEM_SYNTH 'icons/mob/custom_synthetic.dmi'
#endif
#define WALL_CAN_OPEN 1
#define WALL_OPENING 2
#define DEFAULT_WALL_MATERIAL "steel"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"
#define SHARD_STONE_PIECE "piece"
#define SHARD_SPLINTER "splinters"
#define SHARD_NONE ""
#define MATERIAL_UNMELTABLE 1
#define MATERIAL_BRITTLE 2
#define MATERIAL_PADDING 4
#define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass)

86
code/__defines/mobs.dm Normal file
View File

@@ -0,0 +1,86 @@
// /mob/var/stat things.
#define CONSCIOUS 0
#define UNCONSCIOUS 1
#define DEAD 2
// Bitflags defining which status effects could be or are inflicted on a mob.
#define CANSTUN 1
#define CANWEAKEN 2
#define CANPARALYSE 4
#define CANPUSH 8
#define LEAPING 16
#define PASSEMOTES 32 // Mob has a cortical borer or holders inside of it that need to see emotes.
#define GODMODE 4096
#define FAKEDEATH 8192 // Replaces stuff like changeling.changeling_fakedeath.
#define DISFIGURED 16384 // I'll probably move this elsewhere if I ever get wround to writing a bitflag mob-damage system.
#define XENO_HOST 32768 // Tracks whether we're gonna be a baby alien's mummy.
// Grab levels.
#define GRAB_PASSIVE 1
#define GRAB_AGGRESSIVE 2
#define GRAB_NECK 3
#define GRAB_UPGRADING 4
#define GRAB_KILL 5
#define BORGMESON 1
#define BORGTHERM 2
#define BORGXRAY 4
#define HOSTILE_STANCE_IDLE 1
#define HOSTILE_STANCE_ALERT 2
#define HOSTILE_STANCE_ATTACK 3
#define HOSTILE_STANCE_ATTACKING 4
#define HOSTILE_STANCE_TIRED 5
#define LEFT 1
#define RIGHT 2
// Pulse levels, very simplified.
#define PULSE_NONE 0 // So !M.pulse checks would be possible.
#define PULSE_SLOW 1 // <60 bpm
#define PULSE_NORM 2 // 60-90 bpm
#define PULSE_FAST 3 // 90-120 bpm
#define PULSE_2FAST 4 // >120 bpm
#define PULSE_THREADY 5 // Occurs during hypovolemic shock
#define GETPULSE_HAND 0 // Less accurate. (hand)
#define GETPULSE_TOOL 1 // More accurate. (med scanner, sleeper, etc.)
//intent flags, why wasn't this done the first time?
#define I_HELP "help"
#define I_DISARM "disarm"
#define I_GRAB "grab"
#define I_HURT "hurt"
//These are used Bump() code for living mobs, in the mob_bump_flag, mob_swap_flags, and mob_push_flags vars to determine whom can bump/swap with whom.
#define HUMAN 1
#define MONKEY 2
#define ALIEN 4
#define ROBOT 8
#define SLIME 16
#define SIMPLE_ANIMAL 32
#define ALLMOBS (HUMAN|MONKEY|ALIEN|ROBOT|SLIME|SIMPLE_ANIMAL)
#define NEXT_MOVE_DELAY 8
// Robot AI notifications
#define ROBOT_NOTIFICATION_NEW_UNIT 1
#define ROBOT_NOTIFICATION_NEW_NAME 2
#define ROBOT_NOTIFICATION_NEW_MODULE 3
#define ROBOT_NOTIFICATION_MODULE_RESET 4
// Appearance change flags
#define APPEARANCE_UPDATE_DNA 1
#define APPEARANCE_RACE (2|APPEARANCE_UPDATE_DNA)
#define APPEARANCE_GENDER (4|APPEARANCE_UPDATE_DNA)
#define APPEARANCE_SKIN 8
#define APPEARANCE_HAIR 16
#define APPEARANCE_HAIR_COLOR 32
#define APPEARANCE_FACIAL_HAIR 64
#define APPEARANCE_FACIAL_HAIR_COLOR 128
#define APPEARANCE_EYE_COLOR 256
#define APPEARANCE_ALL_HAIR (APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR)
#define APPEARANCE_ALL 511
#define MIN_SUPPLIED_LAW_NUMBER 15
#define MAX_SUPPLIED_LAW_NUMBER 50

View File

@@ -0,0 +1,18 @@
#define SHEET_MATERIAL_AMOUNT 2000
#define TECH_MATERIAL "materials"
#define TECH_ENGINERING "engineering"
#define TECH_PHORON "phorontech"
#define TECH_POWER "powerstorage"
#define TECH_BLUESPACE "bluespace"
#define TECH_BIO "biotech"
#define TECH_COMBAT "combat"
#define TECH_MAGNET "magnets"
#define TECH_DATA "programming"
#define TECH_ILLEGAL "syndicate"
#define TECH_ARCANE "arcane"
#define IMPRINTER 1 //For circuits. Uses glass/chemicals.
#define PROTOLATHE 2 //New stuff. Uses glass/metal/chemicals
#define MECHFAB 4 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
#define CHASSIS 8 //For protolathe, but differently

View File

@@ -0,0 +1,47 @@
// Species flags.
#define NO_BLOOD 1 // Vessel var is not filled with blood, cannot bleed out.
#define NO_BREATHE 2 // Cannot suffocate or take oxygen loss.
#define NO_SCAN 4 // Cannot be scanned in a DNA machine/genome-stolen.
#define NO_PAIN 8 // Cannot suffer halloss/recieves deceptive health indicator.
#define NO_SLIP 16 // Cannot fall over.
#define NO_POISON 32 // Cannot not suffer toxloss.
#define HAS_SKIN_TONE 64 // Skin tone selectable in chargen. (0-255)
#define HAS_SKIN_COLOR 128 // Skin colour selectable in chargen. (RGB)
#define HAS_LIPS 256 // Lips are drawn onto the mob icon. (lipstick)
#define HAS_UNDERWEAR 512 // Underwear is drawn onto the mob icon.
#define IS_PLANT 1024 // Is a treeperson.
#define IS_WHITELISTED 2048 // Must be whitelisted to play.
#define HAS_EYE_COLOR 4096 // Eye colour selectable in chargen. (RGB)
#define CAN_JOIN 8192 // Species is selectable in chargen.
#define IS_RESTRICTED 16384 // Is not a core/normally playable species. (castes, mutantraces)
// unused: 32768 - higher than this will overflow
// Languages.
#define LANGUAGE_HUMAN 1
#define LANGUAGE_ALIEN 2
#define LANGUAGE_DOG 4
#define LANGUAGE_CAT 8
#define LANGUAGE_BINARY 16
#define LANGUAGE_OTHER 32768
#define LANGUAGE_UNIVERSAL 65535
#define LANGUAGE_SOL_COMMON "Sol Common"
#define LANGUAGE_UNATHI "Sinta'unathi"
#define LANGUAGE_SIIK_MAAS "Siik'maas"
#define LANGUAGE_SIIK_TAJR "Siik'tajr"
#define LANGUAGE_SKRELLIAN "Skrellian"
#define LANGUAGE_ROOTSPEAK "Rootspeak"
#define LANGUAGE_TRADEBAND "Tradeband"
#define LANGUAGE_GUTTER "Gutter"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
#define RESTRICTED 2 // Language can only be accquired by spawning or an admin.
#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight.
#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
#define HIVEMIND 16 // Broadcast to all mobs with this language.
#define NONGLOBAL 32 // Do not add to general languages list.
#define INNATE 64 // All mobs can be assumed to speak and understand this language. (audible emotes)
#define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message
#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems

View File

@@ -29,7 +29,7 @@ var/global/list/GlobalPool = list()
if(!D)
// So the GC knows we're pooling this type.
if(!GlobalPool[get_type])
GlobalPool[get_type] = list(new get_type)
GlobalPool[get_type] = list()
if(islist(second_arg))
return new get_type (arglist(second_arg))
else
@@ -58,7 +58,10 @@ var/global/list/GlobalPool = list()
#ifdef DEBUG_ATOM_POOL
world << text("DEBUG_DATUM_POOL: PlaceInPool([]) exceeds []. Discarding.", D.type, ATOM_POOL_COUNT)
#endif
del(D)
if(garbage_collector)
garbage_collector.AddTrash(D)
else
del(D)
return
if(D in GlobalPool[D.type])

View File

@@ -17,13 +17,20 @@
return 0
/proc/max_default_z_level()
return max(config.station_levels, max(config.admin_levels, config.player_levels))
var/max_z = 0
for(var/z in config.station_levels)
max_z = max(z, max_z)
for(var/z in config.admin_levels)
max_z = max(z, max_z)
for(var/z in config.player_levels)
max_z = max(z, max_z)
return max_z
/proc/get_area(O)
var/turf/loc = get_turf(O)
if(loc)
var/area/res = loc.loc
.= res.master
.= res
/proc/get_area_name(N) //get area by its name
for(var/area/A in world)
@@ -34,7 +41,7 @@
/proc/get_area_master(const/O)
var/area/A = get_area(O)
if (isarea(A))
return A.master
return A
/proc/in_range(source, user)
if(get_dist(source, user) <= 1)
@@ -69,18 +76,6 @@
/proc/isNotAdminLevel(var/level)
return !isAdminLevel(level)
//Magic constants obtained by using linear regression on right-angled triangles of sides 0<x<1, 0<y<1
//They should approximate pythagoras theorem well enough for our needs.
#define k1 0.934
#define k2 0.427
/proc/cheap_hypotenuse(Ax,Ay,Bx,By) // T is just the second atom to check distance to center with
var/dx = abs(Ax - Bx) //sides of right-angled triangle
var/dy = abs(Ay - By)
if(dx>=dy) return (k1*dx) + (k2*dy) //No sqrt or powers :)
else return (k2*dx) + (k1*dy)
#undef k1
#undef k2
/proc/circlerange(center=usr,radius=3)
var/turf/centerturf = get_turf(center)
@@ -161,37 +156,35 @@
// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
// being unable to hear people due to being in a box within a bag.
/proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1)
/proc/recursive_content_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_mobs = 1, var/include_objects = 1)
//debug_mob += O.contents.len
if(!recursion_limit)
return L
for(var/atom/A in O.contents)
if(ismob(A))
var/mob/M = A
if(client_check && !M.client)
L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
continue
if(sight_check && !isInSight(A, O))
continue
L |= M
//world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
for(var/I in O.contents)
else if(include_radio && istype(A, /obj/item/device/radio))
if(sight_check && !isInSight(A, O))
continue
L |= A
if(ismob(I))
if(!sight_check || isInSight(I, O))
L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
if(include_mobs)
if(client_check)
var/mob/M = I
if(M.client)
L |= M
else
L |= I
else if(istype(I,/obj/))
if(!sight_check || isInSight(I, O))
L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
if(include_objects)
L |= I
if(isobj(A) || ismob(A))
L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
return L
// The old system would loop through lists for a total of 5000 per function call, in an empty server.
// This new system will loop at around 1000 in an empty server.
// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code.
/proc/get_mobs_in_view(var/R, var/atom/source)
// Returns a list of mobs in range of R from source. Used in radio and say code.
/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1)
var/turf/T = get_turf(source)
var/list/hear = list()
@@ -201,17 +194,17 @@
var/list/range = hear(R, T)
for(var/atom/A in range)
if(ismob(A))
var/mob/M = A
if(M.client)
hear += M
//world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
else if(istype(A, /obj/item/device/radio))
hear += A
if(isobj(A) || ismob(A))
hear |= recursive_mob_check(A, hear, 3, 1, 0, 1)
for(var/I in range)
if(ismob(I))
hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
if(include_mobs)
var/mob/M = I
if(M.client)
hear += M
else if(istype(I,/obj/))
hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
if(include_objects)
hear += I
return hear

View File

@@ -7,6 +7,8 @@ var/list/directory = list() //list of all ckeys with associated client
var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player
var/global/list/mob_list = list() //List of all mobs, including clientless
var/global/list/human_mob_list = list() //List of all human mobs and sub-types, including clientless
var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
@@ -19,6 +21,8 @@ var/global/list/side_effects = list() //list of all medical sideeffects types
var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
var/global/list/turfs = list() //list of all turfs
//Languages/species/whitelist.
var/global/list/all_species[0]
var/global/list/all_languages[0]

View File

@@ -176,24 +176,21 @@ proc/listclearnulls(list/list)
return output
//Randomize: Return the list in a random order
/proc/shuffle(var/list/shufflelist)
if(!shufflelist)
/proc/shuffle(var/list/L)
if(!L)
return
var/list/new_list = list()
var/list/old_list = shufflelist.Copy()
while(old_list.len)
var/item = pick(old_list)
new_list += item
old_list -= item
return new_list
L = L.Copy()
for(var/i=1; i<L.len; i++)
L.Swap(i, rand(i,L.len))
return L
//Return a list with no duplicate entries
/proc/uniquelist(var/list/L)
var/list/K = list()
for(var/item in L)
if(!(item in K))
K += item
return K
. = list()
for(var/i in L)
. |= i
//Mergesort: divides up the list into halves to begin the sort
/proc/sortKey(var/list/client/L, var/order = 1)

View File

@@ -81,3 +81,15 @@
/proc/log_misc(text)
diary << "\[[time_stamp()]]MISC: [text][log_end]"
//pretty print a direction bitflag, can be useful for debugging.
/proc/print_dir(var/dir)
var/list/comps = list()
if(dir & NORTH) comps += "NORTH"
if(dir & SOUTH) comps += "SOUTH"
if(dir & EAST) comps += "EAST"
if(dir & WEST) comps += "WEST"
if(dir & UP) comps += "UP"
if(dir & DOWN) comps += "DOWN"
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")

View File

@@ -101,18 +101,18 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
// if they are imaginary.
/proc/SolveQuadratic(a, b, c)
ASSERT(a)
. = list()
var/discriminant = b*b - 4*a*c
var/bottom = 2*a
// Return if the roots are imaginary.
if(discriminant < 0)
return
var/root = sqrt(discriminant)
. += (-b + root) / bottom
// If discriminant == 0, there would be two roots at the same position.
if(discriminant != 0)
. += (-b - root) / bottom
@@ -131,3 +131,9 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
/proc/norm(x, y)
return sqrt(squaredNorm(x, y))
/proc/IsPowerOfTwo(var/val)
return (val & (val-1)) == 0
/proc/RoundUpToPowerOfTwo(var/val)
return 2 ** -round(-log(2,val))

View File

@@ -125,3 +125,10 @@ Proc for attack log creation, because really why not
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]</font>")
if(admin)
log_attack("<font color='red'>[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]</font>")
//checks whether this item is a module of the robot it is located in.
/proc/is_robot_module(var/obj/item/thing)
if (!thing || !istype(thing.loc, /mob/living/silicon/robot))
return 0
var/mob/living/silicon/robot/R = thing.loc
return (thing in R.module.modules)

View File

@@ -233,7 +233,7 @@ var/syndicate_code_response//Code response for traitors.
set name = "Generate Code Phrase"
set category = "Debug"
world << "\red Code Phrase is: \black [generate_code_phrase()]"
world << "<span class='warning'>Code Phrase is:</span> [generate_code_phrase()]"
return

View File

@@ -34,7 +34,8 @@
input = replace_characters(input, list("\n"=" ","\t"=" "))
if(encode)
//In addition to processing html, html_encode removes byond formatting codes like "\red", "\i" and other.
// The below \ escapes have a space inserted to attempt to enable Travis auto-checking of span class usage. Please do not remove the space.
//In addition to processing html, html_encode removes byond formatting codes like "\ red", "\ i" and other.
//It is important to avoid double-encode text, it can "break" quotes and some other characters.
//Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.)
input = html_encode(input)
@@ -312,4 +313,4 @@ proc/TextPreview(var/string,var/len=40)
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
if(C && (C.prefs.toggles & CHAT_NOICONS))
return tagdesc
return "<IMG src='\ref[text_tag_icons.icon]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
return "<IMG src='\ref[text_tag_icons.icon]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"

View File

@@ -11,3 +11,9 @@
/proc/isfloor(turf/T)
return (istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
/proc/turf_clear(turf/T)
for(var/atom/A in T)
if(A.simulated)
return 0
return 1

View File

@@ -70,19 +70,19 @@
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
if (sep <> null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
@@ -111,7 +111,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
@@ -122,9 +122,9 @@
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
@@ -145,7 +145,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
@@ -165,11 +165,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -181,11 +181,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtextEx(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -325,3 +325,47 @@ proc/tg_list2text(list/list, glue=",")
. = 0
else
. = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307))
// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time.
// returns "YYYY-MM-DD" by default
/proc/unix2date(timestamp, seperator = "-")
if(timestamp < 0)
return 0 //Do not accept negative values
var/const/dayInSeconds = 86400 //60secs*60mins*24hours
var/const/daysInYear = 365 //Non Leap Year
var/const/daysInLYear = daysInYear + 1//Leap year
var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc
var/year = 1970 //Unix Epoc begins 1970-01-01
var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1
var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code***
var/month = 1 //This will be the returned MONTH NUMBER.
var/day //This will be the returned day number.
while(tmpDays > daysInYear) //Start adding years to 1970
year++
if(isLeap(year))
tmpDays -= daysInLYear
else
tmpDays -= daysInYear
if(isLeap(year)) //The year is a leap year
monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334)
else
monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334)
var/mDays = 0;
var/monthIndex = 0;
for(var/m in monthsInDays)
monthIndex++
if(tmpDays > m)
mDays = m
month = monthIndex
day = tmpDays - mDays //Setup the date
return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]"
/proc/isLeap(y)
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))

View File

@@ -444,6 +444,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/sortmobs()
var/list/moblist = list()
var/list/sortmob = sortAtom(mob_list)
for(var/mob/eye/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/ai/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/pai/M in sortmob)
@@ -470,16 +472,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
// mob_list.Add(M)
return moblist
//E = MC^2
/proc/convert2energy(var/M)
var/E = M*(SPEED_OF_LIGHT_SQ)
return E
//M = E/C^2
/proc/convert2mass(var/E)
var/M = E/(SPEED_OF_LIGHT_SQ)
return M
//Forces a variable to be posative
/proc/modulus(var/M)
if(M >= 0)
@@ -921,7 +913,7 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
if(turftoleave)
fromupdate += T.ChangeTurf(turftoleave)
else
T.ChangeTurf(/turf/space)
T.ChangeTurf(get_base_turf(T.z))
refined_src -= T
refined_trg -= B
@@ -1004,7 +996,7 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
var/old_icon1 = T.icon
if(platingRequired)
if(istype(B, /turf/space))
if(istype(B, get_base_turf(B.z)))
continue moving
var/turf/X = new T.type(B)
@@ -1371,3 +1363,8 @@ var/list/WALLITEMS = list(
temp_col = "0[temp_col]"
colour += temp_col
return colour
/atom/proc/get_light_and_color(var/atom/origin)
if(origin)
color = origin.color
set_light(origin.light_range, origin.light_power, origin.light_color)

View File

@@ -229,17 +229,6 @@
/mob/living/carbon/MiddleClickOn(var/atom/A)
swap_hand()
/mob/living/carbon/human/MiddleClickOn(var/atom/A)
if(back)
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.selected_module)
if(world.time <= next_move) return
next_move = world.time + 8
rig.selected_module.engage(A)
return
swap_hand()
// In case of use break glass
/*
@@ -340,7 +329,7 @@
nutrition = max(nutrition - rand(1,5),0)
handle_regular_hud_updates()
else
src << "\red You're out of energy! You need food!"
src << "<span class='warning'>You're out of energy! You need food!</span>"
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(var/atom/A)

View File

@@ -13,13 +13,6 @@
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Upper left action buttons, displayed when you pick up an item that has this enabled.
#define ui_action_slot1 "1:6,14:26"
#define ui_action_slot2 "2:8,14:26"
#define ui_action_slot3 "3:10,14:26"
#define ui_action_slot4 "4:12,14:26"
#define ui_action_slot5 "5:14,14:26"
//Lower left, persistant menu
#define ui_inventory "1:6,1:5"

222
code/_onclick/hud/action.dm Normal file
View File

@@ -0,0 +1,222 @@
#define AB_ITEM 1
#define AB_SPELL 2
#define AB_INNATE 3
#define AB_GENERIC 4
#define AB_CHECK_RESTRAINED 1
#define AB_CHECK_STUNNED 2
#define AB_CHECK_LYING 4
#define AB_CHECK_ALIVE 8
#define AB_CHECK_INSIDE 16
/datum/action
var/name = "Generic Action"
var/action_type = AB_ITEM
var/procname = null
var/atom/movable/target = null
var/check_flags = 0
var/processing = 0
var/active = 0
var/obj/screen/movable/action_button/button = null
var/button_icon = 'icons/mob/actions.dmi'
var/button_icon_state = "default"
var/background_icon_state = "bg_default"
var/mob/living/owner
/datum/action/New(var/Target)
target = Target
/datum/action/Destroy()
if(owner)
Remove(owner)
/datum/action/proc/Grant(mob/living/T)
if(owner)
if(owner == T)
return
Remove(owner)
owner = T
owner.actions.Add(src)
owner.update_action_buttons()
return
/datum/action/proc/Remove(mob/living/T)
if(button)
if(T.client)
T.client.screen -= button
del(button)
T.actions.Remove(src)
T.update_action_buttons()
owner = null
return
/datum/action/proc/Trigger()
if(!Checks())
return
switch(action_type)
if(AB_ITEM)
if(target)
var/obj/item/item = target
item.ui_action_click()
//if(AB_SPELL)
// if(target)
// var/obj/effect/proc_holder/spell = target
// spell.Click()
if(AB_INNATE)
if(!active)
Activate()
else
Deactivate()
if(AB_GENERIC)
if(target && procname)
call(target,procname)(usr)
return
/datum/action/proc/Activate()
return
/datum/action/proc/Deactivate()
return
/datum/action/proc/Process()
return
/datum/action/proc/CheckRemoval(mob/living/user) // 1 if action is no longer valid for this mob and should be removed
return 0
/datum/action/proc/IsAvailable()
return Checks()
/datum/action/proc/Checks()// returns 1 if all checks pass
if(!owner)
return 0
if(check_flags & AB_CHECK_RESTRAINED)
if(owner.restrained())
return 0
if(check_flags & AB_CHECK_STUNNED)
if(owner.stunned)
return 0
if(check_flags & AB_CHECK_LYING)
if(owner.lying)
return 0
if(check_flags & AB_CHECK_ALIVE)
if(owner.stat)
return 0
if(check_flags & AB_CHECK_INSIDE)
if(!(target in owner))
return 0
return 1
/datum/action/proc/UpdateName()
return name
/obj/screen/movable/action_button
var/datum/action/owner
screen_loc = "WEST,NORTH"
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
moved = 0
return 1
if(usr.next_move >= world.time) // Is this needed ?
return
owner.Trigger()
return 1
/obj/screen/movable/action_button/proc/UpdateIcon()
if(!owner)
return
icon = owner.button_icon
icon_state = owner.background_icon_state
overlays.Cut()
var/image/img
if(owner.action_type == AB_ITEM && owner.target)
var/obj/item/I = owner.target
img = image(I.icon, src , I.icon_state)
else if(owner.button_icon && owner.button_icon_state)
img = image(owner.button_icon,src,owner.button_icon_state)
img.pixel_x = 0
img.pixel_y = 0
overlays += img
if(!owner.IsAvailable())
color = rgb(128,0,0,128)
else
color = rgb(255,255,255,255)
//Hide/Show Action Buttons ... Button
/obj/screen/movable/action_button/hide_toggle
name = "Hide Buttons"
icon = 'icons/mob/actions.dmi'
icon_state = "bg_default"
var/hidden = 0
/obj/screen/movable/action_button/hide_toggle/Click()
usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
hidden = usr.hud_used.action_buttons_hidden
if(hidden)
name = "Show Buttons"
else
name = "Hide Buttons"
UpdateIcon()
usr.update_action_buttons()
/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(var/mob/living/user)
if(isalien(user))
icon_state = "bg_alien"
else
icon_state = "bg_default"
UpdateIcon()
return
/obj/screen/movable/action_button/hide_toggle/UpdateIcon()
overlays.Cut()
var/image/img = image(icon,src,hidden?"show":"hide")
overlays += img
return
//This is the proc used to update all the action buttons. Properly defined in /mob/living/
/mob/proc/update_action_buttons()
return
#define AB_WEST_OFFSET 4
#define AB_NORTH_OFFSET 26
#define AB_MAX_COLUMNS 10
/datum/hud/proc/ButtonNumberToScreenCoords(var/number) // TODO : Make this zero-indexed for readabilty
var/row = round((number-1)/AB_MAX_COLUMNS)
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
var/coord_col = "+[col-1]"
var/coord_col_offset = AB_WEST_OFFSET+2*col
var/coord_row = "[-1 - row]"
var/coord_row_offset = AB_NORTH_OFFSET
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:[coord_row_offset]"
/datum/hud/proc/SetButtonCoords(var/obj/screen/button,var/number)
var/row = round((number-1)/AB_MAX_COLUMNS)
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
var/x_offset = 32*(col-1) + AB_WEST_OFFSET + 2*col
var/y_offset = -32*(row+1) + AB_NORTH_OFFSET
var/matrix/M = matrix()
M.Translate(x_offset,y_offset)
button.transform = M
//Presets for item actions
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE|AB_CHECK_INSIDE
/datum/action/item_action/CheckRemoval(mob/living/user)
return !(target in user)
/datum/action/item_action/hands_free
check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE
#undef AB_WEST_OFFSET
#undef AB_NORTH_OFFSET
#undef AB_MAX_COLUMNS

View File

@@ -133,7 +133,8 @@ var/list/global_huds = list(
var/list/other
var/list/obj/screen/hotkeybuttons
var/list/obj/screen/item_action/item_action_list = list() //Used for the item action ui buttons.
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = 0
datum/hud/New(mob/owner)
mymob = owner
@@ -261,11 +262,11 @@ datum/hud/New(mob/owner)
set hidden = 1
if(!hud_used)
usr << "\red This mob type does not use a HUD."
usr << "<span class='warning'>This mob type does not use a HUD.</span>"
return
if(!ishuman(src))
usr << "\red Inventory hiding is currently only supported for human mobs, sorry."
usr << "<span class='warning'>Inventory hiding is currently only supported for human mobs, sorry.</span>"
return
if(!client) return
@@ -279,8 +280,6 @@ datum/hud/New(mob/owner)
src.client.screen -= src.hud_used.other
if(src.hud_used.hotkeybuttons)
src.client.screen -= src.hud_used.hotkeybuttons
if(src.hud_used.item_action_list)
src.client.screen -= src.hud_used.item_action_list
//Due to some poor coding some things need special treatment:
//These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay
@@ -338,8 +337,6 @@ datum/hud/New(mob/owner)
src.client.screen -= src.hud_used.other
if(src.hud_used.hotkeybuttons)
src.client.screen -= src.hud_used.hotkeybuttons
if(src.hud_used.item_action_list)
src.client.screen -= src.hud_used.item_action_list
src.client.screen -= src.internals
src.client.screen += src.hud_used.action_intent //we want the intent swticher visible
else
@@ -356,4 +353,4 @@ datum/hud/New(mob/owner)
hud_used.hidden_inventory_update()
hud_used.persistant_inventory_update()
update_action_buttons()
update_action_buttons()

View File

@@ -385,52 +385,6 @@
client.screen -= hud_used.hotkeybuttons
hud_used.hotkey_ui_hidden = 1
/mob/living/carbon/human/update_action_buttons()
var/num = 1
if(!hud_used) return
if(!client) return
if(!hud_used.hud_shown) //Hud toggled to minimal
return
client.screen -= hud_used.item_action_list
hud_used.item_action_list = list()
for(var/obj/item/I in src)
if(I.icon_action_button)
var/obj/screen/item_action/A = new(hud_used)
//A.icon = 'icons/mob/screen1_action.dmi'
//A.icon_state = I.icon_action_button
A.icon = ui_style2icon(client.prefs.UI_style)
A.icon_state = "template"
var/image/img = image(I.icon, A, I.icon_state)
img.pixel_x = 0
img.pixel_y = 0
A.overlays += img
if(I.action_button_name)
A.name = I.action_button_name
else
A.name = "Use [I.name]"
A.owner = I
hud_used.item_action_list += A
switch(num)
if(1)
A.screen_loc = ui_action_slot1
if(2)
A.screen_loc = ui_action_slot2
if(3)
A.screen_loc = ui_action_slot3
if(4)
A.screen_loc = ui_action_slot4
if(5)
A.screen_loc = ui_action_slot5
break //5 slots available, so no more can be added.
num++
src.client.screen += src.hud_used.item_action_list
//Used for new human mobs created by cloning/goleming/etc.
/mob/living/carbon/human/proc/set_cloned_appearance()
f_style = "Shaved"

View File

@@ -0,0 +1,84 @@
//////////////////////////
//Movable Screen Objects//
// By RemieRichards //
//////////////////////////
//Movable Screen Object
//Not tied to the grid, places it's center where the cursor is
/obj/screen/movable
var/snap2grid = FALSE
var/moved = FALSE
//Snap Screen Object
//Tied to the grid, snaps to the nearest turf
/obj/screen/movable/snap
snap2grid = TRUE
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
var/list/PM = params2list(params)
//No screen-loc information? abort.
if(!PM || !PM["screen-loc"])
return
//Split screen-loc up into X+Pixel_X and Y+Pixel_Y
var/list/screen_loc_params = text2list(PM["screen-loc"], ",")
//Split X+Pixel_X up into list(X, Pixel_X)
var/list/screen_loc_X = text2list(screen_loc_params[1],":")
//Split Y+Pixel_Y up into list(Y, Pixel_Y)
var/list/screen_loc_Y = text2list(screen_loc_params[2],":")
if(snap2grid) //Discard Pixel Values
screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
var/pix_X = text2num(screen_loc_X[2]) - 16
var/pix_Y = text2num(screen_loc_Y[2]) - 16
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
moved = TRUE
//Debug procs
/client/proc/test_movable_UI()
set category = "Debug"
set name = "Spawn Movable UI Object"
var/obj/screen/movable/M = new()
M.name = "Movable UI Object"
M.icon_state = "block"
M.maptext = "Movable"
M.maptext_width = 64
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text
if(!screen_l)
return
M.screen_loc = screen_l
screen += M
/client/proc/test_snap_UI()
set category = "Debug"
set name = "Spawn Snap UI Object"
var/obj/screen/movable/snap/S = new()
S.name = "Snap UI Object"
S.icon_state = "block"
S.maptext = "Snap"
S.maptext_width = 64
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text
if(!screen_l)
return
S.screen_loc = screen_l
screen += S

View File

@@ -61,11 +61,6 @@
owner.ui_action_click()
return 1
//This is the proc used to update all the action buttons. It just returns for all mob types except humans.
/mob/proc/update_action_buttons()
return
/obj/screen/grab
name = "grab"

View File

@@ -20,6 +20,15 @@
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
return
//TODO: refactor mob attack code.
/*
Busy writing something else that I don't want to get mixed up in a general attack code, and I don't want to forget this so leaving a note here.
leave attackby() as handling the general case of "using an item on a mob"
attackby() will decide to call attacked_by() or not.
attacked_by() will be made a living level proc and handle the specific case of "attacking with an item to cause harm"
attacked_by() will then call attack() so that stunbatons and other weapons that have special attack effects can do their thing.
attacked_by() will handle hitting/missing/logging as it does now, and will call attack() to apply the attack effects (damage) instead of the other way around (as it is now).
*/
/obj/item/proc/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
@@ -29,22 +38,30 @@
user.lastattacked = M
M.lastattacker = user
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
if(!no_attack_log)
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
/////////////////////////
// Attacking someone with a weapon while they are neck-grabbed
if(user.a_intent == I_HURT)
for(var/obj/item/weapon/grab/G in M.grabbed_by)
if(G.assailant == user && G.state >= GRAB_NECK)
M.attack_throat(src, G, user)
var/power = force
if(HULK in user.mutations)
power *= 2
// TODO: needs to be refactored into a mob/living level attacked_by() proc. ~Z
user.do_attack_animation(M)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
// Handle striking to cripple.
var/dislocation_str
if(user.a_intent == "disarm")
if(user.a_intent == I_DISARM)
dislocation_str = H.attack_joint(src, user, def_zone)
if(H.attacked_by(src, user, def_zone) && hitsound)
playsound(loc, hitsound, 50, 1, -1)

View File

@@ -6,9 +6,9 @@
if(!client) return
client.inquisitive_ghost = !client.inquisitive_ghost
if(client.inquisitive_ghost)
src << "\blue You will now examine everything you click on."
src << "<span class='notice'>You will now examine everything you click on.</span>"
else
src << "\blue You will no longer examine things you click on."
src << "<span class='notice'>You will no longer examine things you click on.</span>"
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
if(client.buildmode)

View File

@@ -122,7 +122,7 @@
if ((!( src in usr.contents ) && (((!( isturf(src) ) && (!( isturf(src.loc) ) && (src.loc && !( isturf(src.loc.loc) )))) || !( isturf(usr.loc) )) && (src.loc != usr.loc && (!( istype(src, /obj/screen) ) && !( usr.contents.Find(src.loc) ))))))
if (istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/ai = usr
if (ai.control_disabled || ai.malfhacking)
if (ai.control_disabled)
return
else
return

View File

@@ -97,8 +97,6 @@
if (powerlevel > 0 && !istype(A, /mob/living/carbon/slime))
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species.flags & IS_SYNTHETIC)
return
stunprob *= H.species.siemens_coefficient

63
code/_onclick/rig.dm Normal file
View File

@@ -0,0 +1,63 @@
#define MIDDLE_CLICK 0
#define ALT_CLICK 1
#define CTRL_CLICK 2
#define MAX_HARDSUIT_CLICK_MODE 2
/client
var/hardsuit_click_mode = MIDDLE_CLICK
/client/verb/toggle_hardsuit_mode()
set name = "Toggle Hardsuit Activation Mode"
set desc = "Switch between hardsuit activation modes."
set category = "OOC"
hardsuit_click_mode++
if(hardsuit_click_mode > MAX_HARDSUIT_CLICK_MODE)
hardsuit_click_mode = 0
switch(hardsuit_click_mode)
if(MIDDLE_CLICK)
src << "Hardsuit activation mode set to middle-click."
if(ALT_CLICK)
src << "Hardsuit activation mode set to alt-click."
if(CTRL_CLICK)
src << "Hardsuit activation mode set to control-click."
else
// should never get here, but just in case:
soft_assert(0, "Bad hardsuit click mode: [hardsuit_click_mode] - expected 0 to [MAX_HARDSUIT_CLICK_MODE]")
src << "Somehow you bugged the system. Setting your hardsuit mode to middle-click."
hardsuit_click_mode = MIDDLE_CLICK
/mob/living/carbon/human/MiddleClickOn(atom/A)
if(client && client.hardsuit_click_mode == MIDDLE_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/AltClickOn(atom/A)
if(client && client.hardsuit_click_mode == ALT_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/CtrlClickOn(atom/A)
if(client && client.hardsuit_click_mode == CTRL_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/proc/HardsuitClickOn(atom/A)
if(back)
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.selected_module)
if(world.time <= next_move) return 1
next_move = world.time + 8
rig.selected_module.engage(A)
return 1
return 0
#undef MIDDLE_CLICK
#undef ALT_CLICK
#undef CTRL_CLICK
#undef MAX_HARDSUIT_CLICK_MODE

View File

@@ -120,7 +120,7 @@ var/const/tk_maxrange = 15
if(8 to tk_maxrange)
user.next_move += 10
else
user << "\blue Your mind won't reach that far."
user << "<span class='notice'>Your mind won't reach that far.</span>"
return
if(!focus)

View File

@@ -0,0 +1,33 @@
var/datum/controller/process/chemistry/chemistryProcess
/datum/controller/process/chemistry
var/tmp/datum/updateQueue/updateQueueInstance
var/list/active_holders
var/list/chemical_reactions
var/list/chemical_reagents
/datum/controller/process/chemistry/setup()
name = "chemistry"
schedule_interval = 20 // every 2 seconds
updateQueueInstance = new
chemistryProcess = src
active_holders = list()
chemical_reactions = chemical_reactions_list
chemical_reagents = chemical_reagents_list
/datum/controller/process/chemistry/getStatName()
return ..()+"([active_holders.len])"
/datum/controller/process/chemistry/doWork()
for(var/datum/reagents/holder in active_holders)
if(!holder.process_reactions())
active_holders -= holder
scheck()
/datum/controller/process/chemistry/proc/mark_for_update(var/datum/reagents/holder)
if(holder in active_holders)
return
//Process once, right away. If we still need to continue then add to the active_holders list and continue later
if(holder.process_reactions())
active_holders += holder

View File

@@ -78,21 +78,15 @@ var/list/delayed_garbage = list()
destroyed["\ref[A]"] = world.time
/datum/controller/process/garbage_collector/getStatName()
return ..()+"([garbage_collector.dels]/[garbage_collector.hard_dels])"
return ..()+"([garbage_collector.destroyed.len]/[garbage_collector.dels]/[garbage_collector.hard_dels])"
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(var/datum/A)
if(!A)
return
if(istype(A, /list))
var/list/L = A
for(var/E in L)
qdel(E)
return
if(!istype(A))
//warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
if(garbage_collector)
garbage_collector.dels++
@@ -121,7 +115,7 @@ var/list/delayed_garbage = list()
/icon/finalize_qdel()
del(src)
/imagine/finalize_qdel()
/image/finalize_qdel()
del(src)
/mob/finalize_qdel()

View File

@@ -1,16 +1,13 @@
/datum/controller/process/inactivity/setup()
name = "inactivity"
schedule_interval = INACTIVITY_KICK
schedule_interval = 600 // Once every minute (approx.)
/datum/controller/process/inactivity/doWork()
if(config.kick_inactive)
for(var/client/C in clients)
if(C.is_afk(INACTIVITY_KICK))
if(!C.holder && C.is_afk(config.kick_inactive MINUTES))
if(!istype(C.mob, /mob/dead))
log_access("AFK: [key_name(C)]")
C << "<SPAN CLASS='warning'>You have been inactive for more than 10 minutes and have been disconnected.</SPAN>"
C << "<SPAN CLASS='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</SPAN>"
del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
scheck()
#undef INACTIVITY_KICK

View File

@@ -6,18 +6,16 @@
/datum/controller/process/machinery/doWork()
internal_sort()
internal_process()
internal_process_machinery()
internal_process_power()
internal_process_power_drain()
/datum/controller/process/machinery/proc/internal_sort()
if(machinery_sort_required)
machinery_sort_required = 0
machines = dd_sortedObjectList(machines)
/datum/controller/process/machinery/proc/internal_process()
//#ifdef PROFILE_MACHINES
//machine_profiling.len = 0
//#endif
/datum/controller/process/machinery/proc/internal_process_machinery()
for(var/obj/machinery/M in machines)
if(M && !M.gcDestroyed)
#ifdef PROFILE_MACHINES
@@ -43,6 +41,22 @@
scheck()
/datum/controller/process/machinery/proc/internal_process_power()
for(var/datum/powernet/powerNetwork in powernets)
if(istype(powerNetwork) && !powerNetwork.disposed)
powerNetwork.reset()
scheck()
continue
powernets.Remove(powerNetwork)
/datum/controller/process/machinery/proc/internal_process_power_drain()
// Currently only used by powersinks. These items get priority processed before machinery
for(var/obj/item/I in processing_power_items)
if(!I.pwr_drain()) // 0 = Process Kill, remove from processing list.
processing_power_items.Remove(I)
scheck()
/datum/controller/process/machinery/getStatName()
return ..()+"([machines.len])"
return ..()+"([machines.len])"

View File

@@ -1,20 +0,0 @@
/datum/controller/process/powernet/setup()
name = "powernet"
schedule_interval = 20 // every 2 seconds
/datum/controller/process/powernet/doWork()
for(var/datum/powernet/powerNetwork in powernets)
if(istype(powerNetwork) && !powerNetwork.disposed)
powerNetwork.reset()
scheck()
continue
powernets.Remove(powerNetwork)
// This is necessary to ensure powersinks are always the first devices that drain power from powernet.
// Otherwise APCs or other stuff go first, resulting in bad things happening.
for(var/obj/item/device/powersink/S in processing_objects)
S.drain()
/datum/controller/process/powernet/getStatName()
return ..()+"([powernets.len])"

View File

@@ -1,9 +1,14 @@
var/global/list/processing_turfs = list()
var/global/list/turf/processing_turfs = list()
/datum/controller/process/turf/setup()
name = "turf"
schedule_interval = 20 // every 2 seconds
/datum/controller/process/turf/doWork()
for(var/turf/unsimulated/wall/supermatter/SM in processing_turfs)
SM.process()
for(var/turf/T in processing_turfs)
if(T.process() == PROCESS_KILL)
processing_turfs.Remove(T)
scheck()
/datum/controller/process/turf/getStatName()
return ..()+"([processing_turfs.len])"

View File

@@ -1,450 +0,0 @@
/*
Modified DynamicAreaLighting for TGstation - Coded by Carnwennan
This is TG's 'new' lighting system. It's basically a heavily modified combination of Forum_Account's and
ShadowDarke's respective lighting libraries. Credits, where due, to them.
Like sd_DAL (what we used to use), it changes the shading overlays of areas by splitting each type of area into sub-areas
by using the var/tag variable and moving turfs into the contents list of the correct sub-area. This method is
much less costly than using overlays or objects.
Unlike sd_DAL however it uses a queueing system. Everytime we call a change to opacity or luminosity
(through SetOpacity() or SetLuminosity()) we are simply updating variables and scheduling certain lights/turfs for an
update. Actual updates are handled periodically by the lighting_controller. This carries additional overheads, however it
means that each thing is changed only once per lighting_controller.processing_interval ticks. Allowing for greater control
over how much priority we'd like lighting updates to have. It also makes it possible for us to simply delay updates by
setting lighting_controller.processing = 0 at say, the start of a large explosion, waiting for it to finish, and then
turning it back on with lighting_controller.processing = 1.
Unlike our old system there are hardcoded maximum luminositys (different for certain atoms).
This is to cap the cost of creating lighting effects.
(without this, an atom with luminosity of 20 would have to update 41^2 turfs!) :s
Also, in order for the queueing system to work, each light remembers the effect it casts on each turf. This is going to
have larger memory requirements than our previous system but it's easily worth the hassle for the greater control we
gain. It also reduces cost of removing lighting effects by a lot!
Known Issues/TODO:
Shuttles still do not have support for dynamic lighting (I hope to fix this at some point)
No directional lighting support. (prototype looked ugly)
*/
#define LIGHTING_CIRCULAR 1 //comment this out to use old square lighting effects.
#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' //Icon used for lighting shading effects
datum/light_source
var/atom/owner
var/changed = 1
var/list/effect = list()
var/__x = 0 //x coordinate at last update
var/__y = 0 //y coordinate at last update
var/__z = 0 //z coordinate at last update
var/_l_color //do not use directly, only used as reference for updating
var/col_r
var/col_g
var/col_b
New(atom/A)
if(!istype(A))
CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
..()
owner = A
readrgb(owner.l_color)
__x = owner.x
__y = owner.y
__z = owner.z
// the lighting object maintains a list of all light sources
lighting_controller.lights += src
//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one
proc/check()
if(!owner)
remove_effect()
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
// check to see if we've moved since last update
if(owner.x != __x || owner.y != __y || owner.z != __z)
__x = owner.x
__y = owner.y
__z = owner.z
changed = 1
if (owner.l_color != _l_color)
readrgb(owner.l_color)
changed = 1
if(changed)
changed = 0
remove_effect()
return add_effect()
return 0
proc/remove_effect()
// before we apply the effect we remove the light's current effect.
for(var/turf/T in effect) // negate the effect of this light source
T.update_lumcount(-effect[T], col_r, col_g, col_b, 1)
effect.Cut() // clear the effect list
proc/add_effect()
// only do this if the light is turned on and is on the map
if(owner.loc && owner.luminosity > 0)
readrgb(owner.l_color)
effect = list()
for(var/turf/T in view(owner.get_light_range(),get_turf(owner)))
var/delta_lumen = lum(T)
if(delta_lumen > 0)
effect[T] = delta_lumen
T.update_lumcount(delta_lumen, col_r, col_g, col_b, 0)
return 0
else
owner.light = null
return 1 //cause the light to be removed from the lights list and garbage collected once it's no
//longer referenced by the queue
proc/lum(turf/A)
if (owner.trueLuminosity < 1)
return 0
var/dist
if(!A)
dist = 0
else
#ifdef LIGHTING_CIRCULAR
dist = cheap_hypotenuse(A.x, A.y, __x, __y)
#else
dist = max(abs(A.x - __x), abs(A.y - __y))
#endif
if (owner.trueLuminosity > 100) // This will never happen... right?
return sqrt(owner.trueLuminosity) - dist
else
return sqrtTable[owner.trueLuminosity] - dist
proc/readrgb(col)
_l_color = col
if(col)
col_r = GetRedPart(col)
col_g = GetGreenPart(col)
col_b = GetBluePart(col)
else
col_r = null
atom
var/datum/light_source/light
var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
// We may read it, but NEVER set it directly.
var/l_color
//Turfs with opacity when they are constructed will trigger nearby lights to update
//Turfs and atoms with luminosity when they are constructed will create a light_source automatically
turf/New()
..()
if(luminosity)
if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
trueLuminosity = luminosity * luminosity
light = new(src)
//Movable atoms with opacity when they are constructed will trigger nearby lights to update
//Movable atoms with luminosity when they are constructed will create a light_source automatically
atom/movable/New()
..()
if(opacity)
if(isturf(loc))
if(loc:lighting_lumcount > 1)
UpdateAffectingLights()
if(luminosity)
if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
trueLuminosity = luminosity * luminosity
light = new(src)
//Sets our luminosity.
//If we have no light it will create one.
//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its
//queues are complete.
//if we have a light already it is merely updated, rather than making a new one.
atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE)
if(new_luminosity < 0)
new_luminosity = 0
if(!trueLum)
new_luminosity *= new_luminosity
if(light)
if(trueLuminosity != new_luminosity) //non-luminous lights are removed from the lights list in add_effect()
light.changed = 1
else
if(new_luminosity)
light = new(src)
trueLuminosity = new_luminosity
if (trueLuminosity < 1)
luminosity = 0
else if (trueLuminosity <= 100)
luminosity = sqrtTable[trueLuminosity]
else
luminosity = sqrt(trueLuminosity)
atom/proc/AddLuminosity(delta_luminosity)
if(delta_luminosity > 0)
SetLuminosity(trueLuminosity + delta_luminosity*delta_luminosity, TRUE)
else if(delta_luminosity < 0)
SetLuminosity(trueLuminosity - delta_luminosity*delta_luminosity, TRUE)
area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas
luminosity = !!new_luminosity
trueLuminosity = luminosity
//change our opacity (defaults to toggle), and then update all lights that affect us.
atom/proc/SetOpacity(new_opacity)
if(new_opacity == null)
new_opacity = !opacity //default = toggle opacity
else if(opacity == new_opacity)
return 0 //opacity hasn't changed! don't bother doing anything
opacity = new_opacity //update opacity, the below procs now call light updates.
return 1
turf/SetOpacity(new_opacity)
if(..()==1) //only bother if opacity changed
if(lighting_lumcount) //only bother with an update if our turf is currently affected by a light
UpdateAffectingLights()
/atom/movable/SetOpacity(new_opacity)
if(..()==1) //only bother if opacity changed
if(isturf(loc)) //only bother with an update if we're on a turf
var/turf/T = loc
if(T.lighting_lumcount) //only bother with an update if our turf is currently affected by a light
UpdateAffectingLights()
turf
var/lighting_lumcount = 0
var/lighting_changed = 0
var/color_lighting_lumcount = 0
var/lumcount_r = 0
var/lumcount_g = 0
var/lumcount_b = 0
var/light_col_sources = 0
turf/space
lighting_lumcount = 4 //starlight
turf/proc/update_lumcount(amount, col_r, col_g, col_b, removing = 0)
lighting_lumcount += amount
if(!isnull(col_r)) //col_r is the "key" var, if it's null so will the rest
if(removing)
light_col_sources--
lumcount_r -= col_r
lumcount_g -= col_g
lumcount_b -= col_b
else
light_col_sources++
lumcount_r += col_r
lumcount_g += col_g
lumcount_b += col_b
if(light_col_sources)
var/r_avg = max(0, min(255, round(lumcount_r / light_col_sources, 16) + 15))
var/g_avg = max(0, min(255, round(lumcount_g / light_col_sources, 16) + 15))
var/b_avg = max(0, min(255, round(lumcount_b / light_col_sources, 16) + 15))
l_color = rgb(r_avg, g_avg, b_avg)
else
l_color = null
color_lighting_lumcount = max(color_lighting_lumcount + amount, 0) // Minimum of 0.
if(!lighting_changed)
lighting_controller.changed_turfs += src
lighting_changed = 1
turf/proc/lighting_tag(const/level)
var/area/A = loc
return A.tagbase + "sd_L[level]"
turf/proc/build_lighting_area(const/tag, const/level, const/color_light)
var/area/Area = loc
var/area/A = new Area.type() // create area if it wasn't found
// replicate vars
for(var/V in Area.vars)
switch(V)
if ("contents","lighting_overlay", "color_overlay", "overlays")
continue
else
if(issaved(Area.vars[V])) A.vars[V] = Area.vars[V]
A.tag = tag
A.lighting_subarea = 1
A.lighting_space = 0 // in case it was copied from a space subarea
if (l_color != A.l_color)
A.l_color = l_color
//color_light = min(max(round(color_lighting_lumcount, 1), 0), lighting_controller.lighting_states)
//world << "[color_light] [color_lighting_lumcount]"
A.SetLightLevel(level, color_light)
Area.related += A
return A
turf/proc/shift_to_subarea()
lighting_changed = 0
var/area/Area = loc
if(!istype(Area) || !Area.lighting_use_dynamic) return
var/level = min(max(round(lighting_lumcount,1),0),lighting_controller.lighting_states)
var/new_tag = lighting_tag(level)
// pomf - If we have a lighting color that is not null, apply the new tag to seperate the areas.
if (l_color)
// pomf - We append the (rounded!) color lighting lumcount so we can have colored lights.
new_tag += "[l_color][min(max(round(color_lighting_lumcount,1),0),lighting_controller.lighting_states)]"
if(Area.tag!=new_tag) //skip if already in this area
var/area/A = locate(new_tag) // find an appropriate area
var/color_light = min(max(round(color_lighting_lumcount,1),0),lighting_controller.lighting_states)
if (!A)
A = build_lighting_area(new_tag, level, color_light)
else if (l_color != A.l_color)
A.l_color = l_color
//color_light = min(max(round(color_lighting_lumcount, 1), 0), lighting_controller.lighting_states)
A.SetLightLevel(level, color_light)
A.contents += src // move the turf into the area
universe.OnTurfTick(src)
// Dedicated lighting sublevel for space turfs
// helps us depower things in space, remove space fire alarms,
// and evens out space lighting
turf/space/lighting_tag(var/level)
var/area/A = loc
return A.tagbase + "sd_L_space"
turf/space/build_lighting_area(var/tag,var/level)
var/area/A = ..(tag,4)
A.lighting_space = 1
A.SetLightLevel(4)
A.icon_state = null
return A
area
var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area
var/image/lighting_overlay //tracks the darkness image of the area for easy removal
var/lighting_subarea = 0 //tracks whether we're a lighting sub-area
var/lighting_space = 0 // true for space-only lighting subareas
var/tagbase
var/image/color_overlay //Tracks the color image.
proc/SetLightLevel(light, color_light = 0)
if(!src) return
if(light <= 0)
light = 0
luminosity = 0
else
if(light > lighting_controller.lighting_states)
light = lighting_controller.lighting_states
luminosity = 1
if(lighting_overlay)
overlays -= lighting_overlay
lighting_overlay.icon_state = "[light]"
else
lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
if (color_overlay)
overlays.Remove(color_overlay)
color_overlay.icon_state = "5"
else
if (l_color)
color_overlay = image('icons/effects/effects.dmi', ,"5", 10.1)
//color_overlay = image('icons/effects/effects.dmi', ,"white", 10.1)
if (istype(color_overlay))
color_overlay.color = l_color
switch (color_light)
if (6)
color_overlay.icon_state = "5"
//color_overlay.alpha = 180
if (5)
color_overlay.icon_state = "4"
//color_overlay.alpha = 150
if (4)
color_overlay.icon_state = "3"
//color_overlay.alpha = 120
if (3)
color_overlay.icon_state = "2"
//color_overlay.alpha = 90
if (2)
color_overlay.icon_state = "1"
//color_overlay.alpha = 60
if (1)
color_overlay.icon_state = "1"
color_overlay.alpha = 200
//color_overlay.alpha = 30
if (-INFINITY to 0)
//world << "Zero or below, [color_light]."
color_overlay.alpha = 0
else
//world << "Setting the alpha to max... color_light [color_light]."
color_overlay.alpha = 180
color_overlay.blend_mode = BLEND_ADD
if (color_overlay.color)
overlays.Add(color_overlay)
if (isnull(color_overlay))
overlays.Add(lighting_overlay)
else if (light < 6)
overlays.Add(lighting_overlay)
proc/SetDynamicLighting()
src.lighting_use_dynamic = 1
for(var/turf/T in src.contents)
T.update_lumcount(0)
proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
tagbase = "[type]"
if(!tag) tag = tagbase
if(!lighting_use_dynamic)
if(!lighting_subarea) // see if this is a lighting subarea already
//show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly.
SetLightLevel(4)
//#undef LIGHTING_LAYER
#undef LIGHTING_CIRCULAR
//#undef LIGHTING_ICON
#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag.
#define LIGHTING_MAX_LUMINOSITY_MOBILE 5 //Moving objects have a lower max luminosity since these update more often. (lag reduction)
#define LIGHTING_MAX_LUMINOSITY_TURF 1 //turfs have a severely shortened range to protect from inevitable floor-lighttile spam.
//set the changed status of all lights which could have possibly lit this atom.
//We don't need to worry about lights which lit us but moved away, since they will have change status set already
//This proc can cause lots of lights to be updated. :(
atom/proc/UpdateAffectingLights()
for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src))
if(A.light)
A.light.changed = 1 //force it to update at next process()
//caps luminosity effects max-range based on what type the light's owner is.
atom/proc/get_light_range()
return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
atom/movable/get_light_range()
return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOBILE)
obj/machinery/light/get_light_range()
return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
turf/get_light_range()
return min(luminosity, LIGHTING_MAX_LUMINOSITY_TURF)
#undef LIGHTING_MAX_LUMINOSITY_STATIC
#undef LIGHTING_MAX_LUMINOSITY_MOBILE
#undef LIGHTING_MAX_LUMINOSITY_TURF

View File

@@ -72,7 +72,7 @@ Radio:
1355 - Medical
1357 - Engineering
1359 - Security
1341 - death squad
1341 - deathsquad
1443 - Confession Intercom
1347 - Cargo techs
1349 - Service people

View File

@@ -63,7 +63,7 @@ var/list/gamemode_cache = list()
var/guest_jobban = 1
var/usewhitelist = 0
var/mods_are_mentors = 0
var/kick_inactive = 0 //force disconnect for inactive players
var/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
var/load_jobs_from_txt = 0
var/ToRban = 0
var/automute_on = 0 //enables automuting/spam prevention
@@ -95,8 +95,7 @@ var/list/gamemode_cache = list()
var/banappeals
var/wikiurl
var/forumurl
var/rulesurl
var/githuburl
//Alert level description
var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
@@ -116,6 +115,10 @@ var/list/gamemode_cache = list()
var/organ_health_multiplier = 1
var/organ_regeneration_multiplier = 1
//Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
//so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
var/organ_damage_spillover_multiplier = 0.5
var/bones_can_break = 0
var/limbs_can_break = 0
@@ -169,6 +172,7 @@ var/list/gamemode_cache = list()
var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle
var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect
var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach
var/list/sealed_levels = list() // Defines levels that do not allow random transit at the edges.
// Event settings
var/expected_round_length = 3 * 60 * 60 * 10 // 3 hours
@@ -392,9 +396,8 @@ var/list/gamemode_cache = list()
if ("forumurl")
config.forumurl = value
if ("rulesurl")
config.rulesurl = value
if ("githuburl")
config.githuburl = value
if ("guest_jobban")
config.guest_jobban = 1
@@ -460,7 +463,7 @@ var/list/gamemode_cache = list()
config.allow_random_events = 1
if("kick_inactive")
config.kick_inactive = 1
config.kick_inactive = text2num(value)
if("load_jobs_from_txt")
load_jobs_from_txt = 1
@@ -674,6 +677,8 @@ var/list/gamemode_cache = list()
config.organ_health_multiplier = value / 100
if("organ_regeneration_multiplier")
config.organ_regeneration_multiplier = value / 100
if("organ_damage_spillover_multiplier")
config.organ_damage_spillover_multiplier = value / 100
if("bones_can_break")
config.bones_can_break = value
if("limbs_can_break")

View File

@@ -25,7 +25,6 @@ var/datum/controller/failsafe/Failsafe
set background = 1
while(1) //more efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop
if(!master_controller) new /datum/controller/game_controller() //replace the missing master_controller! This should never happen.
if(!lighting_controller) new /datum/controller/lighting() //replace the missing lighting_controller
if(processing)
if(lighting_controller.processing)

View File

@@ -1,130 +0,0 @@
var/datum/controller/lighting/lighting_controller = new ()
datum/controller/lighting
var/processing = 0
var/processing_interval = 5 //setting this too low will probably kill the server. Don't be silly with it!
var/process_cost = 0
var/iteration = 0
var/lighting_states = 7
var/list/lights = list()
var/lights_workload_max = 0
// var/list/changed_lights() //TODO: possibly implement this to reduce on overheads?
var/list/changed_turfs = list()
var/changed_turfs_workload_max = 0
datum/controller/lighting/New()
lighting_states = max( 0, length(icon_states(LIGHTING_ICON))-1 )
if(lighting_controller != src)
if(istype(lighting_controller,/datum/controller/lighting))
Recover() //if we are replacing an existing lighting_controller (due to a crash) we attempt to preserve as much as we can
qdel(lighting_controller)
lighting_controller = src
//Workhorse of lighting. It cycles through each light to see which ones need their effects updating. It updates their
//effects and then processes every turf in the queue, moving the turfs to the corresponing lighting sub-area.
//All queue lists prune themselves, which will cause lights with no luminosity to be garbage collected (cheaper and safer
//than deleting them). Processing interval should be roughly half a second for best results.
//By using queues we are ensuring we don't perform more updates than are necessary
datum/controller/lighting/proc/process()
processing = 1
spawn(0)
set background = 1
while(1)
if(processing)
iteration++
var/started = world.timeofday
lights_workload_max = max(lights_workload_max,lights.len)
for(var/i=1, i<=lights.len, i++)
var/datum/light_source/L = lights[i]
if(L && !L.check())
continue
lights.Cut(i,i+1)
i--
sleep(-1)
changed_turfs_workload_max = max(changed_turfs_workload_max,changed_turfs.len)
for(var/i=1, i<=changed_turfs.len, i++)
var/turf/T = changed_turfs[i]
if(T && T.lighting_changed)
T.shift_to_subarea()
changed_turfs.Cut() // reset the changed list
process_cost = (world.timeofday - started)
sleep(processing_interval)
//same as above except it attempts to shift ALL turfs in the world regardless of lighting_changed status
//Does not loop. Should be run prior to process() being called for the first time.
//Note: if we get additional z-levels at runtime (e.g. if the gateway thin ever gets finished) we can initialize specific
//z-levels with the z_level argument
datum/controller/lighting/proc/initializeLighting(var/z_level)
processing = 0
spawn(-1)
set background = 1
for(var/i=1, i<=lights.len, i++)
var/datum/light_source/L = lights[i]
if(L.check())
lights.Cut(i,i+1)
i--
var/z_start = 1
var/z_finish = world.maxz
if(z_level)
z_level = round(z_level,1)
if(z_level > 0 && z_level <= world.maxz)
z_start = z_level
z_finish = z_level
for(var/k=z_start,k<=z_finish,k++)
for(var/i=1,i<=world.maxx,i++)
for(var/j=1,j<=world.maxy,j++)
var/turf/T = locate(i,j,k)
if(T) T.shift_to_subarea()
changed_turfs.Cut() // reset the changed list
//Used to strip valid information from an existing controller and transfer it to a replacement
//It works by using spawn(-1) to transfer the data, if there is a runtime the data does not get transfered but the loop
//does not crash
datum/controller/lighting/proc/Recover()
if(!istype(lighting_controller.changed_turfs,/list))
lighting_controller.changed_turfs = list()
if(!istype(lighting_controller.lights,/list))
lighting_controller.lights = list()
for(var/i=1, i<=lighting_controller.lights.len, i++)
var/datum/light_source/L = lighting_controller.lights[i]
if(istype(L))
spawn(-1) //so we don't crash the loop (inefficient)
L.check()
lights += L //If we didn't runtime then this will get transferred over
for(var/i=1, i<=lighting_controller.changed_turfs.len, i++)
var/turf/T = lighting_controller.changed_turfs[i]
if(istype(T) && T.lighting_changed)
spawn(-1)
T.shift_to_subarea()
var/msg = "## DEBUG: [time2text(world.timeofday)] lighting_controller restarted. Reports:\n"
for(var/varname in lighting_controller.vars)
switch(varname)
if("tag","bestF","type","parent_type","vars") continue
else
var/varval1 = lighting_controller.vars[varname]
var/varval2 = vars[varname]
if(istype(varval1,/list))
varval1 = "/list([length(varval1)])"
varval2 = "/list([length(varval2)])"
msg += "\t [varname] = [varval1] -> [varval2]\n"
world.log << msg
#undef LIGHTING_ICON

View File

@@ -12,7 +12,6 @@ var/global/pipe_processing_killed = 0
datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
var/datum/random_map/ore/asteroid_ore_map // For debugging and VV.
datum/controller/game_controller/New()
//There can be only one master_controller. Out with the old and in with the new.
@@ -39,7 +38,6 @@ datum/controller/game_controller/proc/setup()
setup_objects()
setupgenetics()
setup_economy()
SetupXenoarch()
transfer_controller = new
@@ -66,11 +64,6 @@ datum/controller/game_controller/proc/setup_objects()
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
T.broadcast_status()
// Create the mining ore distribution map.
// These values determine the specific area that the map is applied to.
// If you do not use the official Baycode asteroid map, you will need to change them.
asteroid_ore_map = new /datum/random_map/ore(null,13,32,5,217,223)
// Set up antagonists.
populate_antag_type_list()

View File

@@ -19,7 +19,7 @@ var/global/datum/shuttle_controller/shuttle_controller
var/datum/shuttle/shuttle = shuttles[shuttle_tag]
shuttle.init_docking_controllers()
shuttle.dock() //makes all shuttles docked to something at round start go into the docked state
for(var/obj/machinery/embedded_controller/C in machines)
if(istype(C.program, /datum/computer/file/embedded_program/docking))
C.program.tag = null //clear the tags, 'cause we don't need 'em anymore
@@ -210,7 +210,7 @@ var/global/datum/shuttle_controller/shuttle_controller
"Fore Port Solars" = locate(/area/skipjack_station/northwest_solars),
"Aft Starboard Solars" = locate(/area/skipjack_station/southeast_solars),
"Aft Port Solars" = locate(/area/skipjack_station/southwest_solars),
"Mining asteroid" = locate(/area/skipjack_station/mining)
"Mining Station" = locate(/area/skipjack_station/mining)
)
VS.announcer = "NSV Icarus"
@@ -234,10 +234,10 @@ var/global/datum/shuttle_controller/shuttle_controller
"South of the station" = locate(/area/syndicate_station/south),
"Southeast of the station" = locate(/area/syndicate_station/southeast),
"Telecomms Satellite" = locate(/area/syndicate_station/commssat),
"Mining Asteroid" = locate(/area/syndicate_station/mining),
"Mining Station" = locate(/area/syndicate_station/mining),
"Arrivals dock" = locate(/area/syndicate_station/arrivals_dock),
)
MS.docking_controller_tag = "merc_shuttle"
MS.destination_dock_targets = list(
"Mercenary Base" = "merc_base",

View File

@@ -1,36 +1,6 @@
//TODO: rewrite and standardise all controller datums to the datum/controller type
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done
/client/proc/print_random_map()
set category = "Debug"
set name = "Display Random Map"
set desc = "Show the contents of a random map."
if(!holder) return
var/datum/random_map/choice = input("Choose a map to debug.") as null|anything in random_maps
if(!choice)
return
choice.display_map(usr)
/client/proc/create_random_map()
set category = "Debug"
set name = "Create Random Map"
set desc = "Create a random map."
if(!holder) return
var/map_datum = input("Choose a map to create.") as null|anything in typesof(/datum/random_map)-/datum/random_map
if(!map_datum)
return
var/seed = input("Seed? (default null)") as text|null
var/tx = input("X? (default 1)") as text|null
var/ty = input("Y? (default 1)") as text|null
var/tz = input("Z? (default 1)") as text|null
new map_datum(seed,tx,ty,tz)
/client/proc/restart_controller(controller in list("Master","Failsafe","Lighting","Supply"))
/client/proc/restart_controller(controller in list("Supply"))
set category = "Debug"
set name = "Restart Controller"
set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
@@ -39,13 +9,6 @@
usr = null
src = null
switch(controller)
if("Failsafe")
new /datum/controller/failsafe()
feedback_add_details("admin_verb","RFailsafe")
if("Lighting")
new /datum/controller/lighting()
lighting_controller.process()
feedback_add_details("admin_verb","RLighting")
if("Supply")
supply_controller.process()
feedback_add_details("admin_verb","RSupply")
@@ -62,7 +25,7 @@
usr.client.debug_variables(antag)
message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.")
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Ticker Process","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano"))
/client/proc/debug_controller(controller in list("Master","Ticker","Ticker Process","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano","Chemistry"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
@@ -72,18 +35,12 @@
if("Master")
debug_variables(master_controller)
feedback_add_details("admin_verb","DMC")
if("Failsafe")
debug_variables(Failsafe)
feedback_add_details("admin_verb","DFailsafe")
if("Ticker")
debug_variables(ticker)
feedback_add_details("admin_verb","DTicker")
if("Ticker Process")
debug_variables(tickerProcess)
feedback_add_details("admin_verb","DTickerProcess")
if("Lighting")
debug_variables(lighting_controller)
feedback_add_details("admin_verb","DLighting")
if("Air")
debug_variables(air_master)
feedback_add_details("admin_verb","DAir")
@@ -132,5 +89,8 @@
if("Nano")
debug_variables(nanomanager)
feedback_add_details("admin_verb", "DNano")
if("Chemistry")
debug_variables(chemistryProcess)
feedback_add_details("admin_verb", "DChem")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return

View File

@@ -170,8 +170,8 @@ datum/controller/vote
additional_antag_types |= antag_names_to_ids[.]
if(mode == "gamemode") //fire this even if the vote fails.
if(!going)
going = 1
if(!round_progressing)
round_progressing = 1
world << "<font color='red'><b>The round will start soon.</b></font>"
if(restart)
@@ -257,7 +257,7 @@ datum/controller/vote
text += "\n[question]"
log_vote(text)
world << "<font color='purple'><b>[text]</b>\nType vote to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
world << "<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
switch(vote_type)
if("crew_transfer")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
@@ -265,8 +265,8 @@ datum/controller/vote
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("custom")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if(mode == "gamemode" && going)
going = 0
if(mode == "gamemode" && round_progressing)
round_progressing = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"
time_remaining = round(config.vote_period/10)
@@ -336,7 +336,7 @@ datum/controller/vote
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//extra antagonists
if(trialmin || (!antag_add_failed && config.allow_extra_antags))
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
@@ -375,7 +375,7 @@ datum/controller/vote
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if("add_antagonist")
if(config.allow_extra_antags || usr.client.holder)
if(config.allow_extra_antags)
initiate_vote("add_antagonist",usr.key)
if("custom")
if(usr.client.holder)

View File

@@ -2,10 +2,8 @@
data_core = new /obj/effect/datacore()
return 1
/obj/effect/datacore/proc/manifest(var/nosleep = 0)
/obj/effect/datacore/proc/manifest()
spawn()
if(!nosleep)
sleep(40)
for(var/mob/living/carbon/human/H in player_list)
manifest_inject(H)
return
@@ -140,160 +138,9 @@
proc/get_id_photo(var/mob/living/carbon/human/H)
var/icon/preview_icon = null
var/g = "m"
if (H.gender == FEMALE)
g = "f"
var/icon/icobase = H.species.icobase
preview_icon = new /icon(icobase, "torso_[g]")
var/icon/temp
temp = new /icon(icobase, "groin_[g]")
preview_icon.Blend(temp, ICON_OVERLAY)
temp = new /icon(icobase, "head_[g]")
preview_icon.Blend(temp, ICON_OVERLAY)
for(var/obj/item/organ/external/E in H.organs)
preview_icon.Blend(E.get_icon(), ICON_OVERLAY)
//Tail
if(H.species.tail)
temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[H.species.tail]_s")
preview_icon.Blend(temp, ICON_OVERLAY)
// Skin tone
if(H.species.flags & HAS_SKIN_TONE)
if (H.s_tone >= 0)
preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD)
else
preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT)
// Skin color
if(H.species.flags & HAS_SKIN_TONE)
if(!H.species || H.species.flags & HAS_SKIN_COLOR)
preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD)
var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s")
if (H.species.flags & HAS_EYE_COLOR)
eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD)
var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style]
if(hair_style)
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD)
eyes_s.Blend(hair_s, ICON_OVERLAY)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style]
if(facial_hair_style)
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD)
eyes_s.Blend(facial_s, ICON_OVERLAY)
var/icon/clothes_s = null
switch(H.mind.assigned_role)
if("Head of Personnel")
clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Bartender")
clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Gardener")
clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Chef")
clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Janitor")
clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Librarian")
clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Quartermaster")
clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Cargo Technician")
clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Shaft Miner")
clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Lawyer")
clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Chaplain")
clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Research Director")
clothes_s = new /icon('icons/mob/uniform.dmi', "director_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Scientist")
clothes_s = new /icon('icons/mob/uniform.dmi', "sciencewhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY)
if("Chemist")
clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY)
if("Chief Medical Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY)
if("Medical Doctor")
clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Geneticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY)
if("Virologist")
clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY)
if("Captain")
clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Head of Security")
clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Warden")
clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Detective")
clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY)
if("Security Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Chief Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Station Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Atmospheric Technician")
clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Roboticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
else
clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
preview_icon.Blend(eyes_s, ICON_OVERLAY)
if(clothes_s)
preview_icon.Blend(clothes_s, ICON_OVERLAY)
qdel(eyes_s)
qdel(clothes_s)
H.regenerate_icons()
var/icon/preview_icon = icon(H.icon)
for(var/image/I in H.overlays_standing)
if(I && I.icon)
preview_icon.Blend(icon(I.icon, I.icon_state), ICON_OVERLAY)
return preview_icon

View File

@@ -9,7 +9,7 @@ client
if(!usr.client || !usr.client.holder)
usr << "\red You need to be an administrator to access this."
usr << "<span class='warning'>You need to be an administrator to access this.</span>"
return
@@ -602,8 +602,8 @@ client
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)")
message_admins("<span class='notice'>[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)</span>")
if("Type and subtypes")
var/i = 0
for(var/obj/Obj in world)
@@ -613,8 +613,8 @@ client
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)")
message_admins("<span class='notice'>[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)</span>")
else if(href_list["explode"])
if(!check_rights(R_DEBUG|R_FUN)) return
@@ -941,8 +941,8 @@ client
return
if(amount != 0)
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ")
message_admins("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [L] ")
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]")
message_admins("<span class='notice'>[key_name(usr)] dealt [amount] amount of [Text] damage to [L]</span>")
href_list["datumrefresh"] = href_list["mobToDamage"]
if(href_list["datumrefresh"])

View File

@@ -53,14 +53,15 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
// if hidden[2] is true, then virus is hidden from PANDEMIC machine
/datum/disease/proc/stage_act()
// Some species are immune to viruses entirely.
if(affected_mob && istype(affected_mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = affected_mob
if(H.species.virus_immune)
cure()
return
age++
var/cure_present = has_cure()
//world << "[cure_present]"
if(carrier&&!cure_present)
//world << "[affected_mob] is carrier"
return
spread = (cure_present?"Remissive":initial_spread)
if(stage > max_stages)
stage = max_stages
@@ -126,7 +127,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
source = affected_mob
else //no source and no mob affected. Rogue disease. Break
return
if(affected_mob.reagents != null)
if(affected_mob)
if(affected_mob.reagents.has_reagent("spaceacillin"))

View File

@@ -53,25 +53,25 @@
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
affected_mob << "<span class='warning'>Your throat feels sore.</span>"
if(prob(1))
affected_mob << "\red Mucous runs down the back of your throat."
affected_mob << "<span class='warning'>Mucous runs down the back of your throat.</span>"
if(4)
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(2))
affected_mob << "\red Your muscles ache."
affected_mob << "<span class='warning'>Your muscles ache.</span>"
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(2))
affected_mob << "\red Your stomach hurts."
affected_mob << "<span class='warning>Your stomach hurts.</span>"
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
if(5)
affected_mob << "\red You feel something tearing its way out of your stomach..."
affected_mob << "<span class='danger'>You feel something tearing its way out of your stomach...</span>"
affected_mob.adjustToxLoss(10)
affected_mob.updatehealth()
if(prob(50))

View File

@@ -24,11 +24,11 @@
if(stage == 1)
if(prob(5))
affected_mob << "\red You feel a stinging pain in your abdomen!"
affected_mob << "<span class='warning'>You feel a stinging pain in your abdomen!</span>"
affected_mob.emote("me",1,"winces slightly.")
if(stage > 1)
if(prob(3))
affected_mob << "\red You feel a stabbing pain in your abdomen!"
affected_mob << "<span class='warning'>You feel a stabbing pain in your abdomen!</span>"
affected_mob.emote("me",1,"winces painfully.")
affected_mob.adjustToxLoss(1)
if(stage > 2)
@@ -37,13 +37,13 @@
var/mob/living/carbon/human/H = affected_mob
H.vomit()
else
affected_mob << "\red You gag as you want to throw up, but there's nothing in your stomach!"
affected_mob << "<span class='danger'>You gag as you want to throw up, but there's nothing in your stomach!</span>"
affected_mob.Weaken(10)
affected_mob.adjustToxLoss(3)
if(stage > 3)
if(prob(1) && ishuman(affected_mob))
var/mob/living/carbon/human/H = affected_mob
H << "\red Your abdomen is a world of pain!"
H << "<span class='danger'>Your abdomen is a world of pain!</span>"
H.Weaken(10)
var/obj/item/organ/external/groin = H.get_organ("groin")

View File

@@ -14,12 +14,12 @@
switch(stage)
if(1)
if(prob(2))
affected_mob << "\red You feel like something is moving inside of you"
affected_mob << "<span class='warning'>You feel like something is moving inside of you!</span>"
if(2) //also changes say, see say.dm
if(prob(2))
affected_mob << "\red You feel like something is moving inside of you"
affected_mob << "<span class='warning'>You feel like something is moving inside of you!</span>"
if(prob(2))
affected_mob << "\red BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
affected_mob << "<span class='danger'>BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ</span>"
if(3)
//Should give the bee spit verb
if(4)
@@ -28,4 +28,4 @@
//Plus if you die, you explode into bees
return
*/
//Started working on it, but am too lazy to finish it today -- Urist
//Started working on it, but am too lazy to finish it today -- Urist

View File

@@ -21,7 +21,7 @@
if(prob(2))
affected_mob.emote("yawn")
if(prob(2))
affected_mob << "\red Your don't feel like yourself."
affected_mob << "<span class='warning'>Your don't feel like yourself.</span>"
if(prob(5))
affected_mob.adjustBrainLoss(1)
affected_mob.updatehealth()
@@ -34,12 +34,12 @@
affected_mob.adjustBrainLoss(2)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "\red Your try to remember something important...but can't."
affected_mob << "<span class='warning'>You try to remember something important...but can't.</span>"
/* if(prob(10))
affected_mob.adjustToxLoss(3)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "\red Your head hurts." */
affected_mob << "<span class='warning'>Your head hurts.</span>" */
if(4)
if(prob(2))
affected_mob.emote("stare")
@@ -49,14 +49,14 @@
affected_mob.adjustToxLoss(4)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "\red Your head hurts." */
affected_mob << "<span class='notice>Your head hurts.</span>" */
if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now
affected_mob.adjustBrainLoss(3)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "\red Strange buzzing fills your head, removing all thoughts."
affected_mob << "<span class='warning'>A strange buzzing fills your head, removing all thoughts.</span>"
if(prob(3))
affected_mob << "\red You lose consciousness..."
affected_mob << "<span class='warning'>You lose consciousness...</span>"
for(var/mob/O in viewers(affected_mob, null))
O.show_message("[affected_mob] suddenly collapses", 1)
affected_mob.Paralyse(rand(5,10))
@@ -64,4 +64,4 @@
affected_mob.emote("snore")
if(prob(15))
affected_mob.stuttering += 3
return
return

View File

@@ -16,16 +16,16 @@
if(2)
/*
if(affected_mob.sleeping && prob(40)) //removed until sleeping is fixed
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
*/
if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1) && prob(5))
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1))
@@ -33,22 +33,22 @@
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
affected_mob << "<span class='warning'>Your throat feels sore.</span>"
if(prob(1))
affected_mob << "\red Mucous runs down the back of your throat."
affected_mob << "<span class='warning'>Mucous runs down the back of your throat.</span>"
if(3)
/*
if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
*/
if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1) && prob(1))
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1))
@@ -56,11 +56,11 @@
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
affected_mob << "<span class='warning'>Your throat feels sore.</span>"
if(prob(1))
affected_mob << "\red Mucous runs down the back of your throat."
affected_mob << "<span class='warning'>Mucous runs down the back of your throat.</span>"
if(prob(1) && prob(50))
if(!affected_mob.resistances.Find(/datum/disease/flu))
var/datum/disease/Flu = new /datum/disease/flu(0)
affected_mob.contract_disease(Flu,1)
cure()
cure()

View File

@@ -16,7 +16,7 @@
if(2)
affected_mob.bodytemperature -= 10
if(prob(1) && prob(10))
affected_mob << "\blue You feel better."
affected_mob << "<span class='notice>You feel better.</span>"
cure()
return
if(prob(1))
@@ -24,9 +24,9 @@
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
affected_mob << "<span class='warning'>Your throat feels sore.</span>"
if(prob(5))
affected_mob << "\red You feel stiff."
affected_mob << "<span class='warning'>You feel stiff.</span>"
if(3)
affected_mob.bodytemperature -= 20
if(prob(1))
@@ -34,6 +34,6 @@
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
affected_mob << "<span class='warning'>Your throat feels sore.</span>"
if(prob(10))
affected_mob << "\red You feel stiff."
affected_mob << "<span class='warning'>You feel stiff.</span>"

View File

@@ -23,11 +23,11 @@
if(prob(8))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your muscles ache."
affected_mob << "<span class='warning'>Your muscles ache.</span>"
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(1))
affected_mob << "\red Your stomach hurts."
affected_mob << "<span class='warning'>Your stomach hurts.</span>"
if(prob(20))
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
@@ -42,7 +42,7 @@
src.original_dna["UI"] = affected_mob.dna.UI.Copy()
src.original_dna["SE"] = affected_mob.dna.SE.Copy()
affected_mob << "\red You don't feel like yourself.."
affected_mob << "<span class='warning'>You don't feel like yourself..</span>"
var/list/newUI=strain_data["UI"]
var/list/newSE=strain_data["SE"]
affected_mob.UpdateAppearance(newUI.Copy())
@@ -65,5 +65,5 @@
affected_mob.dna.UpdateSE()
affected_mob.real_name = original_dna["name"]
affected_mob << "\blue You feel more like yourself."
..()
affected_mob << "<span class='notice'>You feel more like yourself.</span>"
..()

View File

@@ -22,7 +22,7 @@
else if(prob(5))
affected_mob.emote("gasp")
if(prob(10))
affected_mob << "\red You're starting to feel very weak..."
affected_mob << "<span class='warning'>You're starting to feel very weak...</span>"
if(4)
if(prob(10))
affected_mob.emote("cough")

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