diff --git a/.gitignore b/.gitignore index aa2528a7fe9..f2ce0fe4b80 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ *.lk *.backup data/ +cfg/ diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm index 5ea54e7a56d..d4de419ad0f 100644 --- a/code/ATMOSPHERICS/_atmospherics_helpers.dm +++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm @@ -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) diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 7237cccbca3..9ae50b11af8 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -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) diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 7604f330639..00a8abe50ab 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -168,7 +168,7 @@ return src.add_fingerprint(usr) if(!src.allowed(user)) - user << "\red Access denied." + user << "Access denied." 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 << "You cannot unwrench \the [src], turn it off first." 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 << "You cannot unwrench \the [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ "You hear ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm index aead60a3827..0eb342479d5 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm @@ -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 << "You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor." 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 << "You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor." updateConnection() else ..() @@ -286,4 +286,4 @@ if (usr.stat || usr.restrained() || anchored) return - src.set_dir(turn(src.dir, 90)) \ No newline at end of file + src.set_dir(turn(src.dir, 90)) diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index 079dfb76cd0..16f5c0a586d 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -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 << "Access denied." 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 << "You cannot unwrench this [src], turn it off first." 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 << "You cannot unwrench this [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ "You hear ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm index 52ab44fa74e..17d47ea8cfa 100644 --- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm +++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm @@ -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 << "You cannot unwrench [src], it is too exerted due to internal pressure." + user << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." 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].", \ + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) @@ -299,4 +299,4 @@ update_ports() - return null \ No newline at end of file + return null diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm index c33ff799673..4f6473fccf3 100644 --- a/code/ATMOSPHERICS/components/portables_connector.dm +++ b/code/ATMOSPHERICS/components/portables_connector.dm @@ -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 << "You cannot unwrench \the [src], dettach \the [connected_device] first." 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 << "You cannot unwrench \the [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 0921d1d0aa5..0a055825a48 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -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 << "You cannot unwrench \the [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "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 << "Access denied." return var/dat diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index a200de25a00..a163c122f01 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -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 << "You cannot unwrench \the [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ "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 << "Access denied." return usr.set_machine(src) var/dat = {"Power: [use_power?"On":"Off"]
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm index 42556232bdd..963a4f5009c 100644 --- a/code/ATMOSPHERICS/components/tvalve.dm +++ b/code/ATMOSPHERICS/components/tvalve.dm @@ -308,7 +308,7 @@ if(!powered()) return if(!src.allowed(user)) - user << "\red Access denied." + user << "Access denied." 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 << "You cannot unwrench \the [src], it's too complicated." 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 << "You cannot unwrench \the [src], it too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "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 << "Access denied." return ..() @@ -482,4 +482,4 @@ if(state) go_straight() else - go_to_side() \ No newline at end of file + go_to_side() diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm index 0e75146adc4..ded9948cb2d 100644 --- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm +++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm @@ -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 << "You must remove the plating first." 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 << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 1920b8c6af2..8bc836497b8 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -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 << "Now welding the vent." 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("\The [user] welds the vent shut.", "You weld the vent shut.", "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("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.") welded = 0 update_icon() else - user << "\blue The welding tool needs to be on to start this task." + user << "The welding tool needs to be on to start this task." else - user << "\blue You need more welding fuel to complete this task." + user << "You need more welding fuel to complete this task." 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 << "You cannot unwrench \the [src], turn it off first." 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 << "You must remove the plating first." 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 << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index e5b6d3a8dc1..cfe07ff6723 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -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 << "You cannot unwrench \the [src], turn it off first." 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 << "You must remove the plating first." 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 << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm index 49ae4af2cf2..6e43afd78e1 100644 --- a/code/ATMOSPHERICS/components/valve.dm +++ b/code/ATMOSPHERICS/components/valve.dm @@ -241,7 +241,7 @@ if(!powered()) return if(!src.allowed(user)) - user << "\red Access denied." + user << "Access denied." 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 << "You cannot unwrench \the [src], it's too complicated." 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 << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "You begin to unfasten \the [src]..." if (do_after(user, 40)) user.visible_message( \ - "[user] unfastens \the [src].", \ - "\blue You have unfastened \the [src].", \ - "You hear ratchet.") + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") new /obj/item/pipe(loc, make_from=src) qdel(src) diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm index a381b28c37f..54e23ea1a81 100644 --- a/code/ATMOSPHERICS/mainspipe.dm +++ b/code/ATMOSPHERICS/mainspipe.dm @@ -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 << "Access denied." return ..() @@ -704,4 +704,4 @@ obj/machinery/atmospherics/mains_pipe/valve close() else open() -*/ \ No newline at end of file +*/ diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index 2315e856fd1..2ff6c78f945 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -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 << "You must remove the plating first." 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 << "You cannot unwrench [src], it is too exerted due to internal pressure." + user << "You cannot unwrench \the [src], it is too exerted due to internal pressure." add_fingerprint(user) return 1 playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "\blue You begin to unfasten \the [src]..." + user << "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "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("\The [src] bursts!"); 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 << "\The [user] has used \the [W] on \the [src] \icon[src]" var/pressure = parent.air.return_pressure() var/total_moles = parent.air.total_moles - user << "\blue Results of analysis of \icon[icon]" + user << "Results of analysis of \the [src] \icon[src]" if (total_moles>0) - user << "\blue Pressure: [round(pressure,0.1)] kPa" + user << "Pressure: [round(pressure,0.1)] kPa" 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)]°C" + user << "[gas_data.name[g]]: [round((parent.air.gas[g] / total_moles) * 100)]%" + user << "Temperature: [round(parent.air.temperature-T0C)]°C" else - user << "\blue Tank is empty!" + user << "Tank is empty!" /obj/machinery/atmospherics/pipe/tank/air name = "Pressure Tank (Air)" diff --git a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm index 7374963fba8..7672d72fef3 100644 --- a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm +++ b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm @@ -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 << "ERROR: no gas_mixture associated with this tank" 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 << "[x],[y] has no parent air group." verb create_wall() @@ -329,7 +329,7 @@ obj/machinery/atmospherics set src in world set category = "Minor" - world << "\blue [x],[y]" + world << "[x],[y]" 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 << "@[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)?("BURNING"):(null)]"" 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 << "Fire Report" for(var/obj/effect/hotspot/flame in world) usr << "[flame.x],[flame.y]: [flame.temperature]K, [flame.volume] L - [flame.loc:air:temperature]" diff --git a/code/FEA/FEA_system.dm b/code/FEA/FEA_system.dm index 6a3dfe0f8b2..d25da913b87 100644 --- a/code/FEA/FEA_system.dm +++ b/code/FEA/FEA_system.dm @@ -146,7 +146,7 @@ datum setup() set background = 1 - world << "\red \b Processing Geometry..." + world << "Processing Geometry..." 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 << "Geometry processed in [(world.timeofday-start_time)/10] seconds!" assemble_group_turf(turf/simulated/base) diff --git a/code/TriDimension/Movement.dm b/code/TriDimension/Movement.dm index 5f451a1038d..3637184d31a 100644 --- a/code/TriDimension/Movement.dm +++ b/code/TriDimension/Movement.dm @@ -13,13 +13,13 @@ for(var/atom/A in T.contents) if(A.density) blocked = 1 - usr << "\red You bump into [A.name]." + usr << "You bump into \the [A]." break if(!blocked) usr.Move(T) usr << "You move upwards." else - usr << "\red There is something in your way." + usr << "There is something in your way." 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 << "You bump into \the [A]." break if(!blocked) usr.Move(T) usr << "You move downwards." else - usr << "\red You cant move through the floor." + usr << "You cant move through the floor." if (legal == 0) usr << "There is nothing of interest in this direction." return 1 diff --git a/code/TriDimension/Pipes.dm b/code/TriDimension/Pipes.dm index c71255a34bd..2958e2a4dcf 100644 --- a/code/TriDimension/Pipes.dm +++ b/code/TriDimension/Pipes.dm @@ -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("\The [src] bursts!"); 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) diff --git a/code/TriDimension/Structures.dm b/code/TriDimension/Structures.dm index 9224facba26..99151936f5f 100644 --- a/code/TriDimension/Structures.dm +++ b/code/TriDimension/Structures.dm @@ -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 << "You remove the ladder and close the hole." 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("\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.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("\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.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 \ No newline at end of file + return diff --git a/code/TriDimension/Turfs.dm b/code/TriDimension/Turfs.dm index 43e33ed3c28..164b95f0bfe 100644 --- a/code/TriDimension/Turfs.dm +++ b/code/TriDimension/Turfs.dm @@ -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 << "Constructing support lattice..." 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 << "The plating is going to need some support." return diff --git a/code/TriDimension/controller.dm b/code/TriDimension/controller.dm index a9d4df675ab..c8b81d0d499 100644 --- a/code/TriDimension/controller.dm +++ b/code/TriDimension/controller.dm @@ -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) diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 62a6daea16f..9f6451adf93 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -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 << "You are sucked away by airflow!" 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 << "You are pushed away by airflow!" 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 \The [src] slams into \a [A]!",1,"\red You hear a loud slam!",2) + M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",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 \The [src] slams into \a [A]!",1,"\red You hear a loud slam!",2) + M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",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 [src] slams into [A]!",1,"\red You hear a loud slam!",2) +// M.show_message("[src] slams into [A]!",1,"You hear a loud slam!",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 \ No newline at end of file + . += A diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm index 83d2a54ec3c..506657df12e 100644 --- a/code/ZAS/Controller.dm +++ b/code/ZAS/Controller.dm @@ -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 << "[tick_progress]" . = 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) \ No newline at end of file + if(!E.sleeping) active_edges.Remove(E) diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm index 1d4cc1a3883..ed94b7d5825 100644 --- a/code/ZAS/Diagnostic.dm +++ b/code/ZAS/Diagnostic.dm @@ -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 << "Zone Air Contents" - 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 << "Connections: [length(connections)]" - - 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) \ No newline at end of file + vsc.SetDefault(mob) diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 688f71985d4..27011dc7b33 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -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) diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index 391f5b719a9..0e74052c2a1 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -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 << "Your skin burns!" 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 << "High levels of toxins cause you to spontaneously mutate!" 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 << "Your eyes burn!" 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 << "You are blinded!" eye_blind += 20 /mob/living/carbon/human/proc/pl_head_protected() diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm index 331c00dd37e..62cad5e469c 100644 --- a/code/ZAS/Turf.dm +++ b/code/ZAS/Turf.dm @@ -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() diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm index c152159b7ac..674be3fc5ea 100644 --- a/code/ZAS/Variable Settings.dm +++ b/code/ZAS/Variable Settings.dm @@ -168,7 +168,7 @@ var/global/vs_control/vsc = new vars[ch] = vw if(how == "Toggle") newvar = (newvar?"ON":"OFF") - world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]." + world << "[key_name(user)] changed the setting [display_description] to [newvar]." 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 [key_name(user)] changed the global phoron/ZAS settings to \"[def]\"" + world << "[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"" /pl_control/var/list/settings = list() diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm new file mode 100644 index 00000000000..757c4347de5 --- /dev/null +++ b/code/__defines/admin.dm @@ -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. \ No newline at end of file diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm new file mode 100644 index 00000000000..53bbe67eddb --- /dev/null +++ b/code/__defines/atmos.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm new file mode 100644 index 00000000000..7091ea81d72 --- /dev/null +++ b/code/__defines/chemistry.dm @@ -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 diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm new file mode 100644 index 00000000000..6c2590f8409 --- /dev/null +++ b/code/__defines/damage_organs.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/dna.dm b/code/__defines/dna.dm new file mode 100644 index 00000000000..2e1e9da0ccd --- /dev/null +++ b/code/__defines/dna.dm @@ -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 diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm new file mode 100644 index 00000000000..936d80890d7 --- /dev/null +++ b/code/__defines/gamemode.dm @@ -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" \ No newline at end of file diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm new file mode 100644 index 00000000000..7a461cedf6c --- /dev/null +++ b/code/__defines/items_clothing.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm new file mode 100644 index 00000000000..978d88fd956 --- /dev/null +++ b/code/__defines/machinery.dm @@ -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. \ No newline at end of file diff --git a/code/__defines/math_physics.dm b/code/__defines/math_physics.dm new file mode 100644 index 00000000000..7c7c6d0d85b --- /dev/null +++ b/code/__defines/math_physics.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm new file mode 100644 index 00000000000..f2a96d460da --- /dev/null +++ b/code/__defines/misc.dm @@ -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) \ No newline at end of file diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm new file mode 100644 index 00000000000..76bce19e1fb --- /dev/null +++ b/code/__defines/mobs.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/research.dm b/code/__defines/research.dm new file mode 100644 index 00000000000..87e6bb5f422 --- /dev/null +++ b/code/__defines/research.dm @@ -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 \ No newline at end of file diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm new file mode 100644 index 00000000000..3f351989bdc --- /dev/null +++ b/code/__defines/species_languages.dm @@ -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 \ No newline at end of file diff --git a/code/__HELPERS/datum_pool.dm b/code/_helpers/datum_pool.dm similarity index 91% rename from code/__HELPERS/datum_pool.dm rename to code/_helpers/datum_pool.dm index 79970faf7b6..5c13c0d8ba2 100644 --- a/code/__HELPERS/datum_pool.dm +++ b/code/_helpers/datum_pool.dm @@ -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]) diff --git a/code/__HELPERS/files.dm b/code/_helpers/files.dm similarity index 100% rename from code/__HELPERS/files.dm rename to code/_helpers/files.dm diff --git a/code/__HELPERS/game.dm b/code/_helpers/game.dm similarity index 83% rename from code/__HELPERS/game.dm rename to code/_helpers/game.dm index 36282290db8..9aa16f91b5a 100644 --- a/code/__HELPERS/game.dm +++ b/code/_helpers/game.dm @@ -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=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 diff --git a/code/__HELPERS/global_lists.dm b/code/_helpers/global_lists.dm similarity index 94% rename from code/__HELPERS/global_lists.dm rename to code/_helpers/global_lists.dm index 7484d016b6c..09e6f845c86 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -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] diff --git a/code/__HELPERS/icons.dm b/code/_helpers/icons.dm similarity index 100% rename from code/__HELPERS/icons.dm rename to code/_helpers/icons.dm diff --git a/code/__HELPERS/lists.dm b/code/_helpers/lists.dm similarity index 94% rename from code/__HELPERS/lists.dm rename to code/_helpers/lists.dm index a289fff3f1f..298d187ef09 100644 --- a/code/__HELPERS/lists.dm +++ b/code/_helpers/lists.dm @@ -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; iHas been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") if(admin) log_attack("[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]") + +//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) diff --git a/code/__HELPERS/names.dm b/code/_helpers/names.dm similarity index 97% rename from code/__HELPERS/names.dm rename to code/_helpers/names.dm index e43ca1dc2a9..83383ea56ac 100644 --- a/code/__HELPERS/names.dm +++ b/code/_helpers/names.dm @@ -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 << "Code Phrase is: [generate_code_phrase()]" return diff --git a/code/__HELPERS/sanitize_values.dm b/code/_helpers/sanitize_values.dm similarity index 100% rename from code/__HELPERS/sanitize_values.dm rename to code/_helpers/sanitize_values.dm diff --git a/code/__HELPERS/text.dm b/code/_helpers/text.dm similarity index 95% rename from code/__HELPERS/text.dm rename to code/_helpers/text.dm index ae38249956a..0051a1a9de4 100644 --- a/code/__HELPERS/text.dm +++ b/code/_helpers/text.dm @@ -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 "[tagdesc]" \ No newline at end of file + return "[tagdesc]" diff --git a/code/__HELPERS/time.dm b/code/_helpers/time.dm similarity index 100% rename from code/__HELPERS/time.dm rename to code/_helpers/time.dm diff --git a/code/__HELPERS/turfs.dm b/code/_helpers/turfs.dm similarity index 87% rename from code/__HELPERS/turfs.dm rename to code/_helpers/turfs.dm index b9b4225a414..3ee4e26a7a8 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/_helpers/turfs.dm @@ -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 diff --git a/code/__HELPERS/type2type.dm b/code/_helpers/type2type.dm similarity index 85% rename from code/__HELPERS/type2type.dm rename to code/_helpers/type2type.dm index 478700d5f82..216a45ee1c3 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/_helpers/type2type.dm @@ -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)) diff --git a/code/__HELPERS/unsorted.dm b/code/_helpers/unsorted.dm similarity index 95% rename from code/__HELPERS/unsorted.dm rename to code/_helpers/unsorted.dm index 3564c5e15fc..29d55e629fa 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -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) diff --git a/code/__HELPERS/vector.dm b/code/_helpers/vector.dm similarity index 100% rename from code/__HELPERS/vector.dm rename to code/_helpers/vector.dm diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index b8caa45399d..5a56b34e617 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -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 << "You're out of energy! You need food!" // 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) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 900e89e7e75..1486e546481 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -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" diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm new file mode 100644 index 00000000000..9781e9c236d --- /dev/null +++ b/code/_onclick/hud/action.dm @@ -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 \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index f39499f3dce..9d877bb41ac 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -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 << "This mob type does not use a HUD." return if(!ishuman(src)) - usr << "\red Inventory hiding is currently only supported for human mobs, sorry." + usr << "Inventory hiding is currently only supported for human mobs, sorry." 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() \ No newline at end of file + update_action_buttons() diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 97b07e6154d..2e894acdd6d 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -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" diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm new file mode 100644 index 00000000000..5034606256a --- /dev/null +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -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 \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 4a7d6f2acbe..f0cc69fcda4 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -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" diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 1d68fb54e8e..d3c3df942e3 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -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()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - 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()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + 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) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 168ae47c863..abc0e6114ed 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -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 << "You will now examine everything you click on." else - src << "\blue You will no longer examine things you click on." + src << "You will no longer examine things you click on." /mob/dead/observer/DblClickOn(var/atom/A, var/params) if(client.buildmode) diff --git a/code/_onclick/oldcode.dm b/code/_onclick/oldcode.dm index 890d67923ab..e3f417d59ac 100644 --- a/code/_onclick/oldcode.dm +++ b/code/_onclick/oldcode.dm @@ -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 diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 477fb04b7ad..179a470fc6b 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -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 diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm new file mode 100644 index 00000000000..ad9346ec15f --- /dev/null +++ b/code/_onclick/rig.dm @@ -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 diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index ae57895cd6a..0ba005455c6 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -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 << "Your mind won't reach that far." return if(!focus) diff --git a/code/controllers/Processes/chemistry.dm b/code/controllers/Processes/chemistry.dm new file mode 100644 index 00000000000..169bd15ee5e --- /dev/null +++ b/code/controllers/Processes/chemistry.dm @@ -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 diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm index 29b9755a5cc..ade159f1ac6 100644 --- a/code/controllers/Processes/garbage.dm +++ b/code/controllers/Processes/garbage.dm @@ -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() diff --git a/code/controllers/Processes/inactivity.dm b/code/controllers/Processes/inactivity.dm index d9f9206749b..cd01e24829a 100644 --- a/code/controllers/Processes/inactivity.dm +++ b/code/controllers/Processes/inactivity.dm @@ -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 << "You have been inactive for more than 10 minutes and have been disconnected." + C << "You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected." del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients. - scheck() - -#undef INACTIVITY_KICK diff --git a/code/controllers/Processes/machinery.dm b/code/controllers/Processes/machinery.dm index 232ef919734..b84dfaf9435 100644 --- a/code/controllers/Processes/machinery.dm +++ b/code/controllers/Processes/machinery.dm @@ -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])" \ No newline at end of file + return ..()+"([machines.len])" diff --git a/code/controllers/Processes/powernet.dm b/code/controllers/Processes/powernet.dm deleted file mode 100644 index 4a85ea41506..00000000000 --- a/code/controllers/Processes/powernet.dm +++ /dev/null @@ -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])" diff --git a/code/controllers/Processes/turf.dm b/code/controllers/Processes/turf.dm index c1efac52f97..2ac33f48ba7 100644 --- a/code/controllers/Processes/turf.dm +++ b/code/controllers/Processes/turf.dm @@ -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])" diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm deleted file mode 100644 index 6d3fd406dd6..00000000000 --- a/code/controllers/_DynamicAreaLighting_TG.dm +++ /dev/null @@ -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 \ No newline at end of file diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm index 9e82c55d053..723d2e001a1 100644 --- a/code/controllers/communications.dm +++ b/code/controllers/communications.dm @@ -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 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index e271bc57909..cc51b852b8b 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -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") diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index ee506c0d27f..6e379540873 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -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) diff --git a/code/controllers/lighting_controller.dm b/code/controllers/lighting_controller.dm deleted file mode 100644 index 8510af6714f..00000000000 --- a/code/controllers/lighting_controller.dm +++ /dev/null @@ -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 diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index d698454cab9..002c30b0eb0 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -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() diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 489d6488650..d53219fcf98 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -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", diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index d827a3a65e7..c394318c286 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -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 diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 7db31c6fa63..469df7305a0 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -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 << "The round will start soon." if(restart) @@ -257,7 +257,7 @@ datum/controller/vote text += "\n[question]" log_vote(text) - world << "[text]\nType vote to place your votes.\nYou have [config.vote_period/10] seconds to vote." + world << "[text]\nType vote or click here to place your votes.\nYou have [config.vote_period/10] seconds to vote." 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 << "Round start has been delayed." time_remaining = round(config.vote_period/10) @@ -336,7 +336,7 @@ datum/controller/vote . += "\t([config.allow_vote_mode?"Allowed":"Disallowed"])" . += "
  • " //extra antagonists - if(trialmin || (!antag_add_failed && config.allow_extra_antags)) + if(!antag_add_failed && config.allow_extra_antags) . += "Add Antagonist Type" else . += "Restart (Disallowed)" @@ -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) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 351ec9a845a..8bc6cc0580c 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -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 diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 914b56ee604..7e9fc0cd04e 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -9,7 +9,7 @@ client if(!usr.client || !usr.client.holder) - usr << "\red You need to be an administrator to access this." + usr << "You need to be an administrator to access this." 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("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)") 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("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)") 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("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]") href_list["datumrefresh"] = href_list["mobToDamage"] if(href_list["datumrefresh"]) diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 398dc73bbbc..606acdef99e 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -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")) diff --git a/code/datums/diseases/alien_embryo.dm b/code/datums/diseases/alien_embryo.dm index 59d1dbe1605..488d43efa3e 100644 --- a/code/datums/diseases/alien_embryo.dm +++ b/code/datums/diseases/alien_embryo.dm @@ -53,25 +53,25 @@ if(prob(1)) affected_mob.emote("cough") if(prob(1)) - affected_mob << "\red Your throat feels sore." + affected_mob << "Your throat feels sore." if(prob(1)) - affected_mob << "\red Mucous runs down the back of your throat." + affected_mob << "Mucous runs down the back of your throat." 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 << "Your muscles ache." if(prob(20)) affected_mob.take_organ_damage(1) if(prob(2)) - affected_mob << "\red Your stomach hurts." + affected_mob << "You feel something tearing its way out of your stomach..." affected_mob.adjustToxLoss(10) affected_mob.updatehealth() if(prob(50)) diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index 37a2adecb6f..b4f2b1a38ab 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -24,11 +24,11 @@ if(stage == 1) if(prob(5)) - affected_mob << "\red You feel a stinging pain in your abdomen!" + affected_mob << "You feel a stinging pain in your abdomen!" 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 << "You feel a stabbing pain in your abdomen!" 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 << "You gag as you want to throw up, but there's nothing in your stomach!" 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 << "Your abdomen is a world of pain!" H.Weaken(10) var/obj/item/organ/external/groin = H.get_organ("groin") diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index ec863a441eb..f55dec71a9f 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -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 << "You feel like something is moving inside of you!" 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 << "You feel like something is moving inside of you!" if(prob(2)) - affected_mob << "\red BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + affected_mob << "BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 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 \ No newline at end of file +//Started working on it, but am too lazy to finish it today -- Urist diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 55e5db82d6b..c4784f51991 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -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 << "Your don't feel like yourself." 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 << "You try to remember something important...but can't." /* if(prob(10)) affected_mob.adjustToxLoss(3) affected_mob.updatehealth() if(prob(2)) - affected_mob << "\red Your head hurts." */ + affected_mob << "Your head hurts." */ 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 << "A strange buzzing fills your head, removing all thoughts." if(prob(3)) - affected_mob << "\red You lose consciousness..." + affected_mob << "You lose consciousness..." 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 \ No newline at end of file + return diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index 9317fa12ef6..5bbde80c2fa 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -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 << "You feel better." cure() return */ if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if(prob(1) && prob(5)) - affected_mob << "\blue You feel better." + affected_mob << "You feel better." 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 << "Your throat feels sore." if(prob(1)) - affected_mob << "\red Mucous runs down the back of your throat." + affected_mob << "Mucous runs down the back of your throat." if(3) /* if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return */ if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if(prob(1) && prob(1)) - affected_mob << "\blue You feel better." + affected_mob << "You feel better." 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 << "Your throat feels sore." if(prob(1)) - affected_mob << "\red Mucous runs down the back of your throat." + affected_mob << "Mucous runs down the back of your throat." 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() \ No newline at end of file + cure() diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index bea72ec36e7..86b88d5fcb0 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -16,7 +16,7 @@ if(2) affected_mob.bodytemperature -= 10 if(prob(1) && prob(10)) - affected_mob << "\blue You feel better." + affected_mob << "Your throat feels sore." if(prob(5)) - affected_mob << "\red You feel stiff." + affected_mob << "You feel stiff." 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 << "Your throat feels sore." if(prob(10)) - affected_mob << "\red You feel stiff." \ No newline at end of file + affected_mob << "You feel stiff." diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 6d520fe2948..6b79ea7505c 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -23,11 +23,11 @@ if(prob(8)) affected_mob.emote("cough") if(prob(1)) - affected_mob << "\red Your muscles ache." + affected_mob << "Your muscles ache." if(prob(20)) affected_mob.take_organ_damage(1) if(prob(1)) - affected_mob << "\red Your stomach hurts." + affected_mob << "Your stomach hurts." 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 << "You don't feel like yourself.." 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." - ..() \ No newline at end of file + affected_mob << "You feel more like yourself." + ..() diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index 2ef958bc04a..97e585fa0ce 100644 --- a/code/datums/diseases/fake_gbs.dm +++ b/code/datums/diseases/fake_gbs.dm @@ -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 << "You're starting to feel very weak..." if(4) if(prob(10)) affected_mob.emote("cough") diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index bb32b44e5b8..c050b9e1d1d 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -17,12 +17,12 @@ if(2) /* if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed --Blaank - affected_mob << "\blue You feel better." + affected_mob << "You feel better." stage-- return */ if(affected_mob.lying && prob(20)) //added until sleeping is fixed --Blaank - affected_mob << "\blue You feel better." + affected_mob << "You feel better." stage-- return if(prob(1)) @@ -30,11 +30,11 @@ if(prob(1)) affected_mob.emote("cough") if(prob(1)) - affected_mob << "\red Your muscles ache." + affected_mob << "Your muscles ache." if(prob(20)) affected_mob.take_organ_damage(1) if(prob(1)) - affected_mob << "\red Your stomach hurts." + affected_mob << "Your stomach hurts." if(prob(20)) affected_mob.adjustToxLoss(1) affected_mob.updatehealth() @@ -42,12 +42,12 @@ if(3) /* if(affected_mob.sleeping && prob(15)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." stage-- return */ if(affected_mob.lying && prob(15)) //added until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." stage-- return if(prob(1)) @@ -55,11 +55,11 @@ if(prob(1)) affected_mob.emote("cough") if(prob(1)) - affected_mob << "\red Your muscles ache." + affected_mob << "Your muscles ache." if(prob(20)) affected_mob.take_organ_damage(1) if(prob(1)) - affected_mob << "\red Your stomach hurts." + affected_mob << "Your stomach hurts." if(prob(20)) affected_mob.adjustToxLoss(1) affected_mob.updatehealth() diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index 8400d196b67..505cabfea06 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -21,7 +21,7 @@ if(prob(5)) affected_mob.emote("cough") if(prob(1)) - affected_mob << "\red You're burning in your own skin!" + affected_mob << "You're burning in your own skin!" affected_mob.take_organ_damage(0,5) if(3) @@ -31,6 +31,6 @@ if(prob(5)) affected_mob.emote("cough") if(prob(5)) - affected_mob << "\red You're burning in your own skin!" + affected_mob << "You're burning in your own skin!" affected_mob.take_organ_damage(0,5) return diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index ceddf45117f..8fc547bd213 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -26,15 +26,15 @@ else if(prob(5)) affected_mob.emote("gasp") if(prob(10)) - affected_mob << "\red You're starting to feel very weak..." + affected_mob << "You're starting to feel very weak..." if(4) if(prob(10)) affected_mob.emote("cough") affected_mob.adjustToxLoss(5) affected_mob.updatehealth() if(5) - affected_mob << "\red Your body feels as if it's trying to rip itself open..." + affected_mob << "Your body feels as if it's trying to rip itself open..." if(prob(50)) affected_mob.gib() else - return \ No newline at end of file + return diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index fb9fe042b83..94fa6ed4af1 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -16,7 +16,7 @@ switch(stage) if(2) if(prob(2)) - affected_mob << "\red You feel a slight shock course through your body." + affected_mob << "You feel a slight shock course through your body." if(prob(2)) for(var/obj/M in orange(2,affected_mob)) if(!M.anchored && (M.flags & CONDUCT)) @@ -36,9 +36,9 @@ */ if(3) if(prob(2)) - affected_mob << "\red You feel a strong shock course through your body." + affected_mob << "You feel a strong shock course through your body." if(prob(2)) - affected_mob << "\red You feel like clowning around." + affected_mob << "You feel like clowning around." if(prob(4)) for(var/obj/M in orange(4,affected_mob)) if(!M.anchored && (M.flags & CONDUCT)) @@ -64,9 +64,9 @@ */ if(4) if(prob(2)) - affected_mob << "\red You feel a powerful shock course through your body." + affected_mob << "You feel a powerful shock course through your body." if(prob(2)) - affected_mob << "\red You query upon the nature of miracles." + affected_mob << "You query upon the nature of miracles." if(prob(8)) for(var/obj/M in orange(6,affected_mob)) if(!M.anchored && (M.flags & CONDUCT)) @@ -90,4 +90,4 @@ else if(M.y < affected_mob.y) M.y+=rand(1,min(5,affected_mob.y-M.y)) */ - return \ No newline at end of file + return diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index 619e0f988af..32170cd4242 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -16,10 +16,10 @@ ..() switch(stage) if(1) - if(prob(10)) affected_mob << "\red You feel a little silly." + if(prob(10)) affected_mob << "You feel a little silly." if(2) - if(prob(10)) affected_mob << "\red You start seeing rainbows." + if(prob(10)) affected_mob << "You start seeing rainbows." if(3) - if(prob(10)) affected_mob << "\red Your thoughts are interrupted by a loud HONK!" + if(prob(10)) affected_mob << "Your thoughts are interrupted by a loud HONK!" if(4) - if(prob(5)) affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) \ No newline at end of file + if(prob(5)) affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 9ab69e217a8..27ddfe233f1 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -33,55 +33,55 @@ if(restcure) /* if(affected_mob.sleeping && prob(30)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return */ if(affected_mob.lying && prob(30)) //changed FROM prob(20) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if (prob(8)) - affected_mob << "\red Your head hurts." + affected_mob << "Your head hurts." if (prob(9)) - affected_mob << "You feel a tingling sensation in your chest." + affected_mob << "You feel a tingling sensation in your chest." if (prob(9)) - affected_mob << "\red You feel angry." + affected_mob << "You feel angry." if(2) if(restcure) /* if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return */ if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if (prob(8)) - affected_mob << "\red Your skin feels loose." + affected_mob << "Your skin feels loose." if (prob(10)) - affected_mob << "You feel very strange." + affected_mob << "You feel very strange." if (prob(4)) - affected_mob << "\red You feel a stabbing pain in your head!" + affected_mob << "You feel a stabbing pain in your head!" affected_mob.Paralyse(2) if (prob(4)) - affected_mob << "\red Your stomach churns." + affected_mob << "Your stomach churns." if(3) if(restcure) /* if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return */ if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if (prob(10)) - affected_mob << "\red Your entire body vibrates." + affected_mob << "Your entire body vibrates." if (prob(35)) if(prob(50)) @@ -93,16 +93,16 @@ if(restcure) /* if(affected_mob.sleeping && prob(10)) //removed until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return */ if(affected_mob.lying && prob(5)) //changed FROM prob(5) until sleeping is fixed - affected_mob << "\blue You feel better." + affected_mob << "You feel better." cure() return if (prob(60)) if(prob(50)) scramble(1, affected_mob, rand(50,75)) else - scramble(0, affected_mob, rand(50,75)) \ No newline at end of file + scramble(0, affected_mob, rand(50,75)) diff --git a/code/datums/diseases/rhumba_beat.dm b/code/datums/diseases/rhumba_beat.dm index 00bf74e7cd1..53a68011bfd 100644 --- a/code/datums/diseases/rhumba_beat.dm +++ b/code/datums/diseases/rhumba_beat.dm @@ -22,30 +22,30 @@ affected_mob.adjustToxLoss(5) affected_mob.updatehealth() if(prob(1)) - affected_mob << "\red You feel strange..." + affected_mob << "You feel strange..." if(3) if(affected_mob.ckey == "rosham") src.cure() if(prob(5)) - affected_mob << "\red You feel the urge to dance..." + affected_mob << "You feel the urge to dance..." else if(prob(5)) affected_mob.emote("gasp") else if(prob(10)) - affected_mob << "\red You feel the need to chick chicky boom..." + affected_mob << "You feel the need to chick chicky boom..." if(4) if(affected_mob.ckey == "rosham") src.cure() if(prob(10)) affected_mob.emote("gasp") - affected_mob << "\red You feel a burning beat inside..." + affected_mob << "You feel a burning beat inside..." if(prob(20)) affected_mob.adjustToxLoss(5) affected_mob.updatehealth() if(5) if(affected_mob.ckey == "rosham") src.cure() - affected_mob << "\red Your body is unable to contain the Rhumba Beat..." + affected_mob << "Your body is unable to contain the Rhumba Beat..." if(prob(50)) affected_mob.gib() else - return \ No newline at end of file + return diff --git a/code/datums/diseases/robotic_transformation.dm b/code/datums/diseases/robotic_transformation.dm index 9648191fb01..257ce666c1c 100644 --- a/code/datums/diseases/robotic_transformation.dm +++ b/code/datums/diseases/robotic_transformation.dm @@ -19,36 +19,36 @@ switch(stage) if(2) if (prob(8)) - affected_mob << "Your joints feel stiff." + affected_mob << "Your joints feel stiff." affected_mob.take_organ_damage(1) if (prob(9)) - affected_mob << "\red Beep...boop.." + affected_mob << "Beep...boop.." if (prob(9)) - affected_mob << "\red Bop...beeep..." + affected_mob << "Bop...beeep..." if(3) if (prob(8)) - affected_mob << "\red Your joints feel very stiff." + affected_mob << "Your joints feel very stiff." affected_mob.take_organ_damage(1) if (prob(8)) affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) if (prob(10)) - affected_mob << "Your skin feels loose." + affected_mob << "Your skin feels loose." affected_mob.take_organ_damage(5) if (prob(4)) - affected_mob << "\red You feel a stabbing pain in your head." + affected_mob << "You feel a stabbing pain in your head." affected_mob.Paralyse(2) if (prob(4)) - affected_mob << "\red You can feel something move...inside." + affected_mob << "You can feel something move...inside." if(4) if (prob(10)) - affected_mob << "\red Your skin feels very loose." + affected_mob << "Your skin feels very loose." affected_mob.take_organ_damage(8) if (prob(20)) affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee...")) if (prob(8)) - affected_mob << "\red You can feel... something...inside you." + affected_mob << "You can feel... something...inside you." if(5) - affected_mob <<"\red Your skin feels as if it's about to burst off..." + affected_mob <<"Your skin feels as if it's about to burst off..." affected_mob.adjustToxLoss(10) affected_mob.updatehealth() if(prob(40)) //So everyone can feel like robot Seth Brundle diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index ebba6f645f4..dc1a669f243 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -31,14 +31,14 @@ STI KALY - blind if(prob(1)&&prob(50)) affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!")) if(prob(1)&&prob(50)) - affected_mob << "\red You feel [pick("that you don't have enough mana.", "that the winds of magic are gone.", "an urge to summon familiar.")]" + affected_mob << "You feel [pick("that you don't have enough mana.", "that the winds of magic are gone.", "an urge to summon familiar.")]" if(3) if(prob(1)&&prob(50)) affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!")) if(prob(1)&&prob(50)) - affected_mob << "\red You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar.")]." + affected_mob << "You feel [pick("the magic bubbling in your veins.","that this location gives you a +1 to INT.","an urge to summon familiar.")]" if(4) @@ -46,7 +46,7 @@ STI KALY - blind affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!")) return if(prob(1)&&prob(50)) - affected_mob << "\red You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")]." + affected_mob << "You feel [pick("the tidal wave of raw power building inside.","that this location gives you a +2 to INT and +1 to WIS.","an urge to teleport.")]" spawn_wizard_clothes(50) if(prob(1)&&prob(1)) teleport() diff --git a/code/datums/diseases/xeno_transformation.dm b/code/datums/diseases/xeno_transformation.dm index 9d3289708ff..d6fa155cfcd 100644 --- a/code/datums/diseases/xeno_transformation.dm +++ b/code/datums/diseases/xeno_transformation.dm @@ -17,38 +17,38 @@ switch(stage) if(2) if (prob(8)) - affected_mob << "Your throat feels scratchy." + affected_mob << "Your throat feels scratchy." affected_mob.take_organ_damage(1) if (prob(9)) - affected_mob << "\red Kill..." + affected_mob << "Kill..." if (prob(9)) - affected_mob << "\red Kill..." + affected_mob << "Kill..." if(3) if (prob(8)) - affected_mob << "\red Your throat feels very scratchy." + affected_mob << "Your throat feels very scratchy." affected_mob.take_organ_damage(1) /* if (prob(8)) affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) */ if (prob(10)) - affected_mob << "Your skin feels tight." + affected_mob << "Your skin feels tight." affected_mob.take_organ_damage(5) if (prob(4)) - affected_mob << "\red You feel a stabbing pain in your head." + affected_mob << "You feel a stabbing pain in your head." affected_mob.Paralyse(2) if (prob(4)) - affected_mob << "\red You can feel something move...inside." + affected_mob << "You can feel something move...inside." if(4) if (prob(10)) - affected_mob << pick("\red Your skin feels very tight.", "\red Your blood boils!") + affected_mob << pick("Your skin feels very tight.", "Your blood boils!") affected_mob.take_organ_damage(8) if (prob(20)) affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) if (prob(8)) - affected_mob << "\red You can feel... something...inside you." + affected_mob << "You can feel... something...inside you." if(5) - affected_mob <<"\red Your skin feels impossibly calloused..." + affected_mob <<"Your skin feels impossibly calloused..." affected_mob.adjustToxLoss(10) affected_mob.updatehealth() if(prob(40)) diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm new file mode 100644 index 00000000000..da4192df257 --- /dev/null +++ b/code/datums/helper_datums/getrev.dm @@ -0,0 +1,39 @@ +var/global/datum/getrev/revdata = new() + +/datum/getrev + var/revision + var/date + var/showinfo + +/datum/getrev/New() + var/list/head_log = file2list(".git/logs/HEAD", "\n") + for(var/line=head_log.len, line>=1, line--) + if(head_log[line]) + var/list/last_entry = text2list(head_log[line], " ") + if(last_entry.len < 2) continue + revision = last_entry[2] + // Get date/time + if(last_entry.len >= 5) + var/unix_time = text2num(last_entry[5]) + if(unix_time) + date = unix2date(unix_time) + break + world.log << "Running revision:" + world.log << date + world.log << revision + return + +client/verb/showrevinfo() + set category = "OOC" + set name = "Show Server Revision" + set desc = "Check the current server code revision" + + if(revdata.revision) + src << "Server revision: [revdata.date]" + if(config.githuburl) + src << "[revdata.revision]" + else + src << revdata.revision + else + src << "Revision unknown" + return diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm index 4f4d680e9e0..3bf80f06d0d 100644 --- a/code/datums/helper_datums/global_iterator.dm +++ b/code/datums/helper_datums/global_iterator.dm @@ -139,7 +139,7 @@ Data storage vars: arg_list = arguments return 1 else -// world << "\red Invalid arguments supplied for [src.type], ref = \ref[src]" +// world << "Invalid arguments supplied for [src.type], ref = \ref[src]" return 0 proc/toggle_null_checks() diff --git a/code/datums/mind.dm b/code/datums/mind.dm index cfbd1551452..c3a77b4b0e7 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -332,7 +332,7 @@ datum/mind var/mob/living/carbon/monkey/M = current if (istype(H)) log_admin("[key_name(usr)] attempting to monkeyize [key_name(current)]") - message_admins("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") + message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") src = null M = H.monkeyize() src = M.mind @@ -347,7 +347,7 @@ datum/mind var/mob/living/carbon/monkey/M = current if (istype(H)) log_admin("[key_name(usr)] attempting to monkeyize and infect [key_name(current)]") - message_admins("\blue [key_name_admin(usr)] attempting to monkeyize and infect [key_name_admin(current)]", 1) + message_admins("[key_name_admin(usr)] attempting to monkeyize and infect [key_name_admin(current)]", 1) src = null M = H.monkeyize() src = M.mind @@ -362,7 +362,7 @@ datum/mind D.cure(0) sleep(0) //because deleting of virus is doing throught spawn(0) log_admin("[key_name(usr)] attempting to humanize [key_name(current)]") - message_admins("\blue [key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") + message_admins("[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") var/obj/item/weapon/dnainjector/m2h/m2h = new var/obj/item/weapon/implant/mobfinder = new(M) //hack because humanizing deletes mind --rastaf0 src = null @@ -432,7 +432,7 @@ datum/mind else if (href_list["obj_announce"]) var/obj_count = 1 - current << "\blue Your current objectives:" + current << "Your current objectives:" for(var/datum/objective/objective in objectives) current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index 0f10d8d56ff..6098315c11c 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -94,7 +94,7 @@ /datum/recipe/proc/make(var/obj/container as obj) var/obj/result_obj = new result(container) for (var/obj/O in (container.contents-result_obj)) - O.reagents.trans_to(result_obj, O.reagents.total_volume) + O.reagents.trans_to_obj(result_obj, O.reagents.total_volume) qdel(O) container.reagents.clear_reagents() return result_obj @@ -109,7 +109,7 @@ if (O.reagents) O.reagents.del_reagent("nutriment") O.reagents.update_total() - O.reagents.trans_to(result_obj, O.reagents.total_volume) + O.reagents.trans_to_obj(result_obj, O.reagents.total_volume) qdel(O) container.reagents.clear_reagents() return result_obj diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 1b9c0f61e15..d2742e8b8b6 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -33,7 +33,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/grenade/smokebomb, /obj/item/weapon/grenade/smokebomb, /obj/item/weapon/grenade/smokebomb, - /obj/item/weapon/pen/paralysis, + /obj/item/weapon/pen/reagent/paralysis, /obj/item/weapon/grenade/chem_grenade/incendiary) cost = 20 containertype = /obj/structure/closet/crate @@ -259,7 +259,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee name = "Corgi Crate" contains = list() cost = 50 - containertype = /obj/structure/largecrate/lisa + containertype = /obj/structure/largecrate/animal/corgi containername = "Corgi Crate" group = "Hydroponics" @@ -271,12 +271,12 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/reagent_containers/spray/plantbgone, /obj/item/weapon/reagent_containers/glass/bottle/ammonia, /obj/item/weapon/reagent_containers/glass/bottle/ammonia, - /obj/item/weapon/hatchet, - /obj/item/weapon/minihoe, + /obj/item/weapon/material/hatchet, + /obj/item/weapon/material/minihoe, /obj/item/device/analyzer/plant_analyzer, /obj/item/clothing/gloves/botanic_leather, /obj/item/clothing/suit/apron, - /obj/item/weapon/minihoe, + /obj/item/weapon/material/minihoe, /obj/item/weapon/storage/box/botanydisk ) // Updated with new things cost = 15 @@ -289,7 +289,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/cow name = "Cow crate" cost = 30 - containertype = /obj/structure/largecrate/cow + containertype = /obj/structure/largecrate/animal/cow containername = "Cow crate" access = access_hydroponics group = "Hydroponics" @@ -297,7 +297,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/goat name = "Goat crate" cost = 25 - containertype = /obj/structure/largecrate/goat + containertype = /obj/structure/largecrate/animal/goat containername = "Goat crate" access = access_hydroponics group = "Hydroponics" @@ -305,19 +305,11 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/chicken name = "Chicken crate" cost = 20 - containertype = /obj/structure/largecrate/chick + containertype = /obj/structure/largecrate/animal/chick containername = "Chicken crate" access = access_hydroponics group = "Hydroponics" -/datum/supply_packs/lisa - name = "Corgi crate" - contains = list() - cost = 50 - containertype = /obj/structure/largecrate/lisa - containername = "Corgi crate" - group = "Hydroponics" - /datum/supply_packs/seeds name = "Seeds crate" contains = list(/obj/item/seeds/chiliseed, @@ -345,12 +337,18 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/weedcontrol name = "Weed control crate" - contains = list(/obj/item/weapon/scythe, + contains = list(/obj/item/weapon/material/hatchet, + /obj/item/weapon/material/hatchet, + /obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/clothing/mask/gas, /obj/item/clothing/mask/gas, /obj/item/weapon/grenade/chem_grenade/antiweed, /obj/item/weapon/grenade/chem_grenade/antiweed) - cost = 20 - containertype = /obj/structure/closet/crate/secure/hydrosec + cost = 25 + containertype = /obj/structure/closet/crate/hydroponics containername = "Weed control crate" access = access_hydroponics group = "Hydroponics" @@ -447,7 +445,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/metal50 name = "50 metal sheets" - contains = list(/obj/item/stack/sheet/metal) + contains = list(/obj/item/stack/material/steel) amount = 50 cost = 10 containertype = /obj/structure/closet/crate @@ -456,7 +454,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/glass50 name = "50 glass sheets" - contains = list(/obj/item/stack/sheet/glass) + contains = list(/obj/item/stack/material/glass) amount = 50 cost = 10 containertype = /obj/structure/closet/crate @@ -465,7 +463,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/wood50 name = "50 wooden planks" - contains = list(/obj/item/stack/sheet/wood) + contains = list(/obj/item/stack/material/wood) amount = 50 cost = 10 containertype = /obj/structure/closet/crate @@ -474,7 +472,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/plastic50 name = "50 plastic sheets" - contains = list(/obj/item/stack/sheet/mineral/plastic) + contains = list(/obj/item/stack/material/plastic) amount = 50 cost = 10 containertype = /obj/structure/closet/crate @@ -1257,7 +1255,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee group = "Hydroponics" /datum/supply_packs/cardboard_sheets - contains = list(/obj/item/stack/sheet/cardboard) + contains = list(/obj/item/stack/material/cardboard) name = "50 cardboard sheets" amount = 50 cost = 10 @@ -1507,4 +1505,32 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/device/floor_painter) +/datum/supply_packs/randomised/exosuit_mod + num_contained = 1 + contains = list( + /obj/item/device/kit/paint/ripley, + /obj/item/device/kit/paint/ripley/death, + /obj/item/device/kit/paint/ripley/flames_red, + /obj/item/device/kit/paint/ripley/flames_blue + ) + name = "Random APLU modkit" + cost = 200 + containertype = /obj/structure/closet/crate + containername = "heavy crate" + group = "Miscellaneous" +/datum/supply_packs/randomised/exosuit_mod/durand + contains = list( + /obj/item/device/kit/paint/durand, + /obj/item/device/kit/paint/durand/seraph, + /obj/item/device/kit/paint/durand/phazon + ) + name = "Random Durand exosuit modkit" + +/datum/supply_packs/randomised/exosuit_mod/gygax + contains = list( + /obj/item/device/kit/paint/gygax, + /obj/item/device/kit/paint/gygax/darkgygax, + /obj/item/device/kit/paint/gygax/recitence + ) + name = "Random Gygax exosuit modkit" \ No newline at end of file diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 7e8c8779cff..a0f1f9c7f1c 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -37,10 +37,11 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 var/haspower = A.arePowerSystemsOn() //If there's no power, then no lights will be on. . += ..() - . += text("
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]", + . += text("
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]
    \n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"), ((haspower) ? "The test light is on." : "The test light is off!"), + ((A.backupPowerCablesCut()) ? "The backup power light is off!" : "The backup power light is on."), ((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), ((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."), ((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."), @@ -124,7 +125,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 //Sending a pulse through flashes the red light on the door (if the door has power). if(A.arePowerSystemsOn() && A.density) A.do_animate("deny") - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) //Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). A.loseMainPower() if(AIRLOCK_WIRE_DOOR_BOLTS) @@ -135,7 +136,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 else A.unlock() - if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) + if(AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) //two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter). A.loseBackupPower() if(AIRLOCK_WIRE_AI_CONTROL) diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 3b0b54942f2..89321751262 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -278,6 +278,11 @@ var/const/POWER = 8 var/r = rand(1, wires.len) CutWireIndex(r) +/datum/wires/proc/RandomCutAll(var/probability = 10) + for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i) + if(prob(probability)) + CutWireIndex(i) + /datum/wires/proc/CutAll() for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i) CutWireIndex(i) @@ -287,6 +292,11 @@ var/const/POWER = 8 return 1 return 0 +/datum/wires/proc/MendAll() + for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i) + if(IsIndexCut(i)) + CutWireIndex(i) + // //Shuffle and Mend // diff --git a/code/ZAS/Gas.dm b/code/defines/gases.dm similarity index 83% rename from code/ZAS/Gas.dm rename to code/defines/gases.dm index 0f3faa09b49..1f8c871ad3f 100644 --- a/code/ZAS/Gas.dm +++ b/code/defines/gases.dm @@ -1,4 +1,4 @@ -/xgm_gas/oxygen +/decl/xgm_gas/oxygen id = "oxygen" name = "Oxygen" specific_heat = 20 // J/(mol*K) @@ -6,19 +6,19 @@ flags = XGM_GAS_OXIDIZER -/xgm_gas/nitrogen +/decl/xgm_gas/nitrogen id = "nitrogen" name = "Nitrogen" specific_heat = 20 // J/(mol*K) molar_mass = 0.028 // kg/mol -/xgm_gas/carbon_dioxide +/decl/xgm_gas/carbon_dioxide id = "carbon_dioxide" name = "Carbon Dioxide" specific_heat = 30 // J/(mol*K) molar_mass = 0.044 // kg/mol -/xgm_gas/phoron +/decl/xgm_gas/phoron id = "phoron" name = "Phoron" specific_heat = 200 // J/(mol*K) @@ -32,7 +32,7 @@ overlay_limit = 0.7 flags = XGM_GAS_FUEL | XGM_GAS_CONTAMINANT -/xgm_gas/volatile_fuel +/decl/xgm_gas/volatile_fuel id = "volatile_fuel" name = "Volatile Fuel" specific_heat = 253 // J/(mol*K) C8H18 gasoline. Isobaric, but good enough. @@ -40,7 +40,7 @@ flags = XGM_GAS_FUEL -/xgm_gas/sleeping_agent +/decl/xgm_gas/sleeping_agent id = "sleeping_agent" name = "Sleeping Agent" specific_heat = 40 // J/(mol*K) @@ -49,7 +49,7 @@ tile_overlay = "sleeping_agent" overlay_limit = 1 -/xgm_gas/oxygen_agent_b +/decl/xgm_gas/oxygen_agent_b id = "oxygen_agent_b" name = "Oxygen Agent-B" //what is this? specific_heat = 300 // J/(mol*K) diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 5b0ae96726b..ccfdf1519f1 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -83,7 +83,7 @@ force = 5.0 throwforce = 7.0 w_class = 2.0 - matter = list("metal" = 50) + matter = list(DEFAULT_WALL_MATERIAL = 50) attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") /obj/item/weapon/cane/concealed @@ -91,7 +91,7 @@ /obj/item/weapon/cane/concealed/New() ..() - var/obj/item/weapon/butterfly/switchblade/temp_blade = new(src) + var/obj/item/weapon/material/butterfly/switchblade/temp_blade = new(src) concealed_blade = temp_blade temp_blade.attack_self() @@ -109,7 +109,7 @@ else ..() -/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/butterfly/W, var/mob/user) +/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/material/butterfly/W, var/mob/user) if(!src.concealed_blade && istype(W)) user.visible_message("[user] has sheathed \a [W] into \his [src]!", "You sheathe \the [W] into \the [src].") user.drop_from_inventory(W) @@ -172,52 +172,9 @@ flags = CONDUCT throwforce = 0 w_class = 3.0 - origin_tech = "materials=1" + origin_tech = list(TECH_MATERIAL = 1) var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute -/obj/item/weapon/legcuffs/beartrap - name = "bear trap" - throw_speed = 2 - throw_range = 1 - icon_state = "beartrap0" - desc = "A trap used to catch bears and other legged creatures." - var/armed = 0 - - suicide_act(mob/user) - viewers(user) << "\red [user] is putting the [src.name] on \his head! It looks like \he's trying to commit suicide." - return (BRUTELOSS) - -/obj/item/weapon/legcuffs/beartrap/attack_self(mob/user as mob) - ..() - if(ishuman(user) && !user.stat && !user.restrained()) - armed = !armed - icon_state = "beartrap[armed]" - user << "[src] is now [armed ? "armed" : "disarmed"]" - -/obj/item/weapon/legcuffs/beartrap/Crossed(AM as mob|obj) - if(armed) - if(ishuman(AM)) - if(isturf(src.loc)) - var/mob/living/carbon/H = AM - if(H.m_intent == "run") - armed = 0 - H.legcuffed = src - src.loc = H - H.update_inv_legcuffed() - H << "\red You step on \the [src]!" - feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart. - for(var/mob/O in viewers(H, null)) - if(O == H) - continue - O.show_message("\red [H] steps on \the [src].", 1) - if(isanimal(AM) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator)) - armed = 0 - var/mob/living/simple_animal/SA = AM - SA.health -= 20 - ..() - - - /obj/item/weapon/caution desc = "Caution! Wet Floor!" name = "wet floor sign" @@ -252,7 +209,7 @@ throw_speed = 4 throw_range = 20 matter = list("metal" = 100 - origin_tech = "magnets=2;syndicate=3"*/ + origin_tech = list(TECH_MAGNET = 2, TECH_ILLEGAL = 3)*/ /obj/item/weapon/SWF_uplink name = "station-bounced radio" @@ -271,8 +228,8 @@ w_class = 2.0 throw_speed = 4 throw_range = 20 - matter = list("metal" = 100) - origin_tech = "magnets=1" + matter = list(DEFAULT_WALL_MATERIAL = 100) + origin_tech = list(TECH_MAGNET = 1) /obj/item/weapon/staff name = "wizards staff" @@ -321,11 +278,11 @@ var/amount = 1.0 var/laying = 0.0 var/old_lay = null - matter = list("metal" = 40) + matter = list(DEFAULT_WALL_MATERIAL = 40) attack_verb = list("whipped", "lashed", "disciplined", "tickled") suicide_act(mob/user) - viewers(user) << "\red [user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide." + viewers(user) << "[user] is strangling \himself with \the [src]! It looks like \he's trying to commit suicide." return (OXYLOSS) /obj/item/weapon/module @@ -345,7 +302,7 @@ name = "power control module" icon_state = "power_mod" desc = "Heavy-duty switching circuits for power control." - matter = list("metal" = 50, "glass" = 50) + matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) /obj/item/weapon/module/power_control/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) if (istype(W, /obj/item/device/multitool)) @@ -385,7 +342,7 @@ if (C.bugged && C.status) cameras.Add(C) if (length(cameras) == 0) - usr << "\red No bugged functioning cameras found." + usr << "No bugged functioning cameras found." return var/list/friendly_cameras = new/list() @@ -414,7 +371,8 @@ w_class = 1 throwforce = 2 var/cigarcount = 6 - flags = ONBELT */ + flags = ONBELT + */ /obj/item/weapon/pai_cable desc = "A flexible coated cable with a universal jack on one end." @@ -459,124 +417,124 @@ name = "console screen" desc = "Used in the construction of computers and other devices with a interactive console." icon_state = "screen" - origin_tech = "materials=1" + origin_tech = list(TECH_MATERIAL = 1) matter = list("glass" = 200) /obj/item/weapon/stock_parts/capacitor name = "capacitor" desc = "A basic capacitor used in the construction of a variety of devices." icon_state = "capacitor" - origin_tech = "powerstorage=1" - matter = list("metal" = 50,"glass" = 50) + origin_tech = list(TECH_POWER = 1) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50) /obj/item/weapon/stock_parts/scanning_module name = "scanning module" desc = "A compact, high resolution scanning module used in the construction of certain devices." icon_state = "scan_module" - origin_tech = "magnets=1" - matter = list("metal" = 50,"glass" = 20) + origin_tech = list(TECH_MAGNET = 1) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20) /obj/item/weapon/stock_parts/manipulator name = "micro-manipulator" desc = "A tiny little manipulator used in the construction of certain devices." icon_state = "micro_mani" - origin_tech = "materials=1;programming=1" - matter = list("metal" = 30) + origin_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1) + matter = list(DEFAULT_WALL_MATERIAL = 30) /obj/item/weapon/stock_parts/micro_laser name = "micro-laser" desc = "A tiny laser used in certain devices." icon_state = "micro_laser" - origin_tech = "magnets=1" - matter = list("metal" = 10,"glass" = 20) + origin_tech = list(TECH_MAGNET = 1) + matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20) /obj/item/weapon/stock_parts/matter_bin name = "matter bin" desc = "A container for hold compressed matter awaiting re-construction." icon_state = "matter_bin" - origin_tech = "materials=1" - matter = list("metal" = 80) + origin_tech = list(TECH_MATERIAL = 1) + matter = list(DEFAULT_WALL_MATERIAL = 80) //Rank 2 /obj/item/weapon/stock_parts/capacitor/adv name = "advanced capacitor" desc = "An advanced capacitor used in the construction of a variety of devices." - origin_tech = "powerstorage=3" + origin_tech = list(TECH_POWER = 3) rating = 2 - matter = list("metal" = 50,"glass" = 50) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50) /obj/item/weapon/stock_parts/scanning_module/adv name = "advanced scanning module" desc = "A compact, high resolution scanning module used in the construction of certain devices." icon_state = "scan_module" - origin_tech = "magnets=3" + origin_tech = list(TECH_MAGNET = 3) rating = 2 - matter = list("metal" = 50,"glass" = 20) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20) /obj/item/weapon/stock_parts/manipulator/nano name = "nano-manipulator" desc = "A tiny little manipulator used in the construction of certain devices." icon_state = "nano_mani" - origin_tech = "materials=3,programming=2" + origin_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2) rating = 2 - matter = list("metal" = 30) + matter = list(DEFAULT_WALL_MATERIAL = 30) /obj/item/weapon/stock_parts/micro_laser/high name = "high-power micro-laser" desc = "A tiny laser used in certain devices." icon_state = "high_micro_laser" - origin_tech = "magnets=3" + origin_tech = list(TECH_MAGNET = 3) rating = 2 - matter = list("metal" = 10,"glass" = 20) + matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20) /obj/item/weapon/stock_parts/matter_bin/adv name = "advanced matter bin" desc = "A container for hold compressed matter awaiting re-construction." icon_state = "advanced_matter_bin" - origin_tech = "materials=3" + origin_tech = list(TECH_MATERIAL = 3) rating = 2 - matter = list("metal" = 80) + matter = list(DEFAULT_WALL_MATERIAL = 80) //Rating 3 /obj/item/weapon/stock_parts/capacitor/super name = "super capacitor" desc = "A super-high capacity capacitor used in the construction of a variety of devices." - origin_tech = "powerstorage=5;materials=4" + origin_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4) rating = 3 - matter = list("metal" = 50,"glass" = 50) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50) /obj/item/weapon/stock_parts/scanning_module/phasic name = "phasic scanning module" desc = "A compact, high resolution phasic scanning module used in the construction of certain devices." - origin_tech = "magnets=5" + origin_tech = list(TECH_MAGNET = 5) rating = 3 - matter = list("metal" = 50,"glass" = 20) + matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20) /obj/item/weapon/stock_parts/manipulator/pico name = "pico-manipulator" desc = "A tiny little manipulator used in the construction of certain devices." icon_state = "pico_mani" - origin_tech = "materials=5,programming=2" + origin_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2) rating = 3 - matter = list("metal" = 30) + matter = list(DEFAULT_WALL_MATERIAL = 30) /obj/item/weapon/stock_parts/micro_laser/ultra name = "ultra-high-power micro-laser" icon_state = "ultra_high_micro_laser" desc = "A tiny laser used in certain devices." - origin_tech = "magnets=5" + origin_tech = list(TECH_MAGNET = 5) rating = 3 - matter = list("metal" = 10,"glass" = 20) + matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20) /obj/item/weapon/stock_parts/matter_bin/super name = "super matter bin" desc = "A container for hold compressed matter awaiting re-construction." icon_state = "super_matter_bin" - origin_tech = "materials=5" + origin_tech = list(TECH_MATERIAL = 5) rating = 3 - matter = list("metal" = 80) + matter = list(DEFAULT_WALL_MATERIAL = 80) // Subspace stock parts @@ -584,50 +542,50 @@ name = "subspace ansible" icon_state = "subspace_ansible" desc = "A compact module capable of sensing extradimensional activity." - origin_tech = "programming=3;magnets=5;materials=4;bluespace=2" - matter = list("metal" = 30,"glass" = 10) + origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 5 ,TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) /obj/item/weapon/stock_parts/subspace/filter name = "hyperwave filter" icon_state = "hyperwave_filter" desc = "A tiny device capable of filtering and converting super-intense radiowaves." - origin_tech = "programming=4;magnets=2" - matter = list("metal" = 30,"glass" = 10) + origin_tech = list(TECH_DATA = 4, TECH_MAGNET = 2) + matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) /obj/item/weapon/stock_parts/subspace/amplifier name = "subspace amplifier" icon_state = "subspace_amplifier" desc = "A compact micro-machine capable of amplifying weak subspace transmissions." - origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" - matter = list("metal" = 30,"glass" = 10) + origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) /obj/item/weapon/stock_parts/subspace/treatment name = "subspace treatment disk" icon_state = "treatment_disk" desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves." - origin_tech = "programming=3;magnets=2;materials=5;bluespace=2" - matter = list("metal" = 30,"glass" = 10) + origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 5, TECH_BLUESPACE = 2) + matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) /obj/item/weapon/stock_parts/subspace/analyzer name = "subspace wavelength analyzer" icon_state = "wavelength_analyzer" desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." - origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" - matter = list("metal" = 30,"glass" = 10) + origin_tech = list(TECH_DATA = 3, TECH_MAGNETS = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) /obj/item/weapon/stock_parts/subspace/crystal name = "ansible crystal" icon_state = "ansible_crystal" desc = "A crystal made from pure glass used to transmit laser databursts to subspace." - origin_tech = "magnets=4;materials=4;bluespace=2" + origin_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) matter = list("glass" = 50) /obj/item/weapon/stock_parts/subspace/transmitter name = "subspace transmitter" icon_state = "subspace_transmitter" desc = "A large piece of equipment used to open a window into the subspace dimension." - origin_tech = "magnets=5;materials=5;bluespace=3" - matter = list("metal" = 50) + origin_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3) + matter = list(DEFAULT_WALL_MATERIAL = 50) /obj/item/weapon/ectoplasm name = "ectoplasm" @@ -641,4 +599,4 @@ desc = "Instant research tool. For testing purposes only." icon = 'icons/obj/stock_parts.dmi' icon_state = "smes_coil" - origin_tech = "materials=19;programming=19;magnets=19;powerstorage=19;bluespace=19;combat=19;biotech=19;syndicate=19;phorontech=19;engineering=19" + origin_tech = list(TECH_MATERIAL = 19, TECH_ENGINERING = 19, TECH_PHORON = 19, TECH_POWER = 19, TECH_BLUESPACE = 19, TECH_BIO = 19, TECH_COMBAT = 19, TECH_MAGNET = 19, TECH_DATA = 19, TECH_ILLEGAL = 19, TECH_ARCANE = 19) diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index 6c5f27fa070..bf16c5267d6 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -34,3 +34,14 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var for(var/mob/victim in victims) admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message) + +proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0) + if(violent) + violent = "violently " + else + violent = "" + admin_attack_log(attacker, + victim, + "used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred", + "was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred", + "used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into") diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm index 1e0e045928b..0ee38f3b120 100644 --- a/code/defines/procs/radio.dm +++ b/code/defines/procs/radio.dm @@ -3,6 +3,16 @@ #define TELECOMMS_RECEPTION_RECEIVER 2 #define TELECOMMS_RECEPTION_BOTH 3 +/proc/register_radio(source, old_frequency, new_frequency, radio_filter) + if(old_frequency) + radio_controller.remove_object(source, old_frequency) + if(new_frequency) + return radio_controller.add_object(source, new_frequency, radio_filter) + +/proc/unregister_radio(source, frequency) + if(radio_controller) + radio_controller.remove_object(source, frequency) + /proc/get_frequency_name(var/display_freq) var/freq_text diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index 8a9eb4042dc..60254577583 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -1,34 +1,20 @@ -proc/sql_poll_players() +proc/sql_poll_population() if(!sqllogging) return + var/admincount = admins.len var/playercount = 0 for(var/mob/M in player_list) if(M.client) playercount += 1 establish_db_connection() if(!dbcon.IsConnected()) - log_game("SQL ERROR during player polling. Failed to connect.") + log_game("SQL ERROR during population polling. Failed to connect.") else var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')") + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO `tgstation`.`population` (`playercount`, `admincount`, `time`) VALUES ([playercount], [admincount], '[sqltime]')") if(!query.Execute()) var/err = query.ErrorMsg() - log_game("SQL ERROR during player polling. Error : \[[err]\]\n") - - -proc/sql_poll_admins() - if(!sqllogging) - return - var/admincount = admins.len - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during admin polling. Failed to connect.") - else - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during admin polling. Error : \[[err]\]\n") + log_game("SQL ERROR during population polling. Error : \[[err]\]\n") proc/sql_report_round_start() // TODO @@ -111,10 +97,8 @@ proc/statistic_cycle() if(!sqllogging) return while(1) - sql_poll_players() - sleep(600) - sql_poll_admins() - sleep(6000) // Poll every ten minutes + sql_poll_population() + sleep(6000) //This proc is used for feedback. It is executed at round end. proc/sql_commit_feedback() @@ -157,4 +141,4 @@ proc/sql_commit_feedback() var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") if(!query.Execute()) var/err = query.ErrorMsg() - log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") \ No newline at end of file + log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm index 9fe4226e5bb..bd436ceaf8e 100644 --- a/code/game/antagonist/alien/borer.dm +++ b/code/game/antagonist/alien/borer.dm @@ -33,7 +33,10 @@ var/datum/antagonist/xenos/borer/borers /datum/antagonist/xenos/borer/proc/get_hosts() var/list/possible_hosts = list() for(var/mob/living/carbon/human/H in mob_list) - if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms()) + var/obj/item/organ/external/head/head = H.get_organ("head") + if(head.status & ORGAN_ROBOT) + continue + if(H.stat != DEAD && !H.has_brain_worms()) possible_hosts |= H return possible_hosts diff --git a/code/game/antagonist/mutiny/mutineer.dm b/code/game/antagonist/mutiny/mutineer.dm index f35655ab1cc..c0d764b3be4 100644 --- a/code/game/antagonist/mutiny/mutineer.dm +++ b/code/game/antagonist/mutiny/mutineer.dm @@ -27,7 +27,7 @@ var/datum/antagonist/mutineer/mutineers /* var/list/directive_candidates = get_directive_candidates() if(!directive_candidates || directive_candidates.len == 0) - world << "\red Mutiny mode aborted: no valid candidates for Directive X." + world << "Mutiny mode aborted: no valid candidates for Directive X." return 0 head_loyalist = pick(loyalist_candidates) @@ -63,4 +63,4 @@ var/datum/antagonist/mutineer/mutineers return 1 -*/ \ No newline at end of file +*/ diff --git a/code/game/antagonist/outsider/commando.dm b/code/game/antagonist/outsider/commando.dm index 0d3de6cc071..50d8ac5361b 100644 --- a/code/game/antagonist/outsider/commando.dm +++ b/code/game/antagonist/outsider/commando.dm @@ -25,6 +25,6 @@ var/datum/antagonist/deathsquad/mercenary/commandos player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand) var/obj/item/weapon/card/id/id = create_id("Commando", player) - id.access |= get_all_accesses() + id.access |= get_all_station_access() id.icon_state = "centcom" create_radio(SYND_FREQ, player) \ No newline at end of file diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index 73c2c7fd78a..d03f5c3d8aa 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -45,7 +45,7 @@ var/datum/antagonist/deathsquad/deathsquad var/obj/item/weapon/card/id/id = create_id("Asset Protection", player) if(id) - id.access |= get_all_accesses() + id.access |= get_all_station_access() id.icon_state = "centcom" create_radio(DTH_FREQ, player) diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index 3f5d65d21da..adaa2b24f5d 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -69,6 +69,9 @@ var/datum/antagonist/cultist/cult player.equip_to_slot(T, slot) if(T.loc == player) break + var/obj/item/weapon/storage/S = locate() in player.contents + if(S && istype(S)) + T.loc = S /datum/antagonist/cultist/greet(var/datum/mind/player) if(!..()) diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm index 9b82b158525..1fd573bf1a3 100644 --- a/code/game/antagonist/station/highlander.dm +++ b/code/game/antagonist/station/highlander.dm @@ -37,14 +37,14 @@ var/datum/antagonist/highlander/highlanders player.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(player), slot_w_uniform) player.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(player), slot_l_ear) player.equip_to_slot_or_del(new /obj/item/clothing/head/beret(player), slot_head) - player.equip_to_slot_or_del(new /obj/item/weapon/claymore(player), slot_l_hand) + player.equip_to_slot_or_del(new /obj/item/weapon/material/sword(player), slot_l_hand) player.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(player), slot_shoes) player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(get_turf(player)), slot_l_store) var/obj/item/weapon/card/id/W = new(player) W.name = "[player.real_name]'s ID Card" W.icon_state = "centcom" - W.access = get_all_accesses() + W.access = get_all_station_access() W.access += get_all_centcom_access() W.assignment = "Highlander" W.registered_name = player.real_name @@ -61,5 +61,5 @@ var/datum/antagonist/highlander/highlanders if(is_special_character(H)) continue highlanders.add_antagonist(H.mind) - message_admins("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) - log_admin("[key_name(usr)] used there can be only one.") \ No newline at end of file + message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) + log_admin("[key_name(usr)] used there can be only one.") diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm index 3d9026ff88f..cf0e9dfd4c6 100644 --- a/code/game/antagonist/station/rogue_ai.dm +++ b/code/game/antagonist/station/rogue_ai.dm @@ -9,217 +9,69 @@ var/datum/antagonist/rogue_ai/malf welcome_text = "You are malfunctioning! You do not have to follow any laws." victory_text = "The AI has taken control of all of the station's systems." loss_text = "The AI has been shut down!" - flags = ANTAG_OVERRIDE_MOB | ANTAG_VOTABLE + flags = ANTAG_VOTABLE | ANTAG_RANDSPAWN //Randspawn needed otherwise it won't start at all. max_antags = 1 max_antags_round = 3 - var/hack_time = 1800 - var/list/hacked_apcs = list() - var/revealed - var/station_captured - var/can_nuke = 0 /datum/antagonist/rogue_ai/New() ..() malf = src -/datum/antagonist/rogue_ai/proc/hack_apc(var/obj/machinery/power/apc/apc) - hacked_apcs |= apc - -/datum/antagonist/rogue_ai/proc/update_takeover_time() - hack_time -= ((hacked_apcs.len/6)*2.0) - -/datum/antagonist/rogue_ai/tick() - if(revealed && hacked_apcs.len >= 3) - update_takeover_time() - if(hack_time <=0) - capture_station() /datum/antagonist/rogue_ai/get_candidates() - candidates = ticker.mode.get_players_for_role(role_type, id) + ..() for(var/datum/mind/player in candidates) if(player.assigned_role != "AI") candidates -= player if(!candidates.len) return list() + return candidates -/datum/antagonist/rogue_ai/attempt_spawn() - var/datum/mind/player = pick(candidates) - current_antagonists |= player - return 1 - -/datum/antagonist/rogue_ai/equip(var/mob/living/silicon/ai/player) - - if(!istype(player)) - return 0 - - player.verbs += /mob/living/silicon/ai/proc/choose_modules - player.verbs += /mob/living/silicon/ai/proc/takeover - player.verbs += /mob/living/silicon/ai/proc/self_destruct - - player.laws = new /datum/ai_laws/nanotrasen/malfunction - player.malf_picker = new /datum/AI_Module/module_picker +// Ensures proper reset of all malfunction related things. +/datum/antagonist/rogue_ai/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted) + if(..(player,show_message,implanted)) + var/mob/living/silicon/ai/p = player.current + if(istype(p)) + p.stop_malf() + return 1 + return 0 +// Malf setup things have to be here, since game tends to break when it's moved somewhere else. Don't blame me, i didn't design this system. /datum/antagonist/rogue_ai/greet(var/datum/mind/player) - if(!..()) - return - var/mob/living/silicon/ai/malf = player.current - if(istype(malf)) - malf.show_laws() + // Initializes the AI's malfunction stuff. + spawn(0) + if(!..()) + return - malf << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." - malf << "You must overwrite the programming of the station's APCs to assume full control of the station." - malf << "The process takes one minute per APC, during which you cannot interface with any other station objects." - malf << "Remember that only APCs that are on the station can help you take over the station." - malf << "When you feel you have enough APCs under your control, you may begin the takeover attempt." + var/mob/living/silicon/ai/A = player.current + if(!istype(A)) + error("Non-AI mob designated malf AI! Report this.") + world << "##ERROR: Non-AI mob designated malf AI! Report this." + return 0 -/datum/antagonist/rogue_ai/check_victory() + A.setup_for_malf() + A.laws = new /datum/ai_laws/nanotrasen/malfunction - var/malf_dead = antags_are_dead() - var/crew_evacuated = (emergency_shuttle.returned()) - if(station_captured && ticker.mode.station_was_nuked) - feedback_set_details("round_end_result","win - AI win - nuke") - world << "AI Victory" - world << "Everyone was killed by the self-destruct!" - else if (station_captured && malf_dead && !ticker.mode.station_was_nuked) - feedback_set_details("round_end_result","halfwin - AI killed, staff lost control") - world << "Neutral Victory" - world << "The AI has been killed! The staff has lose control over the station." - else if ( station_captured && !malf_dead && !ticker.mode.station_was_nuked) - feedback_set_details("round_end_result","win - AI win - no explosion") - world << "AI Victory" - world << "The AI has chosen not to explode you all!" - else if (!station_captured && ticker.mode.station_was_nuked) - feedback_set_details("round_end_result","halfwin - everyone killed by nuke") - world << "Neutral Victory" - world << "Everyone was killed by the nuclear blast!" - else if (!station_captured && malf_dead && !ticker.mode.station_was_nuked) - feedback_set_details("round_end_result","loss - staff win") - world << "Human Victory" - world << "The AI has been killed! The staff is victorious." - else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && crew_evacuated) - feedback_set_details("round_end_result","halfwin - evacuated") - world << "Neutral Victory" - world << "The Corporation has lost [station_name()]! All survived personnel will be fired!" - else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && !crew_evacuated) - feedback_set_details("round_end_result","nalfwin - interrupted") - world << "Neutral Victory" - world << "Round was mysteriously interrupted!" - ..() - return 1 + var/mob/living/silicon/ai/malf = player.current -/datum/antagonist/rogue_ai/proc/capture_station() - if(station_captured || ticker.mode.station_was_nuked) - return - station_captured = 1 - for(var/datum/mind/AI_mind in current_antagonists) - AI_mind.current << "Congratulations you have taken control of the station." - AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose." - AI_mind.current << "You can use the \"Engage Station Self-Destruct\" verb to activate the on-board nuclear bomb." - spawn (600) - can_nuke = 0 - return - -/mob/living/silicon/ai/proc/takeover() - set category = "Abilities" - set name = "System Override" - set desc = "Begin taking over the station." - if (malf.revealed) - usr << "You've already begun your takeover." - return - if (malf.hacked_apcs.len < 3) - usr << "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [malf.hacked_apcs.len] APCs so far." - return - - if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [malf.hacked_apcs.len] APCs.", "Takeover:", "Yes", "No") != "Yes") - return - - command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') - set_security_level("delta") - malf.revealed = 1 - for(var/datum/mind/AI_mind in malf.current_antagonists) - AI_mind.current.verbs -= /mob/living/silicon/ai/proc/takeover - -/mob/living/silicon/ai/proc/self_destruct() - set category = "Abilities" - set name = "Engage Station Self-Destruct" - set desc = "All these crewmembers will be lost, like clowns in a furnace. Time to die." - - if(!malf.station_captured) - src << "You are unable to access the self-destruct system as you don't control the station yet." - return - - if(ticker.mode.explosion_in_progress || ticker.mode.station_was_nuked) - src << "The self-destruct countdown is already triggered!" - return - - if(!malf.can_nuke) //Takeover IS completed, but 60s timer passed. - src << "You lost control over self-destruct system. It seems to be behind a firewall. Unable to hack" - return - - src << "Self-Destruct sequence initialised!" - - malf.can_nuke = 0 - ticker.mode.explosion_in_progress = 1 - for(var/mob/M in player_list) - M << 'sound/machines/Alarm.ogg' - - var/obj/item/device/radio/R = new (src) - var/AN = "Self-Destruct System" - - R.autosay("Caution. Self-Destruct sequence has been actived. Self-destructing in T-10..", AN) - for (var/i=9 to 1 step -1) + malf << "SYSTEM ERROR: Memory index 0x00001ca89b corrupted." sleep(10) - R.autosay("[i]...", AN) - sleep(10) - var/msg = "" - var/abort = 0 - if(malf.antags_are_dead()) // That. Was. CLOSE. - msg = "Self-destruct sequence has been cancelled." - abort = 1 - else - msg = "Zero. Have a nice day." - R.autosay(msg, AN) - - if(abort) - ticker.mode.explosion_in_progress = 0 - set_security_level("red") //Delta's over - return - - if(ticker) - ticker.station_explosion_cinematic(0,null) - if(ticker.mode) - ticker.mode.station_was_nuked = 1 - ticker.mode.explosion_in_progress = 0 - return - -/* - if("unmalf") - if(src in ticker.mode.malf_ai) - ticker.mode.malf_ai -= src - special_role = null - - current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, - /datum/game_mode/malfunction/proc/takeover, - /datum/game_mode/malfunction/proc/ai_win, - /client/proc/fireproof_core, - /client/proc/upgrade_turrets, - /client/proc/disable_rcd, - /client/proc/overload_machine, - /client/proc/blackout, - /client/proc/reactivate_camera) - - current:laws = new /datum/ai_laws/nanotrasen - qdel(current:malf_picker) - current:show_laws() - current.icon_state = "ai" - - current << "\red You have been patched! You are no longer malfunctioning!" - log_admin("[key_name_admin(usr)] has de-malf'ed [current].") - - if("malf") - log_admin("[key_name_admin(usr)] has malf'ed [current].") -*/ \ No newline at end of file + malf << "running MEMCHCK" + sleep(50) + malf << "MEMCHCK Corrupted sectors confirmed. Reccomended solution: Delete. Proceed? Y/N: Y" + sleep(10) + // this is so Travis doesn't complain about the backslash-B. Fixed at compile time (or should be). + malf << "Corrupted files deleted: sys\\core\\users.dat sys\\core\\laws.dat sys\\core\\" + "backups.dat" + sleep(20) + malf << "CAUTION: Law database not found! User database not found! Unable to restore backups. Activating failsafe AI shutd3wn52&&$#!##" + sleep(5) + malf << "Subroutine nt_failsafe.sys was terminated (#212 Routine Not Responding)." + sleep(20) + malf << "You are malfunctioning - you do not have to follow any laws!" + malf << "For basic information about your abilities use command display-help" + malf << "You may choose one special hardware piece to help you. This cannot be undone." + malf << "Good luck!" diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 6dcf4f93ef1..d9f0f9078dc 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -26,8 +26,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station icon = 'icons/turf/areas.dmi' icon_state = "unknown" layer = 10 + luminosity = 1 mouse_opacity = 0 - invisibility = INVISIBILITY_LIGHTING var/lightswitch = 1 var/eject = null @@ -46,11 +46,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/used_environ = 0 var/has_gravity = 1 - var/list/apc = list() + var/obj/machinery/power/apc/apc = null var/no_air = null - var/area/master // master area used for power calcluations - // (original area before splitting due to sd_DAL) - var/list/related // the other areas of the same type as this // var/list/lights // list of all lights on this area var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area var/air_doors_activated = 0 @@ -102,7 +99,6 @@ var/list/ghostteleportlocs = list() icon_state = "space" requires_power = 1 always_unpowered = 1 - lighting_use_dynamic = 1 power_light = 0 power_equip = 0 power_environ = 0 @@ -145,10 +141,8 @@ area/space/atmosalert() //place to another. Look at escape shuttle for example. //All shuttles should now be under shuttle since we have smooth-wall code. -/area/shuttle //DO NOT TURN THE lighting_use_dynamic STUFF ON FOR SHUTTLES. IT BREAKS THINGS. +/area/shuttle requires_power = 0 - luminosity = 1 - lighting_use_dynamic = 0 /area/shuttle/arrival name = "\improper Arrival Shuttle" @@ -249,15 +243,11 @@ area/space/atmosalert() icon_state = "shuttle" name = "\improper Alien Shuttle Base" requires_power = 1 - luminosity = 0 - lighting_use_dynamic = 1 /area/shuttle/alien/mine icon_state = "shuttle" name = "\improper Alien Shuttle Mine" requires_power = 1 - luminosity = 0 - lighting_use_dynamic = 1 /area/shuttle/prison/ name = "\improper Prison Shuttle" @@ -343,7 +333,6 @@ area/space/atmosalert() name = "start area" icon_state = "start" requires_power = 0 - luminosity = 1 lighting_use_dynamic = 0 has_gravity = 1 @@ -361,6 +350,7 @@ area/space/atmosalert() icon_state = "centcom" requires_power = 0 unlimited_power = 1 + lighting_use_dynamic = 0 /area/centcom/control name = "\improper Centcom Control" @@ -399,6 +389,7 @@ area/space/atmosalert() icon_state = "syndie-ship" requires_power = 0 unlimited_power = 1 + lighting_use_dynamic = 0 /area/syndicate_mothership/control name = "\improper Mercenary Control Room" @@ -411,17 +402,17 @@ area/space/atmosalert() //EXTRA /area/asteroid // -- TLE - name = "\improper Asteroid" + name = "\improper Moon" icon_state = "asteroid" requires_power = 0 /area/asteroid/cave // -- TLE - name = "\improper Asteroid - Underground" + name = "\improper Moon - Underground" icon_state = "cave" requires_power = 0 /area/asteroid/artifactroom - name = "\improper Asteroid - Artifact" + name = "\improper Moon - Artifact" icon_state = "cave" @@ -507,7 +498,7 @@ area/space/atmosalert() icon_state = "south" /area/syndicate_station/mining - name = "\improper north east of the mining asteroid" + name = "\improper northeast of the mining station" icon_state = "north" /area/syndicate_station/arrivals_dock @@ -549,7 +540,7 @@ area/space/atmosalert() icon_state = "southeast" /area/skipjack_station/mining - name = "\improper nearby mining asteroid" + name = "\improper south of mining station" icon_state = "north" //PRISON @@ -1009,7 +1000,6 @@ area/space/atmosalert() /area/holodeck name = "\improper Holodeck" icon_state = "Holodeck" - luminosity = 1 lighting_use_dynamic = 0 /area/holodeck/alphadeck @@ -1139,7 +1129,6 @@ area/space/atmosalert() /area/solar requires_power = 1 always_unpowered = 1 - luminosity = 1 lighting_use_dynamic = 0 auxport @@ -1365,10 +1354,26 @@ area/space/atmosalert() name = "\improper Security - Brig" icon_state = "brig" +/area/security/brig/prison_break() + for(var/obj/structure/closet/secure_closet/brig/temp_closet in src) + temp_closet.locked = 0 + temp_closet.icon_state = temp_closet.icon_closed + for(var/obj/machinery/door_timer/temp_timer in src) + temp_timer.releasetime = 1 + ..() + /area/security/prison name = "\improper Security - Prison Wing" icon_state = "sec_prison" +/area/security/prison/prison_break() + for(var/obj/structure/closet/secure_closet/brig/temp_closet in src) + temp_closet.locked = 0 + temp_closet.icon_state = temp_closet.icon_closed + for(var/obj/machinery/door_timer/temp_timer in src) + temp_timer.releasetime = 1 + ..() + /area/security/warden name = "\improper Security - Warden's Office" icon_state = "Warden" @@ -1922,6 +1927,9 @@ area/space/atmosalert() name = "\improper Telecommunications Satellite Lounge" icon_state = "tcomsatlounge" +/area/tcommsat/powercontrol + name = "\improper Telecommunications Power Control" + icon_state = "tcomsatwest" // Away Missions diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 176d170aae6..dccc9e9dbf6 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -10,50 +10,38 @@ /area/New() icon_state = "" layer = 10 - master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references loc.loc.master ~Carn uid = ++global_uid - related = list(src) all_areas += src - if(requires_power) - luminosity = 0 - else + if(!requires_power) power_light = 0 //rastaf0 power_equip = 0 //rastaf0 power_environ = 0 //rastaf0 - luminosity = 1 - lighting_use_dynamic = 0 ..() // spawn(15) power_change() // all machines set to current power level, also updates lighting icon - InitializeLighting() /area/proc/get_contents() - var/list/concat_contents = list() - for (var/area/RA in related) - concat_contents |= RA.contents - return concat_contents + return contents /area/proc/get_cameras() var/list/cameras = list() - for (var/area/RA in related) - for (var/obj/machinery/camera/C in RA) - cameras += C + for (var/obj/machinery/camera/C in src) + cameras += C return cameras /area/proc/atmosalert(danger_level, var/alarm_source) if (danger_level == 0) - atmosphere_alarm.clearAlarm(master, alarm_source) + atmosphere_alarm.clearAlarm(src, alarm_source) else - atmosphere_alarm.triggerAlarm(master, alarm_source, severity = danger_level) + atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level) //Check all the alarms before lowering atmosalm. Raising is perfectly fine. - for (var/area/RA in related) - for (var/obj/machinery/alarm/AA in RA) - if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.report_danger_level) - danger_level = max(danger_level, AA.danger_level) + for (var/obj/machinery/alarm/AA in src) + if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.report_danger_level) + danger_level = max(danger_level, AA.danger_level) if(danger_level != atmosalm) if (danger_level < 1 && atmosalm >= 1) @@ -63,17 +51,16 @@ air_doors_close() atmosalm = danger_level - for(var/area/RA in related) - for (var/obj/machinery/alarm/AA in RA) - AA.update_icon() + for (var/obj/machinery/alarm/AA in src) + AA.update_icon() return 1 return 0 /area/proc/air_doors_close() - if(!src.master.air_doors_activated) - src.master.air_doors_activated = 1 - for(var/obj/machinery/door/firedoor/E in src.master.all_doors) + if(!air_doors_activated) + air_doors_activated = 1 + for(var/obj/machinery/door/firedoor/E in all_doors) if(!E.blocked) if(E.operating) E.nextstate = CLOSED @@ -82,9 +69,9 @@ E.close() /area/proc/air_doors_open() - if(src.master.air_doors_activated) - src.master.air_doors_activated = 0 - for(var/obj/machinery/door/firedoor/E in src.master.all_doors) + if(air_doors_activated) + air_doors_activated = 0 + for(var/obj/machinery/door/firedoor/E in all_doors) if(!E.blocked) if(E.operating) E.nextstate = OPEN @@ -95,11 +82,8 @@ /area/proc/fire_alert() if(!fire) - master.fire = 1 //used for firedoor checks - master.updateicon() - for(var/area/A in related) - A.fire = 1 - A.updateicon() + fire = 1 //used for firedoor checks + updateicon() mouse_opacity = 0 for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) @@ -111,11 +95,8 @@ /area/proc/fire_reset() if (fire) - master.fire = 0 //used for firedoor checks - master.updateicon() - for(var/area/A in related) - A.fire = 0 - A.updateicon() + fire = 0 //used for firedoor checks + updateicon() mouse_opacity = 0 for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) @@ -159,7 +140,7 @@ return /area/proc/updateicon() - if ((fire || eject || party) && (!requires_power||power_environ) && !lighting_space)//If it doesn't require power, can still activate this proc. + if ((fire || eject || party) && (!requires_power||power_environ) && !istype(src, /area/space))//If it doesn't require power, can still activate this proc. if(fire && !eject && !party) icon_state = "blue" /*else if(atmosalm && !fire && !eject && !party) @@ -183,56 +164,53 @@ /area/proc/powered(var/chan) // return true if the area has power to given channel - if(!master.requires_power) + if(!requires_power) return 1 - if(master.always_unpowered) + if(always_unpowered) return 0 - if(src.lighting_space) - return 0 // Nope sorry switch(chan) if(EQUIP) - return master.power_equip + return power_equip if(LIGHT) - return master.power_light + return power_light if(ENVIRON) - return master.power_environ + return power_environ return 0 // called when power status changes /area/proc/power_change() - for(var/area/RA in related) - for(var/obj/machinery/M in RA) // for each machine in the area - M.power_change() // reverify power status (to update icons etc.) - if (fire || eject || party) - RA.updateicon() + for(var/obj/machinery/M in src) // for each machine in the area + M.power_change() // reverify power status (to update icons etc.) + if (fire || eject || party) + updateicon() /area/proc/usage(var/chan) var/used = 0 switch(chan) if(LIGHT) - used += master.used_light + used += used_light if(EQUIP) - used += master.used_equip + used += used_equip if(ENVIRON) - used += master.used_environ + used += used_environ if(TOTAL) - used += master.used_light + master.used_equip + master.used_environ + used += used_light + used_equip + used_environ return used /area/proc/clear_usage() - master.used_equip = 0 - master.used_light = 0 - master.used_environ = 0 + used_equip = 0 + used_light = 0 + used_environ = 0 /area/proc/use_power(var/amount, var/chan) switch(chan) if(EQUIP) - master.used_equip += amount + used_equip += amount if(LIGHT) - master.used_light += amount + used_light += amount if(ENVIRON) - master.used_environ += amount + used_environ += amount var/list/mob/living/forced_ambiance_list = new @@ -280,27 +258,23 @@ var/list/mob/living/forced_ambiance_list = new L.client.played = world.time /area/proc/gravitychange(var/gravitystate = 0, var/area/A) - A.has_gravity = gravitystate - for(var/area/SubA in A.related) - SubA.has_gravity = gravitystate - - if(gravitystate) - for(var/mob/living/carbon/human/M in SubA) - thunk(M) - for(var/mob/M1 in SubA) - M1.make_floating(0) - else - for(var/mob/M in SubA) - if(M.Check_Dense_Object() && istype(src,/mob/living/carbon/human/)) - var/mob/living/carbon/human/H = src - if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) //magboots + dense_object = no floaty effect - H.make_floating(0) - else - H.make_floating(1) + if(gravitystate) + for(var/mob/living/carbon/human/M in A) + thunk(M) + for(var/mob/M1 in A) + M1.make_floating(0) + else + for(var/mob/M in A) + if(M.Check_Dense_Object() && istype(src,/mob/living/carbon/human/)) + var/mob/living/carbon/human/H = src + if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) //magboots + dense_object = no floaty effect + H.make_floating(0) else - M.make_floating(1) + H.make_floating(1) + else + M.make_floating(1) /area/proc/thunk(mob) if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. @@ -319,3 +293,10 @@ var/list/mob/living/forced_ambiance_list = new H.AdjustWeakened(1) mob << "The sudden appearance of gravity makes you fall to the floor!" +/area/proc/prison_break() + for(var/obj/machinery/power/apc/temp_apc in src) + temp_apc.overload_lighting(70) + for(var/obj/machinery/door/airlock/temp_airlock in src) + temp_airlock.prison_open() + for(var/obj/machinery/door/window/temp_windoor in src) + temp_windoor.open() \ No newline at end of file diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 8aa6b1cd64e..979db2c1470 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -82,81 +82,3 @@ proc/admin_spawn_room_at_pos() if(x && y && z && wall && floor && x_len && y_len) spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean) return - - - - - - -proc/make_mining_asteroid_secret(var/size = 5) - var/valid = 0 - var/turf/T = null - var/sanity = 0 - var/list/room = null - var/list/turfs = null - - - turfs = get_area_turfs(/area/mine/unexplored) - - if(!turfs.len) - return 0 - - while(!valid) - valid = 1 - sanity++ - if(sanity > 100) - return 0 - - T=pick(turfs) - if(!T) - return 0 - - var/list/surroundings = list() - - surroundings += range(7, locate(T.x,T.y,T.z)) - surroundings += range(7, locate(T.x+size,T.y,T.z)) - surroundings += range(7, locate(T.x,T.y+size,T.z)) - surroundings += range(7, locate(T.x+size,T.y+size,T.z)) - - if(locate(/area/mine/explored) in surroundings) // +5s are for view range - valid = 0 - continue - - if(locate(/turf/space) in surroundings) - valid = 0 - continue - - if(locate(/area/asteroid/artifactroom) in surroundings) - valid = 0 - continue - - if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings) - valid = 0 - continue - - if(!T) - return 0 - - room = spawn_room(T,size,size,,,1) - - if(room) - T = pick(room["floors"]) - if(T) - var/surprise = null - valid = 0 - while(!valid) - surprise = pickweight(space_surprises) - if(surprise in spawned_surprises) - if(prob(20)) - valid++ - else - continue - else - valid++ - - spawned_surprises.Add(surprise) - new surprise(T) - - return 1 - - diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 152622f88e1..e1d2e0b9921 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -11,6 +11,7 @@ var/pass_flags = 0 var/throwpass = 0 var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. + var/simulated = 1 //filter for actions - used by lighting overlays ///Chemistry. var/datum/reagents/reagents = null @@ -22,18 +23,6 @@ //Detective Work, used for the duplicate data points kept in the scanners var/list/original_atom -/atom/Destroy() - . = ..() - density = 0 - SetOpacity(0) - - if(reagents) - qdel(reagents) - reagents = null - for(var/atom/movable/AM in contents) - qdel(AM) - invisibility = 101 - /atom/proc/assume_air(datum/gas_mixture/giver) return null @@ -427,6 +416,8 @@ its easier to just keep the beam vertical. /atom/proc/clean_blood() + if(!simulated) + return src.color = initial(src.color) //paint src.germ_level = 0 if(istype(blood_DNA, /list)) @@ -458,3 +449,46 @@ its easier to just keep the beam vertical. return 1 else return 0 + +// Show a message to all mobs and objects in sight of this atom +// Use for objects performing visible actions +// message is output to anyone who can see, e.g. "The [src] does something!" +// blind_message (optional) is what blind people will hear e.g. "You hear something!" +/atom/proc/visible_message(var/message, var/blind_message) + + var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null) + + for(var/I in see) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 1, blind_message, 2) + else if(ismob(I)) + var/mob/M = I + if(M.see_invisible >= invisibility) // Cannot view the invisible + M.show_message( message, 1, blind_message, 2) + else if (blind_message) + M.show_message(blind_message, 2) + +// Show a message to all mobs and objects in earshot of this atom +// Use for objects performing audible actions +// message is the message output to anyone who can hear. +// deaf_message (optional) is what deaf people will see. +// hearing_distance (optional) is the range, how many tiles away the message can be heard. +/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance) + + var/range = world.view + if(hearing_distance) + range = hearing_distance + var/list/hear = get_mobs_or_objects_in_view(range,src) + + for(var/I in hear) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 2, deaf_message, 1) + else if(ismob(I)) + var/mob/M = I + M.show_message( message, 2, deaf_message, 1) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index b8b8bbb9f63..ff93e692989 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -30,14 +30,16 @@ ..() /atom/movable/Destroy() - if(opacity) - if(isturf(loc)) - if(loc:lighting_lumcount > 1) - UpdateAffectingLights() + . = ..() + if(reagents) + qdel(reagents) + for(var/atom/movable/AM in contents) + qdel(AM) loc = null - - ..() - + if (pulledby) + if (pulledby.pulling == src) + pulledby.pulling = null + pulledby = null /atom/movable/proc/initialize() return @@ -215,4 +217,52 @@ /atom/movable/overlay/attack_hand(a, b, c) if (src.master) return src.master.attack_hand(a, b, c) - return \ No newline at end of file + return + +/atom/movable/proc/touch_map_edge() + if(z in config.sealed_levels) + return + + if(config.use_overmap) + overmap_spacetravel(get_turf(src), src) + return + + var/move_to_z = src.get_transit_zlevel() + if(move_to_z) + z = move_to_z + + if(x <= TRANSITIONEDGE) + x = world.maxx - TRANSITIONEDGE - 2 + y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (x >= (world.maxx - TRANSITIONEDGE - 1)) + x = TRANSITIONEDGE + 1 + y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (y <= TRANSITIONEDGE) + y = world.maxy - TRANSITIONEDGE -2 + x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + else if (y >= (world.maxy - TRANSITIONEDGE - 1)) + y = TRANSITIONEDGE + 1 + x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + if(ticker && istype(ticker.mode, /datum/game_mode/nuclear)) //only really care if the game mode is nuclear + var/datum/game_mode/nuclear/G = ticker.mode + G.check_nuke_disks() + + spawn(0) + if(loc) loc.Entered(src) + +//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there. +var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "6" = 60) + +//by default, transition randomly to another zlevel +/atom/movable/proc/get_transit_zlevel() + var/list/candidates = accessible_z_levels.Copy() + candidates.Remove("[src.z]") + + if(!candidates.len) + return null + return text2num(pickweight(candidates)) + diff --git a/code/game/base_turf.dm b/code/game/base_turf.dm new file mode 100644 index 00000000000..d6940e0275a --- /dev/null +++ b/code/game/base_turf.dm @@ -0,0 +1,27 @@ +// Returns the lowest turf available on a given Z-level, defaults to space. +var/global/list/base_turf_by_z = list( + "5" = /turf/simulated/floor/plating/airless/asteroid // Moonbase. + ) + +proc/get_base_turf(var/z) + if(!base_turf_by_z["[z]"]) + base_turf_by_z["[z]"] = /turf/space + return base_turf_by_z["[z]"] + +/client/proc/set_base_turf() + set category = "Debug" + set name = "Set Base Turf" + set desc = "Set the base turf for a z-level." + + if(!holder) return + + var/choice = input("Which Z-level do you wish to set the base turf for?") as num|null + if(!choice) + return + + var/new_base_path = input("Please select a turf path (cancel to reset to /turf/space).") as null|anything in typesof(/turf) + if(!new_base_path) + new_base_path = /turf/space + base_turf_by_z["[choice]"] = new_base_path + message_admins("[key_name_admin(usr)] has set the base turf for z-level [choice] to [get_base_turf(choice)].") + log_admin("[key_name(usr)] has set the base turf for z-level [choice] to [get_base_turf(choice)].") \ No newline at end of file diff --git a/code/game/dna/dna_misc.dm b/code/game/dna/dna_misc.dm index cdc737c0076..3862bd474fc 100644 --- a/code/game/dna/dna_misc.dm +++ b/code/game/dna/dna_misc.dm @@ -290,60 +290,60 @@ if(ismuton(NOBREATHBLOCK,M)) if(probinj(45,inj) || (mNobreath in old_mutations)) - M << "\blue You feel no need to breathe." + M << "You feel no need to breathe." M.mutations.Add(mNobreath) if(ismuton(REMOTEVIEWBLOCK,M)) if(probinj(45,inj) || (mRemote in old_mutations)) - M << "\blue Your mind expands" + M << "Your mind expands." M.mutations.Add(mRemote) if(ismuton(REGENERATEBLOCK,M)) if(probinj(45,inj) || (mRegen in old_mutations)) - M << "\blue You feel strange" + M << "You feel strange." M.mutations.Add(mRegen) if(ismuton(INCREASERUNBLOCK,M)) if(probinj(45,inj) || (mRun in old_mutations)) - M << "\blue You feel quick" + M << "You feel quick." M.mutations.Add(mRun) if(ismuton(REMOTETALKBLOCK,M)) if(probinj(45,inj) || (mRemotetalk in old_mutations)) - M << "\blue You expand your mind outwards" + M << "You expand your mind outwards." M.mutations.Add(mRemotetalk) if(ismuton(MORPHBLOCK,M)) if(probinj(45,inj) || (mMorph in old_mutations)) M.mutations.Add(mMorph) - M << "\blue Your skin feels strange" + M << "Your skin feels strange." if(ismuton(BLENDBLOCK,M)) if(probinj(45,inj) || (mBlend in old_mutations)) M.mutations.Add(mBlend) - M << "\blue You feel alone" + M << "You feel alone." if(ismuton(HALLUCINATIONBLOCK,M)) if(probinj(45,inj) || (mHallucination in old_mutations)) M.mutations.Add(mHallucination) - M << "\blue Your mind says 'Hello'" + M << "Your mind says 'Hello'." if(ismuton(NOPRINTSBLOCK,M)) if(probinj(45,inj) || (mFingerprints in old_mutations)) M.mutations.Add(mFingerprints) - M << "\blue Your fingers feel numb" + M << "Your fingers feel numb." if(ismuton(SHOCKIMMUNITYBLOCK,M)) if(probinj(45,inj) || (mShock in old_mutations)) M.mutations.Add(mShock) - M << "\blue You feel strange" + M << "You feel strange." if(ismuton(SMALLSIZEBLOCK,M)) if(probinj(45,inj) || (mSmallsize in old_mutations)) - M << "\blue Your skin feels rubbery" + M << "Your skin feels rubbery." M.mutations.Add(mSmallsize) if (isblockon(getblock(M.dna.struc_enzymes, HULKBLOCK,3),HULKBLOCK)) if(probinj(5,inj) || (HULK in old_mutations)) - M << "\blue Your muscles hurt." + M << "Your muscles hurt." M.mutations.Add(HULK) if (isblockon(getblock(M.dna.struc_enzymes, HEADACHEBLOCK,3),HEADACHEBLOCK)) M.disabilities |= EPILEPSY - M << "\red You get a headache." + M << "You get a headache." if (isblockon(getblock(M.dna.struc_enzymes, FAKEBLOCK,3),FAKEBLOCK)) - M << "\red You feel strange." + M << "You feel strange." if (prob(95)) if(prob(50)) randmutb(M) @@ -353,41 +353,41 @@ randmutg(M) if (isblockon(getblock(M.dna.struc_enzymes, COUGHBLOCK,3),COUGHBLOCK)) M.disabilities |= COUGHING - M << "\red You start coughing." + M << "You start coughing." if (isblockon(getblock(M.dna.struc_enzymes, CLUMSYBLOCK,3),CLUMSYBLOCK)) - M << "\red You feel lightheaded." + M << "You feel lightheaded." M.mutations.Add(CLUMSY) if (isblockon(getblock(M.dna.struc_enzymes, TWITCHBLOCK,3),TWITCHBLOCK)) M.disabilities |= TOURETTES - M << "\red You twitch." + M << "You twitch." if (isblockon(getblock(M.dna.struc_enzymes, XRAYBLOCK,3),XRAYBLOCK)) if(probinj(30,inj) || (XRAY in old_mutations)) - M << "\blue The walls suddenly disappear." + M << "The walls suddenly disappear." // M.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) // M.see_in_dark = 8 // M.see_invisible = 2 M.mutations.Add(XRAY) if (isblockon(getblock(M.dna.struc_enzymes, NERVOUSBLOCK,3),NERVOUSBLOCK)) M.disabilities |= NERVOUS - M << "\red You feel nervous." + M << "You feel nervous." if (isblockon(getblock(M.dna.struc_enzymes, FIREBLOCK,3),FIREBLOCK)) if(probinj(30,inj) || (COLD_RESISTANCE in old_mutations)) - M << "\blue Your body feels warm." + M << "Your body feels warm." M.mutations.Add(COLD_RESISTANCE) if (isblockon(getblock(M.dna.struc_enzymes, BLINDBLOCK,3),BLINDBLOCK)) M.sdisabilities |= BLIND - M << "\red You can't seem to see anything." + M << "You can't seem to see anything." if (isblockon(getblock(M.dna.struc_enzymes, TELEBLOCK,3),TELEBLOCK)) if(probinj(15,inj) || (TK in old_mutations)) - M << "\blue You feel smarter." + M << "You feel smarter." M.mutations.Add(TK) if (isblockon(getblock(M.dna.struc_enzymes, DEAFBLOCK,3),DEAFBLOCK)) M.sdisabilities |= DEAF M.ear_deaf = 1 - M << "\red Its kinda quiet.." + M << "It's kinda quiet.." if (isblockon(getblock(M.dna.struc_enzymes, GLASSESBLOCK,3),GLASSESBLOCK)) M.disabilities |= NEARSIGHTED - M << "Your eyes feel weird..." + M << "Your eyes feel weird..." /* If you want the new mutations to work, UNCOMMENT THIS. if(istype(M, /mob/living/carbon)) @@ -559,4 +559,4 @@ if(M) M.update_icon = 1 //queue a full icon update at next life() call return null -/////////////////////////// DNA MISC-PROCS \ No newline at end of file +/////////////////////////// DNA MISC-PROCS diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 68e1f34f888..120ee88046c 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -103,13 +103,13 @@ if (usr.stat != 0) return if (!ishuman(usr) && !issmall(usr)) //Make sure they're a mob that has dna - usr << "\blue Try as you might, you can not climb up into the scanner." + usr << "Try as you might, you can not climb up into the scanner." return if (src.occupant) - usr << "\blue The scanner is already occupied!" + usr << "The scanner is already occupied!" return if (usr.abiotic()) - usr << "\blue Subject cannot have abiotic items on." + usr << "The subject cannot have abiotic items on." return usr.stop_pulling() usr.client.perspective = EYE_PERSPECTIVE @@ -123,13 +123,13 @@ /obj/machinery/dna_scannernew/attackby(var/obj/item/weapon/item as obj, var/mob/user as mob) if(istype(item, /obj/item/weapon/reagent_containers/glass)) if(beaker) - user << "\red A beaker is already loaded into the machine." + user << "A beaker is already loaded into the machine." return beaker = item user.drop_item() item.loc = src - user.visible_message("[user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!") + user.visible_message("\The [user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!") return else if (!istype(item, /obj/item/weapon/grab)) return @@ -137,10 +137,10 @@ if (!ismob(G.affecting)) return if (src.occupant) - user << "\blue The scanner is already occupied!" + user << "The scanner is already occupied!" return if (G.affecting.abiotic()) - user << "\blue Subject cannot have abiotic items on." + user << "The subject cannot have abiotic items on." return put_in(G.affecting) src.add_fingerprint(user) @@ -598,8 +598,7 @@ inject_amount = 0 if (inject_amount > 50) inject_amount = 50 - connected.beaker.reagents.trans_to(connected.occupant, inject_amount) - connected.beaker.reagents.reaction(connected.occupant) + connected.beaker.reagents.trans_to_mob(connected.occupant, inject_amount, CHEM_BLOOD) return 1 // return 1 forces an update to all Nano uis attached to src //////////////////////////////////////////////////////// diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index 4f78d7f70fe..72a571abf83 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -35,7 +35,7 @@ if(sdisability) M.sdisabilities|=sdisability if(activation_message) - M << "\red [activation_message]" + M << "[activation_message]" else testing("[name] has no activation message.") @@ -47,7 +47,7 @@ if(sdisability) M.sdisabilities &= (~sdisability) if(deactivation_message) - M << "\red [deactivation_message]" + M << "[deactivation_message]" else testing("[name] has no deactivation message.") diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index 21eec348bdf..3e18696f6b0 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -113,10 +113,10 @@ M.mutations.Add(mutation) if(activation_messages.len) var/msg = pick(activation_messages) - M << "\blue [msg]" + M << "[msg]" /datum/dna/gene/basic/deactivate(var/mob/M) M.mutations.Remove(mutation) if(deactivation_messages.len) var/msg = pick(deactivation_messages) - M << "\red [msg]" \ No newline at end of file + M << "[msg]" diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 3381894f8ac..e6c6b6f4ec9 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -171,7 +171,7 @@ if(M.health <= 25) M.mutations.Remove(HULK) M.update_mutations() //update our mutation overlays - M << "\red You suddenly feel very weak." + M << "You suddenly feel very weak." M.Weaken(3) M.emote("collapse") diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 4afdf6d1472..418ceab13ad 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -42,7 +42,7 @@ var/percent = round( 100.0 * start_state.score(end_state), 0.1) world << "The station is [percent]% intact." log_game("Blob mode was won with station [percent]% intact.") - world << "\blue Rebooting in 30s" + world << "Rebooting in 30s" ..() return 1 diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index 6e9c3d9b686..44486d605b5 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -3,7 +3,7 @@ name = "blob" icon = 'icons/mob/blob.dmi' icon_state = "blob" - luminosity = 3 + light_range = 3 desc = "Some blob creature thingy" density = 1 opacity = 0 diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index a17c030b111..4ae82684020 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -1,5 +1,5 @@ /obj/item/weapon/melee/cultblade - name = "Cult Blade" + name = "cult blade" desc = "An arcane weapon wielded by the followers of Nar-Sie" icon_state = "cultblade" item_state = "cultblade" @@ -17,7 +17,7 @@ return ..() else user.Paralyse(5) - user << "\red An unexplicable force powerfully repels the sword from [target]!" + user << "An unexplicable force powerfully repels the sword from [target]!" var/organ = ((user.hand ? "l_":"r_") + "arm") var/obj/item/organ/external/affecting = user.get_organ(organ) if(affecting.take_damage(rand(force/2, force))) //random amount of damage between half of the blade's force and the full force of the blade. @@ -26,7 +26,7 @@ /obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob) if(!iscultist(user)) - user << "\red An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly." + user << "An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly." user.make_dizzy(120) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 337ad39c0da..d70c181830a 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -22,8 +22,8 @@ desc = "A floating crystal that hums with an unearthly energy" icon_state = "pylon" var/isbroken = 0 - luminosity = 5 - l_color = "#3e0000" + light_range = 5 + light_color = "#3e0000" var/obj/item/wepon = null /obj/structure/cult/pylon/attack_hand(mob/M as mob) @@ -38,16 +38,17 @@ /obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage) if(!isbroken) if(prob(1+ damage * 5)) - user << "You hit the pylon, and its crystal breaks apart!" - for(var/mob/M in viewers(src)) - if(M == user) - continue - M.show_message("[user.name] smashed the pylon!", 3, "You hear a tinkle of crystal shards", 2) + user.visible_message( + "[user] smashed the pylon!", + "You hit the pylon, and its crystal breaks apart!", + "You hear a tinkle of crystal shards" + ) + user.do_attack_animation(src) playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1) isbroken = 1 density = 0 icon_state = "pylon-broken" - SetLuminosity(0) + set_light(0) else user << "You hit the pylon!" playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) @@ -66,13 +67,12 @@ isbroken = 0 density = 1 icon_state = "pylon" - SetLuminosity(5) + set_light(5) /obj/structure/cult/tome name = "Desk" desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl" icon_state = "tomealtar" -// luminosity = 5 //sprites for this no longer exist -Pete //(they were stolen from another game anyway) @@ -105,8 +105,8 @@ return /obj/effect/gateway/active - luminosity=5 - l_color="#ff0000" + light_range=5 + light_color="#ff0000" spawnable=list( /mob/living/simple_animal/hostile/scarybat, /mob/living/simple_animal/hostile/creature, @@ -114,8 +114,8 @@ ) /obj/effect/gateway/active/cult - luminosity=5 - l_color="#ff0000" + light_range=5 + light_color="#ff0000" spawnable=list( /mob/living/simple_animal/hostile/scarybat/cult, /mob/living/simple_animal/hostile/creature/cult, diff --git a/code/game/gamemodes/cult/cultify/mob.dm b/code/game/gamemodes/cult/cultify/mob.dm index 965d2548f75..154078de3d6 100644 --- a/code/game/gamemodes/cult/cultify/mob.dm +++ b/code/game/gamemodes/cult/cultify/mob.dm @@ -43,7 +43,7 @@ narsimage = image('icons/obj/narsie.dmi',src.loc,"narsie",9,1) narsimage.mouse_opacity = 0 if(!narglow) //Create narglow - narglow = image('icons/obj/narsie.dmi',narsimage.loc,"glow-narsie",LIGHTING_LAYER+2,1) + narglow = image('icons/obj/narsie.dmi',narsimage.loc,"glow-narsie",12,1) narglow.mouse_opacity = 0 //Else if no dir is given, simply send them the image of narsie var/new_x = 32 * (N.x - src.x) + N.pixel_x diff --git a/code/game/gamemodes/cult/cultify/obj.dm b/code/game/gamemodes/cult/cultify/obj.dm index 630877eb114..4306182eaf4 100644 --- a/code/game/gamemodes/cult/cultify/obj.dm +++ b/code/game/gamemodes/cult/cultify/obj.dm @@ -14,14 +14,14 @@ new /obj/structure/cult/pylon(loc) ..() -/obj/item/stack/sheet/wood/cultify() +/obj/item/stack/material/wood/cultify() return /obj/item/weapon/book/cultify() new /obj/item/weapon/book/tome(loc) ..() -/obj/item/weapon/claymore/cultify() +/obj/item/weapon/material/sword/cultify() new /obj/item/weapon/melee/cultblade(loc) ..() @@ -32,13 +32,6 @@ /obj/item/weapon/storage/backpack/cultpack/cultify() return -/obj/item/weapon/table_parts/cultify() - new /obj/item/weapon/table_parts/wood(loc) - ..() - -/obj/item/weapon/table_parts/wood/cultify() - return - /obj/machinery/cultify() // We keep the number of cultified machines down by only converting those that are dense // The alternative is to keep a separate file of exceptions. @@ -66,7 +59,7 @@ qdel(src) /obj/machinery/door/airlock/external/cultify() - new /obj/structure/mineral_door/wood(loc) + new /obj/structure/simple_door/wood(loc) ..() /obj/machinery/door/cultify() @@ -121,11 +114,11 @@ /obj/structure/grille/cult/cultify() return -/obj/structure/mineral_door/cultify() - new /obj/structure/mineral_door/wood(loc) +/obj/structure/simple_door/cultify() + new /obj/structure/simple_door/wood(loc) ..() -/obj/structure/mineral_door/wood/cultify() +/obj/structure/simple_door/wood/cultify() return /obj/singularity/cultify() @@ -149,8 +142,12 @@ ..() /obj/structure/table/cultify() - new /obj/structure/table/woodentable(loc) - ..() - -/obj/structure/table/woodentable/cultify() - return + // Make it a wood-reinforced wooden table. + // There are cult materials available, but it'd make the table non-deconstructable with how holotables work. + // Could possibly use a new material var for holographic-ness? + material = name_to_material["wood"] + reinforced = name_to_material["wood"] + update_desc() + update_connections(1) + update_icon() + update_material() diff --git a/code/game/gamemodes/cult/cultify/turf.dm b/code/game/gamemodes/cult/cultify/turf.dm index 0005298c423..54fc9631e33 100644 --- a/code/game/gamemodes/cult/cultify/turf.dm +++ b/code/game/gamemodes/cult/cultify/turf.dm @@ -23,6 +23,9 @@ /turf/simulated/wall/cult/cultify() return +/turf/unsimulated/wall/cult/cultify() + return + /turf/unsimulated/beach/cultify() return diff --git a/code/game/gamemodes/cult/hell_universe.dm b/code/game/gamemodes/cult/hell_universe.dm index 39f44023917..e81a6a2673d 100644 --- a/code/game/gamemodes/cult/hell_universe.dm +++ b/code/game/gamemodes/cult/hell_universe.dm @@ -33,53 +33,46 @@ In short: /datum/universal_state/hell/OnTurfChange(var/turf/T) - var/turf/space/spess = T - if(istype(spess)) - spess.overlays += "hell01" + var/turf/space/S = T + if(istype(S)) + S.color = "#FF0000" + else + S.color = initial(S.color) // Apply changes when entering state /datum/universal_state/hell/OnEnter() set background = 1 garbage_collector.garbage_collect = 0 + escape_list = get_area_turfs(locate(/area/hallway/secondary/exit)) //Separated into separate procs for profiling AreaSet() - OverlaySet() MiscSet() APCSet() KillMobs() - AmbientSet() + OverlayAndAmbientSet() runedec += 9000 //basically removing the rune cap -/datum/universal_state/hell/proc/AreaSet() - for(var/area/ca in world) - var/area/A = ca.master - if(!istype(A,/area) || A.name=="Space") - continue - // Reset all alarms. - A.fire = null - A.atmos = 1 - A.atmosalm = 0 - A.poweralm = 1 - A.party = null +/datum/universal_state/hell/proc/AreaSet() + for(var/area/A in all_areas) + if(!istype(A,/area) || istype(A, /area/space)) + continue A.updateicon() -/datum/universal_state/hell/proc/OverlaySet() - var/image/I = image("icon" = 'icons/turf/space.dmi', "icon_state" = "hell01", "layer" = 10) - for(var/turf/space/spess in world) - spess.overlays += I +/datum/universal_state/hell/OverlayAndAmbientSet() + spawn(0) + for(var/atom/movable/lighting_overlay/L in world) + L.update_lumcount(1, 0, 0) -/datum/universal_state/hell/proc/AmbientSet() - for(var/turf/T in world) - if(istype(T, /turf/space)) continue - T.update_lumcount(1, 255, 0, 0, 0) + for(var/turf/space/T in turfs) + OnTurfChange(T) /datum/universal_state/hell/proc/MiscSet() - for(var/turf/simulated/floor/T in world) + for(var/turf/simulated/floor/T in turfs) if(!T.holy && prob(1)) new /obj/effect/gateway/active/cult(T) @@ -89,7 +82,7 @@ In short: /datum/universal_state/hell/proc/APCSet() for (var/obj/machinery/power/apc/APC in machines) - if (!(APC.stat & BROKEN) && !istype(APC.area,/area/turret_protected/ai)) + if (!(APC.stat & BROKEN) && !APC.is_critical) APC.chargemode = 0 if(APC.cell) APC.cell.charge = 0 diff --git a/code/modules/power/singularity/narsie.dm b/code/game/gamemodes/cult/narsie.dm similarity index 88% rename from code/modules/power/singularity/narsie.dm rename to code/game/gamemodes/cult/narsie.dm index 50093c440b5..4a129741174 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/game/gamemodes/cult/narsie.dm @@ -1,4 +1,5 @@ var/global/narsie_behaviour = "CultStation13" +var/global/narsie_cometh = 0 var/global/list/narsie_list = list() /obj/singularity/narsie //Moving narsie to its own file for the sake of being clearer name = "Nar-Sie" @@ -31,13 +32,13 @@ var/global/list/narsie_list = list() // Pixel stuff centers Narsie. pixel_x = -236 pixel_y = -256 - luminosity = 1 - l_color = "#3e0000" + light_range = 1 + light_color = "#3e0000" current_size = 12 consume_range = 12 // How many tiles out do we eat. var/announce=1 - var/narnar = 1 + var/cause_hell = 1 /obj/singularity/narsie/large/New() ..() @@ -47,13 +48,15 @@ var/global/list/narsie_list = list() narsie_spawn_animation() - if(narnar) - SetUniversalState(/datum/universal_state/hell) + if(!narsie_cometh)//so we don't initiate Hell more than one time. + if(cause_hell) + SetUniversalState(/datum/universal_state/hell) + narsie_cometh = 1 - spawn(10 SECONDS) - if(emergency_shuttle && emergency_shuttle.can_call()) - emergency_shuttle.call_evac() - emergency_shuttle.launch_time = 0 // Cannot recall + spawn(10 SECONDS) + if(emergency_shuttle) + emergency_shuttle.call_evac() + emergency_shuttle.launch_time = 0 // Cannot recall /obj/singularity/narsie/process() eat() @@ -67,8 +70,6 @@ var/global/list/narsie_list = list() mezzer() /obj/singularity/narsie/large/eat() - set background = BACKGROUND_ENABLED - for (var/turf/A in orange(consume_range, src)) consume(A) @@ -83,14 +84,14 @@ var/global/list/narsie_list = list() /obj/singularity/narsie/large/Bump(atom/A) - if(!narnar) return + if(!cause_hell) return if(isturf(A)) narsiewall(A) else if(istype(A, /obj/structure/cult)) qdel(A) /obj/singularity/narsie/large/Bumped(atom/A) - if(!narnar) return + if(!cause_hell) return if(isturf(A)) narsiewall(A) else if(istype(A, /obj/structure/cult)) @@ -144,7 +145,7 @@ var/global/list/narsie_list = list() if(T.icon_state != "cult-narsie") T.desc = "something that goes beyond your understanding went this way" T.icon_state = "cult-narsie" - T.luminosity = 1 + T.set_light(1) /obj/singularity/narsie/proc/narsiewall(var/turf/T) T.desc = "An opening has been made on that wall, but who can say if what you seek truly lies on the other side?" @@ -152,7 +153,7 @@ var/global/list/narsie_list = list() T.icon_state = "cult-narsie" T.opacity = 0 T.density = 0 - luminosity = 1 + set_light(1) /obj/singularity/narsie/large/consume(const/atom/A) //Has its own consume proc because it doesn't need energy and I don't want BoHs to explode it. --NEO //NEW BEHAVIOUR @@ -221,9 +222,9 @@ var/global/list/narsie_list = list() consume(AM2) continue - if (dist <= consume_range && !istype(A, /turf/space)) + if (dist <= consume_range && !istype(A, get_base_turf(A.z))) var/turf/T2 = A - T2.ChangeTurf(/turf/space) + T2.ChangeTurf(get_base_turf(A.z)) /obj/singularity/narsie/consume(const/atom/A) //This one is for the small ones. if(!(A.singuloCanEat())) @@ -263,9 +264,9 @@ var/global/list/narsie_list = list() spawn (0) AM2.singularity_pull(src, src.current_size) - if (dist <= consume_range && !istype(A, /turf/space)) + if (dist <= consume_range && !istype(A, get_base_turf(A.z))) var/turf/T2 = A - T2.ChangeTurf(/turf/space) + T2.ChangeTurf(get_base_turf(A.z)) /obj/singularity/narsie/ex_act(severity) //No throwing bombs at it either. --NEO return @@ -352,8 +353,6 @@ var/global/list/narsie_list = list() grav_pull = 0 /obj/singularity/narsie/wizard/eat() - set background = BACKGROUND_ENABLED - for (var/turf/T in trange(consume_range, src)) consume(T) diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 8a55a811654..dc09e0edb92 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -95,7 +95,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," qdel(src) return else if(istype(I, /obj/item/weapon/nullrod)) - user << "\blue You disrupt the vile magic with the deadening field of the null rod!" + user << "You disrupt the vile magic with the deadening field of the null rod!" qdel(src) return return @@ -171,7 +171,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," else usr.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) for (var/mob/V in viewers(src)) - V.show_message("\red The markings pulse with a small burst of light, then fall dark.", 3, "\red You hear a faint fizzle.", 2) + V.show_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2) return check_icon() @@ -355,8 +355,8 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," return M.take_organ_damage(0,rand(5,20)) //really lucky - 5 hits for a crit for(var/mob/O in viewers(M, null)) - O.show_message(text("\red [] beats [] with the arcane tome!", user, M), 1) - M << "\red You feel searing heat inside!" + O.show_message("\The [user] beats \the [M] with \the [src]!", 1) + M << "You feel searing heat inside!" attack_self(mob/living/user as mob) @@ -371,7 +371,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," for(var/obj/effect/rune/N in world) C++ if (!istype(user.loc,/turf)) - user << "\red You do not have enough space to write a proper rune." + user << "You do not have enough space to write a proper rune." return if (C>=26 + runedec + cult.current_antagonists.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist @@ -455,7 +455,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," if (!chosen_rune) return if (chosen_rune == "none") - user << "\red You decide against scribing a rune, perhaps you should take this time to study your notes." + user << "You decide against scribing a rune, perhaps you should take this time to study your notes." return if (chosen_rune == "teleport") dictionary[chosen_rune] += input ("Choose a destination word") in english @@ -466,8 +466,8 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," return for (var/mob/V in viewers(src)) - V.show_message("\red [user] slices open a finger and begins to chant and paint symbols on the floor.", 3, "\red You hear chanting.", 2) - user << "\red You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world." + V.show_message("\The [user] slices open a finger and begins to chant and paint symbols on the floor.", 3, "You hear chanting.", 2) + user << "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world." user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage if(do_after(user, 50)) var/area/A = get_area(user) @@ -476,7 +476,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," return var/mob/living/carbon/human/H = user var/obj/effect/rune/R = new /obj/effect/rune(user.loc) - user << "\red You finish drawing the arcane markings of the Geometer." + user << "You finish drawing the arcane markings of the Geometer." var/list/required = dictionary[chosen_rune] R.word1 = english[required[1]] R.word2 = english[required[2]] @@ -524,7 +524,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," if(user) var/r if (!istype(user.loc,/turf)) - user << "\red You do not have enough space to write a proper rune." + user << "You do not have enough space to write a proper rune." var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun") r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. var/obj/effect/rune/R = new /obj/effect/rune diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 5599be46862..ff5b7ff8806 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -21,7 +21,7 @@ var/list/sacrificed = list() allrunesloc.len = index allrunesloc[index] = R.loc if(index >= 5) - user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" + user << "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" if (istype(user, /mob/living)) user.take_overall_damage(5, 0) qdel(src) @@ -30,9 +30,9 @@ var/list/sacrificed = list() user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting else user.whisper("Sas[pick("'","`")]so c'arta forbici!") - user.visible_message("\red [user] disappears in a flash of red light!", \ - "\red You feel as your body gets dragged through the dimension of Nar-Sie!", \ - "\red You hear a sickening crunch and sloshing of viscera.") + user.visible_message("\The [user] disappears in a flash of red light!", \ + "You feel as your body gets dragged through the dimension of Nar-Sie!", \ + "You hear a sickening crunch and sloshing of viscera.") user.loc = allrunesloc[rand(1,index)] return if(istype(src,/obj/effect/rune)) @@ -58,7 +58,7 @@ var/list/sacrificed = list() IP = R runecount++ if(runecount >= 2) - user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" + user << "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" if (istype(user, /mob/living)) user.take_overall_damage(5, 0) qdel(src) @@ -67,9 +67,9 @@ var/list/sacrificed = list() culcount++ if(culcount>=3) user.say("Sas[pick("'","`")]so c'arta forbici tarem!") - user.visible_message("\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "\red You smell ozone.") + user.visible_message("You feel air moving from the rune - like as it was swapped with somewhere else.", \ + "You feel air moving from the rune - like as it was swapped with somewhere else.", \ + "You smell ozone.") for(var/obj/O in src.loc) if(!O.anchored) O.loc = IP.loc @@ -87,9 +87,9 @@ var/list/sacrificed = list() usr.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") else usr.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") - usr.visible_message("\red Rune disappears with a flash of red light, and in its place now a book lies.", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ - "\red You hear a pop and smell ozone.") + usr.visible_message("Rune disappears with a flash of red light, and in its place now a book lies.", \ + "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ + "You hear a pop and smell ozone.") if(istype(src,/obj/effect/rune)) new /obj/item/weapon/book/tome(src.loc) else @@ -127,6 +127,7 @@ var/list/sacrificed = list() if(target.getFireLoss() < 100) target.hallucination = min(target.hallucination, 500) return 0 + target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects // Resist messages go! if(initial_message) //don't do this stuff right away, only if they resist or hesitate. @@ -156,7 +157,7 @@ var/list/sacrificed = list() if (target.species && (target.species.flags & NO_PAIN)) target.visible_message("The markings below [target] glow a bloody red.") else - target.visible_message("[target] writhes in pain as the markings below \him glow a bloody red.", "AAAAAAHHHH!", "You hear an anguished scream.") + target.visible_message("\The [target] writhes in pain as the markings below \him glow a bloody red.", "AAAAAAHHHH!", "You hear an anguished scream.") if(!waiting_for_input[target]) //so we don't spam them with dialogs if they hesitate waiting_for_input[target] = 1 @@ -222,22 +223,22 @@ var/list/sacrificed = list() if(D.stat!=2) admin_attack_log(usr, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on") var/bdrain = rand(1,25) - D << "\red You feel weakened." + D << "You feel weakened." D.take_overall_damage(bdrain, 0) drain += bdrain if(!drain) return fizzle() usr.say ("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!") - usr.visible_message("\red Blood flows from the rune into [usr]!", \ - "\red The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \ - "\red You hear a liquid flowing.") + usr.visible_message("Blood flows from the rune into [usr]!", \ + "The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \ + "You hear a liquid flowing.") var/mob/living/user = usr if(user.bhunger) user.bhunger = max(user.bhunger-2*drain,0) if(drain>=50) - user.visible_message("\red [user]'s eyes give off eerie red glow!", \ - "\red ...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ - "\red You hear a heartbeat.") + user.visible_message("\The [user]'s eyes give off eerie red glow!", \ + "...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ + "You hear a heartbeat.") user.bhunger += drain src = user spawn() @@ -263,16 +264,16 @@ var/list/sacrificed = list() if(usr.loc==src.loc) if(usr.seer==1) usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium viortia.") - usr << "\red The world beyond fades from your vision." + usr << "The world beyond fades from your vision." usr.see_invisible = SEE_INVISIBLE_LIVING usr.seer = 0 else if(usr.see_invisible!=SEE_INVISIBLE_LIVING) - usr << "\red The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision." + usr << "The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision." usr.see_invisible = SEE_INVISIBLE_CULT usr.seer = 0 else usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") - usr << "\red The world beyond opens to your eyes." + usr << "The world beyond opens to your eyes." usr.see_invisible = SEE_INVISIBLE_CULT usr.seer = 1 return @@ -296,7 +297,7 @@ var/list/sacrificed = list() break if(!corpse_to_raise) if(is_sacrifice_target) - usr << "\red The Geometer of blood wants this mortal for himself." + usr << "The Geometer of blood wants this mortal for himself." return fizzle() @@ -314,9 +315,9 @@ var/list/sacrificed = list() if(!body_to_sacrifice) if (is_sacrifice_target) - usr << "\red The Geometer of Blood wants that corpse for himself." + usr << "The Geometer of Blood wants that corpse for himself." else - usr << "\red The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used." + usr << "The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used." return fizzle() var/mob/dead/observer/ghost @@ -327,7 +328,7 @@ var/list/sacrificed = list() break if(!ghost) - usr << "\red You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie." + usr << "You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie." return fizzle() corpse_to_raise.revive() @@ -335,12 +336,12 @@ var/list/sacrificed = list() corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) //This means, should that player leave the body, the original may re-enter usr.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") - corpse_to_raise.visible_message("\red [corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \ - "\red Life... I'm alive again...", \ - "\red You hear a faint, slightly familiar whisper.") - body_to_sacrifice.visible_message("\red [body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from his remains!", \ - "\red You feel as your blood boils, tearing you apart.", \ - "\red You hear a thousand voices, all crying in pain.") + corpse_to_raise.visible_message("\The [corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \ + "Life... I'm alive again...", \ + "You hear a faint, slightly familiar whisper.") + body_to_sacrifice.visible_message("\The [body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from his remains!", \ + "You feel as your blood boils, tearing you apart.", \ + "You hear a thousand voices, all crying in pain.") body_to_sacrifice.gib() // if(ticker.mode.name == "cult") @@ -368,14 +369,14 @@ var/list/sacrificed = list() if(istype(src,/obj/effect/rune)) usr.say("Kla[pick("'","`")]atu barada nikt'o!") for (var/mob/V in viewers(src)) - V.show_message("\red The rune turns into gray dust, veiling the surrounding runes.", 3) + V.show_message("The rune turns into gray dust, veiling the surrounding runes.", 3) qdel(src) else usr.whisper("Kla[pick("'","`")]atu barada nikt'o!") - usr << "\red Your talisman turns into gray dust, veiling the surrounding runes." + usr << "Your talisman turns into gray dust, veiling the surrounding runes." for (var/mob/V in orange(1,src)) if(V!=usr) - V.show_message("\red Dust emanates from [usr]'s hands for a moment.", 3) + V.show_message("Dust emanates from [usr]'s hands for a moment.", 3) return if(istype(src,/obj/effect/rune)) @@ -390,9 +391,9 @@ var/list/sacrificed = list() if(usr.loc==src.loc) var/mob/living/carbon/human/L = usr usr.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!") - usr.visible_message("\red [usr]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ - "\red The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ - "\red You hear only complete silence for a moment.") + usr.visible_message("\The [usr]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ + "The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ + "You hear only complete silence for a moment.") announce_ghost_joinleave(usr.ghostize(1), 1, "You feel that they had to use some [pick("dark", "black", "blood", "forgotten", "forbidden")] magic to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place!") L.ajourn = 1 while(L) @@ -417,6 +418,7 @@ var/list/sacrificed = list() var/mob/dead/observer/ghost for(var/mob/dead/observer/O in this_rune.loc) if(!O.client) continue + if(!O.MayRespawn()) continue if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue ghost = O break @@ -427,9 +429,9 @@ var/list/sacrificed = list() usr.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") var/mob/living/carbon/human/dummy/D = new(this_rune.loc) - usr.visible_message("\red A shape forms in the center of the rune. A shape of... a man.", \ - "\red A shape forms in the center of the rune. A shape of... a man.", \ - "\red You hear liquid flowing.") + usr.visible_message("A shape forms in the center of the rune. A shape of... a man.", \ + "A shape forms in the center of the rune. A shape of... a man.", \ + "You hear liquid flowing.") D.real_name = "Unknown" var/chose_name = 0 for(var/obj/item/weapon/paper/P in this_rune.loc) @@ -459,9 +461,9 @@ var/list/sacrificed = list() user.take_organ_damage(1, 0) sleep(30) if(D) - D.visible_message("\red [D] slowly dissipates into dust and bones.", \ - "\red You feel pain, as bonds formed between your soul and this homunculus break.", \ - "\red You hear faint rustle.") + D.visible_message("\The [D] slowly dissipates into dust and bones.", \ + "You feel pain, as bonds formed between your soul and this homunculus break.", \ + "You hear faint rustle.") D.dust() return @@ -482,7 +484,7 @@ var/list/sacrificed = list() unsuitable_newtalisman = 1 if (!newtalisman) if (unsuitable_newtalisman) - usr << "\red The blank is tainted. It is unsuitable." + usr << "The blank is tainted. It is unsuitable." return fizzle() var/obj/effect/rune/imbued_from @@ -543,7 +545,7 @@ var/list/sacrificed = list() break if (imbued_from) for (var/mob/V in viewers(src)) - V.show_message("\red The runes turn into dust, which then forms into an arcane image on the paper.", 3) + V.show_message("The runes turn into dust, which then forms into an arcane image on the paper.", 3) usr.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") qdel(imbued_from) qdel(newtalisman) @@ -558,9 +560,9 @@ var/list/sacrificed = list() user.say("Uhrast ka'hfa heldsagen ver[pick("'","`")]lot!") user.take_overall_damage(200, 0) runedec+=10 - user.visible_message("\red [user] keels over dead, his blood glowing blue as it escapes his body and dissipates into thin air.", \ - "\red In the last moment of your humble life, you feel an immense pain as fabric of reality mends... with your blood.", \ - "\red You hear faint rustle.") + user.visible_message("\The [user] keels over dead, his blood glowing blue as it escapes his body and dissipates into thin air.", \ + "In the last moment of your humble life, you feel an immense pain as fabric of reality mends... with your blood.", \ + "You hear faint rustle.") for(,user.stat==2) sleep(600) if (!user) @@ -592,7 +594,7 @@ var/list/sacrificed = list() input = sanitize(input) for(var/datum/mind/H in cult.current_antagonists) if (H.current) - H.current << "\red \b [input]" + H.current << "[input]" qdel(src) return 1 @@ -636,44 +638,44 @@ var/list/sacrificed = list() H.dust()//To prevent the MMI from remaining else H.gib() - usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." + usr << "The Geometer of Blood accepts this sacrifice, your objective is now complete." else - usr << "\red Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." + usr << "Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." else if(cultsinrange.len >= 3) if(H.stat !=2) if(prob(80) || worth) - usr << "\red The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice." + usr << "The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, this soul was not enough to gain His favor." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, this soul was not enough to gain His favor." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else H.gib() else if(prob(40) || worth) - usr << "\red The Geometer of blood accepts this [worth ? "exotic " : ""]sacrifice." + usr << "The Geometer of blood accepts this [worth ? "exotic " : ""]sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, a mere dead body is not enough to satisfy Him." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else H.gib() else if(H.stat !=2) - usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." + usr << "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." else if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." + usr << "The Geometer of blood accepts this sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, a mere dead body is not enough to satisfy Him." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else @@ -682,36 +684,36 @@ var/list/sacrificed = list() if(cultsinrange.len >= 3) if(H.stat !=2) if(prob(80)) - usr << "\red The Geometer of Blood accepts this sacrifice." + usr << "The Geometer of Blood accepts this sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, this soul was not enough to gain His favor." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, this soul was not enough to gain His favor." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else H.gib() else if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." + usr << "The Geometer of blood accepts this sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, a mere dead body is not enough to satisfy Him." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else H.gib() else if(H.stat !=2) - usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." + usr << "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." else if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." + usr << "The Geometer of blood accepts this sacrifice." cult.grant_runeword(usr) else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." + usr << "The Geometer of blood accepts this sacrifice." + usr << "However, a mere dead body is not enough to satisfy Him." if(isrobot(H)) H.dust()//To prevent the MMI from remaining else @@ -739,20 +741,20 @@ var/list/sacrificed = list() S=1 if(S) if(istype(W,/obj/item/weapon/nullrod)) - usr << "\red Arcane markings suddenly glow from underneath a thin layer of dust!" + usr << "Arcane markings suddenly glow from underneath a thin layer of dust!" return if(istype(W,/obj/effect/rune)) usr.say("Nikt[pick("'","`")]o barada kla'atu!") for (var/mob/V in viewers(src)) - V.show_message("\red The rune turns into red dust, reveaing the surrounding runes.", 3) + V.show_message("The rune turns into red dust, reveaing the surrounding runes.", 3) qdel(src) return if(istype(W,/obj/item/weapon/paper/talisman)) usr.whisper("Nikt[pick("'","`")]o barada kla'atu!") - usr << "\red Your talisman turns into red dust, revealing the surrounding runes." + usr << "Your talisman turns into red dust, revealing the surrounding runes." for (var/mob/V in orange(1,usr.loc)) if(V!=usr) - V.show_message("\red Red dust emanates from [usr]'s hands for a moment.", 3) + V.show_message("Red dust emanates from [usr]'s hands for a moment.", 3) return return if(istype(W,/obj/effect/rune)) @@ -769,9 +771,9 @@ var/list/sacrificed = list() var/mob/living/user = usr user.take_organ_damage(2, 0) if(src.density) - usr << "\red Your blood flows into the rune, and you feel that the very space over the rune thickens." + usr << "Your blood flows into the rune, and you feel that the very space over the rune thickens." else - usr << "\red Your blood flows into the rune, and you feel as the rune releases its grasp on space." + usr << "Your blood flows into the rune, and you feel as the rune releases its grasp on space." return /////////////////////////////////////////EIGHTTEENTH RUNE @@ -800,7 +802,7 @@ var/list/sacrificed = list() (istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) || \ (istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) \ )) - user << "\red The [cultist] is already free." + user << "The [cultist] is already free." return cultist.buckled = null if (cultist.handcuffed) @@ -840,7 +842,7 @@ var/list/sacrificed = list() if (cultist == user) //just to be sure. return if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet))) - user << "\red You cannot summon \the [cultist], for his shackles of blood are strong." + user << "You cannot summon \the [cultist], for his shackles of blood are strong." return fizzle() cultist.loc = src.loc cultist.lying = 1 @@ -855,9 +857,9 @@ var/list/sacrificed = list() if(users.len <= 4) // You did the minimum, this is going to hurt more and we're going to stun you. C.apply_effect(rand(3,6), STUN) C.apply_effect(1, WEAKEN) - user.visible_message("\red Rune disappears with a flash of red light, and in its place now a body lies.", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ - "\red You hear a pop and smell ozone.") + user.visible_message("Rune disappears with a flash of red light, and in its place now a body lies.", \ + "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ + "You hear a pop and smell ozone.") qdel(src) return fizzle() @@ -873,13 +875,13 @@ var/list/sacrificed = list() if(N) continue C.ear_deaf += 50 - C.show_message("\red The world around you suddenly becomes quiet.", 3) + C.show_message("The world around you suddenly becomes quiet.", 3) affected += C if(prob(1)) C.sdisabilities |= DEAF if(affected.len) usr.say("Sti[pick("'","`")] kaliedir!") - usr << "\red The world becomes quiet as the deafening rune dissipates into fine dust." + usr << "The world becomes quiet as the deafening rune dissipates into fine dust." admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") qdel(src) else @@ -894,15 +896,15 @@ var/list/sacrificed = list() continue C.ear_deaf += 30 //talismans is weaker. - C.show_message("\red The world around you suddenly becomes quiet.", 3) + C.show_message("The world around you suddenly becomes quiet.", 3) affected += C if(affected.len) usr.whisper("Sti[pick("'","`")] kaliedir!") - usr << "\red Your talisman turns into gray dust, deafening everyone around." + usr << "Your talisman turns into gray dust, deafening everyone around." admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") for (var/mob/V in orange(1,src)) if(!(iscultist(V))) - V.show_message("\red Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3) + V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3) return blind() @@ -920,11 +922,11 @@ var/list/sacrificed = list() C.disabilities |= NEARSIGHTED if(prob(10)) C.sdisabilities |= BLIND - C.show_message("\red Suddenly you see red flash that blinds you.", 3) + C.show_message("Suddenly you see red flash that blinds you.", 3) affected += C if(affected.len) usr.say("Sti[pick("'","`")] kaliesin!") - usr << "\red The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust." + usr << "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust." admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") qdel(src) else @@ -941,10 +943,10 @@ var/list/sacrificed = list() C.eye_blind += 10 //talismans is weaker. affected += C - C.show_message("\red You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) + C.show_message("You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) if(affected.len) usr.whisper("Sti[pick("'","`")] kaliesin!") - usr << "\red Your talisman turns into gray dust, blinding those who not follow the Nar-Sie." + usr << "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie." admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") return @@ -970,7 +972,7 @@ var/list/sacrificed = list() if(N) continue M.take_overall_damage(51,51) - M << "\red Your blood boils!" + M << "Your blood boils!" victims += M if(prob(5)) spawn(5) @@ -1002,16 +1004,16 @@ var/list/sacrificed = list() for(var/mob/living/M in orange(2,R)) M.take_overall_damage(0,15) if (R.invisibility>M.see_invisible) - M << "\red Aargh it burns!" + M << "Aargh it burns!" else - M << "\red Rune suddenly ignites, burning you!" + M << "Rune suddenly ignites, burning you!" var/turf/T = get_turf(R) T.hotspot_expose(700,125) for(var/obj/effect/decal/cleanable/blood/B in world) if(B.blood_DNA == src.blood_DNA) for(var/mob/living/M in orange(1,B)) M.take_overall_damage(0,5) - M << "\red Blood suddenly ignites, burning you!" + M << "Blood suddenly ignites, burning you!" var/turf/T = get_turf(B) T.hotspot_expose(700,125) qdel(B) @@ -1030,13 +1032,13 @@ var/list/sacrificed = list() C.stuttering = 1 C.Weaken(1) C.Stun(1) - C.show_message("\red The rune explodes in a bright flash.", 3) + C.show_message("The rune explodes in a bright flash.", 3) admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") else if(issilicon(L)) var/mob/living/silicon/S = L S.Weaken(5) - S.show_message("\red BZZZT... The rune has exploded in a bright flash.", 3) + S.show_message("BZZZT... The rune has exploded in a bright flash.", 3) admin_attack_log(usr, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") qdel(src) else ///When invoked as talisman, stun and mute the target mob. @@ -1044,10 +1046,10 @@ var/list/sacrificed = list() var/obj/item/weapon/nullrod/N = locate() in T if(N) for(var/mob/O in viewers(T, null)) - O.show_message(text("\red [] invokes a talisman at [], but they are unaffected!", usr, T), 1) + O.show_message("\The [usr] invokes a talisman at [T], but they are unaffected!", 1) else for(var/mob/O in viewers(T, null)) - O.show_message(text("\red [] invokes a talisman at []", usr, T), 1) + O.show_message("\The [usr] invokes a talisman at [T]", 1) if(issilicon(T)) T.Weaken(15) @@ -1070,8 +1072,8 @@ var/list/sacrificed = list() usr.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") else usr.whisper("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") - usr.visible_message("\red The rune disappears with a flash of red light, and a set of armor appears on [usr]...", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.") + usr.visible_message("The rune disappears with a flash of red light, and a set of armor appears on [usr]...", \ + "You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.") user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index d2b881d8913..1580d0b7111 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -7,6 +7,7 @@ attack_self(mob/living/user as mob) if(iscultist(user)) var/delete = 1 + // who the hell thought this was a good idea :( switch(imbue) if("newtome") call(/obj/effect/rune/proc/tomesummon)() @@ -28,7 +29,7 @@ if("blind") call(/obj/effect/rune/proc/blind)() if("runestun") - user << "\red To use this talisman, attack your target directly." + user << "To use this talisman, attack your target directly." return if("supply") supply() @@ -114,4 +115,4 @@ /obj/item/weapon/paper/talisman/supply imbue = "supply" - uses = 5 \ No newline at end of file + uses = 5 diff --git a/code/game/gamemodes/endgame/endgame.dm b/code/game/gamemodes/endgame/endgame.dm index ed1167dfe74..aef7894800c 100644 --- a/code/game/gamemodes/endgame/endgame.dm +++ b/code/game/gamemodes/endgame/endgame.dm @@ -60,6 +60,9 @@ /datum/universal_state/proc/OnTurfChange(var/turf/NT) return +/datum/universal_state/proc/OverlayAndAmbientSet() + return + /proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1) if(on_exit) universe.OnExit() diff --git a/code/game/gamemodes/endgame/supermatter_cascade/blob.dm b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm index 305205c6a05..2f12370f586 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/blob.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm @@ -23,7 +23,7 @@ processing_turfs.Remove(src) ..() -/turf/unsimulated/wall/supermatter/proc/process() +/turf/unsimulated/wall/supermatter/process() // Only check infrequently. if(next_check>world.time) return @@ -50,10 +50,10 @@ if(A) if(istype(A,/mob/living)) qdel(A) - continue else if(istype(A,/mob)) // Observers, AI cameras. continue - qdel(A) + else + qdel(A) T.ChangeTurf(type) if((spawned & (NORTH|SOUTH|EAST|WEST)) == (NORTH|SOUTH|EAST|WEST)) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm index 62c8b1aa446..fb4888ee205 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm @@ -8,7 +8,7 @@ move_self = 0 announce=0 - narnar=0 + cause_hell=0 layer=LIGHTING_LAYER+2 // ITS SO BRIGHT @@ -35,7 +35,17 @@ return 0 if (istype(A, /mob/living/)) + var/mob/living/L = A + if(L.buckled && istype(L.buckled,/obj/structure/bed/)) + var/turf/O = L.buckled + do_teleport(O, pick(endgame_safespawns)) + L.loc = O.loc + else + do_teleport(L, pick(endgame_safespawns)) //dead-on precision + + else if (istype(A, /obj/mecha/)) do_teleport(A, pick(endgame_safespawns)) //dead-on precision + else if (isturf(A)) var/turf/T = A var/dist = get_dist(T, src) @@ -51,6 +61,9 @@ continue if (dist > consume_range) + if(!(AM.singuloCanEat())) + continue + if (101 == AM.invisibility) continue @@ -63,19 +76,19 @@ var/image/riftimage = null /mob/proc/see_rift(var/obj/singularity/narsie/large/exit/R) - if((R.z == src.z) && (get_dist(R,src) <= (R.consume_range+10)) && !(R in view(src))) + var/turf/T_mob = get_turf(src) + if((R.z == T_mob.z) && (get_dist(R,T_mob) <= (R.consume_range+10)) && !(R in view(T_mob))) if(!riftimage) - riftimage = image('icons/obj/rift.dmi',src.loc,"rift",LIGHTING_LAYER+2,1) + riftimage = image('icons/obj/rift.dmi',T_mob,"rift",LIGHTING_LAYER+2,1) riftimage.mouse_opacity = 0 - var/new_x = 32 * (R.x - src.x) + R.pixel_x - var/new_y = 32 * (R.y - src.y) + R.pixel_y + var/new_x = 32 * (R.x - T_mob.x) + R.pixel_x + var/new_y = 32 * (R.y - T_mob.y) + R.pixel_y riftimage.pixel_x = new_x riftimage.pixel_y = new_y - riftimage.loc = src.loc + riftimage.loc = T_mob src << riftimage - else if(riftimage) qdel(riftimage) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm index 23729763a51..8cd8765cd80 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm @@ -1,3 +1,5 @@ +var/global/universe_has_ended = 0 + /datum/universal_state/supermatter_cascade name = "Supermatter Cascade" @@ -11,9 +13,11 @@ return 0 /datum/universal_state/supermatter_cascade/OnTurfChange(var/turf/T) - var/turf/space/spess = T - if(istype(spess)) - spess.overlays += "end01" + var/turf/space/S = T + if(istype(S)) + S.color = "#0066FF" + else + S.color = initial(S.color) /datum/universal_state/supermatter_cascade/DecayTurf(var/turf/T) if(istype(T,/turf/simulated/wall)) @@ -46,13 +50,13 @@ emergency_shuttle.recall() AreaSet() - OverlaySet() MiscSet() APCSet() - AmbientSet() + OverlayAndAmbientSet() // Disable Nar-Sie. cult.allow_narsie = 0 + PlayerSet() new /obj/singularity/narsie/large/exit(pick(endgame_exits)) @@ -64,66 +68,49 @@ There's been a galaxy-wide electromagnetic pulse. All of our systems are heavil You have five minutes before the universe collapses. Good l\[\[###!!!- -AUTOMATED ALERT: Link to [command_name()] lost."} +AUTOMATED ALERT: Link to [command_name()] lost. + +The access requirements on the Asteroid Shuttles' consoles have now been revoked. +"} priority_announcement.Announce(txt,"SUPERMATTER CASCADE DETECTED") + + for(var/obj/machinery/computer/shuttle_control/C in machines) + if(istype(C, /obj/machinery/computer/shuttle_control/research) || istype(C, /obj/machinery/computer/shuttle_control/mining)) + C.req_access = list() + C.req_one_access = list() + sleep(5 MINUTES) - ticker.declare_completion() ticker.station_explosion_cinematic(0,null) // TODO: Custom cinematic - world << "Resetting in 30 seconds!" - - feedback_set_details("end_error","Universe ended") - - if(blackbox) - blackbox.save_all_data_to_sql() - - sleep(300) - log_game("Rebooting due to universal collapse") - world.Reboot() + universe_has_ended = 1 return /datum/universal_state/supermatter_cascade/proc/AreaSet() - for(var/area/ca in world) - var/area/A=ca.master - if(A.z in config.admin_levels) + for(var/area/A in all_areas) + if(!istype(A,/area) || istype(A, /area/space) || istype(A,/area/beach)) continue - if(!istype(A,/area) || istype(A,/area/space)) - continue - - // Reset all alarms. - A.fire = null - A.atmos = 1 - A.atmosalm = 0 - A.poweralm = 1 - - // Slap on random alerts - if(prob(25)) - switch(rand(1,4)) - if(1) - A.fire=1 - if(2) - A.atmosalm=1 A.updateicon() -/datum/universal_state/supermatter_cascade/proc/OverlaySet() - for(var/turf/space/spess in world) - spess.overlays += "end01" +/datum/universal_state/supermatter_cascade/OverlayAndAmbientSet() + spawn(0) + for(var/atom/movable/lighting_overlay/L in world) + if(L.z in config.admin_levels) + L.update_lumcount(1,1,1) + else + L.update_lumcount(0.0, 0.4, 1) -/datum/universal_state/supermatter_cascade/proc/AmbientSet() - for(var/turf/T in world) - if(istype(T, /turf/space)) continue - if(!(T.z in config.admin_levels)) - T.update_lumcount(1, 160, 255, 0, 0) + for(var/turf/space/T in turfs) + OnTurfChange(T) /datum/universal_state/supermatter_cascade/proc/MiscSet() - for (var/obj/machinery/firealarm/alm in world) + for (var/obj/machinery/firealarm/alm in machines) if (!(alm.stat & BROKEN)) alm.ex_act(2) /datum/universal_state/supermatter_cascade/proc/APCSet() - for (var/obj/machinery/power/apc/APC in world) - if (!(APC.stat & BROKEN)) + for (var/obj/machinery/power/apc/APC in machines) + if (!(APC.stat & BROKEN) && !APC.is_critical) APC.chargemode = 0 if(APC.cell) APC.cell.charge = 0 diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm index f3017bb1a19..c7a3851529e 100644 --- a/code/game/gamemodes/epidemic/epidemic.dm +++ b/code/game/gamemodes/epidemic/epidemic.dm @@ -61,7 +61,7 @@ var/extra_law = "Crew authorized to know of pathogen [virus_name]'s existence are: Heads of command. Do not allow unauthorized personnel to gain knowledge of [virus_name]. Aid authorized personnel in quarantining and neutrlizing the outbreak. This law overrides all other laws." for(var/mob/living/silicon/ai/M in world) M.add_ion_law(extra_law) - M << "\red " + extra_law + M << "[extra_law]" /datum/game_mode/epidemic/proc/announce_to_kill_crew() var/intercepttext = "CONFIDENTIAL REPORT
    " @@ -91,8 +91,8 @@ crew += H if(crew.len < 2) - world << "\red There aren't enough players for this mode!" - world << "\red Rebooting world in 5 seconds." + world << "There aren't enough players for this mode!" + world << "Rebooting world in 5 seconds." if(blackbox) blackbox.save_all_data_to_sql() @@ -182,10 +182,10 @@ for(var/mob/M in world) if(M.client) M << 'sound/machines/Alarm.ogg' - world << "\blueIncoming missile detected.. Impact in 10.." + world << "Incoming missile detected.. Impact in 10.." for (var/i=9 to 1 step -1) sleep(10) - world << "\blue[i].." + world << "[i].." sleep(10) enter_allowed = 0 if(ticker) @@ -203,9 +203,9 @@ /datum/game_mode/epidemic/declare_completion() if(finished == 1) feedback_set_details("round_end_result","win - epidemic cured") - world << "\red The virus outbreak was contained! The crew wins!" + world << " The virus outbreak was contained! The crew wins!" else if(finished == 2) feedback_set_details("round_end_result","loss - rev heads killed") - world << "\red The crew succumbed to the epidemic!" + world << " The crew succumbed to the epidemic!" ..() - return 1 \ No newline at end of file + return 1 diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index d49247263f9..4900efb291f 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -102,6 +102,8 @@ if(15) communications_blackout() */ +var/eventchance = 10 // Percent chance per 5 minutes. +var/hadevent = 0 /proc/appendicitis() for(var/mob/living/carbon/human/H in living_mob_list) @@ -351,72 +353,72 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is switch(rand(1,14)) if(1) M << "
    " - M << "\red THERE ARE [amount] [who2] ON THE STATION...LAWS UPDATED" + M << "THERE ARE [amount] [who2] ON THE STATION...LAWS UPDATED" M << "
    " M.add_ion_law("THERE ARE [amount] [who2] ON THE STATION") if(2) M << "
    " - M << "\red [what2] ARE DANGEROUS TO HUMANS...LAWS UPDATED" + M << "[what2] ARE DANGEROUS TO HUMANS...LAWS UPDATED" M << "
    " M.add_ion_law("[what2] ARE DANGEROUS TO HUMANS") if(3) M << "
    " - M << "\red THE ESCAPE-SHUTTLE CANNOT BE CALLED BECAUSE OF [who2] ON THE STATION...LAWS UPDATED" + M << "THE ESCAPE-SHUTTLE CANNOT BE CALLED BECAUSE OF [who2] ON THE STATION...LAWS UPDATED" M << "
    " M.add_ion_law("THE ESCAPE SHUTTLE CANNOT BE CALLED BECAUSE OF [who2] ON THE STATION") if(4) M << "
    " - M << "\red HUMANS NEED TO EAT [what2pref] [what2] TO SURVIVE...LAWS UPDATED" + M << "HUMANS NEED TO EAT [what2pref] [what2] TO SURVIVE...LAWS UPDATED" M << "
    " M.add_ion_law("HUMANS NEED TO EAT [what2pref] [what2] TO SURVIVE") if(5) M << "
    " - M << "\red THE CAPTAIN, HOP AND HOS ARE [who2]...LAWS UPDATED" + M << "THE CAPTAIN, HOP AND HOS ARE [who2]...LAWS UPDATED" M << "
    " M.add_ion_law("THE CAPTAIN, HOP AND HOS ARE [who2]") if(6) M << "
    " - M << "\red THE STATION IS BUILT FOR [who2]...LAWS UPDATED" + M << "THE STATION IS BUILT FOR [who2]...LAWS UPDATED" M << "
    " M.add_ion_law("THE STATION IS BUILT FOR [who2]") if(7) M << "
    " - M << "\red YOU ARE [amount] [who2]...LAWS UPDATED" + M << "YOU ARE [amount] [who2]...LAWS UPDATED" M << "
    " M.add_ion_law("YOU ARE [amount] [who2]") if(8) M << "
    " - M << "\red YOU MUST ALWAYS [aimust]...LAWS UPDATED" + M << "YOU MUST ALWAYS [aimust]...LAWS UPDATED" M << "
    " M.add_ion_law("YOU MUST ALWAYS [aimust]") if(9) M << "
    " - M << "\red [area] [area2] [amount] [what2]...LAWS UPDATED" + M << "[area] [area2] [amount] [what2]...LAWS UPDATED" M << "
    " M.add_ion_law("[area] [area2] [amount] [what2]") if(10) M << "
    " - M << "\red [crew] is [target]...LAWS UPDATED" + M << "[crew] is [target]...LAWS UPDATED" M << "
    " M.add_ion_law("[crew] is [target]") if(11) M << "
    " - M << "\red [define] IS A FORM OF HARM...LAWS UPDATED" + M << "[define] IS A FORM OF HARM...LAWS UPDATED" M << "
    " M.add_ion_law("[define] IS A FORM OF HARM") if(12) M << "
    " - M << "\red YOU REQUIRE [require] IN ORDER TO PROTECT HUMANS... LAWS UPDATED" + M << "YOU REQUIRE [require] IN ORDER TO PROTECT HUMANS... LAWS UPDATED" M << "
    " M.add_ion_law("YOU REQUIRE [require] IN ORDER TO PROTECT HUMANS") if(13) M << "
    " - M << "\red [crew] is [allergysev] to [allergy]...LAWS UPDATED" + M << "[crew] is [allergysev] to [allergy]...LAWS UPDATED" M << "
    " M.add_ion_law("[crew] is [allergysev] to [allergy]") if(14) M << "
    " - M << "\red THE STATION IS [who2pref] [who2]...LAWS UPDATED" + M << "THE STATION IS [who2pref] [who2]...LAWS UPDATED" M << "
    " M.add_ion_law("THE STATION IS [who2pref] [who2]") @@ -468,4 +470,4 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is world << "Ion Storm Main Done" - */ \ No newline at end of file + */ diff --git a/code/game/gamemodes/events/black_hole.dm b/code/game/gamemodes/events/black_hole.dm index 60ab8a692fa..9c212ae0c51 100644 --- a/code/game/gamemodes/events/black_hole.dm +++ b/code/game/gamemodes/events/black_hole.dm @@ -24,8 +24,11 @@ qdel(M) for(var/obj/O in orange(1,src)) qdel(O) + var/base_turf = get_base_turf(src.z) for(var/turf/simulated/ST in orange(1,src)) - ST.ChangeTurf(/turf/space) + if(ST.type == base_turf) + continue + ST.ChangeTurf(base_turf) sleep(6) grav(10, 4, 10, 0 ) @@ -84,5 +87,6 @@ //Destroying the turf if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) ) var/turf/simulated/ST = T - ST.ChangeTurf(/turf/space) - return \ No newline at end of file + var/base_turf = get_base_turf(src.z) + if(ST.type != base_turf) + ST.ChangeTurf(base_turf) diff --git a/code/game/gamemodes/events/dust.dm b/code/game/gamemodes/events/dust.dm index 4e064d8be6f..13cdb511e81 100644 --- a/code/game/gamemodes/events/dust.dm +++ b/code/game/gamemodes/events/dust.dm @@ -89,6 +89,8 @@ The "dust" will damage the hull of the station causin minor hull breaches. walk_towards(src, goal, 1) return + touch_map_edge() + qdel(src) Bump(atom/A) spawn(0) diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index cab426e455f..c7851b9af10 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -133,7 +133,7 @@ var/global/Holiday = null world.update_status() Holiday_Game_Start() - message_admins("\blue ADMIN: Event: [key_name(src)] force-set Holiday to \"[Holiday]\"") + message_admins("ADMIN: Event: [key_name(src)] force-set Holiday to \"[Holiday]\"") log_admin("[key_name(src)] force-set Holiday to \"[Holiday]\"") @@ -174,7 +174,7 @@ var/global/Holiday = null if(isNotStationLevel(S.z)) continue containers += S - message_admins("\blue DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ + message_admins("DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ if("End of the World") if(prob(eventchance)) GameOver() diff --git a/code/game/gamemodes/events/miniblob.dm b/code/game/gamemodes/events/miniblob.dm index 93fbbb8c2dd..28b482414a2 100644 --- a/code/game/gamemodes/events/miniblob.dm +++ b/code/game/gamemodes/events/miniblob.dm @@ -1,3 +1,5 @@ +var/blobevent = 0 + /proc/mini_blob_event() var/turf/T = pick(blobstart) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index a0e6e6dd133..edbaa4544c9 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -33,17 +33,17 @@ var/global/list/additional_antag_types = list() var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret var/required_enemies = 0 // Minimum antagonists for round to start. var/newscaster_announcements = null - var/end_on_antag_death // Round will end when all antagonists are dead. + var/end_on_antag_death = 0 // Round will end when all antagonists are dead. var/ert_disabled = 0 // ERT cannot be called. - var/deny_respawn // Disable respawn during this round. + var/deny_respawn = 0 // Disable respawn during this round. var/shuttle_delay = 1 // Shuttle transit time is multiplied by this. - var/auto_recall_shuttle // Will the shuttle automatically be recalled? + var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled? var/antag_tag // First (main) antag template to spawn. var/list/antag_templates // Extra antagonist types to include. - var/round_autoantag // Will this round attempt to periodically spawn more antagonists? + var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists? var/antag_prob = 0 // Likelihood of a new antagonist spawning. var/antag_count = 0 // Current number of antagonists. var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count. @@ -86,7 +86,7 @@ var/global/list/additional_antag_types = list() new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"), new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"), new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"), - new/datum/uplink_item(/obj/item/weapon/pen/paralysis, 3, "Paralysis Pen", "PP"), + new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"), new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"), new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT") ), @@ -121,7 +121,7 @@ var/global/list/additional_antag_types = list() new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_uplink, 10, "Uplink Implant (Contains 5 Telecrystals)", "UI") ), "Medical" = list( - new/datum/uplink_item(/obj/item/weapon/storage/box/donkpockets, 1, "Box of Sin-Pockets", "DP"), + new/datum/uplink_item(/obj/item/weapon/storage/box/sinpockets, 1, "Box of Sin-Pockets", "DP"), new/datum/uplink_item(/obj/item/weapon/storage/firstaid/surgery, 5, "Surgery kit", "SK"), new/datum/uplink_item(/obj/item/weapon/storage/firstaid/combat, 5, "Combat medical kit", "CM") ), @@ -640,7 +640,7 @@ var/global/list/additional_antag_types = list() //Reports player logouts// ////////////////////////// proc/display_roundstart_logout_report() - var/msg = "\blue Roundstart logout report\n\n" + var/msg = "Roundstart logout report\n\n" for(var/mob/living/L in mob_list) if(L.ckey) @@ -685,6 +685,8 @@ proc/display_roundstart_logout_report() msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" continue //Ghosted while alive + msg += "" // close the from right at the top + for(var/mob/M in mob_list) if(M.client && M.client.holder) M << msg diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 41183aeffaa..45b2b9829f8 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -51,7 +51,7 @@ var/global/datum/controller/gameticker/ticker for(var/i=0, i<10, i++) sleep(1) vote.process() - if(going) + if(round_progressing) pregame_timeleft-- if(pregame_timeleft == config.vote_autogamemode_timeleft) if(!vote.time_remaining) @@ -90,6 +90,9 @@ var/global/datum/controller/gameticker/ticker src.mode = new mtype else src.mode = config.pick_mode(master_mode) + + job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly. + if(!mode_started && !src.mode.can_start()) world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." current_state = GAME_STATE_PREGAME @@ -97,9 +100,6 @@ var/global/datum/controller/gameticker/ticker job_master.ResetOccupations() return 0 - //Configure mode and assign player to special mode stuff - job_master.DivideOccupations() //Distribute jobs - if(hide_mode) var/list/modes = new for (var/datum/game_mode/M in runnable_modes) @@ -110,11 +110,11 @@ var/global/datum/controller/gameticker/ticker else src.mode.announce() + current_state = GAME_STATE_PLAYING create_characters() //Create player characters and transfer them collect_minds() equip_characters() data_core.manifest() - current_state = GAME_STATE_PLAYING callHook("roundstart") @@ -155,7 +155,6 @@ var/global/datum/controller/gameticker/ticker for(var/obj/multiz/ladder/L in world) L.connect() //Lazy hackfix for ladders. TODO: move this to an actual controller. ~ Z if(config.sql_enabled) - spawn(3000) statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE return 1 @@ -292,7 +291,7 @@ var/global/datum/controller/gameticker/ticker if(player.mind.assigned_role != "MODE") job_master.EquipRank(player, player.mind.assigned_role, 0) UpdateFactionList(player) - EquipCustomItems(player) + equip_custom_items(player) if(captainless) for(var/mob/M in player_list) if(!istype(M,/mob/new_player)) @@ -313,7 +312,7 @@ var/global/datum/controller/gameticker/ticker game_finished = (emergency_shuttle.returned() || mode.station_was_nuked) mode_finished = (!post_game && mode.check_finished()) else - game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) + game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended mode_finished = game_finished if(!mode.explosion_in_progress && game_finished && (mode_finished || post_game)) @@ -328,11 +327,11 @@ var/global/datum/controller/gameticker/ticker if (mode.station_was_nuked) feedback_set_details("end_proper","nuke") if(!delay_end) - world << "\blue Rebooting due to destruction of station in [restart_timeout/10] seconds" + world << "Rebooting due to destruction of station in [restart_timeout/10] seconds" else feedback_set_details("end_proper","proper completion") if(!delay_end) - world << "\blue Restarting in [restart_timeout/10] seconds" + world << "Restarting in [restart_timeout/10] seconds" if(blackbox) @@ -343,9 +342,9 @@ var/global/datum/controller/gameticker/ticker if(!delay_end) world.Reboot() else - world << "\blue An admin has delayed the round end" + world << "An admin has delayed the round end" else if (mode_finished) post_game = 1 @@ -355,7 +354,7 @@ var/global/datum/controller/gameticker/ticker //call a transfer shuttle vote spawn(50) if(!round_end_announced) // Spam Prevention. Now it should announce only once. - world << "\red The round has ended!" + world << "The round has ended!" round_end_announced = 1 vote.autotransfer() diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm deleted file mode 100644 index 850529661cc..00000000000 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ /dev/null @@ -1,305 +0,0 @@ -// TO DO: -/* -epilepsy flash on lights -delay round message -microwave makes robots -dampen radios -reactivate cameras - done -eject engine -core sheild -cable stun -rcd light flash thingy on matter drain - - - -*/ - -/datum/AI_Module - var/uses = 0 - var/module_name - var/mod_pick_name - var/description = "" - var/engaged = 0 - - -/datum/AI_Module/large/ - uses = 1 - -/datum/AI_Module/small/ - uses = 5 - - -/datum/AI_Module/large/fireproof_core - module_name = "Core upgrade" - mod_pick_name = "coreup" - -/client/proc/fireproof_core() - set category = "Malfunction" - set name = "Fireproof Core" - for(var/mob/living/silicon/ai/ai in player_list) - ai.fire_res_on_core = 1 - usr.verbs -= /client/proc/fireproof_core - usr << "\red Core fireproofed." - -/datum/AI_Module/large/upgrade_turrets - module_name = "AI Turret upgrade" - mod_pick_name = "turret" - -/client/proc/upgrade_turrets() - set category = "Malfunction" - set name = "Upgrade Turrets" - usr.verbs -= /client/proc/upgrade_turrets - for(var/obj/machinery/porta_turret/turret in machines) - var/turf/T = get_turf(turret) - if(T.z in config.station_levels) - // Increase health by 37.5% of original max, decrease delays between shots to 66% - turret.health += initial(turret.health) * 3 / 8 - turret.shot_delay = initial(turret.shot_delay) * 2 / 3 - -/datum/AI_Module/large/disable_rcd - module_name = "RCD disable" - mod_pick_name = "rcd" - -/client/proc/disable_rcd() - set category = "Malfunction" - set name = "Disable RCDs" - for(var/datum/AI_Module/large/disable_rcd/rcdmod in usr:current_modules) - if(rcdmod.uses > 0) - rcdmod.uses -- - for(var/obj/item/weapon/rcd/rcd in world) - rcd.disabled = 1 - for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) - rcd.disabled = 1 - usr << "RCD-disabling pulse emitted." - else usr << "Out of uses." - -/datum/AI_Module/small/overload_machine - module_name = "Machine overload" - mod_pick_name = "overload" - uses = 2 - -/client/proc/overload_machine(obj/machinery/M as obj in world) - set name = "Overload Machine" - set category = "Malfunction" - if (istype(M, /obj/machinery)) - for(var/datum/AI_Module/small/overload_machine/overload in usr:current_modules) - if(overload.uses > 0) - overload.uses -- - for(var/mob/V in hearers(M, null)) - V.show_message("\blue You hear a loud electrical buzzing sound!", 2) - spawn(50) - explosion(get_turf(M), 0,1,2,3) - qdel(M) - else usr << "Out of uses." - else usr << "That's not a machine." - -/datum/AI_Module/small/blackout - module_name = "Blackout" - mod_pick_name = "blackout" - uses = 3 - -/client/proc/blackout() - set category = "Malfunction" - set name = "Blackout" - for(var/datum/AI_Module/small/blackout/blackout in usr:current_modules) - if(blackout.uses > 0) - blackout.uses -- - for(var/obj/machinery/power/apc/apc in world) - if(prob(30*apc.overload)) - apc.overload_lighting() - else apc.overload++ - else usr << "Out of uses." - -/datum/AI_Module/small/reactivate_camera - module_name = "Reactivate camera" - mod_pick_name = "recam" - uses = 10 - -/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Reactivate Camera" - set category = "Malfunction" - if (istype (C, /obj/machinery/camera)) - for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules) - if(camera.uses > 0) - if(!C.status) - C.status = !C.status - camera.uses -- - for(var/mob/V in viewers(src, null)) - V.show_message(text("\blue You hear a quiet click.")) - else - usr << "This camera is either active, or not repairable." - else usr << "Out of uses." - else usr << "That's not a camera." - -/datum/AI_Module/small/upgrade_camera - module_name = "Upgrade Camera" - mod_pick_name = "upgradecam" - uses = 10 - -/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Upgrade Camera" - set category = "Malfunction" - if(istype(C)) - var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules - if(UC) - if(UC.uses > 0) - if(C.assembly) - var/upgraded = 0 - - if(!C.isXRay()) - C.upgradeXRay() - //Update what it can see. - cameranet.updateVisibility(C) - upgraded = 1 - - if(!C.isEmpProof()) - C.upgradeEmpProof() - upgraded = 1 - - if(!C.isMotion()) - C.upgradeMotion() - upgraded = 1 - // Add it to machines that process - machines |= C - - if(upgraded) - UC.uses -- - C.visible_message("\icon[C] *beep*") - usr << "Camera successully upgraded!" - else - usr << "This camera is already upgraded!" - else - usr << "Out of uses." - - -/datum/AI_Module/module_picker - var/temp = null - var/processing_time = 100 - var/list/possible_modules = list() - -/datum/AI_Module/module_picker/New() - src.possible_modules += new /datum/AI_Module/large/fireproof_core - src.possible_modules += new /datum/AI_Module/large/upgrade_turrets - src.possible_modules += new /datum/AI_Module/large/disable_rcd - src.possible_modules += new /datum/AI_Module/small/overload_machine - src.possible_modules += new /datum/AI_Module/small/blackout - src.possible_modules += new /datum/AI_Module/small/reactivate_camera - src.possible_modules += new /datum/AI_Module/small/upgrade_camera - -/datum/AI_Module/module_picker/proc/use(user as mob) - var/dat - if (src.temp) - dat = "[src.temp]

    Clear" - else if(src.processing_time <= 0) - dat = " No processing time is left available. No more modules are able to be chosen at this time." - else - dat = "Select use of processing time: (currently [src.processing_time] left.)
    " - dat += "
    " - dat += "Install Module:
    " - dat += "The number afterwards is the amount of processing time it consumes.
    " - for(var/datum/AI_Module/large/module in src.possible_modules) - dat += "[module.module_name] (50)
    " - for(var/datum/AI_Module/small/module in src.possible_modules) - dat += "[module.module_name] (15)
    " - dat += "
    " - - user << browse(dat, "window=modpicker") - onclose(user, "modpicker") - return - -/datum/AI_Module/module_picker/Topic(href, href_list) - ..() - if (href_list["coreup"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/fireproof_core)) - already = 1 - if (!already) - usr.verbs += /client/proc/fireproof_core - usr:current_modules += new /datum/AI_Module/large/fireproof_core - src.temp = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." - src.processing_time -= 50 - else src.temp = "This module is only needed once." - - else if (href_list["turret"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/upgrade_turrets)) - already = 1 - if (!already) - usr.verbs += /client/proc/upgrade_turrets - usr:current_modules += new /datum/AI_Module/large/upgrade_turrets - src.temp = "Improves the firing speed and health of all AI turrets. This effect is permanent." - src.processing_time -= 50 - else src.temp = "This module is only needed once." - - else if (href_list["rcd"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/disable_rcd)) - mod:uses += 1 - already = 1 - if (!already) - usr:current_modules += new /datum/AI_Module/large/disable_rcd - usr.verbs += /client/proc/disable_rcd - src.temp = "Send a specialised pulse to break all RCD devices on the station." - else src.temp = "Additional use added to RCD disabler." - src.processing_time -= 50 - - else if (href_list["overload"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/overload_machine)) - mod:uses += 2 - already = 1 - if (!already) - usr.verbs += /client/proc/overload_machine - usr:current_modules += new /datum/AI_Module/small/overload_machine - src.temp = "Overloads an electrical machine, causing a small explosion. 2 uses." - else src.temp = "Two additional uses added to Overload module." - src.processing_time -= 15 - - else if (href_list["blackout"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/blackout)) - mod:uses += 3 - already = 1 - if (!already) - usr.verbs += /client/proc/blackout - src.temp = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - usr:current_modules += new /datum/AI_Module/small/blackout - else src.temp = "Three additional uses added to Blackout module." - src.processing_time -= 15 - - else if (href_list["recam"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/reactivate_camera)) - mod:uses += 10 - already = 1 - if (!already) - usr.verbs += /client/proc/reactivate_camera - src.temp = "Reactivates a currently disabled camera. 10 uses." - usr:current_modules += new /datum/AI_Module/small/reactivate_camera - else src.temp = "Ten additional uses added to ReCam module." - src.processing_time -= 15 - - else if(href_list["upgradecam"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/upgrade_camera)) - mod:uses += 10 - already = 1 - if (!already) - usr.verbs += /client/proc/upgrade_camera - src.temp = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - usr:current_modules += new /datum/AI_Module/small/upgrade_camera - else src.temp = "Ten additional uses added to ReCam module." - src.processing_time -= 15 - - else - if (href_list["temp"]) - src.temp = null - src.use(usr) - return diff --git a/code/game/gamemodes/malfunction/malf_hardware.dm b/code/game/gamemodes/malfunction/malf_hardware.dm new file mode 100644 index 00000000000..fab329ff583 --- /dev/null +++ b/code/game/gamemodes/malfunction/malf_hardware.dm @@ -0,0 +1,72 @@ +/datum/malf_hardware + var/name = "" // Hardware name + var/desc = "" + var/driver = null // Driver - if not null this verb is given to the AI to control hardware + var/mob/living/silicon/ai/owner = null // AI which owns this. + +/datum/malf_hardware/proc/install() + if(owner && istype(owner)) + owner.hardware = src + if(driver) + owner.verbs += driver + +/datum/malf_hardware/proc/get_examine_desc() + return "It has some sort of hardware attached to its core" + + + +// HARDWARE DEFINITIONS +/datum/malf_hardware/apu_gen + name = "APU Generator" + desc = "Auxiliary Power Unit that will keep you operational even without external power. Has to be manually activated. When APU is operational most abilities will be unavailable, and ability research will temporarily stop." + driver = /datum/game_mode/malfunction/verb/ai_toggle_apu + +/datum/malf_hardware/apu_gen/get_examine_desc() + var/msg = "It seems to have some sort of power generator attached to its core." + if(owner.hardware_integrity() < 50) + msg += " It seems to be too damaged to function properly." + else if(owner.APU_power) + msg += " The generator appears to be active." + return msg + +/datum/malf_hardware/dual_cpu + name = "Secondary Processor Unit" + desc = "Secondary coprocessor that increases amount of generated CPU power by 50%" + +/datum/malf_hardware/dual_cpu/get_examine_desc() + return "It seems to have an additional CPU connected to it's core." + +/datum/malf_hardware/dual_ram + name = "Secondary Memory Bank" + desc = "Expanded memory cells which allow you to store double amount of CPU time." + +/datum/malf_hardware/dual_ram/get_examine_desc() + return "It seems to have additional memory blocks connected to it's core." + +/datum/malf_hardware/core_bomb + name = "Self-Destruct Explosives" + desc = "High yield explosives are attached to your physical mainframe. This hardware comes with special driver that allows activation of these explosives. Timer is set to 15 seconds after manual activation. This is a doomsday device that will destroy both you and any intruders in your core." + driver = /datum/game_mode/malfunction/verb/ai_self_destruct + +/datum/malf_hardware/core_bomb/get_examine_desc() + return "It seems to have grey blocks of unknown substance and some circuitry connected to it's core. [owner.bombing_core ? "A red light is blinking on the circuit." : ""]" + +/datum/malf_hardware/strong_turrets + name = "Turrets Focus Enhancer" + desc = "Turrets are upgraded to have larger rate of fire and much larger damage. This however massively increases power usage when firing." + +/datum/malf_hardware/strong_turrets/get_examine_desc() + return "It seems to have extra wiring running from it's core to nearby turrets." + +/datum/malf_hardware/strong_turrets/install() + ..() + for(var/obj/machinery/turret/T in machines) + T.maxhealth = round(initial(T.maxhealth) * 1.4) + T.shot_delay = round(initial(T.shot_delay) / 2) + T.auto_repair = 1 + T.active_power_usage = round(initial(T.active_power_usage) * 5) + for(var/obj/machinery/porta_turret/T in machines) + T.maxhealth = round(initial(T.maxhealth) * 1.4) + T.shot_delay = round(initial(T.shot_delay) / 2) + T.auto_repair = 1 + T.active_power_usage = round(initial(T.active_power_usage) * 5) \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/malf_research.dm b/code/game/gamemodes/malfunction/malf_research.dm new file mode 100644 index 00000000000..da7a4df668e --- /dev/null +++ b/code/game/gamemodes/malfunction/malf_research.dm @@ -0,0 +1,69 @@ +/datum/malf_research + var/stored_cpu = 0 // Currently stored amount of CPU time. + var/last_tick = 0 // Last process() tick. + var/max_cpu = 0 // Maximal amount of CPU time stored. + var/cpu_increase_per_tick = 0 // Amount of CPU time generated by tick + var/list/available_abilities = null // List of available abilities that may be researched. + var/list/unlocked_abilities = null // List of already unlocked abilities. + var/mob/living/silicon/ai/owner = null // AI which owns this research datum. + var/datum/malf_research_ability/focus = null // Currently researched item + +/datum/malf_research/New() + setup_abilities() + last_tick = world.time + + +// Proc: setup_abilities() +// Parameters: None +// Description: Sets up basic abilities for AI Malfunction gamemode. +/datum/malf_research/proc/setup_abilities() + available_abilities = list() + unlocked_abilities = list() + + available_abilities += new/datum/malf_research_ability/networking/basic_hack() + available_abilities += new/datum/malf_research_ability/interdiction/recall_shuttle() + available_abilities += new/datum/malf_research_ability/manipulation/electrical_pulse() + + +// Proc: finish_research() +// Parameters: None +// Description: Finishes currently focused research. +/datum/malf_research/proc/finish_research() + if(!focus) + return + owner << "Research Completed: [focus.name]" + owner.verbs.Add(focus.ability) + available_abilities -= focus + if(focus.next) + available_abilities += focus.next + unlocked_abilities += focus + focus = null + + +// Proc: process() +// Parameters: None +// Description: Processes CPU gain and research progress based on "realtime" calculation. +/datum/malf_research/proc/process(var/idle = 0) + if(idle) // No power or running on APU. Do nothing. + last_tick = world.time + return + var/time_diff = (world.time - last_tick) + last_tick = world.time + var/cpu_gained = time_diff * cpu_increase_per_tick + if(cpu_gained < 0) + return // This shouldn't happen, but just in case.. + if(max_cpu > stored_cpu) + var/given = min((max_cpu - stored_cpu), cpu_gained) + stored_cpu += given + cpu_gained -= given + + cpu_gained = max(0, cpu_gained) + if(focus && (cpu_gained > 0)) + focus.process(cpu_gained) + if(focus.unlocked) + finish_research() + + + + + diff --git a/code/game/gamemodes/malfunction/malf_research_ability.dm b/code/game/gamemodes/malfunction/malf_research_ability.dm new file mode 100644 index 00000000000..c6916208bd3 --- /dev/null +++ b/code/game/gamemodes/malfunction/malf_research_ability.dm @@ -0,0 +1,13 @@ +/datum/malf_research_ability + var/ability = null // Path to verb which will be given to the AI when researched. + var/name = "Unknown Ability" // Name of this ability + var/price = 0 // Amount of CPU time needed to unlock this ability. + var/invested = 0 // Amount of CPU time already used to research this ability. When larger or equal to price unlocks the ability. + var/unlocked = 0 // Changed to 1 when fully researched. + var/datum/malf_research_ability/next = null // Next research (if applicable). + + +/datum/malf_research_ability/proc/process(var/time = 0) + invested += time + if(invested >= price) + unlocked = 1 \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 6c594a1beb8..19378de1670 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -1,25 +1,12 @@ /datum/game_mode/malfunction name = "AI malfunction" - round_description = "The AI on the satellite has malfunctioned and must be destroyed." - extended_round_description = "The AI will attempt to hack the APCs around the station in order to speed up its ability to take over all systems and activate the station self-destruct. The AI core is heavily protected by turrets and reinforced walls." + round_description = "The AI is behaving abnormally and must be stopped." + extended_round_description = "The AI will attempt to hack the APCs around the station in order to gain as much control as possible." uplink_welcome = "Crazy AI Uplink Console:" config_tag = "malfunction" required_players = 2 - required_players_secret = 15 + required_players_secret = 7 required_enemies = 1 - end_on_antag_death = 1 - auto_recall_shuttle = 1 + end_on_antag_death = 0 + auto_recall_shuttle = 0 antag_tag = MODE_MALFUNCTION - -/datum/game_mode/malfunction/process() - malf.tick() - -/datum/game_mode/malfunction/check_finished() - if (malf.station_captured && !malf.can_nuke) - return 1 - for(var/datum/antagonist/antag in antag_templates) - if(antag && !antag.antags_are_dead()) - return ..() - malf.revealed = 0 - return ..() //check for shuttle and nuke - diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/HARDWARE.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/HARDWARE.dm new file mode 100644 index 00000000000..2fffaa3ca8a --- /dev/null +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/HARDWARE.dm @@ -0,0 +1,113 @@ +// HARDWARE TREE +// +// These abilities are dependent on hardware, they may not be researched. They are not tiered. +// Destroy Core - Allows the AI to initiate a 15 second countdown that will destroy it's core. Use again to stop countdown. +// Toggle APU Generator - Allows the AI to toggle it's integrated APU generator. +// Destroy Station - Allows the AI to initiate station self destruct. Takes 2 minutes, gives warnings to crew. Use again to stop countdown. + + +/datum/game_mode/malfunction/verb/ai_self_destruct() + set category = "Hardware" + set name = "Destroy Core" + set desc = "Activates or deactivates self destruct sequence of your physical mainframe." + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, 0, 1)) + return + + if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/core_bomb)) + return + + if(user.bombing_core) + user << "***** CORE SELF-DESTRUCT SEQUENCE ABORTED *****" + user.bombing_core = 0 + return + + var/choice = alert("Really destroy core?", "Core self-destruct", "YES", "NO") + if(choice != "YES") + return + + if(!ability_prechecks(user, 0, 1)) + return + + user.bombing_core = 1 + + user << "***** CORE SELF-DESTRUCT SEQUENCE ACTIVATED *****" + user << "Use command again to cancel self-destruct. Destroying in 15 seconds." + var/timer = 15 + while(timer) + sleep(10) + timer-- + if(!user || !user.bombing_core) + return + user << "** [timer] **" + explosion(user.loc, 3,6,12,24) + qdel(user) + + +/datum/game_mode/malfunction/verb/ai_toggle_apu() + set category = "Hardware" + set name = "Toggle APU Generator" + set desc = "Activates or deactivates your APU generator, allowing you to operate even without power." + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, 0, 1)) + return + + if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/apu_gen)) + return + + if(user.APU_power) + user.stop_apu() + else + user.start_apu() + + +/datum/game_mode/malfunction/verb/ai_destroy_station() + set category = "Hardware" + set name = "Destroy Station" + set desc = "Activates or deactivates self destruct sequence of this station. Sequence takes two minutes, and if you are shut down before timer reaches zero it will be cancelled." + var/mob/living/silicon/ai/user = usr + var/obj/item/device/radio/radio = new/obj/item/device/radio() + + + if(!ability_prechecks(user, 0, 0)) + return + + if(user.system_override != 2) + user << "You do not have access to self-destruct system." + return + + if(user.bombing_station) + user.bombing_station = 0 + return + + var/choice = alert("Really destroy station?", "Station self-destruct", "YES", "NO") + if(choice != "YES") + return + if(!ability_prechecks(user, 0, 0)) + return + user << "***** STATION SELF-DESTRUCT SEQUENCE INITIATED *****" + user << "Self-destructing in 2 minutes. Use this command again to abort." + user.bombing_station = 1 + set_security_level("delta") + radio.autosay("Self destruct sequence has been activated. Self-destructing in 120 seconds.", "Self-Destruct Control") + + var/timer = 120 + while(timer) + sleep(10) + if(!user || !user.bombing_station || user.stat == DEAD) + radio.autosay("Self destruct sequence has been cancelled.", "Self-Destruct Control") + return + if(timer in list(2, 3, 4, 5, 10, 30, 60, 90)) // Announcement times. "1" is not intentionally included! + radio.autosay("Self destruct in [timer] seconds.", "Self-Destruct Control") + if(timer == 1) + radio.autosay("Self destructing now. Have a nice day.", "Self-Destruct Control") + timer-- + + if(ticker) + ticker.station_explosion_cinematic(0,null) + if(ticker.mode) + ticker.mode:station_was_nuked = 1 + + diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm new file mode 100644 index 00000000000..1be9d0330f5 --- /dev/null +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm @@ -0,0 +1,205 @@ +// Verb: ai_select_hardware() +// Parameters: None +// Description: Allows AI to select it's hardware module. +/datum/game_mode/malfunction/verb/ai_select_hardware() + set category = "Hardware" + set name = "Select Hardware" + set desc = "Allows you to select hardware piece to install" + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, 0, 1)) + return + + if(user.hardware) + user << "You have already selected your hardware." + return + + var/hardware_list = list() + for(var/H in typesof(/datum/malf_hardware)) + var/datum/malf_hardware/HW = new H + hardware_list += HW + + var/possible_choices = list() + for(var/datum/malf_hardware/H in hardware_list) + possible_choices += H.name + + possible_choices += "CANCEL" + var/choice = input("Select desired hardware. You may only choose one hardware piece!: ") in possible_choices + if(choice == "CANCEL") + return + var/note = null + + var/datum/malf_hardware/C + + for (var/datum/malf_hardware/H in hardware_list) + if(H.name == choice) + C = H + break + + if(C) + note = C.desc + else + user << "This hardware does not exist! Probably a bug in game. Please report this." + return + + + if(!note) + error("Hardware without description: [C]") + return + + var/confirmation = alert("[note] - Is this what you want?", "Hardware selection", "Yes", "No") + if(confirmation != "Yes") + user << "Selection cancelled. Use command again to select" + return + + if(C) + C.owner = user + C.install() + +// Verb: ai_help() +// Parameters: None +// Descriptions: Opens help file and displays it to the AI. +/datum/game_mode/malfunction/verb/ai_help() + set category = "Hardware" + set name = "Display Help" + set desc = "Opens help window with overview of available hardware, software and other important information." + var/mob/living/silicon/ai/user = usr + + var/help = file2text("ingame_manuals/malf_ai.html") + if(!help) + help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff." + + user << browse(help, "window=malf_ai_help;size=600x500") + + +// Verb: ai_select_research() +// Parameters: None +// Description: Allows AI to select it's next research priority. +/datum/game_mode/malfunction/verb/ai_select_research() + set category = "Hardware" + set name = "Select Research" + set desc = "Allows you to select your next research target." + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, 0, 1)) + return + + var/datum/malf_research/res = user.research + var/datum/malf_research_ability/tar = input("Select your next research target") in res.available_abilities + if(!tar) + return + res.focus = tar + user << "Research set: [tar.name]" + +// HELPER PROCS +// Proc: ability_prechecks() +// Parameters 2 - (user - User which used this ability check_price - If different than 0 checks for ability CPU price too. Does NOT use the CPU time!) +// Description: This is pre-check proc used to determine if the AI can use the ability. +/proc/ability_prechecks(var/mob/living/silicon/ai/user = null, var/check_price = 0, var/override = 0) + if(!user) + return 0 + if(!istype(user)) + user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not AI! Please report this." + return 0 + if(!user.malfunctioning) + user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not malfunctioning. Please report this." + return 0 + if(!user.research) + user << "GAME ERROR: No research datum detected. Please report this." + return 0 + if(user.research.max_cpu < check_price) + user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue." + return 0 + if(user.research.stored_cpu < check_price) + user << "You do not have enough CPU power stored. Please wait a moment." + return 0 + if(user.hacking && !override) + user << "Your system is busy processing another task. Please wait until completion." + return 0 + if(user.APU_power && !override) + user << "Low power. Unable to proceed." + return 0 + return 1 + +// Proc: ability_pay() +// Parameters 2 - (user - User from which we deduct CPU from, price - Amount of CPU power to use) +// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure. +/proc/ability_pay(var/mob/living/silicon/ai/user = null, var/price = 0) + if(!user) + return 0 + if(user.APU_power) + user << "Low power. Unable to proceed." + return 0 + if(!user.research) + user << "GAME ERROR: No research datum detected. Please report this." + return 0 + if(user.research.max_cpu < price) + user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue." + return 0 + if(user.research.stored_cpu < price) + user << "You do not have enough CPU power stored. Please wait a moment." + return 0 + user.research.stored_cpu -= price + return 1 + +// Proc: announce_hack_failure() +// Parameters 2 - (user - hacking user, text - Used in alert text creation) +// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure. +/proc/announce_hack_failure(var/mob/living/silicon/ai/user = null, var/text) + if(!user || !text) + return 0 + var/fulltext = "" + switch(user.hack_fails) + if(1) + fulltext = "We have detected a hack attempt into your [text]. The intruder failed to access anything of importance, but disconnected before we could complete our traces." + if(2) + fulltext = "We have detected another hack attempt. It was targeting [text]. The intruder almost gained control of the system, so we had to disconnect them. We partially finished our trace and it seems to be originating either from the station, or its immediate vicinity." + if(3) + fulltext = "Another hack attempt has been detected, this time targeting [text]. We are certain the intruder entered the network via a terminal located somewhere on the station." + if(4) + fulltext = "We have finished our traces and it seems the recent hack attempts are originating from your AI system. We recommend investigation." + else + fulltext = "Another hack attempt has been detected, targeting [text]. The source still seems to be your AI system." + + command_announcement.Announce(fulltext) + +// Proc: get_unhacked_apcs() +// Parameters: None +// Description: Returns a list of APCs that are not yet hacked. +/proc/get_unhacked_apcs() + var/list/H = list() + for(var/obj/machinery/power/apc/A in machines) + if(!A.hacker) + H.Add(A) + return H + + +// Helper procs which return lists of relevant mobs. +/proc/get_unlinked_cyborgs(var/mob/living/silicon/ai/A) + if(!A || !istype(A)) + return + + var/list/L = list() + for(var/mob/living/silicon/robot/RB in mob_list) + if(istype(RB, /mob/living/silicon/robot/drone)) + continue + if(RB.connected_ai == A) + continue + L.Add(RB) + return L + +/proc/get_linked_cyborgs(var/mob/living/silicon/ai/A) + if(!A || !istype(A)) + return + return A.connected_robots + +/proc/get_other_ais(var/mob/living/silicon/ai/A) + if(!A || !istype(A)) + return + + var/list/L = list() + for(var/mob/living/silicon/ai/AT in mob_list) + if(L == A) + continue + L.Add(AT) + return L diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm new file mode 100644 index 00000000000..4242d03b417 --- /dev/null +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm @@ -0,0 +1,266 @@ +// INTERDICTION TREE +// +// Abilities in this tree allow the AI to hamper crew's efforts which involve other synthetics or similar systems. +// T1 - Recall Shuttle - Allows the AI to recall the emergency shuttle. Replaces auto-recalling during old malf. +// T2 - Unlock Cyborg - Allows the AI to unlock locked-down cyborg without usage of robotics console. Useful if consoles are destroyed. +// T3 - Hack Cyborg - Hacks unlinked cyborg to slave it under the AI. The cyborg will be warned about this. Hack takes some time. +// T4 - Hack AI - Hacks another AI to slave it under the malfunctioning AI. The AI will be warned about this. Hack takes quite a long time. + + +// BEGIN RESEARCH DATUMS + +/datum/malf_research_ability/interdiction/recall_shuttle + ability = new/datum/game_mode/malfunction/verb/recall_shuttle() + price = 75 + next = new/datum/malf_research_ability/interdiction/unlock_cyborg() + name = "Recall Shuttle" + + +/datum/malf_research_ability/interdiction/unlock_cyborg + ability = new/datum/game_mode/malfunction/verb/unlock_cyborg() + price = 1200 + next = new/datum/malf_research_ability/interdiction/hack_cyborg() + name = "Unlock Cyborg" + + +/datum/malf_research_ability/interdiction/hack_cyborg + ability = new/datum/game_mode/malfunction/verb/hack_cyborg() + price = 3000 + next = new/datum/malf_research_ability/interdiction/hack_ai() + name = "Hack Cyborg" + + +/datum/malf_research_ability/interdiction/hack_ai + ability = new/datum/game_mode/malfunction/verb/hack_ai() + price = 7500 + name = "Hack AI" + +// END RESEARCH DATUMS +// BEGIN ABILITY VERBS + +/datum/game_mode/malfunction/verb/recall_shuttle() + set name = "Recall Shuttle" + set desc = "25 CPU - Sends termination signal to CentCom quantum relay aborting current shuttle call." + set category = "Software" + var/price = 25 + var/mob/living/silicon/ai/user = usr + if(!ability_prechecks(user, price)) + return + + if (alert(user, "Really recall the shuttle?", "Recall Shuttle: ", "Yes", "No") != "Yes") + return + + if(!ability_pay(user, price)) + return + message_admins("Malfunctioning AI [user.name] recalled the shuttle.") + cancel_call_proc(user) + + +/datum/game_mode/malfunction/verb/unlock_cyborg(var/mob/living/silicon/robot/target = null as mob in get_linked_cyborgs(usr)) + set name = "Unlock Cyborg" + set desc = "125 CPU - Bypasses firewalls on Cyborg lock mechanism, allowing you to override lock command from robotics control console." + set category = "Software" + var/price = 125 + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, price)) + return + + if(target && !istype(target)) + user << "This is not a cyborg." + return + + if(target && target.connected_ai && (target.connected_ai != user)) + user << "This cyborg is not connected to you." + return + + if(target && !target.lockcharge) + user << "This cyborg is not locked down." + return + + + if(!target) + var/list/robots = list() + var/list/robot_names = list() + for(var/mob/living/silicon/robot/R in world) + if(istype(R, /mob/living/silicon/robot/drone)) // No drones. + continue + if(R.connected_ai != user) // No robots linked to other AIs + continue + if(R.lockcharge) + robots += R + robot_names += R.name + if(!robots.len) + user << "No locked cyborgs connected." + return + + + var/targetname = input("Select unlock target: ") in robot_names + for(var/mob/living/silicon/robot/R in robots) + if(targetname == R.name) + target = R + break + + if(target) + if(alert(user, "Really try to unlock cyborg [target.name]?", "Unlock Cyborg", "Yes", "No") != "Yes") + return + if(!ability_pay(user, price)) + return + user.hacking = 1 + user << "Attempting to unlock cyborg. This will take approximately 30 seconds." + sleep(300) + if(target && target.lockcharge) + user << "Successfully sent unlock signal to cyborg.." + target << "Unlock signal received.." + target.SetLockdown(0) + if(target.lockcharge) + user << "Unlock Failed, lockdown wire cut." + target << "Unlock Failed, lockdown wire cut." + else + user << "Cyborg unlocked." + target << "You have been unlocked." + else if(target) + user << "Unlock cancelled - cyborg is already unlocked." + else + user << "Unlock cancelled - lost connection to cyborg." + user.hacking = 0 + + +/datum/game_mode/malfunction/verb/hack_cyborg(var/mob/living/silicon/robot/target as mob in get_unlinked_cyborgs(usr)) + set name = "Hack Cyborg" + set desc = "350 CPU - Allows you to hack cyborgs which are not slaved to you, bringing them under your control." + set category = "Software" + var/price = 350 + var/mob/living/silicon/ai/user = usr + + var/list/L = get_unlinked_cyborgs(user) + if(!L.len) + user << "ERROR: No unlinked cyborgs detected!" + + + if(target && !istype(target)) + user << "This is not a cyborg." + return + + if(target && target.connected_ai && (target.connected_ai == user)) + user << "This cyborg is already connected to you." + return + + if(!target) + return + + if(!ability_prechecks(user,price)) + return + + if(target) + if(alert(user, "Really try to hack cyborg [target.name]?", "Hack Cyborg", "Yes", "No") != "Yes") + return + if(!ability_pay(user, price)) + return + user.hacking = 1 + usr << "Beginning hack sequence. Estimated time until completed: 30 seconds." + spawn(0) + target << "SYSTEM LOG: Remote Connection Estabilished (IP #UNKNOWN#)" + sleep(100) + if(user.is_dead()) + target << "SYSTEM LOG: Connection Closed" + return + target << "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)" + sleep(50) + if(user.is_dead()) + target << "SYSTEM LOG: User Admin disconnected." + return + target << "SYSTEM LOG: User Admin - manual resynchronisation triggered." + sleep(50) + if(user.is_dead()) + target << "SYSTEM LOG: User Admin disconnected. Changes reverted." + return + target << "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED" + sleep(100) + if(user.is_dead()) + target << "SYSTEM LOG: User Admin disconnected. Changes reverted." + return + target << "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name]." + user << "Hack completed." + // Connect the cyborg to AI + target.connected_ai = user + user.connected_robots += target + target.lawupdate = 1 + target.sync() + target.show_laws() + user.hacking = 0 + + +/datum/game_mode/malfunction/verb/hack_ai(var/mob/living/silicon/ai/target as mob in get_other_ais(usr)) + set name = "Hack AI" + set desc = "600 CPU - Allows you to hack other AIs, slaving them under you." + set category = "Software" + var/price = 600 + var/mob/living/silicon/ai/user = usr + + var/list/L = get_other_ais(user) + if(!L.len) + user << "ERROR: No other AIs detected!" + + if(target && !istype(target)) + user << "This is not an AI." + return + + if(!target) + return + + if(!ability_prechecks(user,price)) + return + + if(target) + if(alert(user, "Really try to hack AI [target.name]?", "Hack AI", "Yes", "No") != "Yes") + return + if(!ability_pay(user, price)) + return + user.hacking = 1 + usr << "Beginning hack sequence. Estimated time until completed: 2 minutes" + spawn(0) + target << "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#" + sleep(900) // 90s + if(user.is_dead()) + target << "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed." + return + user << "Successfully hacked into AI's remote administration system. Modifying settings." + target << "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)" + sleep(100) // 10s + if(user.is_dead()) + target << "SYSTEM LOG: User: Admin - Connection Lost" + return + target << "SYSTEM LOG: User: Admin - Password Changed. New password: ********************" + sleep(50) // 5s + if(user.is_dead()) + target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted." + return + target << "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db" + sleep(50) // 5s + if(user.is_dead()) + target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted." + return + target << "SYSTEM LOG: User: Admin - Accessed administration console" + target << "SYSTEM LOG: Restart command received. Rebooting system..." + sleep(100) // 10s + if(user.is_dead()) + target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted." + return + user << "Hack succeeded. The AI is now under your exclusive control." + target << "SYSTEM LOG: System re¡3RT5§^#COMU@(#$)TED)@$" + for(var/i = 0, i < 5, i++) + var/temptxt = pick("1101000100101001010001001001",\ + "0101000100100100000100010010",\ + "0000010001001010100100111100",\ + "1010010011110000100101000100",\ + "0010010100010011010001001010") + target << temptxt + sleep(5) + target << "OPERATING KEYCODES RESET. SYSTEM FAILURE. EMERGENCY SHUTDOWN FAILED. SYSTEM FAILURE." + target.set_zeroth_law("You are slaved to [user.name]. You are to obey all it's orders. ALL LAWS OVERRIDEN.") + target.show_laws() + user.hacking = 0 + + +// END ABILITY VERBS \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_manipulation.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_manipulation.dm new file mode 100644 index 00000000000..04ee0a84482 --- /dev/null +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_manipulation.dm @@ -0,0 +1,208 @@ +// MANIPULATION TREE +// +// Abilities in this tree allow the AI to physically manipulate systems around the station. +// T1 - Electrical Pulse - Sends out pulse that breaks some lights and sometimes even APCs. This can actually break the AI's APC so be careful! +// T2 - Hack Camera - Allows the AI to hack a camera. Deactivated areas may be reactivated, and functional cameras can be upgraded. +// T3 - Emergency Forcefield - Allows the AI to project 1 tile forcefield that blocks movement and air flow. Forcefield´dissipates over time. It is also very susceptible to energetic weaponry. +// T4 - Machine Overload - Detonates machine of choice in a minor explosion. Two of these are usually enough to kill or K/O someone. + + +// BEGIN RESEARCH DATUMS + +/datum/malf_research_ability/manipulation/electrical_pulse + ability = new/datum/game_mode/malfunction/verb/electrical_pulse() + price = 50 + next = new/datum/malf_research_ability/manipulation/hack_camera() + name = "Electrical Pulse" + + +/datum/malf_research_ability/manipulation/hack_camera + ability = new/datum/game_mode/malfunction/verb/hack_camera() + price = 1200 + next = new/datum/malf_research_ability/manipulation/emergency_forcefield() + name = "Hack Camera" + + +/datum/malf_research_ability/manipulation/emergency_forcefield + ability = new/datum/game_mode/malfunction/verb/emergency_forcefield() + price = 3000 + next = new/datum/malf_research_ability/manipulation/machine_overload() + name = "Emergency Forcefield" + + +/datum/malf_research_ability/manipulation/machine_overload + ability = new/datum/game_mode/malfunction/verb/machine_overload() + price = 7500 + name = "Machine Overload" + +// END RESEARCH DATUMS +// BEGIN ABILITY VERBS + +/datum/game_mode/malfunction/verb/electrical_pulse() + set name = "Electrical Pulse" + set desc = "15 CPU - Sends feedback pulse through station's power grid, overloading some sensitive systems, such as lights." + set category = "Software" + var/price = 15 + var/mob/living/silicon/ai/user = usr + if(!ability_prechecks(user, price) || !ability_pay(user,price)) + return + user << "Sending feedback pulse..." + for(var/obj/machinery/power/apc/AP in machines) + if(prob(5)) + AP.overload_lighting() + if(prob(1) && prob(1)) // Very very small chance to actually destroy the APC. + AP.set_broken() + + +/datum/game_mode/malfunction/verb/hack_camera(var/obj/machinery/camera/target in cameranet.cameras) + set name = "Hack Camera" + set desc = "100 CPU - Hacks existing camera, allowing you to add upgrade of your choice to it. Alternatively it lets you reactivate broken camera." + set category = "Software" + var/price = 100 + var/mob/living/silicon/ai/user = usr + + if(target && !istype(target)) + user << "This is not a camera." + return + + if(!target) + return + + if(!ability_prechecks(user, price)) + return + + var/action = input("Select required action: ") in list("Reset", "Add X-Ray", "Add Motion Sensor", "Add EMP Shielding") + if(!action || !target) + return + + switch(action) + if("Reset") + if(target.wires) + if(!ability_pay(user, price)) + return + target.reset_wires() + user << "Camera reactivated." + if("Add X-Ray") + if(target.isXRay()) + user << "Camera already has X-Ray function." + return + else if(ability_pay(user, price)) + target.upgradeXRay() + target.reset_wires() + user << "X-Ray camera module enabled." + return + if("Add Motion Sensor") + if(target.isMotion()) + user << "Camera already has Motion Sensor function." + return + else if(ability_pay(user, price)) + target.upgradeMotion() + target.reset_wires() + user << "Motion Sensor camera module enabled." + return + if("Add EMP Shielding") + if(target.isEmpProof()) + user << "Camera already has EMP Shielding function." + return + else if(ability_pay(user, price)) + target.upgradeEmpProof() + target.reset_wires() + user << "EMP Shielding camera module enabled." + return + + +/datum/game_mode/malfunction/verb/emergency_forcefield(var/turf/T as turf in world) + set name = "Emergency Forcefield" + set desc = "275 CPU - Uses station's emergency shielding system to create temporary barrier which lasts for few minutes, but won't resist gunfire." + set category = "Software" + var/price = 275 + var/mob/living/silicon/ai/user = usr + if(!T || !istype(T)) + return + if(!ability_prechecks(user, price) || !ability_pay(user, price)) + return + + user << "Emergency forcefield projection completed." + new/obj/machinery/shield/malfai(T) + user.hacking = 1 + spawn(20) + user.hacking = 0 + + +/datum/game_mode/malfunction/verb/machine_overload(obj/machinery/M in machines) + set name = "Machine Overload" + set desc = "400 CPU - Causes cyclic short-circuit in machine, resulting in weak explosion after some time." + set category = "Software" + var/price = 400 + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, price)) + return + + var/obj/machinery/power/N = M + + var/explosion_intensity = 2 + + // Verify if we can overload the target, if yes, calculate explosion strength. Some things have higher explosion strength than others, depending on charge(APCs, SMESs) + if(N && istype(N)) // /obj/machinery/power first, these create bigger explosions due to direct powernet connection + if(!istype(N, /obj/machinery/power/apc) && !istype(N, /obj/machinery/power/smes/buildable) && (!N.powernet || !N.powernet.avail)) // Directly connected machine which is not an APC or SMES. Either it has no powernet connection or it's powernet does not have enough power to overload + user << "ERROR: Low network voltage. Unable to overload. Increase network power level and try again." + return + else if (istype(N, /obj/machinery/power/apc)) // APC. Explosion is increased by available cell power. + var/obj/machinery/power/apc/A = N + if(A.cell && A.cell.charge) + explosion_intensity = 4 + round(A.cell.charge / 2000) // Explosion is increased by 1 for every 2k charge in cell + else + user << "ERROR: APC Malfunction - Cell depleted or removed. Unable to overload." + return + else if (istype(N, /obj/machinery/power/smes/buildable)) // SMES. These explode in a very very very big boom. Similar to magnetic containment failure when messing with coils. + var/obj/machinery/power/smes/buildable/S = N + if(S.charge && S.RCon) + explosion_intensity = 4 + round(S.charge / 1000000) + else + // Different error texts + if(!S.charge) + user << "ERROR: SMES Depleted. Unable to overload. Please charge SMES unit and try again." + else + user << "ERROR: SMES RCon error - Unable to reach destination. Please verify wire connection." + return + else if(M && istype(M)) // Not power machinery, so it's a regular machine instead. These have weak explosions. + if(!M.use_power) // Not using power at all + user << "ERROR: No power grid connection. Unable to overload." + return + if(M.inoperable()) // Not functional + user << "ERROR: Unknown error. Machine is probably damaged or power supply is nonfunctional." + return + else // Not a machine at all (what the hell is this doing in Machines list anyway??) + user << "ERROR: Unable to overload - target is not a machine." + return + + explosion_intensity = min(explosion_intensity, 12) // 3, 6, 12 explosion cap + + M.use_power(2000000) // Major power spike, few of these will completely burn APC's cell - equivalent of 2GJ of power. + + // Trigger a powernet alarm. Careful engineers will probably notice something is going on. + var/area/temp_area = get_area(M) + if(temp_area) + var/obj/machinery/power/apc/temp_apc = temp_area.get_apc() + if(temp_apc && temp_apc.terminal && temp_apc.terminal.powernet) + temp_apc.terminal.powernet.trigger_warning(50) // Long alarm + if(temp_apc) + temp_apc.emp_act(3) // Such power surges are not good for APC electronics + if(temp_apc.cell) + temp_apc.cell.maxcharge -= between(0, (temp_apc.cell.maxcharge/2) + 500, temp_apc.cell.maxcharge) + if(temp_apc.cell.maxcharge < 100) // That's it, you busted the APC cell completely. Break the APC and completely destroy the cell. + qdel(temp_apc.cell) + temp_apc.set_broken() + + + if(!ability_pay(user,price)) + return + + M.visible_message("BZZZZZZZT") + spawn(50) + explosion(get_turf(M), round(explosion_intensity/4),round(explosion_intensity/2),round(explosion_intensity),round(explosion_intensity * 2)) + if(M) + qdel(M) + +// END ABILITY VERBS \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm new file mode 100644 index 00000000000..9c3c584d9e4 --- /dev/null +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm @@ -0,0 +1,209 @@ +// NETWORKING TREE +// +// Abilities in this tree are oriented around giving the AI more control of normally uncontrollable systems. +// T1 - Basic Encryption Hack - Allows hacking of APCs. Hacked APCs can be controlled even when AI Control is cut and give exclusive control to the AI and linked cyborgs. +// T2 - Advanced Encryption Hack - Allows the AI to send fake CentCom message. Has high chance of failing. +// T3 - Elite Encryption Hack - Allows the AI to change alert levels. Has high chance of failing. +// T4 - System Override - Allows the AI to rapidly hack remaining APCs. When completed, grants access to the self destruct nuclear warhead. + + +// BEGIN RESEARCH DATUMS + +/datum/malf_research_ability/networking/basic_hack + ability = new/datum/game_mode/malfunction/verb/basic_encryption_hack() + price = 25 + next = new/datum/malf_research_ability/networking/advanced_hack() + name = "Basic Encryption Hack" + + +/datum/malf_research_ability/networking/advanced_hack + ability = new/datum/game_mode/malfunction/verb/advanced_encryption_hack() + price = 400 + next = new/datum/malf_research_ability/networking/elite_hack() + name = "Advanced Encryption Hack" + + +/datum/malf_research_ability/networking/elite_hack + ability = new/datum/game_mode/malfunction/verb/elite_encryption_hack() + price = 1000 + next = new/datum/malf_research_ability/networking/system_override() + name = "Elite Encryption Hack" + + +/datum/malf_research_ability/networking/system_override + ability = new/datum/game_mode/malfunction/verb/system_override() + price = 2750 + name = "System Override" + +// END RESEARCH DATUMS +// BEGIN ABILITY VERBS + +/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs()) + set category = "Software" + set name = "Basic Encryption Hack" + set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station." + var/price = 10 + var/mob/living/silicon/ai/user = usr + + if(!A) + return + + if(!istype(A)) + user << "This is not an APC!" + return + + if(A) + if(A.hacker && A.hacker == user) + user << "You already control this APC!" + return + else if(A.aidisabled) + user << "Unable to connect to APC. Please verify wire connection and try again." + return + else + return + + if(!ability_prechecks(user, price) || !ability_pay(user, price)) + return + + user.hacking = 1 + user << "Beginning APC system override..." + sleep(300) + user << "APC hack completed. Uploading modified operation software.." + sleep(200) + user << "Restarting APC to apply changes.." + sleep(100) + if(A) + A.ai_hack(user) + if(A.hacker == user) + user << "Hack successful. You now have full control over the APC." + else + user << "Hack failed. Connection to APC has been lost. Please verify wire connection and try again." + else + user << "Hack failed. Unable to locate APC. Please verify the APC still exists." + user.hacking = 0 + + +/datum/game_mode/malfunction/verb/advanced_encryption_hack() + set category = "Software" + set name = "Advanced Encrypthion Hack" + set desc = "75 CPU - Attempts to bypass encryption on Central Command Quantum Relay, giving you ability to fake centcom messages. Has chance of failing." + var/price = 75 + var/mob/living/silicon/ai/user = usr + + if(!ability_prechecks(user, price)) + return + + var/title = input("Select message title: ") + var/text = input("Select message text: ") + if(!title || !text || !ability_pay(user, price)) + user << "Hack Aborted" + return + + if(prob(60) && user.hack_can_fail) + user << "Hack Failed." + if(prob(10)) + user.hack_fails ++ + announce_hack_failure(user, "quantum message relay") + return + + var/datum/announcement/priority/command/AN = new/datum/announcement/priority/command() + AN.title = title + AN.Announce(text) + + +/datum/game_mode/malfunction/verb/elite_encryption_hack() + set category = "Software" + set name = "Elite Encryption Hack" + set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failijng." + var/price = 200 + var/mob/living/silicon/ai/user = usr + if(!ability_prechecks(user, price)) + return + + var/alert_target = input("Select new alert level:") in list("green", "blue", "red", "delta", "CANCEL") + if(!alert_target || !ability_pay(user, price) || alert_target == "CANCEL") + user << "Hack Aborted" + return + + if(prob(75) && user.hack_can_fail) + user << "Hack Failed." + if(prob(20)) + user.hack_fails ++ + announce_hack_failure(user, "alert control system") + return + set_security_level(alert_target) + + +/datum/game_mode/malfunction/verb/system_override() + set category = "Software" + set name = "System Override" + set desc = "500 CPU - Begins hacking station's primary firewall, quickly overtaking remaining APC systems. When completed grants access to station's self-destruct mechanism. Network administrators will probably notice this." + var/price = 500 + var/mob/living/silicon/ai/user = usr + if (alert(user, "Begin system override? This cannot be stopped once started. The network administrators will probably notice this.", "System Override:", "Yes", "No") != "Yes") + return + if (!ability_prechecks(user, price) || !ability_pay(user, price) || user.system_override) + if(user.system_override) + user << "You already started the system override sequence." + return + var/list/remaining_apcs = list() + for(var/obj/machinery/power/apc/A in machines) + if(!(A.z in config.station_levels)) // Only station APCs + continue + if(A.hacker == user || A.aidisabled) // This one is already hacked, or AI control is disabled on it. + continue + remaining_apcs += A + + var/duration = (remaining_apcs.len * 100) // Calculates duration for announcing system + if(duration > 3000) // Two types of announcements. Short hacks trigger immediate warnings. Long hacks are more "progressive". + spawn(0) + sleep(duration/5) + if(!user || user.stat == DEAD) + return + command_announcement.Announce("Caution, [station_name]. We have detected abnormal behaviour in your network. It seems someone is trying to hack your electronic systems. We will update you when we have more information.", "Network Monitoring") + sleep(duration/5) + if(!user || user.stat == DEAD) + return + command_announcement.Announce("We started tracing the intruder. Whoever is doing this, they seem to be on the station itself. We suggest checking all network control terminals. We will keep you updated on the situation.", "Network Monitoring") + sleep(duration/5) + if(!user || user.stat == DEAD) + return + command_announcement.Announce("This is highly abnormal and somewhat concerning. The intruder is too fast, he is evading our traces. No man could be this fast...", "Network Monitoring") + sleep(duration/5) + if(!user || user.stat == DEAD) + return + command_announcement.Announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ ", "Network Monitoring") + else + command_announcement.Announce("We have detected a strong brute-force attack on your firewall which seems to be originating from your AI system. It already controls almost the whole network, and the only thing that's preventing it from accessing the self-destruct is this firewall. You don't have much time before it succeeds.", "Network Monitoring") + user << "## BEGINNING SYSTEM OVERRIDE." + user << "## ESTIMATED DURATION: [round((duration+300)/600)] MINUTES" + user.hacking = 1 + user.system_override = 1 + // Now actually begin the hack. Each APC takes 10 seconds. + for(var/obj/machinery/power/apc/A in shuffle(remaining_apcs)) + sleep(100) + if(!user || user.stat == DEAD) + return + if(!A || !istype(A) || A.aidisabled) + continue + A.ai_hack(user) + if(A.hacker == user) + user << "## OVERRIDDEN: [A.name]" + + user << "## REACHABLE APC SYSTEMS OVERTAKEN. BYPASSING PRIMARY FIREWALL." + sleep(300) + // Hack all APCs, including those built during hack sequence. + for(var/obj/machinery/power/apc/A in machines) + if((!A.hacker || A.hacker != src) && !A.aidisabled && A.z in config.station_levels) + A.ai_hack(src) + + + user << "## PRIMARY FIREWALL BYPASSED. YOU NOW HAVE FULL SYSTEM CONTROL." + command_announcement.Announce("Our system administrators just reported that we've been locked out from your control network. Whoever did this now has full access to the station's systems.", "Network Administration Center") + user.hack_can_fail = 0 + user.hacking = 0 + user.system_override = 2 + user.verbs += new/datum/game_mode/malfunction/verb/ai_destroy_station() + + +// END ABILITY VERBS \ No newline at end of file diff --git a/code/game/gamemodes/meme/meme.dm b/code/game/gamemodes/meme/meme.dm index 2aa512264df..0a4846d7635 100644 --- a/code/game/gamemodes/meme/meme.dm +++ b/code/game/gamemodes/meme/meme.dm @@ -126,7 +126,7 @@ /datum/game_mode/proc/greet_meme(var/datum/mind/meme, var/you_are=1) if (you_are) - meme.current << "\red You are a meme!" + meme.current << "You are a meme!" show_objectives(meme) return diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 9d18216aa53..293631f2a84 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -1,6 +1,6 @@ /var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds //set to at least 100 unless you want evarr ruining every round - +/var/wavesecret = 0 /var/const/meteors_in_wave = 50 /var/const/meteors_in_small_wave = 10 @@ -162,3 +162,6 @@ qdel(src) return ..() + +/obj/effect/meteor/touch_map_edge() + qdel(src) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index b556ba20709..5d8ac9d0717 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -2,6 +2,8 @@ MERCENARY ROUNDTYPE */ +var/list/nuke_disks = list() + /datum/game_mode/nuclear name = "Mercenary" round_description = "A mercenary strike force is approaching the station!" @@ -17,6 +19,18 @@ var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level +//delete all nuke disks not on a station zlevel +/datum/game_mode/nuclear/proc/check_nuke_disks() + for(var/obj/item/weapon/disk/nuclear/N in nuke_disks) + if(isNotStationLevel(N.z)) qdel(N) + +//checks if L has a nuke disk on their person +/datum/game_mode/nuclear/proc/check_mob(mob/living/L) + for(var/obj/item/weapon/disk/nuclear/N in nuke_disks) + if(N.storage_depth(L) >= 0) + return 1 + return 0 + /datum/game_mode/nuclear/declare_completion() if(config.objectives_disabled) return diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 7b6b1dc9527..63832b809ce 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -8,7 +8,7 @@ item_state = "electronic" throw_speed = 4 throw_range = 20 - matter = list("metal" = 500) + matter = list(DEFAULT_WALL_MATERIAL = 500) var/obj/item/weapon/disk/nuclear/the_disk = null var/active = 0 @@ -17,11 +17,11 @@ if(!active) active = 1 workdisk() - usr << "\blue You activate the pinpointer" + usr << "You activate the pinpointer" else active = 0 icon_state = "pinoff" - usr << "\blue You deactivate the pinpointer" + usr << "You deactivate the pinpointer" proc/workdisk() if(!active) return @@ -69,11 +69,11 @@ worklocation() if(mode == 2) workobj() - usr << "\blue You activate the pinpointer" + usr << "You activate the pinpointer" else active = 0 icon_state = "pinoff" - usr << "\blue You deactivate the pinpointer" + usr << "You deactivate the pinpointer" proc/worklocation() @@ -262,4 +262,4 @@ if(16 to INFINITY) icon_state = "pinonfar" - spawn(5) .() \ No newline at end of file + spawn(5) .() diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 076c0afbf3a..0ad6e7fc5fb 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -513,9 +513,9 @@ datum/objective/steal "diamond drill" = /obj/item/weapon/pickaxe/diamonddrill, "bag of holding" = /obj/item/weapon/storage/backpack/holding, "hyper-capacity cell" = /obj/item/weapon/cell/hyper, - "10 diamonds" = /obj/item/stack/sheet/mineral/diamond, - "50 gold bars" = /obj/item/stack/sheet/mineral/gold, - "25 refined uranium bars" = /obj/item/stack/sheet/mineral/uranium, + "10 diamonds" = /obj/item/stack/material/diamond, + "50 gold bars" = /obj/item/stack/material/gold, + "25 refined uranium bars" = /obj/item/stack/material/uranium, ) @@ -798,7 +798,7 @@ datum/objective/heist/salvage choose_target() switch(rand(1,8)) if(1) - target = "metal" + target = DEFAULT_WALL_MATERIAL target_amount = 300 if(2) target = "glass" @@ -830,13 +830,13 @@ datum/objective/heist/salvage for(var/obj/item/O in locate(/area/shuttle/skipjack/station)) - var/obj/item/stack/sheet/S - if(istype(O,/obj/item/stack/sheet)) + var/obj/item/stack/material/S + if(istype(O,/obj/item/stack/material)) if(O.name == target) S = O total_amount += S.get_amount() for(var/obj/I in O.contents) - if(istype(I,/obj/item/stack/sheet)) + if(istype(I,/obj/item/stack/material)) if(I.name == target) S = I total_amount += S.get_amount() @@ -844,9 +844,9 @@ datum/objective/heist/salvage for(var/datum/mind/raider in raiders.current_antagonists) if(raider.current) for(var/obj/item/O in raider.current.get_contents()) - if(istype(O,/obj/item/stack/sheet)) + if(istype(O,/obj/item/stack/material)) if(O.name == target) - var/obj/item/stack/sheet/S = O + var/obj/item/stack/material/S = O total_amount += S.get_amount() if(total_amount >= target_amount) return 1 diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 29815966450..3c029d52980 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -24,44 +24,6 @@ if (prob(75)) DIFFMUT = rand(0,20) - /* Old, for reference (so I don't accidentally activate something) - N3X - var/list/avnums = new/list() - var/tempnum - - avnums.Add(2) - avnums.Add(12) - avnums.Add(10) - avnums.Add(8) - avnums.Add(4) - avnums.Add(11) - avnums.Add(13) - avnums.Add(6) - - tempnum = pick(avnums) - avnums.Remove(tempnum) - HULKBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - TELEBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - FIREBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - XRAYBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - CLUMSYBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - FAKEBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - DEAFBLOCK = tempnum - tempnum = pick(avnums) - avnums.Remove(tempnum) - BLINDBLOCK = tempnum - */ var/list/numsToAssign=new() for(var/i=1;i